diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/MesProFeedbackController.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/MesProFeedbackController.java index c7ab6b9..ac9afe3 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/MesProFeedbackController.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/MesProFeedbackController.java @@ -17,6 +17,7 @@ import cn.iocoder.yudao.module.mes.dal.dataobject.pro.feedback.MesProFeedbackDO; import cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO; import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteDO; import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProcessDO; +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.service.md.item.MesMdItemService; import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService; @@ -25,6 +26,7 @@ import cn.iocoder.yudao.module.mes.service.pro.feedback.MesProFeedbackService; import cn.iocoder.yudao.module.mes.service.pro.process.MesProProcessService; import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteProcessService; import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteService; +import cn.iocoder.yudao.module.mes.service.pro.task.MesProTaskService; import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; @@ -69,6 +71,8 @@ public class MesProFeedbackController { private MesMdUnitMeasureService unitMeasureService; @Resource private MesProRouteProcessService routeProcessService; + @Resource + private MesProTaskService taskService; @Resource private AdminUserApi adminUserApi; @@ -147,22 +151,12 @@ public class MesProFeedbackController { return success(true); } - @PutMapping("/finish") - @Operation(summary = "执行报工") + @PutMapping("/approve") + @Operation(summary = "审批报工") @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('mes:pro-feedback:finish')") - public CommonResult finishFeedback(@RequestParam("id") Long id) { - feedbackService.finishFeedback(id); - return success(true); - } - - @PutMapping("/cancel") - @Operation(summary = "取消报工") - @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('mes:pro-feedback:update')") - public CommonResult cancelFeedback(@RequestParam("id") Long id) { - feedbackService.cancelFeedback(id); - return success(true); + @PreAuthorize("@ss.hasPermission('mes:pro-feedback:approve')") + public CommonResult approveFeedback(@RequestParam("id") Long id) { + return success(feedbackService.approveFeedback(id)); } // ==================== 拼接 VO ==================== @@ -171,24 +165,27 @@ public class MesProFeedbackController { if (CollUtil.isEmpty(list)) { return Collections.emptyList(); } - // 1.1 物料、计量单位 + // 1.1 任务(获取 taskCode) + Map taskMap = taskService.getTaskMap( + convertSet(list, MesProFeedbackDO::getTaskId)); + // 1.2 物料(直接从 DO.itemId)、计量单位(从 item.unitMeasureId) Map itemMap = itemService.getItemMap( convertSet(list, MesProFeedbackDO::getItemId)); Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( - convertSet(list, MesProFeedbackDO::getUnitMeasureId)); - // 1.2 工单 + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + // 1.3 工单 Map workOrderMap = workOrderService.getWorkOrderMap( convertSet(list, MesProFeedbackDO::getWorkOrderId)); - // 1.3 工作站 + // 1.4 工作站 Map workstationMap = workstationService.getWorkstationMap( convertSet(list, MesProFeedbackDO::getWorkstationId)); - // 1.4 工艺路线 + // 1.5 工艺路线 Set routeIds = convertSet(list, MesProFeedbackDO::getRouteId); Map routeMap = routeService.getRouteMap(routeIds); - // 1.5 工序 + // 1.6 工序 Map processMap = processService.getProcessMap( new ArrayList<>(convertSet(list, MesProFeedbackDO::getProcessId))); - // 1.6 工序的 checkFlag:批量查询后直接构建 routeId -> processId -> checkFlag 的双层 Map + // 1.7 工序的 checkFlag:批量查询后直接构建 routeId -> processId -> checkFlag 的双层 Map List allRouteProcesses = routeProcessService.getRouteProcessListByRouteIds(routeIds); Map> routeProcessCheckFlagMap = new HashMap<>(); for (MesProRouteProcessDO rp : allRouteProcesses) { @@ -196,7 +193,7 @@ public class MesProFeedbackController { .computeIfAbsent(rp.getRouteId(), k -> new HashMap<>()) .put(rp.getProcessId(), Boolean.TRUE.equals(rp.getCheckFlag())); } - // 1.7 报工人/审核人 + // 1.8 报工人/审核人 Map userMap = adminUserApi.getUserMap( convertSetByFlatMap(list, feedback -> Stream.of(feedback.getFeedbackUserId(), feedback.getApproveUserId()))); @@ -218,13 +215,17 @@ public class MesProFeedbackController { // 工单 findAndThen(workOrderMap, vo.getWorkOrderId(), wo -> vo.setWorkOrderCode(wo.getCode()).setWorkOrderName(wo.getName())); - // TODO @芋艿:task code 待 pro_task 服务迁移后补充 - // TODO @AI:貌似已经支持,可以跟进下 - // 物料、计量单位 - findAndThen(itemMap, vo.getItemId(), item -> - vo.setItemCode(item.getCode()).setItemName(item.getName()).setItemSpec(item.getSpecification())); - findAndThen(unitMeasureMap, vo.getUnitMeasureId(), unit -> - vo.setUnitMeasureName(unit.getName())); + // 任务 + findAndThen(taskMap, vo.getTaskId(), task -> + vo.setTaskCode(task.getCode())); + // 物料 → 单位 + findAndThen(itemMap, vo.getItemId(), item -> { + // TODO @AI:specification 全称 + vo.setItemCode(item.getCode()).setItemName(item.getName()).setItemSpec(item.getSpecification()) + .setUnitMeasureId(item.getUnitMeasureId()); + findAndThen(unitMeasureMap, item.getUnitMeasureId(), unit -> + vo.setUnitMeasureName(unit.getName())); + }); // 报工人、审核人 findAndThen(userMap, vo.getFeedbackUserId(), user -> vo.setFeedbackUserNickname(user.getNickname())); diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/vo/MesProFeedbackRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/vo/MesProFeedbackRespVO.java index ba5bd85..425cbb0 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/vo/MesProFeedbackRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/vo/MesProFeedbackRespVO.java @@ -110,10 +110,6 @@ public class MesProFeedbackRespVO { @Schema(description = "过期日期") private LocalDateTime expireDate; - @Schema(description = "批次号", example = "B20250315001") - @ExcelProperty("批次号") - private String batchCode; - @Schema(description = "排产数量", example = "5000.00") @ExcelProperty("排产数量") private BigDecimal scheduledQuantity; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/vo/MesProFeedbackSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/vo/MesProFeedbackSaveReqVO.java index 2f548d7..8e9e746 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/vo/MesProFeedbackSaveReqVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/vo/MesProFeedbackSaveReqVO.java @@ -22,9 +22,6 @@ public class MesProFeedbackSaveReqVO { @NotNull(message = "报工类型不能为空") private Integer type; - @Schema(description = "报工途径", example = "PC") - private String channel; - @Schema(description = "工作站编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @NotNull(message = "工作站不能为空") private Long workstationId; @@ -45,20 +42,9 @@ public class MesProFeedbackSaveReqVO { @NotNull(message = "生产任务不能为空") private Long taskId; - @Schema(description = "产品物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "75") - @NotNull(message = "产品物料不能为空") - private Long itemId; - - @Schema(description = "单位编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "202") - @NotNull(message = "单位不能为空") - private Long unitMeasureId; - @Schema(description = "过期日期") private LocalDateTime expireDate; - @Schema(description = "批次号", example = "B20250315001") - private String batchCode; - @Schema(description = "排产数量", example = "5000.00") private BigDecimal scheduledQuantity; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/feedback/MesProFeedbackDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/feedback/MesProFeedbackDO.java index 6767c80..f56e012 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/feedback/MesProFeedbackDO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/feedback/MesProFeedbackDO.java @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.mes.dal.dataobject.pro.feedback; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 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.MesMdWorkstationDO; import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteDO; import cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO; @@ -47,6 +46,7 @@ public class MesProFeedbackDO extends BaseDO { * 枚举 {@link MesProFeedbackTypeEnum} */ private Integer type; + // TODO @芋艿:这个字段,暂时没使用到; /** * 报工途径 * @@ -87,26 +87,16 @@ public class MesProFeedbackDO extends BaseDO { */ private Long taskId; /** - * 产品物料编号 + * 产品物料编号(冗余自任务) * * 关联 {@link MesMdItemDO#getId()} */ private Long itemId; /** - * 单位编号 - * - * 关联 {@link MesMdUnitMeasureDO#getId()} - */ - private Long unitMeasureId; - /** * 过期日期 */ private LocalDateTime expireDate; /** - * 批次号 - */ - private String batchCode; - /** * 排产数量 */ private BigDecimal scheduledQuantity; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProFeedbackStatusEnum.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProFeedbackStatusEnum.java index 4cc821f..d1d62f3 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProFeedbackStatusEnum.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProFeedbackStatusEnum.java @@ -14,7 +14,6 @@ import java.util.Arrays; * 2. 草稿 → 提交 → 审批中(APPROVING) * 3. 审批中 → 驳回 → 草稿(PREPARE) * 4. 审批中 → 执行 → 待检验(UNCHECK)或已完成(FINISHED),取决于工序 checkFlag - * 5. 草稿/审批中 → 取消 → 已取消(CANCELED) * * @author 芋道源码 */ @@ -22,11 +21,15 @@ import java.util.Arrays; @AllArgsConstructor public enum MesProFeedbackStatusEnum implements ArrayValuable { + // TODO @AI:数据库的字典,需要迁移; + + // TODO @AI:对齐下 /Users/yunai/Java/yudao-all-in-one/ruoyi-vue-pro/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/MesOrderStatusConstants.java + + // TODO @AI:整体注释,变量注释,对齐 /Users/yunai/Java/yudao-all-in-one/ruoyi-vue-pro/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProTaskStatusEnum.java PREPARE(0, "草稿"), APPROVING(1, "审批中"), UNCHECK(2, "待检验"), - FINISHED(3, "已完成"), - CANCELED(4, "已取消"); + FINISHED(3, "已完成"); public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesProFeedbackStatusEnum::getStatus).toArray(Integer[]::new); @@ -45,3 +48,4 @@ public enum MesProFeedbackStatusEnum implements ArrayValuable { } } + diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackService.java index a2f4f9d..e1cce92 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackService.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackService.java @@ -66,17 +66,12 @@ public interface MesProFeedbackService { void rejectFeedback(Long id); /** - * 执行报工(审批中 → 已完成 或 待检验) + * 审批报工(审批中 -> 已完成 或 待检验) * * @param id 编号 + * @return 审批后的状态 */ - void finishFeedback(Long id); - - /** - * 取消报工 - * - * @param id 编号 - */ - void cancelFeedback(Long id); + Integer approveFeedback(Long id); } + diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImpl.java index 6d1e77a..2df77f9 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImpl.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImpl.java @@ -5,11 +5,11 @@ import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import cn.iocoder.yudao.module.mes.controller.admin.pro.feedback.vo.MesProFeedbackPageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.pro.feedback.vo.MesProFeedbackSaveReqVO; import cn.iocoder.yudao.module.mes.dal.dataobject.pro.feedback.MesProFeedbackDO; import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProcessDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.task.MesProTaskDO; import cn.iocoder.yudao.module.mes.dal.mysql.pro.feedback.MesProFeedbackMapper; import cn.iocoder.yudao.module.mes.enums.pro.MesProFeedbackStatusEnum; import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService; @@ -57,11 +57,12 @@ public class MesProFeedbackServiceImpl implements MesProFeedbackService { @Override public Long createFeedback(MesProFeedbackSaveReqVO createReqVO) { // 1. 校验 - validateFeedbackData(createReqVO); + MesProTaskDO task = validateFeedbackData(createReqVO); - // 2. 插入 + // 2. 插入(自动填充 itemId) MesProFeedbackDO feedback = BeanUtils.toBean(createReqVO, MesProFeedbackDO.class) - .setStatus(MesProFeedbackStatusEnum.PREPARE.getStatus()); + .setStatus(MesProFeedbackStatusEnum.PREPARE.getStatus()) + .setItemId(task.getItemId()); feedbackMapper.insert(feedback); return feedback.getId(); } @@ -71,10 +72,11 @@ public class MesProFeedbackServiceImpl implements MesProFeedbackService { // 1.1 校验存在 + 草稿状态 validateFeedbackStatusPrepare(updateReqVO.getId()); // 1.2 校验业务数据 - validateFeedbackData(updateReqVO); + MesProTaskDO task = validateFeedbackData(updateReqVO); - // 2. 更新 - MesProFeedbackDO updateObj = BeanUtils.toBean(updateReqVO, MesProFeedbackDO.class); + // 2. 更新(自动填充 itemId) + MesProFeedbackDO updateObj = BeanUtils.toBean(updateReqVO, MesProFeedbackDO.class) + .setItemId(task.getItemId()); feedbackMapper.updateById(updateObj); } @@ -119,11 +121,25 @@ public class MesProFeedbackServiceImpl implements MesProFeedbackService { .setStatus(MesProFeedbackStatusEnum.PREPARE.getStatus())); } + // TODO @AI:要不改成 boolean:看是不是 finish;如果非 finish 说明要前端提示“报工成功,请等待质量检验完成!” @Override @Transactional(rollbackFor = Exception.class) - public void finishFeedback(Long id) { - // 1. 校验存在 + 审批中状态 + public Integer approveFeedback(Long id) { + // TODO @AI: 逻辑需要继续跟进; + // 1.1 校验存在 + 审批中状态 MesProFeedbackDO feedback = validateFeedbackStatusApproving(id); + // 1.2 校验报工数量 > 0 + if (feedback.getFeedbackQuantity() == null + || feedback.getFeedbackQuantity().compareTo(BigDecimal.ZERO) <= 0) { + throw exception(PRO_FEEDBACK_QUANTITY_MUST_POSITIVE); + } + // 1.3 校验任务未完成 + taskService.validateTaskNotFinished(feedback.getTaskId()); + // 1.4 仍有待检数量时不能执行 + if (feedback.getUncheckQuantity() != null + && feedback.getUncheckQuantity().compareTo(BigDecimal.ZERO) > 0) { + throw exception(PRO_FEEDBACK_NOT_APPROVING); // TODO @芋艿:新增一个专用错误码,例如 PRO_FEEDBACK_UNCHECK_QUANTITY_EXISTS + } // 2.1 查询工序的 checkFlag,决定目标状态 boolean checkFlag = getCheckFlag(feedback.getRouteId(), feedback.getProcessId()); @@ -141,22 +157,7 @@ public class MesProFeedbackServiceImpl implements MesProFeedbackService { // TODO @芋艿:WM 产品产出(WmProductProduceService)未迁移,此处需补充产品产出逻辑 // TODO @芋艿:updateProTaskAndWorkorder 待 pro_task 服务迁移后补充级联更新任务/工单的已生产数量 } - } - - @Override - public void cancelFeedback(Long id) { - // 1.1 校验存在 - MesProFeedbackDO feedback = validateFeedbackExists(id); - // 1.2 只有草稿或审批中可以取消(已完成、已取消不可操作) - if (ObjectUtils.equalsAny(feedback.getStatus(), - MesProFeedbackStatusEnum.FINISHED.getStatus(), - MesProFeedbackStatusEnum.CANCELED.getStatus())) { - throw exception(PRO_FEEDBACK_STATUS_ERROR); - } - - // 2. 更新状态为已取消 - feedbackMapper.updateById(new MesProFeedbackDO().setId(id) - .setStatus(MesProFeedbackStatusEnum.CANCELED.getStatus())); + return targetStatus; } // ==================== 校验方法 ==================== @@ -189,8 +190,9 @@ public class MesProFeedbackServiceImpl implements MesProFeedbackService { * 校验报工单的业务数据(创建 & 修改共用) * * @param reqVO 报工请求 + * @return 关联的生产任务 */ - private void validateFeedbackData(MesProFeedbackSaveReqVO reqVO) { + private MesProTaskDO validateFeedbackData(MesProFeedbackSaveReqVO reqVO) { // 1. 校验工作站存在 workstationService.validateWorkstationExists(reqVO.getWorkstationId()); @@ -220,8 +222,8 @@ public class MesProFeedbackServiceImpl implements MesProFeedbackService { // 3. 校验工单已确认 workOrderService.validateWorkOrderConfirmed(reqVO.getWorkOrderId()); - // 4. 校验任务存在且未终态(已完成/已取消) - taskService.validateTaskNotFinished(reqVO.getTaskId()); + // 4. 校验任务存在且未终态(已完成/已取消),并返回任务用于冗余 itemId + return taskService.validateTaskNotFinished(reqVO.getTaskId()); } /**