yxk-20260731
改善提案-删除流程功能 为已发起且仍在处理中的改善提案增加“删除流程”操作。删除后终止当前 Flowable 实例、清理本轮流程数据,并将提案回退为草稿,允许重新编辑和发起。 Implementation Changes 后端新增 POST /improvementproposal/improvementProposal/withdrawProcess?id=...,复用现有 improvementproposal:improvement_proposal:delete 权限。 在 ImprovementProposalService 新增事务方法:锁定主表后,仅允许 bpm_status='2' 且存在运行中流程实例的提案撤回;流程已完成、已作废、草稿或实例不存在时拒绝操作。 参考党委会的流程清理方式,终止 Flowable 运行实例并删除该实例的历史、审批意见、抄送、流程中间数据和流程日志;不改动全局流程引擎代码。 删除本轮 improvement_dept_score、improvement_institute_vote 数据,避免重新发起后复用旧评分、投票结果。 将流程衍生字段清空:流程实例、初审/评分/负责人奖项、评分汇总、所级投票人数与结果、最终奖项、人工确认、归档人及归档时间;保留提案基本信息、编号和业务附件。 将主表 bpm_status 重置为 1,使现有编辑、删除和发起流程逻辑自动恢复可用。 前端台账操作菜单在处理中记录显示“删除流程”,增加明确提示“删除后将回退为草稿,当前评分、投票和审批数据将被清空”;成功后刷新列表。 不增加批量删除流程功能,现有批量删除仍只处理草稿。
This commit is contained in:
+16
@@ -171,6 +171,22 @@ public class ImprovementProposalController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除运行中的流程并回退草稿。提案基本信息和业务附件会保留,流程产生的评分、投票数据会清空。
|
||||
*/
|
||||
@AutoLog(value = "改善提案-删除流程并回退草稿")
|
||||
@Operation(summary = "改善提案-删除流程并回退草稿")
|
||||
@RequiresPermissions("improvementproposal:improvement_proposal:delete")
|
||||
@PostMapping(value = "/withdrawProcess")
|
||||
public Result<String> withdrawProcess(@RequestParam(name = "id") String id) {
|
||||
try {
|
||||
improvementProposalService.withdrawProcess(id);
|
||||
return Result.OK("流程已删除,提案已回退为草稿");
|
||||
} catch (IllegalStateException e) {
|
||||
return Result.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping(value = "/bpm/initialReview")
|
||||
@Operation(summary = "保存部门精益专员初审结果")
|
||||
public Result<String> saveInitialReview(@RequestBody ImprovementProposalBpmActionDTO action) {
|
||||
|
||||
+7
@@ -31,6 +31,13 @@ public interface IImprovementProposalService extends IService<ImprovementProposa
|
||||
*/
|
||||
String startProcess(String id, String username);
|
||||
|
||||
/**
|
||||
* 删除当前运行中的改善提案流程,并将提案恢复为可编辑、可重新发起的草稿。
|
||||
*
|
||||
* @param id 提案主表 ID
|
||||
*/
|
||||
void withdrawProcess(String id);
|
||||
|
||||
/**
|
||||
* 添加一对多
|
||||
*
|
||||
|
||||
+106
@@ -15,7 +15,16 @@ import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.common.system.vo.LoginUser;
|
||||
import org.jeecg.modules.extbpm.process.service.impl.BpmBaseExtApiImpl;
|
||||
import org.jeecg.modules.extbpm.process.entity.ExtActBpmFile;
|
||||
import org.jeecg.modules.extbpm.process.entity.ExtActBpmLog;
|
||||
import org.jeecg.modules.extbpm.process.entity.ExtActFlowData;
|
||||
import org.jeecg.modules.extbpm.process.entity.ExtActTaskCc;
|
||||
import org.jeecg.modules.extbpm.process.service.IExtActBpmFileService;
|
||||
import org.jeecg.modules.extbpm.process.service.IExtActBpmLogService;
|
||||
import org.jeecg.modules.extbpm.process.service.IExtActFlowDataService;
|
||||
import org.jeecg.modules.extbpm.process.service.IExtActTaskCcService;
|
||||
import org.jeecg.modules.taskapprovalopinion.entity.TaskApprovalOpinion;
|
||||
import org.jeecg.modules.taskapprovalopinion.service.ITaskApprovalOpinionService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -39,6 +48,7 @@ import org.jeecg.modules.system.entity.SysDepart;
|
||||
import org.jeecg.modules.system.service.ISysRoleService;
|
||||
import org.jeecg.modules.system.service.ISysUserDepartService;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -93,6 +103,14 @@ public class ImprovementProposalServiceImpl extends ServiceImpl<ImprovementPropo
|
||||
private ISysUserDepartService sysUserDepartService;
|
||||
@Autowired
|
||||
private IExtActTaskCcService extActTaskCcService;
|
||||
@Autowired
|
||||
private ITaskApprovalOpinionService taskApprovalOpinionService;
|
||||
@Autowired
|
||||
private IExtActFlowDataService extActFlowDataService;
|
||||
@Autowired
|
||||
private IExtActBpmLogService extActBpmLogService;
|
||||
@Autowired
|
||||
private IExtActBpmFileService extActBpmFileService;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@@ -147,6 +165,77 @@ public class ImprovementProposalServiceImpl extends ServiceImpl<ImprovementPropo
|
||||
saveMain(improvementProposal, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void withdrawProcess(String id) {
|
||||
ImprovementProposal proposal = getProcessingProposalForUpdate(id);
|
||||
String processInstanceId = proposal.getProcessInstanceId();
|
||||
long runtimeCount = runtimeService.createProcessInstanceQuery()
|
||||
.processInstanceId(processInstanceId)
|
||||
.count();
|
||||
if (runtimeCount == 0) {
|
||||
throw new IllegalStateException("当前流程已结束或不存在,不能删除流程");
|
||||
}
|
||||
|
||||
// 改善提案未使用 task_task 中间表,按实例 ID 清理本轮流程数据,避免重新发起时读取到旧记录。
|
||||
runtimeService.deleteProcessInstance(processInstanceId, "改善提案删除流程并回退草稿");
|
||||
historyService.deleteHistoricProcessInstance(processInstanceId);
|
||||
clearProcessRelatedData(processInstanceId);
|
||||
improvementDeptScoreMapper.deleteByMainId(proposal.getId());
|
||||
improvementInstituteVoteMapper.deleteByMainId(proposal.getId());
|
||||
|
||||
// MyBatis-Plus 默认会忽略实体中的 null;使用 UpdateWrapper 才能把上一轮流程结果真正清空。
|
||||
LambdaUpdateWrapper<ImprovementProposal> resetWrapper = new LambdaUpdateWrapper<ImprovementProposal>()
|
||||
.eq(ImprovementProposal::getId, proposal.getId())
|
||||
.set(ImprovementProposal::getProcessInstanceId, null)
|
||||
.set(ImprovementProposal::getBpmStatus, BPM_STATUS_DRAFT)
|
||||
.set(ImprovementProposal::getInitialAward, null)
|
||||
.set(ImprovementProposal::getNeedDeptScore, null)
|
||||
.set(ImprovementProposal::getDeptAvgScore, null)
|
||||
.set(ImprovementProposal::getSuggestedAward, null)
|
||||
.set(ImprovementProposal::getLeaderFinalAward, null)
|
||||
.set(ImprovementProposal::getIsneedvote, null)
|
||||
.set(ImprovementProposal::getInstituteVoters, null)
|
||||
.set(ImprovementProposal::getInstituteTotalVoters, null)
|
||||
.set(ImprovementProposal::getInstituteAgreeCount, null)
|
||||
.set(ImprovementProposal::getInstituteDisagreeCount, null)
|
||||
.set(ImprovementProposal::getInstituteVoteResult, null)
|
||||
.set(ImprovementProposal::getFinalAward, null)
|
||||
.set(ImprovementProposal::getManualConfirmResult, null)
|
||||
.set(ImprovementProposal::getArchiveBy, null)
|
||||
.set(ImprovementProposal::getArchiveTime, null);
|
||||
if (improvementProposalMapper.update(null, resetWrapper) != 1) {
|
||||
throw new IllegalStateException("流程已删除,但提案回退草稿失败");
|
||||
}
|
||||
}
|
||||
|
||||
/** 清理仅属于本次流程实例的审批、抄送和日志数据,不影响提案申请附件。 */
|
||||
private void clearProcessRelatedData(String processInstanceId) {
|
||||
taskApprovalOpinionService.remove(new LambdaQueryWrapper<TaskApprovalOpinion>()
|
||||
.eq(TaskApprovalOpinion::getProcessInstId, processInstanceId));
|
||||
extActTaskCcService.remove(new LambdaQueryWrapper<ExtActTaskCc>()
|
||||
.eq(ExtActTaskCc::getProcInstId, processInstanceId));
|
||||
extActFlowDataService.remove(new LambdaQueryWrapper<ExtActFlowData>()
|
||||
.eq(ExtActFlowData::getProcessInstId, processInstanceId));
|
||||
|
||||
List<ExtActBpmLog> bpmLogs = extActBpmLogService.list(new LambdaQueryWrapper<ExtActBpmLog>()
|
||||
.eq(ExtActBpmLog::getProcInstId, processInstanceId));
|
||||
if (!bpmLogs.isEmpty()) {
|
||||
List<String> bpmLogIds = new ArrayList<>();
|
||||
for (ExtActBpmLog bpmLog : bpmLogs) {
|
||||
if (oConvertUtils.isNotEmpty(bpmLog.getId())) {
|
||||
bpmLogIds.add(bpmLog.getId());
|
||||
}
|
||||
}
|
||||
if (!bpmLogIds.isEmpty()) {
|
||||
extActBpmFileService.remove(new LambdaQueryWrapper<ExtActBpmFile>()
|
||||
.in(ExtActBpmFile::getBpmLogId, bpmLogIds));
|
||||
}
|
||||
extActBpmLogService.remove(new LambdaQueryWrapper<ExtActBpmLog>()
|
||||
.eq(ExtActBpmLog::getProcInstId, processInstanceId));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ImprovementProposalDepartmentDTO> getMyProposalDepartments(LoginUser loginUser) {
|
||||
if (loginUser == null || oConvertUtils.isEmpty(loginUser.getId())) {
|
||||
@@ -815,6 +904,23 @@ public class ImprovementProposalServiceImpl extends ServiceImpl<ImprovementPropo
|
||||
return proposal;
|
||||
}
|
||||
|
||||
/**
|
||||
* 撤回只能作用于正在运行的实例;通过主表行锁防止与流程办理、流程结束回写并发交叉。
|
||||
*/
|
||||
private ImprovementProposal getProcessingProposalForUpdate(String id) {
|
||||
if (oConvertUtils.isEmpty(id)) {
|
||||
throw new IllegalStateException("提案ID不能为空");
|
||||
}
|
||||
ImprovementProposal proposal = improvementProposalMapper.selectByIdForUpdate(id);
|
||||
if (proposal == null) {
|
||||
throw new IllegalStateException("未找到对应提案");
|
||||
}
|
||||
if (!"2".equals(proposal.getBpmStatus()) || oConvertUtils.isEmpty(proposal.getProcessInstanceId())) {
|
||||
throw new IllegalStateException("仅处理中的提案允许删除流程");
|
||||
}
|
||||
return proposal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getLatestProposalSequence(Integer year) {
|
||||
String proposalNo = improvementProposalMapper.selectLatestProposalNoByYear(year);
|
||||
|
||||
Reference in New Issue
Block a user