From 8c3c6f45c32b34dd6619112b86d71b534bb2076e Mon Sep 17 00:00:00 2001 From: zhouhefeng Date: Fri, 3 Jul 2026 08:46:44 +0800 Subject: [PATCH] commit --- .../config/ProposalConfigUnitController.java | 146 ++++++++++++++---- .../ProposalUnderTakeReplyController.java | 1 + 2 files changed, 115 insertions(+), 32 deletions(-) diff --git a/src/main/java/com/budwk/app/zhgh/democratic/proposal/controller/config/ProposalConfigUnitController.java b/src/main/java/com/budwk/app/zhgh/democratic/proposal/controller/config/ProposalConfigUnitController.java index 22d32afe..b3a67ed7 100644 --- a/src/main/java/com/budwk/app/zhgh/democratic/proposal/controller/config/ProposalConfigUnitController.java +++ b/src/main/java/com/budwk/app/zhgh/democratic/proposal/controller/config/ProposalConfigUnitController.java @@ -13,7 +13,6 @@ 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.flow.entity.ProcessTask; import com.budwk.app.flow.enums.ProcessTaskStateEnum; import com.budwk.app.flow.service.ProcessTaskService; import com.budwk.app.sys.models.Sys_role; @@ -173,19 +172,23 @@ public class ProposalConfigUnitController { int syncActorCount = 0; int skipUnitCount = 0; - for (ProposalUndertake undertake : undertakes) { + Map> unitLeaderMap = undertakes.stream().collect(Collectors.toMap(ProposalUndertake::getId, undertake -> { List sysUserRoles = dao.query(Sys_user_role.class, Cnd.where(Sys_user_role::getRoleId, "=", sysRole.getId()) .and(Sys_user_role::getUnderTakeId, "=", undertake.getId())); - List userIds = sysUserRoles.stream().map(Sys_user_role::getUserId).distinct().toList(); - if (CollectionUtil.isEmpty(userIds)) { + return sysUserRoles.stream().map(Sys_user_role::getUserId).filter(StrUtil::isNotBlank).distinct().toList(); + })); + for (ProposalUndertake undertake : undertakes) { + if (CollectionUtil.isEmpty(unitLeaderMap.get(undertake.getId()))) { skipUnitCount++; - continue; } + } - List tasks = queryDoingUnitReplyTasks(undertake.getId()); - scanTaskCount += tasks.size(); - for (ProcessTask task : tasks) { - int syncCount = processTaskService.syncTaskActors(task.getId(), userIds); + List taskTargets = queryDoingUnitReplyTaskTargets(); + scanTaskCount = taskTargets.size(); + for (NutMap taskTarget : taskTargets) { + List userIds = unitLeaderMap.get(taskTarget.getString("unitId")); + if (CollectionUtil.isNotEmpty(userIds)) { + int syncCount = processTaskService.syncTaskActors(taskTarget.getLong("taskId"), userIds); if (syncCount > 0) { syncTaskCount++; syncActorCount += syncCount; @@ -197,35 +200,114 @@ public class ProposalConfigUnitController { } /** - * 根据承办单位和提案承办单位记录查询正在办理中的答复任务。 + * 根据提案承办单位记录计算正在办理中的答复任务与承办单位对应关系。 * * 说明: - * 1. 参数 underTakeId 为 proposal_undertake.id,即当前承办单位配置ID。 - * 2. 不依赖 wf_process_task.variable 中的 underTakeId,避免历史任务变量和承办单位配置不一致导致漏同步。 - * 3. 主办单位只匹配 master_reply、opinion_master_reply,协办单位只匹配 slave_reply。 - * 4. 返回值为当前仍在办理中的流程任务列表。 + * 1. 无入参,自动扫描当前进行中的主办答复、协办答复、意见主办答复任务。 + * 2. 返回值为 List,每行包含 taskId 和 unitId,表示该任务应按哪个承办单位负责人同步办理人。 + * 3. 优先使用 task.variable.underTakeId,其次使用现有 actorUnitId 与 proposal_reply_unit.unitId 的匹配关系。 + * 4. 对历史缺少 underTakeId 且 actorUnitId 不匹配承办单位的数据,只在“剩余任务数”和“剩余承办单位数”能一一对应时按顺序补位,避免多个协办单位互相覆盖。 */ - private List queryDoingUnitReplyTasks(String underTakeId) { - Sql sql = Sqls.queryEntity(""" - SELECT DISTINCT - t.* + private List queryDoingUnitReplyTaskTargets() { + Sql sql = Sqls.create(""" + WITH direct_targets AS ( + SELECT DISTINCT + ins.businessNo AS proposalId, + t.id AS taskId, + IF(t.taskName IN ('master_reply', 'opinion_master_reply'), 1, 0) AS isMaster, + pru.unitId AS unitId + FROM + wf_process_task t + INNER JOIN wf_process_instance ins ON ins.id = t.processInstanceId + INNER JOIN proposal_reply_unit pru ON pru.proposalId = ins.businessNo + AND ( + (t.taskName IN ('master_reply', 'opinion_master_reply') AND pru.isMaster = 1) + OR (t.taskName = 'slave_reply' AND pru.isMaster = 0) + ) + LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id + WHERE + t.taskState = @taskState + AND t.taskName IN ('master_reply', 'slave_reply', 'opinion_master_reply') + AND ( + JSON_UNQUOTE(JSON_EXTRACT(t.variable, '$.underTakeId')) = pru.unitId + OR ( + IFNULL(JSON_UNQUOTE(JSON_EXTRACT(t.variable, '$.underTakeId')), '') = '' + AND ta.actorUnitId = pru.unitId + ) + ) + ), + remain_units AS ( + SELECT + pru.proposalId, + pru.unitId, + pru.unitName, + pru.isMaster, + ROW_NUMBER() OVER(PARTITION BY pru.proposalId, pru.isMaster ORDER BY pru.unitName, pru.unitId) AS rn, + COUNT(*) OVER(PARTITION BY pru.proposalId, pru.isMaster) AS unitCount + FROM + proposal_reply_unit pru + WHERE + EXISTS ( + SELECT 1 + FROM wf_process_instance ins + INNER JOIN wf_process_task t ON t.processInstanceId = ins.id + WHERE ins.businessNo = pru.proposalId + AND t.taskState = @taskState + AND ( + (t.taskName IN ('master_reply', 'opinion_master_reply') AND pru.isMaster = 1) + OR (t.taskName = 'slave_reply' AND pru.isMaster = 0) + ) + ) + AND NOT EXISTS ( + SELECT 1 + FROM direct_targets dt + WHERE dt.proposalId = pru.proposalId + AND dt.unitId = pru.unitId + ) + ), + remain_tasks AS ( + SELECT + ins.businessNo AS proposalId, + t.id AS taskId, + IF(t.taskName IN ('master_reply', 'opinion_master_reply'), 1, 0) AS isMaster, + ROW_NUMBER() OVER( + PARTITION BY ins.businessNo, IF(t.taskName IN ('master_reply', 'opinion_master_reply'), 1, 0) + ORDER BY t.id + ) AS rn, + COUNT(*) OVER( + PARTITION BY ins.businessNo, IF(t.taskName IN ('master_reply', 'opinion_master_reply'), 1, 0) + ) AS taskCount + FROM + wf_process_task t + INNER JOIN wf_process_instance ins ON ins.id = t.processInstanceId + WHERE + t.taskState = @taskState + AND t.taskName IN ('master_reply', 'slave_reply', 'opinion_master_reply') + AND IFNULL(JSON_UNQUOTE(JSON_EXTRACT(t.variable, '$.underTakeId')), '') = '' + AND NOT EXISTS ( + SELECT 1 + FROM direct_targets dt + WHERE dt.taskId = t.id + ) + ) + SELECT + taskId, + unitId FROM - wf_process_task t - INNER JOIN wf_process_instance ins ON ins.id = t.processInstanceId - INNER JOIN proposal_reply_unit pru ON pru.proposalId = ins.businessNo - AND pru.unitId = @underTakeId - WHERE - t.taskState = @taskState - AND ( - (t.taskName IN ('master_reply', 'opinion_master_reply') AND pru.isMaster = 1) - OR (t.taskName = 'slave_reply' AND pru.isMaster = 0) - ) + direct_targets + UNION + SELECT + rt.taskId, + ru.unitId + FROM + remain_tasks rt + INNER JOIN remain_units ru ON ru.proposalId = rt.proposalId + AND ru.isMaster = rt.isMaster + AND ru.rn = rt.rn + AND ru.unitCount = rt.taskCount """); - sql.setParam("underTakeId", underTakeId); sql.setParam("taskState", ProcessTaskStateEnum.DOING.getCode()); - sql.setEntity(dao.getEntity(ProcessTask.class)); - dao.execute(sql); - return sql.getList(ProcessTask.class); + return baseService.listMap(sql); } /** diff --git a/src/main/java/com/budwk/app/zhgh/democratic/proposal/controller/transact/ProposalUnderTakeReplyController.java b/src/main/java/com/budwk/app/zhgh/democratic/proposal/controller/transact/ProposalUnderTakeReplyController.java index 9eadb5c6..97f6b8b1 100644 --- a/src/main/java/com/budwk/app/zhgh/democratic/proposal/controller/transact/ProposalUnderTakeReplyController.java +++ b/src/main/java/com/budwk/app/zhgh/democratic/proposal/controller/transact/ProposalUnderTakeReplyController.java @@ -132,6 +132,7 @@ public class ProposalUnderTakeReplyController { LEFT JOIN proposal_type type on type.id = info.typeId LEFT JOIN proposal_merge mer ON mer.proposalId = info.id LEFT JOIN proposal_reply_unit pru ON pru.proposalId = ins.businessNo + AND pru.unitId = IFNULL(t.variable->>'$.underTakeId', ta.actorUnitId) AND ( (t.taskName IN ('master_reply', 'opinion_master_reply') AND pru.isMaster = 1) OR (t.taskName = 'slave_reply' AND pru.isMaster = 0)