From ac2e2b5af3726ee64dc37c3ebf26989a0346f22a Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期六, 07 十一月 2026 19:16:05 +0800
Subject: [PATCH] feat(feedback): 优化报工审批流程并增加报工人校验
---
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskServiceImpl.java | 284 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 273 insertions(+), 11 deletions(-)
diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskServiceImpl.java
index 2510e7a..c2bba44 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskServiceImpl.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskServiceImpl.java
@@ -2,6 +2,10 @@
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
+import cn.iocoder.yudao.module.mes.service.pd.processparamtemplate.MesPdProcessParamTemplateService;
+import cn.iocoder.yudao.module.mes.service.pro.feedback.dto.MesTaskParamSnapshot;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskAutoGeneratePreviewRespVO;
import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskAutoGenerateReqVO;
@@ -11,6 +15,7 @@
import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationMachineDO;
+import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationWorkerDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.task.MesProTaskDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO;
import cn.iocoder.yudao.module.mes.dal.mysql.pro.task.MesProTaskMapper;
@@ -18,11 +23,14 @@
import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodeRuleCodeEnum;
import cn.iocoder.yudao.module.mes.enums.pro.MesProTaskStatusEnum;
import cn.iocoder.yudao.module.mes.service.dv.machinery.MesDvMachineryService;
+import cn.iocoder.yudao.module.mes.service.cal.team.MesCalTeamService;
+import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamDO;
import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodeRecordService;
import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService;
import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationMachineService;
import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService;
+import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationWorkerService;
import cn.iocoder.yudao.module.mes.service.pro.process.MesProProcessService;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProcessDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteDO;
@@ -43,15 +51,28 @@
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_TASK_SCHEDULE_INVALID;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_TASK_ALREADY_FINISHED;
+import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_TASK_CANNOT_PAUSE;
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_TASK_HAS_FEEDBACK;
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_TASK_NOT_EXISTS;
+import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_TASK_NOT_PAUSED;
+import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
+import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
+import cn.iocoder.yudao.module.mes.dal.dataobject.pro.task.MesProTaskPauseRecordDO;
+import cn.iocoder.yudao.module.mes.dal.mysql.pro.task.MesProTaskPauseRecordMapper;
+import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskPauseReqVO;
+import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskResumeReqVO;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
/**
* MES 鐢熶骇浠诲姟 Service 瀹炵幇绫�
@@ -61,12 +82,21 @@
@Service
@Validated
public class MesProTaskServiceImpl implements MesProTaskService {
+ @Resource
+ private cn.iocoder.yudao.module.mes.service.pro.task.schedule.MesProScheduleGuardService scheduleGuard;
+ @Resource
+ private cn.iocoder.yudao.module.mes.dal.mysql.pro.workorder.MesProWorkOrderMapper scheduleWorkOrderMapper;
@Resource
private MesProTaskMapper taskMapper;
+ @Resource
+ private MesPdProcessParamTemplateService paramTemplateService;
@Resource
private MesProFeedbackMapper feedbackMapper;
+
+ @Resource
+ private MesProTaskPauseRecordMapper taskPauseRecordMapper;
@Resource
@Lazy
@@ -97,46 +127,66 @@
@Resource
@Lazy
private MesDvMachineryService machineryService;
+ @Resource
+ private MesCalTeamService teamService;
+ @Resource
+ private MesMdWorkstationWorkerService workstationWorkerService;
+ @Resource
+ private AdminUserApi adminUserApi;
@Override
+ @Transactional(rollbackFor = Exception.class)
public Long createTask(MesProTaskSaveReqVO createReqVO) {
+ scheduleGuard.lock();
// 1. 鏍¢獙鍏宠仈鏁版嵁瀛樺湪
MesProWorkOrderDO workOrder = workOrderService.validateWorkOrderExists(createReqVO.getWorkOrderId());
- workstationService.validateWorkstationExists(createReqVO.getWorkstationId());
+ var station = workstationService.validateWorkstationExists(createReqVO.getWorkstationId());
+ if (java.util.Objects.equals(workOrder.getType(), cn.iocoder.yudao.module.mes.enums.pro.MesProWorkOrderTypeEnum.SELF.getType()) && !java.util.Objects.equals(station.getProcessId(), createReqVO.getProcessId())) {
+ throw exception(PRO_TASK_SCHEDULE_INVALID, "宸ヤ綔绔欎笌宸ュ簭涓嶅尮閰�");
+ }
routeService.validateRouteExists(createReqVO.getRouteId());
processService.validateProcessExistsAndEnable(createReqVO.getProcessId());
+ fillTeamInfo(createReqVO);
// 2. 鑷姩纭畾 itemId锛氫紭鍏堝墠绔紶鍏� 鈫� 宸ヨ壓璺嚎宸ュ簭鐨勪骇鍑轰骇鍝� 鈫� 宸ュ崟鎴愬搧
Long itemId = createReqVO.getItemId();
if (itemId == null) {
MesProRouteProcessDO routeProcess = routeProcessService
.getRouteProcessByRouteIdAndProcessId(createReqVO.getRouteId(), createReqVO.getProcessId());
- if (routeProcess != null && routeProcess.getOutputItemId() != null) {
- itemId = Long.valueOf(routeProcess.getOutputItemId().split(",")[0].trim());
- } else {
- itemId = workOrder.getProductId();
- }
+ itemId = resolveTaskItemId(routeProcess, workOrder.getProductId());
}
MesMdItemDO item = itemService.validateItemExists(itemId);
// 3.1 鏋勫缓浠诲姟 DO锛氳嚜鍔ㄥ~鍏呭鎴蜂俊鎭�
+ List<Long> assigneeUserIds = createReqVO.getAssigneeUserIds();
+ if (CollUtil.isEmpty(assigneeUserIds)) {
+ // 鏈寚瀹氭姤宸ヤ汉鏃堕粯璁ゅ彇宸ヤ綔绔欓厤缃殑浜哄憳锛岄伩鍏嶄竴閿帓浜х敓鎴愮殑浠诲姟鏃犱汉鍙姤
+ assigneeUserIds = getWorkstationWorkerUserIds(createReqVO.getWorkstationId());
+ }
MesProTaskDO task = BeanUtils.toBean(createReqVO, MesProTaskDO.class)
.setItemId(itemId) // 纭繚浣跨敤璁$畻鍚庣殑 itemId
.setName(buildTaskName(item, createReqVO.getQuantity()))
.setCode(autoCodeRecordService.generateAutoCode(MesMdAutoCodeRuleCodeEnum.PRO_TASK_CODE.getCode()))
+ .setAssigneeUserIds(joinUserIds(assigneeUserIds))
.setStatus(MesProTaskStatusEnum.PREPARE.getStatus());
if (task.getClientId() == null && workOrder.getClientId() != null) {
task.setClientId(workOrder.getClientId());
}
// 2.2 鎻掑叆
+ scheduleGuard.validate(workOrder, task, null);
+ freezeTaskParamConfig(task);
taskMapper.insert(task);
+ synchronizeScheduledQuantity(workOrder, task.getRouteId());
return task.getId();
}
@Override
+ @Transactional(rollbackFor = Exception.class)
public void updateTask(MesProTaskSaveReqVO updateReqVO) {
- // 1.1 鏍¢獙瀛樺湪
- MesProTaskDO task = validateTaskExists(updateReqVO.getId());
+ scheduleGuard.lock();
+ MesProTaskDO task = taskMapper.selectOne(new LambdaQueryWrapperX<MesProTaskDO>()
+ .eq(MesProTaskDO::getId, updateReqVO.getId()).last("FOR UPDATE"));
+ if (task == null) throw exception(PRO_TASK_NOT_EXISTS);
// 1.2 鏍¢獙鍏宠仈鏁版嵁瀛樺湪
if (updateReqVO.getWorkOrderId() != null) {
workOrderService.validateWorkOrderExists(updateReqVO.getWorkOrderId());
@@ -150,6 +200,7 @@
if (updateReqVO.getProcessId() != null) {
processService.validateProcessExistsAndEnable(updateReqVO.getProcessId());
}
+ fillTeamInfo(updateReqVO);
MesMdItemDO item;
if (updateReqVO.getItemId() != null) {
item = itemService.validateItemExists(updateReqVO.getItemId());
@@ -158,10 +209,121 @@
}
BigDecimal quantity = updateReqVO.getQuantity() != null ? updateReqVO.getQuantity() : task.getQuantity();
+ MesProTaskDO candidate = BeanUtils.toBean(task, MesProTaskDO.class)
+ .setWorkOrderId(updateReqVO.getWorkOrderId() != null ? updateReqVO.getWorkOrderId() : task.getWorkOrderId())
+ .setRouteId(updateReqVO.getRouteId() != null ? updateReqVO.getRouteId() : task.getRouteId())
+ .setProcessId(updateReqVO.getProcessId() != null ? updateReqVO.getProcessId() : task.getProcessId())
+ .setWorkstationId(updateReqVO.getWorkstationId() != null ? updateReqVO.getWorkstationId() : task.getWorkstationId())
+ .setQuantity(quantity)
+ .setStartTime(updateReqVO.getStartTime() != null ? updateReqVO.getStartTime() : task.getStartTime())
+ .setEndTime(updateReqVO.getEndTime() != null ? updateReqVO.getEndTime() : task.getEndTime());
+ var station = workstationService.validateWorkstationExists(candidate.getWorkstationId());
+ if (java.util.Objects.equals(workOrderService.validateWorkOrderExists(candidate.getWorkOrderId()).getType(), cn.iocoder.yudao.module.mes.enums.pro.MesProWorkOrderTypeEnum.SELF.getType()) && !java.util.Objects.equals(station.getProcessId(), candidate.getProcessId())) {
+ throw exception(PRO_TASK_SCHEDULE_INVALID, "宸ヤ綔绔欎笌宸ュ簭涓嶅尮閰�");
+ }
+ scheduleGuard.validate(workOrderService.validateWorkOrderExists(candidate.getWorkOrderId()), candidate, task.getId());
// 2. 鏇存柊
MesProTaskDO updateObj = BeanUtils.toBean(updateReqVO, MesProTaskDO.class)
.setName(buildTaskName(item, quantity));
+ // 鎶ュ伐浜轰负 null 琛ㄧず涓嶄慨鏀癸紱绌洪泦鍚堣〃绀烘竻绌洪檺鍒讹紙鎵�鏈変汉鍙姤宸ワ級
+ if (updateReqVO.getAssigneeUserIds() != null) {
+ updateObj.setAssigneeUserIds(joinUserIds(updateReqVO.getAssigneeUserIds()));
+ }
+ if (updateReqVO.getProcessId() != null && !updateReqVO.getProcessId().equals(task.getProcessId())) {
+ if (feedbackMapper.selectCountByTaskId(task.getId()) > 0) throw exception(PRO_TASK_HAS_FEEDBACK);
+ freezeTaskParamConfig(updateObj);
+ }
taskMapper.updateById(updateObj);
+ synchronizeScheduledQuantity(workOrderService.validateWorkOrderExists(candidate.getWorkOrderId()), candidate.getRouteId());
+ if (!java.util.Objects.equals(task.getWorkOrderId(), candidate.getWorkOrderId())) synchronizeScheduledQuantity(workOrderService.validateWorkOrderExists(task.getWorkOrderId()), task.getRouteId());
+ }
+
+ private void synchronizeScheduledQuantity(MesProWorkOrderDO order, Long routeId) {
+ if (!java.util.Objects.equals(order.getType(), cn.iocoder.yudao.module.mes.enums.pro.MesProWorkOrderTypeEnum.SELF.getType()) || order.getQuantity() == null || routeId == null) return;
+ List<MesProRouteProcessDO> required = buildRouteProcessList(routeId, order.getId());
+ List<MesProTaskDO> tasks = taskMapper.selectListByWorkOrderId(order.getId());
+ BigDecimal scheduled = required.isEmpty() ? BigDecimal.ZERO : order.getQuantity();
+ for (var process : required) {
+ BigDecimal amount = tasks.stream().filter(task -> java.util.Objects.equals(task.getProcessId(), process.getProcessId())
+ && !java.util.Objects.equals(task.getStatus(), MesProTaskStatusEnum.CANCELED.getStatus()))
+ .map(task -> task.getQuantity() == null ? BigDecimal.ZERO : task.getQuantity()).reduce(BigDecimal.ZERO, BigDecimal::add);
+ scheduled = scheduled.min(amount);
+ }
+ scheduleWorkOrderMapper.updateById(new MesProWorkOrderDO().setId(order.getId()).setQuantityScheduled(scheduled));
+ }
+
+ /** 浠庡伐搴忓拰妯℃澘澶嶅埗瀹氫箟锛屽悗缁ā鏉跨淮鎶や笉鏀瑰彉宸叉帓浜т换鍔°�� */
+ private void freezeTaskParamConfig(MesProTaskDO task) {
+ var process = processService.getProcess(task.getProcessId());
+ if (process == null) throw exception(cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_PROCESS_NOT_EXISTS);
+ int mode = process.getParamCollectMode() == null ? 0 : process.getParamCollectMode();
+ task.setParamCollectMode(mode);
+ task.setParamTemplateSnapshot("");
+ task.setParamSharedSnapshot("");
+ if (mode == 0) return;
+ if ((mode != 1 && mode != 2) || process.getParamTemplateId() == null)
+ throw exception(cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_PROCESS_PARAM_CONFIG_INVALID);
+ var template = paramTemplateService.validateProcessParamTemplateExists(process.getParamTemplateId());
+ var details = paramTemplateService.getProcessParamTemplateDetailListByTemplateId(template.getId());
+ if (CollUtil.isEmpty(details)) throw exception(cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_WORK_ORDER_PARAM_RECORD_TEMPLATE_NO_DETAIL);
+ MesTaskParamSnapshot snapshot = new MesTaskParamSnapshot();
+ snapshot.setTemplateId(template.getId());
+ snapshot.setTemplateCode(template.getTemplateCode());
+ snapshot.setTemplateName(template.getTemplateName());
+ List<MesTaskParamSnapshot.Detail> frozenDetails = BeanUtils.toBean(details, MesTaskParamSnapshot.Detail.class);
+ for (MesTaskParamSnapshot.Detail detail : frozenDetails) {
+ if (detail.getUnitMeasureId() != null) {
+ var unit = unitMeasureService.getUnitMeasure(detail.getUnitMeasureId());
+ if (unit != null) detail.setUnitMeasureName(unit.getName());
+ }
+ }
+ snapshot.setDetails(frozenDetails);
+ task.setParamTemplateSnapshot(JsonUtils.toJsonString(snapshot));
+ }
+
+ /**
+ * 鏍¢獙鐝粍瀛樺湪骞跺洖濉彮缁勫悕绉�
+ */
+ private void fillTeamInfo(MesProTaskSaveReqVO reqVO) {
+ if (reqVO.getTeamId() == null) {
+ return;
+ }
+ MesCalTeamDO team = teamService.validateTeamExists(reqVO.getTeamId());
+ if (team != null) {
+ reqVO.setTeamName(team.getName());
+ }
+ }
+
+ /**
+ * 鑾峰緱宸ヤ綔绔欓厤缃矖浣嶅搴旂殑鍛樺伐缂栧彿
+ */
+ private List<Long> getWorkstationWorkerUserIds(Long workstationId) {
+ if (workstationId == null) {
+ return Collections.emptyList();
+ }
+ List<MesMdWorkstationWorkerDO> workers = workstationWorkerService
+ .getWorkstationWorkerListByWorkstationId(workstationId);
+ if (CollUtil.isEmpty(workers)) {
+ return Collections.emptyList();
+ }
+ Set<Long> postIds = convertSet(workers, MesMdWorkstationWorkerDO::getPostId);
+ if (CollUtil.isEmpty(postIds)) {
+ return Collections.emptyList();
+ }
+ return convertList(adminUserApi.getUserListByPostIds(postIds), AdminUserRespDTO::getId);
+ }
+
+ /**
+ * 灏嗘姤宸ヤ汉鐢ㄦ埛缂栧彿鍒楄〃鎷兼帴涓洪�楀彿鍒嗛殧瀛楃涓�
+ *
+ * @return null 琛ㄧず涓嶄慨鏀�/涓嶉檺鍒讹紱绌哄瓧绗︿覆琛ㄧず娓呯┖闄愬埗
+ */
+ private String joinUserIds(List<Long> userIds) {
+ if (userIds == null) {
+ return null;
+ }
+ return userIds.stream().filter(java.util.Objects::nonNull).distinct()
+ .map(String::valueOf).collect(java.util.stream.Collectors.joining(","));
}
/**
@@ -226,21 +388,52 @@
return routeProcesses;
}
+ /**
+ * 浠诲姟浜у嚭鐗╂枡锛氫紭鍏堝彇宸ュ簭鍦ㄥ綋鍓嶄骇鍝佷笅鐨勪骇鍑猴紙鎸夊綊灞炶繃婊わ級锛屾病鏈変骇鍑烘椂鍙栧伐鍗曟垚鍝�
+ */
+ private Long resolveTaskItemId(MesProRouteProcessDO routeProcess, Long productId) {
+ if (routeProcess == null) {
+ return productId;
+ }
+ if (routeProcess.getId() != null) {
+ // 宸ヨ壓璺嚎妯℃澘锛氭寜浜у嚭褰掑睘杩囨护鍑哄綋鍓嶄骇鍝佺殑浜у嚭
+ List<Long> outputIds = routeProcessService
+ .getOutputItemIdsByRouteProcessId(routeProcess.getId(), productId);
+ if (outputIds != null) {
+ // 鏈夊綊灞為厤缃細璇ヤ骇鍝佹棤浜у嚭鏃跺彇宸ュ崟鎴愬搧锛沶ull 琛ㄧず瀛橀噺鏃犲綊灞炴暟鎹紝缁х画璧拌仛鍚堝厹搴�
+ return CollUtil.isNotEmpty(outputIds) ? outputIds.get(0) : productId;
+ }
+ }
+ // 宸ュ崟宸ュ簭蹇収 / 瀛橀噺鏃犲綊灞炴暟鎹細浜у嚭宸叉寜浜у搧杩囨护锛屽彇绗竴涓�
+ String outputItemId = routeProcess.getOutputItemId();
+ if (outputItemId != null && !outputItemId.isBlank()) {
+ return Long.valueOf(outputItemId.split(",")[0].trim());
+ }
+ return productId;
+ }
+
@Override
+ @Transactional(rollbackFor = Exception.class)
public void deleteTask(Long id) {
- // 1. 鏍¢獙瀛樺湪涓旈潪缁堟��
- validateTaskNotFinished(id);
+ scheduleGuard.lock();
+ MesProTaskDO task = validateTaskNotFinished(id);
// 2. 鏍¢獙浠诲姟涓嬫棤鎶ュ伐璁板綍锛岄伩鍏嶅垹闄ゅ悗鎶ュ伐杩芥函鏂摼
if (feedbackMapper.selectCountByTaskId(id) > 0) {
throw exception(PRO_TASK_HAS_FEEDBACK);
}
// 3. 鍒犻櫎
taskMapper.deleteById(id);
+ synchronizeScheduledQuantity(workOrderService.validateWorkOrderExists(task.getWorkOrderId()), task.getRouteId());
}
@Override
public MesProTaskDO getTask(Long id) {
return taskMapper.selectById(id);
+ }
+
+ @Override
+ public MesProTaskDO getTaskByCode(String code) {
+ return taskMapper.selectByCode(code);
}
@Override
@@ -251,6 +444,20 @@
@Override
public PageResult<MesProTaskDO> getPendingFeedbackPage(MesProTaskPageReqVO pageReqVO) {
return taskMapper.selectPendingFeedbackPage(pageReqVO);
+ }
+
+ @Override
+ public Map<Long, Long> getPendingFeedbackCountByWorkstation(Long assigneeUserId) {
+ List<Map<String, Object>> rows = taskMapper.selectPendingFeedbackCountByWorkstation(assigneeUserId);
+ Map<Long, Long> result = new HashMap<>(rows.size());
+ for (Map<String, Object> row : rows) {
+ Object workstationId = row.get("workstation_id");
+ Object count = row.get("pending_count");
+ if (workstationId instanceof Number && count instanceof Number) {
+ result.put(((Number) workstationId).longValue(), ((Number) count).longValue());
+ }
+ }
+ return result;
}
@Override
@@ -391,6 +598,7 @@
@Override
@Transactional(rollbackFor = Exception.class)
public List<Long> autoGenerateTasks(MesProTaskAutoGenerateReqVO reqVO) {
+ scheduleGuard.lock();
// 1. 鏍¢獙宸ュ崟宸茬‘璁�
MesProWorkOrderDO workOrder = workOrderService.validateWorkOrderConfirmed(reqVO.getWorkOrderId());
// 2. 纭畾宸ヨ壓璺嚎锛氫紭鍏堣姹傛寚瀹� 鈫� 宸ュ崟鍏宠仈 鈫� 浜у搧鍏宠仈
@@ -408,7 +616,7 @@
List<Long> taskIds = new java.util.ArrayList<>();
for (MesProRouteProcessDO rp : routeProcesses) {
cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO proc = procMap.get(rp.getProcessId());
- Long itemId = rp.getOutputItemId() != null ? Long.valueOf(rp.getOutputItemId().split(",")[0].trim()) : workOrder.getProductId();
+ Long itemId = resolveTaskItemId(rp, workOrder.getProductId());
cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO item = itemService.validateItemExists(itemId);
MesProTaskDO task = new MesProTaskDO()
.setWorkOrderId(workOrder.getId())
@@ -421,6 +629,8 @@
.setStatus(MesProTaskStatusEnum.PREPARE.getStatus())
.setClientId(workOrder.getClientId())
.setColorCode(rp.getColorCode());
+ scheduleGuard.validate(workOrder, task, null);
+ freezeTaskParamConfig(task);
taskMapper.insert(task);
taskIds.add(task.getId());
}
@@ -429,4 +639,56 @@
return taskIds;
}
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void pauseTask(MesProTaskPauseReqVO pauseReqVO) {
+ // 1. 鏍¢獙浠诲姟瀛樺湪
+ MesProTaskDO task = validateTaskExists(pauseReqVO.getId());
+ // 2. 鏍¢獙鐘舵�佹槸鍚﹀厑璁稿仠宸ワ紙濡傚繀椤绘槸 鐢熶骇涓� 鎴� 閮ㄥ垎瀹屾垚锛�
+ if (!ObjectUtils.equalsAny(task.getStatus(), MesProTaskStatusEnum.PRODUCING.getStatus(),
+ MesProTaskStatusEnum.PARTIAL_FINISHED.getStatus())) {
+ throw exception(PRO_TASK_CANNOT_PAUSE);
+ }
+
+ // 3. 淇敼浠诲姟鐘舵�佷负宸插仠宸�
+ taskMapper.updateById(new MesProTaskDO().setId(task.getId()).setStatus(MesProTaskStatusEnum.PAUSED.getStatus()));
+
+ // 4. 鍒涘缓鍋滃伐璁板綍
+ MesProTaskPauseRecordDO pauseRecord = new MesProTaskPauseRecordDO()
+ .setTaskId(task.getId())
+ .setWorkOrderId(task.getWorkOrderId())
+ .setWorkstationId(task.getWorkstationId())
+ .setReason(pauseReqVO.getReason())
+ .setRemark(pauseReqVO.getRemark())
+ .setPauseTime(LocalDateTime.now())
+ .setPauseUserId(SecurityFrameworkUtils.getLoginUserId());
+ taskPauseRecordMapper.insert(pauseRecord);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void resumeTask(MesProTaskResumeReqVO resumeReqVO) {
+ // 1. 鏍¢獙浠诲姟瀛樺湪
+ MesProTaskDO task = validateTaskExists(resumeReqVO.getId());
+ // 2. 鏍¢獙鐘舵�佸繀椤绘槸宸插仠宸�
+ if (!ObjectUtils.equalsAny(task.getStatus(), MesProTaskStatusEnum.PAUSED.getStatus())) {
+ throw exception(PRO_TASK_NOT_PAUSED);
+ }
+
+ // 3. 鎭㈠浠诲姟鐘舵��
+ Integer resumeStatus = task.getProducedQuantity() != null
+ && task.getProducedQuantity().signum() > 0
+ ? MesProTaskStatusEnum.PARTIAL_FINISHED.getStatus()
+ : MesProTaskStatusEnum.PRODUCING.getStatus();
+ taskMapper.updateById(new MesProTaskDO().setId(task.getId()).setStatus(resumeStatus));
+
+ // 4. 鏇存柊鏈�鏂扮殑涓�鏉″仠宸ヨ褰�
+ MesProTaskPauseRecordDO pauseRecord = taskPauseRecordMapper.selectLastUnresumedByTaskId(task.getId());
+ if (pauseRecord != null) {
+ pauseRecord.setResumeTime(LocalDateTime.now());
+ pauseRecord.setResumeUserId(SecurityFrameworkUtils.getLoginUserId());
+ taskPauseRecordMapper.updateById(pauseRecord);
+ }
+ }
+
}
--
Gitblit v1.9.3