diff --git a/src/main/java/cn/palmte/work/config/activiti/ActConstant.java b/src/main/java/cn/palmte/work/config/activiti/ActConstant.java index f030f9a..9d66f62 100644 --- a/src/main/java/cn/palmte/work/config/activiti/ActConstant.java +++ b/src/main/java/cn/palmte/work/config/activiti/ActConstant.java @@ -11,6 +11,23 @@ public class ActConstant { public static final String PROC_INS_ID="procInsId"; public static final String PROC_DEF_KEY="procDefKey"; + + /** + * 结束节点 + */ + public static final int TASK_INDEX_END= -1; + + + /** + * 0-未知或者其他节点 + */ + public static final int TASK_INDEX_OTHER= 0; + + /** + * 开始节点 + */ + public static final int TASK_INDEX_START= 1; + /** * 发起审批节点 */ diff --git a/src/main/java/cn/palmte/work/controller/backend/ProjectController.java b/src/main/java/cn/palmte/work/controller/backend/ProjectController.java index c5ad73d..766e630 100644 --- a/src/main/java/cn/palmte/work/controller/backend/ProjectController.java +++ b/src/main/java/cn/palmte/work/controller/backend/ProjectController.java @@ -763,6 +763,24 @@ public class ProjectController extends BaseController { return projectService.batchUpdateApprove(json); } + /** + * 退回到指定节点 + * 1、完结的项目允许重启并指定回退节点 + * 2、跨流程(概算、预算等)退回 + * 3、不跨流程退回(例如:仅在预算的审批流中退回某个节点) + */ + @ResponseBody + @RequestMapping("/rollbackToRecord") + public ResponseMsg rollbackToRecord(@RequestBody String json) { + try { + projectService.rollbackToRecord(json); + return ResponseMsg.buildSuccessMsg("回退成功"); + } catch (Exception e) { + logger.error("", e); + return ResponseMsg.buildSuccessMsg("回退失败:" + e.getMessage()); + } + } + /** * 查看审核流程 */ diff --git a/src/main/java/cn/palmte/work/model/ProjectRepository.java b/src/main/java/cn/palmte/work/model/ProjectRepository.java index d880ed8..7d359e2 100644 --- a/src/main/java/cn/palmte/work/model/ProjectRepository.java +++ b/src/main/java/cn/palmte/work/model/ProjectRepository.java @@ -31,6 +31,9 @@ public interface ProjectRepository extends JpaRepository { Project findById(int id); + @Query(value = "select * from project where approve_id = ?", nativeQuery = true) + List findByApproveId(int adminId); + @Modifying @Transactional(rollbackOn = Exception.class) @Query(value = "update project set approve_id=?, approve_name=? where approve_id = ?", nativeQuery = true) diff --git a/src/main/java/cn/palmte/work/model/ProjectTaskRecord.java b/src/main/java/cn/palmte/work/model/ProjectTaskRecord.java index f53dbbe..f78a18e 100644 --- a/src/main/java/cn/palmte/work/model/ProjectTaskRecord.java +++ b/src/main/java/cn/palmte/work/model/ProjectTaskRecord.java @@ -1,10 +1,11 @@ package cn.palmte.work.model; +import cn.palmte.work.bean.StatusEnum; +import cn.palmte.work.config.activiti.ActConstant; import lombok.Data; import javax.persistence.*; import java.util.Date; -import java.util.List; /** * 项目审批任务记录 @@ -14,6 +15,9 @@ import java.util.List; @Table(name = "project_task_record") public class ProjectTaskRecord { + public static final int STATUS_ROLLBACK = 4;//管理员退回 + public static final int STATUS_RE_ASSIGNEE = 5; //指定承接人 + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; @@ -35,6 +39,8 @@ public class ProjectTaskRecord { /** * @see cn.palmte.work.bean.ApproveStatusEnum#approveStatus + * + * 状态 1-提交审批 2-审批通过 3-审批不通过 4-管理员退回 5-指定承接人 */ @Column(name = "task_status") private int taskStatus; @@ -75,4 +81,73 @@ public class ProjectTaskRecord { @Column(name = "file_url") private String fileUrl; + + /** + * 退回 project_task_record表id + */ + @Column(name = "rollback_record_id") + private int rollbackRecordId; + + /** + * 退回到哪里 保存快照信息 + */ + @Column(name = "rollback_desc") + private String rollbackDesc; + + + /** + * 是否运行管理员退回 + */ + @Transient + private boolean canRollback = false; + + @Transient + private String procDefName = ""; + + @Transient + private String procDefKey= ""; + + public StatusEnum getStatusByProDefId() { + if (procDefId.startsWith(ActConstant.PROCESS_DEFKEY_BUDGET)) { + return StatusEnum.BUDGET_ACCOUNTS; + }if (procDefId.startsWith(ActConstant.PROCESS_DEFKEY_SETTLE)) { + return StatusEnum.SETTLE_ACCOUNTS; + }if (procDefId.startsWith(ActConstant.PROCESS_DEFKEY_FINAL)) { + return StatusEnum.FINAL_ACCOUNTS; + }else{ + return StatusEnum.ESTIMATE_ACCOUNTS; + } + } + + public String getProcDefName() { + if (procDefId.startsWith(ActConstant.PROCESS_DEFKEY_BUDGET)) { + return "预算审批流程"; + }if (procDefId.startsWith(ActConstant.PROCESS_DEFKEY_SETTLE)) { + return "结算审批流程"; + }if (procDefId.startsWith(ActConstant.PROCESS_DEFKEY_FINAL)) { + return "决算审批流程"; + }else{ + return "概算审批流程"; + } + } + + public void setProcDefName(String procDefName) { + this.procDefName = procDefName; + } + + public String getProcDefKey() { + if (procDefId.startsWith(ActConstant.PROCESS_DEFKEY_BUDGET)) { + return ActConstant.PROCESS_DEFKEY_BUDGET; + }if (procDefId.startsWith(ActConstant.PROCESS_DEFKEY_SETTLE)) { + return ActConstant.PROCESS_DEFKEY_SETTLE; + }if (procDefId.startsWith(ActConstant.PROCESS_DEFKEY_FINAL)) { + return ActConstant.PROCESS_DEFKEY_FINAL; + }else{ + return ActConstant.PROCESS_DEFKEY_ESTIMATE; + } + } + + public void setProcDefKey(String procDefKey) { + this.procDefKey = procDefKey; + } } diff --git a/src/main/java/cn/palmte/work/service/ActProcInsService.java b/src/main/java/cn/palmte/work/service/ActProcInsService.java index 35f3250..b686c8d 100644 --- a/src/main/java/cn/palmte/work/service/ActProcInsService.java +++ b/src/main/java/cn/palmte/work/service/ActProcInsService.java @@ -4,12 +4,12 @@ package cn.palmte.work.service; import cn.palmte.work.bean.ApproveStatusEnum; import cn.palmte.work.config.activiti.ActConstant; import cn.palmte.work.model.ActTaskDefRepository; +import cn.palmte.work.model.ProjectTaskRecord; import cn.palmte.work.pojo.ActProcIns; import cn.palmte.work.utils.ActUtil; import cn.palmte.work.utils.InterfaceUtil; import org.activiti.bpmn.model.BpmnModel; import org.activiti.bpmn.model.FlowNode; -import org.activiti.bpmn.model.Process; import org.activiti.bpmn.model.SequenceFlow; import org.activiti.engine.HistoryService; import org.activiti.engine.RepositoryService; @@ -68,7 +68,7 @@ public class ActProcInsService { /** - * 启动流程实列 + * 正常启动流程实列 * * @param procDefKey * @param variables @@ -105,7 +105,49 @@ public class ActProcInsService { taskService.complete(taskId); projectTaskRecordService.saveTaskRecord(Integer.parseInt(instance.getBusinessKey()), - task, ApproveStatusEnum.APPROVAL_PENDING.getApproveStatus(), ActConstant.TASK_INDEX_FIRST_USER_TASK, comment, ""); + task, ApproveStatusEnum.APPROVAL_PENDING.getApproveStatus(), ActConstant.TASK_INDEX_FIRST_USER_TASK, comment); + + return instance.getId(); + } + + + /** + * 系统启动流程实列 + * + * @param procDefKey + * @param businessKey + * @param variables + * @return + * @throws Exception + */ + public String startProcessInstanceBySystem(String procDefKey, String businessKey, Map variables, + ProjectTaskRecord taskRecord) throws Exception { + List list = repositoryService.createProcessDefinitionQuery().processDefinitionKey(procDefKey).active().orderByProcessDefinitionVersion().desc().list(); + if (list == null || list.isEmpty()) { + throw new Exception("procDefKey(" + procDefKey + ")未定义"); + } + + //取最新版本的流程定义进行启动流程实列 + ProcessDefinition processDefinition = list.get(0); + + String adminId = "-1"; + variables.put(ActConstant.START_PROCESS_USERID, adminId); + //启动流程 + ProcessInstance instance = runtimeService.startProcessInstanceById(processDefinition.getId(), businessKey, variables); + logger.info("startProcessInstanceSuccess procInsId:{}, procDefKey:{}, procDefName:{}", instance.getId(), instance.getProcessDefinitionKey(), instance.getProcessDefinitionName()); + + String procInsId = instance.getProcessInstanceId(); + Task task = taskService.createTaskQuery().processInstanceId(procInsId).singleResult(); + if (task == null) { + throw new Exception("procDefKey(" + procDefKey + ")启动异常"); + } + + String taskId = task.getId(); + String comment = "系统提交" + processDefinition.getName(); + Authentication.setAuthenticatedUserId(adminId); + taskService.addComment(taskId, procInsId, comment); + + taskService.setAssignee(taskId, taskRecord.getAssigneeId() + ""); return instance.getId(); } diff --git a/src/main/java/cn/palmte/work/service/ActTaskDefService.java b/src/main/java/cn/palmte/work/service/ActTaskDefService.java index d673f66..6718edd 100644 --- a/src/main/java/cn/palmte/work/service/ActTaskDefService.java +++ b/src/main/java/cn/palmte/work/service/ActTaskDefService.java @@ -78,7 +78,7 @@ public class ActTaskDefService { //保存审批记录 - projectTaskRecordService.saveTaskRecord(Integer.parseInt(processInstance.getBusinessKey()), + projectTaskRecordService.saveTaskRecordWithFileUrl(Integer.parseInt(processInstance.getBusinessKey()), currentTask, type, actTaskDef.getTaskIndex(), message, fileUrl); } @@ -125,12 +125,36 @@ public class ActTaskDefService { } + public void skipTaskByProcInsIdAndTaskName(String procInsId, String skipToTaskName) { + logger.info("skipTaskByProcInsIdAndTaskName procInsId:{}, skipToTaskName:{}", procInsId, skipToTaskName); + ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(procInsId).singleResult(); + + //非指定节点自动跳过 + Task task = taskService.createTaskQuery().processInstanceId(procInsId).singleResult(); + logger.info("skipTaskByProcInsIdAndTaskName currentTaskName:{}, skipToTaskName:{}", task.getName(), skipToTaskName); + while (!skipToTaskName.equals(task.getName())) { + logger.info("skipTaskByProcInsIdAndTaskName completeSkipTask:{}", task.getName()); + + completeSkipTask(task, processInstance, "任务由系统自动审批通过", + ApproveStatusEnum.APPROVAL_PASSED.getApproveStatus()); + + task = taskService.createTaskQuery().processInstanceId(procInsId).singleResult(); + logger.info("skipTaskByProcInsIdAndTaskName currentTaskName:{}, skipToTaskName:{}", task.getName(), skipToTaskName); + } + + } + + private void completeSkipTask(Task task, ProcessInstance processInstance, String message, int type) { String taskId = task.getId(); ActTaskDef actTaskDef = findFirstByProcDefIdAndTaskKey(task.getProcessDefinitionId(), task.getTaskDefinitionKey()); - Authentication.setAuthenticatedUserId("-1"); - taskService.addComment(taskId, processInstance.getProcessInstanceId(), message); + if (actTaskDef.getTaskIndex() != ActConstant.TASK_INDEX_FIRST_USER_TASK) { + //不是发起节点 增加comment + Authentication.setAuthenticatedUserId("-1"); + taskService.addComment(taskId, processInstance.getProcessInstanceId(), message); + } + taskService.setAssignee(taskId, "-1"); if (ActConstant.TASK_TYPE_SINGE == actTaskDef.getTaskType()) { @@ -376,4 +400,18 @@ public class ActTaskDefService { } + public void setTaskAssignAndSaveRecord(int projectId, Admin targetAdmin) { + Task currentTask = actUtil.getCurrentTask(projectId); + if (currentTask != null) { + //设置审批人到流程 + taskService.setAssignee(currentTask.getId(), targetAdmin.getId() + ""); + + //保存一条指定承接人记录 + projectTaskRecordService.saveTaskRecord(projectId, currentTask, ProjectTaskRecord.STATUS_RE_ASSIGNEE, ActConstant.TASK_INDEX_OTHER, + "指定承接人【" + targetAdmin.getRealName() + "]"); + }else{ + logger.error("setTaskAssignAndSaveRecordError task is null, projectId:{}", projectId); + } + } + } diff --git a/src/main/java/cn/palmte/work/service/ProjectInstanceService.java b/src/main/java/cn/palmte/work/service/ProjectInstanceService.java index d068700..653cca9 100644 --- a/src/main/java/cn/palmte/work/service/ProjectInstanceService.java +++ b/src/main/java/cn/palmte/work/service/ProjectInstanceService.java @@ -99,6 +99,24 @@ public class ProjectInstanceService { logger.info("startProcess processDefkey:{}, businessKey:{}", processDefkey, businessKey); String processInstanceId = actProcInsService.startProcessInstance(processDefkey, businessKey, variables); + saveProjectInstance(project, processDefkey, processInstanceId); + } + + + public String startProcessBySystem(Project project, String processDefkey, ProjectTaskRecord taskRecord) throws Exception { + HashMap variables = new HashMap<>(); + variables.put(ActConstant.KEY_PROJECT_TYPE, project.getType()); + String businessKey = String.valueOf(project.getId()); + logger.info("startProcessBySystem processDefkey:{}, businessKey:{}", processDefkey, businessKey); + + String processInstanceId = actProcInsService.startProcessInstanceBySystem( + processDefkey, businessKey, variables, taskRecord); + + saveProjectInstance(project, processDefkey, processInstanceId); + return processInstanceId; + } + + private void saveProjectInstance(Project project, String processDefkey, String processInstanceId) { //保存流程实例id与项目的关联关系 ProjectInstanceRelation relation = new ProjectInstanceRelation(); relation.setProjectId(project.getId()); diff --git a/src/main/java/cn/palmte/work/service/ProjectService.java b/src/main/java/cn/palmte/work/service/ProjectService.java index a81d298..95c8903 100644 --- a/src/main/java/cn/palmte/work/service/ProjectService.java +++ b/src/main/java/cn/palmte/work/service/ProjectService.java @@ -5,6 +5,8 @@ import cn.palmte.work.model.*; import cn.palmte.work.utils.InterfaceUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -23,6 +25,7 @@ import java.util.stream.Collectors; */ @Service public class ProjectService { + private static final Logger logger = LoggerFactory.getLogger(ProjectService.class); @Autowired private Pagination pagination; @Autowired @@ -49,6 +52,10 @@ public class ProjectService { private ProjectBudgetService projectBudgetService; @Autowired private NumSeqService numSeqService; + @Autowired + private ProjectTaskRecordRepository projectTaskRecordRepository; + @Autowired + private ProjectTaskRecordService projectTaskRecordService; private QueryHelper getQueryHelper(Map searchInfo) { /*"CASE p.type WHEN 1 THEN '工程集成类' WHEN 2 THEN '设备集成类' WHEN 3 THEN '战略合作类' ELSE '未知' AS typeDesc," + @@ -543,10 +550,132 @@ public class ProjectService { * @return */ public ResponseMsg batchUpdateApprove(String json) { + int myAdminId = InterfaceUtil.getAdminId(); + List projectList = projectRepository.findByApproveId(myAdminId); + if (projectList.isEmpty()) { + return ResponseMsg.buildSuccessMsg("当前没有审批项目需要承接"); + } + JSONObject obj = JSON.parseObject(json); int adminId = obj.getIntValue("adminId"); Admin targetAdmin = adminRepository.findOne(adminId); - projectRepository.batchUpdateApprove(targetAdmin.getId(), targetAdmin.getRealName(), InterfaceUtil.getAdminId()); - return ResponseMsg.buildSuccessMsg("指定成功"); + + projectRepository.batchUpdateApprove(targetAdmin.getId(), targetAdmin.getRealName(), myAdminId); + + for (Project project : projectList) { + actTaskDefService.setTaskAssignAndSaveRecord(project.getId(), targetAdmin); + } + + return ResponseMsg.buildSuccessMsg("指定承接人成功"); + } + + + + + /** + * 退回到指定节点 + * 1、完结的项目允许重启并指定回退节点 + * 2、跨流程(概算、预算等)退回 + * 3、不跨流程退回(例如:仅在预算的审批流中退回某个节点) + * + * 因为要跨流程和重启结束流程 所以全部采用重新发起一个流程的方式 + */ + public void rollbackToRecord(String json) throws Exception{ + JSONObject obj = JSON.parseObject(json); + int taskRecordId = obj.getIntValue("taskRecordId"); + String message = obj.getString("message"); + String rollbackDesc = obj.getString("rollbackDesc"); + + ProjectTaskRecord one = projectTaskRecordRepository.findOne(taskRecordId); + logger.info("rollbackTask queryTaskRecord : {}", JSONObject.toJSONString(one)); + + int projectId = one.getProjectId(); + int taskStatus = one.getTaskStatus(); + StatusEnum statusEnum = one.getStatusByProDefId(); + String proDefKey = one.getProcDefKey(); + + //是否回退到发起节点 + boolean isStartTask = (taskStatus == 1); + + Project project = projectRepository.findOne(projectId); + //项目退回到指定状态 + project.setStatus(statusEnum.getStatus()); + project.setStatusDesc(statusEnum.getStatusDesc()); + project.setLastUpdateTime(new Date()); + + //指定审批人 + if (isStartTask) { + //退回到发起节点 审批人设置为空 + project.setApproveId(0); + project.setApproveName(""); + }else{ + project.setApproveId(Integer.parseInt(one.getAssigneeId())); + project.setApproveName(one.getAssigneeName()); + } + + //先全部默认为未知 后面再根据情况更新 + setApproveStatus(statusEnum, isStartTask, project); + + //修改项目 + projectRepository.saveAndFlush(project); + logger.info("rollbackTask updateProject : {}", JSONObject.toJSONString(project)); + + //保存退回审批记录 + projectTaskRecordService.saveTaskRecordWithRollback(projectId, one, message, rollbackDesc); + + //启动流程 + String processInstanceId = projectInstanceService.startProcessBySystem(project, proDefKey, one); + logger.info("rollbackTask startProcessBySystem : {}", processInstanceId); + + + //跳到退回任务 + actTaskDefService.skipTaskByProcInsIdAndTaskName(processInstanceId, one.getTaskName()); + logger.info("rollbackTask skipTaskByProcInsIdAndTaskName : success"); + } + + private void setApproveStatus(StatusEnum statusEnum, boolean isStartTask, Project project) { + project.setApproveStatusEstimate(-1); + project.setApproveStatusBudget(-1); + project.setApproveStatusSettle(-1); + project.setApproveStatusFinal(-1); + + if (statusEnum == StatusEnum.ESTIMATE_ACCOUNTS) { + if (isStartTask) { + //退回到发起节点 状态设置为审批未通过 + project.setApproveStatusEstimate(ApproveStatusEnum.APPROVAL_UNPASS.getApproveStatus()); + }else{ + project.setApproveStatusEstimate(ApproveStatusEnum.APPROVAL_PENDING.getApproveStatus()); + } + } else if (statusEnum == StatusEnum.BUDGET_ACCOUNTS) { + project.setApproveStatusEstimate(ApproveStatusEnum.APPROVAL_PASSED.getApproveStatus()); + + if (isStartTask) { + project.setApproveStatusBudget(ApproveStatusEnum.APPROVAL_UNPASS.getApproveStatus()); + }else{ + project.setApproveStatusBudget(ApproveStatusEnum.APPROVAL_PENDING.getApproveStatus()); + } + + }else if (statusEnum == StatusEnum.SETTLE_ACCOUNTS) { + project.setApproveStatusEstimate(ApproveStatusEnum.APPROVAL_PASSED.getApproveStatus()); + project.setApproveStatusBudget(ApproveStatusEnum.APPROVAL_PASSED.getApproveStatus()); + + if (isStartTask) { + project.setApproveStatusSettle(ApproveStatusEnum.APPROVAL_UNPASS.getApproveStatus()); + }else{ + project.setApproveStatusSettle(ApproveStatusEnum.APPROVAL_PENDING.getApproveStatus()); + } + + }else if (statusEnum == StatusEnum.FINAL_ACCOUNTS) { + project.setApproveStatusEstimate(ApproveStatusEnum.APPROVAL_PASSED.getApproveStatus()); + project.setApproveStatusBudget(ApproveStatusEnum.APPROVAL_PASSED.getApproveStatus()); + project.setApproveStatusSettle(ApproveStatusEnum.APPROVAL_PASSED.getApproveStatus()); + + if (isStartTask) { + project.setApproveStatusFinal(ApproveStatusEnum.APPROVAL_UNPASS.getApproveStatus()); + }else{ + project.setApproveStatusFinal(ApproveStatusEnum.APPROVAL_PENDING.getApproveStatus()); + } + + } } } diff --git a/src/main/java/cn/palmte/work/service/ProjectTaskRecordService.java b/src/main/java/cn/palmte/work/service/ProjectTaskRecordService.java index e9b56f1..815785e 100644 --- a/src/main/java/cn/palmte/work/service/ProjectTaskRecordService.java +++ b/src/main/java/cn/palmte/work/service/ProjectTaskRecordService.java @@ -1,8 +1,8 @@ package cn.palmte.work.service; +import cn.palmte.work.config.activiti.ActConstant; import cn.palmte.work.model.ProjectTaskRecord; import cn.palmte.work.model.ProjectTaskRecordRepository; -import cn.palmte.work.utils.ActUtil; import cn.palmte.work.utils.InterfaceUtil; import org.activiti.engine.task.Task; import org.slf4j.Logger; @@ -12,8 +12,7 @@ import org.springframework.stereotype.Service; import top.jfunc.common.db.QueryHelper; import top.jfunc.common.db.utils.Pagination; -import java.util.Date; -import java.util.List; +import java.util.*; @Service @@ -25,9 +24,6 @@ public class ProjectTaskRecordService { @Autowired Pagination pagination; - @Autowired - private ActUtil actUtil; - /** * 保存审批任务记录 @@ -36,8 +32,46 @@ public class ProjectTaskRecordService { * @param status * @param comment */ - public void saveTaskRecord(int projectId, Task task, int status, int taskIndex, String comment, String fileUrl) { - task.getProcessDefinitionId(); + public void saveTaskRecord(int projectId, Task task, int status, int taskIndex, String comment) { + ProjectTaskRecord record = getProjectTaskRecord(projectId, task, status, taskIndex, comment); + saveTaskRecord(record); + } + + public void saveTaskRecordWithFileUrl(int projectId, Task task, int status, + int taskIndex, String comment, String fileUrl) { + ProjectTaskRecord record = getProjectTaskRecord(projectId, task, status, taskIndex, comment); + record.setFileUrl(fileUrl); + saveTaskRecord(record); + } + + public void saveTaskRecordWithRollback(int projectId, ProjectTaskRecord oldRecord, String comment, String rollbackDesc) { + ProjectTaskRecord record = new ProjectTaskRecord(); + record.setProjectId(projectId); + record.setProcDefId(oldRecord.getProcDefId()); + record.setProcInsId(oldRecord.getProcInsId()); + record.setTaskDefKey(oldRecord.getTaskDefKey()); + record.setTaskName(oldRecord.getTaskName()); + record.setTaskComment(comment); + record.setTaskStatus(ProjectTaskRecord.STATUS_ROLLBACK); + record.setAssigneeId(InterfaceUtil.getAdminId() + ""); + record.setAssigneeName(InterfaceUtil.getAdmin().getRealName()); + record.setTaskIndex(ActConstant.TASK_INDEX_OTHER); + record.setCreateTime(new Date()); + record.setRollbackRecordId(oldRecord.getId()); + record.setRollbackDesc(rollbackDesc); + + saveTaskRecord(record); + } + + private void saveTaskRecord(ProjectTaskRecord record) { + try { + projectTaskRecordRepository.save(record); + } catch (Exception e) { + logger.error("", e); + } + } + + private ProjectTaskRecord getProjectTaskRecord(int projectId, Task task, int status, int taskIndex, String comment) { ProjectTaskRecord record = new ProjectTaskRecord(); record.setProjectId(projectId); record.setProcDefId(task.getProcessDefinitionId()); @@ -50,12 +84,7 @@ public class ProjectTaskRecordService { record.setAssigneeName(InterfaceUtil.getAdmin().getRealName()); record.setTaskIndex(taskIndex); record.setCreateTime(new Date()); - record.setFileUrl(fileUrl); - try { - projectTaskRecordRepository.save(record); - } catch (Exception e) { - logger.error("", e); - } + return record; } @@ -70,8 +99,38 @@ public class ProjectTaskRecordService { QueryHelper queryHelper = new QueryHelper(select, " project_task_record tr LEFT JOIN sys_user su on su.id=tr.assignee_id "); queryHelper.addCondition("tr.project_id=?", projectId); queryHelper.addOrderProperty("tr.create_time", true); - return pagination.find(queryHelper.getSql(), ProjectTaskRecord.class); + List projectTaskRecords = pagination.find(queryHelper.getSql(), ProjectTaskRecord.class); + + //设置哪些任务能退回 admin才能退回 + if (!projectTaskRecords.isEmpty() && "admin".equals(InterfaceUtil.getAdmin().getRealName())) { + //预算流程可能有多个 找到最新的一个预算流程 最新的预算流程才能退回 + String lastProcInsId = ""; + Optional lastProcInsIdOp = projectTaskRecords.stream() + .filter(r -> r.getProcDefId().startsWith(ActConstant.PROCESS_DEFKEY_BUDGET)) + .map(ProjectTaskRecord::getProcInsId).max(Comparator.naturalOrder()); + if (lastProcInsIdOp.isPresent()) { + lastProcInsId = lastProcInsIdOp.get(); + } + + for (ProjectTaskRecord record : projectTaskRecords) { + if (record.getTaskStatus() == ProjectTaskRecord.STATUS_ROLLBACK) { + //已退回记录 不能再退回 + continue; + } + + if (!record.getProcDefId().startsWith(ActConstant.PROCESS_DEFKEY_BUDGET)) { + //非预算流程全部支持退回 + record.setCanRollback(true); + } else { + //预算最后一个流程支持退回 + if (record.getProcInsId().equals(lastProcInsId)) { + record.setCanRollback(true); + } + } + } + + } + return projectTaskRecords; } - } diff --git a/src/main/java/cn/palmte/work/utils/ActUtil.java b/src/main/java/cn/palmte/work/utils/ActUtil.java index 3b9108b..b0bce67 100644 --- a/src/main/java/cn/palmte/work/utils/ActUtil.java +++ b/src/main/java/cn/palmte/work/utils/ActUtil.java @@ -61,6 +61,7 @@ public class ActUtil { return null; } ProjectInstanceRelation projectInstanceRelation = relationList.get(0); + logger.info("getCurrentTask projectId:{}, procInsId:{}", projectId, projectInstanceRelation.getProcessInsId()); return taskService.createTaskQuery().processInstanceId(projectInstanceRelation.getProcessInsId()).singleResult(); } catch (Exception e) { logger.error("", e); diff --git a/src/main/resources/templates/admin/project_approve.ftl b/src/main/resources/templates/admin/project_approve.ftl index 036a100..f875417 100644 --- a/src/main/resources/templates/admin/project_approve.ftl +++ b/src/main/resources/templates/admin/project_approve.ftl @@ -2231,6 +2231,22 @@
${node.roleName}-${node.assigneeName}: <#if node.taskIndex!=2 && node.taskStatus==2>审核通过 <#if node.taskIndex!=2 && node.taskStatus==3>审核不通过 + + <#if node.canRollback> + + + + + + <#if node.taskStatus==4> + 退回到【${node.rollbackDesc!}】 + + +
${node.taskComment} @@ -2771,6 +2787,52 @@
+ <#--管理员退回弹窗--> +
+
+ + +
+
+
+
+
+ + +
+
+ *退回意见
+
+ +
+
+ +
+
+
+
+
+ +
+
+
@@ -2917,4 +2979,52 @@ } }); } + + /** + * 打开退回弹窗 + */ + var openRollbackToRecordModal= function(taskRecordId, rbTaskDesc) { + $("#rbTaskRecordId").val(taskRecordId); + $("#rbTaskDesc").html(rbTaskDesc); + + $('#rollbackToRecordModal').modal({ + relatedElement: this, + onConfirm: function() { + console.log("提交"); + }, + onCancel: function() { + console.log("取消"); + } + }); + }; + + /** + * 退回 + */ + var rollbackToRecord = function () { + var message = $("#rollbackTextarea").val(); + var rbTaskDesc = $("#rbTaskDesc").text(); + var rbTaskRecordId = $("#rbTaskRecordId").val(); + var params = { + taskRecordId: rbTaskRecordId, + message: message, + rollbackDesc: rbTaskDesc + }; + $.ajax({ + url: '${base}/project/rollbackToRecord', + data: JSON.stringify(params), + dataType: "json", + contentType: "application/json", + type: 'post', + async: false, + success: function (data) { + if (data.status == 0) { + alert(data.msg); + window.location.href = window.location.href; + } else if (data.status == 1) { + alert(data.msg); + } + } + }); + }; \ No newline at end of file diff --git a/src/main/resources/templates/admin/project_task_record_list.ftl b/src/main/resources/templates/admin/project_task_record_list.ftl index 2f5d68c..829d458 100644 --- a/src/main/resources/templates/admin/project_task_record_list.ftl +++ b/src/main/resources/templates/admin/project_task_record_list.ftl @@ -30,6 +30,10 @@
${node.roleName}-${node.assigneeName}: <#if node.taskIndex!=2 && node.taskStatus==2>审核通过 <#if node.taskIndex!=2 && node.taskStatus==3>审核不通过 + + <#if node.taskStatus==4> + 退回到【${node.rollbackDesc!}】 +
${node.taskComment} @@ -105,20 +109,3 @@ - - - - - - - - - - - - - - - - -