This commit is contained in:
2026-09-10 15:39:09 +08:00
parent c18579fe40
commit a67f80bec9
6 changed files with 132 additions and 22 deletions
@@ -201,6 +201,7 @@ public class ProposalUnderTakeReplyController {
@At
@SaCheckPermission("proposal.unitReply")
@ApiOperation("执行任务")
@Aop(TransAop.READ_COMMITTED)
public Result executeTask(@Param("data") String data) {
Dict args = Json.fromJson(Dict.class, data);
String proposalId = args.getStr("proposalId");
@@ -3,7 +3,6 @@ package com.budwk.app.zhgh.democratic.proposal.interceptor;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.budwk.app.base.constant.RoleConstant;
import com.budwk.app.flow.constant.FlowConst;
import com.budwk.app.flow.engine.FlowInterceptor;
import com.budwk.app.flow.engine.core.Execution;
@@ -11,19 +10,16 @@ import com.budwk.app.flow.engine.core.ServiceContext;
import com.budwk.app.flow.engine.util.FlowUtil;
import com.budwk.app.flow.entity.ProcessInstance;
import com.budwk.app.flow.entity.ProcessTask;
import com.budwk.app.flow.entity.ProcessTaskActor;
import com.budwk.app.sys.models.Sys_role;
import com.budwk.app.sys.services.SysRoleService;
import com.budwk.app.zhgh.democratic.proposal.models.ProposalInfo;
import com.budwk.app.zhgh.democratic.proposal.models.ProposalReplyUnit;
import com.budwk.app.zhgh.democratic.proposal.models.ProposalUndertake;
import com.budwk.app.zhgh.democratic.proposal.service.common.ProposalCommonService;
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.ioc.aop.Aop;
import org.nutz.json.Json;
import org.nutz.lang.util.NutMap;
import java.util.List;
@@ -36,6 +32,7 @@ public class ProposalCaseFilingInterceptor implements FlowInterceptor {
@Aop(TransAop.READ_COMMITTED)
public void intercept(Execution execution) {
Dao dao = ServiceContext.find(Dao.class);
ProposalCommonService proposalCommonService = ServiceContext.find(ProposalCommonService.class);
// 提案ID
String proposalId = execution.getProcessInstance().getBusinessNo();
@@ -87,10 +84,8 @@ public class ProposalCaseFilingInterceptor implements FlowInterceptor {
List<ProcessTask> processTaskList = execution.getProcessTaskList();
for (ProcessTask task : processTaskList) {
// 办理人
ProcessTaskActor taskActor = dao.fetch(ProcessTaskActor.class, Cnd.where(ProcessTaskActor::getProcessTaskId, "=", task.getId()));
String actorUnitId = taskActor.getActorUnitId();
ProposalReplyUnit replyUnit = dao.fetch(ProposalReplyUnit.class, Cnd.where(ProposalReplyUnit::getProposalId, "=", proposalId).and(ProposalReplyUnit::getUnitId, "=", actorUnitId));
// 办理人的角色承办单位匹配,系统所属单位可能与提案承办单位不同。
ProposalReplyUnit replyUnit = proposalCommonService.getReplyUnitByTaskActorRole(proposalId, task.getId(), task.getTaskName());
Dict variable = FlowUtil.variableToDict(task.getVariable());
variable.set("underTakeName", replyUnit.getUnitName());
@@ -6,10 +6,11 @@ import com.budwk.app.flow.engine.core.Execution;
import com.budwk.app.flow.engine.core.ServiceContext;
import com.budwk.app.flow.engine.util.FlowUtil;
import com.budwk.app.flow.entity.ProcessTask;
import com.budwk.app.flow.entity.ProcessTaskActor;
import com.budwk.app.zhgh.democratic.proposal.models.ProposalReplyUnit;
import org.nutz.dao.Cnd;
import com.budwk.app.zhgh.democratic.proposal.service.common.ProposalCommonService;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Dao;
import org.nutz.ioc.aop.Aop;
import org.nutz.json.Json;
import java.util.List;
@@ -20,26 +21,43 @@ import java.util.List;
*/
public class ProposalUnderTakeInfoInterceptor implements FlowInterceptor {
@Override
@Aop(TransAop.READ_COMMITTED)
public void intercept(Execution execution) {
Dao dao = ServiceContext.find(Dao.class);
ProposalCommonService proposalCommonService = ServiceContext.find(ProposalCommonService.class);
// 提案ID
String proposalId = execution.getProcessInstance().getBusinessNo();
// 当前任务
// 创建后续任务时 execution.processTask 会被替换,processTaskId 才始终指向本次办结的原任务
ProcessTask finishedTask = dao.fetch(ProcessTask.class, execution.getProcessTaskId());
if (finishedTask != null && "slave_reply".equals(finishedTask.getTaskName())) {
setReplyUnitVariable(proposalCommonService, proposalId, finishedTask);
dao.update(finishedTask, "variable");
}
// 为本次流转新生成的主办答复任务设置承办单位。
List<ProcessTask> processTaskList = execution.getProcessTaskList();
for (ProcessTask task : processTaskList) {
// 办理人
ProcessTaskActor taskActor = dao.fetch(ProcessTaskActor.class, Cnd.where(ProcessTaskActor::getProcessTaskId, "=", task.getId()));
String actorUnitId = taskActor.getActorUnitId();
ProposalReplyUnit replyUnit = dao.fetch(ProposalReplyUnit.class, Cnd.where(ProposalReplyUnit::getProposalId, "=", proposalId).and(ProposalReplyUnit::getUnitId, "=", actorUnitId));
Dict variable = FlowUtil.variableToDict(task.getVariable());
variable.set("underTakeName", replyUnit.getUnitName());
variable.set("underTakeId", replyUnit.getUnitId());
variable.set("underTakeIsMaster", replyUnit.getIsMaster());
task.setVariable(Json.toJson(variable));
setReplyUnitVariable(proposalCommonService, proposalId, task);
}
dao.update(processTaskList,"variable");
}
/**
* 按任务全部办理人的负责人角色承办单位,补充任务显示所需的承办单位信息。
*
* @param proposalCommonService 提案公共服务
* @param proposalId 当前流程对应的提案 ID
* @param task 当前办结或本次新生成的承办答复任务
*/
private void setReplyUnitVariable(ProposalCommonService proposalCommonService, String proposalId, ProcessTask task) {
ProposalReplyUnit replyUnit = proposalCommonService.getReplyUnitByTaskActorRole(
proposalId, task.getId(), task.getTaskName());
Dict variable = FlowUtil.variableToDict(task.getVariable());
variable.set("underTakeName", replyUnit.getUnitName());
variable.set("underTakeId", replyUnit.getUnitId());
variable.set("underTakeIsMaster", replyUnit.getIsMaster());
task.setVariable(Json.toJson(variable));
}
}
@@ -7,8 +7,10 @@ import com.budwk.app.flow.entity.ProcessInstance;
import com.budwk.app.flow.entity.ProcessTask;
import com.budwk.app.flow.enums.ProcessEventTypeEnum;
import com.budwk.app.zhgh.democratic.proposal.models.ProposalReplyUnit;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
@@ -22,10 +24,21 @@ public class ProposalCaseTaskRevokeEventListener implements ProcessEventListener
private Dao dao;
@Override
@Aop(TransAop.READ_COMMITTED)
public void onEvent(ProcessEvent event) {
if (event.getEventType() == ProcessEventTypeEnum.PROCESS_TASK_REVOKE) {
Long taskId = event.getSourceId();
ProcessTask task = dao.fetch(ProcessTask.class, taskId);
if (task == null || task.getTaskParentId() == null) {
return;
}
// 通用撤回事件传入的是被撤销的后续任务,只有其父任务为委员会立案时才清理承办单位。
ProcessTask parentTask = dao.fetch(ProcessTask.class, task.getTaskParentId());
if (parentTask == null || !"committeeFiling".equals(parentTask.getTaskName())) {
return;
}
ProcessInstance instance = dao.fetch(ProcessInstance.class, task.getProcessInstanceId());
String businessNo = instance.getBusinessNo();
dao.clear(ProposalReplyUnit.class, Cnd.where(ProposalReplyUnit::getProposalId, "=", businessNo));
@@ -2,6 +2,7 @@ package com.budwk.app.zhgh.democratic.proposal.service.common;
import com.budwk.app.base.service.BaseService;
import com.budwk.app.zhgh.democratic.proposal.models.ProposalInfo;
import com.budwk.app.zhgh.democratic.proposal.models.ProposalReplyUnit;
import com.budwk.app.zhgh.democratic.proposal.models.ProposalUndertake;
import org.nutz.lang.util.NutMap;
@@ -11,6 +12,16 @@ import java.util.List;
public interface ProposalCommonService extends BaseService<ProposalInfo> {
/**
* 根据任务办理人的“提案承办单位领导”角色匹配提案承办单位。
*
* @param proposalId 提案 ID,对应 proposal_reply_unit.proposalId
* @param taskId 流程任务 ID,用于获取该任务的全部办理人
* @param taskName 任务节点名称;master_reply、opinion_master_reply 匹配主办单位,slave_reply 匹配协办单位
* @return 当前任务对应的 ProposalReplyUnit,包含承办单位 ID、名称及主协办类型
*/
ProposalReplyUnit getReplyUnitByTaskActorRole(String proposalId, Long taskId, String taskName);
/**
* 查询提案信息
*/
@@ -15,6 +15,7 @@ import com.budwk.app.flow.engine.FlowEngine;
import com.budwk.app.flow.engine.util.FlowUtil;
import com.budwk.app.flow.entity.ProcessInstance;
import com.budwk.app.flow.entity.ProcessTask;
import com.budwk.app.flow.entity.ProcessTaskActor;
import com.budwk.app.flow.enums.ProcessTaskStateEnum;
import com.budwk.app.flow.vo.ProcessTaskVO;
import com.budwk.app.sys.models.Sys_dict;
@@ -28,6 +29,7 @@ import com.budwk.app.web.commons.base.Globals;
import com.budwk.app.zhgh.democratic.proposal.models.ProposalConsolidation;
import com.budwk.app.zhgh.democratic.proposal.models.ProposalInfo;
import com.budwk.app.zhgh.democratic.proposal.models.ProposalMerge;
import com.budwk.app.zhgh.democratic.proposal.models.ProposalReplyUnit;
import com.budwk.app.zhgh.democratic.proposal.models.ProposalUndertake;
import com.budwk.app.zhgh.democratic.teachercongress.prepare.models.Teacher_congress_session;
import com.deepoove.poi.XWPFTemplate;
@@ -74,6 +76,76 @@ public class ProposalCommonServiceImpl extends BaseServiceImpl<ProposalInfo> imp
super(dao);
}
/**
* 根据任务办理人的承办单位角色确定当前提案的主办或协办单位。
*
* @param proposalId 提案 ID,不能为空
* @param taskId 流程任务 ID,不能为空且任务必须存在办理人
* @param taskName master_reply、opinion_master_reply 或 slave_reply
* @return 唯一匹配的提案承办单位记录
*/
@Override
public ProposalReplyUnit getReplyUnitByTaskActorRole(String proposalId, Long taskId, String taskName) {
if (StrUtil.isBlank(proposalId) || taskId == null || StrUtil.isBlank(taskName)) {
throw new BaseException("提案承办单位匹配参数不完整");
}
boolean isMaster;
if (List.of("master_reply", "opinion_master_reply").contains(taskName)) {
isMaster = true;
} else if ("slave_reply".equals(taskName)) {
isMaster = false;
} else {
throw new BaseException("当前任务不是提案承办答复节点,任务ID:" + taskId);
}
List<ProcessTaskActor> taskActors = dao().query(ProcessTaskActor.class,
Cnd.where(ProcessTaskActor::getProcessTaskId, "=", taskId));
if (taskActors.isEmpty()) {
throw new BaseException("提案承办答复任务没有配置办理人,任务ID:" + taskId);
}
Sys_role leaderRole = sysRoleService.getByCode(RoleConstant.PROPOSAL_UNIT_LEADER.name());
if (leaderRole == null) {
throw new BaseException("系统未配置提案承办单位领导角色");
}
List<String> actorIds = taskActors.stream().map(ProcessTaskActor::getActorId).distinct().toList();
List<Sys_user_role> actorRoles = dao().query(Sys_user_role.class,
Cnd.where(Sys_user_role::getRoleId, "=", leaderRole.getId())
.and(Sys_user_role::getUserId, "in", actorIds));
Map<String, Set<String>> actorUnitIds = actorRoles.stream()
.filter(role -> StrUtil.isNotBlank(role.getUnderTakeId()))
.collect(Collectors.groupingBy(Sys_user_role::getUserId,
Collectors.mapping(Sys_user_role::getUnderTakeId, Collectors.toSet())));
// 同一流程任务的办理人应归属同一个角色承办单位,取全部办理人的共同承办单位避免误匹配。
Set<String> commonUnitIds = null;
for (String actorId : actorIds) {
Set<String> unitIds = actorUnitIds.getOrDefault(actorId, Collections.emptySet());
if (commonUnitIds == null) {
commonUnitIds = new HashSet<>(unitIds);
} else {
commonUnitIds.retainAll(unitIds);
}
}
if (commonUnitIds == null || commonUnitIds.isEmpty()) {
throw new BaseException("任务办理人的提案承办单位角色与当前任务不匹配,任务ID:" + taskId);
}
List<ProposalReplyUnit> replyUnits = dao().query(ProposalReplyUnit.class,
Cnd.where(ProposalReplyUnit::getProposalId, "=", proposalId)
.and(ProposalReplyUnit::getUnitId, "in", commonUnitIds)
.and(ProposalReplyUnit::getIsMaster, "=", isMaster));
if (replyUnits.isEmpty()) {
throw new BaseException("任务办理人的角色承办单位未包含在当前提案承办单位中,任务ID:" + taskId);
}
if (replyUnits.size() > 1) {
throw new BaseException("任务办理人匹配到多个提案承办单位,请检查角色配置,任务ID:" + taskId);
}
return replyUnits.get(0);
}
@Override
public NutMap info(String id) {
if (StrUtil.isBlank(id)) {