diff --git a/src/main/java/neatlogic/module/process/dao/mapper/processtask/ProcessTaskMapper.xml b/src/main/java/neatlogic/module/process/dao/mapper/processtask/ProcessTaskMapper.xml
index c3fd9883eb1f2cd711097b21ccae65bc003afb1a..956c61b893de4d3b0531a4e6780ec2e5cd1c6de6 100644
--- a/src/main/java/neatlogic/module/process/dao/mapper/processtask/ProcessTaskMapper.xml
+++ b/src/main/java/neatlogic/module/process/dao/mapper/processtask/ProcessTaskMapper.xml
@@ -2973,7 +2973,7 @@
#{processTaskId},
#{processTaskStepId},
#{userUuid},
- NOW(3),
+ #{actionTime},
#{action},
#{stepStatus},
#{originalUser},
diff --git a/src/main/java/neatlogic/module/process/dao/mapper/processtask/ProcessTaskStepTimeAuditMapper.java b/src/main/java/neatlogic/module/process/dao/mapper/processtask/ProcessTaskStepTimeAuditMapper.java
index 2b6c941c7bed023530451f75ca753232aa9b5ed0..38b31e0ce7dcdb12969db868717dd71c0c1c60a7 100644
--- a/src/main/java/neatlogic/module/process/dao/mapper/processtask/ProcessTaskStepTimeAuditMapper.java
+++ b/src/main/java/neatlogic/module/process/dao/mapper/processtask/ProcessTaskStepTimeAuditMapper.java
@@ -18,6 +18,8 @@
package neatlogic.module.process.dao.mapper.processtask;
import neatlogic.framework.process.crossover.IProcessTaskStepTimeAuditCrossoverMapper;
+import neatlogic.framework.process.dto.ProcessTaskStepCostVo;
+import neatlogic.framework.process.dto.ProcessTaskStepCostWorkerVo;
import neatlogic.framework.process.dto.ProcessTaskStepTimeAuditVo;
import java.util.List;
@@ -27,7 +29,15 @@ public interface ProcessTaskStepTimeAuditMapper extends IProcessTaskStepTimeAudi
ProcessTaskStepTimeAuditVo getLastProcessTaskStepTimeAuditByStepId(Long processTaskStepId);
+ ProcessTaskStepCostVo getLastProcessTaskStepCostByProcessTaskStepId(Long processTaskStepId);
+
int updateProcessTaskStepTimeAudit(ProcessTaskStepTimeAuditVo processTaskStepTimeAuditVo);
int insertProcessTaskStepTimeAudit(ProcessTaskStepTimeAuditVo processTaskStepTimeAuditVo);
+
+ int insertProcessTaskStepCost(ProcessTaskStepCostVo processTaskStepCostVo);
+
+ int insertProcessTaskStepCostWorker(ProcessTaskStepCostWorkerVo processTaskStepCostWorkerVo);
+
+ int updateProcessTaskStepCost(ProcessTaskStepCostVo processTaskStepCostVo);
}
diff --git a/src/main/java/neatlogic/module/process/dao/mapper/processtask/ProcessTaskStepTimeAuditMapper.xml b/src/main/java/neatlogic/module/process/dao/mapper/processtask/ProcessTaskStepTimeAuditMapper.xml
index 5ca4788be9f8962828aa3717d8a1d7a5264d21e3..ab9c64717dd9b81ab2c543390b892d68fb38058f 100644
--- a/src/main/java/neatlogic/module/process/dao/mapper/processtask/ProcessTaskStepTimeAuditMapper.xml
+++ b/src/main/java/neatlogic/module/process/dao/mapper/processtask/ProcessTaskStepTimeAuditMapper.xml
@@ -52,6 +52,27 @@
ORDER BY id DESC LIMIT 1
+
+
select LAST_INSERT_ID() as id
@@ -81,6 +102,33 @@
)
+
+ INSERT INTO `processtask_step_cost` (
+ `id`,
+ `processtask_id`,
+ `processtask_step_id`,
+ `start_operate`,
+ `start_status`,
+ `start_time`,
+ `start_user_uuid`
+ )
+ VALUES
+ (
+ #{id},
+ #{processTaskId},
+ #{processTaskStepId},
+ #{startOperate},
+ #{startStatus},
+ #{startTime},
+ #{startUserUuid}
+ )
+
+
+
+ INSERT INTO `processtask_step_cost_worker` (`id`, `operate_type`, `cost_id`, `type`, `uuid`)
+ VALUES (#{id}, #{operateType}, #{costId}, #{type}, #{uuid})
+
+
UPDATE
`processtask_step_timeaudit`
@@ -96,4 +144,16 @@
WHERE `id` = #{id}
+
+
+ UPDATE `processtask_step_cost`
+ SET
+ `end_operate` = #{endOperate},
+ `end_status` = #{endStatus},
+ `end_time` = #{endTime},
+ `end_user_uuid` = #{endUserUuid},
+ `time_cost` = #{timeCost},
+ `realtime_cost` = #{realTimeCost}
+ WHERE `id` = #{id}
+
\ No newline at end of file
diff --git a/src/main/java/neatlogic/module/process/stephandler/postprocessor/ProcessTaskStepCostPostProcessor.java b/src/main/java/neatlogic/module/process/stephandler/postprocessor/ProcessTaskStepCostPostProcessor.java
new file mode 100644
index 0000000000000000000000000000000000000000..d62f5ed07e7f2fd68c432c8f45624e34bb485a6b
--- /dev/null
+++ b/src/main/java/neatlogic/module/process/stephandler/postprocessor/ProcessTaskStepCostPostProcessor.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2024 深圳极向量科技有限公司 All Rights Reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package neatlogic.module.process.stephandler.postprocessor;
+
+import com.alibaba.fastjson.JSONObject;
+import neatlogic.framework.asynchronization.threadlocal.UserContext;
+import neatlogic.framework.common.constvalue.GroupSearch;
+import neatlogic.framework.process.constvalue.IOperationType;
+import neatlogic.framework.process.constvalue.ProcessTaskOperationType;
+import neatlogic.framework.process.constvalue.ProcessUserType;
+import neatlogic.framework.process.dto.*;
+import neatlogic.framework.process.stephandler.core.IProcessTaskOperatePostProcessor;
+import neatlogic.framework.util.SnowflakeUtil;
+import neatlogic.framework.worktime.dao.mapper.WorktimeMapper;
+import neatlogic.module.process.dao.mapper.processtask.ProcessTaskMapper;
+import neatlogic.module.process.dao.mapper.processtask.ProcessTaskStepTimeAuditMapper;
+import org.apache.commons.collections4.CollectionUtils;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+
+@Component
+public class ProcessTaskStepCostPostProcessor implements IProcessTaskOperatePostProcessor {
+
+ @Resource
+ private ProcessTaskStepTimeAuditMapper processTaskStepTimeAuditMapper;
+
+ @Resource
+ private ProcessTaskMapper processTaskMapper;
+
+ @Resource
+ private WorktimeMapper worktimeMapper;
+
+ @Override
+ public void postProcessAfterProcessTaskStepOperate(ProcessTaskStepVo currentProcessTaskStepVo, IOperationType operationType) {
+ Long processTaskId = currentProcessTaskStepVo.getProcessTaskId();
+ Long processTaskStepId = currentProcessTaskStepVo.getId();
+ JSONObject otherParam = currentProcessTaskStepVo.getParamObj();
+ List list = new ArrayList<>();
+ list.add(ProcessTaskOperationType.STEP_ACTIVE);
+ list.add(ProcessTaskOperationType.STEP_ACCEPT);
+ list.add(ProcessTaskOperationType.STEP_START);
+ list.add(ProcessTaskOperationType.STEP_COMPLETE);
+ list.add(ProcessTaskOperationType.STEP_BACK);
+ list.add(ProcessTaskOperationType.STEP_PAUSE);
+ list.add(ProcessTaskOperationType.STEP_TRANSFER);
+ list.add(ProcessTaskOperationType.STEP_RECOVER);
+ list.add(ProcessTaskOperationType.STEP_RETREAT);
+ list.add(ProcessTaskOperationType.STEP_REDO);
+ list.add(ProcessTaskOperationType.STEP_REAPPROVAL);
+ if (list.contains(operationType)) {
+ Date operateTime = otherParam.getDate("operateTime");
+ if (operateTime == null) {
+ operateTime = new Date();
+ }
+ String stepStatus = currentProcessTaskStepVo.getStatus();
+ if (ProcessTaskOperationType.STEP_COMPLETE == operationType || ProcessTaskOperationType.STEP_BACK == operationType) {
+ List workerList = new ArrayList<>();
+ List processTaskStepUserList = processTaskMapper.getProcessTaskStepUserByStepId(processTaskStepId, ProcessUserType.MAJOR.getValue());
+ if (CollectionUtils.isNotEmpty(processTaskStepUserList)) {
+ for (ProcessTaskStepUserVo processTaskStepUserVo : processTaskStepUserList) {
+ ProcessTaskStepCostWorkerVo workerVo = new ProcessTaskStepCostWorkerVo();
+ workerVo.setType(GroupSearch.USER.getValue());
+ workerVo.setUuid(processTaskStepUserVo.getUserUuid());
+ workerList.add(workerVo);
+ }
+ }
+ saveProcessTaskStepCost(processTaskId, processTaskStepId, operationType, operateTime, stepStatus, workerList);
+ } else {
+ List workerList = new ArrayList<>();
+ List processTaskStepWorkerList = processTaskMapper.getProcessTaskStepWorkerListByProcessTaskStepIdListAndUserType(Collections.singletonList(processTaskStepId), ProcessUserType.MAJOR.getValue());
+ if (CollectionUtils.isNotEmpty(processTaskStepWorkerList)) {
+ for (ProcessTaskStepWorkerVo processTaskStepWorkerVo : processTaskStepWorkerList) {
+ ProcessTaskStepCostWorkerVo workerVo = new ProcessTaskStepCostWorkerVo();
+ workerVo.setType(processTaskStepWorkerVo.getType());
+ workerVo.setUuid(processTaskStepWorkerVo.getUuid());
+ workerList.add(workerVo);
+ }
+ }
+ saveProcessTaskStepCost(processTaskId, processTaskStepId, operationType, operateTime, stepStatus, workerList);
+ }
+ }
+ }
+
+ private void saveProcessTaskStepCost(Long processTaskId, Long processTaskStepId, IOperationType operationType, Date operateTime, String stepStatus, List workerList) {
+ String startUserUuid = UserContext.get().getUserUuid();
+ ProcessTaskStepCostVo lastProcessTaskStepCostVo = processTaskStepTimeAuditMapper.getLastProcessTaskStepCostByProcessTaskStepId(processTaskStepId);
+ if (lastProcessTaskStepCostVo != null) {
+ lastProcessTaskStepCostVo.setEndOperate(operationType.getValue());
+ lastProcessTaskStepCostVo.setEndStatus(stepStatus);
+ lastProcessTaskStepCostVo.setEndTime(operateTime);
+ lastProcessTaskStepCostVo.setEndUserUuid(startUserUuid);
+ long realtimeCost = operateTime.getTime() - lastProcessTaskStepCostVo.getStartTime().getTime();
+ long timeCost = realtimeCost;
+ ProcessTaskVo processTaskVo = processTaskMapper.getProcessTaskBaseInfoById(processTaskId);
+ if (processTaskVo.getWorktimeUuid() != null) {
+ timeCost = worktimeMapper.calculateCostTime(processTaskVo.getWorktimeUuid(), lastProcessTaskStepCostVo.getStartTime().getTime(), operateTime.getTime());
+ }
+ lastProcessTaskStepCostVo.setTimeCost(timeCost);
+ lastProcessTaskStepCostVo.setRealTimeCost(realtimeCost);
+ doSaveProcessTaskStepCost(lastProcessTaskStepCostVo, workerList);
+ }
+ ProcessTaskStepCostVo processTaskStepCostVo = new ProcessTaskStepCostVo();
+ processTaskStepCostVo.setProcessTaskId(processTaskId);
+ processTaskStepCostVo.setProcessTaskStepId(processTaskStepId);
+ processTaskStepCostVo.setStartOperate(operationType.getValue());
+ processTaskStepCostVo.setStartStatus(stepStatus);
+ processTaskStepCostVo.setStartTime(operateTime);
+ processTaskStepCostVo.setStartUserUuid(startUserUuid);
+ doSaveProcessTaskStepCost(processTaskStepCostVo, workerList);
+ }
+
+ private void doSaveProcessTaskStepCost(ProcessTaskStepCostVo processTaskStepCostVo, List workderList) {
+ String operateType = "end";
+ Long id = processTaskStepCostVo.getId();
+ if (id == null) {
+ id = SnowflakeUtil.uniqueLong();
+ operateType = "start";
+ processTaskStepCostVo.setId(id);
+ processTaskStepTimeAuditMapper.insertProcessTaskStepCost(processTaskStepCostVo);
+ } else {
+ processTaskStepTimeAuditMapper.updateProcessTaskStepCost(processTaskStepCostVo);
+ }
+ if (CollectionUtils.isNotEmpty(workderList)) {
+ for (ProcessTaskStepCostWorkerVo processTaskStepCostWorkerVo : workderList) {
+ processTaskStepCostWorkerVo.setId(SnowflakeUtil.uniqueLong());
+ processTaskStepCostWorkerVo.setCostId(id);
+ processTaskStepCostWorkerVo.setOperateType(operateType);
+ processTaskStepTimeAuditMapper.insertProcessTaskStepCostWorker(processTaskStepCostWorkerVo);
+ }
+ }
+ }
+}
diff --git a/src/main/java/neatlogic/module/process/thread/ProcessTaskAuditThread.java b/src/main/java/neatlogic/module/process/thread/ProcessTaskAuditThread.java
index 7a6aa760fe41117ff3273bdd964462c291dbf50f..1d9bab429c172fb654828c77c95bc4ba0f012cb4 100644
--- a/src/main/java/neatlogic/module/process/thread/ProcessTaskAuditThread.java
+++ b/src/main/java/neatlogic/module/process/thread/ProcessTaskAuditThread.java
@@ -35,6 +35,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
+import java.util.Date;
import java.util.Objects;
@Service
@@ -82,6 +83,11 @@ public class ProcessTaskAuditThread extends NeatLogicThread {
processTaskStepAuditVo.setUserUuid(UserContext.get().getUserUuid());// 兼容automatic作业无用户
processTaskStepAuditVo.setStepStatus(currentProcessTaskStepVo.getStatus());
processTaskStepAuditVo.setOriginalUser(currentProcessTaskStepVo.getOriginalUser());
+ Date operateTime = paramObj.getDate("operateTime");
+ if (operateTime == null) {
+ operateTime = new Date();
+ }
+ processTaskStepAuditVo.setActionTime(operateTime);
String source = paramObj.getString("source");
if (StringUtils.isNotBlank(source)) {
processTaskStepAuditVo.setSource(source);
diff --git a/src/main/resources/neatlogic/resources/process/changelog/2024-07-25/neatlogic_tenant.sql b/src/main/resources/neatlogic/resources/process/changelog/2024-07-25/neatlogic_tenant.sql
new file mode 100644
index 0000000000000000000000000000000000000000..789ad8a7914a08f365a41605247f467ff8c47528
--- /dev/null
+++ b/src/main/resources/neatlogic/resources/process/changelog/2024-07-25/neatlogic_tenant.sql
@@ -0,0 +1,28 @@
+CREATE TABLE `processtask_step_cost` (
+ `id` bigint NOT NULL COMMENT 'ID',
+ `processtask_id` bigint NOT NULL COMMENT '工单id',
+ `processtask_step_id` bigint DEFAULT NULL COMMENT '步骤id',
+ `start_operate` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '开始操作类型',
+ `start_status` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '开始操作状态',
+ `start_time` timestamp(3) NOT NULL COMMENT '开始操作时间',
+ `start_user_uuid` char(32) COLLATE utf8mb4_general_ci NOT NULL COMMENT '开始操作人',
+ `end_operate` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '结束操作类型',
+ `end_status` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '结束操作状态',
+ `end_time` timestamp(3) NULL DEFAULT NULL COMMENT '结束操作时间',
+ `end_user_uuid` char(32) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '结束操作人',
+ `time_cost` bigint DEFAULT NULL COMMENT '工作时间耗时',
+ `realtime_cost` bigint DEFAULT NULL COMMENT '自然时间耗时',
+ PRIMARY KEY (`id`),
+ KEY `idx_processtask_id_processtask_step_id` (`processtask_id`,`processtask_step_id`),
+ KEY `idx_processtask_step_id` (`processtask_step_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='工单步骤操作耗时表';
+
+CREATE TABLE `processtask_step_cost_worker` (
+ `id` bigint NOT NULL COMMENT 'ID',
+ `operate_type` enum('start','end') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '起止操作',
+ `cost_id` bigint NOT NULL COMMENT '耗时id',
+ `type` enum('user','team','role') COLLATE utf8mb4_general_ci NOT NULL COMMENT '类型',
+ `uuid` char(32) COLLATE utf8mb4_general_ci NOT NULL COMMENT 'UUID',
+ PRIMARY KEY (`id`),
+ KEY `idx_cost_id` (`cost_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='工单步骤操作耗时处理人表';
\ No newline at end of file
diff --git a/src/main/resources/neatlogic/resources/process/changelog/2024-07-25/version.json b/src/main/resources/neatlogic/resources/process/changelog/2024-07-25/version.json
new file mode 100644
index 0000000000000000000000000000000000000000..240eadf4ccf60011f4ca7b2dd62da414cfb1610b
--- /dev/null
+++ b/src/main/resources/neatlogic/resources/process/changelog/2024-07-25/version.json
@@ -0,0 +1,10 @@
+{
+ "content":[
+ {
+ "type":"新增功能",
+ "detail":[
+ {"msg":"1.IT服务-增加记录步骤处理过程中每个处理人每个阶段的开始时间和结束时间"}
+ ]
+ }
+ ]
+}
diff --git a/src/main/resources/neatlogic/resources/process/sqlscript/ddl.sql b/src/main/resources/neatlogic/resources/process/sqlscript/ddl.sql
index fc28bf1da570e65467e353968b562ed7eb85ab47..c397a8cc5228e56a5c1e7f824a05825ff16821d6 100644
--- a/src/main/resources/neatlogic/resources/process/sqlscript/ddl.sql
+++ b/src/main/resources/neatlogic/resources/process/sqlscript/ddl.sql
@@ -1559,4 +1559,39 @@ CREATE TABLE IF NOT EXISTS `process_workcenter_thead_config` (
`hash` char(32) COLLATE utf8mb4_general_ci NOT NULL COMMENT '配置hash',
`config` text COLLATE utf8mb4_general_ci COMMENT '配置',
PRIMARY KEY (`hash`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
\ No newline at end of file
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
+
+-- ----------------------------
+-- Table structure for processtask_step_cost
+-- ----------------------------
+CREATE TABLE IF NOT EXISTS `processtask_step_cost` (
+ `id` bigint NOT NULL COMMENT 'ID',
+ `processtask_id` bigint NOT NULL COMMENT '工单id',
+ `processtask_step_id` bigint DEFAULT NULL COMMENT '步骤id',
+ `start_operate` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '开始操作类型',
+ `start_status` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '开始操作状态',
+ `start_time` timestamp(3) NOT NULL COMMENT '开始操作时间',
+ `start_user_uuid` char(32) COLLATE utf8mb4_general_ci NOT NULL COMMENT '开始操作人',
+ `end_operate` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '结束操作类型',
+ `end_status` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '结束操作状态',
+ `end_time` timestamp(3) NULL DEFAULT NULL COMMENT '结束操作时间',
+ `end_user_uuid` char(32) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '结束操作人',
+ `time_cost` bigint DEFAULT NULL COMMENT '工作时间耗时',
+ `realtime_cost` bigint DEFAULT NULL COMMENT '自然时间耗时',
+ PRIMARY KEY (`id`),
+ KEY `idx_processtask_id_processtask_step_id` (`processtask_id`,`processtask_step_id`),
+ KEY `idx_processtask_step_id` (`processtask_step_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='工单步骤操作耗时表';
+
+-- ----------------------------
+-- Table structure for processtask_step_cost_worker
+-- ----------------------------
+CREATE TABLE IF NOT EXISTS `processtask_step_cost_worker` (
+ `id` bigint NOT NULL COMMENT 'ID',
+ `operate_type` enum('start','end') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '起止操作',
+ `cost_id` bigint NOT NULL COMMENT '耗时id',
+ `type` enum('user','team','role') COLLATE utf8mb4_general_ci NOT NULL COMMENT '类型',
+ `uuid` char(32) COLLATE utf8mb4_general_ci NOT NULL COMMENT 'UUID',
+ PRIMARY KEY (`id`),
+ KEY `idx_cost_id` (`cost_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='工单步骤操作耗时处理人表';
\ No newline at end of file