From f51654ccbc0213eb26208610586edc5de17c5c6d Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 15 Mar 2026 00:12:44 +0800 Subject: [PATCH] ✨ feat(mes): 添加工单任务状态管理功能 --- yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/task/MesProTaskDO.java | 9 +++++++++ yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/workorder/MesProWorkorderDO.java | 5 +++++ yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProTaskStatusEnum.java | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskService.java | 14 ++++++++++++++ yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskServiceImpl.java | 37 ++++++++++++++++++++++++++++++++++++- yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkorderBomService.java | 12 ++++++++++++ yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkorderBomServiceImpl.java | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++--- yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkorderServiceImpl.java | 84 ++++++++++++++++++++++++++++-------------------------------------------------------- 8 files changed, 222 insertions(+), 60 deletions(-) create mode 100644 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProTaskStatusEnum.java diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/task/MesProTaskDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/task/MesProTaskDO.java index 5f7734e..95df901 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/task/MesProTaskDO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/task/MesProTaskDO.java @@ -1,12 +1,14 @@ package cn.iocoder.yudao.module.mes.dal.dataobject.pro.task; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO; 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.process.MesProProcessDO; import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteDO; import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; +import cn.iocoder.yudao.module.mes.enums.pro.MesProTaskStatusEnum; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; @@ -79,6 +81,7 @@ public class MesProTaskDO extends BaseDO { * 关联 {@link MesMdUnitMeasureDO#getId()} */ private Long unitMeasureId; + /** * 排产数量 */ @@ -99,8 +102,11 @@ public class MesProTaskDO extends BaseDO { * 调整数量 */ private BigDecimal changedQuantity; + /** * 客户编号 + * + * 关联 {@link MesMdClientDO#getId()} */ private Long clientId; /** @@ -127,8 +133,11 @@ public class MesProTaskDO extends BaseDO { * 取消日期 */ private LocalDateTime cancelDate; + /** * 任务状态 + * + * 枚举 {@link MesProTaskStatusEnum} */ private Integer status; /** diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/workorder/MesProWorkorderDO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/workorder/MesProWorkorderDO.java index 4eb7cee..dd6152a 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/workorder/MesProWorkorderDO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/workorder/MesProWorkorderDO.java @@ -32,6 +32,11 @@ import java.time.LocalDateTime; public class MesProWorkOrderDO extends BaseDO { /** + * 父工单编号,空值 + */ + public static final Long PARENT_ID_NULL = 0L; + + /** * 编号 */ @TableId diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProTaskStatusEnum.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProTaskStatusEnum.java new file mode 100644 index 0000000..b4c8be5 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/pro/MesProTaskStatusEnum.java @@ -0,0 +1,68 @@ +package cn.iocoder.yudao.module.mes.enums.pro; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskSaveReqVO; +import cn.iocoder.yudao.module.mes.enums.MesOrderStatusConstants; +import cn.iocoder.yudao.module.mes.service.pro.task.MesProTaskService; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 生产任务状态枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesProTaskStatusEnum implements ArrayValuable { + + /** + * 草稿 + * + * 对应方法:{@link MesProTaskService#createTask(MesProTaskSaveReqVO)} + */ + PREPARE(MesOrderStatusConstants.PREPARE, "草稿"), + /** + * 已完成 + * + * 对应方法:{@link MesProTaskService#finishTaskByOrderId(Long)} + */ + FINISHED(MesOrderStatusConstants.FINISHED, "已完成"), + /** + * 已取消 + * + * 对应方法:{@link MesProTaskService#cancelTaskByOrderId(Long)} + */ + CANCELED(MesOrderStatusConstants.CANCELLED, "已取消"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesProTaskStatusEnum::getStatus).toArray(Integer[]::new); + + /** + * 状态值 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + + /** + * 判断是否为终态(已完成 或 已取消) + * + * @param status 状态值 + * @return 是否为终态 + */ + public static boolean isEndStatus(Integer status) { + return ObjectUtils.equalsAny(status, FINISHED.status, CANCELED.status); + } + +} + diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskService.java index cf9f1f0..1a20ffe 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskService.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskService.java @@ -90,4 +90,18 @@ public interface MesProTaskService { return convertMap(getTaskList(ids), MesProTaskDO::getId); } + /** + * 根据工单编号,完成所有关联任务 + * + * @param workOrderId 工单编号 + */ + void finishTaskByOrderId(Long workOrderId); + + /** + * 根据工单编号,取消所有关联任务 + * + * @param workOrderId 工单编号 + */ + void cancelTaskByOrderId(Long workOrderId); + } 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 839dda1..670fd30 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 @@ -1,19 +1,23 @@ package cn.iocoder.yudao.module.mes.service.pro.task; +import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskPageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskSaveReqVO; import cn.iocoder.yudao.module.mes.dal.dataobject.pro.task.MesProTaskDO; import cn.iocoder.yudao.module.mes.dal.mysql.pro.task.MesProTaskMapper; +import cn.iocoder.yudao.module.mes.enums.pro.MesProTaskStatusEnum; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; +import java.time.LocalDateTime; import java.util.Collection; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_TASK_NOT_EXISTS; /** @@ -75,7 +79,38 @@ public class MesProTaskServiceImpl implements MesProTaskService { @Override public List getTaskList(Collection ids) { - return taskMapper.selectBatchIds(ids); + return taskMapper.selectByIds(ids); + } + + @Override + public void finishTaskByOrderId(Long workOrderId) { + // 1. 读取工单下所有任务,过滤掉已完成/已取消的 + List tasks = taskMapper.selectListByWorkOrderId(workOrderId); + LocalDateTime now = LocalDateTime.now(); + // 2. 构建待更新列表,批量更新 + List updateList = convertList(tasks, + task -> new MesProTaskDO().setId(task.getId()) + .setStatus(MesProTaskStatusEnum.FINISHED.getStatus()).setFinishDate(now), + task -> !MesProTaskStatusEnum.isEndStatus(task.getStatus())); + if (CollUtil.isNotEmpty(updateList)) { + taskMapper.updateBatch(updateList); + } + } + + @Override + public void cancelTaskByOrderId(Long workOrderId) { + // 1. 读取工单下所有任务,过滤掉已完成/已取消的 + List tasks = taskMapper.selectListByWorkOrderId(workOrderId); + LocalDateTime now = LocalDateTime.now(); + // 2. 构建待更新列表,批量更新 + List updateList = convertList(tasks, + task -> new MesProTaskDO().setId(task.getId()) + .setStatus(MesProTaskStatusEnum.CANCELED.getStatus()).setCancelDate(now), + task -> !MesProTaskStatusEnum.isEndStatus(task.getStatus())); + if (CollUtil.isNotEmpty(updateList)) { + taskMapper.updateBatch(updateList); + } } } + diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkorderBomService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkorderBomService.java index 901c9c0..b6ec56a 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkorderBomService.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkorderBomService.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.mes.service.pro.workorder; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.MesProWorkOrderSaveReqVO; import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.bom.MesProWorkOrderBomPageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.bom.MesProWorkOrderBomSaveReqVO; import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderBomDO; @@ -68,4 +69,15 @@ public interface MesProWorkOrderBomService { */ void deleteWorkOrderBomByWorkOrderId(Long workOrderId); + /** + * 根据产品 BOM 自动生成工单 BOM 行 + *

+ * 如果 updated 为 true,会先清理旧的 BOM 数据再重新生成 + * + * @param workOrderId 工单编号 + * @param reqVO 工单创建/更新请求(取 productId、quantity) + * @param updated 是否为更新场景(true 时先删除旧 BOM) + */ + void generateWorkOrderBom(Long workOrderId, MesProWorkOrderSaveReqVO reqVO, boolean updated); + } diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkorderBomServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkorderBomServiceImpl.java index 1b369be..aa1f1c6 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkorderBomServiceImpl.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkorderBomServiceImpl.java @@ -1,19 +1,27 @@ package cn.iocoder.yudao.module.mes.service.pro.workorder; +import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.MesProWorkOrderSaveReqVO; import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.bom.MesProWorkOrderBomPageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.bom.MesProWorkOrderBomSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdProductBomDO; import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderBomDO; import cn.iocoder.yudao.module.mes.dal.mysql.pro.workorder.MesProWorkOrderBomMapper; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdProductBomService; import jakarta.annotation.Resource; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; -import java.util.List; +import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.MD_ITEM_NOT_EXISTS; import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_WORK_ORDER_BOM_NOT_EXISTS; /** @@ -31,11 +39,17 @@ public class MesProWorkOrderBomServiceImpl implements MesProWorkOrderBomService @Resource @Lazy // 延迟加载,避免循环依赖 private MesProWorkOrderService workOrderService; + @Resource + private MesMdItemService itemService; + @Resource + private MesMdProductBomService productBomService; @Override public Long createWorkOrderBom(MesProWorkOrderBomSaveReqVO createReqVO) { // 校验工单存在 workOrderService.validateWorkOrderExists(createReqVO.getWorkOrderId()); + + // 插入数据 MesProWorkOrderBomDO workOrderBom = BeanUtils.toBean(createReqVO, MesProWorkOrderBomDO.class); workOrderBomMapper.insert(workOrderBom); return workOrderBom.getId(); @@ -45,7 +59,8 @@ public class MesProWorkOrderBomServiceImpl implements MesProWorkOrderBomService public void updateWorkOrderBom(MesProWorkOrderBomSaveReqVO updateReqVO) { // 校验存在 validateWorkOrderBomExists(updateReqVO.getId()); - // 更新 + + // 更新数据 MesProWorkOrderBomDO updateObj = BeanUtils.toBean(updateReqVO, MesProWorkOrderBomDO.class); workOrderBomMapper.updateById(updateObj); } @@ -54,6 +69,7 @@ public class MesProWorkOrderBomServiceImpl implements MesProWorkOrderBomService public void deleteWorkOrderBom(Long id) { // 校验存在 validateWorkOrderBomExists(id); + // 删除 workOrderBomMapper.deleteById(id); } @@ -84,4 +100,35 @@ public class MesProWorkOrderBomServiceImpl implements MesProWorkOrderBomService workOrderBomMapper.deleteByWorkOrderId(workOrderId); } -} + @Override + public void generateWorkOrderBom(Long workOrderId, MesProWorkOrderSaveReqVO reqVO, boolean updated) { + // 1. 如果是更新场景,先清理旧的 BOM 数据 + if (updated) { + workOrderBomMapper.deleteByWorkOrderId(workOrderId); + } + + // 2.1 查询产品 BOM + List productBomList = productBomService.getProductBomListByItemId(reqVO.getProductId()); + if (CollUtil.isEmpty(productBomList)) { + return; + } + // 2.2 批量获取并校验 BOM 物料 + Set bomItemIds = CollectionUtils.convertSet(productBomList, MesMdProductBomDO::getBomItemId); + Map itemMap = itemService.getItemMap(bomItemIds); + bomItemIds.forEach(itemId -> { + if (itemMap.get(itemId) == null) { + throw exception(MD_ITEM_NOT_EXISTS); + } + }); + + // 3. 构建工单 BOM 列表并批量插入 + List bomList = new ArrayList<>(productBomList.size()); + for (MesMdProductBomDO productBom : productBomList) { + MesMdItemDO bomItem = itemMap.get(productBom.getBomItemId()); + bomList.add(new MesProWorkOrderBomDO().setWorkOrderId(workOrderId).setItemId(productBom.getBomItemId()) + .setQuantity(reqVO.getQuantity().multiply(productBom.getQuantity())).setUnitMeasureId(bomItem.getUnitMeasureId())); + } + workOrderBomMapper.insertBatch(bomList); + } + +} \ No newline at end of file diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkorderServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkorderServiceImpl.java index 0908db3..58b70ca 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkorderServiceImpl.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkorderServiceImpl.java @@ -7,24 +7,19 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.MesProWorkOrderPageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.MesProWorkOrderSaveReqVO; import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemBatchConfigDO; -import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; -import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdProductBomDO; -import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderBomDO; import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; -import cn.iocoder.yudao.module.mes.dal.mysql.pro.workorder.MesProWorkOrderBomMapper; import cn.iocoder.yudao.module.mes.dal.mysql.pro.workorder.MesProWorkOrderMapper; import cn.iocoder.yudao.module.mes.enums.pro.MesProWorkOrderStatusEnum; import cn.iocoder.yudao.module.mes.enums.wm.BarcodeBizTypeEnum; import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemBatchConfigService; import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; -import cn.iocoder.yudao.module.mes.service.md.item.MesMdProductBomService; +import cn.iocoder.yudao.module.mes.service.pro.task.MesProTaskService; import cn.iocoder.yudao.module.mes.service.wm.barcode.MesWmBarcodeService; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; -import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.Collection; import java.util.Collections; @@ -45,21 +40,16 @@ public class MesProWorkOrderServiceImpl implements MesProWorkOrderService { @Resource private MesProWorkOrderMapper workOrderMapper; - // TODO @AI:不应该直接这么调用,调用对应的 service @Resource - private MesProWorkOrderBomMapper workOrderBomMapper; - + private MesProWorkOrderBomService workOrderBomService; @Resource private MesMdItemService itemService; - - @Resource - private MesMdProductBomService productBomService; - @Resource private MesMdItemBatchConfigService itemBatchConfigService; - @Resource private MesWmBarcodeService barcodeService; + @Resource + private MesProTaskService taskService; @Override @Transactional(rollbackFor = Exception.class) @@ -68,12 +58,12 @@ public class MesProWorkOrderServiceImpl implements MesProWorkOrderService { validateWorkOrderCodeUnique(null, createReqVO.getCode()); // 1.2 校验产品存在 itemService.validateItemExists(createReqVO.getProductId()); - // 1.3 校验批次配置:如果产品有 clientFlag=true,则 clientId 必填 + // 1.3 校验批次配置 validateBatchConfig(createReqVO.getProductId(), createReqVO.getClientId()); // 2.1 设置默认值 if (createReqVO.getParentId() == null) { - createReqVO.setParentId(0L); + createReqVO.setParentId(MesProWorkOrderDO.PARENT_ID_NULL); } // 2.2 插入工单 MesProWorkOrderDO workOrder = BeanUtils.toBean(createReqVO, MesProWorkOrderDO.class); @@ -83,7 +73,7 @@ public class MesProWorkOrderServiceImpl implements MesProWorkOrderService { workOrderMapper.insert(workOrder); // 3. 自动生成 BOM:根据产品 BOM 生成工单 BOM - generateWorkOrderBom(workOrder.getId(), createReqVO.getProductId(), createReqVO.getQuantity()); + workOrderBomService.generateWorkOrderBom(workOrder.getId(), createReqVO, false); // 4. 自动生成条码 barcodeService.autoGenerateBarcode(BarcodeBizTypeEnum.WORKORDER.getValue(), @@ -101,13 +91,11 @@ public class MesProWorkOrderServiceImpl implements MesProWorkOrderService { // 1.3 校验批次配置 validateBatchConfig(updateReqVO.getProductId(), updateReqVO.getClientId()); - // 2. 判断产品或数量是否变更,如果变更则重新生成 BOM + // 2. 判断产品或数量是否变更,如果变更则重新生成 BOM(updated=true 会先清理旧数据) boolean productChanged = ObjUtil.notEqual(oldWorkOrder.getProductId(), updateReqVO.getProductId()); boolean quantityChanged = oldWorkOrder.getQuantity().compareTo(updateReqVO.getQuantity()) != 0; if (productChanged || quantityChanged) { - // 删除旧 BOM 并重新生成 - workOrderBomMapper.deleteByWorkOrderId(updateReqVO.getId()); - generateWorkOrderBom(updateReqVO.getId(), updateReqVO.getProductId(), updateReqVO.getQuantity()); + workOrderBomService.generateWorkOrderBom(updateReqVO.getId(), updateReqVO, true); } // 3. 更新 @@ -127,7 +115,7 @@ public class MesProWorkOrderServiceImpl implements MesProWorkOrderService { // 2. 删除工单 + BOM workOrderMapper.deleteById(id); - workOrderBomMapper.deleteByWorkOrderId(id); + workOrderBomService.deleteWorkOrderBomByWorkOrderId(id); } @Override @@ -168,45 +156,52 @@ public class MesProWorkOrderServiceImpl implements MesProWorkOrderService { @Override public void confirmWorkOrder(Long id) { - // 1. 校验存在 + // 1.1 校验存在 MesProWorkOrderDO workOrder = validateWorkOrderExists(id); - // 2. 只有草稿状态才能确认 - if (!ObjUtil.equal(workOrder.getStatus(), MesProWorkOrderStatusEnum.PREPARE.getStatus())) { + // 1.2 只有草稿状态才能确认 + if (ObjUtil.notEqual(workOrder.getStatus(), MesProWorkOrderStatusEnum.PREPARE.getStatus())) { throw exception(PRO_WORK_ORDER_NOT_PREPARE); } - // 3. 更新状态为已确认 + + // 2. 更新状态为已确认 workOrderMapper.updateById(new MesProWorkOrderDO().setId(id) .setStatus(MesProWorkOrderStatusEnum.CONFIRMED.getStatus())); } @Override + @Transactional(rollbackFor = Exception.class) public void finishWorkOrder(Long id) { // 1. 校验存在 + 只有已确认状态才能完成 MesProWorkOrderDO workOrder = validateWorkOrderExists(id); - if (!ObjUtil.equal(workOrder.getStatus(), MesProWorkOrderStatusEnum.CONFIRMED.getStatus())) { + if (ObjUtil.notEqual(workOrder.getStatus(), MesProWorkOrderStatusEnum.CONFIRMED.getStatus())) { throw exception(PRO_WORK_ORDER_NOT_CONFIRMED); } - // 2. 更新状态为已完成 + // 2. 级联完成所有关联任务 + taskService.finishTaskByOrderId(id); + + // 3. 更新工单状态为已完成 workOrderMapper.updateById(new MesProWorkOrderDO().setId(id) .setStatus(MesProWorkOrderStatusEnum.FINISHED.getStatus()) .setFinishDate(LocalDateTime.now())); - // TODO @芋艿:pro_task 未迁移,暂不级联更新任务状态 } @Override + @Transactional(rollbackFor = Exception.class) public void cancelWorkOrder(Long id) { // 1. 校验存在 + 只有已确认状态才能取消 MesProWorkOrderDO workOrder = validateWorkOrderExists(id); - if (!ObjUtil.equal(workOrder.getStatus(), MesProWorkOrderStatusEnum.CONFIRMED.getStatus())) { + if (ObjUtil.notEqual(workOrder.getStatus(), MesProWorkOrderStatusEnum.CONFIRMED.getStatus())) { throw exception(PRO_WORK_ORDER_NOT_CONFIRMED); } - // 2. 更新状态为已取消 + // 2. 级联取消所有关联任务 + taskService.cancelTaskByOrderId(id); + + // 3. 更新工单状态为已取消 workOrderMapper.updateById(new MesProWorkOrderDO().setId(id) .setStatus(MesProWorkOrderStatusEnum.CANCELED.getStatus()) .setCancelDate(LocalDateTime.now())); - // TODO @芋艿:pro_task 未迁移,暂不级联更新任务状态 } // ==================== 校验方法 ==================== @@ -225,6 +220,7 @@ public class MesProWorkOrderServiceImpl implements MesProWorkOrderService { } private void validateBatchConfig(Long productId, Long clientId) { + // 如果产品有 clientFlag=true,则 clientId 必填 MesMdItemBatchConfigDO batchConfig = itemBatchConfigService.getItemBatchConfigByItemId(productId); if (batchConfig != null && Boolean.TRUE.equals(batchConfig.getClientFlag()) && clientId == null) { // 产品要求批次管理中必须填写客户 @@ -237,28 +233,4 @@ public class MesProWorkOrderServiceImpl implements MesProWorkOrderService { return workOrderMapper.selectList(); } - // ==================== BOM 自动生成 ==================== - - /** - * 根据产品 BOM 自动生成工单 BOM 行 - * - * @param workOrderId 工单编号 - * @param productId 产品编号 - * @param quantity 工单生产数量 - */ - private void generateWorkOrderBom(Long workOrderId, Long productId, BigDecimal quantity) { - List productBomList = productBomService.getProductBomListByItemId(productId); - if (CollUtil.isEmpty(productBomList)) { - return; - } - for (MesMdProductBomDO productBom : productBomList) { - MesMdItemDO bomItem = itemService.validateItemExists(productBom.getBomItemId()); - workOrderBomMapper.insert(new MesProWorkOrderBomDO() - .setWorkOrderId(workOrderId) - .setItemId(productBom.getBomItemId()) - .setQuantity(quantity.multiply(productBom.getQuantity())) - .setUnitMeasureId(bomItem.getUnitMeasureId())); - } - } - } -- libgit2 0.21.4