yxk-20260729
改善提案 在 Task_improve004 增加所级评议人员选择。经办人选择 improve_suoleader 角色中的一人或多人后,通过通用“提交/办理”保存名单、初始化待投票记录,并写入流程变量 suoleadervotelist,供 Task_improve005 多实例任务使用。
This commit is contained in:
+22
@@ -28,6 +28,7 @@ import org.jeecg.modules.improvementproposal.entity.ImprovementDeptScore;
|
||||
import org.jeecg.modules.improvementproposal.entity.ImprovementInstituteVote;
|
||||
import org.jeecg.modules.improvementproposal.entity.ImprovementProposal;
|
||||
import org.jeecg.modules.improvementproposal.dto.ImprovementDeptScoreBpmDTO;
|
||||
import org.jeecg.modules.improvementproposal.dto.ImprovementInstituteVoteCandidateDTO;
|
||||
import org.jeecg.modules.improvementproposal.dto.ImprovementProposalBpmActionDTO;
|
||||
import org.jeecg.modules.improvementproposal.vo.ImprovementProposalPage;
|
||||
import org.jeecg.modules.improvementproposal.service.IImprovementProposalService;
|
||||
@@ -191,6 +192,27 @@ public class ImprovementProposalController {
|
||||
return handleBpmAction(() -> improvementProposalService.saveLeaderAward(action, currentUser()));
|
||||
}
|
||||
|
||||
@GetMapping(value = "/bpm/instituteVoteCandidates")
|
||||
@Operation(summary = "查询所级评议投票候选人")
|
||||
public Result<List<ImprovementInstituteVoteCandidateDTO>> getInstituteVoteCandidates(@RequestParam String mainId,
|
||||
@RequestParam String processInstanceId, @RequestParam String taskId) {
|
||||
ImprovementProposalBpmActionDTO action = new ImprovementProposalBpmActionDTO();
|
||||
action.setMainId(mainId);
|
||||
action.setProcessInstanceId(processInstanceId);
|
||||
action.setTaskId(taskId);
|
||||
try {
|
||||
return Result.OK(improvementProposalService.getInstituteVoteCandidates(action, currentUser()));
|
||||
} catch (IllegalStateException e) {
|
||||
return Result.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping(value = "/bpm/instituteVoteMembers")
|
||||
@Operation(summary = "保存所级评议投票人员")
|
||||
public Result<String> saveInstituteVoteMembers(@RequestBody ImprovementProposalBpmActionDTO action) {
|
||||
return handleBpmAction(() -> improvementProposalService.saveInstituteVoteMembers(action, currentUser()));
|
||||
}
|
||||
|
||||
@PostMapping(value = "/bpm/archiveAward")
|
||||
@Operation(summary = "保存归档最终奖项")
|
||||
public Result<String> saveArchiveAward(@RequestBody ImprovementProposalBpmActionDTO action) {
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
package org.jeecg.modules.improvementproposal.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 所级评议投票候选人。
|
||||
* 仅暴露名单选择和 Flowable 多实例所需的最小用户信息。
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "所级评议投票候选人")
|
||||
public class ImprovementInstituteVoteCandidateDTO implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "用户ID")
|
||||
private String id;
|
||||
|
||||
@Schema(description = "登录用户名")
|
||||
private String username;
|
||||
|
||||
@Schema(description = "真实姓名")
|
||||
private String realname;
|
||||
}
|
||||
+8
@@ -1,6 +1,7 @@
|
||||
package org.jeecg.modules.improvementproposal.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
@@ -35,4 +36,11 @@ public class ImprovementProposalBpmActionDTO implements Serializable {
|
||||
|
||||
@Schema(description = "投票结果:agree/disagree")
|
||||
private String voteResult;
|
||||
|
||||
/**
|
||||
* 精益管理部门经办人在所级评议节点选择的投票人 ID 列表。
|
||||
* 服务端会按固定角色重新校验该列表,不能将其作为投票人身份的信任来源。
|
||||
*/
|
||||
@Schema(description = "所级评议投票人ID列表")
|
||||
private List<String> voterIds;
|
||||
}
|
||||
|
||||
+3
@@ -28,4 +28,7 @@ public interface ImprovementInstituteVoteMapper extends BaseMapper<ImprovementIn
|
||||
* @return List<ImprovementInstituteVote>
|
||||
*/
|
||||
public List<ImprovementInstituteVote> selectByMainId(@Param("mainId") String mainId);
|
||||
|
||||
/** 任务尚未进入投票节点时,仅失效本轮待投票记录,保留已投票历史。 */
|
||||
int logicalDeletePendingByMainId(@Param("mainId") String mainId);
|
||||
}
|
||||
|
||||
+5
@@ -2,8 +2,10 @@ package org.jeecg.modules.improvementproposal.mapper;
|
||||
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.jeecg.modules.improvementproposal.dto.ImprovementInstituteVoteCandidateDTO;
|
||||
import org.jeecg.modules.improvementproposal.entity.ImprovementProposal;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Description: improvement_proposal
|
||||
@@ -20,4 +22,7 @@ public interface ImprovementProposalMapper extends BaseMapper<ImprovementProposa
|
||||
@Select("SELECT * FROM improvement_proposal WHERE id = #{id} AND del_flag = '0' FOR UPDATE")
|
||||
ImprovementProposal selectByIdForUpdate(@Param("id") String id);
|
||||
|
||||
/** 查询指定角色下可供所级评议选择的有效用户。 */
|
||||
List<ImprovementInstituteVoteCandidateDTO> selectInstituteVoteCandidates(@Param("roleCode") String roleCode);
|
||||
|
||||
}
|
||||
|
||||
+12
-1
@@ -12,5 +12,16 @@
|
||||
SELECT *
|
||||
FROM improvement_institute_vote
|
||||
WHERE
|
||||
main_id = #{mainId} </select>
|
||||
main_id = #{mainId}
|
||||
AND del_flag = '0'
|
||||
</select>
|
||||
|
||||
<!-- Task_improve004 重试保存名单时,只替换尚未投票的有效记录。 -->
|
||||
<update id="logicalDeletePendingByMainId" parameterType="java.lang.String">
|
||||
UPDATE improvement_institute_vote
|
||||
SET del_flag = '1'
|
||||
WHERE main_id = #{mainId}
|
||||
AND del_flag = '0'
|
||||
AND vote_status = 'pending'
|
||||
</update>
|
||||
</mapper>
|
||||
|
||||
+13
@@ -10,4 +10,17 @@
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
<!-- 角色名单由服务端查询,前端只能从该受控集合中选择。 -->
|
||||
<select id="selectInstituteVoteCandidates" resultType="org.jeecg.modules.improvementproposal.dto.ImprovementInstituteVoteCandidateDTO">
|
||||
SELECT DISTINCT u.id, u.username, u.realname
|
||||
FROM sys_role r
|
||||
INNER JOIN sys_user_role ur ON ur.role_id = r.id
|
||||
INNER JOIN sys_user u ON u.id = ur.user_id
|
||||
WHERE r.role_code = #{roleCode}
|
||||
AND u.del_flag = 0
|
||||
AND u.username IS NOT NULL
|
||||
AND u.username != ''
|
||||
ORDER BY u.realname, u.username
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
|
||||
+7
@@ -4,6 +4,7 @@ import org.jeecg.modules.improvementproposal.entity.ImprovementDeptScore;
|
||||
import org.jeecg.modules.improvementproposal.entity.ImprovementInstituteVote;
|
||||
import org.jeecg.modules.improvementproposal.entity.ImprovementProposal;
|
||||
import org.jeecg.modules.improvementproposal.dto.ImprovementDeptScoreBpmDTO;
|
||||
import org.jeecg.modules.improvementproposal.dto.ImprovementInstituteVoteCandidateDTO;
|
||||
import org.jeecg.modules.improvementproposal.dto.ImprovementProposalBpmActionDTO;
|
||||
import org.jeecg.common.system.vo.LoginUser;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
@@ -75,6 +76,12 @@ public interface IImprovementProposalService extends IService<ImprovementProposa
|
||||
/** 保存部门负责人确认奖项,并写入所级投票网关变量。 */
|
||||
void saveLeaderAward(ImprovementProposalBpmActionDTO action, LoginUser loginUser);
|
||||
|
||||
/** 查询所级评议节点可选择的角色成员。 */
|
||||
List<ImprovementInstituteVoteCandidateDTO> getInstituteVoteCandidates(ImprovementProposalBpmActionDTO action, LoginUser loginUser);
|
||||
|
||||
/** 保存所级评议名单、待投票记录及多实例流程变量。 */
|
||||
void saveInstituteVoteMembers(ImprovementProposalBpmActionDTO action, LoginUser loginUser);
|
||||
|
||||
/** 保存经办人归档确认的最终奖项。 */
|
||||
void saveArchiveAward(ImprovementProposalBpmActionDTO action, LoginUser loginUser);
|
||||
|
||||
|
||||
+93
@@ -4,6 +4,7 @@ import org.jeecg.modules.improvementproposal.entity.ImprovementProposal;
|
||||
import org.jeecg.modules.improvementproposal.entity.ImprovementDeptScore;
|
||||
import org.jeecg.modules.improvementproposal.entity.ImprovementInstituteVote;
|
||||
import org.jeecg.modules.improvementproposal.dto.ImprovementDeptScoreBpmDTO;
|
||||
import org.jeecg.modules.improvementproposal.dto.ImprovementInstituteVoteCandidateDTO;
|
||||
import org.jeecg.modules.improvementproposal.dto.ImprovementProposalBpmActionDTO;
|
||||
import org.jeecg.modules.improvementproposal.mapper.ImprovementDeptScoreMapper;
|
||||
import org.jeecg.modules.improvementproposal.mapper.ImprovementInstituteVoteMapper;
|
||||
@@ -29,9 +30,13 @@ import org.flowable.engine.RuntimeService;
|
||||
import org.flowable.engine.HistoryService;
|
||||
import org.flowable.engine.TaskService;
|
||||
import org.flowable.task.api.Task;
|
||||
import org.jeecg.modules.system.entity.SysRole;
|
||||
import org.jeecg.modules.system.service.ISysRoleService;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
|
||||
/**
|
||||
* @Description: improvement_proposal
|
||||
@@ -49,8 +54,10 @@ public class ImprovementProposalServiceImpl extends ServiceImpl<ImprovementPropo
|
||||
private static final String TASK_INITIAL_REVIEW = "Task_improve001";
|
||||
private static final String TASK_DEPT_SCORE = "Task_improve002";
|
||||
private static final String TASK_LEADER_AWARD = "Task_improve003";
|
||||
private static final String TASK_INSTITUTE_REVIEW = "Task_improve004";
|
||||
private static final String TASK_INSTITUTE_VOTE = "Task_improve005";
|
||||
private static final String TASK_ARCHIVE = "Task_improve006";
|
||||
private static final String INSTITUTE_VOTE_ROLE_CODE = "improve_suoleader";
|
||||
private static final String AWARD_GOLD = "0";
|
||||
private static final String AWARD_SILVER = "1";
|
||||
private static final String AWARD_BRONZE = "2";
|
||||
@@ -70,6 +77,8 @@ public class ImprovementProposalServiceImpl extends ServiceImpl<ImprovementPropo
|
||||
private HistoryService historyService;
|
||||
@Autowired
|
||||
private TaskService taskService;
|
||||
@Autowired
|
||||
private ISysRoleService sysRoleService;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@@ -313,6 +322,75 @@ public class ImprovementProposalServiceImpl extends ServiceImpl<ImprovementPropo
|
||||
runtimeService.setVariable(action.getProcessInstanceId(), "isneedvote", needInstituteVote);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ImprovementInstituteVoteCandidateDTO> getInstituteVoteCandidates(ImprovementProposalBpmActionDTO action, LoginUser loginUser) {
|
||||
validateRunningTask(action, loginUser, TASK_INSTITUTE_REVIEW);
|
||||
return loadInstituteVoteCandidates();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void saveInstituteVoteMembers(ImprovementProposalBpmActionDTO action, LoginUser loginUser) {
|
||||
ImprovementProposal proposal = validateRunningTask(action, loginUser, TASK_INSTITUTE_REVIEW);
|
||||
ImprovementProposal lockedProposal = improvementProposalMapper.selectByIdForUpdate(proposal.getId());
|
||||
if (lockedProposal == null || !action.getProcessInstanceId().equals(lockedProposal.getProcessInstanceId())) {
|
||||
throw new IllegalStateException("提案流程状态已变化,请刷新后重试");
|
||||
}
|
||||
|
||||
List<ImprovementInstituteVoteCandidateDTO> candidates = loadInstituteVoteCandidates();
|
||||
Map<String, ImprovementInstituteVoteCandidateDTO> candidateById = new LinkedHashMap<>();
|
||||
for (ImprovementInstituteVoteCandidateDTO candidate : candidates) {
|
||||
candidateById.put(candidate.getId(), candidate);
|
||||
}
|
||||
if (action.getVoterIds() == null || action.getVoterIds().isEmpty()) {
|
||||
throw new IllegalStateException("请至少选择一名所级评议人员");
|
||||
}
|
||||
|
||||
LinkedHashSet<String> selectedUserIds = new LinkedHashSet<>();
|
||||
for (String voterId : action.getVoterIds()) {
|
||||
if (oConvertUtils.isEmpty(voterId) || !selectedUserIds.add(voterId)) {
|
||||
throw new IllegalStateException("所级评议人员选择数据不合法");
|
||||
}
|
||||
}
|
||||
LinkedHashSet<String> usernames = new LinkedHashSet<>();
|
||||
for (String voterId : selectedUserIds) {
|
||||
ImprovementInstituteVoteCandidateDTO candidate = candidateById.get(voterId);
|
||||
if (candidate == null) {
|
||||
throw new IllegalStateException("所选人员不属于所级评议小组");
|
||||
}
|
||||
if (!usernames.add(candidate.getUsername())) {
|
||||
throw new IllegalStateException("所级评议人员用户名重复");
|
||||
}
|
||||
}
|
||||
|
||||
List<ImprovementInstituteVote> activeVotes = improvementInstituteVoteMapper.selectByMainId(lockedProposal.getId());
|
||||
if (activeVotes.stream().anyMatch(item -> !"pending".equals(item.getVoteStatus()))) {
|
||||
throw new IllegalStateException("所级评议已开始投票,不能重新选择人员");
|
||||
}
|
||||
// beforeHandle 可能因网络重试重复调用;先失效未投票记录再重建,确保有效名单始终和流程变量一致。
|
||||
improvementInstituteVoteMapper.logicalDeletePendingByMainId(lockedProposal.getId());
|
||||
for (String voterId : selectedUserIds) {
|
||||
ImprovementInstituteVoteCandidateDTO candidate = candidateById.get(voterId);
|
||||
ImprovementInstituteVote vote = new ImprovementInstituteVote();
|
||||
vote.setMainId(lockedProposal.getId());
|
||||
vote.setVoterId(candidate.getId());
|
||||
vote.setVoterName(oConvertUtils.isEmpty(candidate.getRealname()) ? candidate.getUsername() : candidate.getRealname());
|
||||
vote.setVoteStatus("pending");
|
||||
vote.setSysOrgCode(lockedProposal.getSysOrgCode());
|
||||
vote.setDelFlag(NORMAL_DEL_FLAG);
|
||||
improvementInstituteVoteMapper.insert(vote);
|
||||
}
|
||||
|
||||
ImprovementProposal update = new ImprovementProposal();
|
||||
update.setId(lockedProposal.getId());
|
||||
update.setInstituteTotalVoters(selectedUserIds.size());
|
||||
update.setInstituteAgreeCount(null);
|
||||
update.setInstituteDisagreeCount(null);
|
||||
update.setInstituteVoteResult(null);
|
||||
improvementProposalMapper.updateById(update);
|
||||
runtimeService.setVariable(action.getProcessInstanceId(), "suoleadervotelist", String.join(",", usernames));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void saveArchiveAward(ImprovementProposalBpmActionDTO action, LoginUser loginUser) {
|
||||
@@ -355,6 +433,21 @@ public class ImprovementProposalServiceImpl extends ServiceImpl<ImprovementPropo
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 固定按角色编码读取名单,保存时再次查询以防前端伪造用户 ID 或角色配置已变更。
|
||||
*/
|
||||
private List<ImprovementInstituteVoteCandidateDTO> loadInstituteVoteCandidates() {
|
||||
SysRole role = sysRoleService.getRoleNoTenant(INSTITUTE_VOTE_ROLE_CODE);
|
||||
if (role == null) {
|
||||
throw new IllegalStateException("未配置所级评议小组角色:" + INSTITUTE_VOTE_ROLE_CODE);
|
||||
}
|
||||
List<ImprovementInstituteVoteCandidateDTO> candidates = improvementProposalMapper.selectInstituteVoteCandidates(INSTITUTE_VOTE_ROLE_CODE);
|
||||
if (candidates == null || candidates.isEmpty()) {
|
||||
throw new IllegalStateException("所级评议小组角色未配置有效用户");
|
||||
}
|
||||
return candidates;
|
||||
}
|
||||
|
||||
private ImprovementProposalBpmActionDTO toBpmAction(ImprovementDeptScoreBpmDTO scoreAction) {
|
||||
ImprovementProposalBpmActionDTO action = new ImprovementProposalBpmActionDTO();
|
||||
action.setMainId(scoreAction.getMainId());
|
||||
|
||||
Reference in New Issue
Block a user