diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/detail/MesWmProductIssueDetailSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/detail/MesWmProductIssueDetailSaveReqVO.java index de2a2b9..d598289 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/detail/MesWmProductIssueDetailSaveReqVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/detail/MesWmProductIssueDetailSaveReqVO.java @@ -26,6 +26,9 @@ public class MesWmProductIssueDetailSaveReqVO { @NotNull(message = "物料编号不能为空") private Long itemId; + @Schema(description = "库存记录编号", example = "1") + private Long materialStockId; + @Schema(description = "领料数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "300.00") @NotNull(message = "领料数量不能为空") @DecimalMin(value = "0", inclusive = false, message = "领料数量必须大于 0") @@ -49,4 +52,4 @@ public class MesWmProductIssueDetailSaveReqVO { @Schema(description = "备注", example = "备注") private String remark; - } +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/vo/detail/MesWmReturnIssueDetailSaveReqVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/vo/detail/MesWmReturnIssueDetailSaveReqVO.java index 6659bf4..e5ff434 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/vo/detail/MesWmReturnIssueDetailSaveReqVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/vo/detail/MesWmReturnIssueDetailSaveReqVO.java @@ -26,6 +26,9 @@ public class MesWmReturnIssueDetailSaveReqVO { @NotNull(message = "物料编号不能为空") private Long itemId; + @Schema(description = "库存记录编号", example = "1") + private Long materialStockId; + @Schema(description = "退料数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "300.00") @NotNull(message = "退料数量不能为空") @DecimalMin(value = "0", inclusive = false, message = "退料数量必须大于0") diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java index aaee1b8..6205166 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java @@ -91,6 +91,7 @@ public interface ErrorCodeConstants { ErrorCode MD_PRODUCT_BOM_NOT_EXISTS = new ErrorCode(1_040_107_000, "产品BOM不存在"); ErrorCode MD_PRODUCT_BOM_SELF_REFERENCE = new ErrorCode(1_040_107_001, "产品不能作为自身的BOM物料"); ErrorCode MD_PRODUCT_BOM_CIRCULAR = new ErrorCode(1_040_107_002, "BOM物料存在闭环,无法新增"); + ErrorCode MD_PRODUCT_BOM_ITEM_INVALID = new ErrorCode(1_040_107_003, "选择的 BOM 物料不属于当前产品"); // ========== MES 基础数据-产品SOP(1-040-108-000) ========== ErrorCode MD_PRODUCT_SOP_NOT_EXISTS = new ErrorCode(1_040_108_000, "产品SOP不存在"); @@ -167,6 +168,7 @@ public interface ErrorCodeConstants { ErrorCode DV_CHECK_PLAN_NO_MACHINERY = new ErrorCode(1_040_302_003, "启用方案时,至少需要关联一台设备"); ErrorCode DV_CHECK_PLAN_NO_SUBJECT = new ErrorCode(1_040_302_004, "启用方案时,至少需要关联一个点检保养项目"); ErrorCode DV_CHECK_PLAN_NOT_ENABLED = new ErrorCode(1_040_302_005, "点检保养方案未启用,不允许停用"); + ErrorCode DV_CHECK_PLAN_TYPE_MISMATCH = new ErrorCode(1_040_302_006, "点检保养方案类型与当前业务不匹配"); // ========== MES 设备管理-点检方案设备(1-040-302-100) ========== ErrorCode DV_CHECK_PLAN_MACHINERY_NOT_EXISTS = new ErrorCode(1_040_302_100, "点检保养方案设备不存在"); ErrorCode DV_CHECK_PLAN_MACHINERY_DUPLICATE = new ErrorCode(1_040_302_101, "该设备已关联到当前方案,请勿重复添加"); @@ -241,11 +243,17 @@ public interface ErrorCodeConstants { ErrorCode PRO_WORK_ORDER_NOT_PREPARE = new ErrorCode(1_040_502_002, "只有草稿状态的工单才能执行此操作"); ErrorCode PRO_WORK_ORDER_NOT_CONFIRMED = new ErrorCode(1_040_502_003, "只有已确认状态的工单才能执行此操作"); ErrorCode PRO_WORK_ORDER_HAS_CHILDREN = new ErrorCode(1_040_502_004, "存在子工单,无法删除"); + ErrorCode PRO_WORK_ORDER_PRODUCT_MISMATCH = new ErrorCode(1_040_502_005, "当前产品物料与生产工单产品不一致"); ErrorCode PRO_WORK_ORDER_BOM_NOT_EXISTS = new ErrorCode(1_040_502_100, "生产工单BOM不存在"); // ========== MES 生产管理-生产任务(1-040-503-000) ========== ErrorCode PRO_TASK_NOT_EXISTS = new ErrorCode(1_040_503_000, "生产任务不存在"); ErrorCode PRO_TASK_ALREADY_FINISHED = new ErrorCode(1_040_503_001, "生产任务已完成或已取消,不能继续操作"); + ErrorCode PRO_TASK_WORK_ORDER_MISMATCH = new ErrorCode(1_040_503_002, "生产任务不属于当前生产工单"); + ErrorCode PRO_TASK_WORKSTATION_MISMATCH = new ErrorCode(1_040_503_003, "生产任务不属于当前工作站"); + ErrorCode PRO_TASK_ROUTE_PROCESS_MISMATCH = new ErrorCode(1_040_503_004, "生产任务与当前工艺路线或工序不一致"); + ErrorCode PRO_TASK_ITEM_MISMATCH = new ErrorCode(1_040_503_005, "生产任务产品与当前产品物料不一致"); + ErrorCode PRO_WORKSTATION_PROCESS_MISMATCH = new ErrorCode(1_040_503_006, "工作站所属工序与当前工序不一致"); // ========== MES 生产管理-生产任务投料(1-040-503-100) ========== ErrorCode PRO_TASK_ISSUE_NOT_EXISTS = new ErrorCode(1_040_503_100, "生产任务投料记录不存在"); @@ -399,6 +407,8 @@ public interface ErrorCodeConstants { ErrorCode WM_TRANSACTION_RELATED_NOT_EXISTS = new ErrorCode(1_040_703_010, "关联的库存事务不存在"); ErrorCode WM_TRANSACTION_LIST_EMPTY = new ErrorCode(1_040_703_011, "库存事务列表不能为空"); ErrorCode WM_TRANSACTION_BATCH_NOT_EXISTS = new ErrorCode(1_040_703_012, "批次记录不存在"); + ErrorCode WM_MATERIAL_STOCK_REQUIRED = new ErrorCode(1_040_703_013, "库存记录不能为空"); + ErrorCode WM_MATERIAL_STOCK_SELECTION_MISMATCH = new ErrorCode(1_040_703_014, "库存记录与提交的物料、批次或库位信息不一致"); // ========== MES 仓库管理-到货通知单(1-040-704-000) ========== ErrorCode WM_ARRIVAL_NOTICE_NOT_EXISTS = new ErrorCode(1_040_704_000, "到货通知单不存在"); @@ -408,6 +418,7 @@ public interface ErrorCodeConstants { ErrorCode WM_ARRIVAL_NOTICE_STATUS_NOT_PENDING_RECEIPT = new ErrorCode(1_040_704_004, "只有待入库状态才允许完成"); ErrorCode WM_ARRIVAL_NOTICE_IQC_PENDING = new ErrorCode(1_040_704_005, "存在待检验行,无法审批通过"); ErrorCode WM_ARRIVAL_NOTICE_NO_LINE = new ErrorCode(1_040_704_006, "至少需要一条行项目"); + ErrorCode WM_ARRIVAL_NOTICE_VENDOR_MISMATCH = new ErrorCode(1_040_704_007, "到货通知单的供应商与当前单据不一致"); ErrorCode WM_ARRIVAL_NOTICE_LINE_NOT_EXISTS = new ErrorCode(1_040_704_100, "到货通知单行不存在"); ErrorCode WM_ARRIVAL_NOTICE_LINE_NOT_MATCH = new ErrorCode(1_040_704_101, "到货通知单行不属于指定的到货通知单"); @@ -444,6 +455,8 @@ public interface ErrorCodeConstants { ErrorCode WM_OUTSOURCE_ISSUE_LINE_NOT_EXISTS = new ErrorCode(1_040_707_100, "外协发料单行不存在"); ErrorCode WM_OUTSOURCE_ISSUE_LINE_ITEM_NOT_IN_BOM = new ErrorCode(1_040_707_101, "发料单行对应的物料不在当前工单的 BOM 列表中"); ErrorCode WM_OUTSOURCE_ISSUE_DETAIL_NOT_EXISTS = new ErrorCode(1_040_707_200, "外协发料单明细不存在"); + ErrorCode WM_OUTSOURCE_ISSUE_DETAIL_LINE_NOT_MATCH = new ErrorCode(1_040_707_201, "拣货明细不属于指定的外协发料单"); + ErrorCode WM_OUTSOURCE_ISSUE_DETAIL_ITEM_MISMATCH = new ErrorCode(1_040_707_202, "拣货明细的物料与外协发料单行的物料不一致"); ErrorCode WM_OUTSOURCE_ISSUE_WORK_ORDER_TYPE_INVALID = new ErrorCode(1_040_707_008, "工单类型不是外协(代工)类型"); // ========== MES 仓库管理-生产领料出库单(1-040-708-000) ========== @@ -459,6 +472,7 @@ public interface ErrorCodeConstants { ErrorCode WM_PRODUCT_ISSUE_CODE_DUPLICATE = new ErrorCode(1_040_708_102, "领料出库单编码已存在"); ErrorCode WM_PRODUCT_ISSUE_DETAIL_NOT_EXISTS = new ErrorCode(1_040_708_200, "生产领料出库单明细不存在"); ErrorCode WM_PRODUCT_ISSUE_DETAIL_ITEM_MISMATCH = new ErrorCode(1_040_708_201, "拣货明细的物料与领料单行的物料不一致"); + ErrorCode WM_PRODUCT_ISSUE_DETAIL_LINE_NOT_MATCH = new ErrorCode(1_040_708_202, "拣货明细不属于指定的领料出库单"); // ========== MES 仓库管理-生产入库单(1-040-709-000) ========== ErrorCode WM_PRODUCT_PRODUCE_NOT_EXISTS = new ErrorCode(1_040_709_000, "生产入库单不存在"); @@ -501,6 +515,8 @@ public interface ErrorCodeConstants { ErrorCode WM_RETURN_ISSUE_DETAIL_QUANTITY_INVALID = new ErrorCode(1_040_710_201, "退料明细数量必须大于0"); ErrorCode WM_RETURN_ISSUE_DETAIL_QUANTITY_EXCEED = new ErrorCode(1_040_710_202, "退料明细总数量不能超过退料单行数量"); ErrorCode WM_RETURN_ISSUE_CODE_DUPLICATE = new ErrorCode(1_040_710_203, "退料单编码已存在"); + ErrorCode WM_RETURN_ISSUE_DETAIL_LINE_NOT_MATCH = new ErrorCode(1_040_710_204, "退料明细不属于指定的退料单"); + ErrorCode WM_RETURN_ISSUE_DETAIL_ITEM_MISMATCH = new ErrorCode(1_040_710_205, "退料明细的物料与退料单行的物料不一致"); // ========== MES 仓库管理-供应商退货单(1-040-711-000) ========== ErrorCode WM_RETURN_VENDOR_NOT_EXISTS = new ErrorCode(1_040_711_000, "供应商退货单不存在"); @@ -514,6 +530,7 @@ public interface ErrorCodeConstants { ErrorCode WM_RETURN_VENDOR_LINE_NOT_EXISTS = new ErrorCode(1_040_711_100, "供应商退货单行不存在"); ErrorCode WM_RETURN_VENDOR_DETAIL_NOT_EXISTS = new ErrorCode(1_040_711_200, "供应商退货单明细不存在"); ErrorCode WM_RETURN_VENDOR_DETAIL_QUANTITY_INVALID = new ErrorCode(1_040_711_201, "退货明细数量必须大于 0"); + ErrorCode WM_RETURN_VENDOR_DETAIL_LINE_NOT_MATCH = new ErrorCode(1_040_711_202, "拣货明细不属于指定的供应商退货单"); // ========== MES 仓库管理-产品收货单(1-040-712-000) ========== ErrorCode WM_PRODUCT_RECPT_NOT_EXISTS = new ErrorCode(1_040_712_000, "产品收货单不存在"); @@ -588,6 +605,8 @@ public interface ErrorCodeConstants { ErrorCode WM_PRODUCT_SALES_DETAIL_NOT_EXISTS = new ErrorCode(1_040_714_012, "销售出库明细不存在"); ErrorCode WM_PRODUCT_SALES_STOCK_INSUFFICIENT = new ErrorCode(1_040_714_013, "库存不足,无法拣货"); ErrorCode WM_PRODUCT_SALES_LINE_QUANTITY_INVALID = new ErrorCode(1_040_714_014, "出库数量必须大于 0"); + ErrorCode WM_PRODUCT_SALES_DETAIL_LINE_NOT_MATCH = new ErrorCode(1_040_714_015, "拣货明细不属于指定的销售出库单"); + ErrorCode WM_PRODUCT_SALES_DETAIL_ITEM_MISMATCH = new ErrorCode(1_040_714_016, "拣货明细的物料与销售出库单行的物料不一致"); // ========== MES 仓库管理-杂项出库单(1-040-715-000) ========== ErrorCode WM_MISC_ISSUE_NOT_EXISTS = new ErrorCode(1_040_715_000, "杂项出库单不存在"); @@ -616,6 +635,8 @@ public interface ErrorCodeConstants { ErrorCode WM_SALES_NOTICE_CODE_DUPLICATE = new ErrorCode(1_040_720_001, "通知单编号重复"); ErrorCode WM_SALES_NOTICE_STATUS_NOT_ALLOW_DELETE = new ErrorCode(1_040_720_002, "单据状态不允许删除"); ErrorCode WM_SALES_NOTICE_STATUS_NOT_ALLOW_UPDATE = new ErrorCode(1_040_720_003, "单据状态不允许修改"); + ErrorCode WM_SALES_NOTICE_STATUS_NOT_APPROVED = new ErrorCode(1_040_720_004, "发货通知单不是待出库状态"); + ErrorCode WM_SALES_NOTICE_CLIENT_MISMATCH = new ErrorCode(1_040_720_005, "发货通知单的客户与当前单据不一致"); ErrorCode WM_SALES_NOTICE_LINE_NOT_EXISTS = new ErrorCode(1_040_720_010, "发货通知单行不存在"); ErrorCode WM_SALES_NOTICE_LINE_EMPTY = new ErrorCode(1_040_720_011, "发货通知单行为空,不能提交"); diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/dv/MesDvCheckPlanTypeEnum.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/dv/MesDvCheckPlanTypeEnum.java new file mode 100644 index 0000000..c088f88 --- /dev/null +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/dv/MesDvCheckPlanTypeEnum.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.mes.enums.dv; + +import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * MES 点检保养方案类型枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum MesDvCheckPlanTypeEnum implements ArrayValuable { + + CHECK(1, "点检"), + MAINTENANCE(2, "保养"); + + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesDvCheckPlanTypeEnum::getType).toArray(Integer[]::new); + + /** + * 类型值 + */ + private final Integer type; + /** + * 类型名 + */ + private final String name; + + @Override + public Integer[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanService.java index bfb1fe2..598afd7 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanService.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanService.java @@ -63,6 +63,15 @@ public interface MesDvCheckPlanService { void validateCheckPlanExists(Long id); /** + * 校验点检保养方案存在,且类型匹配 + * + * @param id 方案编号 + * @param type 期望的方案类型 + * @return 方案 + */ + MesDvCheckPlanDO validateCheckPlanExistsAndType(Long id, Integer type); + + /** * 校验点检保养方案为草稿状态 * * @param planId 方案编号 diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanServiceImpl.java index 644a149..eea3f1c 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanServiceImpl.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanServiceImpl.java @@ -149,6 +149,15 @@ public class MesDvCheckPlanServiceImpl implements MesDvCheckPlanService { return plan; } + @Override + public MesDvCheckPlanDO validateCheckPlanExistsAndType(Long id, Integer type) { + MesDvCheckPlanDO plan = doValidateCheckPlanExists(id); + if (ObjUtil.notEqual(plan.getType(), type)) { + throw exception(DV_CHECK_PLAN_TYPE_MISMATCH); + } + return plan; + } + private void validateCheckPlanCodeUnique(Long id, String code) { MesDvCheckPlanDO plan = checkPlanMapper.selectByCode(code); if (plan == null) { diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkrecord/MesDvCheckRecordServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkrecord/MesDvCheckRecordServiceImpl.java index 22be2b8..268ccf3 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkrecord/MesDvCheckRecordServiceImpl.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkrecord/MesDvCheckRecordServiceImpl.java @@ -10,6 +10,7 @@ import cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkplan.MesDvCheckPlanSub import cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkrecord.MesDvCheckRecordDO; import cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkrecord.MesDvCheckRecordLineDO; import cn.iocoder.yudao.module.mes.enums.dv.MesDvCheckRecordStatusEnum; +import cn.iocoder.yudao.module.mes.enums.dv.MesDvCheckPlanTypeEnum; import cn.iocoder.yudao.module.mes.enums.dv.MesDvCheckResultEnum; import cn.iocoder.yudao.module.mes.dal.mysql.dv.checkrecord.MesDvCheckRecordMapper; import cn.iocoder.yudao.module.mes.service.dv.checkplan.MesDvCheckPlanService; @@ -37,6 +38,7 @@ import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; @Validated public class MesDvCheckRecordServiceImpl implements MesDvCheckRecordService { + @Resource private MesDvCheckRecordMapper checkRecordMapper; @Resource @@ -162,7 +164,7 @@ public class MesDvCheckRecordServiceImpl implements MesDvCheckRecordService { machineryService.validateMachineryExists(reqVO.getMachineryId()); // 校验点检计划是否存在 if (reqVO.getPlanId() != null) { - checkPlanService.validateCheckPlanExists(reqVO.getPlanId()); + checkPlanService.validateCheckPlanExistsAndType(reqVO.getPlanId(), MesDvCheckPlanTypeEnum.CHECK.getType()); } // 校验点检人是否存在 if (reqVO.getUserId() != null) { diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/maintenrecord/MesDvMaintenRecordServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/maintenrecord/MesDvMaintenRecordServiceImpl.java index afb44b9..13f55e0 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/maintenrecord/MesDvMaintenRecordServiceImpl.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/maintenrecord/MesDvMaintenRecordServiceImpl.java @@ -10,6 +10,7 @@ import cn.iocoder.yudao.module.mes.dal.dataobject.dv.maintenrecord.MesDvMaintenR import cn.iocoder.yudao.module.mes.dal.dataobject.dv.maintenrecord.MesDvMaintenRecordLineDO; import cn.iocoder.yudao.module.mes.dal.mysql.dv.maintenrecord.MesDvMaintenRecordMapper; import cn.iocoder.yudao.module.mes.enums.dv.MesDvMaintenRecordStatusEnum; +import cn.iocoder.yudao.module.mes.enums.dv.MesDvCheckPlanTypeEnum; import cn.iocoder.yudao.module.mes.service.dv.checkplan.MesDvCheckPlanService; import cn.iocoder.yudao.module.mes.service.dv.machinery.MesDvMachineryService; import jakarta.annotation.Resource; @@ -100,7 +101,7 @@ public class MesDvMaintenRecordServiceImpl implements MesDvMaintenRecordService machineryService.validateMachineryExists(reqVO.getMachineryId()); // 校验保养计划是否存在 if (reqVO.getPlanId() != null) { - checkPlanService.validateCheckPlanExists(reqVO.getPlanId()); + checkPlanService.validateCheckPlanExistsAndType(reqVO.getPlanId(), MesDvCheckPlanTypeEnum.MAINTENANCE.getType()); } } diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/card/MesProCardServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/card/MesProCardServiceImpl.java index 577d266..9d47ce9 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/card/MesProCardServiceImpl.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/card/MesProCardServiceImpl.java @@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import cn.iocoder.yudao.module.mes.controller.admin.pro.card.vo.MesProCardPageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.pro.card.vo.MesProCardSaveReqVO; import cn.iocoder.yudao.module.mes.dal.dataobject.pro.card.MesProCardDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; import cn.iocoder.yudao.module.mes.dal.mysql.pro.card.MesProCardMapper; import cn.iocoder.yudao.module.mes.enums.pro.MesProWorkOrderStatusEnum; import cn.iocoder.yudao.module.mes.enums.wm.BarcodeBizTypeEnum; @@ -171,9 +172,12 @@ public class MesProCardServiceImpl implements MesProCardService { // 校验编码唯一 validateCardCodeUnique(reqVO.getId(), reqVO.getCode()); // 校验工单存在 - workOrderService.validateWorkOrderExists(reqVO.getWorkOrderId()); + MesProWorkOrderDO workOrder = workOrderService.validateWorkOrderConfirmed(reqVO.getWorkOrderId()); // 校验物料存在 itemService.validateItemExists(reqVO.getItemId()); + if (ObjUtil.notEqual(workOrder.getProductId(), reqVO.getItemId())) { + throw exception(PRO_WORK_ORDER_PRODUCT_MISMATCH); + } } } 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 2729b10..9df980c 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 @@ -46,6 +46,14 @@ public interface MesProFeedbackService { MesProFeedbackDO getFeedback(Long id); /** + * 校验生产报工存在 + * + * @param id 编号 + * @return 生产报工 + */ + MesProFeedbackDO validateFeedbackExists(Long id); + + /** * 获得生产报工分页 * * @param pageReqVO 分页查询 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 b631427..34faee5 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 @@ -4,11 +4,13 @@ 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.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; 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.dataobject.pro.workorder.MesProWorkOrderDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemconsume.MesWmItemConsumeDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceLineDO; @@ -219,7 +221,8 @@ public class MesProFeedbackServiceImpl implements MesProFeedbackService { // ==================== 校验方法 ==================== - private MesProFeedbackDO validateFeedbackExists(Long id) { + @Override + public MesProFeedbackDO validateFeedbackExists(Long id) { MesProFeedbackDO feedback = feedbackMapper.selectById(id); if (feedback == null) { throw exception(PRO_FEEDBACK_NOT_EXISTS); @@ -251,7 +254,10 @@ public class MesProFeedbackServiceImpl implements MesProFeedbackService { */ private MesProTaskDO validateFeedbackData(MesProFeedbackSaveReqVO reqVO) { // 1. 校验工作站存在 - workstationService.validateWorkstationExists(reqVO.getWorkstationId()); + MesMdWorkstationDO workstation = workstationService.validateWorkstationExists(reqVO.getWorkstationId()); + if (ObjUtil.notEqual(workstation.getProcessId(), reqVO.getProcessId())) { + throw exception(PRO_WORKSTATION_PROCESS_MISMATCH); + } // 2.1 校验工艺路线 + 工序配置有效 MesProRouteProcessDO routeProcess = routeProcessService.getRouteProcessByRouteIdAndProcessId( @@ -277,10 +283,32 @@ public class MesProFeedbackServiceImpl implements MesProFeedbackService { } // 3. 校验工单已确认 - workOrderService.validateWorkOrderConfirmed(reqVO.getWorkOrderId()); + MesProWorkOrderDO workOrder = workOrderService.validateWorkOrderConfirmed(reqVO.getWorkOrderId()); + if (ObjUtil.notEqual(workOrder.getProductId(), reqVO.getItemId())) { + throw exception(PRO_WORK_ORDER_PRODUCT_MISMATCH); + } // 4. 校验任务存在且未终态(已完成/已取消),并返回任务用于冗余 itemId - return taskService.validateTaskNotFinished(reqVO.getTaskId()); + MesProTaskDO task = taskService.validateTaskNotFinished(reqVO.getTaskId()); + validateTaskRelation(task, workstation, workOrder, reqVO); + return task; + } + + private void validateTaskRelation(MesProTaskDO task, MesMdWorkstationDO workstation, + MesProWorkOrderDO workOrder, MesProFeedbackSaveReqVO reqVO) { + if (ObjUtil.notEqual(task.getWorkOrderId(), workOrder.getId())) { + throw exception(PRO_TASK_WORK_ORDER_MISMATCH); + } + if (ObjUtil.notEqual(task.getWorkstationId(), workstation.getId())) { + throw exception(PRO_TASK_WORKSTATION_MISMATCH); + } + if (ObjUtil.notEqual(task.getRouteId(), reqVO.getRouteId()) + || ObjUtil.notEqual(task.getProcessId(), reqVO.getProcessId())) { + throw exception(PRO_TASK_ROUTE_PROCESS_MISMATCH); + } + if (ObjUtil.notEqual(task.getItemId(), reqVO.getItemId())) { + throw exception(PRO_TASK_ITEM_MISMATCH); + } } @Override diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteProductBomServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteProductBomServiceImpl.java index 24aca4b..7b3ec2a 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteProductBomServiceImpl.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteProductBomServiceImpl.java @@ -1,10 +1,13 @@ package cn.iocoder.yudao.module.mes.service.pro.route; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.productbom.MesProRouteProductBomSaveReqVO; import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProductBomDO; import cn.iocoder.yudao.module.mes.dal.mysql.pro.route.MesProRouteProductBomMapper; +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; @@ -30,13 +33,16 @@ public class MesProRouteProductBomServiceImpl implements MesProRouteProductBomSe @Resource @Lazy private MesProRouteService routeService; + @Resource + private MesMdItemService itemService; + @Resource + private MesMdProductBomService productBomService; @Override public Long createRouteProductBom(MesProRouteProductBomSaveReqVO createReqVO) { - // 1.0 已启用的工艺路线,不允许操作 - routeService.validateRouteNotEnable(createReqVO.getRouteId()); - // 1.1 校验唯一性 - validateBomUnique(null, createReqVO.getItemId(), createReqVO.getProcessId(), createReqVO.getProductId()); + // 1. 校验数据 + validateRouteProductBomSaveData(null, createReqVO); + // 2. 插入 MesProRouteProductBomDO routeProductBom = BeanUtils.toBean(createReqVO, MesProRouteProductBomDO.class); routeProductBomMapper.insert(routeProductBom); @@ -45,13 +51,11 @@ public class MesProRouteProductBomServiceImpl implements MesProRouteProductBomSe @Override public void updateRouteProductBom(MesProRouteProductBomSaveReqVO updateReqVO) { - // 1.0 已启用的工艺路线,不允许操作 - routeService.validateRouteNotEnable(updateReqVO.getRouteId()); - // 1.1 校验存在 + // 1. 校验存在 + 校验数据 validateRouteProductBomExists(updateReqVO.getId()); - // 1.2 校验唯一性 - validateBomUnique(updateReqVO.getId(), updateReqVO.getItemId(), updateReqVO.getProcessId(), updateReqVO.getProductId()); - // 3. 更新 + validateRouteProductBomSaveData(updateReqVO.getId(), updateReqVO); + + // 2. 更新 MesProRouteProductBomDO updateObj = BeanUtils.toBean(updateReqVO, MesProRouteProductBomDO.class); routeProductBomMapper.updateById(updateObj); } @@ -75,6 +79,21 @@ public class MesProRouteProductBomServiceImpl implements MesProRouteProductBomSe } } + /** + * 校验保存时的关联数据 + * + * @param id 记录编号(新增时为 null) + * @param reqVO 保存请求 + */ + private void validateRouteProductBomSaveData(Long id, MesProRouteProductBomSaveReqVO reqVO) { + // 校验已启用的工艺路线,不允许操作 + routeService.validateRouteNotEnable(reqVO.getRouteId()); + // 校验唯一性 + validateBomUnique(id, reqVO.getItemId(), reqVO.getProcessId(), reqVO.getProductId()); + // 校验物料属于产品 BOM + validateBomItemBelongsToProduct(reqVO.getProductId(), reqVO.getItemId()); + } + private void validateBomUnique(Long id, Long itemId, Long processId, Long productId) { MesProRouteProductBomDO existing = routeProductBomMapper.selectByUnique(itemId, processId, productId); if (existing == null) { @@ -85,6 +104,14 @@ public class MesProRouteProductBomServiceImpl implements MesProRouteProductBomSe } } + private void validateBomItemBelongsToProduct(Long productId, Long itemId) { + itemService.validateItemExists(itemId); + if (!CollUtil.anyMatch(productBomService.getProductBomListByItemId(productId), + productBom -> ObjUtil.equal(productBom.getBomItemId(), itemId))) { + throw exception(MD_PRODUCT_BOM_ITEM_INVALID); + } + } + @Override public MesProRouteProductBomDO getRouteProductBom(Long id) { return routeProductBomMapper.selectById(id); 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 f995cd0..40d0777 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 @@ -9,6 +9,7 @@ import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.bom.MesProW 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.service.md.item.MesMdItemService; import cn.iocoder.yudao.module.mes.service.md.item.MesMdProductBomService; @@ -25,6 +26,7 @@ import java.util.Set; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.MD_ITEM_NOT_EXISTS; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.MD_PRODUCT_BOM_ITEM_INVALID; import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_WORK_ORDER_BOM_NOT_EXISTS; /** @@ -49,8 +51,8 @@ public class MesProWorkOrderBomServiceImpl implements MesProWorkOrderBomService @Override public Long createWorkOrderBom(MesProWorkOrderBomSaveReqVO createReqVO) { - // 校验工单存在 - workOrderService.validateWorkOrderExists(createReqVO.getWorkOrderId()); + // 校验数据 + validateWorkOrderBomSaveData(createReqVO); // 插入数据 MesProWorkOrderBomDO workOrderBom = BeanUtils.toBean(createReqVO, MesProWorkOrderBomDO.class); @@ -62,6 +64,8 @@ public class MesProWorkOrderBomServiceImpl implements MesProWorkOrderBomService public void updateWorkOrderBom(MesProWorkOrderBomSaveReqVO updateReqVO) { // 校验存在 validateWorkOrderBomExists(updateReqVO.getId()); + // 校验数据 + validateWorkOrderBomSaveData(updateReqVO); // 更新数据 MesProWorkOrderBomDO updateObj = BeanUtils.toBean(updateReqVO, MesProWorkOrderBomDO.class); @@ -83,6 +87,19 @@ public class MesProWorkOrderBomServiceImpl implements MesProWorkOrderBomService } } + private void validateWorkOrderBomSaveData(MesProWorkOrderBomSaveReqVO reqVO) { + // 校验工单存在 + MesProWorkOrderDO workOrder = workOrderService.validateWorkOrderExists(reqVO.getWorkOrderId()); + // DONE @AI:增加注释 + // 校验物料存在 + itemService.validateItemExists(reqVO.getItemId()); + // 校验物料属于产品 BOM + if (!CollUtil.anyMatch(productBomService.getProductBomListByItemId(workOrder.getProductId()), + productBom -> productBom.getBomItemId().equals(reqVO.getItemId()))) { + throw exception(MD_PRODUCT_BOM_ITEM_INVALID); + } + } + @Override public MesProWorkOrderBomDO getWorkOrderBom(Long id) { return workOrderBomMapper.selectById(id); @@ -133,4 +150,4 @@ public class MesProWorkOrderBomServiceImpl implements MesProWorkOrderBomService workOrderBomMapper.insertBatch(bomList); } -} \ No newline at end of file +} diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImpl.java index 98cc655..3363c66 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImpl.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImpl.java @@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.MesQcIpqcPageReqV import cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.MesQcIpqcSaveReqVO; import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProductDO; +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.dataobject.pro.feedback.MesProFeedbackDO; import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defectrecord.MesQcDefectRecordDO; @@ -23,6 +24,7 @@ import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationServic import cn.iocoder.yudao.module.mes.service.pro.feedback.MesProFeedbackService; import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteProcessService; import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteProductService; +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.mes.service.qc.defectrecord.MesQcDefectRecordService; import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateItemService; @@ -76,6 +78,9 @@ public class MesQcIpqcServiceImpl implements MesQcIpqcService { @Resource @Lazy private MesProRouteProcessService routeProcessService; + @Resource + @Lazy + private MesProTaskService taskService; @Resource private AdminUserApi adminUserApi; @@ -136,9 +141,39 @@ public class MesQcIpqcServiceImpl implements MesQcIpqcService { // 校验工位、检测人员存在 MesMdWorkstationDO workstation = workstationService.validateWorkstationExists(reqVO.getWorkstationId()); adminUserApi.validateUser(reqVO.getInspectorUserId()); + // 校验工单存在 + MesProWorkOrderDO workOrder = workOrderService.validateWorkOrderConfirmed(reqVO.getWorkOrderId()); + if (reqVO.getItemId() != null && ObjUtil.notEqual(reqVO.getItemId(), workOrder.getProductId())) { + throw exception(PRO_WORK_ORDER_PRODUCT_MISMATCH); + } + if (reqVO.getProcessId() != null && ObjUtil.notEqual(workstation.getProcessId(), reqVO.getProcessId())) { + throw exception(PRO_WORKSTATION_PROCESS_MISMATCH); + } + // 校验任务关系(如果指定了任务) + if (reqVO.getTaskId() != null) { + MesProTaskDO task = taskService.validateTaskNotFinished(reqVO.getTaskId()); + validateTaskRelation(task, workstation, workOrder, reqVO); + } return workstation; } + private void validateTaskRelation(MesProTaskDO task, MesMdWorkstationDO workstation, + MesProWorkOrderDO workOrder, MesQcIpqcSaveReqVO reqVO) { + if (ObjUtil.notEqual(task.getWorkOrderId(), workOrder.getId())) { + throw exception(PRO_TASK_WORK_ORDER_MISMATCH); + } + if (ObjUtil.notEqual(task.getWorkstationId(), workstation.getId())) { + throw exception(PRO_TASK_WORKSTATION_MISMATCH); + } + Long expectedProcessId = reqVO.getProcessId() != null ? reqVO.getProcessId() : workstation.getProcessId(); + if (expectedProcessId != null && ObjUtil.notEqual(task.getProcessId(), expectedProcessId)) { + throw exception(PRO_TASK_ROUTE_PROCESS_MISMATCH); + } + if (ObjUtil.notEqual(task.getItemId(), workOrder.getProductId())) { + throw exception(PRO_TASK_ITEM_MISMATCH); + } + } + @Override @Transactional(rollbackFor = Exception.class) public void finishIpqc(Long id) { @@ -238,8 +273,8 @@ public class MesQcIpqcServiceImpl implements MesQcIpqcService { return null; } if (Objects.equals(sourceDocType, MesBizTypeConstants.PRO_FEEDBACK)) { - MesProFeedbackDO feedback = feedbackService.getFeedback(sourceDocId); - return feedback != null ? feedback.getCode() : null; + MesProFeedbackDO feedback = feedbackService.validateFeedbackExists(sourceDocId); + return feedback.getCode(); } return null; } diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptServiceImpl.java index 6690cb7..b4de415 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptServiceImpl.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptServiceImpl.java @@ -8,11 +8,13 @@ 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.wm.itemreceipt.vo.MesWmItemReceiptPageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.MesWmItemReceiptSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalNoticeDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptDetailDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptLineDO; import cn.iocoder.yudao.module.mes.dal.mysql.wm.itemreceipt.MesWmItemReceiptMapper; import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmArrivalNoticeStatusEnum; import cn.iocoder.yudao.module.mes.enums.wm.MesWmItemReceiptStatusEnum; import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum; import cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService; @@ -90,7 +92,13 @@ public class MesWmItemReceiptServiceImpl implements MesWmItemReceiptService { vendorService.validateVendorExists(reqVO.getVendorId()); // 校验到货通知单存在 if (reqVO.getNoticeId() != null) { - arrivalNoticeService.validateArrivalNoticeExists(reqVO.getNoticeId()); + MesWmArrivalNoticeDO notice = arrivalNoticeService.validateArrivalNoticeExists(reqVO.getNoticeId()); + if (ObjUtil.notEqual(notice.getStatus(), MesWmArrivalNoticeStatusEnum.PENDING_RECEIPT.getStatus())) { + throw exception(WM_ARRIVAL_NOTICE_STATUS_NOT_PENDING_RECEIPT); + } + if (ObjUtil.notEqual(notice.getVendorId(), reqVO.getVendorId())) { + throw exception(WM_ARRIVAL_NOTICE_VENDOR_MISMATCH); + } } // 校验来料检验单存在 if (reqVO.getIqcId() != null) { diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/materialstock/MesWmMaterialStockService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/materialstock/MesWmMaterialStockService.java index 9d02bdf..a6e667c 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/materialstock/MesWmMaterialStockService.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/materialstock/MesWmMaterialStockService.java @@ -132,4 +132,20 @@ public interface MesWmMaterialStockService { */ void checkAreaMixingRule(Long areaId, Long itemId, Long batchId); + /** + * 校验前端选择的库存记录,兜底避免串单或越权提交 + * + * @param materialStockId 库存记录编号 + * @param itemId 物料编号 + * @param batchId 批次编号 + * @param batchCode 批次号(可选) + * @param warehouseId 仓库编号 + * @param locationId 库区编号 + * @param areaId 库位编号 + * @param quantity 数量(可选,校验库存充足) + * @return 校验通过的库存记录 + */ + MesWmMaterialStockDO validateSelectedStock(Long materialStockId, Long itemId, Long batchId, String batchCode, + Long warehouseId, Long locationId, Long areaId, BigDecimal quantity); + } diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/materialstock/MesWmMaterialStockServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/materialstock/MesWmMaterialStockServiceImpl.java index 249b5ee..a6b8e24 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/materialstock/MesWmMaterialStockServiceImpl.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/materialstock/MesWmMaterialStockServiceImpl.java @@ -185,4 +185,34 @@ public class MesWmMaterialStockServiceImpl implements MesWmMaterialStockService } } + @Override + public MesWmMaterialStockDO validateSelectedStock(Long materialStockId, + Long itemId, + Long batchId, + String batchCode, + Long warehouseId, + Long locationId, + Long areaId, + BigDecimal quantity) { + // 1. 校验库存记录必须存在 + if (materialStockId == null) { + throw exception(WM_MATERIAL_STOCK_REQUIRED); + } + MesWmMaterialStockDO stock = validateMaterialStockExists(materialStockId); + // 2. 校验库存记录的物料、批次、仓库、库区、库位等信息与前端选择的一致,避免串单或越权提交 + if (ObjUtil.notEqual(stock.getItemId(), itemId) + || ObjUtil.notEqual(stock.getBatchId(), batchId) + || (batchCode != null && ObjUtil.notEqual(stock.getBatchCode(), batchCode)) + || ObjUtil.notEqual(stock.getWarehouseId(), warehouseId) + || ObjUtil.notEqual(stock.getLocationId(), locationId) + || ObjUtil.notEqual(stock.getAreaId(), areaId)) { + throw exception(WM_MATERIAL_STOCK_SELECTION_MISMATCH); + } + // 3. 校验库存数量充足(如果前端传了 quantity,则必须保证库存数量 >= quantity) + if (quantity != null && stock.getQuantity() != null && stock.getQuantity().compareTo(quantity) < 0) { + throw exception(WM_MATERIAL_STOCK_INSUFFICIENT); + } + return stock; + } + } diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueDetailServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueDetailServiceImpl.java index 8ad0797..ca02527 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueDetailServiceImpl.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueDetailServiceImpl.java @@ -1,10 +1,14 @@ package cn.iocoder.yudao.module.mes.service.wm.outsourceissue; +import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.detail.MesWmOutsourceIssueDetailSaveReqVO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueDetailDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueLineDO; import cn.iocoder.yudao.module.mes.dal.mysql.wm.outsourceissue.MesWmOutsourceIssueDetailMapper; import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; import jakarta.annotation.Resource; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; @@ -13,7 +17,7 @@ import org.springframework.validation.annotation.Validated; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_OUTSOURCE_ISSUE_DETAIL_NOT_EXISTS; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; /** * MES 外协发料单明细 Service 实现类 @@ -28,9 +32,13 @@ public class MesWmOutsourceIssueDetailServiceImpl implements MesWmOutsourceIssue private MesWmOutsourceIssueDetailMapper outsourceIssueDetailMapper; @Resource @Lazy - private MesWmOutsourceIssueService outsourceIssueService; + private MesWmOutsourceIssueLineService outsourceIssueLineService; @Resource private MesMdItemService itemService; + @Resource + private MesWmWarehouseAreaService warehouseAreaService; + @Resource + private MesWmMaterialStockService materialStockService; @Override public Long createOutsourceIssueDetail(MesWmOutsourceIssueDetailSaveReqVO createReqVO) { @@ -95,10 +103,26 @@ public class MesWmOutsourceIssueDetailServiceImpl implements MesWmOutsourceIssue } private void validateOutsourceIssueDetailSaveData(MesWmOutsourceIssueDetailSaveReqVO saveReqVO) { - // 校验关联的发料单存在 - outsourceIssueService.getOutsourceIssue(saveReqVO.getIssueId()); - // 校验关联的物料存在 + // 校验父数据(行)存在 + MesWmOutsourceIssueLineDO line = outsourceIssueLineService.getOutsourceIssueLine(saveReqVO.getLineId()); + if (line == null) { + throw exception(WM_OUTSOURCE_ISSUE_LINE_NOT_EXISTS); + } + if (ObjUtil.notEqual(line.getIssueId(), saveReqVO.getIssueId())) { + throw exception(WM_OUTSOURCE_ISSUE_DETAIL_LINE_NOT_MATCH); + } + // 校验物料存在 itemService.validateItemExists(saveReqVO.getItemId()); + if (ObjUtil.notEqual(line.getItemId(), saveReqVO.getItemId())) { + throw exception(WM_OUTSOURCE_ISSUE_DETAIL_ITEM_MISMATCH); + } + // 校验仓库、库区、库位的关联关系 + warehouseAreaService.validateWarehouseAreaExists( + saveReqVO.getWarehouseId(), saveReqVO.getLocationId(), saveReqVO.getAreaId()); + // 校验库存记录存在且物料一致 + materialStockService.validateSelectedStock( + saveReqVO.getMaterialStockId(), saveReqVO.getItemId(), saveReqVO.getBatchId(), null, + saveReqVO.getWarehouseId(), saveReqVO.getLocationId(), saveReqVO.getAreaId(), saveReqVO.getQuantity()); } } diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueDetailServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueDetailServiceImpl.java index be75e99..bea4dd4 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueDetailServiceImpl.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueDetailServiceImpl.java @@ -9,6 +9,8 @@ import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productissue.MesWmProductIs import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productissue.MesWmProductIssueLineDO; import cn.iocoder.yudao.module.mes.dal.mysql.wm.productissue.MesWmProductIssueDetailMapper; import cn.iocoder.yudao.module.mes.enums.wm.MesWmProductIssueStatusEnum; +import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; import jakarta.annotation.Resource; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; @@ -35,6 +37,10 @@ public class MesWmProductIssueDetailServiceImpl implements MesWmProductIssueDeta @Resource @Lazy private MesWmProductIssueLineService issueLineService; + @Resource + private MesWmWarehouseAreaService warehouseAreaService; + @Resource + private MesWmMaterialStockService materialStockService; @Override public Long createProductIssueDetail(MesWmProductIssueDetailSaveReqVO createReqVO) { @@ -116,8 +122,18 @@ public class MesWmProductIssueDetailServiceImpl implements MesWmProductIssueDeta private void validateProductIssueDetailSaveData(MesWmProductIssueDetailSaveReqVO reqVO) { // 校验父数据存在 MesWmProductIssueLineDO line = issueLineService.validateProductIssueLineExists(reqVO.getLineId()); + if (ObjUtil.notEqual(line.getIssueId(), reqVO.getIssueId())) { + throw exception(WM_PRODUCT_ISSUE_DETAIL_LINE_NOT_MATCH); + } // 校验物料匹配(明细 itemId 必须与行 itemId 一致) validateDetailItemMatch(reqVO.getItemId(), line.getItemId()); + // 校验仓库、库区、库位的关联关系 + warehouseAreaService.validateWarehouseAreaExists( + reqVO.getWarehouseId(), reqVO.getLocationId(), reqVO.getAreaId()); + // 校验库存记录 + materialStockService.validateSelectedStock( + reqVO.getMaterialStockId(), reqVO.getItemId(), reqVO.getBatchId(), reqVO.getBatchCode(), + reqVO.getWarehouseId(), reqVO.getLocationId(), reqVO.getAreaId(), reqVO.getQuantity()); } /** @@ -130,4 +146,3 @@ public class MesWmProductIssueDetailServiceImpl implements MesWmProductIssueDeta } } - diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesDetailServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesDetailServiceImpl.java index 3f2657b..e8dd04f 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesDetailServiceImpl.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesDetailServiceImpl.java @@ -1,10 +1,13 @@ package cn.iocoder.yudao.module.mes.service.wm.productsales; +import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.detail.MesWmProductSalesDetailSaveReqVO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesDetailDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesLineDO; import cn.iocoder.yudao.module.mes.dal.mysql.wm.productsales.MesWmProductSalesDetailMapper; import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService; import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; @@ -29,17 +32,17 @@ public class MesWmProductSalesDetailServiceImpl implements MesWmProductSalesDeta @Resource private MesMdItemService itemService; - + @Resource + private MesWmProductSalesLineService productSalesLineService; + @Resource + private MesWmMaterialStockService materialStockService; @Resource private MesWmWarehouseAreaService warehouseAreaService; @Override public Long createProductSalesDetail(MesWmProductSalesDetailSaveReqVO createReqVO) { - // 校验物料存在 - itemService.validateItemExists(createReqVO.getItemId()); - // 校验库区关系 - warehouseAreaService.validateWarehouseAreaExists( - createReqVO.getWarehouseId(), createReqVO.getLocationId(), createReqVO.getAreaId()); + // 校验数据 + validateProductSalesDetailSaveData(createReqVO); // 插入 MesWmProductSalesDetailDO detail = BeanUtils.toBean(createReqVO, MesWmProductSalesDetailDO.class); @@ -51,11 +54,8 @@ public class MesWmProductSalesDetailServiceImpl implements MesWmProductSalesDeta public void updateProductSalesDetail(MesWmProductSalesDetailSaveReqVO updateReqVO) { // 校验存在 validateProductSalesDetailExists(updateReqVO.getId()); - // 校验物料存在 - itemService.validateItemExists(updateReqVO.getItemId()); - // 校验库区关系 - warehouseAreaService.validateWarehouseAreaExists( - updateReqVO.getWarehouseId(), updateReqVO.getLocationId(), updateReqVO.getAreaId()); + // 校验数据 + validateProductSalesDetailSaveData(updateReqVO); // 更新 MesWmProductSalesDetailDO updateObj = BeanUtils.toBean(updateReqVO, MesWmProductSalesDetailDO.class); @@ -103,4 +103,27 @@ public class MesWmProductSalesDetailServiceImpl implements MesWmProductSalesDeta return detail; } + private void validateProductSalesDetailSaveData(MesWmProductSalesDetailSaveReqVO reqVO) { + // 校验父数据(行)存在 + MesWmProductSalesLineDO line = productSalesLineService.getProductSalesLine(reqVO.getLineId()); + if (line == null) { + throw exception(WM_PRODUCT_SALES_LINE_NOT_EXISTS); + } + if (ObjUtil.notEqual(line.getSalesId(), reqVO.getSalesId())) { + throw exception(WM_PRODUCT_SALES_DETAIL_LINE_NOT_MATCH); + } + // 校验物料存在 + itemService.validateItemExists(reqVO.getItemId()); + if (ObjUtil.notEqual(line.getItemId(), reqVO.getItemId())) { + throw exception(WM_PRODUCT_SALES_DETAIL_ITEM_MISMATCH); + } + // 校验库位存在 + warehouseAreaService.validateWarehouseAreaExists( + reqVO.getWarehouseId(), reqVO.getLocationId(), reqVO.getAreaId()); + // 校验库存记录存在且物料一致 + materialStockService.validateSelectedStock( + reqVO.getMaterialStockId(), reqVO.getItemId(), reqVO.getBatchId(), reqVO.getBatchCode(), + reqVO.getWarehouseId(), reqVO.getLocationId(), reqVO.getAreaId(), reqVO.getQuantity()); + } + } diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesServiceImpl.java index e92a46e..52d0b07 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesServiceImpl.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesServiceImpl.java @@ -9,6 +9,7 @@ import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesPageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesSaveReqVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesShippingReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.salesnotice.MesWmSalesNoticeDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesDetailDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesLineDO; @@ -16,8 +17,10 @@ import cn.iocoder.yudao.module.mes.dal.mysql.wm.productsales.MesWmProductSalesMa import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; import cn.iocoder.yudao.module.mes.enums.wm.MesWmProductSalesStatusEnum; import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmSalesNoticeStatusEnum; import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum; import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService; +import cn.iocoder.yudao.module.mes.service.wm.salesnotice.MesWmSalesNoticeService; import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService; import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO; import jakarta.annotation.Resource; @@ -54,6 +57,9 @@ public class MesWmProductSalesServiceImpl implements MesWmProductSalesService { private MesMdClientService clientService; @Resource + private MesWmSalesNoticeService salesNoticeService; + + @Resource private MesWmTransactionService wmTransactionService; @Override @@ -262,6 +268,16 @@ public class MesWmProductSalesServiceImpl implements MesWmProductSalesService { validateCodeUnique(id, reqVO.getCode()); // 校验客户存在 clientService.validateClientExists(reqVO.getClientId()); + // 校验发货通知单 + if (reqVO.getNoticeId() != null) { + MesWmSalesNoticeDO notice = salesNoticeService.validateSalesNoticeExists(reqVO.getNoticeId()); + if (ObjUtil.notEqual(notice.getStatus(), MesWmSalesNoticeStatusEnum.APPROVED.getStatus())) { + throw exception(WM_SALES_NOTICE_STATUS_NOT_APPROVED); + } + if (ObjUtil.notEqual(notice.getClientId(), reqVO.getClientId())) { + throw exception(WM_SALES_NOTICE_CLIENT_MISMATCH); + } + } } private MesWmProductSalesDO validateProductSalesExists(Long id) { diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueDetailServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueDetailServiceImpl.java index f0a8781..885df10 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueDetailServiceImpl.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueDetailServiceImpl.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.mes.service.wm.returnissue; +import cn.hutool.core.util.ObjUtil; 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.wm.returnissue.vo.detail.MesWmReturnIssueDetailSaveReqVO; @@ -17,8 +18,7 @@ import java.math.BigDecimal; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_RETURN_ISSUE_DETAIL_NOT_EXISTS; -import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_RETURN_ISSUE_DETAIL_QUANTITY_EXCEED; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; /** * MES 生产退料明细 Service 实现类 @@ -105,11 +105,21 @@ public class MesWmReturnIssueDetailServiceImpl implements MesWmReturnIssueDetail private void validateReturnIssueDetailSaveData(MesWmReturnIssueDetailSaveReqVO reqVO) { // 校验父数据存在 MesWmReturnIssueLineDO line = issueLineService.validateReturnIssueLineExists(reqVO.getLineId()); + if (ObjUtil.notEqual(line.getIssueId(), reqVO.getIssueId())) { + throw exception(WM_RETURN_ISSUE_DETAIL_LINE_NOT_MATCH); + } + if (ObjUtil.notEqual(line.getItemId(), reqVO.getItemId())) { + throw exception(WM_RETURN_ISSUE_DETAIL_ITEM_MISMATCH); + } // 校验仓库、库区、库位的关联关系 warehouseAreaService.validateWarehouseAreaExists( reqVO.getWarehouseId(), reqVO.getLocationId(), reqVO.getAreaId()); // 校验库位物料/批次混放规则 materialStockService.checkAreaMixingRule(reqVO.getAreaId(), reqVO.getItemId(), reqVO.getBatchId()); + // 校验库存记录 + materialStockService.validateSelectedStock( + reqVO.getMaterialStockId(), reqVO.getItemId(), reqVO.getBatchId(), reqVO.getBatchCode(), + reqVO.getWarehouseId(), reqVO.getLocationId(), reqVO.getAreaId(), reqVO.getQuantity()); // 校验明细总数量不超过行数量(排除自身) validateDetailQuantityNotExceed(reqVO.getLineId(), reqVO.getQuantity(), reqVO.getId(), line); } diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorDetailServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorDetailServiceImpl.java index 91e4b7c..1252244 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorDetailServiceImpl.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorDetailServiceImpl.java @@ -3,12 +3,12 @@ package cn.iocoder.yudao.module.mes.service.wm.returnvendor; import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo.detail.MesWmReturnVendorDetailSaveReqVO; -import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnvendor.MesWmReturnVendorDetailDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnvendor.MesWmReturnVendorLineDO; import cn.iocoder.yudao.module.mes.dal.mysql.wm.returnvendor.MesWmReturnVendorDetailMapper; import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; import jakarta.annotation.Resource; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; @@ -32,12 +32,12 @@ public class MesWmReturnVendorDetailServiceImpl implements MesWmReturnVendorDeta @Resource @Lazy private MesWmReturnVendorLineService returnVendorLineService; - @Resource private MesMdItemService itemService; - @Resource private MesWmMaterialStockService materialStockService; + @Resource + private MesWmWarehouseAreaService warehouseAreaService; @Override public Long createReturnVendorDetail(MesWmReturnVendorDetailSaveReqVO createReqVO) { @@ -68,12 +68,18 @@ public class MesWmReturnVendorDetailServiceImpl implements MesWmReturnVendorDeta private void validateDetailSaveData(MesWmReturnVendorDetailSaveReqVO reqVO) { // 校验父数据(行)存在 MesWmReturnVendorLineDO line = returnVendorLineService.validateReturnVendorLineExists(reqVO.getLineId()); + if (ObjUtil.notEqual(line.getReturnId(), reqVO.getReturnId())) { + throw exception(WM_RETURN_VENDOR_DETAIL_LINE_NOT_MATCH); + } // 校验物料存在 itemService.validateItemExists(reqVO.getItemId()); // 校验物料与行物料一致 validateItemConsistency(reqVO.getItemId(), line); + // 校验库位存在 + warehouseAreaService.validateWarehouseAreaExists( + reqVO.getWarehouseId(), reqVO.getLocationId(), reqVO.getAreaId()); // 校验库存记录存在且物料一致 - validateMaterialStock(reqVO.getMaterialStockId(), line); + validateMaterialStock(reqVO, line); } @Override @@ -127,15 +133,11 @@ public class MesWmReturnVendorDetailServiceImpl implements MesWmReturnVendorDeta /** * 校验库存记录存在且物料与行物料一致 */ - private void validateMaterialStock(Long materialStockId, MesWmReturnVendorLineDO line) { - if (materialStockId == null) { - return; - } - MesWmMaterialStockDO stock = materialStockService.getMaterialStock(materialStockId); - if (stock == null) { - throw exception(WM_MATERIAL_STOCK_NOT_EXISTS); - } - if (ObjUtil.notEqual(stock.getItemId(), line.getItemId())) { + private void validateMaterialStock(MesWmReturnVendorDetailSaveReqVO reqVO, MesWmReturnVendorLineDO line) { + materialStockService.validateSelectedStock( + reqVO.getMaterialStockId(), reqVO.getItemId(), reqVO.getBatchId(), reqVO.getBatchCode(), + reqVO.getWarehouseId(), reqVO.getLocationId(), reqVO.getAreaId(), reqVO.getQuantity()); + if (ObjUtil.notEqual(line.getItemId(), reqVO.getItemId())) { throw exception(WM_RETURN_VENDOR_DETAIL_ITEM_MISMATCH); } } diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeService.java index 0eb8647..0a1d840 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeService.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeService.java @@ -40,6 +40,14 @@ public interface MesWmSalesNoticeService { void deleteSalesNotice(Long id); /** + * 校验发货通知单存在 + * + * @param id 编号 + * @return 发货通知单 + */ + MesWmSalesNoticeDO validateSalesNoticeExists(Long id); + + /** * 获得发货通知单 * * @param id 编号 diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeServiceImpl.java index dc2fe57..b129334 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeServiceImpl.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeServiceImpl.java @@ -111,7 +111,8 @@ public class MesWmSalesNoticeServiceImpl implements MesWmSalesNoticeService { return salesNoticeMapper.selectByIds(ids); } - private MesWmSalesNoticeDO validateSalesNoticeExists(Long id) { + @Override + public MesWmSalesNoticeDO validateSalesNoticeExists(Long id) { MesWmSalesNoticeDO notice = salesNoticeMapper.selectById(id); if (notice == null) { throw exception(WM_SALES_NOTICE_NOT_EXISTS);