This commit is contained in:
2026-02-06 09:18:33 +08:00
parent a71e169656
commit 5340b78204
19 changed files with 1804 additions and 44 deletions
@@ -121,6 +121,13 @@ public interface SysRoleService extends BaseService<Sys_role> {
*/
Sys_role getByCode(RoleConstant roleConstant);
/**
* 通过枚举获取角色
* @param roleConstantList
* @return
*/
List<String> getRoleIdsByCode(List<RoleConstant> roleConstantList);
/**
* 清空缓存
*/
@@ -257,6 +257,19 @@ public class SysRoleServiceImpl extends BaseServiceImpl<Sys_role> implements Sys
return role;
}
@Override
public List<String> getRoleIdsByCode(List<RoleConstant> roleList) {
if (roleList.isEmpty()){
return List.of();
}
List<Sys_role> roles = query(Cnd.where("code", "in", roleList));
if (ObjectUtil.isEmpty(roles)) {
throw new BaseException("没有找到code为{}的角色,请检查!!!", roles);
}
List<String> roleIds = roles.stream().map(Sys_role::getId).toList();
return roleIds;
}
@Override
public Sys_role getByCode(RoleConstant roleConstant) {
return getByCode(roleConstant.name());
@@ -0,0 +1,139 @@
package com.budwk.app.zhgh.dayofficework.outlay.outlayManage.club.controller;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.param.PageForm;
import com.budwk.app.base.result.Result;
import com.budwk.app.base.utils.CommonDownloadUtil;
import com.budwk.app.zhgh.club.service.impl.SysClubUserServiceImpl;
import com.budwk.app.zhgh.dayofficework.outlay.outlayManage.service.OutlayManageClubQueryService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;
import org.nutz.dao.sql.Sql;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.util.NutMap;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* @author zhf
* @date 2026/2/5 18:02
* @description 历史拨付查询
*/
@IocBean
@At("/platform/outlay/outlayManage/backHistory")
@Ok("json:full")
@Slf4j
@Api(tags = "协会经费查询")
public class OutlayManageClubBackHistoryController {
@Inject
private OutlayManageClubQueryService clubQueryService;
@At("")
@Ok("beetl:/platform/zhgh/dayofficework/outlay/outlayManage/club/backHistory/index.html")
@SaCheckPermission("outlay.outlayManage.club.backHistory")
public void index() {
}
@At
@ApiOperation("分页查询")
@SaCheckPermission("outlay.outlayManage.club.backHistory")
public Result pageData(PageForm pageForm, Integer year, String clubId, String isGiveMoney, String payed) {
String type = "historyUserNum";
if (StrUtil.isNotBlank(isGiveMoney)) {
type = "1".equals(isGiveMoney) ? "historyGiveMoneyNum" : "historyNotGiveMoneyNum";
}
Sql sql = clubQueryService.backUserSql(pageForm, clubId, type, year, payed);
Pagination pagination = clubQueryService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
List<NutMap> listMap = pagination.getList();
for (NutMap map : listMap) {
List<String> roleCodeList = JSONUtil.toList(map.getString("roleCode"), String.class);
List<String> cleanedCodes = roleCodeList.stream()
.filter(Objects::nonNull)
.map(String::strip)
.map(code -> code.startsWith("\"") && code.endsWith("\"")
? code.substring(1, code.length() - 1)
: code)
.toList();
String roleName = SysClubUserServiceImpl.convertRoleName(cleanedCodes);
map.put("roleName", roleName);
map.put("roleCode", cleanedCodes);
}
pagination.setList(listMap);
return Result.success(pagination);
}
@At
@Ok("void")
@SaCheckPermission("outlay.outlayManage.club.backHistory")
public void doExcel(PageForm pageForm, Integer year, String clubId, String isGiveMoney, String payed, HttpServletResponse response) {
String type = "historyUserNum";
if (StrUtil.isNotBlank(isGiveMoney)) {
type = "1".equals(isGiveMoney) ? "historyGiveMoneyNum" : "historyNotGiveMoneyNum";
}
Sql sql = clubQueryService.backUserSql(pageForm, clubId, type, year, payed);
List<NutMap> listMap = clubQueryService.listMap(sql);
for (NutMap map : listMap) {
List<String> roleCodeList = JSONUtil.toList(map.getString("roleCode"), String.class);
List<String> cleanedCodes = roleCodeList.stream()
.filter(Objects::nonNull)
.map(String::strip)
.map(code -> code.startsWith("\"") && code.endsWith("\"")
? code.substring(1, code.length() - 1)
: code)
.toList();
String roleName = SysClubUserServiceImpl.convertRoleName(cleanedCodes);
map.put("roleName", roleName);
map.put("roleCode", cleanedCodes);
map.put("isGiveMoney", map.getInt("isGiveMoney") == 1 ? "已拨付" : "未拨付");
map.put("payed", map.getInt("payed") == 1 ? "已缴费" : "未缴费");
}
List<ExcelExportEntity> exportEntities = new ArrayList<>();
ExcelExportEntity no = new ExcelExportEntity("序号", "no", 10);
no.setFormat("isAddIndex");
exportEntities.add(no);
exportEntities.add(new ExcelExportEntity("工号", "loginname", 20));
exportEntities.add(new ExcelExportEntity("姓名", "username", 20));
exportEntities.add(new ExcelExportEntity("性别", "sex", 20));
exportEntities.add(new ExcelExportEntity("加入时间", "applyDate2", 20));
exportEntities.add(new ExcelExportEntity("在职状态", "userState", 20));
exportEntities.add(new ExcelExportEntity("是否拨付", "isGiveMoney", 20));
exportEntities.add(new ExcelExportEntity("是否缴费", "payed", 20));
exportEntities.add(new ExcelExportEntity("所在协会", "clubName", 20));
exportEntities.add(new ExcelExportEntity("身份", "roleName", 20));
try {
ExportParams exportParams = new ExportParams();
exportParams.setType(ExcelType.XSSF);
exportParams.setTitle("历史拨付汇总");
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, exportEntities, listMap);
CommonDownloadUtil.download(year + "历史拨付汇总.xlsx", workbook, response);
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -12,8 +12,10 @@ import com.budwk.app.flow.enums.ProcessInstanceStateEnum;
import com.budwk.app.sys.models.Sys_role;
import com.budwk.app.sys.models.Sys_user_role;
import com.budwk.app.sys.services.SysRoleService;
import com.budwk.app.sys.views.View_user;
import com.budwk.app.web.commons.auth.utils.AuthUtil;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.club.model.ClubUser;
import com.budwk.app.zhgh.club.model.SysClub;
import com.budwk.app.zhgh.dayofficework.outlay.outlayManage.club.model.OutlayManageClub;
import io.swagger.annotations.Api;
@@ -31,6 +33,7 @@ import org.nutz.mvc.annotation.Ok;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* @author zhf
@@ -41,7 +44,7 @@ import java.util.List;
@At("/platform/outlay/outlayManage/clubManage")
@Ok("json:full")
@Slf4j
@Api(tags = "分工会经费预算管理")
@Api(tags = "会经费预算管理")
public class OutlayManageClubController {
@Inject
@@ -59,7 +62,7 @@ public class OutlayManageClubController {
@At
@ApiOperation("分页查询")
@SaCheckPermission("outlay.outlayManage.club.manage")
public Result pageData(PageForm pageForm, Integer year) {
public Result pageData(PageForm pageForm, Integer year, String clubId) {
Cnd cnd = Cnd.NEW();
Sql sql = Sqls.create("""
SELECT * FROM `outlay_manage_club` $condition
@@ -71,6 +74,7 @@ public class OutlayManageClubController {
List<String> myClubId = userRoles.stream().map(Sys_user_role::getClubId).toList();
cnd.andEX("clubId", "in", myClubId);
}
cnd.andEX("clubId", "=", clubId);
cnd.asc("clubCode");
sql.setCondition(cnd);
Pagination pagination = baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
@@ -112,48 +116,94 @@ public class OutlayManageClubController {
@SaCheckPermission("outlay.outlayManage.club.manage")
@SLog(tag = "协会预算分配", msg = "根据申报的金额修改本年的预算预算")
public Result issuedOutlay() {
/* Sql sql = Sqls.create("""
Sql sql = Sqls.create("""
SELECT
ab.clubId,
ab.totalBudgetMoney
c.*,
COALESCE(pay_stats.historyGiveMoneyNum, 0) AS historyGiveMoneyNum,
COALESCE(pay_stats.historyNotGiveMoneyNum, 0) AS historyNotGiveMoneyNum,
COALESCE(pay_stats.historyUserNum, 0) AS historyUserNum
FROM
activity_budget ab
LEFT JOIN wf_process_instance wpi ON wpi.businessNo = ab.id
sys_club c
LEFT JOIN wf_process_instance inst ON inst.businessNo = c.id
LEFT JOIN (
SELECT
cu.clubId,
COUNT(CASE WHEN re.isGiveMoney = 1 THEN 1 END) AS historyGiveMoneyNum,
COUNT(CASE WHEN re.isGiveMoney = 0 THEN 1 END) AS historyNotGiveMoneyNum,
COUNT(*) AS historyUserNum
FROM
club_user cu
INNER JOIN club_user_apply cua
ON cu.userId = cua.userId
AND cu.clubId = cua.clubId
LEFT JOIN club_pay_record re
ON re.userId = cu.userId
AND re.clubId = cu.clubId
AND re.year = @year
WHERE
YEAR(cua.applyDate) < @year
AND cua.`mode` = 1
GROUP BY
cu.clubId
) pay_stats ON pay_stats.clubId = c.id
WHERE
YEAR(ab.applyDate) = @year
AND ab.outlayManageSource = 'ACTIVITY_BUDGET_TYPE_THREE'
AND ab.isSchoolBudget =0
AND wpi.state = 20
inst.state = 20;
""").setParam("year", DateUtil.thisYear());
List<NutMap> budgetList = baseService.listMap(sql);
*/
Sql sqlClub = Sqls.create("""
SELECT
c.*
FROM
`sys_club` c
LEFT JOIN wf_process_instance inst ON inst.businessNo = c.id
WHERE
inst.state = @state
""").setParam("state", ProcessInstanceStateEnum.FINISHED.getCode());
List<SysClub> clubList = baseService.listVO(sqlClub, SysClub.class);
List<NutMap> clubList = baseService.listMap(sql);
List<OutlayManageClub> insertUnionList = new ArrayList<>();
clubList.forEach(v -> {
/* BigDecimal totalBudgetMoney = budgetList.stream()
.filter(budget -> budget.getString("clubId").equals(v.getId()))
.map(budget -> new BigDecimal(budget.getString("totalBudgetMoney"))) // 提取 money 属性
.reduce(BigDecimal.ZERO, BigDecimal::add);*/
OutlayManageClub outlayManageClub = new OutlayManageClub();
outlayManageClub.setYear(DateUtil.thisYear());
outlayManageClub.setClubName(v.getClubName());
outlayManageClub.setClubCode(v.getClubCode());
outlayManageClub.setClubId(v.getId());
// outlayManageClub.setTotalQuota(totalBudgetMoney);
outlayManageClub.setClubName(v.getString("clubName"));
outlayManageClub.setClubCode(v.getString("clubCode"));
outlayManageClub.setClubId(v.getString("id"));
outlayManageClub.setHistoryUserNum(v.getInt("historyUserNum"));
outlayManageClub.setHistoryNotGiveMoneyNum(v.getInt("historyNotGiveMoneyNum"));
outlayManageClub.setHistoryGiveMoneyNum(v.getInt("historyGiveMoneyNum"));
BigDecimal totalBudgetMoney;
//如果人数超过50人就是5000,否则就是3000
if (v.getInt("historyGiveMoneyNum") >= 50) {
totalBudgetMoney = BigDecimal.valueOf(5000);
} else {
totalBudgetMoney = BigDecimal.valueOf(3000);
}
if (v.getInt("historyGiveMoneyNum") == 0) {
totalBudgetMoney = BigDecimal.ZERO;
}
outlayManageClub.setTotalQuota(totalBudgetMoney);
insertUnionList.add(outlayManageClub);
});
baseService.insert(insertUnionList);
return Result.success();
}
@At
@ApiOperation("给没有核对的人发送核对提醒")
@SaCheckPermission("outlay.outlayManage.club.manage")
@SLog(tag = "协会预算分配", msg = "给没有核对的人发送核对提醒")
public Result doMsg() {
List<OutlayManageClub> manageClubList = baseService.dao().query(OutlayManageClub.class,
Cnd.where(OutlayManageClub::getYear, "=", DateUtil.thisYear())
.and(OutlayManageClub::getIsCheck, "=", 0));
for (OutlayManageClub club : manageClubList) {
List<String> roleIds = sysRoleService.getRoleIdsByCode(List.of(RoleConstant.CLUB_PRESIDENT, RoleConstant.CLUB_SECRETARY));
List<Sys_user_role> sysUserRoles = baseService.dao().query(Sys_user_role.class,
Cnd.where(Sys_user_role::getClubId, "=", club.getClubId())
.and(Sys_user_role::getRoleId, "in", roleIds));
List<String> clubUserIds = sysUserRoles.stream().map(Sys_user_role::getUserId).toList();
if (!clubUserIds.isEmpty()){
List<View_user> users = baseService.dao().query(View_user.class, Cnd.where("id", "in", clubUserIds));
}
}
return Result.success();
}
}
@@ -0,0 +1,227 @@
package com.budwk.app.zhgh.dayofficework.outlay.outlayManage.club.controller;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.TemplateExportParams;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.budwk.app.base.annotation.SLog;
import com.budwk.app.base.constant.RoleConstant;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.param.PageForm;
import com.budwk.app.base.result.Result;
import com.budwk.app.base.service.BaseService;
import com.budwk.app.base.utils.CommonDownloadUtil;
import com.budwk.app.base.utils.SysOfficeTemplateUtil;
import com.budwk.app.sys.models.Sys_role;
import com.budwk.app.sys.models.Sys_user_role;
import com.budwk.app.sys.services.SysRoleService;
import com.budwk.app.web.commons.auth.utils.AuthUtil;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.web.commons.base.Globals;
import com.budwk.app.zhgh.club.model.SysClub;
import com.budwk.app.zhgh.club.service.impl.SysClubUserServiceImpl;
import com.budwk.app.zhgh.dayofficework.outlay.outlayManage.club.model.OutlayManageClub;
import com.budwk.app.zhgh.dayofficework.outlay.outlayManage.service.OutlayManageClubQueryService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.util.NutMap;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;
/**
* @author zhf
* @date 2026/2/5 09:44
* @description 协会经费查询
*/
@IocBean
@At("/platform/outlay/outlayManage/query")
@Ok("json:full")
@Slf4j
@Api(tags = "协会经费查询")
public class OutlayManageClubQueryController {
@Inject
private OutlayManageClubQueryService clubQueryService;
@Inject
private SysRoleService sysRoleService;
@Inject
private SysOfficeTemplateUtil sysOfficeTemplateUtil;
@At("")
@Ok("beetl:/platform/zhgh/dayofficework/outlay/outlayManage/club/query/index.html")
@SaCheckPermission("outlay.outlayManage.club.query")
public void index() {
}
@At
@ApiOperation("分页查询")
@SaCheckPermission("outlay.outlayManage.club.query")
public Result pageData(PageForm pageForm, Integer year, String clubId) {
Cnd cnd = Cnd.NEW();
Sql sql = Sqls.create("""
SELECT * FROM `outlay_manage_club` $condition
""");
cnd.andEX("year", "=", year);
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
List<String> roleIds = sysRoleService.getRoleIdsByCode(List.of(RoleConstant.CLUB_PRESIDENT, RoleConstant.CLUB_SECRETARY));
List<Sys_user_role> userRoles = clubQueryService.dao().query(Sys_user_role.class,
Cnd.where("userId", "=", SecurityUtil.getUserId())
.and("roleId", "in", roleIds));
List<String> myClubId = userRoles.stream().map(Sys_user_role::getClubId).toList();
cnd.andEX("clubId", "in", myClubId);
}
cnd.andEX("clubId", "=", clubId);
cnd.asc("clubCode");
sql.setCondition(cnd);
Pagination pagination = clubQueryService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
return Result.success(pagination);
}
@At
@ApiOperation("提交核对")
@SaCheckPermission("outlay.outlayManage.club.query")
@SLog(tag = "协会经费查询", msg = "提交核对")
public Result doAudit(String id) {
clubQueryService.dao().update(OutlayManageClub.class,
Chain.make("isCheck", true),
Cnd.where(OutlayManageClub::getId, "=", id));
return Result.success();
}
@At
@ApiOperation("取消核对")
@SaCheckPermission("outlay.outlayManage.club.query")
@SLog(tag = "协会经费查询", msg = "取消核对")
public Result cancelAudit(String id) {
clubQueryService.dao().update(OutlayManageClub.class,
Chain.make("isCheck", false),
Cnd.where(OutlayManageClub::getId, "=", id));
return Result.success();
}
@At
@ApiOperation("更新拨付金额")
@SaCheckPermission("outlay.outlayManage.club.query")
@SLog(tag = "协会经费查询", msg = "更新拨付金额")
public Result doMoney(String clubId) {
clubQueryService.doMoney(clubId);
return Result.success();
}
@At
@ApiOperation("关闭开启核对")
@SaCheckPermission("outlay.outlayManage.club.query")
public Result closeAudit(Boolean flag) {
clubQueryService.dao().update(OutlayManageClub.class,
Chain.make("isDisable", flag),
Cnd.where(OutlayManageClub::getYear, "=", DateUtil.thisYear()));
return Result.success();
}
/**
* 查询已拨付未拨付人员列表
*
* @param pageForm
* @param clubId 社团id
* @param type historyUserNum 全部、historyGiveMoneyNum 已拨付、historyNotGiveMoneyNum 未拨付
* @param year
* @return
*/
@At
@ApiOperation("查询已拨付未拨付人员列表")
@SaCheckPermission("outlay.outlayManage.club.query")
public Result backUserPageData(PageForm pageForm, String clubId, String type, Integer year) {
Sql sql = clubQueryService.backUserSql(pageForm, clubId, type, year, null);
Pagination pagination = clubQueryService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
List<NutMap> listMap = pagination.getList();
for (NutMap map : listMap) {
List<String> roleCodeList = JSONUtil.toList(map.getString("roleCode"), String.class);
List<String> cleanedCodes = roleCodeList.stream()
.filter(Objects::nonNull)
.map(String::strip)
.map(code -> code.startsWith("\"") && code.endsWith("\"")
? code.substring(1, code.length() - 1)
: code)
.toList();
String roleName = SysClubUserServiceImpl.convertRoleName(cleanedCodes);
map.put("roleName", roleName);
map.put("roleCode", cleanedCodes);
}
pagination.setList(listMap);
return Result.success(pagination);
}
@At
@Ok("void")
@SaCheckPermission("outlay.outlayManage.club.query")
public void doExcel(PageForm pageForm, String clubId, Integer year, HttpServletResponse response) {
SysClub sysClub = clubQueryService.dao().fetch(SysClub.class, clubId);
Sql sql = clubQueryService.backUserSql(pageForm, clubId, "historyUserNum", year,null);
List<NutMap> listMap = clubQueryService.listMap(sql);
for (NutMap map : listMap) {
List<String> roleCodeList = JSONUtil.toList(map.getString("roleCode"), String.class);
List<String> cleanedCodes = roleCodeList.stream()
.filter(Objects::nonNull)
.map(String::strip)
.map(code -> code.startsWith("\"") && code.endsWith("\"")
? code.substring(1, code.length() - 1)
: code)
.toList();
String roleName = SysClubUserServiceImpl.convertRoleName(cleanedCodes);
map.put("roleName", roleName);
map.put("roleCode", cleanedCodes);
map.put("iszz", List.of("在职", "在岗").contains(map.getString("userState")) ? "" : "");
map.put("isGiveMoney", map.getBoolean("isGiveMoney") ? "已拨付" : "未拨付");
}
for (int i = 0; i < listMap.size(); i++) {
listMap.get(i).put("index", (i + 1));
}
int zzNum = listMap.stream().filter(map -> List.of("在职", "在岗").contains(map.getString("userState"))).toList().size();
NutMap map = new NutMap();
map.put("schoolName", Globals.MyConfig.getString("schoolName"));
map.put("date", DateUtil.thisYear() - 1 + "年12月31日");
map.put("year", DateUtil.thisYear() - 1);
map.put("totalNum", listMap.size());
map.put("zzNum", zzNum);
map.put("clubName", sysClub.getClubName());
map.put("maplist", listMap);
try {
InputStream is = sysOfficeTemplateUtil.getTemplate("jfClubUserBack");
TemplateExportParams exportParams = new TemplateExportParams(is, null);
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, map);
CommonDownloadUtil.download(Globals.MyConfig.getString("schoolName") + "教职工社团会员统计表.xlsx", workbook, response);
} catch (Exception e) {
log.error("导出Excel汇总表失败", e);
throw new RuntimeException("导出Excel汇总表失败:" + e.getMessage());
}
}
}
@@ -0,0 +1,75 @@
package com.budwk.app.zhgh.dayofficework.outlay.outlayManage.club.model;
import com.budwk.app.base.model.BaseModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.nutz.dao.entity.annotation.*;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* @author zhf
* @date 2026/2/5 14:07
* @description 历史经费拨付情况
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Table("outlay_club_user_back_history")
@TableMeta("{'mysql-charset':'utf8mb4'}")
@Comment("历史经费拨付情况")
public class OutlayClubUserBackHistory extends BaseModel implements Serializable {
@Column
@Name
@Comment("id")
@ColDefine(type = ColType.VARCHAR, width = 32)
@Prev(els = {@EL("uuid()")})
private String id;
@Column
@Comment("协会ID")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String clubId;
@Column
@Comment("用户ID")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String userId;
@Column
@Comment("身份")
@ColDefine(type = ColType.VARCHAR, width = 100)
private List<String> roleCode = new ArrayList<>();
private String roleCodeStr;
@Column
@Comment("申请时间")
@ColDefine(type = ColType.DATETIME)
private Date applyDate;
@Column
@Comment("是否缴费")
@ColDefine(type = ColType.BOOLEAN)
@Default(value = "0")
private Boolean payed;
@Column
@Comment("是否拨付")
@ColDefine(type = ColType.BOOLEAN)
@Default(value = "0")
private Boolean isGiveMoney;
@Column
@Comment("备份年度")
@ColDefine(type = ColType.INT)
private Integer historyYear;
@Column
@Comment("在职状态")
@ColDefine(type = ColType.VARCHAR, width = 20)
private String userState;
}
@@ -44,6 +44,30 @@ public class OutlayManageClub extends BaseModel implements Serializable {
@ColDefine(customType = "decimal(10,2)")
private BigDecimal usedQuota;
@Column
@Comment("人均额度")
@Default("0")
@ColDefine(customType = "decimal(10,2)")
private BigDecimal userAvgMoney;
@Column
@Comment("上年度社团人数")
@Default("0")
@ColDefine(type = ColType.INT)
private Integer historyUserNum;
@Column
@Comment("上年度拨付人数")
@Default("0")
@ColDefine(type = ColType.INT)
private Integer historyGiveMoneyNum;
@Column
@Comment("上年度未拨付人数")
@Default("0")
@ColDefine(type = ColType.INT)
private Integer historyNotGiveMoneyNum;
@Column
@Comment("协会ID")
@ColDefine(type = ColType.VARCHAR, width = 32)
@@ -59,4 +83,16 @@ public class OutlayManageClub extends BaseModel implements Serializable {
@ColDefine(type = ColType.VARCHAR, width = 32)
private String clubCode;
@Column
@Comment("是否核对")
@Default("0")
@ColDefine(type = ColType.BOOLEAN)
private Boolean isCheck;
@Column
@Comment("是否关闭")
@Default("0")
@ColDefine(type = ColType.BOOLEAN)
private Boolean isDisable;
}
@@ -0,0 +1,13 @@
package com.budwk.app.zhgh.dayofficework.outlay.outlayManage.service;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.param.PageForm;
import com.budwk.app.base.service.BaseService;
import org.nutz.dao.sql.Sql;
public interface OutlayManageClubQueryService extends BaseService {
void doMoney(String clubId);
Sql backUserSql(PageForm pageForm, String clubId, String type, Integer year, String payed);
}
@@ -0,0 +1,191 @@
package com.budwk.app.zhgh.dayofficework.outlay.outlayManage.service.impl;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.budwk.app.base.constant.RoleConstant;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.param.PageForm;
import com.budwk.app.base.service.impl.BaseServiceImpl;
import com.budwk.app.zhgh.club.service.impl.SysClubUserServiceImpl;
import com.budwk.app.zhgh.dayofficework.outlay.outlayManage.club.model.OutlayClubUserBackHistory;
import com.budwk.app.zhgh.dayofficework.outlay.outlayManage.club.model.OutlayManageClub;
import com.budwk.app.zhgh.dayofficework.outlay.outlayManage.service.OutlayManageClubQueryService;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.dao.util.cri.SqlExpressionGroup;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.util.NutMap;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* @author zhf
* @date 2026/2/5 14:13
* @description
*/
@IocBean(args = {"refer:dao"})
public class OutlayManageClubQueryServiceImpl extends BaseServiceImpl implements OutlayManageClubQueryService {
public OutlayManageClubQueryServiceImpl(Dao dao) {
super(dao);
}
@Aop(TransAop.READ_COMMITTED)
@Override
public void doMoney(String clubId) {
Sql sql = Sqls.create("""
SELECT
c.*,
COALESCE(pay_stats.historyGiveMoneyNum, 0) AS historyGiveMoneyNum,
COALESCE(pay_stats.historyNotGiveMoneyNum, 0) AS historyNotGiveMoneyNum,
COALESCE(pay_stats.historyUserNum, 0) AS historyUserNum
FROM
sys_club c
LEFT JOIN wf_process_instance inst ON inst.businessNo = c.id
LEFT JOIN (
SELECT
cu.clubId,
COUNT(CASE WHEN re.isGiveMoney = 1 THEN 1 END) AS historyGiveMoneyNum,
COUNT(CASE WHEN re.isGiveMoney = 0 THEN 1 END) AS historyNotGiveMoneyNum,
COUNT(*) AS historyUserNum
FROM
club_user cu
INNER JOIN club_user_apply cua
ON cu.userId = cua.userId
AND cu.clubId = cua.clubId
LEFT JOIN club_pay_record re
ON re.userId = cu.userId
AND re.clubId = cu.clubId
AND re.year = @year
WHERE
YEAR(cua.applyDate) < @year
AND cua.`mode` = 1
GROUP BY
cu.clubId
) pay_stats ON pay_stats.clubId = c.id
WHERE
inst.state = 20 and c.id=@clubId
""").setParam("year", DateUtil.thisYear())
.setParam("clubId", clubId);
sql.setCallback(Sqls.callback.map());
dao().execute(sql);
NutMap info = (NutMap) sql.getResult();
BigDecimal totalBudgetMoney;
//如果人数超过50人就是5000,否则就是3000
if (info.getInt("historyGiveMoneyNum") >= 50) {
totalBudgetMoney = BigDecimal.valueOf(5000);
} else {
totalBudgetMoney = BigDecimal.valueOf(3000);
}
if (info.getInt("historyGiveMoneyNum") == 0) {
totalBudgetMoney = BigDecimal.ZERO;
}
dao().update(OutlayManageClub.class,
Chain.make("historyGiveMoneyNum", info.getInt("historyGiveMoneyNum"))
.add("historyNotGiveMoneyNum", info.getInt("historyNotGiveMoneyNum"))
.add("historyUserNum", info.getInt("historyUserNum"))
.add("totalQuota", totalBudgetMoney),
Cnd.where(OutlayManageClub::getClubId, "=", clubId)
.and(OutlayManageClub::getYear, "=", DateUtil.thisYear()));
//备份历史表
dao().clear(OutlayClubUserBackHistory.class, Cnd.where(OutlayClubUserBackHistory::getClubId, "=", clubId)
.and(OutlayClubUserBackHistory::getHistoryYear, "=", DateUtil.thisYear()));
Sql sql1 = Sqls.create("""
SELECT
cu.*,
cu.roleCode roleCodeStr,
cua.applyDate,
re.isGiveMoney,
re.payed,
us.userState
FROM
club_user cu
LEFT JOIN sys_user us on cu.userId=us.id
LEFT JOIN club_user_apply cua ON cu.userId = cua.userId
AND cu.clubId = cua.clubId
LEFT JOIN club_pay_record re ON re.userId = cu.userId
AND re.clubId = cu.clubId
AND re.YEAR = @year
WHERE
YEAR(cua.applyDate) < @year
AND cua.`mode` = 1 and cu.clubId=@clubId
""").setParam("year", DateUtil.thisYear()).setParam("clubId", clubId);
List<OutlayClubUserBackHistory> listMap = listVO(sql1, OutlayClubUserBackHistory.class);
listMap.forEach(v -> {
String roleCodeStr = v.getRoleCodeStr();
v.setRoleCode(JSONUtil.toList(roleCodeStr, String.class));
v.setHistoryYear(DateUtil.thisYear());
});
insert(listMap);
}
@Override
public Sql backUserSql(PageForm pageForm, String clubId, String type, Integer year, String payed) {
Sql sql = Sqls.create("""
SELECT
clubUser.*,
TIMESTAMPDIFF(YEAR, us.birthday, CURDATE()) AS age,
DATE_FORMAT(clubUser.applyDate, '%Y-%m-%d') applyDate2,
us.sex,
us.mobile,
us.unitName,
us.username,
us.loginname,
club.clubName
FROM
`outlay_club_user_back_history` clubUser
LEFT JOIN vw_user us ON us.id = clubUser.userId
LEFT JOIN sys_club club on club.id=clubUser.clubId
$condition
$order
""");
Cnd cnd = Cnd.NEW();
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
SqlExpressionGroup group = new SqlExpressionGroup();
group.or("us.username", "like", "%" + pageForm.getSearchKeyword() + "%");
group.or("us.loginname", "like", "%" + pageForm.getSearchKeyword() + "%");
cnd.and(group);
}
cnd.andEX("clubUser.clubId", "=", clubId);
if (StrUtil.isNotBlank(payed)){
cnd.and("clubUser.payed", "=", "1".equals(payed) ? 1 : 0);
}
cnd.and("clubUser.historyYear", "=", year);
if (!Objects.equals("historyUserNum", type)) {
cnd.and("clubUser.isGiveMoney", "=", Objects.equals("historyGiveMoneyNum", type) ? 1 : 0);
}
if (StrUtil.isAllNotBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) {
cnd.orderBy(pageForm.getPageOrderName(), "descending".equals(pageForm.getPageOrderBy()) ? "desc" : "asc");
} else {
sql.setVar("order", """
ORDER BY
CASE
WHEN JSON_CONTAINS(clubUser.roleCode, '"CLUB_PRESIDENT"') THEN 1
WHEN JSON_CONTAINS(clubUser.roleCode, '"CLUB_VICE_PRESIDENT"') THEN 2
WHEN JSON_CONTAINS(clubUser.roleCode, '"CLUB_SECRETARY"') THEN 3
WHEN JSON_CONTAINS(clubUser.roleCode, '"CLUB_VICE_SECRETARY"') THEN 4
WHEN JSON_CONTAINS(clubUser.roleCode, '"CLUB_OPERATOR"') THEN 5
WHEN JSON_CONTAINS(clubUser.roleCode, '"CLUB_MEMBER"') THEN 6
ELSE 99
END
""");
}
sql.setCondition(cnd);
return sql;
}
}
@@ -0,0 +1,227 @@
package com.budwk.app.zhgh.dayofficework.outlay.outlayManage.union.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.budwk.app.base.annotation.SLog;
import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.param.PageForm;
import com.budwk.app.base.result.Result;
import com.budwk.app.base.service.BaseService;
import com.budwk.app.sys.models.Sys_union;
import com.budwk.app.zhgh.dayofficework.outlay.outlayManage.union.model.OutLayAllocateUnion;
import com.budwk.app.zhgh.dayofficework.outlay.outlayManage.union.model.OutlayManageUnion;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Lang;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
/**
* @author zhf
* @date 2026/2/3 11:12
* @description 分工会经费分配
*/
@IocBean
@At("/platform/outlay/outlayManage/unionAllocate")
@Ok("json:full")
@Slf4j
@Api(tags = "分工会经费分配")
public class OutlayManageUnionAllocateController {
@Inject
private BaseService baseService;
@At("")
@Ok("beetl:/platform/zhgh/dayofficework/outlay/outlayManage/union/allocate/index.html")
@SaCheckPermission("outlay.outlayManage.union.allocate")
public void index() {
}
@At
@ApiOperation("分页查询")
@SaCheckPermission("outlay.outlayManage.union.allocate")
public Result pageData(PageForm pageForm,
Integer year,
Integer quarterly,
String unionId) {
Sql sql = Sqls.create("""
SELECT
oau.*,
un.`name` unionName
FROM
`outlay_allocate_union` oau
LEFT JOIN sys_union un ON un.id = oau.unionId
$condition
""");
Cnd cnd = Cnd.NEW();
cnd.and("oau.year", "=", year);
cnd.andEX("oau.unionId", "=", unionId);
cnd.andEX("oau.quarterly", "=", quarterly);
cnd.and("oau.delFlag", "=", 0);
cnd.asc("un.unionCode");
sql.setCondition(cnd);
Pagination pagination = baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
return Result.success(pagination);
}
@At
@ApiOperation("分配金额")
@Aop(TransAop.READ_COMMITTED)
@SaCheckPermission("outlay.outlayManage.union.allocate")
public Result doEdit(String id, String allocateMoney) {
if (StrUtil.isEmpty(allocateMoney) || StrUtil.isEmpty(id)) {
return Result.error("参数错误!");
}
OutLayAllocateUnion allocateUnion = baseService.dao().fetch(OutLayAllocateUnion.class, id);
int quarter = DateUtil.month(DateUtil.date()) / 3 + 1;
if (allocateUnion.getQuarterly() < quarter) {
return Result.error("当前是第【" + quarter + "季度】无法修改【第" + allocateUnion.getQuarterly() + "季度】的额度!");
}
baseService.dao().update(OutLayAllocateUnion.class, Chain.make("allocateMoney", allocateMoney),
Cnd.where(OutLayAllocateUnion::getId, "=", id));
//找出今年工会的预算表
OutlayManageUnion newOutlayManageUnion = baseService.dao().fetch(OutlayManageUnion.class,
Cnd.where(OutlayManageUnion::getUnionId, "=", allocateUnion.getUnionId())
.and(OutlayManageUnion::getYear, "=", DateUtil.thisYear()));
if (allocateUnion.getQuarterly() == 1) {
//如果是第一季度,添加年度预算表
Sys_union union = baseService.dao().fetch(Sys_union.class, allocateUnion.getUnionId());
//找出去年剩余的钱
OutlayManageUnion oldOutlayManageUnion = baseService.dao().fetch(OutlayManageUnion.class,
Cnd.where(OutlayManageUnion::getUnionId, "=", allocateUnion.getUnionId())
.and(OutlayManageUnion::getYear, "=", DateUtil.thisYear() - 1));
BigDecimal newTotalQuota = Lang.isNotEmpty(oldOutlayManageUnion) ? oldOutlayManageUnion.getTotalQuota().subtract(oldOutlayManageUnion.getUsedQuota()) : new BigDecimal(allocateMoney);
if (Lang.isNotEmpty(newOutlayManageUnion)) {
//如果有今年的预算,代表第一季度已经分配过一次,现在修改
newOutlayManageUnion.setTotalQuota(newTotalQuota);
baseService.update(newOutlayManageUnion);
} else {
OutlayManageUnion manageUnion = new OutlayManageUnion();
manageUnion.setYear(DateUtil.thisYear());
manageUnion.setUnionId(union.getId());
manageUnion.setUnionName(union.getName());
manageUnion.setUnionCode(union.getUnionCode());
//找出去年剩余多少钱,
if (Lang.isNotEmpty(oldOutlayManageUnion)) {
BigDecimal surplusMoney = oldOutlayManageUnion.getTotalQuota().subtract(oldOutlayManageUnion.getUsedQuota());
//去年剩余的钱加上当年的分配金额
manageUnion.setTotalQuota(surplusMoney.add(new BigDecimal(allocateMoney)));
} else {
manageUnion.setTotalQuota(new BigDecimal(allocateMoney));
}
manageUnion.setUsedQuota(BigDecimal.ZERO);
baseService.insert(manageUnion);
}
} else {
baseService.dao().update(OutlayManageUnion.class,
Chain.make("totalQuota", newOutlayManageUnion.getTotalQuota().add(new BigDecimal(allocateMoney))),
Cnd.where(OutlayManageUnion::getId, "=", newOutlayManageUnion.getId()));
}
return Result.success();
}
@At
@ApiOperation("重置预算季度记录")
@SLog(tag = "分工会预算-季度预算分配", msg = "重置预算季度记录")
@SaCheckPermission("outlay.outlayManage.union.allocate")
public Result deleteAllocateRecord() {
int quarter = DateUtil.month(DateUtil.date()) / 3 + 1;
// 查询当前季度
int count = baseService.dao().count(OutLayAllocateUnion.class, Cnd.where(OutLayAllocateUnion::getQuarterly, "=", quarter)
.and(OutLayAllocateUnion::getYear, "=", DateUtil.thisYear()));
if (count == 0) {
return Result.error("当前季度还未分配,无法重置!");
}
baseService.dao().update(OutLayAllocateUnion.class, Chain.make("delFlag", 1),
Cnd.where(OutLayAllocateUnion::getQuarterly, "=", quarter)
.and(OutLayAllocateUnion::getYear, "=", DateUtil.thisYear()));
return Result.success();
}
@At
@ApiOperation("预算季度记录生成")
@SLog(tag = "分工会预算-季度预算分配", msg = "生成了预算分配记录")
@SaCheckPermission("outlay.outlayManage.union.allocate")
public Result doAllocateRecord() {
int quarter = DateUtil.month(DateUtil.date()) / 3 + 1;
// 查询当前季度
int count = baseService.dao().count(OutLayAllocateUnion.class, Cnd.where(OutLayAllocateUnion::getQuarterly, "=", quarter)
.and(OutLayAllocateUnion::getYear, "=", DateUtil.thisYear())
.and(OutLayAllocateUnion::getDelFlag, "=", 0));
if (count > 0) {
return Result.error("当前季度已分配,如需重新分配请点击重置分配记录!");
}
List<OutlayManageUnion> outlayManageUnionList;
if (quarter == 1) {
//如果是第一季度,查询去年剩余额度
outlayManageUnionList = baseService.dao().query(OutlayManageUnion.class,
Cnd.where(OutlayManageUnion::getYear, "=", DateUtil.thisYear() - 1));
} else {
//非第一季度
outlayManageUnionList = baseService.dao().query(OutlayManageUnion.class,
Cnd.where(OutlayManageUnion::getYear, "=", DateUtil.thisYear()));
}
List<OutLayAllocateUnion> insertList = this.initOutLayAllocateUnion(outlayManageUnionList);
baseService.insert(insertList);
return Result.success();
}
/**
* 初始化需要添加的数据
*
* @param outlayManageUnionList
* @return
*/
public List<OutLayAllocateUnion> initOutLayAllocateUnion(List<OutlayManageUnion> outlayManageUnionList) {
int quarter = DateUtil.month(DateUtil.date()) / 3 + 1;
List<Sys_union> unionList = baseService.dao().query(Sys_union.class, Cnd.NEW());
List<OutLayAllocateUnion> insertList = new ArrayList<>();
for (Sys_union union : unionList) {
OutLayAllocateUnion allocateUnion = new OutLayAllocateUnion();
allocateUnion.setYear(DateUtil.thisYear());
allocateUnion.setQuarterly(quarter);
allocateUnion.setUnionId(union.getId());
allocateUnion.setAllocateMoney(BigDecimal.ZERO);
//根据院级工会ID查询
OutlayManageUnion outlayManageUnion = outlayManageUnionList.stream().filter(o -> o.getUnionId().equals(union.getId())).findFirst().orElse(null);
if (Lang.isNotEmpty(outlayManageUnion)) {
BigDecimal surplusMoney = outlayManageUnion.getTotalQuota().subtract(outlayManageUnion.getUsedQuota());
allocateUnion.setAllocateHeadMoney(surplusMoney);
} else {
allocateUnion.setAllocateHeadMoney(BigDecimal.ZERO);
}
insertList.add(allocateUnion);
}
return insertList;
}
}
@@ -12,6 +12,7 @@ import com.budwk.app.web.commons.auth.utils.AuthUtil;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.dayofficework.outlay.outlayManage.model.OutlayUseDetail;
import com.budwk.app.zhgh.dayofficework.outlay.outlayManage.service.OutlayUseDetailService;
import com.budwk.app.zhgh.dayofficework.outlay.outlayManage.union.model.OutLayAllocateUnion;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
@@ -26,6 +27,8 @@ import org.nutz.lang.Strings;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import java.util.List;
/**
* @author zhf
* @date 2025/7/21 17:19
@@ -62,10 +65,8 @@ public class OutlayManageUnionUseDetailController {
Cnd cnd = Cnd.NEW();
cnd.and("totalQuota", "IS NOT", null);
cnd.and("year", "=", year);
if (AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
cnd.andEX("unionId", "=", unionId);
} else {
cnd.andEX("unionId", "=", unionId);
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
cnd.and("unionId", "=", SecurityUtil.getUnionId());
}
@@ -98,7 +99,7 @@ public class OutlayManageUnionUseDetailController {
@SaCheckPermission("outlay.outlayManage.union.useDetail")
@SLog(tag = "分工会预算使用详情", msg = "删除了分工会预算使用详情:${args[0]}")
public Result doDeleteDetail(String id) {
outlayUseDetailService.doDeleteDetail(id,"union");
outlayUseDetailService.doDeleteDetail(id, "union");
return Result.success();
}
@@ -109,9 +110,19 @@ public class OutlayManageUnionUseDetailController {
@SaCheckPermission("outlay.outlayManage.union.useDetail")
@SLog(tag = "分工会预算使用详情", msg = "编辑了分工会预算使用详情:${args[0]}")
public Result doEditDetail(OutlayUseDetail outlayUseDetail) {
outlayUseDetailService.doEditDetail(outlayUseDetail,"union");
outlayUseDetailService.doEditDetail(outlayUseDetail, "union");
return Result.success();
}
@At
@ApiOperation("查询分工会今年每个季度的分配情况")
@SaCheckPermission("outlay.outlayManage.union.useDetail")
public Result queryQuarterlyList(Integer year, String unionId){
List<OutLayAllocateUnion> allocateUnionList = outlayUseDetailService.dao().query(OutLayAllocateUnion.class,
Cnd.where(OutLayAllocateUnion::getYear, "=", year).and(OutLayAllocateUnion::getUnionId, "=", unionId)
.asc(OutLayAllocateUnion::getQuarterly));
return Result.success(allocateUnionList);
}
}
@@ -0,0 +1,55 @@
package com.budwk.app.zhgh.dayofficework.outlay.outlayManage.union.model;
import com.budwk.app.base.model.BaseModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.nutz.dao.entity.annotation.*;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* @author zhf
* @date 2026/2/3 14:31
* @description
*/
@Data
@EqualsAndHashCode(callSuper = true)
@Table("outlay_allocate_union")
@Comment("分工会经费管理")
public class OutLayAllocateUnion extends BaseModel implements Serializable {
@Column
@Name
@Comment("id")
@ColDefine(type = ColType.VARCHAR, width = 32)
@Prev(els = {@EL("uuid()")})
private String id;
@Column
@Comment("年份")
@ColDefine(type = ColType.INT)
private Integer year;
@Column
@Comment("分工会Id")
@ColDefine(type = ColType.VARCHAR, width = 32)
private String unionId;
@Column
@Comment("季度")
@ColDefine(type = ColType.INT)
private Integer quarterly;
@Column
@Comment("分配前额度")
@ColDefine(customType = "decimal(10,2)")
private BigDecimal allocateHeadMoney;
@Column
@Comment("分配额度")
@ColDefine(customType = "decimal(10,2)")
private BigDecimal allocateMoney;
}
@@ -0,0 +1,127 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
</style>
<div class="platform" id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker
@change="doSearch"
placeholder="选择年度"
style="width: 100%" type="year"
v-model="pageForm.year"
:clearable="false"
value-format="yyyy">
</el-date-picker>
</search-item>
<search-item label="姓名/工号">
<el-input v-model="pageForm.searchKeyword" placeholder="请输入姓名或工号"
clearable></el-input>
</search-item>
<search-item label="所属协会">
<el-select clearable filterable placeholder="所属协会"
style="width: 100%;" v-model="pageForm.clubId">
<el-option :label="item.clubName" :value="item.id"
v-for="item in clubs"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="历史拨付列表">
<el-button @click="doExcel" size="mini" type="primary" icon="el-icon-s-promotion">
导出Excel
</el-button>
<el-radio-group v-model="pageForm.isGiveMoney" size="small" @change="doSearch"
class="ml5">
<el-radio-button label="">全部</el-radio-button>
<el-radio-button label="1">已拨付</el-radio-button>
<el-radio-button label="0">未拨付</el-radio-button>
</el-radio-group>
<el-radio-group v-model="pageForm.payed" size="small" @change="doSearch"
class="ml5">
<el-radio-button label="">全部</el-radio-button>
<el-radio-button label="1">已缴费</el-radio-button>
<el-radio-button label="0">未缴费</el-radio-button>
</el-radio-group>
</table-tool>
<el-table :data="tableData"
@sort-change='pageOrder'
row-key="id" :loading="tableLoading">
<el-table-column type="index" :index="indexMethod" label="序号"
width="80px"></el-table-column>
<el-table-column
show-overflow-tooltip
:label="column.label"
:prop="column.prop"
:key="column.prop"
:sortable="column.sortable"
v-for="column in tableColumns">
<template scope="{row}" v-if="column.prop==='isGiveMoney'">
<span class="text-success"
v-if="row.isGiveMoney"></span>
<span class="text-danger" v-else></span>
</template>
<template scope="{row}" v-else-if="column.prop==='payed'">
<span class="text-success" v-if="row.payed">已缴</span>
<span class="text-danger" v-else>未缴</span>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: '#app',
store,
mixins: [initTableMixins],
data() {
return {
pageForm: {
searchName: "u.username",
year: new Date().getFullYear() + "",
isGiveMoney: "",
payed: "",
},
tableColumns: [
{prop: 'loginname', label: '工号', sortable: true},
{prop: 'username', label: '姓名'},
{prop: 'sex', label: '性别'},
{prop: 'applyDate2', label: '加入时间'},
{prop: 'userState', label: '在职状态'},
{prop: 'isGiveMoney', label: '是否拨付'},
{prop: 'payed', label: '是否缴费'},
{prop: 'clubName', label: '所在协会'},
{prop: 'roleName', label: '身份'},
],
}
},
methods: {
doExcel() {
const {isGiveMoney, clubId, year} = this.pageForm
this.$downLoad("/platform/outlay/outlayManage/backHistory/doExcel", {
clubId: clubId,
year: year,
isGiveMoney: isGiveMoney
})
},
},
async created() {
this.clubs = await this.$businessTool.listClubByRole()
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -20,15 +20,25 @@ layout("/layouts/platform.html"){
value-format="yyyy">
</el-date-picker>
</search-item>
<search-item label="所属协会">
<el-select clearable filterable placeholder="所属协会"
style="width: 100%;" v-model="pageForm.clubId">
<el-option :label="item.clubName" :value="item.id"
v-for="item in clubs"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="预算分配">
<el-button :loading="subLoading" @click="doMsg" type="primary"size="small">短信通知会长
</el-button>
<template v-if="pageForm.year===$moment().format('YYYY')">
<el-button @click="issuedOutlay" size="small" type="primary" v-if="!isAllocation">年度分配
<el-button @click="issuedOutlay" size="small" type="primary" v-if="!isAllocation">{{new
Date().getFullYear()}}年度分配
</el-button>
<el-button type="danger" size="small" @click="resetOutlay" v-else>
分配重置
清空{{new Date().getFullYear()}}年度已分配数据
</el-button>
</template>
</table-tool>
@@ -88,7 +98,7 @@ layout("/layouts/platform.html"){
</div>
<script nonce="${cspNonce!}">
const vue = new Vue({
new Vue({
el: '#app',
store,
mixins: [initTableMixins],
@@ -97,16 +107,33 @@ layout("/layouts/platform.html"){
tableColumns: [
{prop: 'year', label: '年度'},
{prop: 'clubName', label: '协会名称'},
{prop: 'historyUserNum', label: '上年度社团人数'},
{prop: 'historyGiveMoneyNum', label: '上年度拨付人数'},
{prop: 'historyNotGiveMoneyNum', label: '上年度未拨付人数'},
{prop: 'totalQuota', label: '预算费用'},
],
pageForm: {
year: this.$moment().format("YYYY")
},
isAllocation: false
isAllocation: false,
clubs: []
}
},
components: {},
methods: {
doMsg() {
this.$confirm('确定要给会长发短信让会长进系统核对拨付金额吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$axios.post("/platform/outlay/outlayManage/clubManage/doMsg",).then((resp) => {
if (resp.code === 0) {
this.$message.success(resp.msg);
}
})
})
},
doSubmit(row) {
this.$confirm('您确定要提交此条记录吗?', '提示', {
confirmButtonText: '确定',
@@ -170,6 +197,7 @@ layout("/layouts/platform.html"){
}
},
async created() {
this.clubs = await this.$businessTool.listClubByRole()
this.getIsAllocation()
this.pageData()
}
@@ -0,0 +1,71 @@
const clubHistoryBackUser = {
/*language=HTML*/
template: `
<div>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="姓名/工号">
<el-input v-model="pageForm.searchKeyword" placeholder="请输入姓名或工号"
clearable></el-input>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt10">
<el-table :data="tableData"
@sort-change='pageOrder'
row-key="id" :loading="tableLoading">
<el-table-column type="index" :index="indexMethod" label="序号"
width="80px"></el-table-column>
<el-table-column
show-overflow-tooltip
:label="column.label"
:prop="column.prop"
:key="column.prop"
:sortable="column.sortable"
v-for="column in tableColumns">
<template scope="{row}" v-if="column.prop==='isGiveMoney'">
<span class="text-success"
v-if="row.isGiveMoney">是</span>
<span class="text-danger" v-else>否</span>
</template>
<template scope="{row}" v-else-if="column.prop==='payed'">
<span class="text-success" v-if="row.payed">已缴</span>
<span class="text-danger" v-else>未缴</span>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</div>
`,
mixins: [initTableMixins],
data() {
return {
pageForm: {
searchName: "u.username",
},
tableColumns: [
{prop: 'loginname', label: '工号', sortable: true},
{prop: 'username', label: '姓名'},
{prop: 'sex', label: '性别'},
{prop: 'applyDate', label: '加入时间'},
{prop: 'userState', label: '在职状态'},
{prop: 'isGiveMoney', label: '是否拨付'},
{prop: 'payed', label: '是否缴费'},
{prop: 'clubName', label: '所在协会'},
{prop: 'roleName', label: '身份'},
],
pageDataUrl:"/platform/outlay/outlayManage/query/backUserPageData"
}
},
methods: {
onOpen(row, type) {
this.pageForm.searchKeyword = ""
this.pageForm.clubId = row.clubId
this.pageForm.type = type
this.pageForm.year = row.year
this.pageData()
},
}
}
@@ -0,0 +1,237 @@
<!--#
layout("/layouts/platform.html"){
#-->
<style>
</style>
<div class="platform" id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker
@change="doSearch"
placeholder="选择年度"
style="width: 100%" type="year"
v-model="pageForm.year"
:clearable="false"
value-format="yyyy">
</el-date-picker>
</search-item>
<search-item label="所属协会">
<el-select clearable filterable placeholder="所属协会"
style="width: 100%;" v-model="pageForm.clubId">
<el-option :label="item.clubName" :value="item.id"
v-for="item in clubs"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="温馨提示:请先更新拨付金额后再点击核对按钮">
<el-button @click="closeAudit(false)" size="mini" type="primary">
开启核对入口
</el-button>
<el-button @click="closeAudit(true)" size="mini" type="danger">
取消核对入口
</el-button>
</table-tool>
<el-table :data="tableData" style="width: 100%" row-key="id"
v-loading="tableLoading" :size="tableSize" class="vi-table">
<el-table-column type="index" :index="indexMethod" label="序号"
width="80px"></el-table-column>
<el-table-column
show-overflow-tooltip
v-for="column in tableColumns"
:label="column.label"
:prop="column.prop"
:key="column.prop"
:sortable="column.sortable"
:width="column.width"
min-width="50"
>
<template v-slot="{row}" v-if="column.prop==='historyUserNum'">
<el-link type="primary" @click="openBackUser(row,'historyUserNum')">
{{row.historyUserNum}}
</el-link>
</template>
<template v-slot="{row}" v-else-if="column.prop==='historyGiveMoneyNum'">
<el-link type="primary" @click="openBackUser(row,'historyGiveMoneyNum')">
{{row.historyGiveMoneyNum}}
</el-link>
</template>
<template v-slot="{row}" v-else-if="column.prop==='historyNotGiveMoneyNum'">
<el-link type="primary" @click="openBackUser(row,'historyNotGiveMoneyNum')">
{{row.historyNotGiveMoneyNum}}
</el-link>
</template>
<template v-slot="{row}" v-else-if="column.prop==='isCheck'">
<span>{{row.isCheck?'已核对':'未核对'}}</span>
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="400">
<template slot-scope="{row}">
<el-button
:disabled="row.isCheck||row.isDisable"
@click="doMoney(row)"
size="mini"
type="primary">
更新拨付金额
</el-button>
<el-button
:disabled="row.isCheck||row.isDisable"
@click="doAudit(row)"
size="mini"
type="primary">
核对
</el-button>
<el-button v-if="row.isCheck&&!row.isDisable"
@click="cancelAudit(row)"
size="mini"
type="danger">
取消核对
</el-button>
<el-button
v-if="row.isCheck"
@click="doExcel(row)"
size="mini"
type="primary">
导出
</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
<template #view>
<club-history-back-user ref="clubHistoryBackUserRef"></club-history-back-user>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include('clubHistoryBackUser.js'){}#-->
new Vue({
el: '#app',
store,
mixins: [initTableMixins],
components: {
"club-history-back-user": clubHistoryBackUser,
},
data() {
return {
tableColumns: [
{prop: 'year', label: '年度'},
{prop: 'clubName', label: '协会名称'},
{prop: 'historyUserNum', label: '上年度社团人数'},
{prop: 'historyGiveMoneyNum', label: '上年度拨付人数'},
{prop: 'historyNotGiveMoneyNum', label: '上年度未拨付人数'},
{prop: 'totalQuota', label: '预算费用'},
{prop: 'isCheck', label: '预算费用'},
],
pageForm: {
year: this.$moment().format("YYYY")
},
clubs:[]
}
},
methods: {
openBackUser(row, type) {
this.$refs.guava.view(() => {
this.$refs.clubHistoryBackUserRef.onOpen(row, type)
})
},
closeAudit(flag) {
this.$confirm('确定要' + (flag ? '关闭' : '开启') + '拨付核对入口吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$axios.post("/platform/outlay/outlayManage/query/closeAudit", {
flag: flag,
}).then(resp => {
if (resp.code === 0) {
this.doSearch()
this.$message.success(resp.msg);
}
})
})
},
doMoney(row) {
this.$confirm('更新前请前往【缴费管理】菜单,核对是否缴费。核对准确后,再点击更新拨付金额,确定要更新吗?', '提示', {
confirmButtonText: '更新',
cancelButtonText: '前往【缴费管理】菜单',
distinguishCancelAndClose: true,
beforeClose: (action, instance, done) => {
if (action === 'confirm') {
done();
} else if (action === 'cancel') {
window.open("/platform/club/pay")
done();
} else if (action === 'close') {
done();
}
},
type: 'warning'
}).then(() => {
this.$axios.post("/platform/outlay/outlayManage/query/doMoney", {clubId: row.clubId}).then(resp => {
if (resp.code === 0) {
this.doSearch()
this.$message.success(resp.msg);
}
})
})
},
doAudit(row) {
this.$confirm('提交前请先更新拨付金额,提交后不能修改拨付金额,您确定要提交吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$axios.post("/platform/outlay/outlayManage/query/doAudit", {id: row.id}).then(resp => {
if (resp.code === 0) {
this.doSearch()
this.$message.success(resp.msg);
}
})
})
},
cancelAudit(row) {
this.$confirm('确定要取消核对吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$axios.post("/platform/outlay/outlayManage/query/cancelAudit", {id: row.id,}).then(resp => {
if (resp.code === 0) {
this.doSearch()
this.$message.success(resp.msg);
}
})
})
},
doExcel(row) {
this.$downLoad("/platform/outlay/outlayManage/query/doExcel", {clubId: row.clubId, year: row.year})
},
},
async created() {
this.clubs = await this.$businessTool.listClubByRole()
this.pageData()
}
})
</script>
<!--#
}
#-->
@@ -0,0 +1,197 @@
<!--#
layout("/layouts/platform.html"){
#-->
<div id="app" v-cloak>
<guava ref="guava">
<template>
<el-card shadow="never">
<search @search="doSearch">
<search-item label="年度">
<el-date-picker
@change="doSearch"
placeholder="选择年度"
style="width: 100%"
type="year"
v-model="pageForm.year"
:clearable="false"
value-format="yyyy">
</el-date-picker>
</search-item>
<search-item label="所属季度">
<dict-select clearable code="OUTLAY_QUARTERLY"
placeholder="请选择所属季度"
v-model="pageForm.quarterly"></dict-select>
</search-item>
<search-item label="所属工会">
<el-select placeholder="请选择所属工会" v-model="pageForm.unionId"
style="width: 100%;"
clearable
@change="doSearch"
filterable>
<el-option v-for="item in unionList"
:label="item.name"
:key="item.id"
:value="item.id"></el-option>
</el-select>
</search-item>
</search>
</el-card>
<el-card shadow="never" class="mt10">
<table-tool label="预算分配">
<el-button @click="doAllocateRecord" size="small" type="primary" :loading="formLoading">季度记录生成
</el-button>
<el-button @click="deleteAllocateRecord" size="small" type="danger" :loading="formLoading">重置季度记录
</el-button>
</table-tool>
<el-table :data="tableData" style="width: 100%" row-key="id"
v-loading="tableLoading" :size="tableSize" class="vi-table">
<el-table-column type="index" :index="indexMethod" label="序号"
width="80px"></el-table-column>
<el-table-column
show-overflow-tooltip
v-for="column in tableColumns"
:label="column.label"
:prop="column.prop"
:key="column.prop"
:sortable="column.sortable"
:width="column.width"
min-width="50"
>
<template v-slot="{row}" v-if="column.prop==='quarterly'">
<dict-tag :options="dict.type.OUTLAY_QUARTERLY"
:value="row.quarterly"></dict-tag>
</template>
<template v-slot="{row}" v-else-if="column.prop==='allocateMoney'">
<el-input-number v-if="row.edit" :min="0"
style="width: 100%"
size="small"
v-model="row.newAllocateMoney" placeholder="填写总额度">
</el-input-number>
<div v-else>
{{row.allocateMoney}}
</div>
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="200">
<template slot-scope="{row}">
<div v-if="row.edit">
<el-button type="success" icon="el-icon-check" size="mini"
@click="doEdit(row)"
circle></el-button>
<el-button type="danger" icon="el-icon-close" size="mini"
@click="$set(row,'edit',false)"
circle></el-button>
</div>
<el-button v-else size="mini" type="primary"
@click="$set(row,'edit',true);$set(row,'newAllocateMoney',row.allocateMoney);">
编辑
</el-button>
</template>
</el-table-column>
</el-table>
<!--#include("/layouts/pagination.html"){}#-->
</el-card>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
new Vue({
el: '#app',
store,
mixins: [initTableMixins],
dicts: ["OUTLAY_QUARTERLY"],
data() {
return {
pageForm: {
year: this.$moment().format("YYYY")
},
unionList: [],
tableColumns: [
{prop: 'year', label: '年度'},
{prop: 'quarterly', label: '季度'},
{prop: 'unionName', label: '工会名称'},
{prop: 'allocateHeadMoney', label: '分配前额度'},
{prop: 'allocateMoney', label: '分配额度'},
],
quarterlyList: [],
}
},
methods: {
doEdit(row) {
this.$confirm('确定要给【' + row.unionName + '】分配预算吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.formLoading = true
this.$axios.post("/platform/outlay/outlayManage/unionAllocate/doEdit", {
id: row.id,
allocateMoney: row.newAllocateMoney
}).then((resp) => {
if (resp.code === 0) {
this.$message.success(resp.msg)
this.doSearch()
}
}).finally(() => {
this.formLoading = false
})
})
},
deleteAllocateRecord() {
this.$confirm('确定要重置【第' + this.$moment().quarter() + '季度】的预算记录吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.formLoading = true
this.$axios.post("/platform/outlay/outlayManage/unionAllocate/deleteAllocateRecord").then((resp) => {
if (resp.code === 0) {
this.$message.success(resp.msg)
this.doSearch()
}
}).finally(() => {
this.formLoading = false
})
})
},
doAllocateRecord() {
this.$confirm('确定要生成【第' + this.$moment().quarter() + '季度】的预算记录吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.formLoading = true
this.$axios.post("/platform/outlay/outlayManage/unionAllocate/doAllocateRecord").then((resp) => {
if (resp.code === 0) {
this.$message.success(resp.msg)
this.doSearch()
}
}).finally(() => {
this.formLoading = false
})
})
},
},
created() {
this.$businessTool.listUnion().then((data) => {
this.unionList = data
})
this.$businessTool.getDictOptions("OUTLAY_QUARTERLY").then((data) => {
let quarter = this.$moment().quarter();
this.$set(this.pageForm, "quarterly", data[quarter - 1].code)
this.pageData()
})
}
})
</script>
<!--#
}
#-->
@@ -63,8 +63,10 @@ layout("/layouts/platform.html"){
</el-table-column>
<el-table-column align="center" header-align="center" label="操作"
fixed="right" width="150">
fixed="right" width="250">
<template slot-scope="{row}">
<el-button size="mini" type="primary" @click="openAllocateView(row)">经费分配详情
</el-button>
<el-button size="mini" type="primary" @click="openView(row)">使用详情</el-button>
</template>
</el-table-column>
@@ -74,13 +76,19 @@ layout("/layouts/platform.html"){
</template>
<template #view>
<outlay-manage-union-use-detail-info ref="detailInfo" @search="doSearch"></outlay-manage-union-use-detail-info>
<outlay-manage-union-use-detail-info ref="detailInfo"
@search="doSearch"></outlay-manage-union-use-detail-info>
</template>
<template #edit>
<outlay-manage-union-quarterly-allocate ref="quarterlyAllocate"></outlay-manage-union-quarterly-allocate>
</template>
</guava>
</div>
<script nonce="${cspNonce!}">
<!--#include("detailInfo.js"){}#-->
<!--#include("quarterlyOutlayAllocate.js"){}#-->
const vue = new Vue({
el: '#app',
store,
@@ -102,9 +110,15 @@ layout("/layouts/platform.html"){
}
},
components: {
"outlay-manage-union-use-detail-info": OUTLAY_MANAGE_UNION_USE_DETAIL_INFO
"outlay-manage-union-use-detail-info": OUTLAY_MANAGE_UNION_USE_DETAIL_INFO,
"outlay-manage-union-quarterly-allocate": OUTLAY_MANAGE_UNION_QUARTERLY_ALLOCATE
},
methods: {
openAllocateView(row) {
this.$refs.guava.edit(() => {
this.$refs.quarterlyAllocate.open(row)
})
},
openView(row) {
this.$refs.guava.view(() => {
this.$refs.detailInfo.open(row)
@@ -0,0 +1,42 @@
let OUTLAY_MANAGE_UNION_QUARTERLY_ALLOCATE = {
/*language=HTML*/
template:
`
<div>
<template>
<table-tool label="季度分配记录"></table-tool>
<el-table :data="tableData" style="width: 100%" row-key="id" class="vi-table">
<el-table-column type="index" label="序号" width="80px"></el-table-column>
<el-table-column label="季度" prop="quarterly">
<template v-slot="{row}">
<dict-tag :options="dict.type.OUTLAY_QUARTERLY"
:value="row.quarterly"></dict-tag>
</template>
</el-table-column>
<el-table-column label="分配前额度" prop="allocateHeadMoney"></el-table-column>
<el-table-column label="分配额度" prop="allocateMoney"></el-table-column>
</el-table>
</template>
</div>
`,
dicts: ["OUTLAY_QUARTERLY"],
data() {
return {
rowData: {},
tableData: []
}
},
methods: {
open(row) {
this.rowData = row
this.$axios.post("/platform/outlay/outlayManage/unionUseDetail/queryQuarterlyList", {
year: row.year,
unionId: row.unionId
}).then(resp => {
if (resp.code === 0) {
this.tableData = resp.data
}
})
}
}
}