Merge remote-tracking branch 'origin/main'

This commit is contained in:
2026-04-25 16:39:26 +08:00
9 changed files with 272 additions and 2 deletions
@@ -153,6 +153,7 @@ public class ActivitySportsApplyUserServiceImpl extends BaseServiceImpl<Activity
school.applyType,
school.image,
school.eventNotification,
school.activityGroupId,
(SELECT count( 1 ) FROM activity_school_apply app WHERE app.activityId = school.id AND app.`status` = 2 ) apply_num,
(SELECT count( 1 ) FROM activity_school_apply app WHERE app.activityId = school.id AND ( app.applyUser = @userid OR app.userId = @userid )) > 0 applyed,
(SELECT COUNT(1) FROM activity_school_apply app WHERE app.activityId=school.id AND app.unionId=@unionId AND app.unionLeader=TRUE) LeaderCount,
@@ -126,6 +126,37 @@ public class AIdFundPayRecordController {
CommonDownloadUtil.download(pageForm.getYear() + "会员年度缴费记录.xlsx", workbook, response);
}
@At
@Ok("void")
@ApiOperation("导出年度缴费名单")
@SaCheckPermission("medicalMutualAid.aidFund.payRecord")
public void exportAnnualPayMemberList(AidFundPageForm pageForm, HttpServletResponse response) {
/*
* 导出参数说明:
* pageForm 可传所属工会、所属单位、会员类型、姓名/工号关键字等筛选条件;
* 返回 Excel 列为工号、姓名、单位,以及 2015 到当前年度的动态缴费金额列。
*/
List<Integer> years = IntStream.rangeClosed(2015, DateUtil.thisYear())
.boxed()
.toList();
List<ExcelExportEntity> entityList = new ArrayList<>();
entityList.add(new ExcelExportEntity("工号", "loginname", 20));
entityList.add(new ExcelExportEntity("姓名", "username", 20));
entityList.add(new ExcelExportEntity("单位", "unitName", 30));
years.forEach(year -> {
ExcelExportEntity entity = new ExcelExportEntity(String.valueOf(year), String.valueOf(year), 20);
entity.setType(10);
entityList.add(entity);
});
List<NutMap> list = aidFundMemberPayService.getAnnualPayMemberList(pageForm);
ExportParams exportParams = new ExportParams();
exportParams.setType(ExcelType.XSSF);
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entityList, list);
CommonDownloadUtil.download("年度缴费名单.xlsx", workbook, response);
}
@At
@Ok("void")
@ApiOperation("导出缴费名单")
@@ -3,23 +3,28 @@ package com.budwk.app.zhgh.staffbenefit.medicalMutualAid.aidFund.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaMode;
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.result.Result;
import com.budwk.app.base.utils.PageUtil;
import com.budwk.app.flow.engine.FlowEngine;
import com.budwk.app.zhgh.staffbenefit.medicalMutualAid.aidFund.param.AidFundPageForm;
import com.budwk.app.zhgh.staffbenefit.medicalMutualAid.aidFund.service.AidFundMemberChangeRecordService;
import com.budwk.app.zhgh.staffbenefit.medicalMutualAid.aidFund.service.AidFundMemberService;
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.Cnd;
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.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok;
import org.nutz.mvc.annotation.Param;
/**
* @author zhf
@@ -37,6 +42,9 @@ public class AidFundChangeRecordController {
@Inject
private AidFundMemberChangeRecordService changeRecordService;
@Inject
private FlowEngine flowEngine;
@At("")
@Ok("beetl:/platform/zhgh/staffbenefit/medicalMutualAid/aidFund/changeRecord/index.html")
@SaCheckPermission("medicalMutualAid.aidFund.changeRecord")
@@ -105,5 +113,25 @@ public class AidFundChangeRecordController {
return Result.success(pagination);
}
/**
* 删除基金会员变更记录。
*
* @param id 变更记录 ID,前端列表行中的 row.id
* @return Result,删除成功时返回 success;ID 为空时返回失败提示
*/
@At
@ApiOperation("删除")
@Aop(TransAop.READ_COMMITTED)
@SaCheckPermission("medicalMutualAid.aidFund.changeRecord")
@SLog(tag = "基金会员-变更记录", msg = "删除变更记录")
public Result delete(@Param("id") String id) {
if (StrUtil.isBlank(id)) {
return Result.error("请选择需要删除的变更记录");
}
changeRecordService.delete(id);
flowEngine.processInstanceService().deleteProcessInstanceByBusinessKey(id);
return Result.success();
}
}
@@ -3,11 +3,13 @@ package com.budwk.app.zhgh.staffbenefit.medicalMutualAid.aidFund.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaMode;
import cn.hutool.core.util.StrUtil;
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.utils.PageUtil;
import com.budwk.app.flow.enums.ProcessTaskStateEnum;
import com.budwk.app.web.commons.auth.utils.AuthUtil;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.staffbenefit.condolence.model.Condolence;
import com.budwk.app.zhgh.staffbenefit.medicalMutualAid.aidFund.service.AidFundMemberChangeRecordService;
@@ -26,6 +28,7 @@ import org.nutz.mvc.annotation.Ok;
import org.nutz.mvc.annotation.Param;
import java.util.List;
import java.util.Objects;
/**
* @author zhf
@@ -115,7 +118,9 @@ public class AidFundUnionAuditController {
cnd.andEX("info.changeType", "=", changeType);
cnd.and("t.taskName", "=", "06ed1d6d-5f96-485f-9150-ed1ef4a082d6");
cnd.and("ta.actorId", "in", List.of(SecurityUtil.getUserId()));
if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name())){
cnd.and("ta.actorId", "in", List.of(SecurityUtil.getUserId()));
}
if (approval) {
cnd.and("t.taskState", "in", List.of(ProcessTaskStateEnum.FINISHED.getCode(), ProcessTaskStateEnum.INTERRUPT.getCode()));
@@ -133,4 +138,50 @@ public class AidFundUnionAuditController {
Pagination<NutMap> pageVO = changeRecordService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql);
return Result.success(pageVO);
}
/**
* 查询所有未审核分工会对应的分工会主席工号。
*
* @param year 年度,按变更记录申请时间的年份筛选
* @param aidFundMemberUserType 基金会员类型,传字典编码;为空时不限制
* @param changeType 变更类型,传字典编码;为空时不限制
* @return Resultdata 为需要发送通知的分工会主席工号列表
*/
@At
@ApiOperation("查询未审核分工会主席工号")
@SaCheckPermission("medicalMutualAid.aidFund.unionAudit")
public Result notifyUnapprovedUnionChairman(@Param(value = "year") Integer year,
@Param(value = "aidFundMemberUserType") String aidFundMemberUserType,
@Param(value = "changeType") String changeType) {
Sql sql = Sqls.create("""
SELECT DISTINCT
chairman.loginname
FROM
wf_process_task t
LEFT JOIN wf_process_instance ins ON ins.id = t.processInstanceId
LEFT JOIN aid_fund_member_change_record info ON info.id = ins.businessNo
LEFT JOIN vw_user us ON us.id = info.userId
LEFT JOIN sys_user_role ur ON ur.unionId = us.unionId
LEFT JOIN sys_role role ON role.id = ur.roleId
LEFT JOIN sys_user chairman ON chairman.id = ur.userId
$condition
""");
Cnd cnd = Cnd.NEW();
cnd.andEX("YEAR(info.applyTime)", "=", year);
cnd.andEX("IFNULL(info.aidFundMemberUserType, us.aidFundMemberUserType)", "=", aidFundMemberUserType);
cnd.andEX("info.changeType", "=", changeType);
cnd.and("t.taskName", "=", "06ed1d6d-5f96-485f-9150-ed1ef4a082d6");
cnd.and("t.taskState", "=", ProcessTaskStateEnum.DOING.getCode());
cnd.and("role.code", "=", RoleConstant.BRANCH_UNION_CHAIRMAN.name());
cnd.and("chairman.loginname", "is not", null);
sql.setCondition(cnd);
// 这里只返回需要发送通知的主席工号,真实消息发送功能由后续消息接口接入。
List<String> loginNames = changeRecordService.listMap(sql).stream()
.map(map -> map.getString("loginname"))
.filter(Objects::nonNull)
.distinct()
.toList();
return Result.success(loginNames);
}
}
@@ -15,4 +15,12 @@ public interface AidFundMemberPayService extends BaseService<AidFundMemberPay> {
Sql getSql(AidFundPageForm pageForm);
List<NutMap> getYearPayList(AidFundPageForm pageForm);
/**
* 查询年度缴费名单导出数据。
*
* @param pageForm 页面筛选参数,包含所属工会、所属单位、会员类型、姓名/工号关键字等条件
* @return 返回导出行数据,字段包含 loginname、username、unitName,以及 2015 到当前年度的缴费金额字段
*/
List<NutMap> getAnnualPayMemberList(AidFundPageForm pageForm);
}
@@ -201,4 +201,102 @@ public class AidFundMemberPayServiceImpl extends BaseServiceImpl<AidFundMemberPa
}
return nutMaps;
}
@Override
public List<NutMap> getAnnualPayMemberList(AidFundPageForm pageForm) {
/*
* 导出参数说明:
* pageForm.unionId:按所属工会筛选;
* pageForm.unitId:按所属单位筛选;
* pageForm.aidFundMemberUserType:按基金会员类型筛选;
* pageForm.searchKeyword:按姓名或工号模糊筛选。
* 返回值字段:loginname、username、unitName 为人员基础信息,2015 到当前年度字段为对应年度缴费金额。
*/
List<Integer> years = IntStream.rangeClosed(2015, DateUtil.thisYear())
.boxed()
.toList();
Cnd userCnd = Cnd.where(View_user::getAidFundMember, "=", 1);
userCnd.andEX(View_user::getUnionId, "=", pageForm.getUnionId());
userCnd.andEX(View_user::getUnitId, "=", pageForm.getUnitId());
userCnd.andEX(View_user::getAidFundMemberUserType, "=", pageForm.getAidFundMemberUserType());
if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) {
SqlExpressionGroup group = new SqlExpressionGroup();
group.orLike(View_user::getLoginname, pageForm.getSearchKeyword(), true);
group.orLike(View_user::getUsername, pageForm.getSearchKeyword(), true);
userCnd.and(group);
}
userCnd.desc(View_user::getUnitCode);
List<View_user> userList = dao().query(View_user.class, userCnd);
Set<String> oldLoginNames = new HashSet<>();
Map<String, String> oldLoginToUserId = new HashMap<>();
for (View_user user : userList) {
if (StrUtil.isNotBlank(user.getOldLoginName())) {
oldLoginNames.add(user.getOldLoginName());
}
}
if (!oldLoginNames.isEmpty()) {
List<Sys_user> oldUsers = dao().query(Sys_user.class,
Cnd.where(Sys_user::getLoginname, "in", new ArrayList<>(oldLoginNames)));
for (Sys_user oldUser : oldUsers) {
oldLoginToUserId.put(oldUser.getLoginname(), oldUser.getId());
}
}
Set<String> allUserIds = new HashSet<>();
for (View_user user : userList) {
allUserIds.add(user.getId());
if (StrUtil.isNotBlank(user.getOldLoginName())) {
String oldUserId = oldLoginToUserId.get(user.getOldLoginName());
if (oldUserId != null) {
allUserIds.add(oldUserId);
}
}
}
List<AidFundMemberPay> payList = allUserIds.isEmpty()
? new ArrayList<>()
: query(Cnd.where(AidFundMemberPay::getUserId, "in", new ArrayList<>(allUserIds)));
Map<String, Map<Integer, Double>> payIndex = new HashMap<>();
for (AidFundMemberPay pay : payList) {
if (pay.getUserId() == null || pay.getYear() == null || pay.getMoney() == null) {
continue;
}
payIndex.computeIfAbsent(pay.getUserId(), k -> new HashMap<>())
.put(pay.getYear(), pay.getMoney());
}
List<NutMap> result = new ArrayList<>();
for (View_user user : userList) {
NutMap row = NutMap.NEW();
row.put("loginname", user.getLoginname());
row.put("username", user.getUsername());
row.put("unitName", user.getUnitName());
Set<String> userIds = new HashSet<>();
userIds.add(user.getId());
if (StrUtil.isNotBlank(user.getOldLoginName())) {
String oldUserId = oldLoginToUserId.get(user.getOldLoginName());
if (oldUserId != null) {
userIds.add(oldUserId);
}
}
for (Integer year : years) {
Double yearMoney = 0.0;
for (String userId : userIds) {
Double money = Optional.ofNullable(payIndex.get(userId))
.map(map -> map.get(year))
.orElse(0.0);
yearMoney += money;
}
row.put(String.valueOf(year), yearMoney == 0.0 ? null : yearMoney);
}
result.add(row);
}
return result;
}
}
@@ -84,6 +84,7 @@ layout("/layouts/platform.html"){
<el-table-column label="操作" fixed="right" width="200">
<template slot-scope="{row}">
<el-button @click="onView(row)" size="mini" type="primary">查看</el-button>
<el-button @click="onDelete(row)" :loading="formLoading" size="mini" type="danger">删除</el-button>
</template>
</el-table-column>
</el-table>
@@ -135,6 +136,23 @@ layout("/layouts/platform.html"){
this.$refs.infoRef.onOpen(row)
})
},
onDelete(row) {
this.$confirm("确定要删除【" + row.username + "】的变更记录吗?删除后将同步删除关联流程记录", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.formLoading = true
this.$axios.post(loc() + "/delete", {id: row.id}).then((res) => {
if (res.code === 0) {
this.$message.success(res.msg)
this.doSearch()
}
}).finally(() => {
this.formLoading = false
})
})
},
async unionChange(val) {
this.pageForm.unitId = null
this.unitList = await this.$businessTool.listUnit(val)
@@ -75,6 +75,12 @@ layout("/layouts/platform.html"){
type="primary">导出会员缴费金额
</el-button>
<el-button @click="exportAnnualPayMemberList"
size="small"
icon="el-icon-download"
type="primary">导出年度缴费名单
</el-button>
<el-button :disabled="tableData.length==0" :loading="tableLoading" @click="clearPayRecord"
icon="el-icon-delete"
size="small"
@@ -191,6 +197,9 @@ layout("/layouts/platform.html"){
exportYearPayRecord(){
this.$downLoad('/platform/medicalMutualAid/aidFund/payRecord/exportYearPayRecord', this.pageForm)
},
exportAnnualPayMemberList() {
this.$downLoad('/platform/medicalMutualAid/aidFund/payRecord/exportAnnualPayMemberList', this.pageForm)
},
exportPayRecord() {
this.$downLoad('/platform/medicalMutualAid/aidFund/payRecord/exportPayRecord', this.pageForm)
},
@@ -40,10 +40,13 @@ layout("/layouts/platform.html"){
<el-radio-button label="true">已审核</el-radio-button>
<el-radio-button label="false">未审核</el-radio-button>
</el-radio-group>
<el-button @click="notifyUnapprovedUnionChairman" :loading="formLoading" size="small" type="primary">
一键通知未审核工会
</el-button>
</table-tool>
<el-table :data="tableData" :size="tableSize" @sort-change="pageOrder"
ref="table" row-key="id" style="width: 100%">
ref="table" row-key="id" style="width: 100%" v-loading="tableLoading">
<el-table-column :index="indexMethod" header-align="center" label="序号"
type="index" width="60px"></el-table-column>
<el-table-column
@@ -158,6 +161,29 @@ layout("/layouts/platform.html"){
this.$refs.infoRef.onOpen(row)
})
},
notifyUnapprovedUnionChairman() {
this.$confirm("确定要通知未审核的分工会吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
this.formLoading = true
this.$axios.post(loc() + "/notifyUnapprovedUnionChairman", {
year: this.pageForm.year,
aidFundMemberUserType: this.pageForm.aidFundMemberUserType,
changeType: this.pageForm.changeType
}).then((res) => {
if (res.code === 0) {
const loginNames = res.data || []
this.$alert(loginNames.length ? loginNames.join("、") : "暂无需要发送通知的人员", "需要发送人的工号", {
confirmButtonText: "确定"
})
}
}).finally(() => {
this.formLoading = false
})
})
},
handleTaskAction(val) {
this.$confirm("您确定要提交吗?", "提示", {