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")
|
@PostMapping(value = "/bpm/initialReview")
|
||||||
@Operation(summary = "保存部门精益专员初审结果")
|
@Operation(summary = "保存部门精益专员初审结果")
|
||||||
public Result<String> saveInitialReview(@RequestBody ImprovementProposalBpmActionDTO action) {
|
public Result<String> saveInitialReview(@RequestBody ImprovementProposalBpmActionDTO action) {
|
||||||
|
|||||||
+7
@@ -31,6 +31,13 @@ public interface IImprovementProposalService extends IService<ImprovementProposa
|
|||||||
*/
|
*/
|
||||||
String startProcess(String id, String username);
|
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.util.oConvertUtils;
|
||||||
import org.jeecg.common.system.vo.LoginUser;
|
import org.jeecg.common.system.vo.LoginUser;
|
||||||
import org.jeecg.modules.extbpm.process.service.impl.BpmBaseExtApiImpl;
|
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.extbpm.process.service.IExtActTaskCcService;
|
||||||
|
import org.jeecg.modules.taskapprovalopinion.entity.TaskApprovalOpinion;
|
||||||
|
import org.jeecg.modules.taskapprovalopinion.service.ITaskApprovalOpinionService;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
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.ISysRoleService;
|
||||||
import org.jeecg.modules.system.service.ISysUserDepartService;
|
import org.jeecg.modules.system.service.ISysUserDepartService;
|
||||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
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.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
@@ -93,6 +103,14 @@ public class ImprovementProposalServiceImpl extends ServiceImpl<ImprovementPropo
|
|||||||
private ISysUserDepartService sysUserDepartService;
|
private ISysUserDepartService sysUserDepartService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private IExtActTaskCcService extActTaskCcService;
|
private IExtActTaskCcService extActTaskCcService;
|
||||||
|
@Autowired
|
||||||
|
private ITaskApprovalOpinionService taskApprovalOpinionService;
|
||||||
|
@Autowired
|
||||||
|
private IExtActFlowDataService extActFlowDataService;
|
||||||
|
@Autowired
|
||||||
|
private IExtActBpmLogService extActBpmLogService;
|
||||||
|
@Autowired
|
||||||
|
private IExtActBpmFileService extActBpmFileService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
@@ -147,6 +165,77 @@ public class ImprovementProposalServiceImpl extends ServiceImpl<ImprovementPropo
|
|||||||
saveMain(improvementProposal, null, null);
|
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
|
@Override
|
||||||
public List<ImprovementProposalDepartmentDTO> getMyProposalDepartments(LoginUser loginUser) {
|
public List<ImprovementProposalDepartmentDTO> getMyProposalDepartments(LoginUser loginUser) {
|
||||||
if (loginUser == null || oConvertUtils.isEmpty(loginUser.getId())) {
|
if (loginUser == null || oConvertUtils.isEmpty(loginUser.getId())) {
|
||||||
@@ -814,6 +903,23 @@ public class ImprovementProposalServiceImpl extends ServiceImpl<ImprovementPropo
|
|||||||
}
|
}
|
||||||
return proposal;
|
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
|
@Override
|
||||||
public Integer getLatestProposalSequence(Integer year) {
|
public Integer getLatestProposalSequence(Integer year) {
|
||||||
|
|||||||
Reference in New Issue
Block a user