Commit 5c5776961f62f1600544b80d52fb5202bded8fbc

Authored by YunaiV
1 parent 5c60fab8

✨ feat(mes): 添加生产任务状态校验和反馈数据验证逻辑

新增对生产任务状态的校验,确保任务未完成时才能进行报工操作。同时,优化报工数据的验证逻辑,确保输入的数量符合业务要求,提升系统的健壮性和用户体验。
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/MesProFeedbackController.java
@@ -55,25 +55,18 @@ public class MesProFeedbackController { @@ -55,25 +55,18 @@ public class MesProFeedbackController {
55 55
56 @Resource 56 @Resource
57 private MesProFeedbackService feedbackService; 57 private MesProFeedbackService feedbackService;
58 -  
59 @Resource 58 @Resource
60 private MesMdWorkstationService workstationService; 59 private MesMdWorkstationService workstationService;
61 -  
62 @Resource 60 @Resource
63 private MesProRouteService routeService; 61 private MesProRouteService routeService;
64 -  
65 @Resource 62 @Resource
66 private MesProProcessService processService; 63 private MesProProcessService processService;
67 -  
68 @Resource 64 @Resource
69 private MesProWorkOrderService workOrderService; 65 private MesProWorkOrderService workOrderService;
70 -  
71 @Resource 66 @Resource
72 private MesMdItemService itemService; 67 private MesMdItemService itemService;
73 -  
74 @Resource 68 @Resource
75 private MesMdUnitMeasureService unitMeasureService; 69 private MesMdUnitMeasureService unitMeasureService;
76 -  
77 @Resource 70 @Resource
78 private MesProRouteProcessService routeProcessService; 71 private MesProRouteProcessService routeProcessService;
79 72
@@ -226,6 +219,7 @@ public class MesProFeedbackController { @@ -226,6 +219,7 @@ public class MesProFeedbackController {
226 findAndThen(workOrderMap, vo.getWorkOrderId(), wo -> 219 findAndThen(workOrderMap, vo.getWorkOrderId(), wo ->
227 vo.setWorkOrderCode(wo.getCode()).setWorkOrderName(wo.getName())); 220 vo.setWorkOrderCode(wo.getCode()).setWorkOrderName(wo.getName()));
228 // TODO @芋艿:task code 待 pro_task 服务迁移后补充 221 // TODO @芋艿:task code 待 pro_task 服务迁移后补充
  222 + // TODO @AI:貌似已经支持,可以跟进下
229 // 物料、计量单位 223 // 物料、计量单位
230 findAndThen(itemMap, vo.getItemId(), item -> 224 findAndThen(itemMap, vo.getItemId(), item ->
231 vo.setItemCode(item.getCode()).setItemName(item.getName()).setItemSpec(item.getSpecification())); 225 vo.setItemCode(item.getCode()).setItemName(item.getName()).setItemSpec(item.getSpecification()));
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java
@@ -226,6 +226,7 @@ public interface ErrorCodeConstants { @@ -226,6 +226,7 @@ public interface ErrorCodeConstants {
226 226
227 // ========== MES 生产管理-生产任务(1-040-503-000) ========== 227 // ========== MES 生产管理-生产任务(1-040-503-000) ==========
228 ErrorCode PRO_TASK_NOT_EXISTS = new ErrorCode(1_040_503_000, "生产任务不存在"); 228 ErrorCode PRO_TASK_NOT_EXISTS = new ErrorCode(1_040_503_000, "生产任务不存在");
  229 + ErrorCode PRO_TASK_ALREADY_FINISHED = new ErrorCode(1_040_503_001, "生产任务已完成或已取消,不能继续操作");
229 230
230 // ========== MES 生产管理-安灯呼叫配置(1-040-504-000) ========== 231 // ========== MES 生产管理-安灯呼叫配置(1-040-504-000) ==========
231 ErrorCode PRO_ANDON_CONFIG_NOT_EXISTS = new ErrorCode(1_040_504_000, "安灯呼叫配置不存在"); 232 ErrorCode PRO_ANDON_CONFIG_NOT_EXISTS = new ErrorCode(1_040_504_000, "安灯呼叫配置不存在");
@@ -245,6 +246,10 @@ public interface ErrorCodeConstants { @@ -245,6 +246,10 @@ public interface ErrorCodeConstants {
245 ErrorCode PRO_FEEDBACK_STATUS_ERROR = new ErrorCode(1_040_506_005, "报工单状态不正确,无法执行此操作"); 246 ErrorCode PRO_FEEDBACK_STATUS_ERROR = new ErrorCode(1_040_506_005, "报工单状态不正确,无法执行此操作");
246 ErrorCode PRO_FEEDBACK_WORK_ORDER_NOT_CONFIRMED = new ErrorCode(1_040_506_006, "关联的工单未确认,无法创建报工"); 247 ErrorCode PRO_FEEDBACK_WORK_ORDER_NOT_CONFIRMED = new ErrorCode(1_040_506_006, "关联的工单未确认,无法创建报工");
247 ErrorCode PRO_FEEDBACK_QUALIFIED_UNQUALIFIED_MISMATCH = new ErrorCode(1_040_506_007, "合格品数量与不良品数量之和必须等于报工数量"); 248 ErrorCode PRO_FEEDBACK_QUALIFIED_UNQUALIFIED_MISMATCH = new ErrorCode(1_040_506_007, "合格品数量与不良品数量之和必须等于报工数量");
  249 + ErrorCode PRO_FEEDBACK_ROUTE_PROCESS_INVALID = new ErrorCode(1_040_506_008, "未找到对应的工艺工序配置,请检查工艺路线与工序");
  250 + ErrorCode PRO_FEEDBACK_TASK_OR_ORDER_FINISHED = new ErrorCode(1_040_506_009, "当前生产任务或工单已完成,不能继续报工");
  251 + ErrorCode PRO_FEEDBACK_QUANTITY_MUST_POSITIVE = new ErrorCode(1_040_506_010, "报工数量必须大于 0");
  252 + ErrorCode PRO_FEEDBACK_QUALIFIED_UNQUALIFIED_REQUIRED = new ErrorCode(1_040_506_011, "请输入合格品和不良品数量,且合计须大于 0");
248 253
249 // ========== MES 生产管理-生产流转卡(1-040-507-000) ========== 254 // ========== MES 生产管理-生产流转卡(1-040-507-000) ==========
250 ErrorCode PRO_CARD_NOT_EXISTS = new ErrorCode(1_040_507_000, "生产流转卡不存在"); 255 ErrorCode PRO_CARD_NOT_EXISTS = new ErrorCode(1_040_507_000, "生产流转卡不存在");
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImpl.java
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.mes.service.pro.feedback; @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.mes.service.pro.feedback;
2 2
3 import cn.hutool.core.util.BooleanUtil; 3 import cn.hutool.core.util.BooleanUtil;
4 import cn.hutool.core.util.ObjUtil; 4 import cn.hutool.core.util.ObjUtil;
  5 +import cn.hutool.core.util.ObjectUtil;
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 7 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
7 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; 8 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
@@ -11,13 +12,17 @@ import cn.iocoder.yudao.module.mes.dal.dataobject.pro.feedback.MesProFeedbackDO; @@ -11,13 +12,17 @@ import cn.iocoder.yudao.module.mes.dal.dataobject.pro.feedback.MesProFeedbackDO;
11 import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProcessDO; 12 import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProcessDO;
12 import cn.iocoder.yudao.module.mes.dal.mysql.pro.feedback.MesProFeedbackMapper; 13 import cn.iocoder.yudao.module.mes.dal.mysql.pro.feedback.MesProFeedbackMapper;
13 import cn.iocoder.yudao.module.mes.enums.pro.MesProFeedbackStatusEnum; 14 import cn.iocoder.yudao.module.mes.enums.pro.MesProFeedbackStatusEnum;
  15 +import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService;
14 import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteProcessService; 16 import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteProcessService;
  17 +import cn.iocoder.yudao.module.mes.service.pro.task.MesProTaskService;
15 import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; 18 import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService;
16 import jakarta.annotation.Resource; 19 import jakarta.annotation.Resource;
  20 +import org.springframework.context.annotation.Lazy;
17 import org.springframework.stereotype.Service; 21 import org.springframework.stereotype.Service;
18 import org.springframework.transaction.annotation.Transactional; 22 import org.springframework.transaction.annotation.Transactional;
19 import org.springframework.validation.annotation.Validated; 23 import org.springframework.validation.annotation.Validated;
20 24
  25 +import java.math.BigDecimal;
21 import java.time.LocalDateTime; 26 import java.time.LocalDateTime;
22 27
23 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 28 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -42,23 +47,31 @@ public class MesProFeedbackServiceImpl implements MesProFeedbackService { @@ -42,23 +47,31 @@ public class MesProFeedbackServiceImpl implements MesProFeedbackService {
42 @Resource 47 @Resource
43 private MesProRouteProcessService routeProcessService; 48 private MesProRouteProcessService routeProcessService;
44 49
  50 + @Resource
  51 + private MesMdWorkstationService workstationService;
  52 +
  53 + @Resource
  54 + @Lazy // 避免循环依赖
  55 + private MesProTaskService taskService;
  56 +
45 @Override 57 @Override
46 public Long createFeedback(MesProFeedbackSaveReqVO createReqVO) { 58 public Long createFeedback(MesProFeedbackSaveReqVO createReqVO) {
47 - // 1. 校验工单已确认  
48 - workOrderService.validateWorkOrderConfirmed(createReqVO.getWorkOrderId());  
49 - // TODO @芋艿:校验 pro_task 存在且未完成(待 pro_task 服务迁移) 59 + // 1. 校验
  60 + validateFeedbackData(createReqVO);
50 61
51 // 2. 插入 62 // 2. 插入
52 - MesProFeedbackDO feedback = BeanUtils.toBean(createReqVO, MesProFeedbackDO.class);  
53 - feedback.setStatus(MesProFeedbackStatusEnum.PREPARE.getStatus()); 63 + MesProFeedbackDO feedback = BeanUtils.toBean(createReqVO, MesProFeedbackDO.class)
  64 + .setStatus(MesProFeedbackStatusEnum.PREPARE.getStatus());
54 feedbackMapper.insert(feedback); 65 feedbackMapper.insert(feedback);
55 return feedback.getId(); 66 return feedback.getId();
56 } 67 }
57 68
58 @Override 69 @Override
59 public void updateFeedback(MesProFeedbackSaveReqVO updateReqVO) { 70 public void updateFeedback(MesProFeedbackSaveReqVO updateReqVO) {
60 - // 1. 校验存在 + 草稿状态 71 + // 1.1 校验存在 + 草稿状态
61 validateFeedbackStatusPrepare(updateReqVO.getId()); 72 validateFeedbackStatusPrepare(updateReqVO.getId());
  73 + // 1.2 校验业务数据
  74 + validateFeedbackData(updateReqVO);
62 75
63 // 2. 更新 76 // 2. 更新
64 MesProFeedbackDO updateObj = BeanUtils.toBean(updateReqVO, MesProFeedbackDO.class); 77 MesProFeedbackDO updateObj = BeanUtils.toBean(updateReqVO, MesProFeedbackDO.class);
@@ -173,6 +186,45 @@ public class MesProFeedbackServiceImpl implements MesProFeedbackService { @@ -173,6 +186,45 @@ public class MesProFeedbackServiceImpl implements MesProFeedbackService {
173 } 186 }
174 187
175 /** 188 /**
  189 + * 校验报工单的业务数据(创建 & 修改共用)
  190 + *
  191 + * @param reqVO 报工请求
  192 + */
  193 + private void validateFeedbackData(MesProFeedbackSaveReqVO reqVO) {
  194 + // 1. 校验工作站存在
  195 + workstationService.validateWorkstationExists(reqVO.getWorkstationId());
  196 +
  197 + // 2.1 校验工艺路线 + 工序配置有效
  198 + MesProRouteProcessDO routeProcess = routeProcessService.getRouteProcessByRouteIdAndProcessId(
  199 + reqVO.getRouteId(), reqVO.getProcessId());
  200 + if (routeProcess == null) {
  201 + throw exception(PRO_FEEDBACK_ROUTE_PROCESS_INVALID);
  202 + }
  203 + // 2.2 校验数量
  204 + boolean checkFlag = Boolean.TRUE.equals(routeProcess.getCheckFlag());
  205 + if (checkFlag) {
  206 + // 需要检验:只需填报工数量,且必须 > 0
  207 + if (reqVO.getFeedbackQuantity() == null
  208 + || reqVO.getFeedbackQuantity().compareTo(BigDecimal.ZERO) <= 0) {
  209 + throw exception(PRO_FEEDBACK_QUANTITY_MUST_POSITIVE);
  210 + }
  211 + } else {
  212 + // 不需检验:需填合格品 + 不良品数量,合计 > 0
  213 + BigDecimal qualified = ObjectUtil.defaultIfNull(reqVO.getQualifiedQuantity(), BigDecimal.ZERO);
  214 + BigDecimal unqualified = ObjectUtil.defaultIfNull(reqVO.getUnqualifiedQuantity(), BigDecimal.ZERO);
  215 + if (qualified.add(unqualified).compareTo(BigDecimal.ZERO) <= 0) {
  216 + throw exception(PRO_FEEDBACK_QUALIFIED_UNQUALIFIED_REQUIRED);
  217 + }
  218 + }
  219 +
  220 + // 3. 校验工单已确认
  221 + workOrderService.validateWorkOrderConfirmed(reqVO.getWorkOrderId());
  222 +
  223 + // 4. 校验任务存在且未终态(已完成/已取消)
  224 + taskService.validateTaskNotFinished(reqVO.getTaskId());
  225 + }
  226 +
  227 + /**
176 * 获取指定工艺路线中指定工序的 checkFlag 228 * 获取指定工艺路线中指定工序的 checkFlag
177 * 229 *
178 * @param routeId 工艺路线编号 230 * @param routeId 工艺路线编号
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskService.java
@@ -82,6 +82,14 @@ public interface MesProTaskService { @@ -82,6 +82,14 @@ public interface MesProTaskService {
82 MesProTaskDO validateTaskExists(Long id); 82 MesProTaskDO validateTaskExists(Long id);
83 83
84 /** 84 /**
  85 + * 校验任务存在且未完成(非终态)
  86 + *
  87 + * @param id 编号
  88 + * @return 生产任务
  89 + */
  90 + MesProTaskDO validateTaskNotFinished(Long id);
  91 +
  92 + /**
85 * 获得生产任务列表 93 * 获得生产任务列表
86 * 94 *
87 * @param ids 编号列表 95 * @param ids 编号列表
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskServiceImpl.java
@@ -29,6 +29,7 @@ import java.util.List; @@ -29,6 +29,7 @@ import java.util.List;
29 29
30 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 30 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
31 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; 31 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
  32 +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_TASK_ALREADY_FINISHED;
32 import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_TASK_NOT_EXISTS; 33 import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_TASK_NOT_EXISTS;
33 34
34 /** 35 /**
@@ -152,6 +153,15 @@ public class MesProTaskServiceImpl implements MesProTaskService { @@ -152,6 +153,15 @@ public class MesProTaskServiceImpl implements MesProTaskService {
152 } 153 }
153 154
154 @Override 155 @Override
  156 + public MesProTaskDO validateTaskNotFinished(Long id) {
  157 + MesProTaskDO task = validateTaskExists(id);
  158 + if (MesProTaskStatusEnum.isEndStatus(task.getStatus())) {
  159 + throw exception(PRO_TASK_ALREADY_FINISHED);
  160 + }
  161 + return task;
  162 + }
  163 +
  164 + @Override
155 public List<MesProTaskDO> getTaskList(Collection<Long> ids) { 165 public List<MesProTaskDO> getTaskList(Collection<Long> ids) {
156 return taskMapper.selectByIds(ids); 166 return taskMapper.selectByIds(ids);
157 } 167 }