Commit 6ccf334c71110d7833090cb9a452e1b1f0489090
1 parent
6f68fd61
✨ feat(wm): 新增库存记录编号字段及相关校验
在多个请求对象中新增库存记录编号字段,并在相关服务中实现校验逻辑,以确保库存记录的有效性和一致性。这将增强库存管理的准确性,避免潜在的错误提交。 - MesWmProductIssueDetailSaveReqVO.java: 新增 materialStockId 字段 - MesWmReturnIssueDetailSaveReqVO.java: 新增 materialStockId 字段 - MesWmMaterialStockService.java: 新增 validateSelectedStock 方法 - MesWmMaterialStockServiceImpl.java: 实现 validateSelectedStock 方法 - MesWmProductIssueDetailServiceImpl.java: 更新校验逻辑以使用库存记录 - MesWmReturnIssueDetailServiceImpl.java: 更新校验逻辑以使用库存记录 - MesWmOutsourceIssueDetailServiceImpl.java: 更新校验逻辑以使用库存记录 - MesWmProductSalesDetailServiceImpl.java: 更新校验逻辑以使用库存记录 - MesWmReturnVendorDetailServiceImpl.java: 更新校验逻辑以使用库存记录
Showing
25 changed files
with
414 additions
and
57 deletions
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 { |
| 26 | 26 | @NotNull(message = "物料编号不能为空") |
| 27 | 27 | private Long itemId; |
| 28 | 28 | |
| 29 | + @Schema(description = "库存记录编号", example = "1") | |
| 30 | + private Long materialStockId; | |
| 31 | + | |
| 29 | 32 | @Schema(description = "领料数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "300.00") |
| 30 | 33 | @NotNull(message = "领料数量不能为空") |
| 31 | 34 | @DecimalMin(value = "0", inclusive = false, message = "领料数量必须大于 0") |
| ... | ... | @@ -49,4 +52,4 @@ public class MesWmProductIssueDetailSaveReqVO { |
| 49 | 52 | @Schema(description = "备注", example = "备注") |
| 50 | 53 | private String remark; |
| 51 | 54 | |
| 52 | - } | |
| 55 | +} | ... | ... |
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 { |
| 26 | 26 | @NotNull(message = "物料编号不能为空") |
| 27 | 27 | private Long itemId; |
| 28 | 28 | |
| 29 | + @Schema(description = "库存记录编号", example = "1") | |
| 30 | + private Long materialStockId; | |
| 31 | + | |
| 29 | 32 | @Schema(description = "退料数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "300.00") |
| 30 | 33 | @NotNull(message = "退料数量不能为空") |
| 31 | 34 | @DecimalMin(value = "0", inclusive = false, message = "退料数量必须大于0") | ... | ... |
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java
| ... | ... | @@ -91,6 +91,7 @@ public interface ErrorCodeConstants { |
| 91 | 91 | ErrorCode MD_PRODUCT_BOM_NOT_EXISTS = new ErrorCode(1_040_107_000, "产品BOM不存在"); |
| 92 | 92 | ErrorCode MD_PRODUCT_BOM_SELF_REFERENCE = new ErrorCode(1_040_107_001, "产品不能作为自身的BOM物料"); |
| 93 | 93 | ErrorCode MD_PRODUCT_BOM_CIRCULAR = new ErrorCode(1_040_107_002, "BOM物料存在闭环,无法新增"); |
| 94 | + ErrorCode MD_PRODUCT_BOM_ITEM_INVALID = new ErrorCode(1_040_107_003, "选择的 BOM 物料不属于当前产品"); | |
| 94 | 95 | |
| 95 | 96 | // ========== MES 基础数据-产品SOP(1-040-108-000) ========== |
| 96 | 97 | ErrorCode MD_PRODUCT_SOP_NOT_EXISTS = new ErrorCode(1_040_108_000, "产品SOP不存在"); |
| ... | ... | @@ -167,6 +168,7 @@ public interface ErrorCodeConstants { |
| 167 | 168 | ErrorCode DV_CHECK_PLAN_NO_MACHINERY = new ErrorCode(1_040_302_003, "启用方案时,至少需要关联一台设备"); |
| 168 | 169 | ErrorCode DV_CHECK_PLAN_NO_SUBJECT = new ErrorCode(1_040_302_004, "启用方案时,至少需要关联一个点检保养项目"); |
| 169 | 170 | ErrorCode DV_CHECK_PLAN_NOT_ENABLED = new ErrorCode(1_040_302_005, "点检保养方案未启用,不允许停用"); |
| 171 | + ErrorCode DV_CHECK_PLAN_TYPE_MISMATCH = new ErrorCode(1_040_302_006, "点检保养方案类型与当前业务不匹配"); | |
| 170 | 172 | // ========== MES 设备管理-点检方案设备(1-040-302-100) ========== |
| 171 | 173 | ErrorCode DV_CHECK_PLAN_MACHINERY_NOT_EXISTS = new ErrorCode(1_040_302_100, "点检保养方案设备不存在"); |
| 172 | 174 | ErrorCode DV_CHECK_PLAN_MACHINERY_DUPLICATE = new ErrorCode(1_040_302_101, "该设备已关联到当前方案,请勿重复添加"); |
| ... | ... | @@ -241,11 +243,17 @@ public interface ErrorCodeConstants { |
| 241 | 243 | ErrorCode PRO_WORK_ORDER_NOT_PREPARE = new ErrorCode(1_040_502_002, "只有草稿状态的工单才能执行此操作"); |
| 242 | 244 | ErrorCode PRO_WORK_ORDER_NOT_CONFIRMED = new ErrorCode(1_040_502_003, "只有已确认状态的工单才能执行此操作"); |
| 243 | 245 | ErrorCode PRO_WORK_ORDER_HAS_CHILDREN = new ErrorCode(1_040_502_004, "存在子工单,无法删除"); |
| 246 | + ErrorCode PRO_WORK_ORDER_PRODUCT_MISMATCH = new ErrorCode(1_040_502_005, "当前产品物料与生产工单产品不一致"); | |
| 244 | 247 | ErrorCode PRO_WORK_ORDER_BOM_NOT_EXISTS = new ErrorCode(1_040_502_100, "生产工单BOM不存在"); |
| 245 | 248 | |
| 246 | 249 | // ========== MES 生产管理-生产任务(1-040-503-000) ========== |
| 247 | 250 | ErrorCode PRO_TASK_NOT_EXISTS = new ErrorCode(1_040_503_000, "生产任务不存在"); |
| 248 | 251 | ErrorCode PRO_TASK_ALREADY_FINISHED = new ErrorCode(1_040_503_001, "生产任务已完成或已取消,不能继续操作"); |
| 252 | + ErrorCode PRO_TASK_WORK_ORDER_MISMATCH = new ErrorCode(1_040_503_002, "生产任务不属于当前生产工单"); | |
| 253 | + ErrorCode PRO_TASK_WORKSTATION_MISMATCH = new ErrorCode(1_040_503_003, "生产任务不属于当前工作站"); | |
| 254 | + ErrorCode PRO_TASK_ROUTE_PROCESS_MISMATCH = new ErrorCode(1_040_503_004, "生产任务与当前工艺路线或工序不一致"); | |
| 255 | + ErrorCode PRO_TASK_ITEM_MISMATCH = new ErrorCode(1_040_503_005, "生产任务产品与当前产品物料不一致"); | |
| 256 | + ErrorCode PRO_WORKSTATION_PROCESS_MISMATCH = new ErrorCode(1_040_503_006, "工作站所属工序与当前工序不一致"); | |
| 249 | 257 | // ========== MES 生产管理-生产任务投料(1-040-503-100) ========== |
| 250 | 258 | ErrorCode PRO_TASK_ISSUE_NOT_EXISTS = new ErrorCode(1_040_503_100, "生产任务投料记录不存在"); |
| 251 | 259 | |
| ... | ... | @@ -399,6 +407,8 @@ public interface ErrorCodeConstants { |
| 399 | 407 | ErrorCode WM_TRANSACTION_RELATED_NOT_EXISTS = new ErrorCode(1_040_703_010, "关联的库存事务不存在"); |
| 400 | 408 | ErrorCode WM_TRANSACTION_LIST_EMPTY = new ErrorCode(1_040_703_011, "库存事务列表不能为空"); |
| 401 | 409 | ErrorCode WM_TRANSACTION_BATCH_NOT_EXISTS = new ErrorCode(1_040_703_012, "批次记录不存在"); |
| 410 | + ErrorCode WM_MATERIAL_STOCK_REQUIRED = new ErrorCode(1_040_703_013, "库存记录不能为空"); | |
| 411 | + ErrorCode WM_MATERIAL_STOCK_SELECTION_MISMATCH = new ErrorCode(1_040_703_014, "库存记录与提交的物料、批次或库位信息不一致"); | |
| 402 | 412 | |
| 403 | 413 | // ========== MES 仓库管理-到货通知单(1-040-704-000) ========== |
| 404 | 414 | ErrorCode WM_ARRIVAL_NOTICE_NOT_EXISTS = new ErrorCode(1_040_704_000, "到货通知单不存在"); |
| ... | ... | @@ -408,6 +418,7 @@ public interface ErrorCodeConstants { |
| 408 | 418 | ErrorCode WM_ARRIVAL_NOTICE_STATUS_NOT_PENDING_RECEIPT = new ErrorCode(1_040_704_004, "只有待入库状态才允许完成"); |
| 409 | 419 | ErrorCode WM_ARRIVAL_NOTICE_IQC_PENDING = new ErrorCode(1_040_704_005, "存在待检验行,无法审批通过"); |
| 410 | 420 | ErrorCode WM_ARRIVAL_NOTICE_NO_LINE = new ErrorCode(1_040_704_006, "至少需要一条行项目"); |
| 421 | + ErrorCode WM_ARRIVAL_NOTICE_VENDOR_MISMATCH = new ErrorCode(1_040_704_007, "到货通知单的供应商与当前单据不一致"); | |
| 411 | 422 | ErrorCode WM_ARRIVAL_NOTICE_LINE_NOT_EXISTS = new ErrorCode(1_040_704_100, "到货通知单行不存在"); |
| 412 | 423 | ErrorCode WM_ARRIVAL_NOTICE_LINE_NOT_MATCH = new ErrorCode(1_040_704_101, "到货通知单行不属于指定的到货通知单"); |
| 413 | 424 | |
| ... | ... | @@ -444,6 +455,8 @@ public interface ErrorCodeConstants { |
| 444 | 455 | ErrorCode WM_OUTSOURCE_ISSUE_LINE_NOT_EXISTS = new ErrorCode(1_040_707_100, "外协发料单行不存在"); |
| 445 | 456 | ErrorCode WM_OUTSOURCE_ISSUE_LINE_ITEM_NOT_IN_BOM = new ErrorCode(1_040_707_101, "发料单行对应的物料不在当前工单的 BOM 列表中"); |
| 446 | 457 | ErrorCode WM_OUTSOURCE_ISSUE_DETAIL_NOT_EXISTS = new ErrorCode(1_040_707_200, "外协发料单明细不存在"); |
| 458 | + ErrorCode WM_OUTSOURCE_ISSUE_DETAIL_LINE_NOT_MATCH = new ErrorCode(1_040_707_201, "拣货明细不属于指定的外协发料单"); | |
| 459 | + ErrorCode WM_OUTSOURCE_ISSUE_DETAIL_ITEM_MISMATCH = new ErrorCode(1_040_707_202, "拣货明细的物料与外协发料单行的物料不一致"); | |
| 447 | 460 | ErrorCode WM_OUTSOURCE_ISSUE_WORK_ORDER_TYPE_INVALID = new ErrorCode(1_040_707_008, "工单类型不是外协(代工)类型"); |
| 448 | 461 | |
| 449 | 462 | // ========== MES 仓库管理-生产领料出库单(1-040-708-000) ========== |
| ... | ... | @@ -459,6 +472,7 @@ public interface ErrorCodeConstants { |
| 459 | 472 | ErrorCode WM_PRODUCT_ISSUE_CODE_DUPLICATE = new ErrorCode(1_040_708_102, "领料出库单编码已存在"); |
| 460 | 473 | ErrorCode WM_PRODUCT_ISSUE_DETAIL_NOT_EXISTS = new ErrorCode(1_040_708_200, "生产领料出库单明细不存在"); |
| 461 | 474 | ErrorCode WM_PRODUCT_ISSUE_DETAIL_ITEM_MISMATCH = new ErrorCode(1_040_708_201, "拣货明细的物料与领料单行的物料不一致"); |
| 475 | + ErrorCode WM_PRODUCT_ISSUE_DETAIL_LINE_NOT_MATCH = new ErrorCode(1_040_708_202, "拣货明细不属于指定的领料出库单"); | |
| 462 | 476 | |
| 463 | 477 | // ========== MES 仓库管理-生产入库单(1-040-709-000) ========== |
| 464 | 478 | ErrorCode WM_PRODUCT_PRODUCE_NOT_EXISTS = new ErrorCode(1_040_709_000, "生产入库单不存在"); |
| ... | ... | @@ -501,6 +515,8 @@ public interface ErrorCodeConstants { |
| 501 | 515 | ErrorCode WM_RETURN_ISSUE_DETAIL_QUANTITY_INVALID = new ErrorCode(1_040_710_201, "退料明细数量必须大于0"); |
| 502 | 516 | ErrorCode WM_RETURN_ISSUE_DETAIL_QUANTITY_EXCEED = new ErrorCode(1_040_710_202, "退料明细总数量不能超过退料单行数量"); |
| 503 | 517 | ErrorCode WM_RETURN_ISSUE_CODE_DUPLICATE = new ErrorCode(1_040_710_203, "退料单编码已存在"); |
| 518 | + ErrorCode WM_RETURN_ISSUE_DETAIL_LINE_NOT_MATCH = new ErrorCode(1_040_710_204, "退料明细不属于指定的退料单"); | |
| 519 | + ErrorCode WM_RETURN_ISSUE_DETAIL_ITEM_MISMATCH = new ErrorCode(1_040_710_205, "退料明细的物料与退料单行的物料不一致"); | |
| 504 | 520 | |
| 505 | 521 | // ========== MES 仓库管理-供应商退货单(1-040-711-000) ========== |
| 506 | 522 | ErrorCode WM_RETURN_VENDOR_NOT_EXISTS = new ErrorCode(1_040_711_000, "供应商退货单不存在"); |
| ... | ... | @@ -514,6 +530,7 @@ public interface ErrorCodeConstants { |
| 514 | 530 | ErrorCode WM_RETURN_VENDOR_LINE_NOT_EXISTS = new ErrorCode(1_040_711_100, "供应商退货单行不存在"); |
| 515 | 531 | ErrorCode WM_RETURN_VENDOR_DETAIL_NOT_EXISTS = new ErrorCode(1_040_711_200, "供应商退货单明细不存在"); |
| 516 | 532 | ErrorCode WM_RETURN_VENDOR_DETAIL_QUANTITY_INVALID = new ErrorCode(1_040_711_201, "退货明细数量必须大于 0"); |
| 533 | + ErrorCode WM_RETURN_VENDOR_DETAIL_LINE_NOT_MATCH = new ErrorCode(1_040_711_202, "拣货明细不属于指定的供应商退货单"); | |
| 517 | 534 | |
| 518 | 535 | // ========== MES 仓库管理-产品收货单(1-040-712-000) ========== |
| 519 | 536 | ErrorCode WM_PRODUCT_RECPT_NOT_EXISTS = new ErrorCode(1_040_712_000, "产品收货单不存在"); |
| ... | ... | @@ -588,6 +605,8 @@ public interface ErrorCodeConstants { |
| 588 | 605 | ErrorCode WM_PRODUCT_SALES_DETAIL_NOT_EXISTS = new ErrorCode(1_040_714_012, "销售出库明细不存在"); |
| 589 | 606 | ErrorCode WM_PRODUCT_SALES_STOCK_INSUFFICIENT = new ErrorCode(1_040_714_013, "库存不足,无法拣货"); |
| 590 | 607 | ErrorCode WM_PRODUCT_SALES_LINE_QUANTITY_INVALID = new ErrorCode(1_040_714_014, "出库数量必须大于 0"); |
| 608 | + ErrorCode WM_PRODUCT_SALES_DETAIL_LINE_NOT_MATCH = new ErrorCode(1_040_714_015, "拣货明细不属于指定的销售出库单"); | |
| 609 | + ErrorCode WM_PRODUCT_SALES_DETAIL_ITEM_MISMATCH = new ErrorCode(1_040_714_016, "拣货明细的物料与销售出库单行的物料不一致"); | |
| 591 | 610 | |
| 592 | 611 | // ========== MES 仓库管理-杂项出库单(1-040-715-000) ========== |
| 593 | 612 | ErrorCode WM_MISC_ISSUE_NOT_EXISTS = new ErrorCode(1_040_715_000, "杂项出库单不存在"); |
| ... | ... | @@ -616,6 +635,8 @@ public interface ErrorCodeConstants { |
| 616 | 635 | ErrorCode WM_SALES_NOTICE_CODE_DUPLICATE = new ErrorCode(1_040_720_001, "通知单编号重复"); |
| 617 | 636 | ErrorCode WM_SALES_NOTICE_STATUS_NOT_ALLOW_DELETE = new ErrorCode(1_040_720_002, "单据状态不允许删除"); |
| 618 | 637 | ErrorCode WM_SALES_NOTICE_STATUS_NOT_ALLOW_UPDATE = new ErrorCode(1_040_720_003, "单据状态不允许修改"); |
| 638 | + ErrorCode WM_SALES_NOTICE_STATUS_NOT_APPROVED = new ErrorCode(1_040_720_004, "发货通知单不是待出库状态"); | |
| 639 | + ErrorCode WM_SALES_NOTICE_CLIENT_MISMATCH = new ErrorCode(1_040_720_005, "发货通知单的客户与当前单据不一致"); | |
| 619 | 640 | ErrorCode WM_SALES_NOTICE_LINE_NOT_EXISTS = new ErrorCode(1_040_720_010, "发货通知单行不存在"); |
| 620 | 641 | ErrorCode WM_SALES_NOTICE_LINE_EMPTY = new ErrorCode(1_040_720_011, "发货通知单行为空,不能提交"); |
| 621 | 642 | ... | ... |
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/dv/MesDvCheckPlanTypeEnum.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.mes.enums.dv; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.common.core.ArrayValuable; | |
| 4 | +import lombok.AllArgsConstructor; | |
| 5 | +import lombok.Getter; | |
| 6 | + | |
| 7 | +import java.util.Arrays; | |
| 8 | + | |
| 9 | +/** | |
| 10 | + * MES 点检保养方案类型枚举 | |
| 11 | + * | |
| 12 | + * @author 芋道源码 | |
| 13 | + */ | |
| 14 | +@Getter | |
| 15 | +@AllArgsConstructor | |
| 16 | +public enum MesDvCheckPlanTypeEnum implements ArrayValuable<Integer> { | |
| 17 | + | |
| 18 | + CHECK(1, "点检"), | |
| 19 | + MAINTENANCE(2, "保养"); | |
| 20 | + | |
| 21 | + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesDvCheckPlanTypeEnum::getType).toArray(Integer[]::new); | |
| 22 | + | |
| 23 | + /** | |
| 24 | + * 类型值 | |
| 25 | + */ | |
| 26 | + private final Integer type; | |
| 27 | + /** | |
| 28 | + * 类型名 | |
| 29 | + */ | |
| 30 | + private final String name; | |
| 31 | + | |
| 32 | + @Override | |
| 33 | + public Integer[] array() { | |
| 34 | + return ARRAYS; | |
| 35 | + } | |
| 36 | + | |
| 37 | +} | ... | ... |
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanService.java
| ... | ... | @@ -63,6 +63,15 @@ public interface MesDvCheckPlanService { |
| 63 | 63 | void validateCheckPlanExists(Long id); |
| 64 | 64 | |
| 65 | 65 | /** |
| 66 | + * 校验点检保养方案存在,且类型匹配 | |
| 67 | + * | |
| 68 | + * @param id 方案编号 | |
| 69 | + * @param type 期望的方案类型 | |
| 70 | + * @return 方案 | |
| 71 | + */ | |
| 72 | + MesDvCheckPlanDO validateCheckPlanExistsAndType(Long id, Integer type); | |
| 73 | + | |
| 74 | + /** | |
| 66 | 75 | * 校验点检保养方案为草稿状态 |
| 67 | 76 | * |
| 68 | 77 | * @param planId 方案编号 | ... | ... |
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 { |
| 149 | 149 | return plan; |
| 150 | 150 | } |
| 151 | 151 | |
| 152 | + @Override | |
| 153 | + public MesDvCheckPlanDO validateCheckPlanExistsAndType(Long id, Integer type) { | |
| 154 | + MesDvCheckPlanDO plan = doValidateCheckPlanExists(id); | |
| 155 | + if (ObjUtil.notEqual(plan.getType(), type)) { | |
| 156 | + throw exception(DV_CHECK_PLAN_TYPE_MISMATCH); | |
| 157 | + } | |
| 158 | + return plan; | |
| 159 | + } | |
| 160 | + | |
| 152 | 161 | private void validateCheckPlanCodeUnique(Long id, String code) { |
| 153 | 162 | MesDvCheckPlanDO plan = checkPlanMapper.selectByCode(code); |
| 154 | 163 | if (plan == null) { | ... | ... |
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 |
| 10 | 10 | import cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkrecord.MesDvCheckRecordDO; |
| 11 | 11 | import cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkrecord.MesDvCheckRecordLineDO; |
| 12 | 12 | import cn.iocoder.yudao.module.mes.enums.dv.MesDvCheckRecordStatusEnum; |
| 13 | +import cn.iocoder.yudao.module.mes.enums.dv.MesDvCheckPlanTypeEnum; | |
| 13 | 14 | import cn.iocoder.yudao.module.mes.enums.dv.MesDvCheckResultEnum; |
| 14 | 15 | import cn.iocoder.yudao.module.mes.dal.mysql.dv.checkrecord.MesDvCheckRecordMapper; |
| 15 | 16 | import cn.iocoder.yudao.module.mes.service.dv.checkplan.MesDvCheckPlanService; |
| ... | ... | @@ -37,6 +38,7 @@ import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; |
| 37 | 38 | @Validated |
| 38 | 39 | public class MesDvCheckRecordServiceImpl implements MesDvCheckRecordService { |
| 39 | 40 | |
| 41 | + | |
| 40 | 42 | @Resource |
| 41 | 43 | private MesDvCheckRecordMapper checkRecordMapper; |
| 42 | 44 | @Resource |
| ... | ... | @@ -162,7 +164,7 @@ public class MesDvCheckRecordServiceImpl implements MesDvCheckRecordService { |
| 162 | 164 | machineryService.validateMachineryExists(reqVO.getMachineryId()); |
| 163 | 165 | // 校验点检计划是否存在 |
| 164 | 166 | if (reqVO.getPlanId() != null) { |
| 165 | - checkPlanService.validateCheckPlanExists(reqVO.getPlanId()); | |
| 167 | + checkPlanService.validateCheckPlanExistsAndType(reqVO.getPlanId(), MesDvCheckPlanTypeEnum.CHECK.getType()); | |
| 166 | 168 | } |
| 167 | 169 | // 校验点检人是否存在 |
| 168 | 170 | if (reqVO.getUserId() != null) { | ... | ... |
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 |
| 10 | 10 | import cn.iocoder.yudao.module.mes.dal.dataobject.dv.maintenrecord.MesDvMaintenRecordLineDO; |
| 11 | 11 | import cn.iocoder.yudao.module.mes.dal.mysql.dv.maintenrecord.MesDvMaintenRecordMapper; |
| 12 | 12 | import cn.iocoder.yudao.module.mes.enums.dv.MesDvMaintenRecordStatusEnum; |
| 13 | +import cn.iocoder.yudao.module.mes.enums.dv.MesDvCheckPlanTypeEnum; | |
| 13 | 14 | import cn.iocoder.yudao.module.mes.service.dv.checkplan.MesDvCheckPlanService; |
| 14 | 15 | import cn.iocoder.yudao.module.mes.service.dv.machinery.MesDvMachineryService; |
| 15 | 16 | import jakarta.annotation.Resource; |
| ... | ... | @@ -100,7 +101,7 @@ public class MesDvMaintenRecordServiceImpl implements MesDvMaintenRecordService |
| 100 | 101 | machineryService.validateMachineryExists(reqVO.getMachineryId()); |
| 101 | 102 | // 校验保养计划是否存在 |
| 102 | 103 | if (reqVO.getPlanId() != null) { |
| 103 | - checkPlanService.validateCheckPlanExists(reqVO.getPlanId()); | |
| 104 | + checkPlanService.validateCheckPlanExistsAndType(reqVO.getPlanId(), MesDvCheckPlanTypeEnum.MAINTENANCE.getType()); | |
| 104 | 105 | } |
| 105 | 106 | } |
| 106 | 107 | ... | ... |
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; |
| 7 | 7 | import cn.iocoder.yudao.module.mes.controller.admin.pro.card.vo.MesProCardPageReqVO; |
| 8 | 8 | import cn.iocoder.yudao.module.mes.controller.admin.pro.card.vo.MesProCardSaveReqVO; |
| 9 | 9 | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.card.MesProCardDO; |
| 10 | +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; | |
| 10 | 11 | import cn.iocoder.yudao.module.mes.dal.mysql.pro.card.MesProCardMapper; |
| 11 | 12 | import cn.iocoder.yudao.module.mes.enums.pro.MesProWorkOrderStatusEnum; |
| 12 | 13 | import cn.iocoder.yudao.module.mes.enums.wm.BarcodeBizTypeEnum; |
| ... | ... | @@ -171,9 +172,12 @@ public class MesProCardServiceImpl implements MesProCardService { |
| 171 | 172 | // 校验编码唯一 |
| 172 | 173 | validateCardCodeUnique(reqVO.getId(), reqVO.getCode()); |
| 173 | 174 | // 校验工单存在 |
| 174 | - workOrderService.validateWorkOrderExists(reqVO.getWorkOrderId()); | |
| 175 | + MesProWorkOrderDO workOrder = workOrderService.validateWorkOrderConfirmed(reqVO.getWorkOrderId()); | |
| 175 | 176 | // 校验物料存在 |
| 176 | 177 | itemService.validateItemExists(reqVO.getItemId()); |
| 178 | + if (ObjUtil.notEqual(workOrder.getProductId(), reqVO.getItemId())) { | |
| 179 | + throw exception(PRO_WORK_ORDER_PRODUCT_MISMATCH); | |
| 180 | + } | |
| 177 | 181 | } |
| 178 | 182 | |
| 179 | 183 | } | ... | ... |
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackService.java
| ... | ... | @@ -46,6 +46,14 @@ public interface MesProFeedbackService { |
| 46 | 46 | MesProFeedbackDO getFeedback(Long id); |
| 47 | 47 | |
| 48 | 48 | /** |
| 49 | + * 校验生产报工存在 | |
| 50 | + * | |
| 51 | + * @param id 编号 | |
| 52 | + * @return 生产报工 | |
| 53 | + */ | |
| 54 | + MesProFeedbackDO validateFeedbackExists(Long id); | |
| 55 | + | |
| 56 | + /** | |
| 49 | 57 | * 获得生产报工分页 |
| 50 | 58 | * |
| 51 | 59 | * @param pageReqVO 分页查询 | ... | ... |
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; |
| 4 | 4 | import cn.hutool.core.util.ObjectUtil; |
| 5 | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | 6 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 7 | +import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; | |
| 7 | 8 | import cn.iocoder.yudao.module.mes.controller.admin.pro.feedback.vo.MesProFeedbackPageReqVO; |
| 8 | 9 | import cn.iocoder.yudao.module.mes.controller.admin.pro.feedback.vo.MesProFeedbackSaveReqVO; |
| 9 | 10 | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.feedback.MesProFeedbackDO; |
| 10 | 11 | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProcessDO; |
| 11 | 12 | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.task.MesProTaskDO; |
| 13 | +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; | |
| 12 | 14 | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemconsume.MesWmItemConsumeDO; |
| 13 | 15 | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceDO; |
| 14 | 16 | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceLineDO; |
| ... | ... | @@ -219,7 +221,8 @@ public class MesProFeedbackServiceImpl implements MesProFeedbackService { |
| 219 | 221 | |
| 220 | 222 | // ==================== 校验方法 ==================== |
| 221 | 223 | |
| 222 | - private MesProFeedbackDO validateFeedbackExists(Long id) { | |
| 224 | + @Override | |
| 225 | + public MesProFeedbackDO validateFeedbackExists(Long id) { | |
| 223 | 226 | MesProFeedbackDO feedback = feedbackMapper.selectById(id); |
| 224 | 227 | if (feedback == null) { |
| 225 | 228 | throw exception(PRO_FEEDBACK_NOT_EXISTS); |
| ... | ... | @@ -251,7 +254,10 @@ public class MesProFeedbackServiceImpl implements MesProFeedbackService { |
| 251 | 254 | */ |
| 252 | 255 | private MesProTaskDO validateFeedbackData(MesProFeedbackSaveReqVO reqVO) { |
| 253 | 256 | // 1. 校验工作站存在 |
| 254 | - workstationService.validateWorkstationExists(reqVO.getWorkstationId()); | |
| 257 | + MesMdWorkstationDO workstation = workstationService.validateWorkstationExists(reqVO.getWorkstationId()); | |
| 258 | + if (ObjUtil.notEqual(workstation.getProcessId(), reqVO.getProcessId())) { | |
| 259 | + throw exception(PRO_WORKSTATION_PROCESS_MISMATCH); | |
| 260 | + } | |
| 255 | 261 | |
| 256 | 262 | // 2.1 校验工艺路线 + 工序配置有效 |
| 257 | 263 | MesProRouteProcessDO routeProcess = routeProcessService.getRouteProcessByRouteIdAndProcessId( |
| ... | ... | @@ -277,10 +283,32 @@ public class MesProFeedbackServiceImpl implements MesProFeedbackService { |
| 277 | 283 | } |
| 278 | 284 | |
| 279 | 285 | // 3. 校验工单已确认 |
| 280 | - workOrderService.validateWorkOrderConfirmed(reqVO.getWorkOrderId()); | |
| 286 | + MesProWorkOrderDO workOrder = workOrderService.validateWorkOrderConfirmed(reqVO.getWorkOrderId()); | |
| 287 | + if (ObjUtil.notEqual(workOrder.getProductId(), reqVO.getItemId())) { | |
| 288 | + throw exception(PRO_WORK_ORDER_PRODUCT_MISMATCH); | |
| 289 | + } | |
| 281 | 290 | |
| 282 | 291 | // 4. 校验任务存在且未终态(已完成/已取消),并返回任务用于冗余 itemId |
| 283 | - return taskService.validateTaskNotFinished(reqVO.getTaskId()); | |
| 292 | + MesProTaskDO task = taskService.validateTaskNotFinished(reqVO.getTaskId()); | |
| 293 | + validateTaskRelation(task, workstation, workOrder, reqVO); | |
| 294 | + return task; | |
| 295 | + } | |
| 296 | + | |
| 297 | + private void validateTaskRelation(MesProTaskDO task, MesMdWorkstationDO workstation, | |
| 298 | + MesProWorkOrderDO workOrder, MesProFeedbackSaveReqVO reqVO) { | |
| 299 | + if (ObjUtil.notEqual(task.getWorkOrderId(), workOrder.getId())) { | |
| 300 | + throw exception(PRO_TASK_WORK_ORDER_MISMATCH); | |
| 301 | + } | |
| 302 | + if (ObjUtil.notEqual(task.getWorkstationId(), workstation.getId())) { | |
| 303 | + throw exception(PRO_TASK_WORKSTATION_MISMATCH); | |
| 304 | + } | |
| 305 | + if (ObjUtil.notEqual(task.getRouteId(), reqVO.getRouteId()) | |
| 306 | + || ObjUtil.notEqual(task.getProcessId(), reqVO.getProcessId())) { | |
| 307 | + throw exception(PRO_TASK_ROUTE_PROCESS_MISMATCH); | |
| 308 | + } | |
| 309 | + if (ObjUtil.notEqual(task.getItemId(), reqVO.getItemId())) { | |
| 310 | + throw exception(PRO_TASK_ITEM_MISMATCH); | |
| 311 | + } | |
| 284 | 312 | } |
| 285 | 313 | |
| 286 | 314 | @Override | ... | ... |
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteProductBomServiceImpl.java
| 1 | 1 | package cn.iocoder.yudao.module.mes.service.pro.route; |
| 2 | 2 | |
| 3 | +import cn.hutool.core.collection.CollUtil; | |
| 3 | 4 | import cn.hutool.core.util.ObjUtil; |
| 4 | 5 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 5 | 6 | import cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.productbom.MesProRouteProductBomSaveReqVO; |
| 6 | 7 | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProductBomDO; |
| 7 | 8 | import cn.iocoder.yudao.module.mes.dal.mysql.pro.route.MesProRouteProductBomMapper; |
| 9 | +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; | |
| 10 | +import cn.iocoder.yudao.module.mes.service.md.item.MesMdProductBomService; | |
| 8 | 11 | import jakarta.annotation.Resource; |
| 9 | 12 | import org.springframework.context.annotation.Lazy; |
| 10 | 13 | import org.springframework.stereotype.Service; |
| ... | ... | @@ -30,13 +33,16 @@ public class MesProRouteProductBomServiceImpl implements MesProRouteProductBomSe |
| 30 | 33 | @Resource |
| 31 | 34 | @Lazy |
| 32 | 35 | private MesProRouteService routeService; |
| 36 | + @Resource | |
| 37 | + private MesMdItemService itemService; | |
| 38 | + @Resource | |
| 39 | + private MesMdProductBomService productBomService; | |
| 33 | 40 | |
| 34 | 41 | @Override |
| 35 | 42 | public Long createRouteProductBom(MesProRouteProductBomSaveReqVO createReqVO) { |
| 36 | - // 1.0 已启用的工艺路线,不允许操作 | |
| 37 | - routeService.validateRouteNotEnable(createReqVO.getRouteId()); | |
| 38 | - // 1.1 校验唯一性 | |
| 39 | - validateBomUnique(null, createReqVO.getItemId(), createReqVO.getProcessId(), createReqVO.getProductId()); | |
| 43 | + // 1. 校验数据 | |
| 44 | + validateRouteProductBomSaveData(null, createReqVO); | |
| 45 | + | |
| 40 | 46 | // 2. 插入 |
| 41 | 47 | MesProRouteProductBomDO routeProductBom = BeanUtils.toBean(createReqVO, MesProRouteProductBomDO.class); |
| 42 | 48 | routeProductBomMapper.insert(routeProductBom); |
| ... | ... | @@ -45,13 +51,11 @@ public class MesProRouteProductBomServiceImpl implements MesProRouteProductBomSe |
| 45 | 51 | |
| 46 | 52 | @Override |
| 47 | 53 | public void updateRouteProductBom(MesProRouteProductBomSaveReqVO updateReqVO) { |
| 48 | - // 1.0 已启用的工艺路线,不允许操作 | |
| 49 | - routeService.validateRouteNotEnable(updateReqVO.getRouteId()); | |
| 50 | - // 1.1 校验存在 | |
| 54 | + // 1. 校验存在 + 校验数据 | |
| 51 | 55 | validateRouteProductBomExists(updateReqVO.getId()); |
| 52 | - // 1.2 校验唯一性 | |
| 53 | - validateBomUnique(updateReqVO.getId(), updateReqVO.getItemId(), updateReqVO.getProcessId(), updateReqVO.getProductId()); | |
| 54 | - // 3. 更新 | |
| 56 | + validateRouteProductBomSaveData(updateReqVO.getId(), updateReqVO); | |
| 57 | + | |
| 58 | + // 2. 更新 | |
| 55 | 59 | MesProRouteProductBomDO updateObj = BeanUtils.toBean(updateReqVO, MesProRouteProductBomDO.class); |
| 56 | 60 | routeProductBomMapper.updateById(updateObj); |
| 57 | 61 | } |
| ... | ... | @@ -75,6 +79,21 @@ public class MesProRouteProductBomServiceImpl implements MesProRouteProductBomSe |
| 75 | 79 | } |
| 76 | 80 | } |
| 77 | 81 | |
| 82 | + /** | |
| 83 | + * 校验保存时的关联数据 | |
| 84 | + * | |
| 85 | + * @param id 记录编号(新增时为 null) | |
| 86 | + * @param reqVO 保存请求 | |
| 87 | + */ | |
| 88 | + private void validateRouteProductBomSaveData(Long id, MesProRouteProductBomSaveReqVO reqVO) { | |
| 89 | + // 校验已启用的工艺路线,不允许操作 | |
| 90 | + routeService.validateRouteNotEnable(reqVO.getRouteId()); | |
| 91 | + // 校验唯一性 | |
| 92 | + validateBomUnique(id, reqVO.getItemId(), reqVO.getProcessId(), reqVO.getProductId()); | |
| 93 | + // 校验物料属于产品 BOM | |
| 94 | + validateBomItemBelongsToProduct(reqVO.getProductId(), reqVO.getItemId()); | |
| 95 | + } | |
| 96 | + | |
| 78 | 97 | private void validateBomUnique(Long id, Long itemId, Long processId, Long productId) { |
| 79 | 98 | MesProRouteProductBomDO existing = routeProductBomMapper.selectByUnique(itemId, processId, productId); |
| 80 | 99 | if (existing == null) { |
| ... | ... | @@ -85,6 +104,14 @@ public class MesProRouteProductBomServiceImpl implements MesProRouteProductBomSe |
| 85 | 104 | } |
| 86 | 105 | } |
| 87 | 106 | |
| 107 | + private void validateBomItemBelongsToProduct(Long productId, Long itemId) { | |
| 108 | + itemService.validateItemExists(itemId); | |
| 109 | + if (!CollUtil.anyMatch(productBomService.getProductBomListByItemId(productId), | |
| 110 | + productBom -> ObjUtil.equal(productBom.getBomItemId(), itemId))) { | |
| 111 | + throw exception(MD_PRODUCT_BOM_ITEM_INVALID); | |
| 112 | + } | |
| 113 | + } | |
| 114 | + | |
| 88 | 115 | @Override |
| 89 | 116 | public MesProRouteProductBomDO getRouteProductBom(Long id) { |
| 90 | 117 | return routeProductBomMapper.selectById(id); | ... | ... |
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 |
| 9 | 9 | import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; |
| 10 | 10 | import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdProductBomDO; |
| 11 | 11 | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderBomDO; |
| 12 | +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; | |
| 12 | 13 | import cn.iocoder.yudao.module.mes.dal.mysql.pro.workorder.MesProWorkOrderBomMapper; |
| 13 | 14 | import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; |
| 14 | 15 | import cn.iocoder.yudao.module.mes.service.md.item.MesMdProductBomService; |
| ... | ... | @@ -25,6 +26,7 @@ import java.util.Set; |
| 25 | 26 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 26 | 27 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| 27 | 28 | import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.MD_ITEM_NOT_EXISTS; |
| 29 | +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.MD_PRODUCT_BOM_ITEM_INVALID; | |
| 28 | 30 | import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_WORK_ORDER_BOM_NOT_EXISTS; |
| 29 | 31 | |
| 30 | 32 | /** |
| ... | ... | @@ -49,8 +51,8 @@ public class MesProWorkOrderBomServiceImpl implements MesProWorkOrderBomService |
| 49 | 51 | |
| 50 | 52 | @Override |
| 51 | 53 | public Long createWorkOrderBom(MesProWorkOrderBomSaveReqVO createReqVO) { |
| 52 | - // 校验工单存在 | |
| 53 | - workOrderService.validateWorkOrderExists(createReqVO.getWorkOrderId()); | |
| 54 | + // 校验数据 | |
| 55 | + validateWorkOrderBomSaveData(createReqVO); | |
| 54 | 56 | |
| 55 | 57 | // 插入数据 |
| 56 | 58 | MesProWorkOrderBomDO workOrderBom = BeanUtils.toBean(createReqVO, MesProWorkOrderBomDO.class); |
| ... | ... | @@ -62,6 +64,8 @@ public class MesProWorkOrderBomServiceImpl implements MesProWorkOrderBomService |
| 62 | 64 | public void updateWorkOrderBom(MesProWorkOrderBomSaveReqVO updateReqVO) { |
| 63 | 65 | // 校验存在 |
| 64 | 66 | validateWorkOrderBomExists(updateReqVO.getId()); |
| 67 | + // 校验数据 | |
| 68 | + validateWorkOrderBomSaveData(updateReqVO); | |
| 65 | 69 | |
| 66 | 70 | // 更新数据 |
| 67 | 71 | MesProWorkOrderBomDO updateObj = BeanUtils.toBean(updateReqVO, MesProWorkOrderBomDO.class); |
| ... | ... | @@ -83,6 +87,19 @@ public class MesProWorkOrderBomServiceImpl implements MesProWorkOrderBomService |
| 83 | 87 | } |
| 84 | 88 | } |
| 85 | 89 | |
| 90 | + private void validateWorkOrderBomSaveData(MesProWorkOrderBomSaveReqVO reqVO) { | |
| 91 | + // 校验工单存在 | |
| 92 | + MesProWorkOrderDO workOrder = workOrderService.validateWorkOrderExists(reqVO.getWorkOrderId()); | |
| 93 | + // DONE @AI:增加注释 | |
| 94 | + // 校验物料存在 | |
| 95 | + itemService.validateItemExists(reqVO.getItemId()); | |
| 96 | + // 校验物料属于产品 BOM | |
| 97 | + if (!CollUtil.anyMatch(productBomService.getProductBomListByItemId(workOrder.getProductId()), | |
| 98 | + productBom -> productBom.getBomItemId().equals(reqVO.getItemId()))) { | |
| 99 | + throw exception(MD_PRODUCT_BOM_ITEM_INVALID); | |
| 100 | + } | |
| 101 | + } | |
| 102 | + | |
| 86 | 103 | @Override |
| 87 | 104 | public MesProWorkOrderBomDO getWorkOrderBom(Long id) { |
| 88 | 105 | return workOrderBomMapper.selectById(id); |
| ... | ... | @@ -133,4 +150,4 @@ public class MesProWorkOrderBomServiceImpl implements MesProWorkOrderBomService |
| 133 | 150 | workOrderBomMapper.insertBatch(bomList); |
| 134 | 151 | } |
| 135 | 152 | |
| 136 | -} | |
| 137 | 153 | \ No newline at end of file |
| 154 | +} | ... | ... |
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 |
| 8 | 8 | import cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.MesQcIpqcSaveReqVO; |
| 9 | 9 | import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; |
| 10 | 10 | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProductDO; |
| 11 | +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.task.MesProTaskDO; | |
| 11 | 12 | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; |
| 12 | 13 | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.feedback.MesProFeedbackDO; |
| 13 | 14 | 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 |
| 23 | 24 | import cn.iocoder.yudao.module.mes.service.pro.feedback.MesProFeedbackService; |
| 24 | 25 | import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteProcessService; |
| 25 | 26 | import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteProductService; |
| 27 | +import cn.iocoder.yudao.module.mes.service.pro.task.MesProTaskService; | |
| 26 | 28 | import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; |
| 27 | 29 | import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService; |
| 28 | 30 | import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateItemService; |
| ... | ... | @@ -76,6 +78,9 @@ public class MesQcIpqcServiceImpl implements MesQcIpqcService { |
| 76 | 78 | @Resource |
| 77 | 79 | @Lazy |
| 78 | 80 | private MesProRouteProcessService routeProcessService; |
| 81 | + @Resource | |
| 82 | + @Lazy | |
| 83 | + private MesProTaskService taskService; | |
| 79 | 84 | |
| 80 | 85 | @Resource |
| 81 | 86 | private AdminUserApi adminUserApi; |
| ... | ... | @@ -136,9 +141,39 @@ public class MesQcIpqcServiceImpl implements MesQcIpqcService { |
| 136 | 141 | // 校验工位、检测人员存在 |
| 137 | 142 | MesMdWorkstationDO workstation = workstationService.validateWorkstationExists(reqVO.getWorkstationId()); |
| 138 | 143 | adminUserApi.validateUser(reqVO.getInspectorUserId()); |
| 144 | + // 校验工单存在 | |
| 145 | + MesProWorkOrderDO workOrder = workOrderService.validateWorkOrderConfirmed(reqVO.getWorkOrderId()); | |
| 146 | + if (reqVO.getItemId() != null && ObjUtil.notEqual(reqVO.getItemId(), workOrder.getProductId())) { | |
| 147 | + throw exception(PRO_WORK_ORDER_PRODUCT_MISMATCH); | |
| 148 | + } | |
| 149 | + if (reqVO.getProcessId() != null && ObjUtil.notEqual(workstation.getProcessId(), reqVO.getProcessId())) { | |
| 150 | + throw exception(PRO_WORKSTATION_PROCESS_MISMATCH); | |
| 151 | + } | |
| 152 | + // 校验任务关系(如果指定了任务) | |
| 153 | + if (reqVO.getTaskId() != null) { | |
| 154 | + MesProTaskDO task = taskService.validateTaskNotFinished(reqVO.getTaskId()); | |
| 155 | + validateTaskRelation(task, workstation, workOrder, reqVO); | |
| 156 | + } | |
| 139 | 157 | return workstation; |
| 140 | 158 | } |
| 141 | 159 | |
| 160 | + private void validateTaskRelation(MesProTaskDO task, MesMdWorkstationDO workstation, | |
| 161 | + MesProWorkOrderDO workOrder, MesQcIpqcSaveReqVO reqVO) { | |
| 162 | + if (ObjUtil.notEqual(task.getWorkOrderId(), workOrder.getId())) { | |
| 163 | + throw exception(PRO_TASK_WORK_ORDER_MISMATCH); | |
| 164 | + } | |
| 165 | + if (ObjUtil.notEqual(task.getWorkstationId(), workstation.getId())) { | |
| 166 | + throw exception(PRO_TASK_WORKSTATION_MISMATCH); | |
| 167 | + } | |
| 168 | + Long expectedProcessId = reqVO.getProcessId() != null ? reqVO.getProcessId() : workstation.getProcessId(); | |
| 169 | + if (expectedProcessId != null && ObjUtil.notEqual(task.getProcessId(), expectedProcessId)) { | |
| 170 | + throw exception(PRO_TASK_ROUTE_PROCESS_MISMATCH); | |
| 171 | + } | |
| 172 | + if (ObjUtil.notEqual(task.getItemId(), workOrder.getProductId())) { | |
| 173 | + throw exception(PRO_TASK_ITEM_MISMATCH); | |
| 174 | + } | |
| 175 | + } | |
| 176 | + | |
| 142 | 177 | @Override |
| 143 | 178 | @Transactional(rollbackFor = Exception.class) |
| 144 | 179 | public void finishIpqc(Long id) { |
| ... | ... | @@ -238,8 +273,8 @@ public class MesQcIpqcServiceImpl implements MesQcIpqcService { |
| 238 | 273 | return null; |
| 239 | 274 | } |
| 240 | 275 | if (Objects.equals(sourceDocType, MesBizTypeConstants.PRO_FEEDBACK)) { |
| 241 | - MesProFeedbackDO feedback = feedbackService.getFeedback(sourceDocId); | |
| 242 | - return feedback != null ? feedback.getCode() : null; | |
| 276 | + MesProFeedbackDO feedback = feedbackService.validateFeedbackExists(sourceDocId); | |
| 277 | + return feedback.getCode(); | |
| 243 | 278 | } |
| 244 | 279 | return null; |
| 245 | 280 | } | ... | ... |
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; |
| 8 | 8 | import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; |
| 9 | 9 | import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.MesWmItemReceiptPageReqVO; |
| 10 | 10 | import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.MesWmItemReceiptSaveReqVO; |
| 11 | +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalNoticeDO; | |
| 11 | 12 | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptDO; |
| 12 | 13 | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptDetailDO; |
| 13 | 14 | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptLineDO; |
| 14 | 15 | import cn.iocoder.yudao.module.mes.dal.mysql.wm.itemreceipt.MesWmItemReceiptMapper; |
| 15 | 16 | import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; |
| 17 | +import cn.iocoder.yudao.module.mes.enums.wm.MesWmArrivalNoticeStatusEnum; | |
| 16 | 18 | import cn.iocoder.yudao.module.mes.enums.wm.MesWmItemReceiptStatusEnum; |
| 17 | 19 | import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum; |
| 18 | 20 | import cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService; |
| ... | ... | @@ -90,7 +92,13 @@ public class MesWmItemReceiptServiceImpl implements MesWmItemReceiptService { |
| 90 | 92 | vendorService.validateVendorExists(reqVO.getVendorId()); |
| 91 | 93 | // 校验到货通知单存在 |
| 92 | 94 | if (reqVO.getNoticeId() != null) { |
| 93 | - arrivalNoticeService.validateArrivalNoticeExists(reqVO.getNoticeId()); | |
| 95 | + MesWmArrivalNoticeDO notice = arrivalNoticeService.validateArrivalNoticeExists(reqVO.getNoticeId()); | |
| 96 | + if (ObjUtil.notEqual(notice.getStatus(), MesWmArrivalNoticeStatusEnum.PENDING_RECEIPT.getStatus())) { | |
| 97 | + throw exception(WM_ARRIVAL_NOTICE_STATUS_NOT_PENDING_RECEIPT); | |
| 98 | + } | |
| 99 | + if (ObjUtil.notEqual(notice.getVendorId(), reqVO.getVendorId())) { | |
| 100 | + throw exception(WM_ARRIVAL_NOTICE_VENDOR_MISMATCH); | |
| 101 | + } | |
| 94 | 102 | } |
| 95 | 103 | // 校验来料检验单存在 |
| 96 | 104 | if (reqVO.getIqcId() != null) { | ... | ... |
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/materialstock/MesWmMaterialStockService.java
| ... | ... | @@ -132,4 +132,20 @@ public interface MesWmMaterialStockService { |
| 132 | 132 | */ |
| 133 | 133 | void checkAreaMixingRule(Long areaId, Long itemId, Long batchId); |
| 134 | 134 | |
| 135 | + /** | |
| 136 | + * 校验前端选择的库存记录,兜底避免串单或越权提交 | |
| 137 | + * | |
| 138 | + * @param materialStockId 库存记录编号 | |
| 139 | + * @param itemId 物料编号 | |
| 140 | + * @param batchId 批次编号 | |
| 141 | + * @param batchCode 批次号(可选) | |
| 142 | + * @param warehouseId 仓库编号 | |
| 143 | + * @param locationId 库区编号 | |
| 144 | + * @param areaId 库位编号 | |
| 145 | + * @param quantity 数量(可选,校验库存充足) | |
| 146 | + * @return 校验通过的库存记录 | |
| 147 | + */ | |
| 148 | + MesWmMaterialStockDO validateSelectedStock(Long materialStockId, Long itemId, Long batchId, String batchCode, | |
| 149 | + Long warehouseId, Long locationId, Long areaId, BigDecimal quantity); | |
| 150 | + | |
| 135 | 151 | } | ... | ... |
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 |
| 185 | 185 | } |
| 186 | 186 | } |
| 187 | 187 | |
| 188 | + @Override | |
| 189 | + public MesWmMaterialStockDO validateSelectedStock(Long materialStockId, | |
| 190 | + Long itemId, | |
| 191 | + Long batchId, | |
| 192 | + String batchCode, | |
| 193 | + Long warehouseId, | |
| 194 | + Long locationId, | |
| 195 | + Long areaId, | |
| 196 | + BigDecimal quantity) { | |
| 197 | + // 1. 校验库存记录必须存在 | |
| 198 | + if (materialStockId == null) { | |
| 199 | + throw exception(WM_MATERIAL_STOCK_REQUIRED); | |
| 200 | + } | |
| 201 | + MesWmMaterialStockDO stock = validateMaterialStockExists(materialStockId); | |
| 202 | + // 2. 校验库存记录的物料、批次、仓库、库区、库位等信息与前端选择的一致,避免串单或越权提交 | |
| 203 | + if (ObjUtil.notEqual(stock.getItemId(), itemId) | |
| 204 | + || ObjUtil.notEqual(stock.getBatchId(), batchId) | |
| 205 | + || (batchCode != null && ObjUtil.notEqual(stock.getBatchCode(), batchCode)) | |
| 206 | + || ObjUtil.notEqual(stock.getWarehouseId(), warehouseId) | |
| 207 | + || ObjUtil.notEqual(stock.getLocationId(), locationId) | |
| 208 | + || ObjUtil.notEqual(stock.getAreaId(), areaId)) { | |
| 209 | + throw exception(WM_MATERIAL_STOCK_SELECTION_MISMATCH); | |
| 210 | + } | |
| 211 | + // 3. 校验库存数量充足(如果前端传了 quantity,则必须保证库存数量 >= quantity) | |
| 212 | + if (quantity != null && stock.getQuantity() != null && stock.getQuantity().compareTo(quantity) < 0) { | |
| 213 | + throw exception(WM_MATERIAL_STOCK_INSUFFICIENT); | |
| 214 | + } | |
| 215 | + return stock; | |
| 216 | + } | |
| 217 | + | |
| 188 | 218 | } | ... | ... |
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueDetailServiceImpl.java
| 1 | 1 | package cn.iocoder.yudao.module.mes.service.wm.outsourceissue; |
| 2 | 2 | |
| 3 | +import cn.hutool.core.util.ObjUtil; | |
| 3 | 4 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 4 | 5 | import cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo.detail.MesWmOutsourceIssueDetailSaveReqVO; |
| 5 | 6 | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueDetailDO; |
| 7 | +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourceissue.MesWmOutsourceIssueLineDO; | |
| 6 | 8 | import cn.iocoder.yudao.module.mes.dal.mysql.wm.outsourceissue.MesWmOutsourceIssueDetailMapper; |
| 7 | 9 | import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; |
| 10 | +import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService; | |
| 11 | +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; | |
| 8 | 12 | import jakarta.annotation.Resource; |
| 9 | 13 | import org.springframework.context.annotation.Lazy; |
| 10 | 14 | import org.springframework.stereotype.Service; |
| ... | ... | @@ -13,7 +17,7 @@ import org.springframework.validation.annotation.Validated; |
| 13 | 17 | import java.util.List; |
| 14 | 18 | |
| 15 | 19 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 16 | -import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_OUTSOURCE_ISSUE_DETAIL_NOT_EXISTS; | |
| 20 | +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; | |
| 17 | 21 | |
| 18 | 22 | /** |
| 19 | 23 | * MES 外协发料单明细 Service 实现类 |
| ... | ... | @@ -28,9 +32,13 @@ public class MesWmOutsourceIssueDetailServiceImpl implements MesWmOutsourceIssue |
| 28 | 32 | private MesWmOutsourceIssueDetailMapper outsourceIssueDetailMapper; |
| 29 | 33 | @Resource |
| 30 | 34 | @Lazy |
| 31 | - private MesWmOutsourceIssueService outsourceIssueService; | |
| 35 | + private MesWmOutsourceIssueLineService outsourceIssueLineService; | |
| 32 | 36 | @Resource |
| 33 | 37 | private MesMdItemService itemService; |
| 38 | + @Resource | |
| 39 | + private MesWmWarehouseAreaService warehouseAreaService; | |
| 40 | + @Resource | |
| 41 | + private MesWmMaterialStockService materialStockService; | |
| 34 | 42 | |
| 35 | 43 | @Override |
| 36 | 44 | public Long createOutsourceIssueDetail(MesWmOutsourceIssueDetailSaveReqVO createReqVO) { |
| ... | ... | @@ -95,10 +103,26 @@ public class MesWmOutsourceIssueDetailServiceImpl implements MesWmOutsourceIssue |
| 95 | 103 | } |
| 96 | 104 | |
| 97 | 105 | private void validateOutsourceIssueDetailSaveData(MesWmOutsourceIssueDetailSaveReqVO saveReqVO) { |
| 98 | - // 校验关联的发料单存在 | |
| 99 | - outsourceIssueService.getOutsourceIssue(saveReqVO.getIssueId()); | |
| 100 | - // 校验关联的物料存在 | |
| 106 | + // 校验父数据(行)存在 | |
| 107 | + MesWmOutsourceIssueLineDO line = outsourceIssueLineService.getOutsourceIssueLine(saveReqVO.getLineId()); | |
| 108 | + if (line == null) { | |
| 109 | + throw exception(WM_OUTSOURCE_ISSUE_LINE_NOT_EXISTS); | |
| 110 | + } | |
| 111 | + if (ObjUtil.notEqual(line.getIssueId(), saveReqVO.getIssueId())) { | |
| 112 | + throw exception(WM_OUTSOURCE_ISSUE_DETAIL_LINE_NOT_MATCH); | |
| 113 | + } | |
| 114 | + // 校验物料存在 | |
| 101 | 115 | itemService.validateItemExists(saveReqVO.getItemId()); |
| 116 | + if (ObjUtil.notEqual(line.getItemId(), saveReqVO.getItemId())) { | |
| 117 | + throw exception(WM_OUTSOURCE_ISSUE_DETAIL_ITEM_MISMATCH); | |
| 118 | + } | |
| 119 | + // 校验仓库、库区、库位的关联关系 | |
| 120 | + warehouseAreaService.validateWarehouseAreaExists( | |
| 121 | + saveReqVO.getWarehouseId(), saveReqVO.getLocationId(), saveReqVO.getAreaId()); | |
| 122 | + // 校验库存记录存在且物料一致 | |
| 123 | + materialStockService.validateSelectedStock( | |
| 124 | + saveReqVO.getMaterialStockId(), saveReqVO.getItemId(), saveReqVO.getBatchId(), null, | |
| 125 | + saveReqVO.getWarehouseId(), saveReqVO.getLocationId(), saveReqVO.getAreaId(), saveReqVO.getQuantity()); | |
| 102 | 126 | } |
| 103 | 127 | |
| 104 | 128 | } | ... | ... |
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 |
| 9 | 9 | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productissue.MesWmProductIssueLineDO; |
| 10 | 10 | import cn.iocoder.yudao.module.mes.dal.mysql.wm.productissue.MesWmProductIssueDetailMapper; |
| 11 | 11 | import cn.iocoder.yudao.module.mes.enums.wm.MesWmProductIssueStatusEnum; |
| 12 | +import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService; | |
| 13 | +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; | |
| 12 | 14 | import jakarta.annotation.Resource; |
| 13 | 15 | import org.springframework.context.annotation.Lazy; |
| 14 | 16 | import org.springframework.stereotype.Service; |
| ... | ... | @@ -35,6 +37,10 @@ public class MesWmProductIssueDetailServiceImpl implements MesWmProductIssueDeta |
| 35 | 37 | @Resource |
| 36 | 38 | @Lazy |
| 37 | 39 | private MesWmProductIssueLineService issueLineService; |
| 40 | + @Resource | |
| 41 | + private MesWmWarehouseAreaService warehouseAreaService; | |
| 42 | + @Resource | |
| 43 | + private MesWmMaterialStockService materialStockService; | |
| 38 | 44 | |
| 39 | 45 | @Override |
| 40 | 46 | public Long createProductIssueDetail(MesWmProductIssueDetailSaveReqVO createReqVO) { |
| ... | ... | @@ -116,8 +122,18 @@ public class MesWmProductIssueDetailServiceImpl implements MesWmProductIssueDeta |
| 116 | 122 | private void validateProductIssueDetailSaveData(MesWmProductIssueDetailSaveReqVO reqVO) { |
| 117 | 123 | // 校验父数据存在 |
| 118 | 124 | MesWmProductIssueLineDO line = issueLineService.validateProductIssueLineExists(reqVO.getLineId()); |
| 125 | + if (ObjUtil.notEqual(line.getIssueId(), reqVO.getIssueId())) { | |
| 126 | + throw exception(WM_PRODUCT_ISSUE_DETAIL_LINE_NOT_MATCH); | |
| 127 | + } | |
| 119 | 128 | // 校验物料匹配(明细 itemId 必须与行 itemId 一致) |
| 120 | 129 | validateDetailItemMatch(reqVO.getItemId(), line.getItemId()); |
| 130 | + // 校验仓库、库区、库位的关联关系 | |
| 131 | + warehouseAreaService.validateWarehouseAreaExists( | |
| 132 | + reqVO.getWarehouseId(), reqVO.getLocationId(), reqVO.getAreaId()); | |
| 133 | + // 校验库存记录 | |
| 134 | + materialStockService.validateSelectedStock( | |
| 135 | + reqVO.getMaterialStockId(), reqVO.getItemId(), reqVO.getBatchId(), reqVO.getBatchCode(), | |
| 136 | + reqVO.getWarehouseId(), reqVO.getLocationId(), reqVO.getAreaId(), reqVO.getQuantity()); | |
| 121 | 137 | } |
| 122 | 138 | |
| 123 | 139 | /** |
| ... | ... | @@ -130,4 +146,3 @@ public class MesWmProductIssueDetailServiceImpl implements MesWmProductIssueDeta |
| 130 | 146 | } |
| 131 | 147 | |
| 132 | 148 | } |
| 133 | - | ... | ... |
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesDetailServiceImpl.java
| 1 | 1 | package cn.iocoder.yudao.module.mes.service.wm.productsales; |
| 2 | 2 | |
| 3 | +import cn.hutool.core.util.ObjUtil; | |
| 3 | 4 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 4 | 5 | import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.detail.MesWmProductSalesDetailSaveReqVO; |
| 5 | 6 | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesDetailDO; |
| 7 | +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesLineDO; | |
| 6 | 8 | import cn.iocoder.yudao.module.mes.dal.mysql.wm.productsales.MesWmProductSalesDetailMapper; |
| 7 | 9 | import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; |
| 10 | +import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService; | |
| 8 | 11 | import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; |
| 9 | 12 | import jakarta.annotation.Resource; |
| 10 | 13 | import org.springframework.stereotype.Service; |
| ... | ... | @@ -29,17 +32,17 @@ public class MesWmProductSalesDetailServiceImpl implements MesWmProductSalesDeta |
| 29 | 32 | |
| 30 | 33 | @Resource |
| 31 | 34 | private MesMdItemService itemService; |
| 32 | - | |
| 35 | + @Resource | |
| 36 | + private MesWmProductSalesLineService productSalesLineService; | |
| 37 | + @Resource | |
| 38 | + private MesWmMaterialStockService materialStockService; | |
| 33 | 39 | @Resource |
| 34 | 40 | private MesWmWarehouseAreaService warehouseAreaService; |
| 35 | 41 | |
| 36 | 42 | @Override |
| 37 | 43 | public Long createProductSalesDetail(MesWmProductSalesDetailSaveReqVO createReqVO) { |
| 38 | - // 校验物料存在 | |
| 39 | - itemService.validateItemExists(createReqVO.getItemId()); | |
| 40 | - // 校验库区关系 | |
| 41 | - warehouseAreaService.validateWarehouseAreaExists( | |
| 42 | - createReqVO.getWarehouseId(), createReqVO.getLocationId(), createReqVO.getAreaId()); | |
| 44 | + // 校验数据 | |
| 45 | + validateProductSalesDetailSaveData(createReqVO); | |
| 43 | 46 | |
| 44 | 47 | // 插入 |
| 45 | 48 | MesWmProductSalesDetailDO detail = BeanUtils.toBean(createReqVO, MesWmProductSalesDetailDO.class); |
| ... | ... | @@ -51,11 +54,8 @@ public class MesWmProductSalesDetailServiceImpl implements MesWmProductSalesDeta |
| 51 | 54 | public void updateProductSalesDetail(MesWmProductSalesDetailSaveReqVO updateReqVO) { |
| 52 | 55 | // 校验存在 |
| 53 | 56 | validateProductSalesDetailExists(updateReqVO.getId()); |
| 54 | - // 校验物料存在 | |
| 55 | - itemService.validateItemExists(updateReqVO.getItemId()); | |
| 56 | - // 校验库区关系 | |
| 57 | - warehouseAreaService.validateWarehouseAreaExists( | |
| 58 | - updateReqVO.getWarehouseId(), updateReqVO.getLocationId(), updateReqVO.getAreaId()); | |
| 57 | + // 校验数据 | |
| 58 | + validateProductSalesDetailSaveData(updateReqVO); | |
| 59 | 59 | |
| 60 | 60 | // 更新 |
| 61 | 61 | MesWmProductSalesDetailDO updateObj = BeanUtils.toBean(updateReqVO, MesWmProductSalesDetailDO.class); |
| ... | ... | @@ -103,4 +103,27 @@ public class MesWmProductSalesDetailServiceImpl implements MesWmProductSalesDeta |
| 103 | 103 | return detail; |
| 104 | 104 | } |
| 105 | 105 | |
| 106 | + private void validateProductSalesDetailSaveData(MesWmProductSalesDetailSaveReqVO reqVO) { | |
| 107 | + // 校验父数据(行)存在 | |
| 108 | + MesWmProductSalesLineDO line = productSalesLineService.getProductSalesLine(reqVO.getLineId()); | |
| 109 | + if (line == null) { | |
| 110 | + throw exception(WM_PRODUCT_SALES_LINE_NOT_EXISTS); | |
| 111 | + } | |
| 112 | + if (ObjUtil.notEqual(line.getSalesId(), reqVO.getSalesId())) { | |
| 113 | + throw exception(WM_PRODUCT_SALES_DETAIL_LINE_NOT_MATCH); | |
| 114 | + } | |
| 115 | + // 校验物料存在 | |
| 116 | + itemService.validateItemExists(reqVO.getItemId()); | |
| 117 | + if (ObjUtil.notEqual(line.getItemId(), reqVO.getItemId())) { | |
| 118 | + throw exception(WM_PRODUCT_SALES_DETAIL_ITEM_MISMATCH); | |
| 119 | + } | |
| 120 | + // 校验库位存在 | |
| 121 | + warehouseAreaService.validateWarehouseAreaExists( | |
| 122 | + reqVO.getWarehouseId(), reqVO.getLocationId(), reqVO.getAreaId()); | |
| 123 | + // 校验库存记录存在且物料一致 | |
| 124 | + materialStockService.validateSelectedStock( | |
| 125 | + reqVO.getMaterialStockId(), reqVO.getItemId(), reqVO.getBatchId(), reqVO.getBatchCode(), | |
| 126 | + reqVO.getWarehouseId(), reqVO.getLocationId(), reqVO.getAreaId(), reqVO.getQuantity()); | |
| 127 | + } | |
| 128 | + | |
| 106 | 129 | } | ... | ... |
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; |
| 9 | 9 | import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesPageReqVO; |
| 10 | 10 | import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesSaveReqVO; |
| 11 | 11 | import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.MesWmProductSalesShippingReqVO; |
| 12 | +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.salesnotice.MesWmSalesNoticeDO; | |
| 12 | 13 | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesDO; |
| 13 | 14 | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesDetailDO; |
| 14 | 15 | 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 |
| 16 | 17 | import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; |
| 17 | 18 | import cn.iocoder.yudao.module.mes.enums.wm.MesWmProductSalesStatusEnum; |
| 18 | 19 | import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum; |
| 20 | +import cn.iocoder.yudao.module.mes.enums.wm.MesWmSalesNoticeStatusEnum; | |
| 19 | 21 | import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum; |
| 20 | 22 | import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService; |
| 23 | +import cn.iocoder.yudao.module.mes.service.wm.salesnotice.MesWmSalesNoticeService; | |
| 21 | 24 | import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService; |
| 22 | 25 | import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO; |
| 23 | 26 | import jakarta.annotation.Resource; |
| ... | ... | @@ -54,6 +57,9 @@ public class MesWmProductSalesServiceImpl implements MesWmProductSalesService { |
| 54 | 57 | private MesMdClientService clientService; |
| 55 | 58 | |
| 56 | 59 | @Resource |
| 60 | + private MesWmSalesNoticeService salesNoticeService; | |
| 61 | + | |
| 62 | + @Resource | |
| 57 | 63 | private MesWmTransactionService wmTransactionService; |
| 58 | 64 | |
| 59 | 65 | @Override |
| ... | ... | @@ -262,6 +268,16 @@ public class MesWmProductSalesServiceImpl implements MesWmProductSalesService { |
| 262 | 268 | validateCodeUnique(id, reqVO.getCode()); |
| 263 | 269 | // 校验客户存在 |
| 264 | 270 | clientService.validateClientExists(reqVO.getClientId()); |
| 271 | + // 校验发货通知单 | |
| 272 | + if (reqVO.getNoticeId() != null) { | |
| 273 | + MesWmSalesNoticeDO notice = salesNoticeService.validateSalesNoticeExists(reqVO.getNoticeId()); | |
| 274 | + if (ObjUtil.notEqual(notice.getStatus(), MesWmSalesNoticeStatusEnum.APPROVED.getStatus())) { | |
| 275 | + throw exception(WM_SALES_NOTICE_STATUS_NOT_APPROVED); | |
| 276 | + } | |
| 277 | + if (ObjUtil.notEqual(notice.getClientId(), reqVO.getClientId())) { | |
| 278 | + throw exception(WM_SALES_NOTICE_CLIENT_MISMATCH); | |
| 279 | + } | |
| 280 | + } | |
| 265 | 281 | } |
| 266 | 282 | |
| 267 | 283 | private MesWmProductSalesDO validateProductSalesExists(Long id) { | ... | ... |
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueDetailServiceImpl.java
| 1 | 1 | package cn.iocoder.yudao.module.mes.service.wm.returnissue; |
| 2 | 2 | |
| 3 | +import cn.hutool.core.util.ObjUtil; | |
| 3 | 4 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; |
| 4 | 5 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 5 | 6 | import cn.iocoder.yudao.module.mes.controller.admin.wm.returnissue.vo.detail.MesWmReturnIssueDetailSaveReqVO; |
| ... | ... | @@ -17,8 +18,7 @@ import java.math.BigDecimal; |
| 17 | 18 | import java.util.List; |
| 18 | 19 | |
| 19 | 20 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 20 | -import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_RETURN_ISSUE_DETAIL_NOT_EXISTS; | |
| 21 | -import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_RETURN_ISSUE_DETAIL_QUANTITY_EXCEED; | |
| 21 | +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; | |
| 22 | 22 | |
| 23 | 23 | /** |
| 24 | 24 | * MES 生产退料明细 Service 实现类 |
| ... | ... | @@ -105,11 +105,21 @@ public class MesWmReturnIssueDetailServiceImpl implements MesWmReturnIssueDetail |
| 105 | 105 | private void validateReturnIssueDetailSaveData(MesWmReturnIssueDetailSaveReqVO reqVO) { |
| 106 | 106 | // 校验父数据存在 |
| 107 | 107 | MesWmReturnIssueLineDO line = issueLineService.validateReturnIssueLineExists(reqVO.getLineId()); |
| 108 | + if (ObjUtil.notEqual(line.getIssueId(), reqVO.getIssueId())) { | |
| 109 | + throw exception(WM_RETURN_ISSUE_DETAIL_LINE_NOT_MATCH); | |
| 110 | + } | |
| 111 | + if (ObjUtil.notEqual(line.getItemId(), reqVO.getItemId())) { | |
| 112 | + throw exception(WM_RETURN_ISSUE_DETAIL_ITEM_MISMATCH); | |
| 113 | + } | |
| 108 | 114 | // 校验仓库、库区、库位的关联关系 |
| 109 | 115 | warehouseAreaService.validateWarehouseAreaExists( |
| 110 | 116 | reqVO.getWarehouseId(), reqVO.getLocationId(), reqVO.getAreaId()); |
| 111 | 117 | // 校验库位物料/批次混放规则 |
| 112 | 118 | materialStockService.checkAreaMixingRule(reqVO.getAreaId(), reqVO.getItemId(), reqVO.getBatchId()); |
| 119 | + // 校验库存记录 | |
| 120 | + materialStockService.validateSelectedStock( | |
| 121 | + reqVO.getMaterialStockId(), reqVO.getItemId(), reqVO.getBatchId(), reqVO.getBatchCode(), | |
| 122 | + reqVO.getWarehouseId(), reqVO.getLocationId(), reqVO.getAreaId(), reqVO.getQuantity()); | |
| 113 | 123 | // 校验明细总数量不超过行数量(排除自身) |
| 114 | 124 | validateDetailQuantityNotExceed(reqVO.getLineId(), reqVO.getQuantity(), reqVO.getId(), line); |
| 115 | 125 | } | ... | ... |
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; |
| 3 | 3 | import cn.hutool.core.util.ObjUtil; |
| 4 | 4 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 5 | 5 | import cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo.detail.MesWmReturnVendorDetailSaveReqVO; |
| 6 | -import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO; | |
| 7 | 6 | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnvendor.MesWmReturnVendorDetailDO; |
| 8 | 7 | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnvendor.MesWmReturnVendorLineDO; |
| 9 | 8 | import cn.iocoder.yudao.module.mes.dal.mysql.wm.returnvendor.MesWmReturnVendorDetailMapper; |
| 10 | 9 | import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; |
| 11 | 10 | import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService; |
| 11 | +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; | |
| 12 | 12 | import jakarta.annotation.Resource; |
| 13 | 13 | import org.springframework.context.annotation.Lazy; |
| 14 | 14 | import org.springframework.stereotype.Service; |
| ... | ... | @@ -32,12 +32,12 @@ public class MesWmReturnVendorDetailServiceImpl implements MesWmReturnVendorDeta |
| 32 | 32 | @Resource |
| 33 | 33 | @Lazy |
| 34 | 34 | private MesWmReturnVendorLineService returnVendorLineService; |
| 35 | - | |
| 36 | 35 | @Resource |
| 37 | 36 | private MesMdItemService itemService; |
| 38 | - | |
| 39 | 37 | @Resource |
| 40 | 38 | private MesWmMaterialStockService materialStockService; |
| 39 | + @Resource | |
| 40 | + private MesWmWarehouseAreaService warehouseAreaService; | |
| 41 | 41 | |
| 42 | 42 | @Override |
| 43 | 43 | public Long createReturnVendorDetail(MesWmReturnVendorDetailSaveReqVO createReqVO) { |
| ... | ... | @@ -68,12 +68,18 @@ public class MesWmReturnVendorDetailServiceImpl implements MesWmReturnVendorDeta |
| 68 | 68 | private void validateDetailSaveData(MesWmReturnVendorDetailSaveReqVO reqVO) { |
| 69 | 69 | // 校验父数据(行)存在 |
| 70 | 70 | MesWmReturnVendorLineDO line = returnVendorLineService.validateReturnVendorLineExists(reqVO.getLineId()); |
| 71 | + if (ObjUtil.notEqual(line.getReturnId(), reqVO.getReturnId())) { | |
| 72 | + throw exception(WM_RETURN_VENDOR_DETAIL_LINE_NOT_MATCH); | |
| 73 | + } | |
| 71 | 74 | // 校验物料存在 |
| 72 | 75 | itemService.validateItemExists(reqVO.getItemId()); |
| 73 | 76 | // 校验物料与行物料一致 |
| 74 | 77 | validateItemConsistency(reqVO.getItemId(), line); |
| 78 | + // 校验库位存在 | |
| 79 | + warehouseAreaService.validateWarehouseAreaExists( | |
| 80 | + reqVO.getWarehouseId(), reqVO.getLocationId(), reqVO.getAreaId()); | |
| 75 | 81 | // 校验库存记录存在且物料一致 |
| 76 | - validateMaterialStock(reqVO.getMaterialStockId(), line); | |
| 82 | + validateMaterialStock(reqVO, line); | |
| 77 | 83 | } |
| 78 | 84 | |
| 79 | 85 | @Override |
| ... | ... | @@ -127,15 +133,11 @@ public class MesWmReturnVendorDetailServiceImpl implements MesWmReturnVendorDeta |
| 127 | 133 | /** |
| 128 | 134 | * 校验库存记录存在且物料与行物料一致 |
| 129 | 135 | */ |
| 130 | - private void validateMaterialStock(Long materialStockId, MesWmReturnVendorLineDO line) { | |
| 131 | - if (materialStockId == null) { | |
| 132 | - return; | |
| 133 | - } | |
| 134 | - MesWmMaterialStockDO stock = materialStockService.getMaterialStock(materialStockId); | |
| 135 | - if (stock == null) { | |
| 136 | - throw exception(WM_MATERIAL_STOCK_NOT_EXISTS); | |
| 137 | - } | |
| 138 | - if (ObjUtil.notEqual(stock.getItemId(), line.getItemId())) { | |
| 136 | + private void validateMaterialStock(MesWmReturnVendorDetailSaveReqVO reqVO, MesWmReturnVendorLineDO line) { | |
| 137 | + materialStockService.validateSelectedStock( | |
| 138 | + reqVO.getMaterialStockId(), reqVO.getItemId(), reqVO.getBatchId(), reqVO.getBatchCode(), | |
| 139 | + reqVO.getWarehouseId(), reqVO.getLocationId(), reqVO.getAreaId(), reqVO.getQuantity()); | |
| 140 | + if (ObjUtil.notEqual(line.getItemId(), reqVO.getItemId())) { | |
| 139 | 141 | throw exception(WM_RETURN_VENDOR_DETAIL_ITEM_MISMATCH); |
| 140 | 142 | } |
| 141 | 143 | } | ... | ... |
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeService.java
| ... | ... | @@ -40,6 +40,14 @@ public interface MesWmSalesNoticeService { |
| 40 | 40 | void deleteSalesNotice(Long id); |
| 41 | 41 | |
| 42 | 42 | /** |
| 43 | + * 校验发货通知单存在 | |
| 44 | + * | |
| 45 | + * @param id 编号 | |
| 46 | + * @return 发货通知单 | |
| 47 | + */ | |
| 48 | + MesWmSalesNoticeDO validateSalesNoticeExists(Long id); | |
| 49 | + | |
| 50 | + /** | |
| 43 | 51 | * 获得发货通知单 |
| 44 | 52 | * |
| 45 | 53 | * @param id 编号 | ... | ... |
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 { |
| 111 | 111 | return salesNoticeMapper.selectByIds(ids); |
| 112 | 112 | } |
| 113 | 113 | |
| 114 | - private MesWmSalesNoticeDO validateSalesNoticeExists(Long id) { | |
| 114 | + @Override | |
| 115 | + public MesWmSalesNoticeDO validateSalesNoticeExists(Long id) { | |
| 115 | 116 | MesWmSalesNoticeDO notice = salesNoticeMapper.selectById(id); |
| 116 | 117 | if (notice == null) { |
| 117 | 118 | throw exception(WM_SALES_NOTICE_NOT_EXISTS); | ... | ... |