From 11ff5b4a7ce3a86d6f2949497ef63a1514bceea5 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 18 Apr 2026 10:04:51 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E5=90=8C=E6=AD=A5=E3=80=91BOOT=20?= =?UTF-8?q?=E5=92=8C=20CLOUD=20=E7=9A=84=E5=8A=9F=E8=83=BD=EF=BC=88mes?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .image/common/iot-feature.png | Bin 315373 -> 59728 bytes .image/common/ruoyi-vue-pro-biz.png | Bin 47617 -> 65743 bytes .../framework/test/core/util/RandomUtils.java | 5 + .../module/mes/enums/DictTypeConstants.java | 105 +++-- .../module/mes/enums/ErrorCodeConstants.java | 64 +++ .../mes/enums/cal/MesCalShiftTypeEnum.java | 4 +- .../MesDvCheckPlanTypeEnum.java} | 13 +- .../dv/MesDvMaintenRecordStatusEnum.java | 5 +- .../autocode/MesMdAutoCodeRuleCodeEnum.java | 2 + .../MesDvCheckPlanMachineryController.java | 2 +- .../MesDvCheckPlanMachineryRespVO.java | 2 +- .../MesDvCheckRecordController.java | 4 +- .../vo/MesDvCheckRecordRespVO.java | 2 +- .../machinery/MesDvMachineryController.java | 4 +- .../vo/MesDvMachineryImportExcelVO.java | 2 +- .../dv/machinery/vo/MesDvMachineryRespVO.java | 2 +- .../machinery/vo/MesDvMachinerySaveReqVO.java | 2 +- .../MesDvMaintenRecordController.java | 4 +- .../vo/MesDvMaintenRecordRespVO.java | 2 +- .../dv/repair/MesDvRepairController.java | 3 +- .../admin/dv/repair/vo/MesDvRepairRespVO.java | 2 +- .../client/vo/MesMdClientImportExcelVO.java | 33 ++ .../md/client/vo/MesMdClientSaveReqVO.java | 23 ++ .../vendor/vo/MesMdVendorImportExcelVO.java | 33 ++ .../md/vendor/vo/MesMdVendorSaveReqVO.java | 24 ++ .../workstation/MesMdWorkshopController.java | 21 +- .../admin/pro/card/MesProCardController.java | 9 - .../admin/pro/card/vo/MesProCardRespVO.java | 6 +- .../pro/card/vo/MesProCardSaveReqVO.java | 6 +- .../feedback/MesProFeedbackController.java | 4 +- .../admin/pro/task/MesProTaskController.java | 51 +-- .../pro/task/MesProTaskIssueController.java | 4 +- .../pro/task/vo/MesProTaskIssueRespVO.java | 14 +- .../pro/task/vo/MesProTaskIssueSaveReqVO.java | 12 +- .../pro/task/vo/MesProTaskPageReqVO.java | 7 + .../admin/pro/task/vo/MesProTaskRespVO.java | 8 +- .../MesProWorkOrderBomController.java | 12 +- .../workorder/MesProWorkOrderController.java | 6 +- .../vo/MesProWorkOrderItemRespVO.java | 5 +- .../vo/MesProWorkOrderPageReqVO.java | 3 + .../workorder/vo/MesProWorkOrderRespVO.java | 2 +- .../vo/bom/MesProWorkOrderBomRespVO.java | 2 +- .../qc/defect/vo/MesQcDefectPageReqVO.java | 4 +- .../admin/qc/defect/vo/MesQcDefectRespVO.java | 4 +- .../qc/defect/vo/MesQcDefectSaveReqVO.java | 8 +- .../MesQcDefectRecordController.java | 2 +- .../indicator/MesQcIndicatorController.java | 7 - .../indicator/vo/MesQcIndicatorPageReqVO.java | 4 +- .../qc/indicator/vo/MesQcIndicatorRespVO.java | 4 +- .../indicator/vo/MesQcIndicatorSaveReqVO.java | 6 +- .../admin/qc/ipqc/vo/MesQcIpqcRespVO.java | 6 +- .../qc/ipqc/vo/line/MesQcIpqcLineRespVO.java | 4 +- .../admin/qc/iqc/vo/MesQcIqcRespVO.java | 6 +- .../qc/iqc/vo/line/MesQcIqcLineRespVO.java | 4 +- .../admin/qc/oqc/vo/MesQcOqcRespVO.java | 10 +- .../admin/qc/oqc/vo/MesQcOqcSaveReqVO.java | 20 +- .../qc/oqc/vo/line/MesQcOqcLineRespVO.java | 4 +- .../vo/MesQcPendingInspectRespVO.java | 9 +- .../admin/qc/rqc/vo/MesQcRqcRespVO.java | 46 +-- .../admin/qc/rqc/vo/MesQcRqcSaveReqVO.java | 6 +- .../qc/rqc/vo/line/MesQcRqcLineRespVO.java | 4 +- .../qc/template/MesQcTemplateController.java | 7 - .../MesQcTemplateIndicatorRespVO.java | 4 +- .../admin/tm/tool/vo/MesTmToolPageReqVO.java | 2 +- .../admin/tm/tool/vo/MesTmToolRespVO.java | 2 +- .../admin/tm/tool/vo/MesTmToolSaveReqVO.java | 13 +- .../tool/vo/type/MesTmToolTypeSaveReqVO.java | 6 +- .../MesWmArrivalNoticeController.java | 10 - .../MesWmArrivalNoticeLineController.java | 13 - .../vo/MesWmItemConsumeLinePageReqVO.java | 2 + .../MesWmItemReceiptLineController.java | 10 +- .../vo/line/MesWmItemReceiptLineRespVO.java | 6 + .../MesWmMaterialStockController.java | 10 +- .../vo/MesWmMaterialStockPageReqVO.java | 15 + .../vo/MesWmMaterialStockRespVO.java | 3 + .../wm/miscissue/vo/MesWmMiscIssueRespVO.java | 5 +- .../miscissue/vo/MesWmMiscIssueSaveReqVO.java | 5 +- .../vo/MesWmMiscReceiptRespVO.java | 5 +- .../vo/MesWmMiscReceiptSaveReqVO.java | 5 +- .../wm/packages/MesWmPackageController.java | 15 +- .../wm/packages/vo/MesWmPackagePageReqVO.java | 3 + .../vo/line/MesWmPackageLineSaveReqVO.java | 4 +- .../MesWmProductIssueDetailSaveReqVO.java | 5 +- .../MesWmProductReceiptLineSaveReqVO.java | 2 +- .../MesWmProductSalesController.java | 3 +- .../vo/line/MesWmProductSalesLineRespVO.java | 3 + .../line/MesWmProductSalesLineSaveReqVO.java | 3 + .../MesWmReturnIssueDetailSaveReqVO.java | 3 + .../MesWmReturnSalesDetailSaveReqVO.java | 3 + .../line/MesWmReturnSalesLineSaveReqVO.java | 5 +- .../MesWmReturnVendorDetailSaveReqVO.java | 11 +- .../MesWmSalesNoticeController.java | 10 - .../vo/MesWmSalesNoticePageReqVO.java | 7 +- .../vo/MesWmSalesNoticeRespVO.java | 4 +- .../vo/MesWmSalesNoticeSaveReqVO.java | 4 +- .../admin/wm/sn/MesWmSnController.java | 20 +- .../admin/wm/sn/vo/MesWmSnGroupRespVO.java | 4 + .../admin/wm/sn/vo/MesWmSnRespVO.java | 4 + .../plan/MesWmStockTakingPlanController.java | 11 - .../vo/MesWmStockTakingPlanPageReqVO.java | 3 + .../vo/line/MesWmTransferLineSaveReqVO.java | 3 +- .../MesWmWarehouseLocationRespVO.java | 4 - .../MesWmWarehouseLocationSaveReqVO.java | 4 - .../dal/dataobject/cal/plan/MesCalPlanDO.java | 4 + .../dv/checkplan/MesDvCheckPlanDO.java | 1 + .../dv/checkrecord/MesDvCheckRecordDO.java | 2 + .../checkrecord/MesDvCheckRecordLineDO.java | 2 + .../dv/machinery/MesDvMachineryDO.java | 4 +- .../maintenrecord/MesDvMaintenRecordDO.java | 3 +- .../MesDvMaintenRecordLineDO.java | 3 +- .../dataobject/dv/repair/MesDvRepairDO.java | 3 + .../md/autocode/MesMdAutoCodePartDO.java | 28 +- .../md/autocode/MesMdAutoCodeRecordDO.java | 8 +- .../md/autocode/MesMdAutoCodeRuleDO.java | 2 + .../dataobject/md/item/MesMdItemTypeDO.java | 2 + .../dataobject/md/item/MesMdProductBomDO.java | 2 +- .../pro/andon/MesProAndonConfigDO.java | 2 + .../pro/andon/MesProAndonRecordDO.java | 3 + .../dal/dataobject/pro/card/MesProCardDO.java | 2 + .../pro/feedback/MesProFeedbackDO.java | 3 + .../dal/dataobject/pro/task/MesProTaskDO.java | 2 + .../pro/task/MesProTaskIssueDO.java | 16 +- .../pro/workorder/MesProWorkOrderDO.java | 4 + .../pro/workrecord/MesProWorkRecordDO.java | 4 +- .../pro/workrecord/MesProWorkRecordLogDO.java | 2 + .../dataobject/qc/defect/MesQcDefectDO.java | 4 +- .../qc/defectrecord/MesQcDefectRecordDO.java | 3 + .../qc/indicator/MesQcIndicatorDO.java | 4 +- .../MesQcIndicatorResultDO.java | 2 + .../dal/dataobject/qc/ipqc/MesQcIpqcDO.java | 4 + .../mes/dal/dataobject/qc/iqc/MesQcIqcDO.java | 4 + .../mes/dal/dataobject/qc/oqc/MesQcOqcDO.java | 16 +- .../mes/dal/dataobject/qc/rqc/MesQcRqcDO.java | 65 +-- .../dal/dataobject/tm/tool/MesTmToolDO.java | 5 +- .../dataobject/tm/tool/MesTmToolTypeDO.java | 2 + .../arrivalnotice/MesWmArrivalNoticeDO.java | 2 + .../wm/barcode/MesWmBarcodeConfigDO.java | 3 + .../dataobject/wm/barcode/MesWmBarcodeDO.java | 3 + .../wm/itemconsume/MesWmItemConsumeDO.java | 2 + .../wm/itemreceipt/MesWmItemReceiptDO.java | 2 + .../materialstock/MesWmMaterialStockDO.java | 34 +- .../wm/miscissue/MesWmMiscIssueDO.java | 13 +- .../wm/miscreceipt/MesWmMiscReceiptDO.java | 13 +- .../outsourceissue/MesWmOutsourceIssueDO.java | 2 + .../MesWmOutsourceReceiptDO.java | 2 + .../MesWmOutsourceReceiptLineDO.java | 2 + .../wm/packages/MesWmPackageDO.java | 2 + .../wm/productissue/MesWmProductIssueDO.java | 2 + .../productproduce/MesWmProductProduceDO.java | 2 + .../MesWmProductProduceLineDO.java | 2 + .../productreceipt/MesWmProductReceiptDO.java | 2 + .../wm/productsales/MesWmProductSalesDO.java | 11 +- .../productsales/MesWmProductSalesLineDO.java | 9 + .../wm/returnissue/MesWmReturnIssueDO.java | 3 + .../returnissue/MesWmReturnIssueLineDO.java | 2 + .../wm/returnsales/MesWmReturnSalesDO.java | 2 + .../returnsales/MesWmReturnSalesDetailDO.java | 4 + .../returnsales/MesWmReturnSalesLineDO.java | 6 + .../wm/returnvendor/MesWmReturnVendorDO.java | 2 + .../wm/salesnotice/MesWmSalesNoticeDO.java | 6 +- .../plan/MesWmStockTakingPlanDO.java | 2 + .../plan/MesWmStockTakingPlanParamDO.java | 2 + .../task/MesWmStockTakingTaskDO.java | 3 + .../task/MesWmStockTakingTaskLineDO.java | 2 + .../wm/transaction/MesWmTransactionDO.java | 14 +- .../wm/transfer/MesWmTransferDO.java | 3 + .../warehouse/MesWmWarehouseLocationDO.java | 6 - .../unitmeasure/MesMdUnitMeasureMapper.java | 4 + .../workstation/MesMdWorkstationMapper.java | 4 + .../MesMdWorkstationToolMapper.java | 4 + .../mysql/pro/task/MesProTaskIssueMapper.java | 4 + .../dal/mysql/pro/task/MesProTaskMapper.java | 18 +- .../pro/workorder/MesProWorkOrderMapper.java | 5 + .../MesQcIndicatorResultMapper.java | 6 + .../mysql/qc/ipqc/MesQcIpqcLineMapper.java | 4 + .../dal/mysql/qc/iqc/MesQcIqcLineMapper.java | 4 + .../mes/dal/mysql/qc/iqc/MesQcIqcMapper.java | 4 + .../dal/mysql/qc/oqc/MesQcOqcLineMapper.java | 4 + .../dal/mysql/qc/rqc/MesQcRqcLineMapper.java | 4 + .../MesQcTemplateIndicatorMapper.java | 4 + .../dal/mysql/tm/tool/MesTmToolMapper.java | 2 +- .../MesWmArrivalNoticeMapper.java | 6 - .../dal/mysql/wm/batch/MesWmBatchMapper.java | 4 + .../MesWmMaterialStockMapper.java | 21 +- .../MesWmOutsourceIssueMapper.java | 4 + .../MesWmOutsourceReceiptMapper.java | 4 + .../mysql/wm/packages/MesWmPackageMapper.java | 9 +- .../salesnotice/MesWmSalesNoticeMapper.java | 15 +- .../plan/MesWmStockTakingPlanMapper.java | 8 +- .../dv/checkplan/MesDvCheckPlanService.java | 9 + .../checkplan/MesDvCheckPlanServiceImpl.java | 15 + .../MesDvCheckPlanSubjectServiceImpl.java | 3 +- .../MesDvCheckRecordLineServiceImpl.java | 7 +- .../MesDvCheckRecordServiceImpl.java | 13 +- .../dv/machinery/MesDvMachineryService.java | 17 + .../machinery/MesDvMachineryServiceImpl.java | 18 +- .../MesDvMaintenRecordLineServiceImpl.java | 2 +- .../MesDvMaintenRecordServiceImpl.java | 11 +- .../dv/repair/MesDvRepairLineServiceImpl.java | 2 +- .../dv/subject/MesDvSubjectService.java | 7 + .../dv/subject/MesDvSubjectServiceImpl.java | 14 +- .../service/md/client/MesMdClientService.java | 7 + .../md/client/MesMdClientServiceImpl.java | 12 + .../mes/service/md/item/MesMdItemService.java | 16 + .../service/md/item/MesMdItemServiceImpl.java | 29 +- .../md/item/MesMdProductSipServiceImpl.java | 2 +- .../md/item/MesMdProductSopServiceImpl.java | 2 +- .../MesMdUnitMeasureServiceImpl.java | 52 ++- .../service/md/vendor/MesMdVendorService.java | 8 + .../md/vendor/MesMdVendorServiceImpl.java | 32 +- .../workstation/MesMdWorkshopServiceImpl.java | 7 +- .../MesMdWorkstationMachineServiceImpl.java | 8 +- .../workstation/MesMdWorkstationService.java | 16 + .../MesMdWorkstationServiceImpl.java | 20 +- .../MesMdWorkstationToolService.java | 8 + .../MesMdWorkstationToolServiceImpl.java | 5 + .../andon/MesProAndonRecordServiceImpl.java | 7 +- .../card/MesProCardProcessServiceImpl.java | 20 +- .../service/pro/card/MesProCardService.java | 16 +- .../pro/card/MesProCardServiceImpl.java | 31 +- .../pro/feedback/MesProFeedbackService.java | 17 +- .../feedback/MesProFeedbackServiceImpl.java | 86 ++-- .../pro/process/MesProProcessService.java | 7 + .../pro/process/MesProProcessServiceImpl.java | 14 +- .../route/MesProRouteProcessServiceImpl.java | 2 - .../MesProRouteProductBomServiceImpl.java | 47 ++- .../pro/task/MesProTaskIssueService.java | 8 + .../pro/task/MesProTaskIssueServiceImpl.java | 6 +- .../service/pro/task/MesProTaskService.java | 8 - .../pro/task/MesProTaskServiceImpl.java | 9 +- .../MesProWorkOrderBomServiceImpl.java | 23 +- .../pro/workorder/MesProWorkOrderService.java | 8 + .../workorder/MesProWorkOrderServiceImpl.java | 5 + .../MesProWorkRecordServiceImpl.java | 3 +- .../qc/indicator/MesQcIndicatorService.java | 8 + .../indicator/MesQcIndicatorServiceImpl.java | 11 + .../MesQcIndicatorResultService.java | 17 + .../MesQcIndicatorResultServiceImpl.java | 121 +++++- .../service/qc/ipqc/MesQcIpqcLineService.java | 8 + .../qc/ipqc/MesQcIpqcLineServiceImpl.java | 13 +- .../service/qc/ipqc/MesQcIpqcServiceImpl.java | 78 +++- .../service/qc/iqc/MesQcIqcLineService.java | 8 + .../qc/iqc/MesQcIqcLineServiceImpl.java | 13 +- .../mes/service/qc/iqc/MesQcIqcService.java | 8 + .../service/qc/iqc/MesQcIqcServiceImpl.java | 12 + .../service/qc/oqc/MesQcOqcLineService.java | 8 + .../qc/oqc/MesQcOqcLineServiceImpl.java | 14 +- .../service/qc/oqc/MesQcOqcServiceImpl.java | 15 +- .../service/qc/rqc/MesQcRqcLineService.java | 8 + .../qc/rqc/MesQcRqcLineServiceImpl.java | 13 +- .../service/qc/rqc/MesQcRqcServiceImpl.java | 7 + .../MesQcTemplateIndicatorService.java | 18 + .../MesQcTemplateIndicatorServiceImpl.java | 12 + .../mes/service/tm/tool/MesTmToolService.java | 8 + .../service/tm/tool/MesTmToolServiceImpl.java | 20 +- .../tm/tool/MesTmToolTypeServiceImpl.java | 15 +- .../MesWmArrivalNoticeLineServiceImpl.java | 2 +- .../MesWmArrivalNoticeService.java | 9 +- .../MesWmArrivalNoticeServiceImpl.java | 49 ++- .../service/wm/batch/MesWmBatchService.java | 27 +- .../wm/batch/MesWmBatchServiceImpl.java | 50 ++- .../itemreceipt/MesWmItemReceiptService.java | 23 +- .../MesWmItemReceiptServiceImpl.java | 15 +- .../MesWmMaterialStockService.java | 16 + .../MesWmMaterialStockServiceImpl.java | 49 ++- .../MesWmMiscIssueLineServiceImpl.java | 5 +- .../miscissue/MesWmMiscIssueServiceImpl.java | 1 + .../MesWmMiscReceiptLineServiceImpl.java | 2 +- .../MesWmOutsourceIssueDetailServiceImpl.java | 37 +- .../MesWmOutsourceIssueLineServiceImpl.java | 2 +- .../MesWmOutsourceIssueService.java | 8 + .../MesWmOutsourceIssueServiceImpl.java | 9 +- ...esWmOutsourceReceiptDetailServiceImpl.java | 47 +-- .../MesWmOutsourceReceiptLineServiceImpl.java | 8 +- .../MesWmOutsourceReceiptService.java | 8 + .../MesWmOutsourceReceiptServiceImpl.java | 38 +- .../packages/MesWmPackageLineServiceImpl.java | 29 +- .../wm/packages/MesWmPackageService.java | 13 - .../wm/packages/MesWmPackageServiceImpl.java | 11 +- .../MesWmProductIssueDetailServiceImpl.java | 22 +- .../MesWmProductIssueLineServiceImpl.java | 6 +- .../MesWmProductIssueServiceImpl.java | 18 +- .../MesWmProductProduceLineService.java | 8 + .../MesWmProductProduceLineServiceImpl.java | 12 + .../MesWmProductProduceService.java | 4 +- .../MesWmProductProduceServiceImpl.java | 12 +- .../MesWmProductReceiptLineServiceImpl.java | 4 +- .../MesWmProductReceiptServiceImpl.java | 5 +- .../MesWmProductSalesDetailServiceImpl.java | 47 ++- .../MesWmProductSalesLineService.java | 8 + .../MesWmProductSalesLineServiceImpl.java | 85 +++- .../MesWmProductSalesService.java | 9 + .../MesWmProductSalesServiceImpl.java | 25 +- .../MesWmReturnIssueDetailServiceImpl.java | 14 +- .../MesWmReturnIssueLineServiceImpl.java | 2 +- .../MesWmReturnIssueServiceImpl.java | 6 +- .../MesWmReturnSalesDetailServiceImpl.java | 25 +- .../MesWmReturnSalesLineServiceImpl.java | 25 +- .../MesWmReturnSalesServiceImpl.java | 6 +- .../MesWmReturnVendorDetailServiceImpl.java | 30 +- .../MesWmReturnVendorLineServiceImpl.java | 16 +- .../MesWmReturnVendorServiceImpl.java | 2 +- .../MesWmSalesNoticeLineService.java | 17 + .../MesWmSalesNoticeLineServiceImpl.java | 17 +- .../salesnotice/MesWmSalesNoticeService.java | 16 +- .../MesWmSalesNoticeServiceImpl.java | 18 +- .../mes/service/wm/sn/MesWmSnServiceImpl.java | 16 +- .../plan/MesWmStockTakingPlanService.java | 8 - .../plan/MesWmStockTakingPlanServiceImpl.java | 6 +- .../MesWmTransferLineServiceImpl.java | 16 +- .../MesWmWarehouseLocationServiceImpl.java | 3 +- .../mysql/pro/task/MesProTaskMapperTest.java | 280 +++++++++++++ .../MesWmProductSalesDetailMapperTest.java | 220 ++++++++++ .../cal/plan/MesCalPlanServiceImplTest.java | 119 ++++++ .../plan/MesCalPlanShiftServiceImplTest.java | 53 +++ .../team/MesCalTeamShiftServiceImplTest.java | 108 +++++ .../MesProFeedbackServiceImplTest.java | 220 +++++++++- .../MesQcIndicatorResultServiceImplTest.java | 288 +++++++++++++ .../qc/ipqc/MesQcIpqcServiceImplTest.java | 390 +++++++++++++++++- .../qc/iqc/MesQcIqcServiceImplTest.java | 3 + .../qc/oqc/MesQcOqcServiceImplTest.java | 3 + .../qc/rqc/MesQcRqcServiceImplTest.java | 3 + .../MesWmArrivalNoticeServiceImplTest.java | 3 + .../MesWmMaterialStockServiceImplTest.java | 110 +++++ .../MesWmProductProduceServiceImplTest.java | 78 ++-- .../MesWmReturnSalesLineServiceImplTest.java | 7 + .../src/test/resources/sql/clean.sql | 8 + .../src/test/resources/sql/create_tables.sql | 230 ++++++++++- 328 files changed, 4614 insertions(+), 1020 deletions(-) rename yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/{wm/MesWmMiscReceiptTypeEnum.java => dv/MesDvCheckPlanTypeEnum.java} (60%) create mode 100644 yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/task/MesProTaskMapperTest.java create mode 100644 yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productsales/MesWmProductSalesDetailMapperTest.java create mode 100644 yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanServiceImplTest.java create mode 100644 yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanShiftServiceImplTest.java create mode 100644 yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamShiftServiceImplTest.java create mode 100644 yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcIndicatorResultServiceImplTest.java create mode 100644 yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/materialstock/MesWmMaterialStockServiceImplTest.java diff --git a/.image/common/iot-feature.png b/.image/common/iot-feature.png index 37a68a5b6737010061e0b508d6c3fb999e852e5f..357781c53e7b82d60d8314492cbc2748cbca8a14 100644 GIT binary patch literal 59728 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 WW+UAnPuq&vq}1C(fC2)q@%{sei?{6n literal 315373 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

{kB(X`o@jEf~yvK^BNB9Otle=wRn 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

69@Y~&i#xSEVH=D{;&5GhC$vNrH|RA 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 z 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

yz%C?BzT!|krQx8$bB@WpLE8+|G- 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%0An-*H_ArvJG~M+mv*mp z{{VS)T41rh=J&?kIYibH@5Q=OBVeN(eeKw& zl7fIV2eM?ANv7~tM)N)H^#(B&rU@@(&wZOayX`uPZR1P@?*Pg)H-OD*%?m&RwxKTM z{_kGfrzF1jc6BeDT`R*Og}ky`!3O>7QYnmvIu+DxHRE?NEixfxjls0hW&8Ghj45=( zF#*so8)AXOj84PMYr22GxLJ9iucgvzYcr9;UO8+8>IM=bZ6=6!1v2|PGdMUlX0R~P zZAC-8o5M8rUfah7hYw;m9tJd7vi5VyXVK1Kt}*UEAU*_mWG=UzwziEpf6{^Mwa^Tb z(Hqb%P4bKQ%FB67;s$c#?J#c{Mp*vZAA9>(PePKz#!E^_1OiAM@&|cY7VS>xL^UCk zkpM20;gQm(%E{cRCbwS=!wdG9Pg?bC_z!) zOzG-0K(*J`z$n45%f#9 zZMNx?xY^tu<+~39N}QS^scTy20dfQhCq6s?v=hVU?%Vk4m0uNlrtiZf?upP^Zx_@I z`3wI5{6l&gq@meme(;&MLy-PpstX{|NZsBhmf<*z_%vBEWJ*$C@Ni7Q0+m{Bg(p$9*HJ1;V zZZ(JOK8Ina4%!TqMq5@H-)_OcI*@t80MbBfpt?aIGywumrU~#NXuG7C*3@%8ly`=J z*h$^FAZs=f?)MsQyP%b2OGJ}FLv37M$l2I){6i$hgc&3p;0_UTZaKz!8)s=%EpWuX2r_=m z0hr?;{l+sjc)yL1OERWNWbW^N(P;OojE)Tf-k?O!R1NE}ZIulQf+%_A z!l*)Gd^Xm*KgHb3wSM7mY2y>i48PTBURDdUpKYaybbi!BfAm<8VRCEFpPR#^qMl}B@eHCD*yy{O%ng3b6{ z*2w^#BX-v}JJJq&q(se@;M(}72X%O-JA~z5Y!8C{{Rsh6f(vuy+bi=5YmV@PIW_Ta|d2&|L5 zh!c)q$bK(s=$1hYHp*_2PVr?!C=sgU4MM6j-uuO_fY@6Sf&DA@tm3g?s0fs)|R!ywaw}InDmO_FFUGmE{ zJAnP#A!KhFZtk>EP#>(iB^qRvWRgH>NG!C<7iFYEp?Ir61S$@_eTjnHA(YKG2F%z2 zVIGd8gM9X|`)?n<$3C}OEMeJR95XTH6TtAhK`OpGx#)Bju~(WQ@Bov20LnCoi_b4@?FVf9J6y*8a;YJ^qE28z$|m>lRWZa* z?GfCxZZ6{`p#{$>z3RFZQB=G{k<-lAQru|4zA;Sk5GnyX`g4A zWHcGKs%FH)J*TU}zN0}iQJ|3mHJf{|bLPBx=?zL#*W((;H~<*nCpi%}oeT_&6J@fN z@gs0=H7sx$1fySViD(kbL7MKnE9Kr~oTxzHV-f8Ou0SI|k_!cvsCD;t2C?c5UPr}ufe1@oK6OIn)3!$-k6eG?^;Mnbmf>=aX&uVclA#FR0ZnMrBoJ!Brt=C4G{1C^p;;{M zlxb-~Do!=MhlquKB3Wr3x@&#gUgJ2sXH^y*=~#{mFX3yYbZe_&p#VQqT2)|xnr)MifB z1ZV0zS2--^&vX>cKa>UYue(uazndiQZqbs7y31N2RVN~OG6Ep9H-Hu7o*a7krKAfb zswQJ1hz4iDYw%UK1_>YmnFGG<*M-l;dN;ZQoN@r0WyT|iA#N+Ana`#2a7}E#JR9wph=)uK;;!9$UuMg}zG>{)Esp6>03ZM@N6&FP4z6YF!%KmBZ$u29_+s?J zbt%JJzYzy9eE#=G-MAN1Il~U(978t`2>t>9w-C{biGyYE_F>y^THhA+cwLKz6k7U} zjZ)zz4BN6zhvyubmaPAGE8ZDsLG5pEt3TwBSAxQ}^Z zu8qgK5DsGRJ>i%;m_LSjEcqdU2uRW||_90n_a}LpAvNzl`%RbWB-Hdx= zY~O$}*EU^@IJGCZvDkxmoZj1;4=|D5iL-OduG3KN#M#4{T()8CgU65AY{SI+D3)E4 zp_g0bo`xS`;OoR;od$B7?vBtGzVD21%#Lk-kYlJjwTo|Obh){}Hfc5)-T@cx3qKje zW}0ajmAh$v@n&T80i_Kys3+;EO)~w6{3j9ES8!Kw8*tXDZSF^lR?wa)Er4^ zhF!2;H_cC4{bNI#?frfn!wy#y4aNZ?)xXR$#k9MRK9&D zhkjXM++=myn!!L!oy*=l_O4l&J%@J;)Is(PJ#Fb}%U7A5_DctKmO~^w8kRsF(HYzn z?=nk7Elm*a+gi54!#R&@X&MzncYtwlA^+hgQQfVf43JtvMQAw^P$!8-eDf3|shi#jbeZ1tQ(n>T;uv7t zVdG4acUojJtpID@Xa>8hx(XY1;Ry#MDr=(h8YtmFSAnq8=k3JKquw@q?%uz0=rpYc z9k?N&(|xy(Z8rV$r)@CVt|t#6WHOng?r{7|C0BM?GMdhxw!`PHVCB+iH<9x>qfEFh zzHRe}cM%UAI(EmlWw&53%SUh@Om;TUV_7sk;|y^I2@nh!%KW>Rl&7|Ki_3@7cTFgB z!4?dh%m4>6ZK}9K5rGV!*(`(J{{WO5P*-sdVOEK}s#EZgByk;;1NKt@v?#I98CutL zZjIrUM)HwDikketn|thkhVtA!n_o9FwUASeY9(z#jnw`pB9>P{=aKRYkCgf%S8rbp?JXW=C zl;SAAcj=dn?Z%NhNCGqw2KO*Sb=t7RGSY@+PL-BgB>vEPcLO<+$|?$)XU8R9#8uw^ z042Fmp_n`bs{PhcN+BpRP_!W1R&o8Rdj!bllNm(YXt@*&Y_2*wRUG0j>Rec1sPk8Vwtxar;1aG{k8&`n(rE9i)?)Mi*Tsul@du zg1fiI4BgwL<}wmi`fUA}$s2~Eoi`mYa|;y-0O~3+wu`32r!M!OS}JsV2}lC`3!uhZ z#!H|9GsjGb$`%@3D8yDE3~Oe`G498_dnCp~OpWr4{{ACX8kRZ@>cN>j-fE1}poJM4 z_ev@RHsoUw-Lld|O4|-sbhhFxr|p4F_Jcd7tS5Ms4#F1m-L|$|c9-lAFoPa~K#|tg>M*igO(SGL=O-58p<2{SNGR?Y~8nVWlPIp=p4Dux+wX#_xs$WB8qbVntTviYP8;uYLn z6VTJ1;BR@6?O1DclFMwCiWX=JpvZuYQ|u}z0X&K2=9JS-O|1>ae%w6is9;gs_Yo|= zVcR4+ExFxkmf2*T)<`V|n;C){2pTPWOTg6wBrQWZ{qGu;G%KAGR2K1@PXsVnqQ;ZD z?Fld-H-(3Wpz>bxWaCad2Fi{drr5^_%+2O=i)X^oU@mO6OwkX%((Veh(=32$UNjkI zg^)^`04YVw%vvF$$ta+p6y`>J5{eM%t*LA68et@_2YcDYKXVTAaPF2FZJp&|t>#gt zsv1yPAqilV7S+Ph`bH_V9PQBH2!W-$@_;;w+Q!!yOe^cekYHPoA~ej}*)G0gejs69 zwBiySxc1#N&~2t(m}g9GW&^-?8weGW$9bSxASg?9f5a1*l_`>8hu`LE%LBd5w#kA88TXg0Y1>0|*z6`rzr-Zw3?Y8$FscEJ=fvwh= z6xJAGHNnN(lXmed4lf+O_uOmK3m+39ypr}};pMXja=5sNIg9qb)aDW@9sCqb6nm2C z^gAs70E@g27brkvJ?`DCX@W@&7VNZ% zF&Q>Qn~aR=uX)5am|yZzmPYa2m^a;D`KFmJd!cu&!Z9SY(Pf!N^GxoJ?8&|0N}xc+ zC>08g?ct=GPK&Ig`Ompy8#rzV5c= z%>G>RB4FYfiJ5?YTXgm!2kkInrkN~1e2s>8X>@;Q)oh$0V}Sv|&7IJ4CoVIb0XnS; zy(GsC#*Ag$L_2yfnHpt1_ZJYdvAjlYfXd2BoPn7%5tC4=!ismz5HnIjv%SguMx#ge zUhrWF0%Xxjr9o$Sl14~qRG=$sMqcj#9fn?(w?Sm1Y@!y4Zkx<8xVwR{J)%))1-HSB zWVjgXbRaMO9L`$2S2|%hypjog)wx{CQrMi`Im6iu`N?w}<{BZ0C`qIgQk*Qwo5Sf1bzW@^{WikmeY>I-2jBC48P!lyqZDp_SCE>OX zTxrH6;+5~a_XgwL_bywU-do8L>?O`#M3w`GFpRM2^hC~O9lTh9aRTA|Ok?(2a^elP z*#g+rgq@)K8)J?5l;PFK#pf(vY1wI;ry#xeTJ_uro8I}CW$O^vPA2n7wl?OvUtMDuS}J4rDm(~e z+_dhI7BFH&PH`n?_wU=rYSgWUcR^A6O|QM9B~Xnk-6`W=m8?N{14s5_43KwsziGBN zRMYOUn@FS+mw3@_OuvO`hTHB2+G(QB?)eRGWKcAl$W<9-Syd=EnPSxROK#X`mx)wl z2FMKl5YZLhXLs)-Bk>L583}CEc23NDgByk=(IP<&gTP-tS%bh|1#PdiS#yYV+c$%J zh&|c~oA3aef^iYyATuc>07>4Nv`=-K7HCQ`Qm9VtNwl5fD@}jNECfQxGa^e$8Cq_z zLqt#(Nu^CGYfkbl+qQ{emUmes?y%E4&2IO@AR{VB8{43(D81&8+SN&Mw-4_oE?-;^ zl+7N$#B4XZH)8tU*&|X(i?|tG+`dnnad)F2XHOivmqo`%Hwyiy@X*mQk0G6n$bi9X zagB-u13t?Z#0m&iid9T!b|24%eV=&(pT-CL_$j9q8vYmgN=CQ(=iVr z-!kE%+n200!10D%dq7!eel|lSqX7ULikqbZfEjEYfbSA9{Y`?eNVc6LP4FW<>$R|B z!zjy0-Xmmf&7nf0OX>&HC$$a)3xY>xV95q@&^TA);P6jC%^fQ&$dJXt2sOTP2_o zO78Cz4C-qF$slS$$yAKg9MA$9%~FMOHt{&BUq-}rAkOJI$QC*LrF{bdTw?IU5J3)b zX=oW`lmHJYH{~H9RD}eFXaUl^!5qqj_E3W0tB?45-oMJ zPvRTY4GAMm?*c*lbMg&pJE5`~2vwJX*<_(;3R-`}2g$wrB?3@=x#$fAERVcKtC=|( z22m)-A7Pldg_uj;L(Cx~;GyPl69_nlV&LOt@o3a6bTnh9k6cB{;^E#h_7Uq1ylAuR zn%{Ws;|;aS(~?H+;~|nakdwSSr|ypeB1*U-&AxLL+pcf?FE6aWHo+mczrsOQGW9B3g@l*m7EP4EdHGZ4n>fma#Wx@HlIHwq3k~Z`-&=6{Z(`mdhKA?ayYE+crdM)52LUAD`>cUT?9ULo%` zwM|LFcB^a(@*$Uh)<*0*8_cjGAKfeV#5*H-mN%PN zC7r;|U54CyMjo^oST>stG{NtGXw!Skx>_s%+W>&s-7Mr!X!muN=nm^(lF@7KZn9C5 z4>D>F_uWMb(>6-&KX~GKE_Cg-!!KgmhI&BV_KX+phFBq>D!Zzzg(0E3ZF^f~lF=oV z47Aqhq0e~^NHScA$ub7sGil()4-wUmao~_*-)7@TkOlbUSHIaiLEB3T*Sp_o-6T!G z$|J(}i}>-DnFOm$G_4TNdaYD5p1HD}&gn&5?2hRGu-HoR;_ z3B0)_LE*(T$tjhPOwb(D;hIw{{HiUWGH-DCE~`v8y`X%Jyp&a-RF+8YswDv#b5+2`g|AD-C`sVvJ!(tqIyvK**xtsmC19WYvDwq486!A z6Nfy#-#(3{!03E5PeW?G*UBJ(M~EXnQU`VTm#<#FNg+kuBf1I{TJsdnmg8)m%6!gV}PH-nJH_A6ob8rG zPL@-pt~iYir@jwnIHrIA5`!&&KRY$j!gcy;dP^g(xjOlH+BbnVInJ8e6d-(ST*X27 zj}16l!%rLk04>g%Cv<(e^DKo*5bdUds-b8CMHQgcM(AqSVMJ#)*g7vAGfCT z8_h>PLRDJaV44L0=uSvWBqFW77e)Xz>H>5bjcswK9xyasW2GiAbf8Jzi$wdto1 zTWyw`X<6=e5WcbZO9ZhW1aU5O%suPaqW9i>ExvOZqt@L-MPY^Abs0Uwo8K1PLOe3~ z`;NnxZr{G#VdFAqjXMnnnFs3aFuE7M`0TMaklbsnJ-w6XxVeCn2XcG6D~+7Z-pk~; zmm-+Wrb1r}4*mDoCD0BYMa4xh&$EVd;pEXvRUXD9O`pNTvf=^!MjW?zF1rzt?K^VtGX4|oCL$rzv-F%h z+Uzwf6S}5TeM*&ysS?vn(lFzDI+<{95&)4hzDJ3tS(v)`x=nd-rpiDwHy7^!;2?XZ znpL0{%?3YMPN3TzAQ&GHQHNcOlZa_G@31z!xDThk>V_l?O{}o8JCQ-+qPcZ zd$BK_MQ*Y;;-@XN$wVVCJ1ZnI>&=3fhieJ+3@qy#Hk-t3Nxiqm{YS#On9rbY?4I>b zuFc!Il8E@C@*)yLDuEZoRBfFP*l;6gv+7X~rGL-Ja7Oog(hd%$hsGtFN&R zBw?YO!bu|DT^U$|y>hSE7hXDU#1k^e35-OdTz<^}^|x=|I1M~y(@ZwgcCi>OiFePl zW+wh@-;H={i?_38$otuRuU5}k{e+h~Wq*WrD(ZH&}9IH`I^_yp7=E1QjFNd&D=^Zl z}X1x0zUYuXU`Nhn{41bp22kvFFnT7HFtQuvxrNO%In}XkE#1vfJ#1t&mVIj2zIw!@o?%Rx>&I>#wCC*ZhV$*Uc`c?a<+{%a%h7w0B!0 zb%##fFbE7dV{(qspc$hnxG2bEE!e}Tpz+kS**=?p~%@#lfQ@Rbg zTXn2EHSTw5z}T6S8>ESdH=O&%P`xKd3&zr>8XLP8jRl3R4KNM4b6mLHjJI0^t|UeG zyzEBDIBshRB$dkGOSou=iKJKdu3WbH`Edyk4%3$p-n9`N`P(jotVp|hJ3-k@{6O8da}hSK{{Xp3q_vRAWd6)} zD9tKBBmkt45tdmYpa*o&mPR&h87mL=Y}zH`Y*DNT#ZPBOk-zl`H*9XU84T|aXms{{ z=2~d7p)#8OFj|_+j^eT;<`WH{vGQFhfQy>VCfFs4a1avM z79PY#N6aIxWX2j@ER{jIW$W1Zn8&R$;mfFYOZMM39XVm9o-)YyJ0i2`;P7q)0lva+ zWDxk)V%$f=FPm-bJ5DbfA_%7K*d`~lXvlC7G#RaJY?ZeT&bI?)jh(K9`wO;$i<{j{ z8n{xKtaOiMOYwPS5wX(g1RJQhi8bSKb)UjcAfg@z-({LX#Jz=&a>$By^|o3K+KKHi zhq`-C-Hy*owRf1E-H8S_<8|hh-SacM&#q1AkVVdL-gYH1k=Jqj7>Gk!v%153ty-(u_iv~yAlb(P@VfPE;kQgZ>BGz@xmPyvyOC_&dZT5o=CT^lm>{(%B8CMYcW$zUj;^x$WySUN>k(qUjPOHdbaRvARhHHVSSk3mfnQNLuhE9Vd za1p7>%Jbn~*shz{Ha}?`NFkfsg108}-8@&4H%RZ}Mj1ptxzX|nmt|ft8+orgsbpLm zhQm*qW_<)%LQA`AQ)Vb!L)kJz+HZZQk#VuO%P85K3NhCBM@9|kh&)-uo1uso`es=z zu)}OSyR)0f<_U&gK4aNBmJQI*Y_czQAZ+!Ck-K-y@CsFQ=1+D++8Yz@4%!%#cwyip zTe~v*&xP{Ige~vGn8=rK!d&U@B424m$Dc&NKWT`lrvvRwIfyL8wC^r1wi86+X4XBX zmva4GdF-_}5>GpXdxzJGNj-mdW^qug!A+vBC{^;TWObe?7FjX%ycrFn_sD_Vk9(Gr7inAgtXO>VE_rexh-XUTj}rbv#Xk8cntR) z1iBz`zNCUKyUm1fR_S2Q%UD4JA(Ttw?;ZWPH+K?oBK5w3hmD-#9r(Wzn0v!`W_N;b z6}=rZY{X33gk$Z6>xXb~(9rA$VW!Jg&u7cIcJN2EQ)z4wxiWYuMiXNe&X*@>Y4#sD zmcyH^D!KT#GSG>o7!s(uZ*{9EIq*dExJzg7B z1138*f*UY$GkSxt&<^`<;}N`CGA0boyT>4^JMjMi5b)y_qx&ZC?)u7Z<{9k?e5Lok z;$L{1(&%2iAldTuI-Ab%M+G6=zG;bs9Nu*wD40v|`W4I9CH#hX_7#R&`)h};H_LRc zb=JeHpLK2x#FM#@T&tlVmfdTuCv+X|OJuT-@kdbG!~0gBG#&56ynfrp;$Qnnr^k8g z#-3>+>g*SY7_+lo{KO1WiFJ3j<;L6HE!t93euwy@>>0#6w(LH_Tq}f_7jL2^_ipS- z0K1deH$KtN+GbIYp8Hplm>u1u?2(Mu#~rXD>fY>6xmSY^F=kp#%*AV?KfAMgvhEiB zU8s`-HJ2T>8Bj8?5)0~< zwre`%8I96RK@;}v*x7EV?z~rN-g9P)hE1ov?%ZyUA`BZ|1@fluy8`jcgF|?Gcg-_R z)|c5dTGc-3TB{_LYO0rA{6m;Xc(}*!gQpOz#6-Vswp$_8Bs&c~eDQ_`@ZJoteUNK5 z=+^ZaHm>dvC-U`do!8IWWt0JuS$5Kp00t9RlXCwKg66sQdMLk|Hc z5CGF4GD}HBWdT4%FqJTMHlu!tN!00Xv9RbbCIBaQD3M{TX11|(F_iXG{*_U+Du+4N z%XGm44eTUkI$YgbIe&RbXLL5&0MlLl)>;aMck-hxWXU0tLqyxpOda5j!0ys4ecEsB z?_69tzSWYgma&b=C7EOdgA;JN>dh`C=#C6-xnthix(F6`Dp0gTwqE{?-# z^ww7yE`pDkO0dR6_UqpZu^$l%9mm2-uY9Hv+sOHIWz(0C&)hQ*!+Y$p^n3|*7gclG z9Ln@tMZv%ky6Tieh_JYB^MTSL#>?fKMZ4{z)yry8sOq4!bZKE-6CIr51>=qhejoyry-I-iiZJqWZuWlhckjvZ`g_6?}=(gDn zG{ZLRF3!;x{{RoRZtVWRyb8Nle)8=PkN78YS-No-&A5jb65(9yopR*U8{3E%#mobz zGZ^RzTZon&N~BVlhfibXPa9W??WP{lm@kId--(+s?WMF7Yp`Bzi5k*JeQnvF)nlKxI8+ptFA*pp4>*B%kv!uecV*K_AF zvxeo9xH(&F&1G@$vGEWwuuKs7fcfhtALql&blXp9*t_eDn>IMW>#cxSGWy#jq%zU<;aeEE}u?Xy;9hRaMuD;Hkv@i%dW&+G`eW^74Y_xNO-4Co)+!h&%JY9 zv^Kig_YrPx9^ysMzzvtB7@2scxAzn7T;mVp@9rbwE!!7DUv(~(-MsMdv*_3<6tU!N z&Ura|0^$v*mcGdCr>!vMx1Scwc;$U|7r0a1lJO&F%yYii+TmZD{{H|0CzxY!WA9za z#>=gHuQb~9-6sD4d|=!Ci*#mgBd1MEuOYl|<ba(ipINwe?`}K-DmlT8-C>WjGBXlvu@syY5?N=P?sA zn@7wY-G5afGr3s9AxP-kXCD zdFEn!6!q)oCNUyDA+YJ|moTh3hGW>5Efs9xE$!R)6s{fy?WKva@++A&n_!ODkG68d zhtaTe30>2>@)?Y6)0E4vjwVGx#KlHL%I@pw{A9v+6$oYKDTgqSY_kqt2g9&?i*qfI z_RHG}aftXsjTgG*?ISzFyhFk(&xH7SHN-i5`fYaZOBY6aawacij-NZb^X6tw9leBk zI%W<5xL2QQdoYJ|(0Xmo&aXC^x?4SMlYZvACcC|t#}GEpyw}?MZ1;R1KG_jI!TZ@Q zx((j97dga0cPGC$hEXYc@yr7b-%KPES+uHS4-WP)xnYN$x^$aHhcyLo{90r9?KyiK#4Dy+W#-6P zde5_99ngK7TjO-HH;6`>Xf?dn>8n8lK?^9Ll+f-F-8+W&Yb*x5+XUcF(6|A1oX=;m zJ6gftTb+EczXW5j?fi-;xw}v9UF?f_CW^!pKWYp}-dxBRFz_t8ZYVuz(*?V4SK5MG z++`h?j{sffPj_?;-s&Skf`J1Jf*E!L2)vwYTK8|UzyiZIYaAiPr+75PO~+><37e7F z+3u*;L&Kay+XU+(Z8wo{ZvtR*z85@(uH-2VZh#`%1mq94csD`djWS4Dv>MeC%j0g+ zS04oLMZ~&Sh7xrhJHK-n8GNb4t>d>&Tth|7;H3s(6!tCTI}s1uM@K`4lE^U?9{Iy; zwB{AIgT_tbxvelR+y?t>yJe;#nPGy;4d&vTA(c(lEQ%5dQ{81*JHK4|=v@2O`dt-z zE|jY9Ka#&*fpiZTOciUcB9Fb+?XPt0AFZnG=Skj;L`| z-Byct!DC4d-f`^Qz%WRg_XBXguF6=N`!<7cl^a5|Q!?hmU_`VFW;-B~V4gs(_1gi4 z9xFt)!6Bx~lGfn+-QW`{hJYbzwM!v83^6>Jw9fEoM!jIPpa3^m01_yta)_aoWm;$o zUoeC{R?LG|s znW%S;T{Hc*O0eW_vyHjhi6E%R0mdkGhsooM@IA*68el7Gfr*l{~Bba{#_AU&* zg<>)t64_*XQ0%;gaP8TK-F*z@>p8=W+bH3tHeZY!#Q5gs7dsO$M*Pd~wb#Tukt>tI zUTKt`8Mm%x*n2&R5RV?kT3(0sMcQlSB$pp zw%ici?IVnvXX0KL+>8XcnCpW06?O0Yj}S4}XdFwsa||V(UU^m4e9YPh32p`6iuO~< zx9>zlsCYZUGI;_Z7=nj=4$kW>ym`BBpiD9{sxZvm@2((K^oE5s1v7( zOhi0(?zt_2ICBv(+e5S-^k1wo`$g8hGt3EnaOc;`=0nCwFB_RgAH+-Nk#}ZgFqiun z$8z}Q9XgF_1iWFGmR&ONJ8yQ`xWu*+TweGhW7X&q|CFbtXZSZ8osaqJCsW3NBD~k zAH=)x+oc*NsLLS!A_|r6l*g7IfbCfTGy=3iXLh~d%7#l!=E-QC;MVYLQimcX1T`X+ zJZ!0I5!DF%MhF5KJG-ZK;tH)>Af43%#&m_7jBaF0q70G_>CYi?VV86T@A@@&yv6S% zXOm6yBIiM(#@p?*jnBE5zjiQ!V9d-V-3P4}T6i}|EHYRMM)(`2cO>rygImosgenC~Qqgxl?9Au# zyU#VcQYh=kC35l1qVdJT!$i#G?pp*j#4G2HntJRs+ikR2V2$FNth2bv)!@|yL1@r| zPD@ozDhUBlWo`v$;fcbGJttFh8s4~<0v!1UTWQNecu8K8g*;$5!-}Zdl-%NQ%@f#W z=rC_+(<_}aSo-nHwq{X{G+GM~@~3sCSwCrPG>o#-MAfE<3!NE4sjTg@W`ASbce21c z1Tt}J9NB4sP)k@~`Id`Y%(NM0mO`KmfEf*v5P`DTvIJytX?K0BS_4HP>1vBY&}i>6 zHEOiZ+Sly{!z@^ij@grGtQEP@IG23(N5y%S`4x9`v9FcoMU)E8IN=? zm+gsjYi>3i%B*qSGGUKw$1wz*d=*35jTG`Dv-@f$S^=MHaU}b@-`WP2`CZa?x7k;% z6y0U%AhyQqvqo)0-kCHUZ)kUC`w!tE-?I;}?kvQ-cM{>uTc#U#EV?W_Z`nO(?EB68 zMwn^iE{jw&Lft6vgbRfEzpQ4*__wj%#%!Sc`jccM9iNb8>KQ<3La4 zv-`<1on8s!4jfG;u+Z>7VTXW~eYfq+HxS$)ZMRG~Zt-n7dnWi7w>HUmpyvp2mlN>L z;B3!|m~l9pVE!IVuiRw1X*ifjf^2x)VtP9d9!hL$w^GGZM(W*oBphff`bw|4rP z%xwy64P{`=aq8Pqt}yCAQzrYpqBlUi-uyW=9ZIc7Rhgm=8IE(9=GZuIfD9W5Cf)Nk z>AOxa_DOQEmQl5R&AZZjw~iY<;uaU)8>4-$^tHsEK4m4IUl~Q(yf-%R#Y^bi>zSFk1YV23Nc%RxZ^6FqU&%jJv!F`?K z@4e2yIQNS<_jK8~bJ_H!`Axm#@Ew?#2W7(lApFPM1V-QT0T+rCGB!r%*$ytOe@NW=>G0r`_z zkT*`@A*8s&v?d_NK*XzMba8tMHi+#i+4}qJu^B7B5LkJH*sm(uQx!1cNMNwqGDka? zxn|*ADXrjhE{B1hPa!An7>}307?{Vd+!kL$y$wUe2V10m>5ag5ca%0lk_%shby^^y zXf)7kBfLtb4Y<3veouAbUCQp{j_=*MV=enrDUit_ByzT1D@|{;FPB5ZLp1a<*6#ak zleztwEsfUgUpt82V|A|cK#ko35xc!oSs{=KLV~-<2o~kzo7!QdH(O1CyTHqcpLm_o z<7gQL+1a3mkyiB|S+yWTK!OAf=>R#r49E~NS8DGv%d5QvRj|;2Eh!)X*S2W@XsrWVQbQ zqg!70LifI~#I0bNy7CU=fYYZWwUqc@qdLJ={HWRK-XY=)VsDN<>?cr7c_ z=;In|*8mX0J3XuJ4R^2EPqG=CQo>^*0g(0uLK3p!p)qo ztil#!FqYjNvTz>p%^{?a?`IR}h#5=itV76241han^zLaEUA%J-2>?s@h^C!7WrEvn zF=vXsr8p@z!;DCjLg7Bu(D4&ni+*L$jmB)@ePJLR#Z0c;dM;CGiI%^dukV@xKFJ{-0 zX$cJB<8Tt0TMaPsHe&I&P;joxFJc;JT++oi(>VM$#pozkk@1mH_;ZNRQuruW(J@gm z(UDhLXzC5by~8frZZbM8`}SNqaKkMYn=YNO?YG;ZuUhV@v@pG8BK^l!19qoYKo4OA zjmHz2gV>C(7Vtn~ev^$f-r7y6N|=*PuLrP6-OAILf(ITr>#+0;49{Xcl9`E>N@EiO zE)$1uVqhWW4Km9z#vS`NPv1E&d(10O9J@Zu5Z>nNRBIFaD`ax!_FkX8Zc{7XceH-d zY=)joAtIhSbmtK!Ofd1=PuzQVPZ({0S$5Pz&t@BBGQ%#5A)MjZl1VnYn;Y!8cdt~M zV_@=9L6SBGj|CY4GjI{1jYoh87_OF)uc<*`?0&xqJjWCENT&h2CZJ=T6#w+tWs#xD5wy zMH&t6R`qs(zsZP#fn*1eb81Tf|T=iS@Kd8V)%Qf%vZV_+`yrao;ogpx`xn~3?;<>U-3JVS7@ ziBvlcMMXxmkkC$;ZRAt-7-Y9=vA3PlyjRm>U8%11*OASyHRGOP4eFOjWO5iNxwPVO zFo}BS?C^3~YljcwW1^m+JCLlreAeqsIvv5g(j~oK5Y=|{REGjcH!RQI26&N{lDU;B zy|rcFpxPI;2OeE4-cA}+_Zy;Z^%tQzx5$g`#I(Y0} z>?OIf8@q=1Wa=X3-I;v;S%=pW8agGrrz(Y;z{j|{(&sUb9zQTl#Y4;?;={&b8EK|o zyLjvto;LM@4byG+v}xmHmYQv*x0`LCTXTg6tLuvLI0_IFf%aZP4X}yA#T8?X;+8do%Zs^`HWZcQ&kcqZRuesg(#_x1f*v9~X zsqQe=NHQC_0<^^@M?bD_`p=tXt z?n`c246@TL4aPUaTc+LIwf*9Ax{6_=5axHii>3-thE=v23PI4KC9e}9hTJyc^QTW; zwCVG=uAei!B3ODFWwu@hzp`vJcbPuWHp5J`U6vXjd&6zVHM>Th^GlgxMCJh-!u}J; z-=EQT11cSy;ZL&iEaM%QK!+Yv20^*E6^>gw?GJLck-8Dr(&RTYaRV)xy_UyIXE5)6 z+RH45Z($#j%U@>QnL(FPZ2KnOw+=(bA2jW^uUs>AFY_U(6QU}S?zd2>PiIg|Eh4fg zQh>5RBr?|bZFO#C)wy!N*tb6E%I>tQ?Qv1>C6d@!D0ovB81d`an7?BV13zkh+eDU+ zb&lX+gOKSl5Py*vZIVDU5%)*{g6QuSkg^FxHASivEn8O$Qw>{c1BRw)(*v^C!Eh19 zxodBV$&6+$mdJB)PZg>GzTyCfZs;Tvml4A;l_w@`+c7S;*tmmlRLo`7~z%~aOtw>?zwC;yf<|Z6w|7(N#5QFMHx~_EYJYapkDJqrbRb_ zwvjft!2C(QU8J}x0e7yP_GN*)NI${b!H%=2IUGcN+kl+xE^cct zW?2UB?a!HNE7}KaHrv-=520Z2?CUBTj}4|NGPd#6)E?K0U}g5mBYkEjG~Ih7I35P}!$s&4e~`!JD~vCi_wCO96N< ztQ5--KG?<2xe$|PUgB;40K_Zh2@1?C%5wTkET2o@CGxm;tVKsYW$UlCHsz1AKDgbe zm;;J5lCB=KEh!B&>{8T%Je`Z057c*E_ zag!FNJ;hg8Ue;2;zv7$FR zrT`k@F)whikv*M33(nQTSETGn+%bnNhnYLVq)B0kFf)lDjtd}gFBtLX4t9yUdopcn z9fp_EVT#u-^Itp@#w;k5%&x4qeKfeR@bMSQ;@+#9F^ifRbmj_67Up#)n8QXqgNcC! zm(GLsnfo>rc7IED;k^4ZMSoXWrU~Kg%D5PljWG9i4-@Xx*7VMC*7HQ-B>wSDWzf-( zF_QReiFDxJ#kjjr(`Rf)%wwle(eIx#4+7!RciSJ_d>Ef?Q*$qN%{wAbE^ZKE?a{o^ zHdlKpzC5Mbc z2mNlvdr#sf$v6)*!HiJZV`+J=B+KzD7jGsDO75N+&1X_pPfBC9$)&O)(2{ zqG0C{5iHEi>D)9Sk;Fhwpj(S!ww&8T7f!1gT;bZ+)O)b<+Jc_w?LJ+&Y&U@dp|}EF z4a{s|8NFVctG(fjZCEtJq`9qW0Kl6Wj&L+rhZCM({kV2&*_UX$kA!fS)@y+n;~#tR zlVz#Q*~B}W+dsGuCYMI{-C0z8)x()&%4v5d&IID=%4W^|nqdVS_GZ|98t?3n>Pydz z8yD@u{^ejEGDG5)%(&w%zL#S7VZ4tK?klV@#7QmfyE8X4NNGkLUnzvHHtol;9@Ca( zPo>Z^Cs8w(3Lzm{iY^_qPu)Bu+W!D&O`C8Y_+1%v+WBHV-Ny_60FK*HZ2590kPvYf z^6%peT;69qx-tl;hiyR4XP9vL{I)h*0K{W1<}+w0*Kn_5U9{nsmiKFHWSDK^hVtE< z@Ka{}pxDI;#rnAOvxxY`gz>m*ceZwMckdho>UDb}Z*27t8>O+GmwzW}8wHl$KlMBgkdk*tn({c=N5nxZcx=pC+Z0mZm>aJxj zvYl#s-EjbWjvvL4ARc037FlBs(3?SGKG8ShW}TFxu;%8sgEwyOPqD)raaKt%y>huM z?)O6(h1a-uO6betrA*8x59MwenNB8A@h;%u9W?cq4jnv)4Mf_DnYR7!xi?>GtG~63 zmhVfkUt}w_0elDN)92D?+5FMd5*YY6r_We}nMK1g z8Fu77aPEb^le^2YhSr$%iI=M3Vr~Bbz&)sL_8U%PZ|)V`$&LP-+-z0DnH%e;GL&BX zvmtcyYU)jUV4gaf%VV5D#6f+fmZ4sj-2J0+fP~q{6*ktpJ9=Xc;kmQS9Xm*270kh% zoUVQ%LNOz~&+gtAzk7NmSGxU5w_iTHF0YO7a^yll#TFwVge7lv!HHNd(Tq4q7xF!J?A%iX$rA;cpzh=-lx1fo$I>TNWXJ&>_1 zYuUv)a@)7Ai?$_uF^>)QeA};VTvWftYU*0&W$l;YBsWqH4cq(Md#@DQZFpO|mlp0x zUpjXYGQD$n*Mbrn1;Bn`UI@6@=Z@iEU%qu+NOsP~x#k#L93sLEoUvZ-ZHM+tlXI^$ zJ}F^z@&^Slsq~?_e7gBx+sl92c?EZ`EzorZ4>6csm`l4kjGIj!M8ddr4CUvx-==W~ zV;L6GdwT6TF~&Qcc$m8}+b-cWmke=+9tv$Jl1OnezqG+kZym*%Irb1u-pj7jxOnJi zZr;U3%Hf{I!8TcS8u;5x;=g>?`b{%Rh^F?mQiAeDY9YKE1kbu=1Gj7eJ1@dG;pp`a zHE|B8(&F}=*7ivwdM-w72Uzi|FV@mKL*SOoKgJwq!^@cqjX0->*J9*gjs(hMA|PR| zoZAs2olCAg)Ws{~5g8EbX*iX`{i^X_xcN(oR1_nJ4`ncJ7<}odmw!Fk+6QTUpReW% zL+vq$`#9q69b;Aem0?tLeh$l`E|uiL%l`m*;bP6wZS*wK@y*%3*A6~u4f_s0XxoWQ z))por5+&oU$IQ8E!D8*g+FxmnjfNfK))7rFe$hJ}I>!r8YGF?$Iln>+Sq&Ms`m zQGDfhs~9mS9`Mfc;jEJf8R+?%rmka z?zW3@I8xUQU%UfaWCnmBoQLSd(M^K zY*xJZf3$uQU_HjU*okp&lvV1w5(~$3CiCYPfz|z*K|FHB(}II$HOx_qjbTJ7W$P}Q zcGE45s}>t!rh(m1+7{WUBq7X!yt{#<1*(?2-P9b+KxGox6!(T5jqJ6JGAYw#_hS3g z6TsvEj?N2ur7D6R;OgbadPwb%=o#cpHu0cWGU2-}?%TFnC6FPvzHf?`zd!)(GpIgNpVj+sQ5w~h=$_-L5; zXKc$L3`}%OFUPTmY_QVZOPZ}+<{2njG0|dyKxnqZOtqLRyvW^Dp`kzsFFn$_*R`p8 z7n;yoPJrI&k%}$s7L3*(8=hx6W(35A}o2 zDTVaT_#jw@oA<|8(%kU z?~)aUk+9KZ1R$`{BoNae0-&?pXn?~ZqrJM#ti9%j4=)VGf&gd;V9-wO94W{mwcY`x zAzGf4WbB(y=@pV2$9V>(P3v5rff(veZv8au!T?=(M=Yg%V?W%jS8cZgcH z?JK+&jtgf8cMk2&qNFj{`;3@5v(&h1i0B8g*K+LM zNnGAGWe+>McZuXX*>nWm%Wh+S(!)=p-ML|gTts3$`oSHo?v4m-zl`^VnXWi(C4d`3 zPIidIJT#Wh*pH8YbFmapC6~VnFxomXr%+MR*9Pp(A)v105sGRSE&Q@Im3Zma*a8Z(CEcULPHoFwC^su@O3eV45>%RAYms z?dr(tm<%==M(}h@f;fX~cV#Bi_i9zlAG(at~^Vcbn*1MA_iSA znOsaIkjz{?Wu{#-8F{9$b4M_7jXY_lCD8A~EpG3Qhho{B?dHnY^9FBgQB7h7%ClTq z+2ZoC79s>>T)yT&O&;7SvOFy|@?SE!G17qq@#$fRmK+!CP!^4!!5x)G)>whGX4RP6 zG};RZr`UsxbE}<&_jc!BJJW;{*i0G27ckd$>%`tEOO_#{qFA3rLB&m=Sc-Pjh8TMG zIuY122A@2tu-^mbyCCgn<@%LfvxM0kz*!o1Y=h>c|0-!2-tleWRkq4TJW^*ozGIFTop|iul2U z*LL?^i=Q=tzE@`OO4*oR2Oi$?&Z3M2bSpAw=kf6oP;oHt8Fc7JHxlLR4!~`Fkjd`K zS!8s#2l0-7DZ2C9m4jG`w9X@6y`Ao*;em;g#zJ94)v0?D`J5z?x$!);ydfbe=>A=r;*m>cbevT0TImRyL2Cr~%G;zB{*$y{5D)jtlN zOk7RnPUeu&uAIDvdg+MfT)zzaC!wP4hC^A#>C+7RGSDps8QcW2N3&z^vhBmL%OS(C zNk?om-3&6$?%)iLld&{$EUQhe-UaTR=S&8hMVkPdjKPTDR(Kn@SjHnoOMTf~o**vWh_@6l-}?y}Z#RfNhWsrFE$RK+JCg!z%e!wYSZB zOaR7H5Cx5gc(z)=(@gbWROqanBaO!EfB;N;!PcqG_c<`HwXSbjp@htvJzn4=nsCZ#=zf7Q9h>bkKTLECWgpPt6xf_;}c_0KB~Y z*;)Axex3u>Y(#b9YnMAMS4_SiooSy6*ie+BewlJwt&&udS=^~1rm{2?T2)hXl8Tfh zP$i~L`9jSVGfm+^;;T`R70~jX?KgB)C(Q^R{{VHM(Pf$(@(i*{P=rFr{{Z83r+EdY z5te`iwv2(gSq&$3r6?#9c7?ikN8K$YpqSw%_9H=;0nBDR)R{lkhKz(A06AxQlVjuv z5QO{90;G;gO$M2GA}#k=}XroHMhlf3UDZ7=Ou{g=GBp4(~%z-mJ$CM~c zgic@|QNqb+gdicRmXe_6%{5_~kkBJ`r|^k1gLD9$(evu1c=F>^WP%z$%Fw9o!`+=sJ?=|E}-vhdXBxM1m00pIMHVqlb?xtd( z)M_|WcS`8h8_>`$L<>!U5N2}D(H6?&LWz;jU33Yk714 z=i-1Svi(oVdeX@idFj_)R!pU8x`iuV8K?*ePb*|E8>5Ji6Fym9JiAggRiqU1F+b6szGi!Ti5aSV?5;eEWEOlX6Z+NuRwzpm~Sq+`-($4EZkV$2PP}3?JMDCvZHso#NO|nC6 zBP5nfEIc8S$Z4$*55%8@7K<%zgbRJ1NFJlj{AP?CP!iZ8C+93e}XuMpqD!a8&L2pa>M@$3Ql5I8-A)tZFxM}C+nbBw7DuCAw zK+)4Tn~*r0<(!OliG~dpiw!cvDy5cMX^{V?7hcP9?4!Z z@PP0Kby^S<5{(Y?RH5Af0L`+1UHJ(Crlk;#G*q$-Ba~;nbPrmlL{WxWXLw}LC*%Fs zyNv`ASP`CZuE8{|eYf3B3Z->6%-)pIX#v#9gYOB;v*&x6n~btr)jAw%6BSz$3Eqpk z&|@ojcdTh`#1nDwGgyd8bX>w()Ke0ftZXbaMCw-JV#7>K#Fk*w58pw<%pJRQ<{`v8 zPCn4Xk@lkTfB~(cro|}r8AerxNn{p(&MQC`nIx9iA`8OMC=%Csi?bnNpzKLtw@?s7 z8>T}-jFu?$0#1ve%XJs%VnZYZ6DflX_dsMqIwTyZ(=Sf3Lbw5?p&PB2^eltj6(plorM3S6C@GtYPXV!&>|#yw z@QZMew?8JGc*I=8h$3zvjLvhd!Ho1aJ>Y!#uV&@Zcv@B&4%qgar+J;y(G0Yx(@c`f zRV;>ga$8;-r6_JmDrJ}d0PU#v%)Wdnyu&3oU9`#)3n7$6ET?&z6dl|&zFiFQrlFu5 zxp=_cVd!86fGE-c*7(Sf5SC3SLnzPL?GQFlniU(Mw91pcMn*(7yQ~rdgslfVXzg>2 zrPNbtYh)YE<^;?UH@w)9975jNdli@prmLc*K{t$nXtZnkMCG4?Yj|%KiiS6h3WPya zL8u_`Lr(1`9um-Ggj52RQVA3%T*3q(G_vP&gJYpL%lvUSWQ8RTRI z0Cz^T86_wXG}m-884Uqm32sDAb^{}nW#7Q)EvBc?Zni{3bCCqa>;_TJ$5<+nz4C|g z@Xli#v+W0j zxMAx}sc4!8zy#2g-ZLQ|_k)l7&Y6CPtEs&-~cbWm8*)X{<2xbYERhpje^VW{&%Xt0P zj_WxKBO;LnAF^TCMP`t!GK!3*^DlfiStWOxAuZb-CtwiTZVizjWM(a?5)4?G1WthQ zThRjNZ$79b#DD-MBF^QNhrwgxE}gSN4N8#F2uUcRT0^1`C<1-Zw&iy1+Z&;#(Tv#* zG>o##eeytF>W$Uh0MS%;T5A3`cjOzxepL&-Uh#!?*68wlr4SHNqKu!ywukQJ-fe~m zlfpDNLq)H$Fck{!pnlf!glIIV$*4Nn`BK+gs&N7voLImD_Bxs6V5Qv&Y5`2FPdT66-SLU^K`VQ*)WBMno@r1j_3iF5pB`8Dw92&y`Hft zmpY%uLBq=5-Ul!)KX_v05OEPPaMH-xo2OzahzLlS#^T}O9zJduMMXa@VVQc{PfkV~ zyCGyTyC{Qb)D!kLLoIhsU_@@_RDcks>a#?b?(Bda;U*JwQUj+&Z zt)#5-$v9Gl3DIbp(MDF*p;Y1V4X)NWz?c&jGnnBdauBlD!?zVc({bIM?96V+Y-i5b z?pVC}%v>w?knwQsx_<1o9tPPV*$e;~47@wRt>h!UP2KOrNwioytcICvHX8vIwf0~I zEFv;l19C=7{ey8gG5JS|wTlF}%>Hagp9= zd?N2i3niAM@T{`e-U1DP(XZh?)HS+7qdUr3pwN$9N2LR+3^a|v7BWOcz|QdzARmhH zRk|eZw3gKk10kK9Te?JP0CVG=>_`o72HrFt5U0A^MWMROU>)#?o9fdgl%Zs!A*O)o z)23Q2&@>d6fT0cUqUcG^nkXQ$gtdN|yHYkoEVC+u4EKXu(2V~8Fl4Xz%Ls}ZUDBhx z(ygcaw;&~v`z{dB{{Y0@Q8$MBD-h1>TdfZDDAPfE%>#4NhDnAv7u$G<$nZC`8_zho zPsuj`CbLL@Y}UZbbYx?R$i#69!#3M*TmI4h@C>uK&*5MI+B_wdC7^Q@2fP{~83VI% zH;8cUw+11t#*XUmy)CBkJE0U4LP~&1ssP9~y&te7EHVI-L84Hz2*QGgcr*Sm(lSw| zNG%G`nwBjlWKtgK{f`LBs4W;q3EpQmhxo?nAeKTJic+DQV}D5K)a<^ChyVe-G6;fT z&m9M34D(l|(RVT;sLt>k#ktrGGMwX-S(7z>ch9wLmdhKZpwVQ2Kr6b*WRlA!o5c|_ z4DPkl#YR1fVW$t`T6*b?=H07J23p=wH|a{1LV>nw3KEz2NbdP8mZdO=N-x-%CwnC$ z+NOn36y!pZVs8A8d6bnvgiuxqmh`6UO}?TvuJ3pXfW6qI(i&8OiY8=k&mVNgLckt8 zmPd4D)hz1sYdQqQtpxCmH5Vc9VP=uW=nDnWY00xueMv%)t%~Z zZ0EgcGZHfA7888z?%;o`up8r4T(4F?MXz;y))4GQd@^A25>8wx^=<^U-`H%m<*024}U)#)JW+$hk8 zIz`930kCzrJmTEe%`S_%wHW%f0cdb0^QbTY8ry)&Ej~$f12B*f@L+eLTsmNqLNxR} z-hH}BMwlmg393^yZr!sx%z$^z2p|GI$wpLhQH%wv$@MNNXXWWMQKrmA=ZcJ1c$E5O5KmWx548UTu`JGDXF4VIABfDkPL=ry|2=j}9smYD^z5P+?Q znmeGT`)#xU-tRQiEP~40BEMirTiz{7AsT3a%UjT-&@yTMeWp|>N*(rEsVsmj8@V7& z&)CpgsZt?Osjgx8Xk^av5T`Y^S9GqEKyOm*(i@z1fDHmf$%{qcfgF}U$p^Y7vjc${ z$Gd3}n7j~YlyR~!u_2An+s)=G$PGL@jQ7JqIGUA44)rCSi$4?Y`~Nr0d2;SOr?#21 zr5F;i&CHoOmeG0G9Lu4R(j1dRIZlY?G-vf$Lor2Ca|{zj+dD+494kuo{`o$B|HA#a zAJ=_dulsd9UkO89T`#}axmt}>$u`+BlDwBjKSPxjdu_MVNGkIAABdl}khlI%zwPVRJC( z={?2aMToS-U|h$Q6V} zbDZd2*Z#_noKf0675}9VQ`~X{EPg=c{4uJZCZZ}C^k6P;z@S?vbuH7-#K3Lk&{w7{ zF1fz8(Lk?@tlFiu)?6W%JLdIQe*mHEq<7#}a9lbK49`pk`fmRvjDuwqWuoE0GT|xOzJ%5+tIZXg?85YVQ99EjD*FEE;tS8*WOKc)`^RZV4(x6 zcb!pt=jRxU!|WGonny-6q}gAGWXf68jvKPRZ<0YujYpa*oi8*@9QkpAUEi0HWc~F+ z=%^{AX>7SSwDi*(*+W|G7Njr{;k!vEo-4v&?~;?#lFy}Qo7_FQzrTXrq>t{MXOj2t zw)hBEhDgh0SXA6F?J79<&|QGAti2+x+NN()wlQ zPKsUf#vaz$Rl4{ZYeaE67Q3!o=+%66Wp-(x`sG_)e+tWi00b*^j=9>RC_V+)Cqn)F zJY$MM8jxUUAXGSPDlhiy#41}{$zMC-+s)X@eG)@n$)O-`sQ&stX>K8znXd(HB@yy9HF=g02^D__;^M!Go2y{*$Nh{>X~u(@SS*kQ4lQA$f0VxL7UnM&P%5yV`I= z=s{T#(!~n93+f8cnTO>|?_bOyUfuK8Q{O=%z4EkLw{gi5U^C(fgDCp1 zE`^ES53TXTN4;Uxn(>TPiGk(&R9=~3$&AiiwhvaXm6n;xw(n^6t;bWXLrYMS+ZSK8#rv7qtD zP`w!8p5?d{H5%85VFo#8%&_8<2z8f%5-s9nNgj1AJq176zd--{j&6s3DEQp7S+_Bm zl>c*9i;h0MWkSG{M7?J!EBTrno(tWPU;-FFRgd^HW1uGpc_ww=cR#y(U^Ka#(dZ9@*RqzU?jF4)yP5d9vu}Fs?N!3M8C42tX<748A~eRpg+B0e`+thsK&R}yVqb|;wnbVugPaMYYd$_>Sx%0^L>@^M9W!$j*uJ;LLfktcE_*|~XMw!F?!RG; z;HeC<{J3wH%i)zk)nJoOXP9Ck*N8tLY|yQL(~vzK`;2vbjdjrMM7?bnc4`$Rv6lXH z^$)*mw)T-hD(J?V4un01FuU_cg#=yO$!+p)o;9`3_XH%8Q#eu?I&qGI6vm*HxJAPa zI|J{q&WD#ZV>-jt^N!f9;p3&NoL-If#Q9zQ-d@q(2im9XZBlLFcXWCCTPS@l$)h{* zMOEznu7f7x9n!gzUOgX^Rj>FXjfLob!JG20e$dMK6Fe81{PbK|7q!FvCtTbNvPOpn zj8}X82axem3`#Q*%APsqjcT*}L5xmE4YPf597@`=H*Eb+AlEoO)-@n6X| zx?TN6?n_4VeAFu3Vj-f>W@%O@32cC&NonPeht$RAmsK{epZo%W=?_;OG=@;_24PeB zb9Y&Z+ZYuTJbR27?obn!^4Bp%wbttkBNGtv;2o*nCPO(HHWy}FqZnA%C=b3Joh#~M zPa7L`zPJ@sokV#dG^;)#veLSCAvVe4lYs^ma^>Ilm|Y97v7cdA9G76;;fM9(;~h=+ zI>|iOM_6Jwy%edy;f<+)n3-avyxrN5g|^B)~_)f;ri>x{o= zfcX%Wywg95f9DCsHLD`Ljcs+VBG|Twlij`ImHYjCRbfQe0k8NP2f-0&HVr!L91+#V zB1SA{^=ds(kqvx_01jCar)~{S$ql=ld?Ztvh3pf02e1Zx(02%q$L}H7WBA5Cm@vXL z!nf*v`xoP(seLH#)MrF~kAT2nW%&JTKp4Y8m0aqX+lU4c`hK4C!VQP|<7(u8j=r-({`>2A!4a8r z%`MB_4#KTq_;~m`kuz4TLkjR7HY9EcI+7Kdbo)8X^1{Fo&eroT@*HuSGs}d_;~ywe8J#e zcKc7)Zz_27sbiuq^t5=11L?)_MF_Qh+o>7Nj8SUJ=kw1KvaU$)o$Bc2rTZHlLj6O1 z{G}R4chjAgZA&a6e)+4XY4K z?c{G4W7^Ui3`5J_soWlUb*$qbnn~J*BUHNatdvoh=915EeDlp5)OdLLLTBBYF@%o> z?!6HCx}W1Yi-Ayzg3WGkgjW`TsR;wVcivM}0`psR^iE9W$rU2%ZKDu}%A zz(c;|2Gzw>`;gV$*!2VY6%HWI$ko;s!kd^qo@PMHU8`fm|Hw*T9kx`(mQjwf{t?D4 zNoPO<{N3#wxzZh9RrFQ)0;kmf0QMg9k}}6<6IPIit8j0|_R-=)kJG*4nfuC3ijlhI z`COu5=egsQD#yTjJ!#5j9fb06rWWG)!|K?WCjSrRCb2laxZYmo(F zSyv9o>eJ2$xa{(Au6oqOyC~w@FRDk`>Mn2Z-r}A*vz@4u|LTW^tam#Xd?Zz&3yUGq zPlY~VV58on--`b0y!`3)`KJRv+B;M{I`>^#IkaAif&U9;E zS&(7BJq0O;p4D0s!|MlFH<&|lGOsT~L!gTgV5c52B5e6hp7m%SdMCJ^CR|mneR1Z}%UdUK{QhEt&DB zs7NdYf%AeD(>gTeAqwJS1$}zLF?-N~b(FLH@9&V|i2T9iQ8KdjWKE#~1Vweo*Fl-_#G?d(5@365E3 zh?{#q;vA>0^*KyO)vyykTYTmZlZ@93>_iltcxD{=R2{gvQ?Z)@1qKcWjur6itzJgwiZ6Sx^P?G*-04sq2^S>TSR@ z4gR4QN;4B7`f@Cc<^0N!&2w@j%(}q5 zh1S|rQGVPe^rzBt1A2fxH2nDxY}U{+Mp)+5#mmJmT{3U?tpihjAak_ql!G2~_1(Hh z3~mUwxcLX!`)c73`>6J#C3s)Dml{KQ*U0tJhT_IQ=P@Y+=f`+KYyNE(hU^nPvm5UekQZ*IKtE6QOK@SDv*~dM2ochHw;(RDCjQVy5XX0do6x z9Gxs2M}+?*UWi|eS*?!utgz%1^J|OlV(ZRaEwU~5zO-q8JG$flk5~Xxe2PS=v(aQ6 zsTuPvb(d~pSckY*+&iZWLaFWYyxhccklt<|ADkDMD$bSf68fgH4B3A1GE)9Sk88}n zD8X!DGes~xmr8_eZHPr9OfAuLj#5WB!N`CcI!?cSeWWI5f*7vm;tvyfar*}17N~p< zn+6oO-)eQJksQkm0k8r+qS0-T`e{Pes%R$CK;`83Pi~yAQ8>E{5&J&a1)SPbg+dL8 z^aq9Vn%%q`h6N~{<%+L{3FG#~vTX|tcLj3&yx83x-wBBaa&GX(Ypm_XF#TirTq~;+ zG9R1$bmvdlm1lZBVtKr{n&lXG&E`x&TEWKR>a_$Gt~oG}^IC4zaFSF#dF^pR)9Ao= zesR8=ZED^E;18E<+_KoI2+|^~ddMabtAg{KPfYTKn(5Jl^_I0K4oHi|ZoV znG=UgK#Sl>n=xI`NHzbNu*S-Noncng$Fr8s*2v$x^1RjFEj1aiK*r#e}h7YeTU*M*Iu7wyzVvOS>m@J|GxO< z=B@U|p8l5=HWv8LHbbvn|NUhhGbgag90nY$2)Q{}z1>3JL#^+JDz~Yx%UJuCc=W0S zXYia3tTovmwHuy6Y}zORUJ?Z}FC>2I8cUgygwhJnts4+EtoMyzLef(&KOAq(PAA-X zUP4&pQ%c9AbKm6;slN%%kxVug@y=Ytou0H4eYpps<*Y`dO#sRvi92IKNQxQ!9PV*@ zAMEms#!+pjTf=2i6326_j!}wb(^Jqa?i!2cL3dki^6%rk+SU~(h%5$irBk|ahE=zr zk)}Hto)Zn|+N!Cq^lg~sa6vCYV-r(C)bguKdZ=OSrzAeL;v)iw?lt9?uc{SAKZ?t} zu)yztOlRW>+Tvq{97i?8-Q5*#z%sLoksggg>W|xqQ%ZeK9LzY%0-JPqItZX404-T+ z=wBI7vgqiF*vG2R`<=ZT42@^&~&F_|c(x}xbzxn*)r&nV*J>RYma-FZW zTDJExxk)Y!fH8hJA;!03w#5_26%U1L<`^O zt=j)O`zzqfPD1xg1WoAxbsflMDTVIl9GkIzGi$+qnPXaD4J*{?q&D8Ozn5}eDW4i* z*`FUGw5)F@!4IlrdeUDyw+ZGRfUj9E`U8wgp4>WQ>7Kjko>*e0QY(cX&xH`u0P}MA zH4;0lB$C4=u^quM57)_RCu&FLc)mHk^Ic@Bz@y0~K8^9g%^@ZKPFEH9;Q&&IYm-q> zEHrxW#MdDD!Xg~GRGg-1MKYh2I%Qxs%)#V_|ce7c~uy%e# zd4fly4;9P4X+|Katj+i@o19a={TXfgyR5Cge%(L^PEFAQ+H;QGQBp4d^OmoS_;k-f zQ!}hZ{T&R*+^cpbE*R^uwWD|rTxbf?-HKP?t)W~*-?kYZ@era3fem~nqXJDu{;zag zw79Rfy}49+pQz`x^7H#=@@ZiQ4_FbXzcVS$$hfU7 zZwT`BW&?vCpX}Nxm9B&(Zg~6dhb|Py>QkRkYXafdLU4|+0OaR$3(^t$thx!PMTDJ_CRiE2p;K=)~WhNLq}B_onCZioZl=p%S1{kW>Vukzn>KD^uw*l`@nF}R=4%kYyyXbcNn zh*Q%!Eu%<_euj9v$LF)M@$ZmJJ^M+e08PCj#c4MQjNqer3)ehP-$J-AnOq?@+V1pP z?n6~Ch3*x{+}0n`Qeu>*iNBsloOIi&%$YwY`gwTAzBvAlUWrwd)z|1AJnj-UD4Awt z9EDl@n*kt{R<*jM!az0(_Q%OhxFH`bF@ImSKQ<}D(OV=n@Bd)Wy|Eu!Rx-MTT2OKM zEaK)+)2k13YO=Wr=MmXFD3#CvWwmH0v_r6}b#bEZE#ivxLnq#^lwrq_4;45E(?rn^ zN&(kHUkFHw0!iBMS2A`nOg7uGyUsA({^~1D_%(}9@E|eq*Os`=xo}aMi}uYkvE1u= z^eZup=@TZr0G7{CzOQ9p#`ixp`vx zFdQjlXhiNvJok3{plqG)r0^%TsN4l9@8R40sm8Ap0)J%f%}WPJ;V$- zRQ!>aw_HR?ikTE!1Myo^X#jLI7meB!GqQC%q-y{FE6a$z+-I`D?8&zI_pNPD8DH+` zN#30+xXX@AqTznUiE0Qm){L(SNh4IjWznM}baWt{+Gvg@u3r{!{;MS25c;eOf9oMb zXd)G){LGzt)LFU#Y>Eqd7GF?Cq@jXKB^xLP*SBJn)zS%8G3AlWkVpKXH>^n=3@5o7 zKE>8$lhbtQU#Xs{NJ^7t!p}m`x-z+ZB9254+fPSl4}gptz*JYN-`PGNJxmD$jpAB% z^<8Ip3<4?|s~;^9uDCuKe1gDAW(>n4k;a=ND7(>&cGI8W zv7dmf5}MtYpkF&V;-Z*H)q9-Bhot`8n|BgN8aJo=5wfXGoI*is4q10hC56mx$>IMv zB_RJ1|`);^+h0O&_sYVVR+OFSa@fsredlccqqt6s~aV` zIR;3*A&v)ma4m;?%^ti4fA1pdh&-4%1~BX{<|vu=eO@{8vY-g5%oxcpR&2I0v74 z`SrS~%Z@p&$ElSj6cv^fux)r---AFaAegQ8$ z6q79DSF6C&*v>`~KcG7KDca-E_HOp*j;Un?Ox~VPceUvpZ>=6sVP}E0cc?KY z0?Rjc2!h6nZ-eVnv;6;kh)*gXRydd=)|Xuo|MA%69A7q|phwxWG{1!0xFK#B!=cKqC=V%Dd9L6>i)iUElBk5#-CLAU zl9cszST_^aPky2uXi&nh$KH=oC}1#mLk(~3^{i#n)`d@tJ@46g+x>kZSNRCICRt(= zhU+Pr(z!c!Xmw}iy`sZ9K+3@xbH5X0i)HBWMIj@}e;S*Ci z&M4iaq>I;#6L-CK@LMGBstPR%mqZV2mvZ?ZXYgL(oj#A&@+r)G4%P4U)OJ-*Ky;S6 zXmR>LZU8br_cID;ZV}oI&a#(!rG%VNA%UmRF2&j<4X8?dW_o-YtP!f>n}t*tEJHK% zIvx2RUT>QU2p$l0`bJP)tSVRUFUi-b(Zjq1opt)_M+hZ(Dpf_n>Gp=Mt5Rv{Sa1>J zNnb!l4qxInWU(Z#{%EXl%8f_o=Y$s{E@pU|;!o*jm8dT+;Kc;%iAuQ9F?_wP!`O$e zhQGIW@*9S?(Cl77ddhyg(o}*cSJkLx-uwGK=NDZPJhNm1XMD^7k5#b^%RNUvZ4O3f zoi*4llevQZQdby<-t}`>SL3>VU2>n-?Cj#tXLXi(<)m;p=vuJTk?KEiB0icgPW0Iu zr!Z}`m}SBv1w{Fq2^`L|uHRFoseY-}Vha&%>%!xdHUD`(WR^)&EH#ES z(%PKl9fv)eT5}LwfKb)5*do;zH_X5vGN{2E0BPi7V4rqQkdD7? z?7r`P$4BMwHpZJ;Ke!Gh1NnRH!81BBq>x5GzPFtZsFHs!?{6;T6sgG-5HcX)izTS| zIMy>mi|TN~@%zj}EJ)bTgvk`3SonICk z)ktIkLJw9;%uH1rKXLunRLy%0;WY(DR#rA!%~>zyBDliyST9HThJjw&?*8%O+cd4W z_TeX=$ls17UNJA3H=U&1XSVzID0p-VBhuV8?Djjg}QXz4(a4Rw7brJsos`V_IHEKZ>uVJ|qU_N)raopBAfTYoeaKd0Ilvy%|JO1G)x=(kc~k z>2QL#oHSh3PXl`e{7#Nu2#vLm2LnD}_4S!Jg5;RI9FkkrreSd3$ok?3OOPzJiFgp zx7DGIU>}E+GKHKXCv^!(k8$ zfq|)hoAr7hcw=dVX7TYU%*gu8`RRP{KA=I~3ZPPI`IQf!NNlDrN)y)+@v5 z@)|~-2eZ1lS)Qxq4)cxS@^0JrWxhS*et7-BnWHbgUi{o{=MZ?7UA@%YJbtKkSP@7v z%IPvjeG(uENKMtcA%`;{UY?Zo%|;DClfj-jGMe`*nGHoH2LxbmkBSm{4yp(x~fgIXR-+I6h(m)b9LS8h;ARqBiQHExh{5Me)fuEhUfLiLJ3J z!+WTWv~78V;0d|jJ+^+{ ziZ>U?7a$|wfDUTemIT`@NpifpLT_%}T5_v)(9z5Kcu_N6rx^GEW^=n__h=t#u`v!> z$LojA^$lDVx`~(=@tYT`d-i-7P{Ok6k1xGPPZJio5ntLd`)aAm{z1U2(pyMb004>F zYh-p$44@tK+v)+TQSj?Lz9+3VaqYYW#)%X|suI^VC19#}ug^SH2)Wx$o#S>g@%O)mHRPHF02ei8Lb1>;VMSf zzIXS&frQ|-_J?(}gb_ILDk*+A(^Xi1THZ&TXT1Wd5h?Tms5IK^XGG`~ZvyKg)J>nR z44o65r2s)6R3}A{Xhga<&@X9=2moL`*H(usVt)Sr`@6WfI6FH#I5=o(YMPjsSX^BE_3PL8_;`4D_|47D z>F&vgrHj}7Z$7UL+>A^d9v-fFcnAs#uCA`$T$R3i_bxd;SwvJsR!&wzLgI-s#5mxo zvVpRyx@KT!uvLup$cV3@g@uWoo72mPti}zeUxxE`!@;78NUv2TNaaz&S8 zmXnsgN$9&0Z3kF1vf+K_Oh8Rt%0uj za+1iT0+0g$*XOE`$8g`d?diuZq5J>{jNX_<&vf-VVh8(XS$N_ySa$Ly>|ef%&H|O z%9I)?o;)-;;7g`>0n`p%{F;_k4ijy(thth&%ioG;mdJ4|>DIX;JV}Faw_IL`T zzlRNGaq43b+nH-|daH$VopEz>pKim#tB}xBB^>cRD~;y)vAi5ZDJ|Agn7PaZjO#sB zDausd`H(H2EzeW#6*h+1a$-{*piUypp}2|Q(S){W{_CKE9NAmS^*f8LNOjoXt1I%1 zYhU0cYQK04)5JWl4!jEz`HZ>>#pQB%5HFCdf%?X{Hpz&o37$GQU?b)n0L#41(1lge z4zj};wOe!CZ>#i}c__n@2T*C0B31d;geUPRW;j}_r5g)Vc`4q)!o?{PJ1A*QUC8Z# z2$#&Y!7n6$rcB<}TIiv2CKy1IsG~D4MV>F(MiH7|PB4ae48%AOO-ZO7d|IFbsYDCq zNTxtn=iXuja9bJb+#1}+<)EZ+B}z0U;ruu|=MooFWq7}sqv-t;rIM&keoB#=e90#Y z10LWc?NL21U8=C(218%dF6B;+y$OQIWn*ZBY=_?oJnPH4UR-*hIEzm4z__OeTmn98 zN7<7V(n0&Q6SbX9&ri%L|7rM^rmi>b#&`fsgHa$zmhy3U-bY1YfSPM;u`r;jto!Z1 zBu*zkNLv?tn;13cGZVISj0c<09(yB+{yqQOy&d%WpGL(YGh}rSYJBC(!ZJOiC9vK+t|1j{gi*+I;I&r#DFa9+VL!h|EhmRwUWc ze}&FP_HU0{b9U@k`nWcI(PSyIk+noqRCLW;e{IA-Tl-c2TtiWVL2;nW-5&MG1vTjU zqm=(v)osW3y5_xJ^nMQFxS;%{ z48s1+AARn0D{}h@pC2h`NIG4?dGo)erYjCS;j^Rwkxh{xj|HoONE#~sL)5O;s%f&> zuaozv#n5`^9MiScisczS%YQ)fLP(Vt++43G^Q zv%0QZnMXmVyA};EnC{~2`$4H6&==ot-?@$1<*g6Zn)Ntq-~^-&JyPnQzbdRe%-+XS8}Vwz*>=qW?Y z%8~9lK3SLwhjy-@aKGP=|6RF&zM}b6(X?6<<)6MTVz=r?CK5Nt^;h7)Pn1Lja&GdF z+wZ`EOC2{aX`27t(6P6pBWv); zJ)?;Sxhd%WZ=ml}TPrYdzNTT|Y`*-ZpKuFOon7pNp$ru(%|`{hV0JKtEcUznOSn7w zm8s%R1jM(q85`Y|ZLHIIt?{_}W5cksw6a#I2kCA=r<`)|FO zt%^BmaY#usH&XkhufHl-{<5PUdmbgt*YWe)lq#Bc%i;QDT2qt})0fMT)=C^wY}y66cpMxYU&$ z`Y(HUIh1LmS}9@7|6(^Sk#!dWUz*EWy7{*cb~G{@G|2uH@|T8?7?!BN?6`~g#iC&U zlEW@X2Mdk-$MGgGGZqI@n4I?xbwdc#JtSBK8x)o7%7Skj`$hS1;RgE@%Za(VV$pI* zO$v34=R8|$GnC5nwDHoM%qxQjX{-kb#)V&qLm}B8<52SuvMC(EqXGsdq>G#~+9o5i zw4iSW)8g$?(wq#ESBrI1S{c%i{2Dtr>=-&Ph8(SepilP6QjUoLhM!fuqfuLBWL|Os z5D_9=Kv_xsBFiQ(5)f<@lN@>O1ed^Kn9HB09?Kv zc;sMYxNsmL6ac2%qMGftjF*QXz<|Gnh3f6UOd*j#7$Eqz=uEsV<*~^?NC4or2nPKv z@3252Sb)EU+TZg2Uwr?7grKp=L`o}r^ipJme%BXm)!PYIy*kQZDK&z`tW=#AZ>KjE ziQou$}U1x-xwH#YV`Cf(}&H2!>l)@mU>NaEbGJGcM5&v#T4*Rj3 zTf*sj+i)P~d)sMtI0ha=icH-pMorc>&8XvY2?oRF=P`$woN3Q&zSC_cTubmhdi*ld z)LE|5BHg5x7nR+uE3&5^5gJx04Ww0kb;D{FihaNJX)o!Pqy+h@4fl zF!C+xzq%?VlQrbzn9781(fg zCQ?tG8$qe>A#YyZe{i>4=-^RY5&0@)q`z+H$T}Ng=O>&E=5UbBG0oxFQkNcjzX6ee z9UW{RN*mezFnXxLF^I^BvrAhakR%^Fd@c#oLz?A3jdsgZ1TX(AA1zY)+|5QxAplvq=omMD`YfztH;Q&QfR3+cXN{jGHW?+S zb=YQ*Lt2}i{?pGRu_zhL32TZEmk82iw>xq1d-B=aHgSDKHKT(S1cjm>R0#B0_RHWs zyrFr1xNdEeI~6EsOeE^N?fdLerOup@2D>Acx^2SRjAa6z_vQ-(u<58FsX>!W%RYBm z^4`ow4o*ZJMcO*`L>`y(>wZTXp3^lRbvY6LvyMpJl;b&)Nk@&;{T~zBCH~bsqoBVU zW359O6m+2IINu(<#TC|g`WFd_qnl3z=&-0OO92*gUu1Z-m%ROZ2xofB7^;a&i5Wwz zKN;Z<)n%qj0Bo;pSyiJIQSQUyda6}d{4)LJ-AS&^QQ~R0cAAUJ#>~`{aKhv!zZPgR zkB)?9)zGLIn-mn(wQ8eJM{xMdbAk#j+w=S^91>+l4HmrnqR{qHU7HOMBFDhe-k0)s z1Dxk$w+VX%lKfmygb=sy2c46|0dI80#(LuUYH^-vu zXAB)MI)6~wOFc5tP%2jvtl4ynxixD1N00WiaXD1$6;pge{|0n^GzU(;L|@%IKVlvF zTV8iBD6bI0uuqvT+4goXs_N`{!kMycCFO~v_rJ_jR&ru@?^cugVWNX9fV}$t8M0b) z7^R9~uV8Wh_sxvdd&>UD{P-Q8-6}_U+3sS~k;kj>3y(+4ZoRs(anRsqm`$%`Ygq9S zI^J7+d=miM68>rzFxJ-;rtrC>0-F=@M2i>J#ZXI;GW!e7vjr-3I-reG>sn%;9j8J- z-O}C`PSVK$(DqFE=CV)h6YU;ctr5g7$p{N8WpmHnN2%P$Gsu0Dyx%2Pq( z5RTi|`OSAtiZB>M=@m4cDOI3ogtTJV_jo)#+xL?RLM)BGFWryBPHf$Hf5O=|pRrG{ zJkePy7ud?EGgnKGf?Oqe`bUBWr8l?&6Hu;?V4>F01U#nksKN*Hh+ix)5(^`q=84*_ zbcD$_!x-^5S#wBIENp4WBS4@FW|A&%P~1W9$U9Q3gEIz@b3+1IX+e%sk;|i@Lf?8gdbN z3}cYd`t!x{&!ys4K8Li~LJ~|YD#?jIJvqyNaklMCHG+XB%)j>@o8c72AAE8kq^(9< zw>xZWV!V=&<8yN`EYX!yVB!Y&>zWnNrl&-~hxj3O7``1ncMJ>6T)B5%ZJs$N1%7X= z4hQ4?kF363*umC2S#{2TjNtL$sU(?Gj;it5Bz%F_YcgLlvJ@vku!@7-!W!!7zC|q;DuDlFbQEK;7Y%U{cb- z7Lw>@9O!_eS6elX;66@rx*5${e4H?9kZO&UtC=P;kiKg^PWTK;K_7V<>K1fpW9@Sk`tMP=rOPIw8C~YYCs* zO@e*4RvDwW_!Bgl$`jz<*qj3X)xf^xt_6SX>3`szWA{tNczalmZL{CZng`~}#|7J5 zkYJ!Q0Xb}NC6-4)WK?>H#f}S3gPd++neFK1F%kb~-=anKexoFXgJXr1&BfDxJ8|+t zdi$pCs3A!1=Ry^DRG4SvK5cMLLpU&tOqC+<(d_eWRg4?cmm-=rHBPRHj#t?>cjOL^ zCNBeDz8u++?yNn)V-iIe-*J>8S;1KOSaMqOdi%LU4f!Y^j@ z;v(uvn~X$QH~ybziHSf(q|S34mTtT?t>lVwk=J*fX4)AqB}Psm{`V1*a{1MKBu?vB zVmasP=rOIMt+D7F#NpE~9Qa`xNXeV~x(O(}7vtoPOgzEloE81?tfw5e+Su?@rvRA2 zo~He}A&QIHZ1J4#Bowld;ZiQ1uL1`u5J$!*U&lRG!&^{A*ZzJ8zl~5cDAK~mHIL7S zeG`Bh$Ciiw&CxSuG0ThUH+SqL} zvLD%(VvmvEX2cui6Hsh8_N2_5eCB^HpnGgkgY6oQzZR(?+!c}T$td#PbL1t0MB*6bTds%LV(=gyBbR@wPnzQdJ# z{ViA(k`hbAuS7v?ZHyI#^6L&)|1Hb(=h^0qq2Sa4JW`=N8(5nBOrg43TcXITx%KU? zB;_CwU{+Bg;PJx)V+xoS0@W5Y85!l1&>QKXY8x}ZO#w5vTUTMHH#?=C;qOryxUuxm zsFVCgEnzXI9#~x*X$<|!pQDQ16dBd=J(`U2CZH&?RYBaX^I%vQS$a%c&=e`TvapX- zrXS{aCCOpsi9b-!i0}ItO#zFGH~+OPgyc%IWKyE==1dpPzRv#5=c(8yl*zJW)5+@M zlzyizLu7=DpAjY=U%}!aaj}LJ<}|jTh3P37EV1Cv7u?BqGvQ5 zeE6&f>vw*H^XS2c_Vh@H%%7zTGe^smx7s$AIgz{CUS7et(>p@Gt_mxB)52wr7BR(j z<*$so*vpP+Hd_h)(B+r4H$+1p%>}$EJ@&HO4a8PNzm6Qd*dv44#%n#5W%iV0J+!Bv zg+plGqS_1~i#>CMpNnn1K4oc~C6C=-3wQ!X=Fq?r%*ed(9EF&2Gp5KqL|1iXIo=)J z&yVzXfGGMaqNS&8*z%143&9Q2ikXOp$gvMfe9 z-mq*AkWp?>!aNK!vCh!tvG3|Qa}OoDvb63gqU%_>CitRJlN%ns7t-0DZX#uBx5A2r zSaSOkG!&C(F~C7&C!x}&#!=|5sdC=iZrP)e0kq1ZlrV2ru02Xv(5L^~fWTTGUYW@W z3+ijo5`hQZD(Qzj=W=J-460Va7b}|N27O1fH&vaUfaNY6nyWu=zgk&zei!;Jo$NSw zco={%=Gi<+Mr9FQ^XeOIk1tu+P?Jkv-{+kvKi@uRs!_m>6@XesoDc)DM0^ErtTF^- zp@VD$08yHS@n+_f9^z2etoe_#XblUc;#8V zVc%(Dp-P*+T#xL{WQw)tS{GJY{cZP48^H8-?`OU%mC}YTzrUioB;rjkW?h8k0J-gI zC3M5q{Zi~{Pv6y0@ByjdzQNPP84RMwXh8VWuq|FdjY(W(62=0rCrI1qb61t*ZvT##I+tvA`2RcZT5iH+!5Le>V5b7Z`dBc!M zt#P8tP+n}C(B$f+pl3s40UsNewxxB4i!s~aYPr(v3DTL1YS8lhBuGE$VNggJyx6{k z__vCMRynFVesI%L6ck5qH$mZOqQbev&(QSE)onnU1ms{&Q(P+n3oCA^gm6w%#b1Tr z0We%WLu|UxQ64EF|ADT9j8bG!LqB!xI8i~$UVU3m1+NfToABufJ!>ik(E(~qOAM=A zu^*~Xm>6(KXO{_=aYq0}s%wU>$+*4y>QpaWK7M`;urPY2X7MaI24WP!ao}3G!OdkZ zU^S+X^!_d|hTRGRsE8=KJDsP8@6-wo-{+$61~$~!YSvBx0z{Cezwdjzfmycd;zlNnQn>L~sTf~J$b|DkoloJ%L}7fL1(s2N&9O) z*g9LOA-V?gYHoi^8F(VIe6zirg8GbSEp3GY3kPd6^5>}}e-N0ET2JhmY=PFbJ{J6j zRn#(|_d}l_*PIE!L=+aB2AtBxG6W4q%6^x)RI~4k0`6;wSoDWL9{b#lr+@aA^#k>@ z=fAKz@okku?i(0nQXd+3#j)X2)5+L@VQkPX>zL4#EuZ=eV?1{)>{!3vsg1LE06@VM zl~J1tyGL<%hGdPw?isFfg};oh$A0?+xo8-FH8Jyyi)KeL7Sr`hV9Hs10DGo~o^R}s z3OtVCd|H2whgjY^^GGFuS*OGN!P z3_5pJgUj&7yBm>_fCg1|ZN*w1)mYd(u}lCf@4|dVG0}@P9h9-^w-(KII|LfkF)woII(OFvy+kl_a*Y(P%NA%h$3{G zg~V`14Nk_vX2A^$`=b4P*w>yv39Q{pKU4C$SFKVfJLmmb3=CA4n5Hh6>8(|lwacmQ z*>fxjr|)^wXDJ%ZF&s!>Ncr^sr2a#K)yy+j75F!tA6aWCbEfn$YmZ9&vBSZM;}vkR zqh{mKp!&xhNAN*>4&AXPl4*8~&-Cm4>BYD0>KQj`XjM$2@p=SXPGW3JMvZ+QTmI7o zD(xAT0~WHoOIk<1-bq(M-H) zcjiTO#Dg^?c8E*M7WY7d-cI4GF}j(vAY3YN{{`poWbwXG|T|68%vPmQ9T+(CQ zYC>-LUrjay$he_+JNvIyzPB^ZT->iq19S5TJ4TGSEqP5`njG-}36C3R-(fE;NW)W7(y0sFl6HP%ShC>lA21dk*T1?Op>7WYBy$BD+iQD2??< z+l=5P!abpaBJ25%8IqJ18coA9lf1>Uddy-%BNhxJ#xp69v_nJ{P#Y}dswR($De1R- zJ5Zj5$dDaLTTm9ANITbdno?ZTkq;?IM36fUC!3ASs#l4y@;h#Q3uanLcN&F%_cJrf zU5vzOgLf%pqJqTd5n*o(RV%V{);6@;qE|z| zk6DepGD9Bf_N(3;2=9D;>RPlZ0}yIAppx&$!o<8q^nFu*dEK!k6{t^i^C=hz3J<&N z$LuFzBeBb6c_V@1V}!3+jCY<A2a~jXn;pctDg8M0;LVscA-lCx40);|4YkArSGN)M?Rz*d_bgO0 ztI2o`f|xkB#uyDnI`IQ&jfWvnU%X-Bspn4GK6I35+lU;6xLL^Gh@Oo-vEA3QIG?Fs8pCQi$XN?(gf2TO^N zcx)}jyr>a;8q7*$i>*8mIh)T#;>5A>Hky)tDf_|cp3H}NGOT$gQ0YU}Fpfi#;u1q! zj&dMwTGl>C;T)Pi-Hxfd`!HrXNN_I zIabRm`6i+H!CyL?TQ%99y6Fgn-QP*<_A33iOtpuhwl(DoU!R;DJ9!ZYmgVq0*N$M2 zViT0Y2v<5ONL+)XptqX~CVw~-{(=t{1q{X<8ZwDE!OyDoh#U!+^uIsXq}XuliKn77 zZawQnKSglO)F9R6NlO9(X`F;*W@Bo%UXD-yjEuM?BTr?hU6U%`W()R54XF2Q=!Izh zQRo7WFHOE*&t((apfCj$c_BxsV=@*$oN&c?RKuyK$$zX%LygV0o%GqPL5QT~d4PIrzh`nr z_Mad(?Q7wokoyKgKQ>HMk%G95N1(f0ll;sS5rQJh6jr)V>BkV=NcFA!L6+KyM1|Q= zsHnxP z&1O}xS|2waf|y^bamtwKAz~CTRKlsUTAgSVEh8cnd=P6bQrRpwd^gbwhi-T#i*hTg zZfosoWEa<65xMkyz`{0(MPAi%a*}s*I6y3vr3gO>f@qVg_!*PR z_C?iX84%(bCt=3Z6(2C+z1*2AtyG6c|Xq2GBWzW4?9^XxinOvtQ7w5CrEXdnY3?|Wxn%m zmkeWhuaWia+E|-;1$=thnj{RWja+OCFzbehVGqJM0p;0baT)!LyI~h?xu;^KXD1D5 z;6;90eJn6gWaVk2M|Zx}R!GupR%!QSTdi>Rn2ah^ibuLS0o*$Yw3#OYepO8hI9mSU zm5g#7aE*pA933P;+7$w8QczV!ue_NN#(v@)&}xQDB0b%0Hm(u83dcMLlcC^skFX(h zOh`qKXu{kP zDFwpsR2gP%U-D+^VrB({)FPGve-&_Cry+4!XWEq^?xAxkBWEh+|F-S0IKzyR7@ zrXA%5o~+ZWqU{2LIADy2{bFWx2wG!%KMvIn%#pE4j)S~go|~`i*95SEhauILRu19U z@`qni`WqxEh<8UbX=p4$aOEl**fA}tvhBD)&e)L?h0!TTFWOA`d7Yg1< zVwoH4^tjCQK(Z)n-L>F@;V|+`%GbpDZG&7I$xv>cdZoG|Sc+y>{*M53z)cb=H;VL^A<~uA>x7F57j4I z1)V>S%}?9WsS&p#_xF89e6t_Qw?W~6)5!5kAY}$tSSEx<6d(#rnZd@vqi%%8P(VvM zm|)>MEbT85wbnfToXQ{+@+;@;nbii@C>Rj+y&)b2zn|XTOOnkLS09iOnct2*01 ztF96ixGMJurm5#d&d$QQ_y}fSuHwCNcL3qWlG$MvR@DG$IoWL+)=cPL^p7XUqgPAz z9NPMZ2}Anum-xxO@i)l18eO2&wHYo-h*j?6GO`OUzH zk2_Y;a-WjsLMr4uRsn`SqAa#eS_wyVAa~q zG%4*gW8!imQo@`OFE$6}>bb?P4wgOIbfc#fv1^cxBJZI<)5|i#hvnv@l@E1tO|b4S_$R)98K7sqDm_`cy!2fp!7*{PLmh zc=BB_5dDjoO|;Xe@QfO#v_Gt#3ik=EJHuC;*zh{+R6WRWSF~gzF5Ug^#^%$C?)A^p zln4ulEis|6JlJoCY@(VKb*R$<{ht=s*DIk-c? zh30?ue9>h|`xXnr*UD%L@h&?Cb>F*l3MSe;aGrWlqB%lF2Okg?!s#!_XvgB;<=GUc^K+A8q@T|( z0|G8N!jCL!6e^A9o+)U(68yVi#aLFrwYQ}he_ac~@@0n6of8ydmgF+2sJOJ0+?gfO zS7+x?xFrXyGQW2)0YbS8v>{?=`Jhr;(`eHR7<%}3VdnkoJP<3FK`{SY(=*=<*~M*b zq_lx&dX`ziX$YhxidO5}51`G{TAC~GZiQELJA_U|!2Xd)2gRf^iP3gQShz;=u;C4p zVglH-PDp;^d~B6WM6~oHbLOhR)55NisxnNvrWX>XD0~oR+WpB=w2kyr)8>x8SY+r8GcHZpKcnFF+0 zLE;kdI8c^Hj-vxSFZ)svI5n}NWF5nUIg)WWBEqr0OX0616+3R!C7_c`byd=KID}3$ zgi%un(na7FbDavjVYU;2&Q6sB*@;2;NGkW?E=Nv9dm{DTI~J_4)_VDnlrD1LFrdvu zcW0pSJ!1PVUK;F35h=Z-h6!S!5MYt*69=vsMWoY+;G3_tgTync$q63Z88d%QYUpEE zccsG+f=M9Ja+!G5S_TEd*9_XU3kg^xEl{tAD#=Bi%q8YKpE+v>sl@1<$&YO$>V74@>e$wx8~ zRqL*U{Ky{Xw@#^=Y+V+f{$ht;U>cC~){ql8729mSTApW?`MUM8nGx&p?2CT_n6lXA z0pru?k4dkGo4=o73)p!C_$)4mNPHUJA}yId}IDRH?8 z%7Lp-j{U*E$6eT>D9BXi=0fWCiBjl{hPsNAw;@nt$K1-q+w;)~;E6zxI5%vBasQM% z5rsa~+!LkJPKfEH>W!ovE2=PD33pCyZ$)NM5vfMo9S!p7a?5b0wQ-HA)Xf_F&W8Kl z8`p|)Ese6g9~Bsp*O@9$3}73uA)-S(K{YcG=Jd#A+sXXK!Ly*+a5s;x_TEmx{>_gMYzzMW9)+d@> zA^TdQsj-`mBOT}~zo~jkOE+wo;C24qDR%8jJTyIaf%RbBgnuj>0vbi{GT9S-gNxdg z?h98v8ZnHHqLFcoer?~(hM6*Z)8VoyJC9(aqX)Q}$E%qzqM*2rzq=MjRdf^O^3|%V z3fhMETv?nkJUzbJRlqoo0W*cNamu*7Gqb{6hx}5@uv;J(bl1^=*4ARxdZ+Y+t6EI0ZD%i0DY?*;7hU3q4LCrPZN?<@AQ{oh| zhM2ra4g3!8?%v@<)v`eWHDNI36|6ni^m`@dAK~_yT`3E7q)$w5cH1;vn@=$B5$M0v zOm;pjbGYJ|Rat8;EbM~P2S)UpfAjalY;+sE7SX?flN2vP^X`t?9Q`ia_iB^kOGv4Y zOzDeCodp@E_60-tT4Eth z$50%Tx4T`_Klgo9f`m>n=d68>PAW@Q-7ELrzqrfrd*CAR)Q|UFu_~4FjQOlo&{BOq zI5rU2k$*nkcNY1>$>PPV8!sIa^XCEG$DkGVxMt_)IbB3)$5~z9z?0*vYox44 zJ7r}DCz&@>jf;Ocog#*2FAx9p|0uLRXd092wqyKmH~vwBWfL9A^-N=rQft`{GK-tr z7$9jODf35|STvgz$x9ErDDZy={SARrPfr76jmq$bXFqYsI=(yF2#%B#LJsEmZ*8(o zGmuffX%Gq4n%>0n5IsPQ(XItZG9gE!P$yT=_QUmAm%`qRNc_$@+D;C~lVFL=KcDP~ zJY*S2Ve1gI6&ug=wPztG8D;SQL&UijS~zEVbgwz`anEK#2SnB%~SoVICM z-qWAU2EynNkyaJ7SedC#Kge@MhR;0ZAq^C;!ob9Gtw@xnma6P^*sTPjo-8dq^PzT#t^}u{V;$QFB5|9Whs@AoY1a0haUctXD8CVo7O-ZE|E+8PLo77CKThWO;!g^ zO8flED%5DT1NgQ&^1rL+ST~d45SS#q?Jbw+s|`^bjQ#ny&e}NsHYq;ChOCrEx)dP& z)jQPQzepx2upatWtKTEA{vYNTVo)SJ2d=E8+TZ!MdZX|XqlhtfItTxcmJzXN6p3qZ z5EX2ES}vWk6f8-|>)3#KzxVIBL7=!hvVMR1W6P%cN|n|oQ}|rU0}pR)eCwM~mc&1V z=hm!~XL@DsZM!dZ#G%~Jv27+Jq5VThKGo3GM;SJ+^p5W;HV)I6OmCLW93eD{CPTGW z_8mBoyf6C?T@HhPY*Lp=dea4B9TZXbmQpYNJbNa*YNQqC^!`}^v8Ex;AHqX~hT3f) z+HIeGVkh&`hwPN%@szGu=`r{au{v;bKD5p>qIjh$DVX*qu^%{K=1Ns4V|jxB$yqCVY6-SX@e?6Bn~zH6ALsY z0P~{9RZiyEkrqJz9u*3xmwtN|3SP=GzQuop6+jzd@N!5Lfm$OIX}O3|U5Ok#VVVD` z>~pHp|@{rc{Rlp$1si=_pdj!c?#=VDKZ zUCMEQjXL2D$vQV_Q5#bHkYPkbGs#bI%rS>!(y2%lauSPLu9{yP(m(3an*Zv&90?^U zIA$yn1pt_^A@B$OeX9P@;Y=NS(HE=(?v?a_U~y8IdBdnjVwMR+o z@H7?`a7-P=S<=4jocK;x`0yBNcOXRMIB9 z$#EbOBSIchgSmVPzzjH62eF57lW8x8RD$HZG51a}cTi)M&__Qa?N~6MPLaYiAlb3E zf|!v1^dsU%;$wP-yGD|E`7kd(fGO4vI|iBWG8U6_R|?``D4tmKX=#W&Bw4+-7xf~~ zEG@(kZ?PXv4Z|^7Pr;uU9ywj@>H9jB_yB|HlSSlKTL|U?F+?}TKzDX9tJ1I{aItyH z!A7=E`sHYnz1fOzI>%AlnxEiElRXe7_o{l~X`ziJZNr)Ri=&%4x$W$c$_#C4#axKe zJY(Pw262J5Pz1Tu>o*B{pwsb?sNmihoU>VVF>?981h%*l-E+D zh5?b;=m%$o!lsqo%Of(_a-d5LOEb=&QN!EOS}+-+wc^$oRHA|D2b`+c_`Q_T8eO^b zM+Sxnv_$Bht(Edo;iEnWq=#@y(;d~l5$(is2H1tKm z(r7t#44`rgrEAUL34#`eYz^%`_cOH75p9EvjP)af_)-(P10B(?6y0dbuHPNe05&{t z^J)P^<0(e&?xt>?esWx(CLG4z;hnbkLavgjOR6E#_!YaovYgXVDs+Bv7#0qVyOUP486lC26|aeR zJ0(ET$wPjs?#dKe;cN?Y$X)+PbJb zS2=ib<-L^6x}k~b@$i53c#15QobJ*qHnx;)gY4|CKRb|Kcz$v&>MsSv_yTV&;I6zR z!)=1)ge5Iy`yhgra=z9(XRdo?tDK-d9HlmCfgJqy;^LHViR=15h}$BuW`&|vxy(VE zygTc+L`45L5pO`HAGn|-X=?gadQHyro~94E=!}t3?e*CmQ20T7qEMGjxxdw@9pG=& zSR?^OR&!9JGSlCXr&kSfE?*bFbiA5XDPBH>q~v>Y-Q#^WMc^Te!<0>YJ2xkz?8Q=j z?DboKDHWMyapK|}_=~T6OZ0c8oM*^;4NtoN8|wscip|&uqt#2>kc1ajw*PF$S zLk2M&&s$fJ{I@HL9>JUo6i#Zg4AdfA3=v!>ml0`x$u5ogKhNPW67_G*4Eb*}lYQ1r zQ%?3OAv|-2FsW@QI?#OBpXEf_mT#Bi|6;8csAo#Cw&yx!HLkcxB{O1NikE`w_9}93 zdE|qUEGaWnZ%v;2=kg6kgEq1+6?N%1Ria04n({FtMHyj5I75r`$GZF@zukWtDeQ)`G4X%XR zDF64u%V#$y2X255n*QI-<`pF4=6tum@S0_(`$-GMk8#5| zo@U{gfx1W7b4(RFfhE!5#C;rtlcY`=cu;b22?~9rI^O~tA*;PIbJ8SP`d0P1nWvsO zTcLu`yk!G{uz5S1aNf@-8R9hqJBDx&(Pw?ePxYa9qeS<=AE|}J6NjJqH8M22P|=KF z^-Nxh*=M?PzG@>*M;V`{K|+d6I$}4f10)gWs~nafhiG6hx{Ra<$toCX>4mqa{J`pS zBJl`egq|(w^M(}1HEdZ1yrVK*EEgpiP%!Ql0XJ+}Et0CKfRR1_O0Z|?;d@1qdZqkA zm&qvlvtZ(p{&~L(>l{1ebrnz#5UHZ8PaMTn^l#Y)O56^4k<=f6C+#YE#z^T+qfRLL z0t^71{8{FKsV$Ax0UI>#rM+|;Ulq?5*RD6Wotb~e^!!3)b*I@fJuN|s z4k37=o}7ZZs=l+?X$ z7Xd7XIFmQNSR;lj$w6?qVK*!;TSEGh3>&8%CRw4YV)Vg5U3h9JS`U5mclun(k&#DI$zp808T zwd+6Ph6u?F$YPd^=i2c|kZ6tDOTh<3XM!%qh>TJG)<sopV+U1GU}_yhw!vS{f;{GI|VlU3ROQ6XO1CuPA?X=;Os~v zNE9~`p#>BB#SK?C`2h8tRpI3zE^I4FVtr(h3VJHD-i(h!4K1{wiPQ{H#vy3pSRZu$ zR`AIXk)g?GYGM&au2O_)Ij#m@L$YgZGBt9;_TFo!yz;3ed-S0t=(}ZDl%SO%G8I?< z&3yqUt;23OJ~vAb$5oFioRd4?Oj3EVT__Lv8TZ>-f$9@H?#p*Sv9Al5A7n(G_7lE* z$pLdOh4hUB4L8#=Vnb6<_kkz)duC0$GSV8!DDtomfns~~n|*EFJNIFvg%foZ5RIa^ zN-TQ0eZZ8a*LnnRXnVY}F7-=yRfc5s<3K$|iUq&pr+ zz@2??GVC2#oRR^T8%EByiEYrX_1!B2lHJ{5Hmf^iu)ba7Obc&jK;ZCx!Il-kAYvU~ z-AO~wgl3XH133T{5YS}ec)G$A6p1zp{5o-pJr{yRdh3;VlKxumS`|S(!d`FVfhAlM z$8%#y3sr@ORR)RCjO(~&*aiSM3YZDB0E@hO89zEZv`Yvb3Oag)(Gqth;Y6p_uiqQqwRDF zm~sJn?y5-{e~7D7j=2H`#2NI;zJ{m&_>KRof4Cg>h4`gmIV2_(^&sm=c4;z7Z9(?F z>wC6M$al+=qv)j}-Rqvs-i4jEU2Sue7yvWul#peBZ0qIvzmO6F2fMH}F{v4+9@1+Z z9RSG=3>TbLOD6hatcML3P6og7YbpA1GquDor}dDwM}FYoWo4hvihJ%TB*S>`Er{3N zcCqC-X8gxXfQ|lawH3^B`0-NUbrt9Fnm7C1-wT{u^cxdj;c2g{ z+9^4#QlhFP#q#<@aqg|d4NFS+<=~5E5nFqT$oQm9I!_Rt?XhjCX)G|yA;ADWJeaor}Lb$eQ-71`WGcHBYBuT8*)=Dx&R`f-e zG$92wV2C*1AOu05$`7;KfHqkTk#iFSWI7zMCCst-rrq%(H|*i1aiqQLyWC=mdF)nN zN0c#GjE(Du{E#zZldl@sK%M}OrMgd4l-JwG@?6JFgOP$8#tPaT@mdOO_c<8UFxe2& zNy9uirw^(ihDcl<4T+VTy_5Tv{Z6l$hk&VEq__15!^T_4SHh+vdMk|QET1Bwr~=!m zCg6!I3oJdF-78*~1J>mx#mB@8k08*ioJmAsV=(}Zj<%yJ!pSF7@2QTZ5;Qd(Sz)rh zDj$sK>4XLTpxA@QY9IIWFk^}nrsc*rDzk9-(TrQm6~AhQZIk%kC^pH`iG$XdLf+Wp zMQ~O+1`L*oeV@F7_3iLl{I-=u*nvp~)jY8DCndhr4S%tqI~_ftABaCDC3>fk`*p&!rR-^P})A8BF!EVUaMt6l?G6%#ShvIMWCxO=-uHNF1ygtAB;o26P0A6cq;Lo;< z7D~c5SRq(` zb86XLhZC*uIK(#(=79~z0KGfB7N96$0r8AS@p4;eDEw#7is4oAyD;p9?xg;QL?Esg zSYL%M?(cg(x4M@j%>kV>4j9q+iuG+?nVy;t=305w&2{2=@@Bs2f?K+x=~M}dj=7%n zBeBRjs*{ts;}bXb|1tNMVNrhH|0oVfC@RVT(p^I1DL(JmLFyXQOu!p`7MP{+G?X-lnZqC$K@-5+a zt(P|D*NmbsCfEn~T!mmrx{$TLu{HN1`bOVk*1-o`#{%bO<01|jY(=*F7dpO%h%+=e z@!4Tbdx$>ZEgAlmAvtIYMgpt{P~>S^g-J>;+y90D3hzxh9Z z&P`Z0Fjh%`|0O@X^`kB9encnMh3b~Uoxb$a!Uy>)1hS|G zsx2KxmAfAH}skcW88A&WgGpP=}eZq9CdSykcQE!XmF6+ZMO`}So=7H zIf5ob$btc;62_`#pw#X{pEZ1}Fo|t#s!XC8XrKavM@YlHrhOuFzF?0WKLlrFt@~gD z5{UMqZ*i&qa#Ev0RHDqGK2m4wi~s6YlAyS{-FtvTN_<*wb96 zRcr4>~e((nCB=#a%Bznd@4@_72P1Y%jR8IbhVLu^YVkc zCr4wPp;I5#xl`ccunR>#xr^2RKRnGq<-z=s4yw^>VV*NvpRORgLWuEgiiZouEe_dp z=QlbR??dhJurCBMY56GWXmABktKu$X?i(_nq0zeTt8WC;^>r6q7?urO2u8!1OO9kR z1@uaulJoQGxGb_IJ}q7)-2z^E=2%g&87)yr>AbshgRt!up2bhOK&3TTc(k%jJJLUl`YB`uKPY zK~(AQlb6FWz|B-B?QG5V2@!YrL_kkFZ)eLL%5Bj`luGkhS!?mDlb{|sk-qO&5hFr% zFxdChH}J+&oG*H)5vd0&c*jGMGaN-1>zP|~cK5Dit+FB30F4M%u>e-*tG;wkwmW0| znyn`%ci42qi8VtR`s^fV_Mpv4zO%x$P}X) ziK6cyH{B~X+uzvy(^SBJx=J2{y&np98=>TEN?ji!x z&;+NNvRGTPR#e3LIAKhCw4t<-}yugJzg8 zaK98Sl z`hNPc81&0F_BTz=A&XEM6>RLH`K_*9V~dyqnzTA?ChJK05t8nY+x#-K-SOh#NAi!} z+tRD;ZKvnVoVzRxJgS9;De~HUB#^aD#mb^@g(jTgHd0P^t#(DcDa+L>h{xT#M_ic~ z4e=S?)%6P&h}o-B4|7jfIi4Btbx}msL0euzT6}Bk6FF$;R)wpI^SB53m8I&wy9?x( z5o2)K8SZ4JJ1AD@RH5YUX(>G?zU9Yp1B&_9l6MP~M+zSPzL;<*qqhGT*e<>`qUJI= zfU>SkT_=V0O?z->@EYoW`ivD-VR;I?%H9@PT8Mx`M_7@)ZjG#W%XpC1t%!vfltFHP zJ1^3qNf+Ji<#60=z+BdTbJTZ6wGaNS1>%xA_J_SK>sV199coGgyQ}dwV1w!N`wAel z`c`?7gI5pkZ{kByRl_V_`9-al@jDNNDa&In-2u_ZUDmS`sy8dbyh2j%Km~7%SlZqo zACx`*u=utBA@IV7|A%alJCL82%fx9(yP1-?DG!)gTD&tf$BH9;?ihcn6rYpgAUa}X zkx)mc5s$AJ@g%52x%2n~W{X>`-?Xug?k+9S5nMYwG$Sle)Xa)`t%gEnvAC4VB?gMS zJ1U>F`Sx~};|yCz%^|80?uH^FxN^HV@(@YC`T&=MBsId^>7jsllq# z2iH#Jdo_=#zlue*OCb$ujM~`CPE-H`$9P9#E9*#`wzU)u0eXEHXyB_eQSd0mBzBq| zU|=!)a=5ci!t($FFN-RqfU#I-jHSnY;P;6WmrugWaTW}ByW&LVQPgCJ^}0Gy zZSD+v&glZWPgHHSaIL@#0a&s&zdbQKb6fAlV>O7a2A?vwP7HA%BM>)Ko*cGSHFnDC zcSUUKQxsYiO$M*$MnEaTJ17~kC^%NxEe!cigO@!4)hd3*LT2A)wGHx92oryg*$Ow}qS&_k>D zZglW^CBY27s*zwG3U0oe$MFZ$S2Xg6wG**UMDi)vJ}M?nt~eau`Vr4#v=IQ+{3J0w z#~eW*pr;{f8T3PnN@?A^ zL*=Om&CM;psDQ`3vzHiRtF?-fVPR~^a@HM$-W^+kU~%M%!8y4C>1(_fxc(IZh1|+g2&RiHAXbk!LR8|8S>53`1lg|!b!Qt!)g-A9*|Xie$R z2_}zHh<0J^7%w-%326(a*klSMYtbHb2z4Bz=P5IMx1@jZTIgz#?+p>Na=Ep>ln^jx zQ;KjZdiOB~m0#orjj|Naqd@J+pYgydk4_l9XR~v^i?`Dnz!-?ym5nc*a7lP^AvlZ_ z*b7(DUMj#xe?Mz)FaNq?@3z|wl8(7qDzG5MQ}@0CpgGH3ZeS{y1LmbP;`SkwFnv8| zJdJQ_5MKPlTTYPOnHNSUOnQ4g+x@{Ho{i(%+6ntv;&zU9K(ImZLCf5+GY3o!JAt{E z>rN;%N7k={yx5#&wGL>;tx+5xdRXs{nD_&J8w7<>ns!Xp%Y7vvEG>BG+B+AofiQp2 zb`%G7uYWCaWDUt0mH1%TGK}Qa)*HXyIO%Iblw&>I9bc1X82+QeW@{RE(^Lwn!{G2b;yx4wNUys+t!hq;J#r&elmh^W8V;6;3N%2Irsc z+_0Kfnf!j)pL52Ur)J%nj$G>^g26G zbfQ4CQDm=?78@gL-%16yGKOl~+F6v3M{;jaSvBMdBEEGJ7cpvmk|R!zk%En~Mv&P% zYNjGXrNmO~<2{Ur_}O0!lA?(5`-v|uF+SA^;m=aOmmedTnkcPOQ8-w?NDy`-JE6c= z5w_0)ib=$%m`($y(2xUQ)u&DPs-mtNwER&fk=8Z=i&}@o7&`)azZ1S!gIP9^ty0v| zAnkLsv*Cgzm<|1Y>(6-^$V)jY{s1Aw6pdoczdKPqbCeEbgFscr$nQBmxmrILmZT$# zv9Z)Ocr42b6!Hv6x*%i+H!>HxD+9x#iA5i79;;m$KM912xW`|61Ds`q4?Tv<iJ5 z8}4gg(%Yw5BjiL_B5FEjSybqKm8X(k)_HqGlIySI85LA0#AgEWHg#x#Ed2q6UlQts z0VXRO(@h>tRiliS)o0aaskJB!vyjX@S<5fm+IKCJsa`6Bu=d>xX<2}M08S~?6QScK zYwCBt=~=Vuw+B6B+#TWa`Oq_oEk^R0^LWSYly^nnxI70Ee$0M+WpBO4++{(-z^Fyf z8i9CumN7{j7w`3ZB2kgbdQLp`cbzlEiaO=Q2W)h&8sCqM-9jx!@(2_!W2IfM%4Rcv z7v?KLbnQcm)M&L~a!e|#UAnZ=p@jv5^=hj%xA%PR`YL?)X%TG-G@QU%Ol+QCQ(^59 zo>ngX+~r#3bP%x5-)6pJdY&t=Yx&hNjr)c?ff>J+UCL!W1^=X(0QJl5)rlVUubS_zy>cW} zlIXQREh(mxqt7!Fsj(1LIvHI!h3?ofA8nh}%dxl=x%L%`3lb_02()>?U2`_V#K zd6KTM=8e3GFNW@)X3596X2#-WaYuFTOb9roLfcResv;MPM1$`PFB)a^7C*OLZ^ZB3{&aWWl{N6it&RM6*wI=-H z+dfIq=;jxU&ZQl*3t5B;X|DD^4CeWY%|!ciVq=nH^oYzUAig?#VajPHqSU{ImYd@r zg=NAM6xI)2>(}nnLN@{og8a!C#+EkXel9HXLwZsKNH?+|RVCNSbgv#eO&h5516z&Y4uiRY#-`v3dTRk;)>NvgYz;8=yPn@WYJbk#<2fVrC z4sY#>v{owawUPm9*SH+Rc3WY%`l&aUzzjx33&@WWpWnb-G7lZG8N@`bj%qnk(1ZsH zx(+Ek`qrEG^HtqN&Q0a0#kwm31V7|UI*|rKWybq8t97Uw&L^TDqnfOoIwK9x*n#Zo zZ_~l78`-Rbw{%93kG^Qg&x6Z|ZLo}{S&?3cTrXe}8&zIhi&?$P&AISKDu%iQ|q z_udf>yUPN4mOGEpvU&rG{JUml-_bh_nc~fD!WVdP2S3xi@&Wd0>xX*)@30?rE7R0+%nD1+9t^2)njnwOr@6*K=Umg zRxA3;z<>5mZdkGUmS7GgDOU~P$wWx|-j>}gO)OnQ>KJiGucV`Y{MFYa-|15n+IcA) zuxe^}`o<5C8gYEh@tLVdPW~exs#s4utY1oNO@`1bn(T4<^t`662!QpFqEvO_a#=WW zk)sf+S%MGi=j0IG8m<0-l^YG^LQ8b>D2cC0b_Q=*+-wP5HHhPo*VQvyTZgn7)ie|S>~$KMKOh0QKmv2Exn<9&b9teO-v+LUlJ4oHv1m2Kt6IU!MGiVA!g#KLV8@ULHTl6FDqg zjFH^VR~+Qf@=ebirw>*4om1>4ei1BSb3kjw-l6o5j49teC=AVN*XuE##a(O=$_B$1(@N@scnl44zdNH@OUOHiz&-+x zL&aoJ+wRNGu!E(?Yh03HgPX+=Rtr0R0uoUJ} z0&OLk-pIIB&hfF{PkcJ>mF|VuD?5yGfXGL7zie8F3V!F!E1vNB1!+)Xof!3}x1lm} z3_xekad1I;ytaK-RkNmf*4bmn8Dn0JtBXU=SG8)d3-1b0KSo4k?Sva4D+$92`+f7d zwYaqhYnp{hM+hKRcxx_7N#uPgawKDFzV$tFp=x8Mg3W(k|JfZZI6rf+R#x%(RNpj? zxr#$Qtfh0-i09GwKoI^qg@#vhGT*D1owc^5|GNRGvQ+VSAmsJ2`W5}EDv>QwXmpm}xWE9JZ z(WBeSj@Uoqpwg}iX(-y9Q!7L*=9a%H0%xydVyp<~b=B8=KJH_raHxou??EWWMgbqo zmHH?Xi&Wl;I_tKv(232qNk*o?vSUmccsVr(C5X;<sl%kH&K6k&Z*(rIj=WU&DlX#zTdHLflwj!cWLDF z^HW046CPb1Bx`-(;V`Tuv#EIh3U5d+?`qP64of;guq}3bm9A}y4E5~?H>`Tb8Mzhn z$Or2<88r-ZBNAENfY@{lPP7XriLU98kJTexu-e#Rp98U~_@@^jo~nol0Z|r-c-8?? zoJ@d>x%9?;LHS7RiQj@M?k`+jQczb*qA(G<+dX&#+`9LS-ZA6;ZmaY8?S9OTFx*6# zgV7xp&3(3Fx_q{V+XYp4GU<)$IG=EYYnEc)D?Ata*iAs|s)V*xPvV(Ro}iUd$@l{G zh%O?%3e~P?sKH7p^b%nq3{!dZ(U#}@en?=TA#4Rlyzw_SAdi_C(;+hXvPAyg+Ow*g zrgEId70KT<*lI$pn|RQX2*|6KML9pDVbZeS$~~L1Qs1d(vukbzPUW>JmD$j*sCHgI zk;me1NacQ481V2*aLJ|Lr<=cnW6xD|m~C+$x<_CH9^bOYBI4TZ@;rQvZMLqI5u}CH z75nA=;LBiDG%a|AGK;XSv&oScfRYyU*WBCJ!sBqq+=e_hQPMe&0L3tJeR0pg@p{|8 z^7{+o#%BX04grVKjqk5YbMGg-d15nFO@4=CX&%nPaV0XsRj zS|u=z7A~pK)Jz6>!jmvy;2*zAJHvychU9EF9Pc@XO9_zA2A7Y69k9 z$cKn1XJ{pPlGaYb{#W5A+6C?yJR<6=(+p_gojmjhG@Sjdiwc1Q5M2kDJ&-HwxzT^w zLIw4dGO4pEo@%s6wJw@g-x}e%Kj$21Q&5``Pn!9bFQeK%|;??$8jd~TRPir3U<5E zEc3a3m6+3hm-svW?tM9#?W}wei5(2D{bZXge5y|~tXF-Z(#z2S^o{~HG^GxRpJQ)QK7|wh=_bvdx(>fW%e$DQ( zNf~|p%VCF-C=7Y%e(vHs4rGoZ`n-C~<47z5 zm0VBxW2|DUdukeIq|<7B>D<$f&cd_(F4SXfa$$a9?guZx?P%4`zzfsxZhOW z8)|$rhKSe6aW{}R2N$is2H&V5l@S#YzU{S~4r!bCsSHO&1?aumv{j$H zKsJ)6nvd%H8;*JA{HDyBQ)djnDZ$xKE~5U@63@YX|V;?*p7Z_Ioh(1Kv@#wVX^!L zG5-7U?jmPz~zT>QUqiq)CQ6wm?fRIq(#@Vt3%9rwO5cnEz*nqMJl!56Dz zng7oS2?%(+{69d(8Grv}x(@^C|9-rLz=)acjE`<%Q4F?KT;m>hWEzVmq zo%V@<{kyoDa>Hs3$V;D#;Ip3$pgOhxf&6v=k}Lmjtgh9KA6PkZTm5APf|o0xN1uU; zJRhQTw*=a>t@+a(fN>PaEu6AO>}r{nTAcuDM-9_01HIvh@$L3iyl4#w9k%43f|or7 zVceZK+goExqJE8UrC+O{TMB~4&uZrk9c%iw4rB{}!1ByxdLS}+bN+=?evD|Zz74wS zAIi#WN{u#kl&6AY`rk$luN(QiGV>P9gR;s0m(~25HTh!UmZ!0afSptFUpk?3kgjsY zhz+eMU|0Q*E(V}3TddV28$rIniuFG&)LyrsIs(cIUJCFk`Af)oP3Xinx?3uq`+1f{ zARQbKoO+-O#QXRAcTePjqt9T^MWdFky>zxG!DKEGK)Gf$`VX@y$Xvy1dLfEJTZb!A8}Xnm z_n6C6uj$GpCT|^HMA^lGWmhd1R?Hid#|yb-Qpd9Vr^5c;E;CAZZfMmL)82ZiqD8{V zaw+^ysn(<-js_+WDMph%3Xk-(lda7)eqEdgy9-(zNO)!<*gwf zNqb+qHs5fRwAv37RL(|9_V(VmuV)oM$Zg4ZzvC!n9ZV zRxB4LJo7kR?OLs7c!088C8cM9BREd3b&u?S#)|gSu3oVG4-4m>t1(C-wEfPJKb;$# z_HJaSj>;(2;#fF5DEvQszxs!=7bA$hjY3Vbd9irU-SqbVrLq9bmdZUo2u_2MGGA}XcLy4>9dqS}KVy>;@gD>(9PijR*+KrJm-*yAIOS<##YUOxXVDv7Tgsp~nv zv`bk!w%KcF*5uzV-jAT2ceJ#$WFiEm*jlC%stB`H`v0NRQ&vVPAkKPx$C{P=XBX*Wk==27`jLIMh2ONj=Y<$M8Jj>nUQhv@$K0a)aU!@ zlU6|byt1M78wY39Lbkr{;nfN2?-M8KYe5CO9(3TJro_ltuKn>TzvIzOJz|WY%5>qg zsrkH~KDZlwTJ3CrI{GZBNkm3L3aJJ#GBZmfT4-UFVyB{$qnUdilJ=>8C?|;T9qWQX( z)+JQ0<&s=i_oa{%>lWt<+v@h@Z!G=lynJZyIT&8A+&9w@NEwy|ms3z+yS6Tti;rnA zcG+N4M67(P#6|jd18May`D-7hU(-lcwFHS(qfgGteV-0n%Z@TZz8x-&y*6>4Y}}i_ z|6e^^F`j@Y2l97hd_~pjsAOTDn{KL9(&Rtd^qsJQT3vYpcgq^%h7rIf#s(0w>vKIg zJ$zg~w`urS-@oS6fSD=C${J$aox&UOHPr~ zAM0;lOZnRY^adt?j)}KM!HNQ5^m<`%G-`v>ZCql*JpR9;V!8R4IA40W)1*HYUV{ns z7l!tqCMl08{W-GEv=#l|k`#0jKNDL~Z9ajjltiF+ zhx;wF&-CrDN&XS`a<30=$epOYrf-MN@YY=0JbA=?-Sr>e>w>-SpYRl@^qPRA-+?xjAr&z8ra7^L;8)U{{HW!Ti!TI4y{MI zeZF2sLp8v4(m$bO?%8&ll=NXHxUyX@i~OfZX7EofeEM5Bz?N7IfjLSR7=hcz1DG-x z=d5U8wqx4^8UI<*5}$JvMf_#lD+U+6slQ8KwgUR|;i%ZS6(39D!1K7&b~p+{z_616 zro#yyyj}?JFpr+9iDAF?N|y2U zZf5{|K8w5VBCzS*zuR5iQ0wy}t5Yy6F#zPnz_5f)=ZJpjdMnB}WCWu@>2o=@#O1%c z5PSSTEy`YpyB0&&{Sk@EyY_Vr26Nb;7t?U*Iq830EDeDjB9f;?!Ddb8tKg{0`3B2L za4%~hqJNVH!U?^={=6>ytNnGJqrXG%x=3E<`+vgeYm5I6qR#(B@Yi1YD;Oj??W&?J ze0=AI8HJ?sV>3g4Nv>=Z`epWcQ<5CyW+SwyL15eX2Z8PWE6aa!)kLD^=#u|QTH^o? zuv+lr?^93}+>dr*$SC38I^W+10*nJw*qAGOF}}h_PH99os5%?PImwf7NG$X zfDSRLMkznRmJ#A%BW~bn_XJ~bzi34fiBv@K%Z{gD^&x`>u zos6B<{LjDdS{8eH;GNwNI8}o82k^QvfQGkB%9COxd3VFbt`g`Kb&mFFL79g@*3}@1 zypGApGmwo_%pABpcb_lW61|6IC%)u9Pshah5p3)m$RCgw3B^LG0nz=6pu~{Q>mrmh zfSwt;h2^8iwDBfT{JS#k&8~+5taUP1oIIZyKSeLn*?rHVRfk6wlf5;ppZ&A$5&^-n ziXaQ$le&$Uve4G&TrVX^rOuB8}_Gu&{V!fOHC)hm{ei^!`>Sjwv$m3be~E z97^)$NwIFzzQPil3f^u?1^bdbc<0$jf@!e(N1m-bAewVPTQuiA+0JgP>1VvPijDOJ zA4o!cG8>Dy8c~(!*M&>$ei*S_Rpn#L$HIC^0P^K^9=HId@!cx!2hX(H-cx$-ffcu} zD+a*|QRQ7`Lc#$hp!P*HUjbNy%~WPcp{JMxf^L&ZOg(yvh4o{J7?!-s4rU`m^gUK#e>*(fZ=CT#l!8aHzta?)722E(yajw#7=cNMBGbhJ( zS@oFZzqGyH_Nu!>u_hV_Xbu7gE3W~L8if0$wzq?D@a5y1$oDojqva=XaY?f$gbJhE=5gwIvO1 z6AoG$KsG7N!gmHhi_&ukx5=+7)Ar@q%jM+ z6II7FjW+5^=Je~70i8>@;Ri??g8DHfEOF@x(Iu50kYwz?XXB|ll0TaBV920OR+Ly* z7%3%j$wlfb&V$UF*8o`m?BugUP|QArALc0-$^m%#9 z@GpfVC+KKuP+>w3ko>?l1D^)OD7ZVZIfWhm2jAZ?Mrf26CcNebBR=F$LS{X7Hf61# zhQ;%>GPv|m&#}h{aEROSyJkTnXov!t2ID;ay*l#SKjoxYfS4JRPHUk~?+=5F&b{W< zW`TvSL`|pBWbMv;O@Ol2X_QFhK=}JUy|{PO^uzlyvIpF^V{Si>ODy!*&?$wG#CcwY zy!g6QsNaJfTp%3%cF^`u2QOi`dY|v{M-rjU=X#3hnVm<{Z6>*~AGz=g_>g{xeS;SV zTmfNSAmYC%U|jP@LuX%#eu+ndGLU#&HER^7z;sc7=CQnv8jvlRFY@UGJ#Gd{@^vCor1K{w!@L50v zDzrX+DRDGRBo~iqgFa?ItZPvutG5-t!RT~wN(#Ge%iP1Bdl&pV5kTiMZAfTHOM?ei zmj2HsE2B{naFti1+_`uP?VbO8QQ6>oGQ9U+TOhE^@c-x4sPGt6>VmKE8BG(e=ejzZ1cV)i8UdK?;^TwexX9J_Z=+U`+jBjp;8aA zHI#IzxWaR+>Fa||q1mB2QDeOxt%v51@qc#Dy;saQH(f}Bq3;s(x9ZE?iUW#dIITZb zyUK%xC88cuhad}ZXuHT6VXpUHOoYul8JP(|$lfT84A)C0lz9S1#xsR~0BnVQy80Vk z?NjzLl#k+ZpgroYu4B1x@ayc~K7XHTgUuk$3t(A0Ph1rM2rN4)QW?MdS*)s#=>VnJ zj=d2vA8d$)(?3}52*SdN?_u=JvtrpsL+7xUOph6+TbcLE{nK~|Gk$|XG9d3uXZ4Q0 zKpYhSb-*SSoRF}%1>z;hGt(f4N%M|6IY8?=WCWtA*I73xKdeXhFWlp4N9*AT@U4-h z7x$WuxT_+A0{m&jWBcD9C>8ZU4!6u$-uk_pJ6G1hV`=<&$`z7|x~(L#@YMWgw7~mD zAygKnaHhHrGw1?s7=b-7t__+SEG`%52*-oI7i!Z(U@6UwU^13G@eHYO$c zE83J$70oU7(v<{sVH|3dL`(5agEYI{7CDm%l6Q#@B81NV)S$j0!3_gO=u22&jaql2 z6#!b*uzppvnm!U*KYugzS}Z(IvmAj2Z z0VHJ7ppSGL(BLoom4?$BFPEk(o*}0r+{KbnWth_pKVj=o$auCA>4Fub;5V%J7gTu% z5FwHj6vy+iBrE2d7Ev!y-p`GO6DRTk&NNa^$plm}cW;tNRp7wWyK4iG9*anh6N&Tf z3&AkNN0y`SH;zkjYo zhvyJ70#L~uIa6W4vob)Suk`Cp|5evZ$hgYEVJ|X1Dw`11n>msQEIvcnk)5&VIha1O zoGS;$9%6e|1!db6L3EX~Q8^Na0J4m(gV9~N*)6EaA`qgxGl`W5BriuP*yK2X2&sOE zi~$yy=(`d#dWFT4z8G3lCQOTSWTbBb5N#h1WjxkH4invkHhrP7j^j*reAVHRM}!gG zT0DJ7gk{oS6gJ{T7^qx8^C8~H00cY7K{a?hpecK@S<5pXl!(IrVn&LUem^(~I+vB@ zqkvSwbEuP{i&(zLkYHB46MK7F70r(zJpWBj%A0_S)lfzkZ@ns9l8tJ^#87#89u-E| zjbU1F%fzx?*Q{Gf5+y!i&p*>OC;<)=IxASBOLx$NmH`v8MNp}c!;}gYB$&yhQQV0N zM$wk=N96PKhKJBU@zM{DzYyy)ynV?S097gbwp!47b%sUo@YmzzSo znp_*R6vtX_LYhhPc@v5VAZ#KLt3gKG| z#K)$Ind7oRl4Y#WqOh*JKV01I{;>GD6Lk0eTnjpMY1u6_aGoQr{2V;nu43as{8+`k zrIya3?=yo4N1R6&S#~_sIZnkzJQez?J=ahpYXU$37($al$2%_N*bU`=YnR1Im4M_^ z!QU&UUL5>s`+pUP9VgX++lv`8O}-SZ4l|AVTM|J-m4mh zTe7(FHWV0$VEbH?m5iEwA~S@z$IAKQnN>YOF0}{wCFcB1s=FrSaM^pQ9D=#4!2xp5Ndn7^ak6tY=o$a0b7_8wp2PR8jo^weVdHxQ^Ll4 zh^b(u+#(_Ct|FxkEiPA@U5jvLwG$%z^GIdkQ%l*qJ6i3H;Y|T_ANkoGo`r4$%2_H8_Lc9hh3z(%Skd*|^bvD5jjH^n_Twd00pwGBR9X?hbCes80wD=N zoi}6yh2Ev!Fh9emOGVLF_e3kB>DgPfkThl+=FAAl#yi@HH>nPq7NOo>207Q1 zku-0u6mNPwoe8?YYTACUhhzhgENqX)nt}1<737_+H(kt=E5$5j;;N8=&D^7(Fa(=I ze!PKk4|qeHDwOV-ieZk>tLihm71tCRYn92~ZV3bA2bIe6WbXpX-;0X0cjMHby<4eB z)=wezoQlU$M-z9k8>Dz~G^z+#8E4eX<0|H>pSg^v=#Y8ZwU@X<$nw>jjn#})k}6CS zw@&Uc=$)HyDI=XQZu7atbL@6`Qdk5|v`KRopZss*)rVJ!tLQ{idR|%BMCreJ*@f4v zj-WCx0}rBcJypdkZUE1Do`#!knfGndIo-!qXJIXo&fKf!Wh?bbRfX2H4jt;vSX2+yO>{UYeQ{R;#xbQtLG1M}-O(61zMxA4p6_vFr1} zSi{iCpkszvIYX9KTYz2GlrTk53oAyL+h=(c-Q)`*L#IcH5%tEwMk4x!puKc^^JJT;I^zGbICJk;iokee$vovagx1+h(X zNObZd1xQA!)^;>^=S!3>A+d=%&CH)iS%CQ#U$g=Pk{?t+fRs@+BtHY2pANWX_E-(5 zpbZ~DlFi|x@v6MM{N9OH7`9aoNV2S`h3u$rpGSo9*fZ9_Qn>9IrIe8*omV@A?2|1Z zKwhn_hdy@IBgzvePw=2u(GhC3NF@=Su=^u)w9G?fgbQBU?;7&W)$sX*X~}(+JDh;} zaw{@}Tv~a(iuOJ9yrzm{dOn9p>yRs_?8k$-j{G1H>);pq5ZlSPTAU>Goz&yOKOXZ1 zg))i7wxl9jWM6#|<~Sa@|7v?9NJD2cYyCq%k@z$g$v!CpIj2=GkA#NVy{~)?Z{vjR z_!MFO1@;J1XcKWL2Jda0ue3hztk74)%|ZHz8F|GSah$J)7koZ>bj%Y?l9@R26izequ4 z9SrthtnrUq2o(vRHgj*PqpqnQ@$m5NXGm!8`|jr^RychN{vnf?CIXsZf_7{Vb`=-% zdjsjAm|F@77~q>xW6NoEAdDhtQ$qptGYR7C;Ox-8Brx!G=kDT|JIe<1&TbTNxnkC? z`;|`)ua~D!l484feGg6&<0bS{H}IvnkO&PgZh}nv zzBp~HHMnbfY#FxHuLF(^wo-(qy26s}$m)@&G<8mkv@6N^`t#QMrTV7DEzzsd*RItR7B zY*IYAq=Xz!kT_GZZY+-k@AqQQJL@0(LP9re>##OXzXU9aFoZjF-c?5LqeM4>PZf$7$0jIdgplIrM=&!M3;}OQn7oxCd>-@u< zAWu9+4_Tn^ARKESkxlDRYGPG`wWvG?>5=+XlGkdj}ZW(+8 z&+(KiC+$pJAcJqSBP#&P6n2BHmY+5<3YjjszEU^-OM{Lky%f7+EYiaTo^qFP#y_vI z(~jro9feMb-+W2E^>B2}%qYi_vIYXqizKQLFqK-0tRyQ#s$Iil_Jmt^DAs?S9s^!ZnbFA|P<*b^h^)|5$^w*LD>5*%)M>DZn9On7H%Z zPjOHEwht6+sydH?7mK=U@^~XXHQ7dc_WAmFRCMStvx2k3U+SF9gVhI^S!Cr^HD0R~ zM2xuqi92`=%gikqsXdtL!+lj;XL-w*^bITL=!#=WW)$@l{3mfOJg4J$JwYE~$Okhu zUyNOz_~jf2Z6QW zsgkWMp^Y`{7L_5gTre_&<@@=Q3Q8l%JHGFYFv3!rw9B$awskKkeTY^(VvHDzRLxO9 z(dn-9@nbu|_9pACL~m*_X<3rx*E0vWVxO>$AzZLuAQsxqdDo$HJ%peC%Cq0|{B%JW z>qw+&n1edOq%IF`>2|m>R)n6V?I$^;U21G;^NgwvEoaVdYqKPRGxU^Yy{YG+fk?mp zttR@V)6_04#9-~uVfu~Tj~~Vvq$Im#`5ik-3v-2EZ7=ob1gLc%Ts~_1nVXEl@`tb? zzNshR%KqM#z`S6|i}6W7AG|&m5SAL1Ofodod5w2_K!OYAhSE&!Rzs-JnjS-v8ANJ) zz%WkZhxa?Bq)r-j5f=>(LaYBvBRc(iBS4`C!TMR+pkY!TkGcH zGs8M}qB~*>+HQZ3>5u(GiJ`M&g~?eKv3w3Mdk~LPG%M}?J8R(gZ-;fgM5mN&f+P`B z=3Q+MI)}dWs2sH%@T~o}!4spQL;sgIn%Cu)~#mquOTOM=5Zf!B)72gwrrik&P z@x^~d$QX^>RlJ+#R^hLrg?_bks)8=v({~TBD>WldQ&#+9YZxuRdDffI$5@Mg-=RUC zZ?^u;L2{I|cU+_fMQ9rcoM9nq@$oAA!M6hurW6zv%pG~k1he&I00V5yU?CjEPY_a+ z{jH~21>FTEI*6DIf^Mg^w`(A!*pwkpSfk{IKQ_fOz#M0Yy5^JJ*6$Lp#-NDU>v?c5 zmvoRHzMOZn8zA{ZZD~WN%K*<)x}O&z_|D?=^@2JWJI7ZqG<0kjYRAGxh)Y)-d)0i| z?ifuAtW-|&9ThQlNDHJtOz1m*5Hk3kT<@pIR2lH-_%nj4^VA(8^s*~jf+hlJxNjI; z(8`_c zO)Z4#gCO774$!kGytXCYK0q_69Fc8O^6JBa^9ibr z8Kw>+#XpZ0V#rriQ#1DXY-R~P%E-tgm@XEX6A#_$B~Tv^hNX9pmv zdMgc&#~-%9Z<61zn{&;J*jFTYB=j`3@ed!84$mUOmx9!Z#S ziCUkf?8|0Fd)k~FKokmoN2!ZuE%Pfb31ySBZ8qcBnPs(G9L|Cg90bu=mji7+EAR!G>yQDON5=$*02AzT;-7PI$(%t`O@teQ*H}A|l z|Cx7Z*kSKI_uO;N?dQ3lb52c%3W#l4}&o}sFLG%L&<13ZgPCUb%O+~CANj97HGbx!Z;iX}d{Pds)STNMzM99OG0YRiUG z0k*$7B!XR#{AjoyJ;*%$JjefeZobjy@P%Ttp4gGJJ>|Rmu`!|yR;S{_snN#_;I_IsZelWzo=|p1-RFzo>eORg(R8}T z2)wB)EU(0(>92_Um21l_OW`G6+r|u0r9$a`CrNBm^$GSzZ8y$E7fwwpAdzkxuP|e@ zWfuFhZngjCLE$IIRubCQmlmk;IISa+sK2l=&9h3u0l+%dLQ1`AMSQ$D+u#j?U!TOE z*7jw`>mEgFDR>9Eh4S?jhHBv};a}pLxL|=gQ>o|ZGH@19`@FjwJ%U>0;CL2h?|Ier zqn*UQ;H}{&4gC28#*dNFf$N*hCA|MpOFwW9#L*TY;5TdZd}Rv90mo5heo+u;U{qtV zP28IH@n$Q*;+Wydr_78Ha&4z{n{D_~{~d#>*RgV=%VD%fmzay&B(!gJGGF$O%G2pE zp0AKx+IUV1nEPR?EDJ9QUqK%aWcjrub9p6NW-@2FA2*|OEku65j+#qAkfTHb=V<3W z;+sZd{`-LDA5`4+k8e3(^>sv+tdJlUoLFqa0Lk6h?>+p&-Hm30@vIQuI05Bn+U)~T zfnPn|;;F4>F{qLfonW+vd%@(=ejahN;5A#0TJ zHgA)&TJmkYh`bXH+;<0)PJsB8pY{3AdrhakK=6t-9Gu~cLN%Nj{|8xx;D8^lxgqz| zM;VAJ>IHhXKO1m8ZQkL_ZQiv~Gn1F~0IEep8GPy4SywNt(s9HQ^4Nl+++oYZ$e84#%e( zL~SEiVDaZ8Tw1GYo_k`=pLsEzw$~4ws@AhJ-|7(w$!GepMlqXT6yUetNARe62^{*rz!4^q858_?h97GY+OM-(Lr@Fyl| zuqx)kY(_-av#jQ-qNQq#?7y9Qgh~kW14imS4ZqnI})aO#)52%3Blk4WK z3G}U?RDVczw$zO{j2rS^ML*AQBWenmvq%fsBTH1@#<+zfK#7ljegPkQMg9oo{1fn& zdfedo%b2`xMkrC?t~Dt4_GU94UyDON@0ZTshHiuqAGf2JY|r^O$BIL;nDjbVq#n-+ z9m2J--VB{%eB&l&JLN~YjpH<+U%hBFise-wJ!d0ufB8VP#-)2S0ZhfyD@V|It&I_c zvs7XmJ2b?>4#9+DnZ)Vl8|1J@l;G(!!y)!Jr+RQFA8NB^~f~dYalijorDLnc9dD97MfYRxsRA3@=@u01Asqg zjIBBaMG?*7jccN>kY)QEl3L=H%8uR9M_<2~;^P~ImL%JV;Q4a5i0+v`y$V@u=6hIh zTO)!{jjq5iZhn($nKM=Is?e63=@E=^1E6 z`&CBW?O#i8fvcQ}hm)F-rj(Cd-HNe!8P1}oVh zIR155$W)@V`9UW9J{AjE7IE>sOdfpTC5~anfdQ@E1ta8OJ8c?>h1rV3Mv+e>JSAhH zuNYqGilYx6t4JC?>~$*-j3cGKWrGMm`kDdf>|rcAU)h0+j&**Ct|tsL*3+z=k2vu&~kcJ$Ox z%Q!#N8XdI3s>h9fw%hgSxn}1Q*U+JDXT%B~3mq>yd$U2EG7P-WqIa{n=%f#q*nam^ zzEw6Hi*T!tSa?szoCrQ>F&<7VgX5~$ZT|Su--s2*@#pzZ))Li?K$t_u%i%s6HqjlA zaCwEfti^T-r-t=3xUz_nVu*Z6;4}I3Xz-+jFf=-AexNkk`XlqxWQN2JNFPl@yGf>L zUxl~b28^}eW}|}z7Pb2^fBT_N2_y^Y{q!cU#1aoeTF#Lt94{J`XIihEU>?Z6*tpvS>)f>O&fo;Bw z*jr5Bc)g(E5(UQY3DLhqZFesj2{1EpQ7? zMuBrM!7F{KAQoIubt}vba#eJq99{|g~nw@q@<6@e3$~_hz;^Xh<_E} zVh%Awj?H22<0I%zl^T?@k_ntHY!3PA6`C+L;#f{Aoy6PFbS#Fd!)YIKRXzT}K=1mW za(T=&5=R&fp>90og-mHE1$jNMQVN0+2Df>>&!dwA@A~^&0ear&AduRyknO>)aG-G(;ZQSN5KYH-)Qhxnebz8y9*4;)`zJZ4mh57 z>IMZ~dhP^X;19`IazS?YAkwl|C$sU5(+g6&fkCI6L+q(*RJ-n#YZMO_wd-NvD&B_} z;^ArA)8r#%pUDW*E0r-}I3r^XWF{pZ$Lb5_tI&zSX+Nw zz!Fl|5BXuWW}DbRZ1XIJy6SNfH)YIB*g@MtgEUSZA?w+gUfQN0vm2y`vTCTUkG-Zd)VuQuoS^rXCPVEzDW;OO)0;DHNM-^ehiRz8x0BY5;Z@+S6ra%=e$x4i#!bDxli)S5H6u1+pbL@&ItG+s8`Wn{p^vMtZR~RPgOrE zVL51#ka#SwvJW^SY-0FnjE(##2D`*g2%8B zA1j9=Y+;*Q>?a+LFH;baYNH(JD@|Q3hlhlO=3gJHjAqyNFvRbB&3PJZcL8agtNlYs2#oNcpAcRFf6dfR(q9iiK}8981SNIYbXOrTTd35d~jYoyg$v z)wo46c~k6H7Gjv%6R2m8&p3ZmC2klZ%vK-DJIPFLV@?EYf_ctk2UEwN0`LALr3B9N z9l|SNAl?V5@rd;bVw=fbGU5(GaN{BI7%8?|dCCv{I4Se@z&fK3m%gICro%c&Twde! zxn6j{wz(R>_~wU;%e?<(R+7z`3qPg2!n1CRN(m3KuBQyA;duUf4UegP5%r&(g;u7S zA)y&qd^g)))_ekj#U%NQ3;Ldz#BuhVUb2AUV$*!5J#sIX_cjRCs>=5YmF6(ro!n=6 z>mL)G{$3A+x$C4x=|sH&v%Sa<`l+s;;%m*CyZ_!-YbG59Do)!Yh`H|Jk-Dw|&zL%P z(SLdK^qv8caf7SF(a$4++APK5CtoC#oUZLz@sFwF`1-sK|9H#l7BmRLs!)Y=89#nz zYhv)k1{~l12q3NsEkIp@O))zg?yCzt!Qj1+ zdg6(gW#Z*K)HNc9Z7!%nxqdvcpp7w9;e4v6e~`)c7C2eu;OPtl+wm+vT8x6Fe2tN( zz=I67D4}G8xPMrF*dcLS1UDji+$xE9tYUs^NLSCE;6W9sZ{aXC7N>6hd++4_7mr32 zP^H;IaeldFRcE~XqK!X4@6ffx-6Ws?1a=VxTS-eo)I7AZ2nb4I^gUKlY{qTUaLCXY z=d&vicu`eZVYW8;vKHQYZJgyOzROl3MeFs>F7xy9?xDZGNs6kY{2YEyxPP}L-eq%x zi?pQ2WRx3lc$aRyCKldIP!lF5v0!s-XXQSRGlu`+@~{^%IdaBJ8b28?u2+*UvtaFZ zc&1_2cN&iRww-gmJK^R18715PskHB6#aR>6KKA0|Ra<_lo?v@%d6fP4X@f<8xAmPQ z&T>x>g177^a=)D@fMM;ZQEqXgRR;vUE%Q_;YV|R+QuC7*M8u}+HLKef%KQ6axQ1(d zCO(D&4+!$)drv$LiMg*2ZKD;N>2?|f@lLbNvTtEvx}mI2kn;KVYrq?iCok_4QID{K z_8}j$p+V87rHb<(%6cjk$1R^!US=8EmHK3{9QlqK1hA*g4S~F9d8KfGle?djWH`(B zuI#}GR}d`s5Sw@h{@z)Uu5<8=~E9N%VkMyca-Q$%~|MnAed9EM%;;*A@Dt zAc_FjvmL+#etU1hK<~pPh6#8Ous++o@)=HX9HRK-!+v)d~-!Z|<9}{!o`@!G;FPx-7 z27ku4Up^XUh=qb%`3?)2|JMrXK?cxdPm5Ih@+5c8Vqc9CK^G_@4f6k#j2<-BoyDm- zp-ahinkMwWOD`RNxLMDyX&M`?Tae%sFJB)re;_&2xnD41xs}nJzcEmBvZ(S`uf$DIZ*$H?U_q7K0Yo3xc4PH}$#k+RWW>=l^8)iZ`wfF!uRPzP%L7=EAqN($1yp zPC7t5cV(c-DKALQ^a(_K-k&Og$O>2zVi6+q1z8}^hs|H{EfzPVXnk-j(6T>oR^TqE zP+*+>EHaUB%1VfXy2o)ga5zLE*yCBdOEE#7H6~@>y6SH)UtNA(gFF|eWnp%pqG47` z({?GvyTNB@A#Q}UG{yO{53GQl07Rw~E|>DkMxrw8CsDOcCi=AbJL{p@9Z zl;BAs$f=YB++p0_8xtiR7bNTg_UyQ3%lGQiiG`y)RRWK`295C!SF6@Rdy;RJ1NWN3UKidWzVXs=aw0c5`3O+4K`jwMX_{=+G=zKu<}5; z=({49$HjMrcE_GG!KEJppcQR4=1q`81{%uagdRpUaKM}hHx5dcie*w6)Hj$xGjR%~ zd9o^$2E&RUuQmE5Gn)-Y>N@>w5L&4yVT1$D`LpcZ-{GAk-7A`-y-pEy%Dy7WQ0gyU zyYG8@dz~`IY(Nl}lX~y2?CRa^rH<07RsRbBB8$ZEh;|n^WkRXRAy4R*yVL=+5dhw~ zx^=IGM*00k!~X+N2BiNR+JpF_41kpW8y*B;p^!=CP@Mmt3O)mm`rb}K%FF?b8i0A) zrhYdga|ffYFiPK?ITi4B+N`3Wzc}gRBGG?>uXF~LL0F4w!OX30S znP2A`_L%Lcha{jp08_eD0YHVJ{;4`0KUwlN_3u(WuaQ_pU-67Ei5^6q7tlJ)n-@r^ z;MGBb4hM-Jm%wB{vQ^CkksvEJn@&<8%eC`a$CJRA;ir*@Hg=_GEx1;MZStE<=I{7h{wp%tllaJkv!r* zcb2$=$N4N1V0-$PvgBdS-`UX$381U!q$4T0e!dvuja1v=H&SgL_w7_2XQkN2JHw)9 z15mo6gi|f-u^R_{yr#RvB_xckD8aEP%t6TE&z&i#k%&6+c(WP`t)FiJyDnFPJR7X5 zr#T`u*dH?91_U)lbhTFS%Cu*S!kEKrh>2+uo;#A zq{*I?2}2?qjpELUOZpJ?VMr9A7m{i%Wh+^yg17y^?(1D*?gu2`5w_x{hBzk&2rNF{ z!T3$;`m=PjahqYxNfg{j$l&`Y-$KHCn*{2=0V25Ei6BuIxAZb8T377|spVZU4tF|r zuA1}7`h&*xjj6x0&a&3>b#!h7jT!I5==GI9XiYKH{)R+4H(Xb<15pY{j=ZKtFmq`yUnM+d9K?Xe&*{zjhzBRt5 z-luxa*8q@nYiWSk@*my?W?~z~k3;kOri+}xRSiMcu7ox<&gUmfHr^}yI^edDvI*sE zpSJI=Cp)%n5JsGwJ%!q`6tkfcaddeZ%CT}tt2+M5du)A|4vOoygn*gf@c~03s$dmv+W1B7KVO` z(`9-E9@D&|zkLmEo0n0A-~0(dLby|=F9B4$t_Ml6ymeJCH#~v^G}gX`{j3kjoEQFw z#NHqS?V5h00(Tgnu}uufSwmP^pF;}dNe8$u_#DyW1JJtiG#G%Z>WfoKil!qCdtN)r zu+;z&thq^~KSajF^!g#8=Lr*_v9*JQu@N~|C8_53qH6O0rB(sFUxi*XBN=cNpmv9x zzk}>Iq%nLuVe5~mOKYb9rEG~X{R_n2)FTQaJDm{kv=Y}a1dTEwL*r%cYPL7?R}mG-Ex3cQkZ@T-vQ|}r?~+e%C6Wjr;#%kM%#WFf-8&8 zZfOTuU(710jn#XoW=0eGAsYicnpzF`OAyyNf7I^);%ewo*y@G)E7{3V2=yxG(H7zO z|2NfDx>2e0r-vxr#nM_d7J?Fs3|9bJKx0w(UxnEUK z2DoA%(7$nq{uBRCb$&~jc8K)fpnzN189>VBUv+6T7`goS z^Avxf(wOG3UAnd?&(sA&zrXVvm~X*uU5#e#=W4!j(nF$|LBd{46-l>YR=w>Uds9kaWeXwi|_ z@Hy#&nzdK-0HECH1i8_n@c#?a|G$;sU;$eHY3pAA`iiawW`{4xx|z9M00qtNCUPFQ zZGbA^kRTr9S?mwEpt%CJ(d}u#rsSF!xg_09vC3)j?=69a=kJP?r8`#-`U|hmM{Y`r zkyAYq1kW}**$_&C6~Y+>Z+b4o#iVHjy%v3ITZ^Y+wx zA*m>Pg=mt8{e6FVo0_A9e` z*_2loFj5P0iC>q^YAr|x*e3?B!WH;<1II4Fa% zu?(Op9(X?rN-Q3ziXF~fEbfhx6XKJl3PX^AgmnR+Jhk`(1u!oZu{?tstYiyBJ&#A^ z=Az_ecHcP{J1c!h3~^P~Zv&2v86e05X6{MUU|V7k8vv6=eg)&+9e2F{?ey%WDj3Fz z@|)n!P1)TSAB+QtPey)r^w)S*^a@p{gkg`kVyy3{?jGFW(?gdYJh$~u zht@lSt4!2?jXCG7tgfySNVYVSglJ&%Mp(fry*}q(N_CUh7FF2STW{b{W1ML5@xLvbIJueB5Lsa!ClR%g^ zyS`EJ6cM!Q9O+fo(MVRe2hx0goHew&cY7(SN=loiV`71Z{m{EGJb2?Juex;S3Xe$9 z?#SuJ<-{(F`MM8BpiG#X(^9DDLzpr^dD;zmVo;YUCh3s0$&WLWQADo&q zk(>AE@ZoraeSK}&&akS&GeO?O7djey3hL645OK(O8&TLTh9P!)rwW*NZlJTeI^TrUUiMr&TdE3iZ zu9GcX;FKt>p_Y#uLHEAFq>13|q;bLc9+oniW-TKu+uyw(jHH&Mo%Wo3?ZAfI3qi=F zwaV(Run~@v6+a(ae@(=;{(=oKN&We>X0ZP~$TB(mW)fpm_i2hqAV2u)JDc)IJ-`Rb zc%X)naE15p%=KqXQCFvB2<=GDchh#A*boL>NDyCS2WB$q_5F-UCbHS5$t>=w zA%^23E_C&>Wuvhr8Q4r3Eb>iVTFe)?Y?>?vq1=%o-}WXVVRb3H(n> zh{l$iT=L{5zE4fj!-v-$do_e1X`V^7qhb?1kK)k$lV-P{@`9QXC!gPN?sD&Q)%yQi}bw*1%&ZV_aiq2jZII`K1*dly`6f zL9pDbXZ9IUBfjT455o|~^F}Sg-Ceotr*C`n{1^%y;aUNgZ4@uMZez8eQ}=;R7b-id zFNdpPxL1@k{Q2 zk7Z08FkH@Z2SZAGx+w!CCIx~?u&$N1uWQ^F+mK8{yv1c%JaGMQ2emAjm^^0P)#De&63x8*fBQj`q=L$6^{He>_%H`rI z9WxieE9q-@COISX0f*P&-ZxVNC^wc?EZ)`=LX78+GN|yu`_OFh;UwRNU2ZH+A=mPLM%yvhIYHQ*D{p;#Xo_6$Wx_tA;Z* z3HOk}$&0#P4=?*5DCG68&o-?-Kd5`5&SmUj(uQ~16Z$=<}>7t@Yn8G@Vz*X;9$ypsEF3DRy06*<=xS7e=+ru7R8B z<5I>FtcP%1q?FXn8+k_4+eLL_qw>k$&c4mW&^MIP>q!5&y^;i2{S~Z0?pg}``y?}`B5*Tf_hpsI5AP=yfI<1 z2Mzv&a}v|F>orEs+bX!ot4z#`5QlMzgLSBU#gjRCeYzR>(NT?)0k>s96Z!aXj&ROl zat+i2%C?<{es*6Tu;GO-C|kXX;YyxrSBzCv7;f7A-TlHEzJE<&K_K&9TdYbWp2+NzFGnRX^C3Hy2EEwTzxC_ItI}fedU6o=@R!sp(8W zKNZsVK!aR>a<09Z)Gn%|{L*Ts2L-CjPO>;kG3#YldRG4SqD=9yszo>Fw+ zj0QZ0vUk{Z?L4r#-aHzDd1hODX|?3G?WQjGWR+FjvnoYxZx$D-AD>3$rlr(|!dgA{ zjTcf*!1_yB(;ce=Q7aLc7h;^x=pdeXLo7@f&glYCF2e-F#2+uHV|;dHa@Y^1*a|~@ zV8S7-!h9KOeatL zXu$$(j5%oVK`gSThV<=71-)V$ul5g6)vyD}5pA2tC$B#WKn{u6*nd;rx-5EMChjzr zGj)rOvY$vzf3PdDW86FmCV@vqaONTup@Ol)9igoR>>^%zDFUSJnoUpgs;fsnxws{P zZQgi9M(9|*riT+l@JbtG2*NmBIVtTepBu+XZ*a#wS|*D7waEjPbAe?85@LqFOmQT#>beTNp4=R5{x&RhjD&qSDq~E3vOk^xpf;S0b`c))~Q+ZiI{YSK1YG5 z%(p0(*y_J=<&_c{N2Se2!SG4V4ndqfl+(AtewZf+W^$$7R4$Ky)N=9JrlWy}HokXs z5nV&Np(-wd6Z?7k4+ZW|ar4EHq-g5y0|n7ZeK9bb!t3D)J=)HDJw%Gd^-{mX5I=w} zTEMv3SK~S#NGx@It&0LygyTB2JmwZ;ct>~@(n^eC9%^^iR~bKDZ=c7YRGWieyYnkm z^N)|pg$Vw<;zxABdk`aw-X(+cDV;9I&e*m0_Y({myJ^Y~7MVN+yuO2!Cmv}Ok@7Nj zA3Bd~D{Q=4{H3=yN?;O<*x2mye;Kj-nIPzHSxN(Tv6&gZD$xTfk%F(!&i0oi;YH1se$b2a8~N-wLP?4T zjIUYfsEod(xYKSH9!~zwYA8N&qoF0Ts!W0UKe4ii3>v-aeqcRgG8;MS^p zZG&q<(kIii4JMpTGlld%E4|ry@6qR!4kuhf&G;)VUSlT`^zcH@@UM?T^=C@Yq^iA)&cw&vXb^DVqPmPhUOTiAc)1Zjk7qz|X(~D+*?@AIy zvK>>83+aGnd7vx?B!?3p;u<4Mxt`89h$L(UubtojqV?DVZyR`%@CMlZ~4ug zl5au;ogd=T0%E}l?gnlq{%+#1Ti<@wsp^uZxA$odvD zGuP_#bHd%B%7+YMc=qb9zS$B;O6|vR0>EL)Ez~!j;ds)=bvIy17*bgPu(%GAb@ja! zEjrwhh8zC+zG=z4`Qb<84(iVsP9@T&4Ncc`?Hti2Du^FAd6-VNIp>BKPQNrMr9{dS zHHYMUdvCoDT5kw$+92n%x-ek4<%L@yD1e{{(+6a$&MR7xR`-)^GM{JaHg>iz$vh{> zzW$Pe?=JNM5N*Uy6fk)hDLei6&J^5e@?|_^RmE+lyWgc9T7L+=fIR{HMfc?SB|&{d zxU_dXDCN6?6;hp19?sRWqLY8ps^S_3JzIU6uZS=2SUGaE7 z3LB0{llMu=1@EzJy0Db+{UL#**n>BKqapuwVnp2V63wVhYy$rkMfEh5#0t~|&f8=| z;5(8zXSZ>^3rZm~qn>!Q?S)N}sNYz^kc|&qB$|QxhVF{O5XTuS8Z!F?tx%kRQpZ~Q zSjH5Le7+-Xad;}A*t<}`GN;DAw|-#N(HG?&q+$Jfb@Wwn2o&J% zyMW&fJn`{<(#oHcr$`usM$7^^JUXAPuMF96{ zQjcUxZrSy>kEY09ND^Hj)NtIC!ISmf4{CLzLQ8jyKmE9C+k)vdvc2mJP*vAN19b$~ z8s72R=dy|odLdS>`_~rTCr1x-bUW5aSuW*Gkqx2;G_A9BKRNqat*54byG!NkJlzNO zHj?nhi0PXSMG;`wx`EB9)1yyfe`IcfM3})_H939K@7%?NU ziLKHKv+H*=aGgJ=RCb|Z8V&De%}}UL2!0lVc_)k21O1@vWiDwF>o;r=ykJqy-s^K z6))Vd;A3o)e4?-_laiPlcel!{mn0m=Yz#jd2v zWJvMm!K6=56yk|`90Ki;PGHPotatwZ@FR+p^Bqy+!xk$pfNPz0C(@PU@p@*@k!nA*598|+@LG<|8PM_G(bjSN zH4FFYfsj%%_`cwaX?_2||C^7n(s@^{L&NoaEL)lt!O?YpZ;5w8#1L!J*$gc8m zq=5!9?mfHwg(}B+4JR!*L2Qw8gp0+&A9RdA@=8g6Q`C_Mo~m7^mk$+QjghRDv6q)`+JavC)5QewePTSHCjHe1LalVM6uJ(8C6WRUP5s7X%S zrUQZJQaY^=eDUI%A)!4xSX;1V7K$I7GI92c`Eng3>;y6ZM+L#oDF?H@QqX+={a0&Ewr2Gg1}S)i zGtiEx$aSpe=o1u0rqa5K#z8k!hd?Qrb=pX2^gHz8C|hhQ3xPd8hC<2_#rf4s2wdGz zpRY-(>N;F0USrR*8+y0Ecmv&X_oa6Ij$2JCT>m05-_0*kg>a4mlC9Mi%)GhLLy&c$ zq)+fM>)tK{vjgkj!661r?ZAtmqSw!Se#@X6(2Bzb3!x{V@qVZcG99jZA8*eS>f==QQrjHF3#Kn7@~ePV8)<353B z;2~fH(n}+|7!~9mi$k?PR-oq*gw76#QZ$lYpQI?X*(sj;K3p zbf7eC0P!biAgB0yrb+amDxA@JhvITGvL~22q-`lI1F!fLka8jYsnpg3pmbWOhVk=f@r&MIrpB zu+}wjk>yO4(2%=BfZ&Ax^4p)^d6r|1;~b;qWpGl#=#vh7%L8JA%pdG@{TrSE=La z)0mK^bVJThfGOX1_~1J-=(!%w`?O&sk^Rkt{LMUGZ3dsa0ykDjU-#ZNF19p;n zrTAw{{FH*6`(j~;mYsrEEXjx-r~V^<{?BY*)S@hk;sV8nJf%ye<{Q2lXguS6^zR=+ zKFT|NcyZ-(E0FOH(ksiw{o%m>5tgraE=44(xd?5;WSN4*$>AwZNL@5E*lFZy$*UC;H2qAG*hD+nqJDy&m6b&%W zXs9p7yN+l$);t+qJjF*FQJ}h=c56}KegfcE9%Y^yqzJqiM`4aa{;Gm<0`J~Y{O@VT zaPG=Mk)GQ{yZlm4VTctw2Naax=?qE;1L46(sG2-}{KOHhIVMW5UVglt!yie=9Tg zIR}k%7Pdk`Cg45)OI(n_gYk)dY6lbSG8TuN-t_!=OCTy4idYP^Bq?(CIye7hTgT_P z^oI!C5QpSh>hOC&@D?ku{s$w)hNh(Kd3uPd*qgOFNz0|L7E306cS z^f?sz0oUv;&fw9ivbd;*II(q)@zR1fN2HKe86~9Cco!zPL$Y^vebW^sMA60pIGH4* zw!hQ@a@G^vfeQW>TnjHgmdmKe)z}mUaz4!=`iF?e~)%(2`E}4KiRX^$VGkS ztlj;R^*Nw&4uz6FK3iOkLE!ib*}aF%f&q_zUDE9W8q3-NyzC`Di6uU%c4k;>`WSlq za1KwK0Lks>2h?GB!`df28gO#|A|5oBvzJmN%@6nTQv%eMcn1EU{)$YyVAKt4oFJ9m z9R}RZ2=1qZtPNW-lW4CfMt1mwY)iOTK1B*31PD-2?#30j1be-28Rs8u5N!#k1-Y3? zme&GzHG;<}A$_zyHq)z8kjU$P&H%UBy3U!hJ=0w8oXmr1I$VI)@G9`_Z~Pr6!Lug@6>n}wdibHrMxhc?dC7#eMu(Juq%azU1EWhRr3IuVBy^*@5g8(50@588 zAt^9GDJ7>MAT1@|zy~0xwx*Ky8C|aGxpr)cY>>Y&-0fOx@3YA!fsedNw%5Y^k4npExK)&Hh#&oZ~~-Us$0)(ZNScFbcdU$m3T z>zSFG65z-ce@-kGD;^CkTzD3Z|LNgrCS|wY!Q|eI!noB2Oo-bSy2$6fq#Y2<>r}-V z%r`nV1hb>dSvb+F+-b|&WOtG&p&VrH&FdWpYDf&B!`tk3^lGMJQKCdOhEB$kk-`6#k4>iURj9F zzO~KKigtIXnup9?ft1peAcD!A1Dl-c0(Vtf*>C3NyJ|LW%D;G%wsuYx;ZgXZe?wYd zIj6487d{2Tv4RbA%wbSGE(2G9y0ZA8?&pZhd{sSfj*C;+YL*K#1GBnmeHshvSkFEdI5C`1|6dpRFkL<< zHipB5&{i>N4`GIM)w1AIACY(#R}Txe{FgdHtwtdPbLj)+y}!wSk3(U68<1w*XPaGU zCam{-pDf6SlqBgj)=~)(j9~j`gwQo1^nBHI4)l{U3;4N2r)iV86?aPkVVZ*Tb1Jyo zy6_o-XZ!-GfpE@lkuSo4b8(AFFni01?^ytq=jE3R0h6gk`_=#JT0*?0ebHfh-^NvO zj~nKiHp^Kg(UW*bF^G!T!Poy>dThVu5|Dcqef3aFn|o2`zC4+$Ns6|OwuwmS?Hfv@ z{E`fpxEQyO)ufooO07qt3rl60GQ?R6 zeBKDvXh3k}j;Syp--_RaKx*QzgVub-01{m{hq*k>l(+!O7jUq|dAn|#gfmx-UNEaa z(t03Q{J97&VXp;>n5qEl=96s~a+W_>Wi6PI)Va)~XgI4WkR@Y~P>b3Wm(rxI)Tm>I zVu=tLo!$kjrsy0(iv!-9m+@#n8?3c$f72x-szgcmdaq*Na#}g z0TFB30DT6^#^;sKCR1(wC6p+WLn;qi^)Xr2btY%Bgq@$fvc|-Eo%@y{*M*-fL?7FH z`2~xTt-KqmXAuqadYn+fmZX#b-^;+;H z^MNGzdMB5IZSf>~3XSfU4ruq@hfnh%^vJe5sTe~veJaNIB~?>}hhNZBejoF$skrM7 zvr&-t2CGdc*n*VIH!70WN3bXo+W`L7n3s(?1Z_gvH>lD9wEBgr8JzTBgU#$a#ngEZ z37_Ewy1K?Dy%kY6wq0o`0Ph~?=0MH4Xv>_>OFZXw=?>NOStQKqHBQf880fQAPdR!B zH}tST@tQIx3rgYRQf2dpVl@yH&um|O|J?5Oz&eiBR(LCPiA7YpS>4b&Rn!Wq=(WgO0%~X#ZV_8ge z)^OtDAPthd;o&4c29i3Ae3uW8))|j_C|vLEkZ&Sdcir-gW+*hmV^Un*6uo3BnIfDf zBl}rzRX>*Ako@`G#;~obo6Hi1PT^$;8Fn{q^u-t^^UHc0$K|9FAO)rX0W)o-*#1<; z$ftq^Mj07a+V>i>t}}A0s-uG?JR69gF3%PP?iiyQwb4TO+fXMw5tnG_CvQqvF|4I2 z9bPY3`pmyVPC+@%Bb_KTv0447Pdx zp~C1P)#^=7ZD9dr;G2K!2r#ENG zK6vDrDU&?3X{sPy`W3`T%tb0rou`Qa|5$5b5sZQ@6>;J<70q4@9ugjUf57!i4K=g+Y~M^WxR|!o}aV zdD3$^QZ;9!DlJtnr#;i)5NU9xq7Y^Rjep3qaFPjbm3`-Fb(;V#rpXd})3{VI=zdbP zw5h1?ZK6+zNe&dmhx&H3emNXvK^!dLaQpQnMJO9Mrs@d#g5NZe>}}+ACRjI@B~_5v zYgY{fF>crgBp3i}(d;K~*IGMf@e3(o!h*3z5{7i-;519L_Mm;T9H65>+FagK4nK04 z_hh@<6b;!_$89=SXyP^?+hiXNZfgyTcxJdZ2&0l7{ZQTfsi;(gm;oaWS`8lC5Szkj3W{M{Xi&OPgcrrw)}=c7m*)fM>3@o_8V z!jD?s7t7ziz^{sesPOqKOkNa7mmw$mIt>vJFs2FElF@j7IgRJh&i-T?e4R{8ED@th z9r?XKYVLtyXo6CYwl>N%%M`8ZtBDDhCV-+RW|t5hzwGgU0Y73VVAo#_w9ztVBI&$V_ zW#`eaqR7sou&>{xs=gz|j#wTI5x)%CO3l;LBu=x7Rk}LQ6lWO90PW6tu4D5Q+>?YU ze);UfSdEB&fNpe>RJQITbw9pg9BNkG3JtM?4aWF(vH^90ag3#GH*cWB;Bv@xp2&wQ z4dh^))8>vDL}GX@ZEQquWI84pK1>oD zk|MCrSWlD;=zoMS0#zy)9}tXWTWGuXT~fjBkCJ8^Yqr z0f5hIzK(${^*?dW_q#TkTc?NGm(l913W0?PsiV;acYH6;DXs+Pz+LlYe3P=v%2%Np z?ifm^nyD3I0~9*;VzwEp+zqt+A_0{Q_hh&fKB8!p(X1I<4zIC!dKO*Vt9wp^Hm?ZD zvz;Tr=F2KUCjj80RZSvQwP8`$(J~@by1gsnv>_##3=)woi9Aea9Bp$fpTJE~cCs%3 z>$W!x@ApbeGmT;h5M`J~@qTTnCVQFO?f`shwIM~f}a{>aCwmxc#u2$yg z=joeWkv=jd2Vs*XT`#UNI$y{8Z~_zgy0mM>!qm{ECSkk=t<5byK-xs4@-sVNwvMNIm3PEm|FIjT_vMcDX40OlE`gE6bqi;=8LB{m%7n4sLtBq%b-Hk%bi-2IylZ^)#Y>)|S6>5CYL znm1`=k0oj+7jh(DK?)tyw3>MtS!VdpqV`wg7Qp%mk9y@TZJ&Jp(z>$HxLn}q0Gf7wv?TOO%al;oDwFuQx%IsyST|n^nQCt@jaQy#&$(E$ix7J@*yXBp%uqJsU?_d_!5ztLcF0?z zyv~>PtzNM(KAAegA~OW$#I~R=)YR;Y?Ds~oGHC97R3cD5%z7^JGDB&b#z%N|>h-mv z!2XAIX2op44fK^TSk%B9z1wxuJ~hiMRC*0}UXLe8^}dtT#Bnj6pO7uT%zHUE{mU@n zO@HIQ6oYI)b^i@zch&46y-A8AgPVJ8>WJi>>R7P#8=`I7zWB|<@aS}mCObL|m0O>P zfnZ*^p%;Qs*t^Xwov@9)25xQW(%G#h_V^Y!ie5w|H=TRYr>lFC%-Ker^E|2&%u3q= zAE}g>!qq5pIegJ*;2fDZyd-vx?8Yy)Y&WxYTRbK^;Tyjh9)>-~$nV0Q&I1@;gxkCE z8{7?{?*j$j(-F5wY>;=QAs10kL9%ZKi@Z-Xd-dUE(b*)U``=6+Grr1szxKU>5###O z^R%XPu>msYy0*>Em}5tlYvyZX&!+?ocDCktsXP^k*r<5+Qik{|y(v`?dekzQ;_F*K z1M_crY?}{Inu-rxe=g(+0chOTRT7HHles2}`Y^q0(tlvosW4X|oI~Da11(MGA?cPC z(@n)t7Ju>bM{USGJdYwI6$ov7WtOe+ox0#cEGTz7&4Lu2V&Rd@ZFi@CAOnyCkr|$ zl2PeA$M-EUE6@2~7Bjn=s?&CrF3!rpy76Xt_>T02(YG9+c@HsloPXi=uK+-*Lr>`vx0;27>N)Ci;o*wwjCt>^tb5%(9;`Y1%n~ zyU`Nrhy+Z??U0Wv4fUTqGVwmygsE0rowFRCu1lnVnK2v375&VE@;!IdkRze*7PEh| z$Q9z-nG;Rn_dvpDnoAFAzyE%n5eNDNGVeoS(v$O0gvV?L5 zqVJxyo0V@9@}*=Dk?9%eiI9Cc_R>gcOLsX8@AkRB*|4I8 z)6ZS@I&O+%L?(;eylQB*=rh?%{xel5+iRBS&1?JO27`At!D)Hf7aFYDcf|<*$(Ysa zCScfrXtrm$TIfSD8phbT(fu{nWTHonXHvmz!-hS3}38I=j%Tl@8Q)INW;D-}% z$ro8lOJL8xLW=ZUXP@~}`C(H0!~CIud>!|EaOC7bB2VkoC)nEY^2sz13`_9gLd^o9 z*t5vti(TIv`r)@wd|()vx@%OuFjUDxfOkwW%|R6WAloC$@nYYb_WSACXCVsLw8D8% zKh!(t@7*)CS*_H8>aQ!5f1l)3S~c!EVn%6#$5gU^D3bq|D-dL@v6)v=*^WvjHSDm5 zP%^!6orl_$E(^0Z8W*aUxr&0Ph`(|hiiuBrZ#FgG{8r{>wOLvE6L~6tUi{+d@vBO& zc+wN!ctNoVY#f}^oG0m_LOs+^crBb3=XL3%qB#1fRe^O*`oIZkjZrp|i)nVSrEl~X zoUT~!Y77h%brTTGRiW}6%ob@G6V;L6WAdJUIgS&rlsVp%= zcm^?}b#0!qL3uSn=EO2JQb>(BO5fY^Qei;@>6rz;dABPif%lCAuch&1$DQAD1$`Yw zX>ER+wfSyk9B(ESDf}rx=9K=lytAw0hM;`(XUIHOM3nP-si4?S=-be9Woe-T!hNfn zXeTg~kJ&@d8JWkM;t(@ym9YvG25 zevzO=!)ZPZXwou4Y_|y*d0NU*U9HdH3y{*wi3j_ezAxXBaw9d93~KGS-;kuAx=f*q z<>apZO2BOJ*zf~MnY7J>?oNWUYC!2nC4hYAr2wF%b)bTpHPz6cAKIWHJVoYjee+v3 zub`_jm-`09es0s@1>@COI#_o{y{da|K<|&~>}8_g^05KaE%?w_YSY zNu+~sCsCk9ExF7h@77#r_K0lt-Eo++pF=9IU0jwit019^GZEB7TS=~rL8FSDD6W)! z@jz7;!__Q?&}1yw^45kTCkasIg3W7){pX{kQg98DdEj#7vyG;=q=Os{o3LfYNZOSl zDxuTZ2ul-EKaT^L=89_)Byt&OUNOEDr}wruO~O{VqN#w6A3LsI65l!3crfARcW{w? z<-7H@(ab}ryhiGf(?BN-*fx01y>m!2^Ze>lSHjkT@nlQEwS^eYVUz|8(dnR&NMZ4>N_$a%e1RwCYCvqyZFv! zW~r=8Dz)B^5uv?i*_?G=7bhOoqq6H!2NbZS;m-q5;4_0<1l+PmG(wXlu7`ahM0S+(S$oyU&e}+XHfLFoP5nB!tZT8n zFXc***qvJw)RG=Fk{)gO@WBE9wtA~lQYopS&WF@O3(+da8eghs$)4og&%=ZdCBZAK zQ7qidoBGBe)ESB-u1{J}KesF2PZtYk2F=Zd?&_9^G}mNbb?`{FQ#?SM+H+M>}8 z!)|Q2wZ*Axx+V#b(;R?3421mAxI|Ajw%o&kaGNJfEWtYqy{uN+c;na(2XTUbh z?djq}!Xp|ZtzB7zsdlap-0Cl1>f1SSHsKGo&kDtoO$`_el?9C-gzLTsgsQF$%6^Bu zid3jE@)icztAb0mql=o|*AQZM zB(2KaCnw>It*1Bh=w}Pz zd#OTGd``tcdGEp(IhvSairqL1WdV4{=XXL#;cIiY_-}NlnaFvu zRLS6xtPh-OaBM6U6x6@F=4#e~+Q&h}U zm<`H`(l7>tzuwynpJ`@EuQnmm2sf#C{oT0Yr(~%?@lTve?c$3!OTO`!WBSf$J5KNZ zo)u643b2;Z6`obPfIt}#A1@7 z(BQiF&tfK;{|G%^Prmcww)P` zeZ=I$$ftk^OO#!?^_MgqQnQ z=PF#;3F~jKI1{7`EB}`7!vl_k?Tf^opO~CeI7sareC~WN==b_vCBsj0Ga4?~#75^> z2}YGFJX=^$Ge{ZRemuLe$vz%0d`)gY7rv)MM!!8M_q@wYBo8dK9W6+CeFloXaW$u= zt8%>Dx=T+oo~m*5JN~ph5;AMs3gZ2WdZqJHHsg)DRG#pRJxoUjsFH~!%%!BJag4?_ zC%_TeHwQK$=LRG{4o?>c>z$Oo?0OBfIy#OHeRQT>^_2^(drh@0wvQOJC&jX?eg0DB zn9Dv7yz_}qU2rmwDn#X^9-pSNcLwzeE6+9hJu~znjy76EWm2_t^GV-j?L03w zqu#ZW4FNz-bWG;fq@+6fKe8xkPGmhN+9FW7dvMjMiq*OnBgVxyGeT_eR_G1Iyw>%t z@V{oMK)g$+SMqqSiG0^Yi{rBzFoCLDOInkPeP>FYhp{d2Opk-=O(r*z;O>LL{}9zs zYTzzFog(z8P?cYgJWxe;Zi=C{WOo=nhfT^dk}-@2F)o+*Do-sT)P5+C_esWn}39+EBhBA2uCZ^S_YpbYdIhMTU+VMj2P;p>2 zt{+?myj?mDiVige9Dm)oUN*bn*}G(vZe1s(S0@H!+V%ckDy9M8Dde{fIKy>3Hf{V1 z+<0KT9X(Dt&nkyw_Z+f=b4wREey_IEf+Zd!H`viQS#)dgaB-qfW6qD=Q2k4<3H=1? zTxcXl8lJKSE>v;Aw^Td5L3m?P7?mHV%?3Oi-Gb$oG6XPC@*)pk%=4v<@QVx_PT-SO z|1~`hzI_UxK~Xp@xJDnIx)`2}b5MlGOO`P5^jF}V&{9!GXUyP9-%A90{CmEfEN-{a z1A}IMEPxE5!^)El?djhuk$#_Vi0-Y5>9|sA?z>3F^6l-cy;GfX_^KpBNdqtqX?O&Rd+BBGF4uTE?U_KvJ5bskCG z$zZ1JENMJwmy6^;bDf%{cJ25kEqHTXGA8aE-LH`WpVf^_ zT+T4KaGdIWs|CeFcsQf`I!MW!M`yn5z!kHf3V2cWi z{X%X=uK6)Z>6qf(IjP4yX)3+iXLM(`+WTK2MG2&w-GtVvo0kECn5$<_cVc)r$v{%} z@XG`Q&x@x!SJ8yNs4ppCdqPW-*y+wGZK#1NP6WMlw9|qc5bZb*60nDlHZc&WY`4B{ z3k}HOYq}^vCYtd(A^7HRs)!5L0H{3e3J`<&tcHmG&IBrtNgRy9kgFozBd3p4iC#fE zx{v~@I66-34hTd)6b1I~Lt+bSE`n|mWxi}-0IXwq?0=7iw{CEqeMI-4p_)?pXMhV! zeh(M8&cXk9{?Gxxs!tse28z*-n023pj30CKT!jqQ^B~3VJRza%9VVHD5rCbRs{cRW zqW{1OG#3X^>TAV|1?+0rTsGcka~o&YkPaNh8Qk1T_|>HZ=rIfK0|<1jq|aJjg= zvEm{6Q?577p~=H{$B%oa&0i%+%-*$P_*`*-k|~WVrZ>MJw_a=|d3H+Hr#GGak42=pXRHrU9`b?uMS1 zRdXl!Pz?%uyQO^(kXZ&P)W4ye8f+U#0k21VN{GKlGIIzJB-_+Ay_*q#9DUS15|Vp~ z9V|C=2GKz_$f>uKOGXekWBq;MWkL+Q5Ldh(D~z9z0qy!Y*@33&>AzZFdSv_fjnGyRm{|YmhHaxi z8K{=KJlqU}!_v?;Pb9_vU0w4iV{yb7U8{`qj-^%c5;t}XIM`A=7xwaTm1jAPw>Rvl_Q z*hoWvypCuWNUDqx=-fGI!>=anU2uKe>*~5b;!Sxjh_5j+BlGuIy96v$Z6rEdHRIb2 zagD=(h}iETIoe9V#8_-Uc6}5zz9Y@&@Ov!w(=+lNI&MBjM!mq)F$2R7J}qGWGGj{j z?*?zvUjh_V5kISCuWb29{iD0r8y$`D>tnK38Hs8voQjS5qd-H;b8|<`Lls;XAC`5i zwz}${26bcA+qTm`Ik0L73zhBgX>sdaiGS>V1>_b5_mW3rAOPoX^SuxJbl%e={}h>6 z_J4APdGn2g`vW>U{-vxPv44d7S!EUZs+Rx{Iy%aLQgm%~@_!4gc|_LPoT!4ZR%s8P z9*b%$ZDOGN;}EYvOLuD~EbAtLxCOn>x73PG>!DO_Ctxa{j7cluo*?CI6@)ux-4Hhy zl~uPrqW1Tsh4q+gt21Us1?Q&{Bvc?j#2^39{-l1bo0x}>7~?U&OmUVf3o!vB|1>fl z>JndLmA)0d}X{8)hkPu0Gt72u+x#?_0~&Mc?7v+w zWLh%5i&^7zI;_I%kM(5$4Fz$jyB(~A+b;J^i$}?PSkwi>;|l4G8w8VBlvGkWtJ-vI6t^t872W}DezPmR3p$9IlLztA?JhQ!XGgrG5Jw^J(wpz zX#rUe$8!+q)o_K~qP8F=LGQ>5v;K(jC8j)vjKxqBTS2(HANnpTtrY3$-KLQEs5eJP zmj>7~rHWziBOI{3gwwk12;NT{GMl5dge$g#luzwU0163$CAdJKAL(*|?>(4E!+5$D zbsx>st%aBr5G9UaKV6>3T!81yvL~;?Uo`K8bzewj;^SC4=HnA;NdZP6?1o1~gx{f; zT~T407wC+w#BmqswyzX$6rc;x&$ehmACku&+t)phh`P)tK{!QF$ZR)(Oc)fpDiA9{ z#s|Y)ph)H8>%eqj#(|OjT0+~ln;bEAoFm`nktT(=Dk0iYaai`kLQrUM=?wT>DrD)| zqwdRec~+~KDFPH08$Lmf9|5DC|8uCcSjt-qaeoT zi>NWA0)@J{4(b*^)mKtc&dmV^0kHm{e(Ez~(DibOC$YSAIJyg|{CuL=EJ|HaC{qTd zmnH_MXKasH!I1KboC9sS?q5~AVVR=Wfc8{d;R1!4XZSWeMdz3GU}*Kt$Ut8|Gjlu@ z(!i8Fi;GIo?fm)p|n(kdaOiGFYf$D&y8RJwaymTlsyq(ndrSlb1RO;L84v=(8yErtQaC#DE5~@*_U&uu zN?ln?_O<)}*bWX3UNtW+F0QYyPfkv*uCBJWww9NddwP1nVDRDLVQy~j%gf8n$#u)h zV_;uU|IWb6@Wjo{&E4JI&iC)HR*#R5FaL^fPi|h#A08eqFE9VyJU6dAzPh?NIKMl+ zeYt&k^?!VH^Xl!3soBqg;FqB>RTY(v&6n2Ir<=3e;GxjRvxnZDzK7MFw)KBsEx!8p z`1^VLS(uq09UZl|wPmGdo*W;yw6^y3^=)iy^sGO4d3z1+4W*~2Kb=1Y^ab{=KfH`h z4j?l}2BkvRWo$3!3|O z`b|U4WHe<$$HL7V+`OB8f$G{4$`a4d&)^DoJrg~bz_`@9p^o+rB{Suu@~-E{LQz>! zd#}*1-~C>u<}KsDdenKT+iJMLzgsw3XuIk()Hhrl-x&BBPHs*9S$lNMb$WSjw@I~& z|C?ZDW%ze*_@;k&c-Z~o_+sK>@)!)>cXe%>Z|~XYU0zsr1G`lZRolDRxmuZbu69L) zMKn$}20DK0J$yO+(~~-ymJA6ho+^PRL5)C~Dl*dBdt36NqR$I!Y^-cSkf8h)SY}Y@ z%*6E1K(qC|^<=0+yq8aLbX-YSsc)2@v!bG@lvI$KT2@`Qk&%*<&$s@KhpWqc_aOJN zzoVn@vP5m|o#u{uXv%`4BRw7c{nkO}pH7&eVSip>M@CL{Wp$mISwvdI{>I))ZBs#k z+aF8I*qqoATie3?!e6Do(kjzuD{88%e5a@4kMm$qIP~Z+GqE7C1YR;Y5IHv&l$({i zy_GV(eZRW$tD__M(!*nY@9yYm{PAJ&?%SC?l!mv2c_w>9`<46tdV% zYK@KpqH^Y|w?`3n(Z+IAXDVz9;DQ^1>Xg@Q;x%hFYGf ze)BR9JWd4X|JjiLX}{r@?-3BR0!0uJ-XkKRAXp<{5?-SsAT$Vro)#;Ac9X^i(BzRZic{FIzZ)80B3^fi;B?5VAuYfhJ7h zs_&u~XqhS|4G|F3>4*pcOkNl^#SyB< z!&7egLK(FhUKdXLY}3dH0h{A43pP1dwVD|tZUsTQaPdWx1;%HGQ(La~57=0!&l`u! zRWIvbb{p|8)H6g5u=+IP9zTuW<%rYvF)-qGZ(Us+PA<`og1MJsN*pePlq8H=Hm`!em%(eZ}(ggHn{FZ}m{z zCnjM6^DQm`lRNj5#Sn#?DisWiYBuV~~TFLGhwp3drfssP*5W{TCa*D`@y8s}6=tHQpPj%9;z z;8TBhX=60uW92N)eDTa>5PYi?nq+_h++tN}rVX604$#6(l7bbNXeGd}Cz4NmYC*26 zN-OzB$gkX2Vetfz?1XlhX!-ut|GhMPe@x;(Y|NzMMo{m!)Teo^eJ)w1BvV)~DpN2p z2UMiBoy669ZyBK#!Q%5UCH-IJ9MFmu12birmf!zz`)c0~>iLfro6iE?e}{qsaq9fb zeC9ioWq=*k|DBmF90G zEEkEQYkpJr5t#QUh=#OYX%9j@v=~Mm$mU4~ujWXGb~Id;ob3F4e+_2B_>x?XS$#&u ze9~E2A3X#`O!%yF2I8!uAzcR+vHkG?0pi#lpV*_sDi$=E8|K6|xxrgMm17b6i^4x5*t2Z>dq9FP-clp1oWor#HD7!lU@ZV*b0oojIB>VV3zcW?)-}Nj5 z8B|;;i5bAR&Y!UVtJe$6pc~ySBKn`ehfB2>%BB$hD=GluOaQ@5r9>&R<{wBczl4vQ z4N%C}lT{BTsD#+Vljz!$Y{oYSEt07h-%8)uCL#moskua>lgZKB>N`ID%@4VcN zo*$~eW8Yi$Gv_GB_H0%p>9v2#(`*0v#I?O!s0W6vJY@mrV{x$%eq&smSywY(7eoL> z{rn#Mun+_U#l+YtrgaZmOIks<;+alP<%kFjeZ$9-U23YZ=G|$n1J85(c%(Jjru+80 zhYqG|6LR>&7SyBe&J_niK+%!J{Tx4QiECnoQXOEKwX{(#wrcWo^(bB3Zc&0Xw4*;- z4q{C}c9P-97#vv0!bA~8GbEdUw&@>v<^n*qiTXqN$y@B_j2{6mMf1&8cicwjylR-q zKnGfvekz4(b6auUUxkv2Q`>9n>r^YN#mMqrT zCo)J6^Jx#BH?twT#Y}(SoQXY4r?*b9${6{GHad)vxivHT^_WMprp0Z+0A9v?(8v0S zb8a89GxM;dM3Gq!ye41YFFn<>J~1!^P*fm#s(ykd9qZPOZi0`?9ZEWeIxowe7R8

sK(r~K%rBMTS2DNhIsfn6z_PE*`q5_iC0%Xdeg-%MJ(VCXWh=?^O4ENDoJmJavRxwFK{UhF zG%*Up!$}m(Zb=E@nMHZofS?K6q`;+l9uvvv zP}rO{(*=V;VNMJ7#8MWH_hkIcj~A*GZ6F)!kCcIZO)-V*3oDwgaci~`6n@g^d98?$ zVAF0J;*g)a(~--U(oXAElRWNZ+DzxeTWv9IJ&dzL(91uxF_G#yApiL$Z{tEUMugwE zh=d;5$Q_dCRq5Orh_tlC^;Ecw=UEA^m8tYf@2CmjjASXl<~|<<26dNERn>5EoFU9n zLy%;jRw5;@;~w(MPMT)gOgAUz{G|W@;m<{yHE&RrtQ;{;x0rn>NdE0|ic$uK; z6@)m)2prQsAy;msBf?$1 zIWU;f74X#uLM|AfRKd{;pnHcF(C&;D@s_(?JXfpQ0P$xt8L@=r0uLQZ36bljJn=!n zt_AEPl&A=_2ia(Sp9Jb(r0vXx1h$WF3Ad`D*RnLmm0b~b6rjrkE`0p*~9`YZ9_URX`6VJ~eT#7>08NE9_ z+4u+dww46=Gf}unfV;WPhlAs#?mbK0a5+4FpqU4YT*?&9Z_5b073P3H(o0!jfM>MBne5%WLOwo z5$?$S)`S-z+mDVXW7L_Ibv}HO@sM-YO<9^LF4R)k=IMJq2l*o6T_y7kIDP4p*!GHb z)Z^BfzXjpM)k_F{1-NQ(WdO|g`a`j2+xhh6*@>vU838$`9ltL@ykm$4+^Cn27Dj4u zDV2Rts~Les=57Me*;UX_*Hi~a|KtZ)CV}*H@k@8@(A&KJ2?Islls`s-WDn4qQ1=M& zqV=&6O_eyO%6OuUFfyaRi}&Yek3k}$<9UT(q*tJ6Nv59P^v;w06U@Q?Iu!3CA=3#| zw6Hi!5FfpURQVs>PXhp1r7TZk9b?<~tr~EWiGGKTW`I_|L_gbFzmgI+=jJ z3ZehIn}$AxhdPXmYyd*c7pN0KgB_L>{DnCz zDe1Fi4i(csL~`Bw+eZ{}jnx|Wgn7H2zuq(Rm+5U>_cxNt&rzTTWANqUB^rN6Ap7!} zE@1j47Y+^(bp+f;PlY2yz>=;r6Sk~Z4V@I@{Zm0x`=@F^2#wU3Qw6N{4_Wb>=CI-o zJA?eBLE3?B4a@|wc&8W=#SD-*r!h%(HPar=h=khdtlE;mBj&D1DiwsSEt1;PPUP>vq6(m#baMSL}n3co_geA~?0tPo-SKb+B3oKh-$~ zWKKkm&z!ZGFDx*G7_in+nq8zqM-?8%pL2{H10+6zKbCf7Is*d;bd9qgex)f>n!JV0 z@u{T7Uy?%gi>oC&n!gTD$kr9ffb|J(S8jKUBXd0ThR0&{?mOf2nCG7LZa-}9`9?Xz zvfBuxc36T1p35LyL(MFi>~kq^J&=-^fnE`NBPf+%1F|1iZD}Z|;)Zs~f?rzn4eLH` z3iJ}py++E_8&iba8<4&f$kfyj!eml9Jp}P~JLGrtVA)3(l=tV$_!wM&>(1LC8k{T( z=-lX?>+NX&iR=iZxkgA- zzvIlse*`dzQFK^j=lvet$EZWDn_NKEt`QC2rvf+Oi{5&?&N->?S6TU5g_f*{8v6?T z_VSAOCD@_l3z=i>?5T>AEl8}|W zMLR83@8Fgj^iSBoZFJGaD^;L8dLs>g3}4f23(fyQlmdK_B7MdGi5$4>zH7(-!V8>c zi2_K5X}$T#h^Y#GD}gQ?QxI!@S@?56{RStcZq#SB!9M{c^L1oMwjUqs@T5_4L*{p$#avNa{$9(_IKXQVkD-gS@}C(K7ee^ z$9V6KMcO{$tIPqIHhNZ;k3tBNd`ISQL-<{e6yQ}ZCPOd~6BnwV@UIUa@s-#XZKdXQ z0p?FDIO%|%!#z8UzjrnJ&Ll)}YE@i5V~tfx>B$io)?p0cDMn03_xbHJ7^9K#PnYQ6 zr(BzsSR97}o6S@&@1n-a7mc1-PVjM}c=l8x3A>1I!PGH(+ufOIS~8ONx_8g6Cm>J( zvhX#pk`hWFH6wJ;&1>#y4%?qLnC=!gIRCSwCd7@zdNK$p{cMb`@d(jtJ~Oo|R=xxY z;O3&&+i{AgBK*~A4e0Q{NpH4EM)-k?FhDL?QLbsrTNA%D)N|=t)SI@ng9CUcjjqw+ z>qy@xGAh^$mM#ByxHAGt@SX&xcDdwES&ET~Ivg6XV?P^;D+xL-vL)>>k8#6Z@vi`9 zgIhH%q)tkGt01j+g<`afnPX2=%ur05Fu~B@aW4?&nR}IUDO<+Zu`m^!F7Y^* z-(6{3kMnRZU&$(B(YX%8!uTo{Q>_%)znfs@J6iq4wNG0Xa}k5azn<^<2P!x|>@TA4 z_T~&fe_0}?avkDM_SSD;jfr?-W(03<^8b^VU2@rEcl?(Q$`T2NJm43!KmAKHbZopH znH_;NKSoEQ{bPdJ@{J^YR(=mV`=HI{B}~8DlZiI-G{H0WD+Kg?hWE4Tiz0A*POrp1 zyXB+q$9MfEu@gBu#80>HC{r6Iih`9S66ew6I`dTiST1b}lfmdRKkCOIT0hQ0s>v)2 zTq(-xbwaZxii*o-4ZMfnZjIl*%i8GuyKe^^m)mg5OV81^pj2oy~Gqh;=o zfEAOwYBQxAlv0Lhp;RzOQdm9Chm)KBk|r6`KOJ=Yf=Ab2^mF*sNz8AX@{zdpu>9W- z$EN)Q)1@atSmyIl6}#9=e5UuFH^utxm+BK1>JTnI%=DCPM} z{T_YC3Cacy+hH@CfEhCMoO`WJ+D5O#m6{LM3a*CBBYcSmlp?qG< zZ*ulYy%F6NHBpx35T0S{0P`yV8p^A3$n`{0cf{=NYQJn~a4!-`1sW5>!tk8UU6yuH z9#s}UHoJe^pT&2MDHV_UEivm@BU8Iy*CLT7UzZ^K`6VXebX4=8D)z+Z@wkEA>+(Wa z+~XO33IH!UxL+rsH*B^}bu}!zb(!XCnMQKi*&7+#_@e-1y*fPJzaL|*E-+r7_8LF9 z*xRW0ccTlWaqiCS*&!DAt-1%sRrjP084B?Ha`kj!&PQqfc}LzIvSn+e;P)O?$>_e zIzGGlt> zf;}V3Jfh6jNVFmJswl+d9PwBR;lqu_sd;$jZ}oarfZVVJX-#H=QqkR4XIeGH04Bh; z5V;1yTOvbb!@>!j3{svJ=Xdd-Ks%m+yq8pvOmI_97io-`Assird_T{y3P#3#`v}%> z`28FI!-dP98e|l|oYLpdy&(Y;nh5A5+6ZB!D4>WCI8#1kmB98giA-2cKgZnnL)7b* zLK}OOCPuU0#11w`M1Q!eBX>+GnM_yf(`X^*5L3#Z;`XZUp6j zG@7?xj_i*MpSCtOUXBRw;!^&z6Q`CQd70O+8~&~shD{xNU4`UAiySb2E z3ymWFlLTt4N1EG21?RDjoeqDJr?|JtVG$YZn3?+JD#z$s)d*#fM572Oa<+dYT05<{ zbM@mn{a_a_x`;9=K9WBA=`CNwzFuHe`mF4^38y!qh;v@fxkgF9=dmEKSQWUu2Fq+J z;nY^K3bB#11)848D-mtxc6ADyG8#=K`6k}T7KZ&P@MB^N6y7|cYIi~W86XU@ow9QF zE)@)~GZ<Pk;%C>fzvH0Xd+vug-YiO?29LUYgcHC0)7x=)pvNk1B?O zeZA2_v1;Pr&gMO<=bv{qWJPed@-vmKD`SfnKB?LH1lFYApVN*b_zr9T4Co5~)71rM z0MxQR|CY&Hg!9dS{cR^JJ1=)V(i(?4{ZkjSYhPd@w^bynu`aT?v z?avG|`WMm0?V&;*v3d70zQsZ6U5WZh`b-qPbwVBL@!cgEml*q*FlW)r}CqXoCS5S?R=F#YJ zE&sr@OvJ{P5bSi0^YCL%OB?iBbqKA+(i}JO*sc#7iE6aC z?UPs;loS;v>nNHZaC!03chvudRrh6_gs(Q>HyOTHgPsq%p7PPN=vFL{CF9d!13je{ zP%n!=?CmLh$2SG8IW=E z;#Lo7Pp^0b?rp{VuVh8cL#BC=;=Vxszgg_C9BW36?%$qkRA={uS1 z6rot@R~4ym|7$u~2QiytuBUJW5a~r(eo^||(BlQ_jNu-C#vMsqyoVE^~z*;vt zJCYZx!D}D;Y=p^z0`L~ne{!8jGK{jDJWvNWO7E0vC{zSP zN1zj@UF;p~cDO=~blr~c$l7nQk}qkQqUF%{YuW~bi%10x`-eea^g4o#zC<` z_Owb9Y^8ruog!c__y!#`D0trFFa?(JyswiJGHz*t^SVgZ`3rk&p8t@D|5PSD5WQy{ z3N1s1rBw6b6 zPt#?c?w`-5(PTKxB>YHpKtKTK-ac)CgAps$s;dTA!J$zb(wpx^$&vKfq0Fx(A*J!|NUgJ zP25#R9~i`=t*ud;z|3m(UT};E;jd7qwxe?iJ8Xye5-UetfLJM1D(Aby8urj7;&l~) z2W6t{nY8j&;z>F@eWQn{)I}*7{~E@`&rg!_)F*eMot<0!lOLEV)4Gl8y*v7zfwb?O zB%W0${|&20`fSV3!XFZ_oNxX>Y3SlxV2%=WmrlTV7qwb|IU>)Zf9+?9j3ee-6lX2; zcrS)qR9nVi3TrUqIp@Fj$xC}vf#>v5ZXZ9AG~;MWvpJ8^mf>mvPQqAhoZ zwjIqvhDAHES?P8h-d$ayG{eR?(ufVF2(!3Q0wA22%K?0>wCA1WlxG|R%{(q@GW(@7 z_rUiQS$Tb~tM$tQUcct-Of1h&d)?|Ve|!&j>kvrX8Va5#xnKp$trz-F>$K`5$(adJ z%z7rFMG~Ox_zcua1$ydA!l{FKZSshAr06;Yc(E(&Cz6g!>VvPY7Y@2yQGbm{M5=u# z;C2lG3Al9#=13d$Z2}p4&^Kfz3Ogm9OVK!DaT!q{NI+43SQueKa6)$@1e7&aX0N{^ zuhLFgLZgn!*aO1LCR!u|I+HqKC|2%mxjKPH4 z6FAbLj1Aq)_fP_PsIP$Rb6roAJw-b#0K|fV2(0>;JC$gP8P5{FOmKSdNkwgVrt$gH zJjL%eqE{~{5U(A=Rb)lZa8R{zl5%q@4M2c|-qcDeo1G&0+XgbQis%hvkK2Dj$#_RU zKG+oAxB<^G|L$2F-JzglVxeq9i}X6sf0XJWAhbt4A*O|sM_Ba-RsA5Y^oq_-LP~LS zne(nuO78dpl247vNWf<_V4L@&m2*PH4^Z@O7DQ-JP|M0&eKh>+;I5+8)7Pl+xo5el z28bi${3LA+1Jr78?7a&TMefAUV$3zRD7G-MNT6|~P$BJ>$(^5==>%#7IdpeQRT($x zg$Gj+6JzEwKH#JuJ-k^hJ=*&{lJec@lA-J0O?rx8O2x^hx8K84+o9SBZWsUR{ASIC z+KGVRt%E?F2oS$pR&5D3m3)9cl9mWbJ*34d`w0#Qg_$l&QrkWEgem4K@iWTe;s1X7 z4lzhdbcH2zDMK*_&%$bQ5=P__rX8&vznrap`te5_MYpjGe*TaV59@dJ!C^ z7)Sw?9mm>Wggv!08a%D>Y<{tRznn+pDm#AX9KXI+yNQ{eLxc}z4@Kv$GMUOhFPR5r$7iyla>A|8Vo$LEN@g?BYYe@wB%(zVu5Vc9^!68=2P z1%}O9Sjzid&#d(e?)EY(zUPFN^@=vr18J&jWZ-eLi)GsJ>C$S85pcRL{7>FHl0DmA zdG($t1f;u>ip-Y*#h~4r zUsL=1w=*54)ZZ@-{(Tg7OZOBNs;@Win_#j~zpTa(MS5p-0sbQ#E)>wduR;P7860~D9FJ;1hB0mm4o}8xh*$RAGE_~$7;ZvB8uA!!+(J&5 ze*2j&cU(MNPj>zJS6E?6X*i?!CM;SPl}KzLD8?ZV5UH+F z+035M#+ziyu+S$3{$W-EsQn57xBi@dEzwx!aiv~DuXB=@DH^;w$pD=oem)cU&wL9Q zu$K1qSHxrQL}bW*K0gM5eqme4OFXF1ba+HO&G`NB*W|D69loJaIItOtlNMswto@?9 zl_G@3528-MJLLxEeay{b&fN4@ zfM3q8ws}?mJDIs888!8JJh~qU9p99HoV}rFY_2~XiK(-+^ieM`GyYCjbP0KXJJrR) z_{S4?J=u;|EY-(24NPh>3eRNHXt20_kzO)Oi~XfMh!7>6oxi4lYOuP!@l6Un-|FWi#`HE zTsXNTBq33}Bc4Ci($Y}g(a7U{eX?xt_RkQqaD8{s{&{pH`Dr6b*uDIM**p2QqAQY# z1ltVUF(R}A(6PXZvyt^n-%77IPJi4z9-iq&gf)41kB%87!JU9>K>P+UWr#57@xjZOt8QpyS zFXF)YFPrme4SC~x55X;Yr&|5?Efp~)7$DyF=b}#sJKI|1((kNm>30P?MBQ$+tl|x1 zctyB!+&p7(i>b

mDJ(z}c(9Dr|`JT-x#wlp>)hYBg!#E=Wl9W$b@jkZ7>Ec_(W z%Q2of6tJ}i+Sq$S_=kN70B$1Bl;hDk7_jR@Q)*G}kz@0Lv5Qszbv|XL&5sB74{hFu zHP;QJ9g1*c;oD`S7N08`ad&Ii?e*!tA$?H><;S1#WJ6rXE$@{)g@)cpE+-MZmf$7R z^NH~F3q*&*7*fE;zsZ1}ASJ0Fs;=MC9YklwzPI5x@OI7D zl+$~>`FK;YOlI69E>!P+SzR2B;m7d?ak*?$T7v6Jf|$*@cHtL7b|_`6im*w#ntRe^(&LuQCa(k^2if8w z7$k#;6;Tw4^I%iij4-hi-v`$Qva>s=`R}|@!^$!lj)gS~;*L(yTGLhJMpEjP>DVX` z<~Rys)-;mCmZ1bf9Ey-L5+X}>A84!&QeBB`R(mOT^!G;~dVsp!TS3mQ4--}&e}e{* zmMCQf2mp-nt*HA|1_9{VEYCmyR@}5+b2jlF4Icjwh=BxNh7#agL@hGG*c9elb(vd? zkxB`KW(X+Eu>j>@ogba^YAclZI7~~(8VJaFk3*ZCo%bUt(#r*_Qt+Bh?VZBOzqrsc z2oi_;O|fp5I)XnknyxTzDjqy*%HPR&CmUO9 zc8!Afj0M-^Z^YM3pNvmL2UJ48Cw9fA%Fvw3wyikZvSpEF?g_}-=MV5Nn z42heWM&viBw0c)=PQr5Nog9ue4Py;;P$%P1jWBqb$*S?i7S_8E}{Whz;Pk^Sp8;vQl8`Q)N z<^xit98Ps^g6}xIF)3%vgIG%m!&f!p9gN|}+D!4K3`m?xG*4Jcq7NE$4HYNr?#s!^ zFGobJhr0f23&SNHM<>vS0jOf zZyofa5xnPdjcgRcCG;kO;B?`36=Cc)Sje~}^b1S?uwMT#rG zaLvPoO}RwI)qu>*n>DKOo6;Y>%e}94L3kq3U6uN+HlcOF6KSNKJSzKIpPj#K__o#a zzkwAT61amo2(1fk3npo!G)U|LkQjIPspc#lZU9@RIS@W8;fI;gb$(pS63MA#NwvsK zRZ7S{Z)=h8737f*v!0>TbF80#V_T@##jexlS$5;UF{ih? zO2;BEXRePpYFXkH=cg>e>hWz3c2vFTbzUxh`&a!_#oDB%`zeid_%I^hcrJr!sy#8J z9;!7wrJOZ$^$nikq3Wm!n?({%lH;K6H5k5>J(dGCbnj7-kqj~CtN@c0ymT(Rj$&90 z&BPNb${%V*!bQ$f0KC`vQY%ofL(QJU0r7#-Slf6hSpfgC$-+yKAjUi+;Ba9QY?Cv8 zfHpAZ9ugc^Tort%2jZE;hWK94Fo?$taes2{Nt-aV%OCz@XeCPkrL+eK$0p7==zSld zzZCrb38vMBExeS~AW=~BMV_sT6WaL|Tsl3VLr0xK;#4P)J#RvEo&r zjt2z233bjYfkn4@5-X-MmJr?NXN(VO&HZzGiQgu`ioGl!RUO?E;$ zkBy6M9~H4L5TbFf5c|2|*t9`Q86&d%f-CaQIhZsUuaEiyRz0Y<%4;zsq2CKcF#fnm z>bgo~T^f#`Uajc;J}H0U<+>Y<{{SL^zR20`L+;aJ@QK`vb09*+5Fh;~`NzY^OYXEf z9X+v#{ti39*P#t7{X8i6!RYNc6V3b0v=iJqSWAI%=F-dGb2=r?F~=_MA7v_rUFKt3 zR?V@UlNmD7H_>a=<4A~Cd|@Ph0h(F$q%8>2a**=WwG<{jvmdl z_Z8)LogrllA8<9^R_&Mr3EP{Uj`42u(yev0v3x;?fbz%uV@nxQFT%W0!gm z-8L+CV1$KvO?~b7JU>g15ru6= zxP3R~s?~N8>2r3{MnT3kc#05_q^HJoUBTX5v32Kr5?_yk7#BY|fAY=8e+^Tn*_02$ zM`~!7U0Qw{Ds^c@ihZT>^h=!0_jS`j+5|hrv9Qt*`n#fi5*FU?5d+qav)1U$PMrkS z=us0~@7W)m-?_&Tr(Q>h;tyU3aBqo+YHSIIg0Q8LN!Z*UCRPBnpfmd8bJ!t zr~-f@V9)OTzHijZBh4QV+r-OZI*dkiPKL}B5!**2m=CR-zG+ekNS>mK>7fJm?}Hce zdMJv!6;r0A*9XB}TYY9oH)3(<<4~{t4Da>mDghnrflTnm=`V~(DHo2<+c5b%wJG;@ zm+X1UvR}7xX%TOo6p>#SttTE-Y1Hh+?lo-N-{Az0Alpt?YpSn~^^1%m3nI)C! z53$M=-|s280H)V2%2#WN4wXRmeS)n}2I-{E?#?X^afKsX#WC`|@HndYSWJz2)GdEd$-b@5toE40Sn%8P=gw@g+C?@I_T+euil6`GvV zTFUN3(B@mYl(4$3Opm=#|C#sNbU!L++c{FoZ<6<$0BhKuEOkltqjfP{J?8K?wLvZJ zZ3A57(A3a0S#A9IEe}fCGj;~CW`0WZt5da}gfGp1zi_0Tked5*5eAfC0Ow>F!~!;q zy=8XMPIDhs+id_1CN<7#_M*ZX#TL6=EPd&tzBtd7_YgG*5G{8%td0tJBdXN)JQt=- zME}G_DPe^eJ3?Ks(@HF2<@oy27QfTDEGf71Ecp_`l^%j^w>Qq^vGF2vpNuQ@zliOTyg zX+Yh#?M|J~5lpZTX@n;~?@j#)e#Dc5ft{pgpuRUf2!D5qPdQ=S6-UKCs7hIfGN6p{ zVHw;c`!L<@66gZeOZUor{uqvwhR3H9Dy+ts6E+F~E;-p_iKjFLddxt!?4f>orHh3a zA!gs;32t;WE{p`9UtOZ%BZ0U9-x%{tp#q8I=Co*#?Jk5eBM!`X^1KqxU9O$)kc4|J z34PwZd**B5F+-d)U_AA`BEX$Ug3kmWy+5hK#^P8DpE|g(RpCS%@^VGn>7K|O-Y4)FOY|%%B;Rig#Z=P zoe+`RdUB{IYt@QZ@Z%j1ZP9{Fe>F85ROw6n4<6yoT7-O z<)d~!AZ&7UZHv^Q^(y~jV*%_uFk>EK7JOvc7DL%Q!g_^OU zraCM@z%{#j^5^65N<7)J!#UlI!4E#-PRE6Z3!lTS-s~-G&-hM$RQMJBvZ$HSAq@wt z9q;Waq-6~wqu8W>d=8b<867qfP3S9Sp8${~8FzaME1zu0eAA&e)e3{H*0?KxoD znbg@@oXCi}SnYfaO{`|5azK!*>CVQ} ztWi+^YC$zCAr)*GoPeudJfiG>w{&u-xZA~l+M%) z_Fb)idWTyoe@2xOaSF@Bh?)9|=jMZt<29KdFS)oAKGwW3bW+||!q{*?)V2AFqGnn6lEENE2A1l$6lee%l!O&(290jobH^~LG)rd zdYQb@J}5F}iuvbp1JxfMi{c%Wca~+r60&y>>dsioMOf)7HO~&f?#z7`?-9XvV;~>} zzA7CV*F3X8MMQYLC)o68%JIZp3CLOsOd{VY{n4$t&riV$LpWN>!4KfTll>z{Q-mms z=&GOzL4i_phYw|0WC^>|Gt-n40X1wjU?HZC@R-GaWNN@RjR;UA6YrC01n55`B$o)r zC<_l@)DC~8wI)&_5Apz@29wROXHqj^rnX=z(9+tg4ifRZRvI3fA>6A$iki#e6Q}qC zW}TljPt&4uz^b{8&^~D}2xD<3C2234nxa5<6~S)9_ve`FNGWd zE#Fa=(7BLg0LH#E$*nRJqYDXf&*}hsk~PZ`^J22b=8u3XH6-F@r`)>2p%g+*9ylq% z@EJgsO;KWv&yI8AonJb za7gHFf0$mD5q7q{REWIekT1b=2#zc3a}~fh4y@To)pMR6nH}qAdYZhJ>tvMbT9GDcpE?M>c$%LG^nv>S&*yOhqP=9Ek2-~JDKc%usY^8L zG1B$H8U+&Y4wck*4MZ$nLfnf`M6oW`9^zM683N$*Fo(u0W#40U3W4X(Xz{uAErG%TVz3{(X8#S){kC zI1_p*@$8iAtXqgzR2>Uef`WsqNo1H+2VKj{Kd(;0GcMfgILeN2b#O2NW&vsPZI*Iq zUe%qJfwRhGCaZ;wUFkuj4-p2mE9rmA+gRx%}e?FOj)Xre#h9g%R1Cai*71*7H_s`*;1%$&qw!Z)6KVoE9x(ZN)CE;mjm5%iJ zC=)Ntr0^sEbhO}@9Dsq?!?Vvo4w{8|C1;J73Q2>%Bnd* zUYF;SBmXw9RLBbB;{Uv9XDGhCJ`BAb=zkVBsKKL1?rB52Sty6IdTd#+dTJ9eN>y&F zWwlz(w3=!BL=GB>%zRBlSqdAU+-m40ix!LB2dH6vZ zYbA|MxTWIzWz0d0#xvHaSL9EJ2Kg262Z9Mp%7wu_{Ee|arF1ujqGSDOk=3ps+?7s6 z&kr_}v@tajYIT9QlnS183E#oTx$)bUl083I(9O6l4PX2n(BtgMOi!854II`ECuT7ov-SKl|`@=+tO(IJ@?ME-YJDd2dNWD#gYOVI;x=c<6eI(o&R*0gA?iqA|0gERl9 zYGu&yV-wHb75yg1Bii4~M1eyGzAM*;i*iy+{HK71Qm|IMeS^lpphv+f^9DM~l+3^~5PCg-9$ z;59hm5;GN(qz+emG=HxrFJXy+wXZ+hSG@bc0SV)xB!0F`VRNU!%+g`zAyQKEfzrA2`fB+E5SEnX{z4XV9TDi2@!>g-gpH7|JyKsoL;QL(Yi7$G^oWPA{-Jp*-sw$?ftx!KVYO#L? zds!YHFk3>GRTz*_6+!+|oXN1<`Mosks9lKrzMRWsjj4;sZ+hO(DSQu* z{?F5&z0Yo+I7AXmkP@Ql$?W>B92fmRca#8f*R&p)6!#hsV916pK6)P>m^uAtYM8JZ z@lO=5cO`9eyB5B_GZBibU^&M8+vZe0_*d53aThA#Zwxr!j+IuATljk2s1Je*fqs9j zj{<_08eYi9VxbDdi*J^4JmA-7QdyJi5&Pfsmg{xW*|Ab=l*lj}>0hdRBR}^3?P{j# z9}vF5Wtn_zsb?iEcq_@di0Hqb(16k+c!~cj6$PrlN3DkGu3eFV44hu`)CxH}$u3M3 zW=jQqpRX7UaQ!*7_vIh?1AdB5@u2iHym+5pzp@?%4o&lEAW`EP_7??qk3e)jPMbKr zCUs>Yt7qyr)zru#?602;{OEE|8t<=pN8_U zI+h`KJAm_r86^^RPwBOmN5ca zB=g6zqNUl6OedC~N2{sBZKvFZ3eczMn z-oN;l&_V5qg0jUX{2z*qzYGu0Uoaawj&)>`H6Q3@5_rU#wXD- zMVsK{GS-lNPjZ%-=^0-H?(I@o{pR}A|JjfbDm+RryG2sL*uSWfh-eF=+?uOosA!e0 z$s6UprsAEE3m)7_ud+=a4W}Lzsu=#-RBD}P5@j}OJ*ScQt|-02fH0=tp#_xG#3me< zK*QOXUZF2Nw?cP+K3Y0tJyC~Zx54e*{H?XDD!ty8qcq2QzwbR`9yuZ3IEt^!KJs>#= z=DF$vm43>4{u62iM}5ejK>eN>XIvkv-@Zafi8~Z0k$!GJfHk88tr4PjE}`+CTe?68jPd1Ran^z$XgCn<_nfpp^ZnO=fJ_H;{k$2qLeKRPiN&zVXzN5Zidv zZE8Zs0I)sb^6z(eXqb*OI{g8Dp*WI(fmKS~1lrhL+TFMLRhX}xBK}_V%5$&Poka`i~Zg7afk?)SJq_wR)N&2 z*02zTt9c$(p!*pp6nT%JWkv*Mn=&;FeTl|ZegB@$mc6_jFWU^hWx91#%6w_QJ7pBr zs6-^dVshW~g`2{m6Q=R_^>^y8es@&!0ef?M_MS`K2oW&s@t4Thl=+4M`PoLhY% zGDCwtMsQM5{rb(P!x3^vEey9HMcl+estA0*ObuBt5 zHM9d(JQO?e1KM#^hZhU3otPG2;r1Fe%y8t(YYGNd^hz@Y$ZI9hK7)rYH5nKNiEZ1! zIaL2sFHUo>lo?;CS3x@MjC@uGTNXo%DZuS-aeZw|B11S;FzkedvGO+!l;rx)>8{Se z(W76QW~e4wN(G0kf+5_Ybn$zS7+|@YiTm@(TN)SLlqWl8S{&Imb#>Ez87A(nU+3o+ z_{1fxJR(vFt*`GpV`*-;@_WkTiO>Qj4S54#T~B4%)!{`j09M-+`WX7pX(P=?-yq;= zCEm(lZcGG$xjz%~&-cS6@5e|+5!l$F1I7)*=GQ{A!mnMcn5uufEb3mDtT-=Tgqr}% z)tJ?F)_u{+swemNqRI^26G{Ths^XPcA(k&PcSusPR&`62QS5a?N%bBPGnHU>?5@zz zgk=C)xqiMhOym;ds2ZnyCR3SQUjw7cV@irL6OZ86BJss6a+Qlkv>xU&8=IN z-?V8IQz9ybCar**aj}z!T^rK|s}_cbhpa)u&xU54+$;wtbjL7 zoeNTGsnZ4R>UDb#RIKx|i2%Qx%|-`O6zv@zU>qOHtp^mJAK0{nIl z$=b6Ha0$~j)Ud*9EK|ynd^^hfDJofTQsiIki zqmDKylTyu}9iD7F1ECPum3y=#bbftJJPm5(NT&3b1maK?ANPWdxxl8k2Fc)cH9d@k zZ4sTrYJY-r#QB{a335J73rg3-^-s}1;jf;6B2!%nYUJgax@=p;Nb@*#%ZA3l1z>Lj}wX#V(Q z5TB)}bZ~~Pzr(3u{-*jxLNoOOSaUdU?vBd81TE7?ABTfKiIQi5*^FkM>vxat#ycTE zNpK%v?o%y5_zaJFp^Tm?X@WEv{QZSx&FeOb3p(s!^*3#PL zx&@Viwp%C>*Lq%OFst@(HL-r6Uo!^Z?N`N5SUZZ^uyhMtSJ#)KB$ zc>#Nq4|o&c7}|Ak8uA3F*v^WI!Bz3lB8+6nselQBq`rYJ0d*IobRA9+fn5=Wdy=Re zZ0Pd96E*X3ks&dwWO0be8W86D5)FOTb?#gRbZCL*N0T?Ny!VE>#Yt(e)C(@C|M=v0 zf6VWFdy{^DT(6{8Sg1QA-;L(=p8ajPf-bfdD9t%#4JoHpA}8LB9ORB@S&}M|gZHU< zs7j?GN0l-(nCv}F4pE8AXrTlRD92-F4}hQuoS{pV&Ind-y2_&8ki(W)Q7x)8;&z>W zzXYSzN0KE2O=1qKEFQ`haZLU3%4~RBl|Xb4!IU4P#4~|vBiJjyxqe(2IQ0Wv4(CZJ z56;1&pBp`dLBehaLYIprQD2%Tg|C|&u|e(tzdrua>#w#A)&}SkBt(KW+zzXYW=tm@UEZ|_ zQu>_nFA}bmm@Rt$g_1J7_T5Ae7AXP;0{V75KG5Ic{&I*7L_)wKmT#$x7gMg zfjTFPNf7AtmVguL3r%^icwOszZWGuQcP=)g zyOHKRwmJ>Adf>KB*(;O1fIV6NIS#Q0#5Z^}3+IjWr5_7=E`|(C0XJPyUn>1k+4BLd zkvceim(4u)0g*SbR&V3++_@Wo4&5y8GQfXS(1tly!8;Eb;K8GiGR~%n8*5PWO?2cf zg~#d0{ZS(utm$#Mi|=NChJplUI-Fi}yOT+e>_etqCVJORp!*1QAy2EUn=pQTHK?+u zf#LIzqc!cPgmxk=8ZJuTJmM$yhcW){?)4(ZS|g*KXF!2~Kls|`Y4+3!OXy+tlv%O) zu?>;%F0ZJtuqUg?iu`)&=XRvUW>&rVvZW7JsZKth+RRTuby=kWLHIa-N`@QVvTctP z|7>y3FC8_B84UmQbjIydl}u&@;0{E}9l>L#mH?o{gAM4+_J-a@)bwjxUgjjeaLo}{ zUgG}M6gu`GVwFRXZ~RhByPif~X7EmUJwI=1`Xb*)|7t%rsNl!*>XDZOK~>pgt^v19 zX18?ja%v88cZ9g`wAx82a0Rea0MirjzH4@iN_Rg# z%yC;07P+ns%#(@zVSv*MXW{v@XGs*uMj7PLw=ZzKnCs-w+?cZyI3hp6jv;v5qcT8x z&NWmW!bjOav}ws-zo2GI9%)Os7p0svCgh?a6H1v)N|+fBBQi>Lvc~5Q=8~~e>8xPt z#QGXzGM8+yk??`2@6!(9OXrX&MXxG7Ul|aC+VL*-!v{N9P!M91bWAEQJt7+VjpKk_ z?5|(+(U4%lcqm!eVctu{=L12M{OdVUsTn_0KfnRN%jI7iqb*(+%ip&1C;8M}5`Q*X zw$bX*=|vO?e~@kDL*MX}+jAh(P>bDfd^l6e?Zjz`*LZ}2)#w_^BV)iM*+qP=jYy(0 z;QGE&nvzaUofah60Db81kA^zbY2Rbn+N*#k?){16JN`Wx({nuQI^v-w^sobfO^%Mv z3k*;pvthipivA~M5+ymLQ(Rx3`VQWWrZR+Zm!yrzsgN_hXOSQ8!HtQ;c4p49VV0q*<-xlAIukuhL-f zX1y7SwlmDtNPRygL&zGN;3)0+%{fav{N~NaBN_6H1NzOM47>`T?a+fP!{dHpTJiQK z+Ql@*yY6`@e|ddQPLX8pkFt~x&*b|R94LoDG^t<9#lh|!LU0DFy1nAM9t+gUl;?9r z8grWVSDOdlqo{JX%~b7_NKvb>Q8&_dt$wfqfI}T@5D@8qyg&HJ>t~{*DZS8h^=N^u z4`Sa+EH<|4?f@re8Rm&^)Ue72Ng?#diw9~mgXKbTY`%v{d)86~J&ml%`-FjcSMDF| z4t@ruw;ru!(7W_bMYXgzZlZ&hu6G+#jx#*gci1PmW~5g{-1I>1mpvgWl1lkGFgC0p zWpuh=Mz>8E@WtB$b;wTPPtqRt(T!(1I5$*~drpC1Rj#Xsz*+HLE@%QR3vXMEfgxO0 z1^b)Jp1Mmz$4PY&!GP=s2W^|KRO;Zip&ArsV!5%|5-C!4Kdv+}DZeLay+E)Mm)1m} z^2CM5si5~-jv_U2g{qBp_e{IT3&d%^ibtN4TCLSi9059&0`-M?RFX2|IrA`TK=@Dk z;U9_?MmlXe1lWVGknove5(ZubT^`=k3iSOj-Y;2~@61*QBMG-lV@s7FbKTLdTa8G= zXO5pR1SlF_r?iSRU2nBY!xtzYB82}u_|FI~s_gBR#y6Y|OV=SUOPd|gKeRQbQwbVeJ|Xk#sMra zDM{!!lUYp09kwjZq*@X2OleUy7l71Nzi$$had%2lhQeRS|yVr!b$uRgLiCcKrAC6Ja zBSm+pn&28ZjkldMd1w~%`=E2d?uqwZOVNs#^I>F>nbO`!kergI18b^%C~B z5+gUBKp&0LmJe32M<-L6&E9Tpuuj^8IMSVb&asj5wnA;Jh9MJt?z+JiIo;tW<@rbG zoA>4XE6TO&UQheYNGqbt&u)r8M&-`$dzZboOExw(Uf+UUZoFgHaTIxoh65~0N>kSw zD5bGp1(z9ftALE!cHg|N?`xK#hwR&6oe^oN<+Fneixk-$rd@uHB+ry@N3Quk=`VMy zRe<)@z|8XSma)?y6NQCCg3PGQ-)$c78l}Ydyg>G846Qvh(Rc)8e+$C?YnzNd-y?b$ znXWNedzJD>f{zuoL&XNU*MwuJ7#ppcignAW{D2CRPr%;gZP<^up)uqzUo`g(po!G; z-1N0*@QaL!x0%H>KdJ#DMm*j2bGbS{1N>UInC9;a0|s?N%2sec%u;$@#@*a8feiHa zrs#$??$hn3OIxgerk&q|m!r2_n8yu>Hhy+yTH0@r%ruY4^uBw+LL^l!0WImL#) zfoZD8r@qdM$9g?Q<*;?m9nh>WaF+yD8Yp0rO1hkAh(^#r#<+tL17x30vygEktY4&z0RJU|5iV&;k< zcGvc!ANv0I4`Te?X`@vlYs0$e=|IMMA@%8^<$+bzWlzw!g@E#zUmL@; z)#0*1Esa$q;u4&(mT=l!rL{40)_k?-4uq91yo2d}=2D}R0r!>%#gibN4U}{&N<>=d zTWY$ae)OcHbE!ar1!^bs1tFSt2e!+{5qSaA62z4-Qj81E#zJ02EUHnIcJW2heXan& z?p~HSgO)Dur$qHP5G~CD`ktqFq9@EyVuEzbcI_Wv0M|ylcG-08muYy&TVf(rWa9Gg z=?u!+#;y|Z(SsM!c`c)du?tOEoMBwBE6N}?TTKEC>I%u{eB){d zl33LDByWiswFV0m>EdF&uVC7Os(3_<)SI$ed#(2-d6V$Zw|8Mh8W#yc-cHjk+n?a0 zq9Wdpo4p4!QKC-|Bj?I!Yh0^_(oy~7lERZ4(L0_BICSOv4WAP|KH~(HW8O93Wf&yC zzr}%|=p|j(hB)L?)6Zo-;*i;gXKOuT91?<>6?R) zF%DX)`_;cBsgSZ^PJ39sn83UF?HuBXg=MYQ)+I$0U#UP(^!gpZmY`*wMFK8>Bq)%=uu{Y1|!1^T=v#d@^gn%l9nGxqz8ff;B)!ohe_4j*Pc(X$K}W4Ien4G zb^doEc4SLx>8>Q2=P!38^xXMUW*SH>g;RUoxqsgjX8la)mn|v8E-7@bZ0)WS*KzUR zuKz4hTqZHqIg4>Kk7*LQj8nbc%I(h(s!}l%&oIvC#k3qP4W#q^u-SXO1LL*GX zR~Xyd^f>%8ZqPd46Qy(A>GB(V3=IpM0{YN>)bZajS#ELB0`L}f{bfJE zo$K1sKBNCca1gMg5BB#*urP;*jis>Ag5;Cmv_qS6Td@u&W-uSAy(nX^e>2)GmveYm z+{N1~3SvWj+>!$Ip*quIRrqYr+wPw5zP+JxjcE~iBMD@!?%fttJ!<(Zho zpt|@W7MH1dvwBijB_qAp2)=SG^W7-N{$ACR6}~QHL%8(R@Gh4|U276JzV|i!2ysj=EEwVvZoGHbc`#b6#sfZWn6$ z^EtU>tMiswx7mcyDDY>~6E^-v_pf#I9mJH+iw`E738~L)B{vaE(IWp;&6rxu{#4<~ zf84*Wx;y7att$uWeHAq`6Cinh1?A9T_#Cm?CNnn-zCxSz1$U5+;bu3rf_rA$doT5cgP2qVt2NP-S^0ExQzs|-&?5QYxv}sQ3cdVO zDr4vuP3d?>`kSVyS9tq-o3C+oa2jlA25cmSpYCyG=GpzxQtaJb0oU`AU4u71|7mg& zhX+<5zy3hMPOMWOu1x7#Wgmpe@54xzsH6Il)3SR;?3mHI6_EM;r}J_qlw@jwqjXO6 ziBB%Al&Ryy`)8EXgB0h2DIb64RzCIB6PXH|)`_7wdK)YFbTLtfGs7$$rKi9Z#TR6w zHx1UDD@!H{u^9BJQF%3w;PbyN7R+@Xb`T$;k=uV3IL zSHbJ;rX>+uHwz?ySY~@Sn2{FsV|DzAfItgwmaC|tV{Hg^C)-;f07alqbAWiCc*URv z%x5F_jMWu-75Tz<)jtZ>6~QDGg;U>ao2Q<{=HG#_{ssU*c!et)GLl`fe0rF}=TW>k zMx#;mTl4uEZS7rPmc#}D8C$T$#9gY93V*2N^G;GEo=mhXl)6kX3Ci-1(saBe?IU;q zByvwC6CB9x;QW+~QxV-icOg{ARU2&U=DGR~aFgw6=`_genZE>++ws;!y%zAX}QznlI(8tB0)nvMYp-b>jSlZJ70Q%8?4wnAi@1gh9 zZ7l21d4k+c3a3D|Z&j^;qeAY4h?zn%D=eYqg#nxM^|vxMb1o#V8|JS#BuyTe#yrl2 zu?_7wC41-m(1oY;@B2afgx6TNW1KX%Wk<`O1He9Y=U%s04o?*R?GHhf>F68Nkh{B2 z6ElxdkCpRLZaF3wzuLdB{aKQ0koc&ru{Vew~dhf5{8~XxsjXVO}W(#~Ocx3eRei^gi;3Q??h=8s_ zf)q4%wNQ5>ru96C3Rn=TDGy5ob_Ig0r;L)O#_`vc7^bZp9yLubck$^jiy(8qFA_bf zMY$lF_22`>t~~V!Vu)tMw4p2zlhkM+d3ubx+9*U#B@_cPs~Y_1Q7l_5q7f_%PnK;j`FEPPeO{`}TlYlkyHQzf|i4;7D< zLmx?GipG}CFuR>*l15a$q%~vrN2_x8^4Ws!)U<~+Iq4_|LH&A|d$o1DLX>bo-GwsM zm73vUDtm%v^aEZy?@- zgF!1{bZgh<$^FxRD7nyh5@FIyzH{SLxBI`yBNt)NaAh&qp8I-r+~|K*8RA2S>pT~W ziy{&$&I;I2{Qm-<)FC*P{a$k3!u!SFO1uA7pGpU3uk@b<+@yiygre^LLtkktTiU6* z>3EgQ`&3m7?MnO$s#7He{rZ@5_3o(A9a@a^R~4Ui;an@EQ$lW?M@Mnbj2rPkz;=c4 zN+ExBUDDkmK2*(#lg}BV2IR>#R1ez+mFxeM>MjT*t{XgKf5P5}yvyUIR}+46vM%TX zjZGR+mEY-7UBw#~zFDB_v5N%nm1L2J+gbIN*4UZn_iBGDhrJ1!nysW&7ep`WP46ni zi_+u3+_fy~rm5*ut|Z)}(n{&c(3=C_+K@7oYem>78a8uQ@0GKbN78ICx^H5O0(q7x z^6|Jadn(XF)RbhYwtOtC>ASX8h)5&YVT{*2tiiv>%oCQ1`5rqNN#%Q|MTvB_R!DU6 zyDkpHR&Io{-`rOx$`q>tr&SFh-v~8AB?4ySL$xGyMVEa#mdRsMZ+0i{q31n1S_O_4 zujL_$j9uEo1UN+>SqUaQiXD|r^1JO$j`){_ecIhdtuj=ZM9-a5eU=@YzD2r?J}cRS z9d=>RO~0!}r?t%dpE_aj<02+7Wi(vEI0wLA&?9SB{F}{AuD79`>fhfunf}F{O=>}K z9wQn1>P-{fj*H(ASLm(H6(xIVOzbTtOdi{JN0_Q--mUf#;e(rXBfI^)G+8h zWc#&lbLsov`;X5C)8z5?d+UOpxAE%d{qd%UpVImD2rwnzqQUuHuS3JcnQ=<~=7x2- zB0*HVO?oYL&;7ra4K#tF7`5u#oe@(pIS_Ds9)vAYsP48w})DHs9QT%PBDPWK|>auds@Y=Oy%>S@(+wg_91G_JoxJ| z;2~DZFb!$orFNNr)_Xzk|Dp)rg>%5HMo6_&kFMbq3*oso*&aqOL`{f6ZN!Uh#eAvE zlSk7ta-3!dHVO&>$!T@&>3AG!8eXD9W{n~2@Gi?*!t-fE4=|J7Mo$pw3apiKMGxL4 z({E1wiN9khn5IsD{aH@A{0!XH$id4XsB{(xziVEee0vmL_kjdsT;xBm4FcK^@+=G9Ny%dieegBm@w& z8bt9Q!Y(^Up#u7+0;i?d|3kG$*HC$|-D%V3_$? z^dOY1^Un!~b*JageH5JtNO{i?wEJ(H+`xyHcm1Q3q~PHod2y9zn*UmR()FQ*&S}NNzwM@i zy4_k!KXap~go2ZGSae#z8XNmx>qKniv1(=3Sg4xh(0EbT+`(TpTfkAJ$vPk#Teu^4 z?GF~Iln0B#q5evE$gAXXajK(RXjrM&eTmUJc|^fU zlu06o){-wOUtF_MeMxGT!%n0fVtD_VCH9R}*J9JTi!{Hw$5_w3CXj=<&r0So0WMKX z^pnhuexZG!oV-}qnSR3FL?ve1OK0sq~No8$P(0j-}t;om}=E;&Bes)QEfH`pA zS{(}+;2nH?4M58G*wXC=&3%U40Rc$8qH2xeouJJWPizD+UxL<*6%zHmpa~Sf_xQ8M zK#0f2^AqZav!?MfFyj?A0IC0+P#q0mt69p(%@GSDVDAATwADkXtw_3+b08#*l6_k; z=X{Eb`@msL*zrlNpG2*tZUX5 zbbU|2pMyE7$N)Ax zesKxWvMfTkgX@h4Gfv}Mq(nv+klAw^#G2i5n2i_zz3rbHXLc5Hw!s!~Nx9+)jiwd|)tuPT$G_n*lfwD?~>`?#f`NAk2XtdV!>*l=>83- zEQhtil^Dr-3)Kg8R%ZJU!EWIKOPfIeS<&mY&WY*mfq%W6_J3R* z^f$i?2!i|*2cF%QIexyV$^T!oZJ@`eQ(!q>NQ=*&G&)}VYzof;JW*u&HRx3l%?*%|u>Z%X~vuftNXbGq~i)Ad9f>5b>>DeIy5# zdAfSvTer473bxODex5^Id(c9Q{IZxj0&a$kmcqP+XCoDF@|j&`%0WMye-N~`e7g-G zHT4uVg6Fpi$oCMUp}+ktH>l>g)7xeu6axFw&pxdmx{)*t`1(v*8iVi3Eu!k=n_S7% zyM}@I+nGbQo!SZWwP$OOYkTTQ6zt2eRlXCkITk3=z5Cn*$Tm*47y027R}1Z{)#hzb z@*S$3@-UUj>@xU^V?Yabt}i8+krQy^Hhl9G5BsE&Uxp_j6?W#>QR80sO-mpImid)5 zZR6ziwF5^k2f~7mW!gu?2sZgGB}HBV?oC8=$#jJ8LP@YPxuLo8w(C->p0}e>Fr}8E zyM~sb5#Rg}DQ*y-J~TQ1Qc(6bPHP~1U=G-J9Tn)|{AFe7wJ$nd8QxFUd#|#Hm);MG z0c~m>trOr}IIbpx-0Lstc(0B)Utk6ggGm6jwRlFpZ*Kr~vaF<$Vq>-DajslD9B5rj zgF4!lWG4Qlz72*4QN* z|CmR#w==?X{`zYD7X9jqA#i+h>l~b!o&IR)4^7WtSFg;7xmCs8wX%|(3Mu)tgsnEb zQ8<`rnLZ{3`ckR$Y^A4 z#lWgYauVsF`v*qDab(}k#)nFlh=X=aqMfpjJ`yO?KIdjp?u{h=M!RP@0LjRn9T4oX^_ z+~&@hycxo*mZ0pVVicBad6F29DlJe9EOxpoCya1DJZoEAM|*(gr5OnN%bxL)gCIPP z+$&S#@{20(X>G_X8pAnClww&%Hea%k7em>+Z zKp}g&)}#dr$4A|z`nsG)sxIUQYjPQg7>dELI%#V+*fjFJe0BsI|9Q7#TbiHA%d z=Oy&Y9GAY9ga8Zr0&koXlP*a(|1O~?=jB_pSGxJOz}0qbgnUX_R7z`FS@JEIFF&8? zGdy^wws@pQ2TkLw%VG-#Xbd=!God+Y2bU|YErIPvz`J_}(%TtsVT2AfDms@kb#&1gaUzyeuh}fl_rj?Mnq(Ren?M3Kc zdGP7<6pl`o!#+v`B~`xQsZk~Gtxuz9<6nR(W0|0t7B+0A9D`66H=5s+9y=0j4C zWqkaD`DV-CY>HN+H+w9%T!t#LzbqbEW;I_sbx`VnJjNy;g%3CWh|6-zyT~q`jT~YL zeccbkYI0m^EKy>8Vwat&)g3%urUst!^%R&IFVhwcJyQq?l#)&WEW%|<@UR)m@i!8) z)jB!w58j2Ds5-WtICj{GvQ`6XF+X(&60k~>waLpx#5irmk>+d-&`}VZLYX$``fmt) zO$K`Af0I#aJ2fsH)EmnH9nQi>9oJ=PM8~4yN>fQXZ*QCMjCo#mO)(Z0{Bkt>6@jl{ z0Jks$hSCCZtPQ=9kG50=M&yjiwJkxqM@{DeBm_c+~ylWfA625CQ@?qOR#8xNzg8G`-eYhT7 zX*w3>YhWci%uzkjsnu!!eE<&$C23Ii6$QF)mKXi=Mh||>%qA}oW{AI7kUEX>gvA@! zl=jO3iP};-%Lue#_Mz@@bwOW4fL5T$;~(Gf=%BkGtX{qmNj4o_G*eJ~ zxmf7&9fOi!>if+zV=J6s5a&9!9bCJ~nyZ>GG-`aHdr9gOWyco;NW-^lyjyf>djg@f zG-ghCMnw_y{&;587I5T{eXPUwc#Nnp5EeZ?Jxsn+QWnd+3~A|o)$14WRkKsMkR!AsWbZn$I#TpErg{AUZ%PS0&AtX9wM znI1lmu2xLOs9i-E7h#%9{h?6^ca7D{@pUj?B>o>C$3fBkBov>=IGq;J$n3K_I;_^y zU)KYK`YYosSKUFjK3Dax^xU6*1yMBZ*1MJd;niZOd(jDJ3Yb#6SrDqe5MelU}8_UiLIneBDga zNN?SRXgn$Pypm4Y?gpQbmIL^#ZQzLai*svT(7Q{IjAd}^NFavkXf2%A`U@OmmQ>3U z@orSKepB=Lp;0_cf5q#!s-ms?P4(&JjDCi#_v2-Pp3lb4&BieJy7?=s7tUIGihli0 z_Go(JPT;+F2JA*l|IFzX(kr1EuB|W+Z66klJ$<^s zr6Qi)q@_MLC!Lf}v*6mrN6>xKB%+(h^}#Tf$hUp7)_q}-U{1i7LX`VFr*no;Umi!X z@*0i|j50}1`*>pB3RPWS5YwvzVx3SjftsW8!Lc&K)wi^^=D;KLH{3r_?h%LZ=1Sj@ zS8gMI6O{F{|2``;@{I@Oz2$8AAoe%;)bnY?1+CE8rt&4nFQh#Z<_kh4<|E~@X8EBD zT4>=Lh`#o(59VH%lV;U+^YcI_xnj_4&48MQqh@LRWoA5mBLv&CfwSC*+h*mfQ0VvA zFMw3?gI&#yXpO~g9;P&wowE48SGa^XW;%Oo&pSswfZ$jJnm7Wqd)NX$Xrj(v#DQcJ~VY| zccT`SeUy{wG=++vCQC^V3e-QDAI2qQF9 z#6pLaN{(XtYGp?u_$~OBqi}DCUMHbEdzpM`%c%-9JGE46Z;RJ%ZYllxkE?7ugBMy1 z$p8nm&O9LdYya!s)UWZF2paDJiIe@Ocmdcx%m1&lw{UAC=-P*iTk+sUiU%vuqQSK# zXmBlVMOq|yDNb={2o#4B+=5G?xE5%OyF-ECUhK>BJn!}U1HQ~$S9T|RW;V0CXJ_V| zbKj6~#xsmeAEUR|i#0%^?!Cw@!4gJMf*!G20IVOHT?uvBFtlb!(8-upii?;v!(n7g zjBigxMDv48g*e9PGYfwjS}Vf9KR?e-5qG*y37n*VM*r-*jO4P$>#%w8{Z(VRr?Y53 z83y;0B)c(oWK*r4L!Hefiugr}-soON0ed66=mj=6(1_(y1->58=!}}54dj4wh&mup za|9v&)-{ll{^emvr((UlsN~eggY!;tQu(JU{O4-&zjRosdE;Kx@hClVneKsahsvvi z&nMvjP@J`sSYi#Qe_dzH9~b!b|IqdbkE;pP0b_K&W-RMlOr_X(`{LRHvx>d7;eO+= zUgDfZkGRS*jBzWC7^|qQX3dvPAeT;8zNxteWDn_VEg5L&HA(>`Ot(ggLL1CbN~kGO z=qz$7hkrdm1Kur3xG|N}o{Ydmf^BB}s86FAc_=lD;v7aHv??8OWpA>m76&2Eq0pNI zS05C8mZk6;Yp^v~_U8^-f9ySLBLgwlaUd1ZSGzaTd)(qfITDsMw&QIPn)^A2en!lS zoXyULi1&TuDCGC9;04nMqB~Fii=4;RwSl)m_hGs9lb|MZ&!r_F)bP^PV@@3DK}9^d zIw6L2QMbiqgn^3xwgz3cr#eC0i}5J|R%K)~zpzXVkySjQ>TH7ze_erS1?1V{2xo~j zv^vm{>*TmZ|8 zG1ddiJR3c8&eqjXDoi-zf_J0t^zQ5&L3|S}aO|Iv^G4iw^d50`>R)iWh2{Yd_0*|) zQM3%Mv=#}hFqUsSR|@XGSE|Lt$=iOpoX9_QG!$F?{YYEj!Tb!OHvJdPtWEdiSC?^` zi0g-q!YXI;nLOWdp=ow@MscZvw z*hpxvDcedQ_I^f8)azD>T>GwvUr|Trj#5V*GcJfU_WYXFxA{>)%&*T|caXM^0#ue~ zOP8l!MrX6B9mVssj)S`*&mbZtV+lRuHM*02^^wq!hBVR4G?NY+EULI(f$a7&S9lX2g zxfq&FFc9B@%mQ^%^$SPIZnU$f{jH?z8pa}Xx5VFf^gWKr&GMk0CNYw|yL`uR&s6iA z0%|X%1`=~o3tt+BWV@pMbF6Ku<1458;U8#i(Trm(mkKUSo;L2OCw*^H`vkBGCqE(T zb{fA@A}Nuv?_BC)7z5h;fMPmaCNJfF5*xYNG@WBYm?B|lMi`&2n0{!=f9~P9Sr>~` z+RmY)*`hkTTSXL^1QDDvb2`3VzkeXw9FU#p4b|T2Oz2GrnHB!P2{NrwLsjzOD3k#+ zR$r?%M)`Pzd?c28(c<54{M`R3(MUpd){7YG$5rHHIjI;h=ydJfg2|rg;h}k787*Pw zaR5HBfo!rnqOX>Wx8YZ5g{zBtsCg~H^Uy9p3mLwP=rr{@r4e^ysF4YJ?Z}Gbnxv}t z0Eem?I4MZO*%v6-bLVNFounfI=!K`9C}Vf=&exhmtyVd$h?c|3OgNpu7t0H)e(>Xg zRA&+KUK1J{A|ynt-mQ)x-%FGPPGoKF&@-l43YhzhYGgP4l>a*>qTYDI^-zDZN9HwW z^Y;b)pQSLC%&bLMRcNgmHeG{~+0mEE)@*4u5b**uKog-=@Ppd?Z;jmzy=t{W>1 zQp~&e`1FFGlpF?hEKosienuLns!0T3+bk7`pDRVye>kQZSbF;XTD{dEPN9)v?1ks} zhAb$}|Hd&(JlJ>dWPg99WHK47`tfYpvmU2wmVf7jas+4A+o_A6(@oPQzX9H$WDn*^ zNLkCG)ZK=Vu#lVL?UUjgWdx1aUguD8SAf~K7w7yuOR-l`dkmM_zGPii4WCh|E(@*# z+L4-|T=NfjXWJ0mJXB*HovmPcgE7TiUh9FhBIVB--np|eFb+ZUd;!%QhaQC8SAa%U zRCMX!X?iGnS+c6oZwC=-*__PS7Sxi=N;@Zx8XnrV1%X^D2Xn;JtZnzNF8y2h>z_B% zENP}knUlv-DWxst=$4WMSkB%_e&pyMS)h=hH^nggLw8lU5Dh-BZ9X|y5PICRDeck9 zK^Ygw-gT5sCQrOLTx#*U8$9_|Ut;(J0<6KAqd0mOvRaWUm#R>bwh{7PNBPI$H)t>!k#&zo{y|-ZTG;{ z1J>@0A^c%a;LsJexwLj#hVCf0@)GAJ=_mSS3%WZHIUUxv<#D1;e+lL|;;tUT6x94+ z0v*e5flf3$-Z^(y%F&hkCX~M}|Fs*qsi`b7ezk%n;LwbaTP=5vs)kp^r>%rvwN_u5 z8%{1AAQ15z3#+KQ4~Jw@B!X5Vk4Q?Wu5qfmaHnIReD&Up@L^6ZDBvJf@^bxd%E8NS zB+Sr#r6cGgYOq>*z>vDp$t}~EUaV6EVKh=cZ47ivnX9+a16n>c?SCUiXxj8F(3YbH z3p2Vh^S+l;C3VlGl5#u;i^z#Q*@Xk?Ut0=!f_KrrBsHhQm1LDWmn8kc-%VzIj>tEc zU&oXkG`;BR=8tI2ZbO#~=y2D5lgk}qnxil-b=y&EJT1BkOFr1>t=oB>s!;0E)MbdP zh_UO_mb~;Gm5RnNo}<+AHo5Gw&qC!VF}AheSUJq`Dud7SQH#3S(M2YehJvE3`>ED{ zuMPOCGZPALIne>{+K7j>x}BBE$z43IYO^+vjlEH^wDBBi&%N#!S<+D&ri#_%grpjT zd6hM+?RG`@71PcpT@2Lr28196ymFt*PoKIZF_?{k-REi;EyB+2Yh_{dm)dy?czj1t z>HvgCwjq$kkmvR*@u>$r)C2W$!7RrDm?uL}Yq;nVof6O6v4v-PZMC2+s~4kH0eH2q zT=)IS+`{$wZmn&PCX4Kxz|ZPQRgeh?bwwz+O+nkSKn$i${qvF+r#6zaZuE0$UM#zp zUQ8E;c$hM!W^4S21@QJtZ%@q4t>t2K<6pl`Dbcu=bo=|g#qyV22{P@c;8c&Y&LVbU z%LUwDS9 zM}D7Baq8`X8g1Xshq@pa&UhNidMBZRC}EemUNIL57iyxP<&#{dDq=2Y{0u+cK7ttqe6mKr`=W`$;dW4V`nO zPhNB+iry7US3-LFmmZdmt`d1gMsf^G&7;g8NuC_bE-s!Xw1W)vX>q?jxqH>r6R}Lx z^y{KPoHlDIoW<+I5ZgJG8K{^$VM^q#JoZ}{nXtH062A3HCr`Acq=~i!9>pm(vusG# zuOanBsGp>5z+(e4p(#zpiUuUMf%;-{?Bf;ht%YFxdP`1afk@dPJvJ&O6=i; z-BKxakG`uae#@F@(`y+K+WH#L!;zrWpKe5_XxnE)w46Rt!)?%4baq=gV1@QCfH9-( zz!}+yOFO4ZbM1!IwgKZk)#`NH3=T~&u;HO_h3>y5T=#;>H0_wbwYAyD^bs>z;}c%u zduLu_e(q#wYyK7*Rjafpbr{xS?{^F%e6US5fGHgalxwCV^7J&&@{)Bv{Z&p%R!<&D zTiF*B1+jBjPRzx7h$Tx}92p45<#q9JfVM*(!SX=BA`T7XGxn}Vl7dxgZ>rF5VJsw! zPs3q=HanEQqsZb_D8`E4W=C%9%DLj&$K%6Q5IV|gK9~Oqk8=9kmWsF8+gePgTKFw3G`s3%um;&IoSF05 z!T(z|?4xRm4ZR%}ZN@?TI(YwbwsL+|6Z8Y(bJq2Pas_4BBZeg9>!}`H{?iF*&mUp7fJ*+-zt+$zjOG!r`0WA}!OLPN z=k9!&rsC!uQjt2Czw!Mb6rUqae%v8L_OsOwX3Gaq4?!S3Z^>tJ@$p&L84 zTag$?+lWZ+VCArnq4J^TOTbbdAr#aOdD2;>sg@Jstw#6toLi4b&F&ptUc-R-d{J9Z z$uAB61{3wJ-q>}a12!^smGaTa$FjIi_g6zl=quTZl(&iW5uB}=! zKdVd?rhbyT{%w^#P}1am{8t4s!&Or1_JWk?fp)Q4&A@&y`^CivJBueg`ajl(@0FJ~ zZF;rHus>ihh@ZH6d5&a5-`z=->+ytzc>e$}JE!$Pr3OcnxcPawZ6*NriiR+V@T3In(w4;W;0SFglYq%oX zVR3NaGos3nBL@d)G+m$&H-X4!C4jxD~yq zTKL{vs;lWHb8aN!yO*|)%QE9bz3-!^Zh24*?{+_R+>&!TIC)`0Iqym#v}E8$?)Bp- zwfBFjI`}YE+y?l!_O2^-d}xItLa#$9sDTMx22UL>r^v@Us+SL1i>Vq@N^`Bw{T8?O$LcvsT9BFOLw?lWaV zK#;DK;PY-2XO(l`({yswHrowr(R{P{GySJFDlfyG@})`~C`n`b#FVbHgc{o?Ed9Hs z4s5v*NkHgl9oVOQF=(R+ad)N1B9(7b*N05`W{I_D;UHCCHv;-Sd(kF7m7y*YM!1%b z;XAiE?t>RKLCxb?wGcHQ!`DEm#20zNPCYbV%@ATkcFzzW9^X z$EaGLiJrWrE;2zvEP3ra$eO&H0>OET+c^vh+ruJ~_7X`|0Pf}|{p_z7yReM?mc-Qh z>wNQ#N#Sh1i#PW_=Ia#ihxx2V(LMX&%Z?RW#7bJleNx(6>3p?&(_4gf_1q!D{o=@| z5$ZJp6GLtCrc-70d-Y^B7~>*xi75lW!vwIujz)b&`AN5QKQ1g;2`>J6xORGGryz6-k&0X|(7k0a87~H%vQxf#*;DwsaS^ zUQSy^SdQ8K$1d)P9h7HqH0ZyL6zMvj-DFB%1~oOzNjsZ5pLEn9y%c57;@Ugv0jH@M zD!{!jJoUU~8m~>ucvyMM-KuWX{*yGkBYsjojN0>3dtQS368=FWx3oXS|E0OM3%YR~ zG<4=ckWCXD8ZCTNf6H(>oiK@%d^OMk`A^d2o^p0QXb)cTZbY<3jZ2fF=@**b;vZQ| zg{xLCn-l$0(6EHma%MZ|4(ir?i$)=8o;mYHz?y*;&RyEq03Vu8~i?b z5)SwG>TUAf?Tx#p-Jboyq%@w2sRmhM4NsG&gbJ#Aye)lH2Og*X8?^~E4QOMQ33QY$ z9KBkAX6)vM`t#8{+Mf`fq2}>X zfW(Vb1!pc+ws?2FxM=m%J;SFRN1GNveYbgNo9jaMhAhnP*Z{bgzeG!SOaq&5v>oZa zxODt+U6cP@(AAjPuMAK^Z0tt6GO9l`h5=uwAoSEGEKKHa(zvU;cy!&#xYsQJxRyfx z)A<&plT1==a)S{y*VmZ8tMMH4d2+@+mzw>ngS-+hzwx#oQ~RJSlnth#KK;D`Tjx?c zvEbpTwK8yI_~d1gW{e}Z?LFn;Sqn*s%4IA3)xQO~Jda#5zhZu+ugSyiA#AWO_ww4k7ujt=e zrrapid%bwh=}{hMs3ue%;mDf1xsDUb`$uwU(O)?2HQ*T{rbS6$NJ33WdFM@B@yy9@ zaX&5%57O~8Omkdpwuo6=(Tk#IjUvD3!~gQo`VVmWGtSY4xS$t|Qpm`NvRb`0d}8J{ zPMNjUT*My~URph-Vs0+030 z2E!FFkG_g@bKcLtU4T^Pd1{qZH@-p{GSXK{*S*Uvb;DXp75Q{>4V>$ixahGq?+Rx?FeCi}#cjDXiEwc670Ff5HQCc*kvLu1xFJ z-}Opy&fMFzJOpQXdI$$w0UghUr-WbUR+Q0Ft={ODU3aRO81KrwDV_G;?0{o(X%iia zCEJH66A(-S9zt97WQH;2z`MygnBn!m>0Ysca6MMy#sxFxa9r)EORED`cMVKb%-pki zv`ia5_#*+6Wvab0x_N%J8EOFWpbWVEfvvp(wlYP8^G^kl>Ni&P4auENaMl)!A~?BR zd8E@NtjA~eF)P*d{apbfj)|{fvDCp>MgTW<)DmdJ=NT2}Zkw^~e$KV;(@pUoY|V!IJq&^Y&=_v1ER%9n_T-N-NkR8|Q*l@qFjHVo^#5XeJ6$yo!X}!pnOJuYMU~6nG z^G)GcH(*tfQ*iiv`quei#oH7peaH;Xr>EXH@fVUP-#@TD&SUyT(mnub%Z^6C&n~cK zgMv&1wxdq`gp9NB+U|XY6u_nBRooHqjP!k>F~$cCc&MB{_tZ}oeY%jv!&*#5qcYqQ zFOm-L7S9W_hPzNo!}s1YdW63Sufcpcd~{UZ5aganWGu9^#kkz$>QE`Vl*x)W#K7dE zr)CRB0}yO-lIdS9$+0g~IewV7j4vh>-2!z?nqep6%9dONVbqJjG!Sn z4Uyw_5x=m$bFKeSk1*H^YzcJ#hw^HXs>)rm+V;i+4>kA19etwW2K?z+t+9|LxlFgM zdT);?K;#?`4`s#d-PlVRkr)Iw3iO4stjaQ@$(wV8D6D1H#&vJpm=Llg2+MuD|3u-SErOht zhx)1(W=9$AmGQgxjcOb|2Nl~$F|NZm`aB_tdNxq|;soTYC}o?6t+C#g<5)5Np*t`c z(+OTwOqLHb>%nu>9~0>*viBWt1V zPihwsy()9nd5M!^=~1biphaL6vu5gyFECYS<@zU%8k2DCOA(On73Z=Ur+gV?L>SGj zG#;nwvI`^i46Ndk&CyIOsPyPKxS`AaE~(Xfh#|{ld=?gWJD^IpQ(P;RJ(ci}%Qss^qd6aYM{UEj`yz9RU9Si>@z@jIQ&y@7Ayb;TG zGSKjvUd8A@4SPJwn-*vHS0$DLW|n99an<-Wb{&IvIw2E#%x#*NcdJe^j8+7hv7xcp zQEAAj9Jt~TSV7P;&q3j5%?EDVqET(K?|@%IzBmbB>koeh`109Vbnc}$JM~5Pey3Y=3NsaR-I)7n zLqVtFx)}p@)59qg1Dkhz^p0O`1Oe>B-J)P_B!`(N1kto&0?ld|S51?|*Q06Q7fD`= z`DlT?@vr~oW$vcS^FPzy%ArAKHhF7~uQ~S<%SksYkRT%-5}t-tl{K;q&`k-{98Ag*OehZ! zSB!`8_|TTBhV+S7es-c&bC3JzhNzC}lPIe?SJ*MgIjzW0vr2QLN$ zUe&|y4lZX5y;6d65&k`wR;9^Sc}~tEd|)-@i*&LDye#~|U--WvkV1PVGOdR9v2gl5 zj@Ps{Z{mmWk$1sg5raO7A$Q$d5B$m>w@#0m^ny_x(`l@mq;&*jpU^x{*+RRGx{Kxm z0p*{it{))Ur((6~>i>|FiO4T+`!6kl4GD9~Qj@3ryzEPa5Gbzpeq3`*4Gio&s&3C- z;LK?ateR$#cY4aOp$TWr`odf-eQ^Nr38>K{MKSSBVYM-X$uEgqSVymG@WA(c3-?r) zvaTB8i4PRup^1CVex$@x+Z#!t1Hs zd{pvp0E}DXFYqojEX*~bJ_U{l;AGwk?M^}X&R9xUd0v~0nmtpLBH_Dagp#vn8Z+%q zK*H@XHZQjP)hFC%a~?%9pM&^5k>cDk+n44(V-7q*O}tpSu7lI7(}4UMGBS2{oq1w~ z%#WC;1D?8&?CZ~r*Bd9=q1@*Anr^o&Do}sI5V++Rgh<}AlSnE`(tS1+ox~MOF)Eb4{1)H~fio!bN1JvhAY?uJQnUAl@IdFAD!XjbGJ z6KFUx#Qo$Q2@7SxO&S87RPi3wJgd*c|gqTU2Xi@BTl z10Q{71s9w-P7ANpKPS9ZeRBSFfamOTqWo1T)X?56UDxgLXC)j{{*dTzozrXNu44pCY^)Bb{v>o}00T34J@QeVrNs z8y#q!wM+S3N*zv*Wo5)7oe~BXx^fc{9sLY@phALmb_Zj)VG8jZ&(> zsQX(3H$NP)AMfWUhWUSd{P*YGi@+UJkB>!g3wj(cGMg{ZSe`1?7Z%kw@eku_Vgi%q z0KKpOTcg@L+!W_7Xk0!qVK2G#6NI{-QDSL2 zXrjFDc)sDx-(tdpeDe(C=A4j2q4)fx)LzleQYO!~)2nARaLjS&>w+mCqVUfYZp zyssRfwGaa$s4Se~!|o`=fCN}O^4n3*WBtAJ##I9d`q!7uwBY%Gk=lPc=j7>;JrEQE zllV>>Ke^qn`N?@u6wLLpmc8=5H2*rP4d?vF{V>0*-#@c)I_5p=+H`lZZQPgDeM<1H zEvLHKpJ~3YjN_Tp&PIFItYrGr?b{i0)54bbAQKmXpu?ICk^m)CW6xnnmm98UNYHny zN8<9;&phf5z&GVA0@@nJdfE~5h<%;$p_eZ%J@nE`aZH}3m}5K-GA8s0o;4oUhfqXN zBm4k_(5-%x)oY2`h;A=>N2Z_tm0)?eIe%aLUxvmaoi-@jaHm?*0oUq&V=+#rQ?55q zZpYcNG?WfGiTuI~I+%qnlKRJTV&5fofwP7G+ex4E4=a|%_uG9>a6e3N+jEo zPvqd6K*Lg8e-vZnhp?b1>1v$I{GJ@nFKESMls4~WL=Jv_=>}&F&PGHR4~UxZfT?`o z4wXA|y&)_btSJ#ynNbNFu!o-lz*ss5=#a6yH;`hVNg2$+pWR}-?2E)1>ns0aRI4^~ z0Y)RmzoUT>iB={pWg=L6DB*-eYQAtod0Pn*`9`sN`k4kETP}hoBGVcyer2dTyeyfY zk7_>rW>7PztBPV=`AsV{1|?-X2n9jI(YgjFew_f^@EPZ))?VK5GgSp>=K;(UqyRO* zg*vtf?f7P9-D~VYf_cH&n){4p>-B*~va4(jOa8Ir*JIX)Cr(m1?lYbh8u43GZXae7 z2N*ot>6p2KWzc~jWj##OpkA5uXmi(yhA~XgTNY^D4Q@Gf_SPuo{blwAA{gmYoT!PN zfe*eh!2iQXvrit)rP;DsuhqE3`Rb|S0+)P6AKdr6aPHOa0o{r=Z#cqZ9`nP?uEzK5 zy#&eG_M){;nxWB97pl4EyZdyxu`cA`--P(8jrLHN_bFT>nn6T!CJIK*1DEmUNjZGV z%@Ajy+6I8O?%*^I2%Ae4YU_b04rgWM%B30ORQhE zTkJtVAwj4bytC+!i{7(KH=kxR5x8xARXsWH7aaIfi#5NPwJN4?yd0~R23Ii$7drq) zBL&iG3H|E3F~WSLHn3Zo98LBE!5eduy6+oGq0 z7uhGaOB{_SdkKv1G**!hlH}_~ zy^ws%Gxu3hau*d8T9UrahL@`Lc0Vn~M%jpm-eOKAH1lU`lDM*Hy9r@lJvImev3+C) z-zx7%>gl5U`ot*x8v1+RRlBX2GH#z$zm%b?43+(5YOWT@WUZwYaQD5gHP}D} zJoKgA|F8zF09kAx(X%=GkOG~u_Y@4h3^_Gs!&9FCwE>6VPTeI|9RVw zNAgQeZ(O+;gywzK)ENWA7r`gRwb~5wFujkT zQG!uK%fz)&uau#0;R;C$c7bA0XKe8)6YM!B$SqavmoW&%^O;t_?g#|GbsFJ@GO-fZ zzh(qgR|4kz9DoXg4FbylY5}2D-lYs}`r?`qbY7^*grscrN(BD>4}l9Xa?(Tct^0KG z)M|6?U^m1ue8Z`YiFv1(7*}Yaud0sl;rwF);@ihoNuL$VEAG-U$Z3Ef>atlC^(@)3 z)V(IiIL0R2G7YU+0L|LGlc%A1f9mK=@)PQ$J_u;OGw<~T<`L8>QXl8=iGa(?gij|6 zy!DmCCskhCuSRcoYv&v9I}~L1+dBe7p3M`VPX`>bwh5)c=DnwSPBjJ;wEKH%bs0s7wl6N3H+&&AB8^g;Q>{lc2R?uFC*a;5@IHMe@u@gs>{nJ zd-P6{54tLTy$f~u-J1Hm?QmV67d<~8Q~_Vi1SFtZ|0<~cj z>(FPg+CC;?O!~`wfdeq&Bj48cbknzJ7exEhmum5Z5p-tF2qzdsW9UtV7rekV7`{H& zA(|sYzwHeFt_z4^3;1YBNnHSS_h* zZCGcS+L1(#jw^81kVi)75 z5((j3t)9$m%*c#53Ul9BDs2@}IRB!sdD8N^|Z3ransE|*TpSXAN4OL5uj6GN&Gb@)@<8Of`et) z%k}Fw2)m00Um(=Hx9M*Sp|figuR^l_7@4?Ye<1Ch#E+jIRjb~Lp`LuHr>qk*N=tkP znP~Qe-UCkTS9}~(j+~hsGj_%c<9F3)`*9bquWt3K2D6^CV646x+bcBS#Kq>tXrr;( zB{Pnfq96CWCu(mxGwpX>gh5N+{>LnHpAX4;S*nK;9i_1OMQm5Jk6pV&9uFB~kZr-( z`Tp@Sd>m3TSqn1>@_EgSq%WEDLfD#(@t{Ef;I<7E3m=z=w-h=J6nu4~g#M1{t$ zUjgAkDLw~}n9QQvArYc2kf!^SgX?oC5gNMLFR7qKWBP|5b@g4Tg!5_#F+6X`_*&qPz}vhAauit-YDZUQY;{q}1LOZ7+< zq7pv)ko*H>yNWXArZYWy=V)>3{02_qR-Mrfuak)4-$E(ZF)lZrp7ScBZ;bQKpSxN9 z@f$N{7c*ooyf8N}#U+fhu-L+RjCWBYko=vh9!Y1YSJ+Y2LEpBxT}^H<;Pl1_JlqZDH|4CEQIi|VfIV-E-F^>O}qou%zI7W}`1pRm1 zgsh(d_rVK_Qi-G$@=x4|cyU-8U9l+S20cp z?%CM?a+>n5*4q?|TRXtr=i!-`%Kj&As~1fb=(vL9V@Iamt5cb)p8)N=Mp=|>pA9Tr zsj2mt`K<`?*+3DVc7{Jw5l>V=>9BeL=m~d1P*#SN!SK+6)ve95_L{hXgZ1m_5!K;2 znCfsb%%`sW)Cl-H_%!&p_mul#IJb@+rS3HOmbYHZXYTTsupXJIlD-qf@P2eHJi4~U z$uDYcnBc^j08Hgw%ACwfJ|RC-Hx>9E_m>^VEADqw3K|qNC-Vd?2Ei17|9>(CZ^KB!1!|OE|Lxx!WHxj8Fps<$2i?L>Upyu0 zuqTRH|B6L4N5{L8GPAf(BjsdDDds|dJZ9gfF`xp5_R2vu?-nEfVA$}+RI)IY1=Er) z8}Y6fH6T2n37Y6E;;%2W)A>lUi$2T(Fl>tL`*OK*Aqzbv05KW2z{Tt46XowG@oJ2X z+z}9Tb^=}`{O6nd!dk8U8$d1p|K&+{o(8&9$^VrpL-wS28sz``chz)DFIdMf|0hqL zI`42}eZX^ZSvh%Hr1!tNs5DCNiY7fIWR#lEuAd>a2@%>nWe{1daUJv)A%a4mNAbTk z#gyo6>o^C{rb_;=S#&EfknG^%?O;trs>1-HvF_UBXHdl)@puZ!2F`N z1@Q~x8@F2}yQbI8Fb&A3K11*+8t26Nd4Z;JR4LSum@4BFO_w2AVEFPikIWr?itAi5 zv|p|cDN7SpcQDYFcs2m}-omjnVu(gS1;~gBt%d!3+@|gdTKlFJL8Dutw4wOlG%|Uu zMr{H1L;URnRR0%cg;32-M@>J=44fPbeB^)oe;7Z;FrGWHz;lxr1DXFChZU1yR@z+!ap@o=T#?(# zL_+=xvXeL2t5%va8cF!JS^Z|r=l=j<-lVp+cBmQv3t+(yi_)L|4_AniXNw8sGoG!B zaNIdl|1ZuI0G6Q++)5_AUH&D!_0`($|IYCXH^)j$ieKR%kI3+(0WJ8=v9WAI3O5y1 zmDXJMPWbx?PO@SrBbB%}R+Ln54>KU05IUZqqQ4&=sjqHS9R4LQe=Vrj*NvjPxbS^8 znT$$AqBST1W*8&f7f?J+v$T7h{u^12cpjWUFtfd|xErmrP1saB{k5A1xVTAp^rbuM z2i-Jjlt#e4h}BD(l;iftpyrBzZ{qSX+{)=DzC|w1#;Mj##w$SwEp&2S^NPar3#ORmwPV?;ckwhqO^+FnVsUv453OBVS&PlpDeJXd%*&QQ@DH z%b?Vm9>tVx6VetjXJ*wH^%DiH3)Cca=3+(4D?>Nyy6pI}&jS+4^mZ{4%EcMJ!zr({ z;s7x!LWTZ?{a*`o!^>QXx!;_T!4(P|Cj}w+dFT>qmy}nk@*FztI!b#U#Tk>@Jb*X< z3~(Y?bMghn-ump|2(zMs-Fy^9Z`3lpg(VvHI=FqEJOc4NTQy& diff --git a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/RandomUtils.java b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/RandomUtils.java index 1cafbcd45..2e7555232 100644 --- a/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/RandomUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/RandomUtils.java @@ -9,6 +9,7 @@ import uk.co.jemos.podam.api.PodamFactory; import uk.co.jemos.podam.api.PodamFactoryImpl; import java.lang.reflect.Type; +import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.Arrays; import java.util.Date; @@ -52,6 +53,10 @@ public class RandomUtils { } return RandomUtil.randomInt(); }); + // BigDecimal:限制精度在 DECIMAL(10,2) 范围内,避免 H2 等数据库溢出 + PODAM_FACTORY.getStrategy().addOrReplaceTypeManufacturer(BigDecimal.class, + (dataProviderStrategy, attributeMetadata, map) -> + BigDecimal.valueOf(RandomUtil.randomInt(0, 10000000), 2)); // LocalDateTime PODAM_FACTORY.getStrategy().addOrReplaceTypeManufacturer(LocalDateTime.class, (dataProviderStrategy, attributeMetadata, map) -> randomLocalDateTime()); diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/DictTypeConstants.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/DictTypeConstants.java index ea234136e..8d268ff1b 100644 --- a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/DictTypeConstants.java +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/DictTypeConstants.java @@ -7,32 +7,81 @@ package cn.iocoder.yudao.module.mes.enums; */ public interface DictTypeConstants { + // ========== 基础数据 (MD) ========== String MES_MD_ITEM_OR_PRODUCT = "mes_md_item_or_product"; // MES 物料产品标识 + String MES_MD_AUTO_CODE_PART_TYPE = "mes_md_auto_code_part_type"; // MES 分段类型 + String MES_MD_AUTO_CODE_CYCLE_METHOD = "mes_md_auto_code_cycle_method"; // MES 循环方式 + String MES_MD_AUTO_CODE_PADDED_METHOD = "mes_md_auto_code_padded_method"; // MES 补齐方式 String MES_CLIENT_TYPE = "mes_client_type"; // MES 客户类型 String MES_VENDOR_LEVEL = "mes_vendor_level"; // MES 供应商级别 - String MES_CAL_HOLIDAY_TYPE = "mes_cal_holiday_type"; // MES 假期类型 - String MES_TM_TOOL_STATUS = "mes_tm_tool_status"; // MES 工具状态 - String MES_TM_MAINTEN_TYPE = "mes_tm_mainten_type"; // MES 保养维护类型 - String MES_CAL_SHIFT_TYPE = "mes_cal_shift_type"; // MES 轮班方式 - String MES_CAL_SHIFT_METHOD = "mes_cal_shift_method"; // MES 倒班方式 - String MES_CAL_CALENDAR_TYPE = "mes_cal_calendar_type"; // MES 班组类型 - String MES_CAL_PLAN_STATUS = "mes_cal_plan_status"; // MES 排班计划状态 - String MES_DV_MACHINERY_STATUS = "mes_dv_machinery_status"; // MES 设备状态 - String MES_DV_SUBJECT_TYPE = "mes_dv_subject_type"; // MES 点检保养项目类型 + + // ========== 生产计划与执行 (PRO) ========== + String MES_PRO_WORK_ORDER_STATUS = "mes_pro_work_order_status"; // MES 生产工单状态 + String MES_PRO_WORK_ORDER_SOURCE_TYPE = "mes_pro_work_order_source_type"; // MES 工单来源类型 + String MES_PRO_WORK_ORDER_TYPE = "mes_pro_work_order_type"; // MES 工单类型 + String MES_PRO_LINK_TYPE = "mes_pro_link_type"; // MES 工序关系类型 + String MES_TIME_UNIT_TYPE = "mes_time_unit_type"; // MES 时间单位 + String MES_PRO_ANDON_STATUS = "mes_pro_andon_status"; // MES 安灯处置状态 + String MES_PRO_ANDON_LEVEL = "mes_pro_andon_level"; // MES 安灯级别 + String MES_PRO_WORK_RECORD_TYPE = "mes_pro_work_record_type"; // MES 上下工状态类型 + String MES_PRO_FEEDBACK_STATUS = "mes_pro_feedback_status"; // MES 生产报工状态 + String MES_PRO_FEEDBACK_TYPE = "mes_pro_feedback_type"; // MES 生产报工类型 + String MES_PRO_FEEDBACK_CHANNEL = "mes_pro_feedback_channel"; // MES 生产报工途径 + String MES_PRO_TASK_STATUS = "mes_pro_task_status"; // MES 任务状态 + + // ========== 仓储条码与管理 (WM) ========== + String MES_BARCODE_FORMAT = "mes_barcode_format"; // MES 条码格式 + String MES_BARCODE_BIZ_TYPE = "mes_barcode_biz_type"; // MES 条码业务类型 + String MES_WM_TRANSACTION_TYPE = "mes_wm_transaction_type"; // MES 库存事务类型 + String MES_WM_QUALITY_STATUS = "mes_wm_quality_status"; // MES 质量状态(待检/合格/不合格) + + // ========== 仓储入库 (WM Receipt) ========== + String MES_WM_ARRIVAL_NOTICE_STATUS = "mes_wm_arrival_notice_status"; // MES 到货通知单状态 + String MES_WM_ITEM_RECEIPT_STATUS = "mes_wm_item_receipt_status"; // MES 采购入库单状态 + String MES_WM_PRODUCT_PRODUCE_STATUS = "mes_wm_product_produce_status"; // MES 生产入库单状态 + String MES_WM_MISC_RECEIPT_TYPE = "mes_wm_misc_receipt_type"; // MES 杂项入库类型 + String MES_WM_MISC_RECEIPT_STATUS = "mes_wm_misc_receipt_status"; // MES 杂项入库状态 + String MES_WM_OUTSOURCE_RECEIPT_STATUS = "mes_wm_outsource_receipt_status"; // MES 委外入库状态 + String MES_WM_PRODUCT_RECEIPT_STATUS = "mes_wm_product_receipt_status"; // MES 产品入库状态 + String MES_WM_RETURN_ISSUE_TYPE = "mes_wm_return_issue_type"; // MES 生产退料类型 + String MES_WM_RETURN_ISSUE_STATUS = "mes_wm_return_issue_status"; // MES 生产退料单状态 + String MES_WM_RETURN_SALES_STATUS = "mes_wm_return_sales_status"; // MES 销售退货状态 + + // ========== 仓储出库 (WM Issue) ========== + String MES_WM_MISC_ISSUE_TYPE = "mes_wm_misc_issue_type"; // MES 杂项出库类型 + String MES_WM_MISC_ISSUE_STATUS = "mes_wm_misc_issue_status"; // MES 杂项出库单状态 + String MES_WM_SALES_NOTICE_STATUS = "mes_wm_sales_notice_status"; // MES 发货通知单状态 + String MES_WM_PRODUCT_SALES_STATUS = "mes_wm_product_sales_status"; // MES 销售出库单状态 + String MES_WM_OUTSOURCE_ISSUE_STATUS = "mes_wm_outsource_issue_status"; // MES 委外出库状态 + String MES_WM_PRODUCT_ISSUE_STATUS = "mes_wm_product_issue_status"; // MES 生产领料状态 + String MES_WM_RETURN_VENDOR_STATUS = "mes_wm_return_vendor_status"; // MES 供应商退货单状态 + + // ========== 仓储移库与盘点 (WM Transfer) ========== + String MES_WM_TRANSFER_STATUS = "mes_wm_transfer_status"; // MES 转移单状态 + String MES_WM_TRANSFER_TYPE = "mes_wm_transfer_type"; // MES 转移单类型 + String MES_WM_STOCK_TAKING_PLAN_PARAM_TYPE = "mes_wm_stock_taking_plan_param_type"; // MES 盘点参数值类型 + String MES_WM_STOCK_TAKING_TYPE = "mes_wm_stock_taking_type"; // MES 盘点类型 + String MES_WM_STOCK_TAKING_TASK_STATUS = "mes_wm_stock_taking_task_status"; // MES 盘点任务状态 + String MES_WM_STOCK_TAKING_TASK_LINE_STATUS = "mes_wm_stock_taking_task_line_status"; // MES 盘点任务明细状态 + + // ========== 其它仓储 (WM Misc) ========== + String MES_WM_PACKAGE_STATUS = "mes_wm_package_status"; // MES 打包状态 + String MES_WM_ITEM_CONSUME_STATUS = "mes_wm_item_consume_status"; // MES 物料消耗状态 + + // ========== 质量管理 (QC) ========== String MES_INDICATOR_TYPE = "mes_indicator_type"; // MES 检测项类型 String MES_QC_RESULT_TYPE = "mes_qc_result_type"; // MES 质检结果值类型 String MES_DEFECT_TYPE = "mes_defect_type"; // MES 缺陷检测项类型 String MES_DEFECT_LEVEL = "mes_defect_level"; // MES 缺陷等级 - String MES_PRO_WORK_ORDER_STATUS = "mes_pro_work_order_status"; // MES 生产工单状态 - String MES_PRO_WORK_ORDER_SOURCE_TYPE = "mes_pro_work_order_source_type"; // MES 工单来源类型 - String MES_PRO_WORK_ORDER_TYPE = "mes_pro_work_order_type"; // MES 工单类型 String MES_QC_TYPE = "mes_qc_type"; // MES 检测种类(IQC/IPQC/OQC/RQC) - String MES_PRO_LINK_TYPE = "mes_pro_link_type"; // MES 工序关系类型 - String MES_TIME_UNIT_TYPE = "mes_time_unit_type"; // MES 时间单位 String MES_IPQC_TYPE = "mes_ipqc_type"; // MES IPQC 检验类型 String MES_ORDER_STATUS = "mes_order_status"; // MES 单据状态(IQC/IPQC/OQC/RQC 通用) String MES_QC_CHECK_RESULT = "mes_qc_check_result"; // MES 检测结果 String MES_QC_SOURCE_DOC_TYPE = "mes_qc_source_doc_type"; // MES 来源单据类型 + + // ========== 设备管理 (DV) ========== + String MES_DV_MACHINERY_STATUS = "mes_dv_machinery_status"; // MES 设备状态 + String MES_DV_SUBJECT_TYPE = "mes_dv_subject_type"; // MES 点检保养项目类型 String MES_DV_CYCLE_TYPE = "mes_dv_cycle_type"; // MES 点检保养周期类型 String MES_DV_CHECK_PLAN_STATUS = "mes_dv_check_plan_status"; // MES 点检保养方案状态 String MES_MAINTEN_RECORD_STATUS = "mes_mainten_record_status"; // MES 保养记录状态 @@ -41,23 +90,15 @@ public interface DictTypeConstants { String MES_DV_CHECK_RESULT = "mes_dv_check_result"; // MES 点检结果 String MES_DV_REPAIR_STATUS = "mes_dv_repair_status"; // MES 维修工单状态 String MES_DV_REPAIR_RESULT = "mes_dv_repair_result"; // MES 维修结果 - String MES_PRO_ANDON_STATUS = "mes_pro_andon_status"; // MES 安灯处置状态 - String MES_PRO_ANDON_LEVEL = "mes_pro_andon_level"; // MES 安灯级别 - String MES_PRO_WORK_RECORD_TYPE = "mes_pro_work_record_type"; // MES 上下工状态类型 - String MES_PRO_FEEDBACK_STATUS = "mes_pro_feedback_status"; // MES 生产报工状态 - String MES_PRO_FEEDBACK_TYPE = "mes_pro_feedback_type"; // MES 生产报工类型 - String MES_PRO_FEEDBACK_CHANNEL = "mes_pro_feedback_channel"; // MES 生产报工途径 - String MES_WM_ARRIVAL_NOTICE_STATUS = "mes_wm_arrival_notice_status"; // MES 到货通知单状态 - String MES_WM_ITEM_RECEIPT_STATUS = "mes_wm_item_receipt_status"; // MES 采购入库单状态 - String MES_WM_PRODUCT_PRODUCE_STATUS = "mes_wm_product_produce_status"; // MES 生产入库单状态 - String MES_WM_RETURN_VENDOR_STATUS = "mes_wm_return_vendor_status"; // MES 供应商退货单状态 - String MES_WM_QUALITY_STATUS = "mes_wm_quality_status"; // MES 质量状态(待检/合格/不合格) - String MES_WM_RETURN_ISSUE_STATUS = "mes_wm_return_issue_status"; // MES 生产退料单状态 - String MES_WM_RETURN_ISSUE_TYPE = "mes_wm_return_issue_type"; // MES 生产退料类型 - String MES_WM_MISC_ISSUE_TYPE = "mes_wm_misc_issue_type"; // MES 杂项出库类型 - String MES_WM_MISC_ISSUE_STATUS = "mes_wm_misc_issue_status"; // MES 杂项出库单状态 - String MES_WM_SALES_NOTICE_STATUS = "mes_wm_sales_notice_status"; // MES 发货通知单状态 - String MES_WM_TRANSFER_STATUS = "mes_wm_transfer_status"; // MES 转移单状态 - String MES_WM_TRANSFER_TYPE = "mes_wm_transfer_type"; // MES 转移单类型 + // ========== 排班日历 (CAL) ========== + String MES_CAL_HOLIDAY_TYPE = "mes_cal_holiday_type"; // MES 假期类型 + String MES_CAL_SHIFT_TYPE = "mes_cal_shift_type"; // MES 轮班方式 + String MES_CAL_SHIFT_METHOD = "mes_cal_shift_method"; // MES 倒班方式 + String MES_CAL_CALENDAR_TYPE = "mes_cal_calendar_type"; // MES 班组类型 + String MES_CAL_PLAN_STATUS = "mes_cal_plan_status"; // MES 排班计划状态 + + // ========== 工具管理 (TM) ========== + String MES_TM_TOOL_STATUS = "mes_tm_tool_status"; // MES 工具状态 + String MES_TM_MAINTEN_TYPE = "mes_tm_mainten_type"; // MES 保养维护类型 } diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java index aaee1b8f6..14c22c27c 100644 --- a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java @@ -18,11 +18,16 @@ public interface ErrorCodeConstants { ErrorCode MD_ITEM_TYPE_CODE_DUPLICATE = new ErrorCode(1_040_100_005, "同一父分类下已存在该编码的分类"); ErrorCode MD_ITEM_TYPE_PARENT_IS_CHILD = new ErrorCode(1_040_100_006, "不能设置自己的子分类为父分类"); ErrorCode MD_ITEM_TYPE_EXITS_ITEM = new ErrorCode(1_040_100_007, "该分类下存在物料,无法删除"); + ErrorCode MD_ITEM_TYPE_NOT_LEAF = new ErrorCode(1_040_100_008, "只能将物料挂载到叶子分类(该分类下存在子分类)"); // ========== MES 基础数据-计量单位(1-040-101-000) ========== ErrorCode MD_UNIT_MEASURE_NOT_EXISTS = new ErrorCode(1_040_101_000, "计量单位不存在"); ErrorCode MD_UNIT_MEASURE_CODE_DUPLICATE = new ErrorCode(1_040_101_001, "计量单位编码已存在"); ErrorCode MD_UNIT_MEASURE_HAS_ITEM = new ErrorCode(1_040_101_002, "该计量单位下存在物料,无法删除"); + ErrorCode MD_UNIT_MEASURE_HAS_SECONDARY = new ErrorCode(1_040_101_003, "该主单位下存在辅单位,无法删除"); + ErrorCode MD_UNIT_MEASURE_HAS_TASK_ISSUE = new ErrorCode(1_040_101_004, "该计量单位已被生产投料引用,无法删除"); + ErrorCode MD_UNIT_MEASURE_HAS_QC_TEMPLATE_INDICATOR = new ErrorCode(1_040_101_005, "该计量单位已被质检方案指标项引用,无法删除"); + ErrorCode MD_UNIT_MEASURE_HAS_QC_LINE = new ErrorCode(1_040_101_006, "该计量单位已被质检单据行引用,无法删除"); // ========== MES 基础数据-物料(1-040-102-000) ========== ErrorCode MD_ITEM_NOT_EXISTS = new ErrorCode(1_040_102_000, "物料不存在"); @@ -30,6 +35,7 @@ public interface ErrorCodeConstants { ErrorCode MD_ITEM_NAME_DUPLICATE = new ErrorCode(1_040_102_002, "物料名称已存在"); ErrorCode MD_ITEM_IMPORT_LIST_IS_EMPTY = new ErrorCode(1_040_102_003, "导入物料数据不能为空"); ErrorCode MD_ITEM_BATCH_REQUIRED = new ErrorCode(1_040_102_004, "当前物料启用了批次管理,请选择批次"); + ErrorCode MD_ITEM_IS_DISABLE = new ErrorCode(1_040_102_005, "物料已禁用"); // ========== MES 基础数据-物料批次属性配置(1-040-102-100) ========== ErrorCode MD_ITEM_BATCH_CONFIG_NOT_EXISTS = new ErrorCode(1_040_102_100, "物料批次属性配置不存在"); @@ -51,6 +57,10 @@ public interface ErrorCodeConstants { ErrorCode WM_BATCH_MOLD_REQUIRED = new ErrorCode(1_040_717_011, "批次配置要求模具不能为空"); ErrorCode WM_BATCH_LOT_NUMBER_REQUIRED = new ErrorCode(1_040_717_012, "批次配置要求生产批号不能为空"); ErrorCode WM_BATCH_QUALITY_STATUS_REQUIRED = new ErrorCode(1_040_717_013, "批次配置要求质量状态不能为空"); + ErrorCode WM_BATCH_NOT_EXISTS = new ErrorCode(1_040_717_014, "批次不存在"); + ErrorCode WM_BATCH_ITEM_MISMATCH = new ErrorCode(1_040_717_015, "批次不属于当前物料"); + ErrorCode WM_BATCH_CLIENT_MISMATCH = new ErrorCode(1_040_717_016, "批次不属于当前客户"); + ErrorCode WM_BATCH_VENDOR_MISMATCH = new ErrorCode(1_040_717_017, "批次不属于当前供应商"); // ========== MES 基础数据-客户(1-040-103-000) ========== ErrorCode MD_CLIENT_NOT_EXISTS = new ErrorCode(1_040_103_000, "客户不存在"); @@ -58,6 +68,7 @@ public interface ErrorCodeConstants { ErrorCode MD_CLIENT_NAME_DUPLICATE = new ErrorCode(1_040_103_002, "客户名称已存在"); ErrorCode MD_CLIENT_NICKNAME_DUPLICATE = new ErrorCode(1_040_103_003, "客户简称已存在"); ErrorCode MD_CLIENT_IMPORT_LIST_IS_EMPTY = new ErrorCode(1_040_103_004, "导入客户数据不能为空"); + ErrorCode MD_CLIENT_IS_DISABLE = new ErrorCode(1_040_103_005, "客户已禁用"); // ========== MES 基础数据-供应商(1-040-104-000) ========== ErrorCode MD_VENDOR_NOT_EXISTS = new ErrorCode(1_040_104_000, "供应商不存在"); @@ -66,6 +77,7 @@ public interface ErrorCodeConstants { ErrorCode MD_VENDOR_NICKNAME_DUPLICATE = new ErrorCode(1_040_104_003, "供应商简称已存在"); ErrorCode MD_VENDOR_IMPORT_LIST_IS_EMPTY = new ErrorCode(1_040_104_004, "导入供应商数据不能为空"); ErrorCode MD_VENDOR_HAS_REFERENCE = new ErrorCode(1_040_104_005, "该供应商已被其他业务引用,无法删除"); + ErrorCode MD_VENDOR_IS_DISABLE = new ErrorCode(1_040_104_006, "供应商已禁用"); // ========== MES 基础数据-车间(1-040-105-000) ========== ErrorCode MD_WORKSHOP_NOT_EXISTS = new ErrorCode(1_040_105_000, "车间不存在"); @@ -77,6 +89,7 @@ public interface ErrorCodeConstants { ErrorCode MD_WORKSTATION_NOT_EXISTS = new ErrorCode(1_040_106_000, "工作站不存在"); ErrorCode MD_WORKSTATION_CODE_DUPLICATE = new ErrorCode(1_040_106_001, "工作站编码已存在"); ErrorCode MD_WORKSTATION_NAME_DUPLICATE = new ErrorCode(1_040_106_002, "工作站名称已存在"); + ErrorCode MD_WORKSTATION_IS_DISABLE = new ErrorCode(1_040_106_003, "工作站已禁用"); // ========== MES 基础数据-设备资源(1-040-106-100) ========== ErrorCode MD_WORKSTATION_MACHINE_NOT_EXISTS = new ErrorCode(1_040_106_100, "设备资源记录不存在"); ErrorCode MD_WORKSTATION_MACHINE_EXISTS = new ErrorCode(1_040_106_101, "该设备已分配至工作站:{}"); @@ -91,6 +104,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不存在"); @@ -149,6 +163,7 @@ public interface ErrorCodeConstants { // ========== MES 设备管理-设备台账(1-040-301-000) ========== ErrorCode DV_MACHINERY_NOT_EXISTS = new ErrorCode(1_040_301_000, "设备不存在"); ErrorCode DV_MACHINERY_CODE_DUPLICATE = new ErrorCode(1_040_301_001, "设备编码已存在"); + ErrorCode DV_MACHINERY_IS_DISABLE = new ErrorCode(1_040_301_007, "设备已禁用"); ErrorCode DV_MACHINERY_IMPORT_LIST_IS_EMPTY = new ErrorCode(1_040_301_002, "导入设备数据不能为空"); ErrorCode DV_MACHINERY_HAS_CHECK_PLAN = new ErrorCode(1_040_301_003, "设备已关联点检计划,无法删除"); ErrorCode DV_MACHINERY_HAS_CHECK_RECORD = new ErrorCode(1_040_301_004, "设备已关联点检记录,无法删除"); @@ -159,6 +174,7 @@ public interface ErrorCodeConstants { ErrorCode DV_SUBJECT_NOT_EXISTS = new ErrorCode(1_040_304_000, "点检保养项目不存在"); ErrorCode DV_SUBJECT_CODE_DUPLICATE = new ErrorCode(1_040_304_001, "项目编码已存在"); ErrorCode DV_SUBJECT_USED_BY_CHECK_PLAN = new ErrorCode(1_040_304_002, "点检保养项目已被点检保养方案使用,无法删除"); + ErrorCode DV_SUBJECT_IS_DISABLE = new ErrorCode(1_040_304_003, "点检保养项目已禁用"); // ========== MES 设备管理-点检计划(1-040-302-000) ========== ErrorCode DV_CHECK_PLAN_NOT_EXISTS = new ErrorCode(1_040_302_000, "点检计划不存在"); @@ -167,6 +183,8 @@ 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, "点检保养方案类型与当前业务不匹配"); + ErrorCode DV_CHECK_PLAN_NOT_ENABLED_FOR_RECORD = new ErrorCode(1_040_302_007, "点检保养方案未启用,不允许创建记录"); // ========== 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, "该设备已关联到当前方案,请勿重复添加"); @@ -203,16 +221,19 @@ public interface ErrorCodeConstants { ErrorCode TM_TOOL_TYPE_CODE_DUPLICATE = new ErrorCode(1_040_400_001, "工具类型编码已存在"); ErrorCode TM_TOOL_TYPE_NAME_DUPLICATE = new ErrorCode(1_040_400_002, "工具类型名称已存在"); ErrorCode TM_TOOL_TYPE_HAS_TOOL = new ErrorCode(1_040_400_003, "该工具类型下存在工具,无法删除"); + ErrorCode TM_TOOL_TYPE_HAS_WORKSTATION_TOOL = new ErrorCode(1_040_400_004, "该工具类型已被工作站工装资源引用,无法删除"); // ========== MES 工具管理-工具台账(1-040-401-000) ========== ErrorCode TM_TOOL_NOT_EXISTS = new ErrorCode(1_040_401_000, "工具不存在"); ErrorCode TM_TOOL_CODE_DUPLICATE = new ErrorCode(1_040_401_001, "工具编码已存在"); + ErrorCode TM_TOOL_HAS_BATCH = new ErrorCode(1_040_401_002, "该工具已被批次引用,无法删除"); // ========== MES 生产管理-工序(1-040-500-000) ========== ErrorCode PRO_PROCESS_NOT_EXISTS = new ErrorCode(1_040_500_000, "工序不存在"); ErrorCode PRO_PROCESS_CODE_EXISTS = new ErrorCode(1_040_500_001, "工序编码已存在"); ErrorCode PRO_PROCESS_NAME_EXISTS = new ErrorCode(1_040_500_002, "工序名称已存在"); ErrorCode PRO_PROCESS_USED_BY_ROUTE = new ErrorCode(1_040_500_003, "工序已被工艺路线引用,无法删除"); + ErrorCode PRO_PROCESS_IS_DISABLE = new ErrorCode(1_040_500_004, "工序已禁用"); // ========== MES 生产管理-工序内容(1-040-500-100) ========== ErrorCode PRO_PROCESS_CONTENT_NOT_EXISTS = new ErrorCode(1_040_500_100, "工序内容不存在"); @@ -241,11 +262,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, "生产任务投料记录不存在"); @@ -278,6 +305,7 @@ public interface ErrorCodeConstants { ErrorCode PRO_CARD_CODE_DUPLICATE = new ErrorCode(1_040_507_001, "流转卡编码已存在"); ErrorCode PRO_CARD_STATUS_ERROR = new ErrorCode(1_040_507_002, "流转卡状态不正确"); ErrorCode PRO_CARD_CANCEL_NOT_ALLOWED = new ErrorCode(1_040_507_003, "已完成或已取消的流转卡不允许取消"); + ErrorCode PRO_CARD_NOT_PREPARE = new ErrorCode(1_040_507_004, "流转卡不是草稿状态,不允许修改或删除"); // ========== MES 生产管理-流转卡工序(1-040-507-100) ========== ErrorCode PRO_CARD_PROCESS_NOT_EXISTS = new ErrorCode(1_040_507_100, "流转卡工序记录不存在"); @@ -323,6 +351,11 @@ public interface ErrorCodeConstants { ErrorCode QC_IPQC_QUANTITY_MISMATCH = new ErrorCode(1_040_604_004, "合格品与不合格品数量之和须等于检测数量"); ErrorCode QC_IPQC_NO_TEMPLATE = new ErrorCode(1_040_604_005, "当前产品未配置 IPQC 检测模板"); ErrorCode QC_IPQC_CHECK_RESULT_EMPTY = new ErrorCode(1_040_604_006, "完成检验单前,检测结果必须填写"); + ErrorCode QC_IPQC_SOURCE_DOC_TYPE_UNKNOWN = new ErrorCode(1_040_604_007, "未知的 IPQC 来源单据类型"); + ErrorCode QC_IPQC_SOURCE_DOC_NO_PENDING_LINE = new ErrorCode(1_040_604_008, "来源报工单不存在待检产出行,无法创建 IPQC"); + ErrorCode QC_IPQC_SOURCE_LINE_NOT_BELONG = new ErrorCode(1_040_604_009, "来源单据行不属于该报工单"); + ErrorCode QC_IPQC_SOURCE_LINE_REQUIRED = new ErrorCode(1_040_604_010, "来源单据类型为报工时,来源产出行 ID 不能为空"); + ErrorCode QC_IPQC_SOURCE_LINE_NOT_PENDING = new ErrorCode(1_040_604_011, "来源产出行不是待检验状态"); // ========== MES 质量管理-过程检验行(1-040-604-100) ========== ErrorCode QC_IPQC_LINE_NOT_EXISTS = new ErrorCode(1_040_604_100, "过程检验行不存在"); @@ -333,6 +366,8 @@ public interface ErrorCodeConstants { // ========== MES 质量管理-检验结果(1-040-606-000) ========== ErrorCode QC_RESULT_NOT_EXISTS = new ErrorCode(1_040_606_000, "检验结果不存在"); + ErrorCode QC_RESULT_VALUE_FORMAT_INVALID = new ErrorCode(1_040_606_001, "检测值格式不正确:{}"); + ErrorCode QC_FINISH_INDICATOR_RESULT_REQUIRED = new ErrorCode(1_040_606_002, "完成检验单前,至少需要录入一条检测结果"); // ========== MES 质量管理-出货检验(1-040-607-000) ========== ErrorCode QC_OQC_NOT_EXISTS = new ErrorCode(1_040_607_000, "出货检验单不存在"); @@ -341,6 +376,8 @@ public interface ErrorCodeConstants { ErrorCode QC_OQC_QUANTITY_MISMATCH = new ErrorCode(1_040_607_004, "合格品与不合格品数量之和须等于检测数量"); ErrorCode QC_OQC_NO_TEMPLATE = new ErrorCode(1_040_607_005, "当前产品未配置 OQC 检测模板"); ErrorCode QC_OQC_CHECK_RESULT_EMPTY = new ErrorCode(1_040_607_006, "完成检验单前,检测结果必须填写"); + ErrorCode QC_OQC_SOURCE_DOC_TYPE_UNKNOWN = new ErrorCode(1_040_607_007, "未知的 OQC 来源单据类型"); + // ========== MES 质量管理-出货检验行(1-040-607-100) ========== ErrorCode QC_OQC_LINE_NOT_EXISTS = new ErrorCode(1_040_607_100, "出货检验行不存在"); @@ -399,6 +436,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 +447,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 +484,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 +501,8 @@ 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, "拣货明细不属于指定的领料出库单"); + ErrorCode WM_PRODUCT_ISSUE_NO_DETAIL = new ErrorCode(1_040_708_203, "领料出库单没有拣货明细,无法执行领出"); // ========== MES 仓库管理-生产入库单(1-040-709-000) ========== ErrorCode WM_PRODUCT_PRODUCE_NOT_EXISTS = new ErrorCode(1_040_709_000, "生产入库单不存在"); @@ -501,6 +545,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 +560,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 +635,20 @@ 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, "拣货明细的物料与销售出库单行的物料不一致"); + ErrorCode WM_PRODUCT_SALES_LINE_SALES_NOTICE_LINE_REQUIRED = new ErrorCode(1_040_714_017, + "出库单关联了发货通知单,必须选择发货通知单行"); + ErrorCode WM_PRODUCT_SALES_LINE_SALES_NOTICE_LINE_NOT_ALLOWED = new ErrorCode(1_040_714_018, + "出库单未关联发货通知单,不能选择发货通知单行"); + ErrorCode WM_PRODUCT_SALES_LINE_NOTICE_LINE_ITEM_MISMATCH = new ErrorCode(1_040_714_030, + "出库行物料与发货通知单行物料不一致"); + ErrorCode WM_PRODUCT_SALES_LINE_NOTICE_LINE_QUANTITY_MISMATCH = new ErrorCode(1_040_714_031, + "出库行数量与发货通知单行数量不一致"); + ErrorCode WM_PRODUCT_SALES_LINE_NOTICE_LINE_BATCH_MISMATCH = new ErrorCode(1_040_714_032, + "出库行批次号与发货通知单行批次号不一致"); + ErrorCode WM_PRODUCT_SALES_LINE_NOTICE_LINE_OQC_MISMATCH = new ErrorCode(1_040_714_033, + "出库行 OQC 检验标识与发货通知单行不一致"); // ========== MES 仓库管理-杂项出库单(1-040-715-000) ========== ErrorCode WM_MISC_ISSUE_NOT_EXISTS = new ErrorCode(1_040_715_000, "杂项出库单不存在"); @@ -616,8 +677,11 @@ 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, "发货通知单行为空,不能提交"); + ErrorCode WM_SALES_NOTICE_LINE_NOT_MATCH = new ErrorCode(1_040_720_012, "发货通知单行不属于指定的发货通知单"); // ========== MES 仓库管理-条码配置(1-040-730-000) ========== ErrorCode WM_BARCODE_CONFIG_NOT_EXISTS = new ErrorCode(1_040_730_000, "条码配置不存在"); diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/cal/MesCalShiftTypeEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/cal/MesCalShiftTypeEnum.java index 940cbc888..c85671e47 100644 --- a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/cal/MesCalShiftTypeEnum.java +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/cal/MesCalShiftTypeEnum.java @@ -19,7 +19,7 @@ import java.util.List; public enum MesCalShiftTypeEnum implements ArrayValuable { SINGLE(1, "单白班", ListUtil.of( - Pair.of("白班", new String[]{"08:00", "17:00"}) + Pair.of("白班", new String[]{"08:00", "18:00"}) )), TWO(2, "两班倒", ListUtil.of( Pair.of("白班", new String[]{"08:00", "20:00"}), @@ -45,7 +45,7 @@ public enum MesCalShiftTypeEnum implements ArrayValuable { * 班次配置列表 * * key: 班次名称(如 "白班", "夜班", "中班") - * value: [startTime, endTime](如 ["08:00", "17:00"]) + * value: [startTime, endTime](如 ["08:00", "18:00"]) */ private final List> shifts; diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmMiscReceiptTypeEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/dv/MesDvCheckPlanTypeEnum.java similarity index 60% rename from yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmMiscReceiptTypeEnum.java rename to yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/dv/MesDvCheckPlanTypeEnum.java index 072637efb..c088f8823 100644 --- a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmMiscReceiptTypeEnum.java +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/dv/MesDvCheckPlanTypeEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.mes.enums.wm; +package cn.iocoder.yudao.module.mes.enums.dv; import cn.iocoder.yudao.framework.common.core.ArrayValuable; import lombok.AllArgsConstructor; @@ -7,15 +7,18 @@ import lombok.Getter; import java.util.Arrays; /** - * MES 杂项入库类型枚举 + * MES 点检保养方案类型枚举 + * + * @author 芋道源码 */ @Getter @AllArgsConstructor -public enum MesWmMiscReceiptTypeEnum implements ArrayValuable { +public enum MesDvCheckPlanTypeEnum implements ArrayValuable { - ADJUST(1, "库存调整"); + CHECK(1, "点检"), + MAINTENANCE(2, "保养"); - public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesWmMiscReceiptTypeEnum::getType).toArray(Integer[]::new); + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesDvCheckPlanTypeEnum::getType).toArray(Integer[]::new); /** * 类型值 diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/dv/MesDvMaintenRecordStatusEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/dv/MesDvMaintenRecordStatusEnum.java index dd755ecec..b80ac7afb 100644 --- a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/dv/MesDvMaintenRecordStatusEnum.java +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/dv/MesDvMaintenRecordStatusEnum.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.mes.enums.dv; import cn.iocoder.yudao.framework.common.core.ArrayValuable; +import cn.iocoder.yudao.module.mes.enums.MesOrderStatusConstants; import lombok.AllArgsConstructor; import lombok.Getter; @@ -20,13 +21,13 @@ public enum MesDvMaintenRecordStatusEnum implements ArrayValuable { * * 对应 MesDvMaintenRecordService#createMaintenRecord 方法 */ - PREPARE(1, "草稿"), + PREPARE(MesOrderStatusConstants.PREPARE, "草稿"), /** * 已提交 * * 对应 MesDvMaintenRecordService#submitMaintenRecord 方法 */ - SUBMITTED(2, "已提交"); + SUBMITTED(MesOrderStatusConstants.FINISHED, "已提交"); public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesDvMaintenRecordStatusEnum::getStatus) .toArray(Integer[]::new); diff --git a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/md/autocode/MesMdAutoCodeRuleCodeEnum.java b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/md/autocode/MesMdAutoCodeRuleCodeEnum.java index 698ec85dd..1acb33c9f 100644 --- a/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/md/autocode/MesMdAutoCodeRuleCodeEnum.java +++ b/yudao-module-mes/yudao-module-mes-api/src/main/java/cn/iocoder/yudao/module/mes/enums/md/autocode/MesMdAutoCodeRuleCodeEnum.java @@ -12,10 +12,12 @@ import lombok.Getter; @AllArgsConstructor public enum MesMdAutoCodeRuleCodeEnum { + MD_ITEM_TYPE_CODE("MD_ITEM_TYPE_CODE", "物料分类编码"), MD_ITEM_CODE("MD_ITEM_CODE", "物料编码"), MD_VENDOR_CODE("MD_VENDOR_CODE", "供应商编码"), MD_CLIENT_CODE("MD_CLIENT_CODE", "客户编码"), MD_WORKSTATION_CODE("MD_WORKSTATION_CODE", "工作站编码"), + MD_WORKSHOP_CODE("MD_WORKSHOP_CODE", "车间编码"), TM_TOOL_TYPE_CODE("TM_TOOL_TYPE_CODE", "工具类型编码"), WM_ARRIVAL_NOTICE_CODE("WM_ARRIVAL_NOTICE_CODE", "到货通知单编码"), WM_ITEM_RECEIPT_CODE("WM_ITEM_RECEIPT_CODE", "采购入库单编码"), diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/MesDvCheckPlanMachineryController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/MesDvCheckPlanMachineryController.java index ef7a3d011..00dc6cb6c 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/MesDvCheckPlanMachineryController.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/MesDvCheckPlanMachineryController.java @@ -75,7 +75,7 @@ public class MesDvCheckPlanMachineryController { return BeanUtils.toBean(list, MesDvCheckPlanMachineryRespVO.class, vo -> MapUtils.findAndThen(machineryMap, vo.getMachineryId(), machinery -> vo.setMachineryCode(machinery.getCode()).setMachineryName(machinery.getName()) - .setMachineryBrand(machinery.getBrand()).setMachinerySpec(machinery.getSpec()) + .setMachineryBrand(machinery.getBrand()).setMachinerySpecification(machinery.getSpecification()) ) ); } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/machinery/MesDvCheckPlanMachineryRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/machinery/MesDvCheckPlanMachineryRespVO.java index 0d2b74267..f3e226a52 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/machinery/MesDvCheckPlanMachineryRespVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/machinery/MesDvCheckPlanMachineryRespVO.java @@ -28,7 +28,7 @@ public class MesDvCheckPlanMachineryRespVO { private String machineryBrand; @Schema(description = "规格型号", example = "HTF120") - private String machinerySpec; + private String machinerySpecification; @Schema(description = "备注") private String remark; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/MesDvCheckRecordController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/MesDvCheckRecordController.java index d6b55292e..39761d1aa 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/MesDvCheckRecordController.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/MesDvCheckRecordController.java @@ -46,10 +46,8 @@ public class MesDvCheckRecordController { @Resource private MesDvCheckRecordService checkRecordService; - @Resource private MesDvCheckPlanService checkPlanService; - @Resource private MesDvMachineryService machineryService; @@ -143,7 +141,7 @@ public class MesDvCheckRecordController { .setPlanCycleType(plan.getCycleType()).setPlanCycleCount(plan.getCycleCount())); MapUtils.findAndThen(machineryMap, vo.getMachineryId(), machinery -> vo .setMachineryCode(machinery.getCode()).setMachineryName(machinery.getName()) - .setMachineryBrand(machinery.getBrand()).setMachinerySpec(machinery.getSpec())); + .setMachineryBrand(machinery.getBrand()).setMachinerySpecification(machinery.getSpecification())); MapUtils.findAndThen(userMap, vo.getUserId(), user -> vo.setNickname(user.getNickname())); }); diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/MesDvCheckRecordRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/MesDvCheckRecordRespVO.java index 857d9dc10..2985316c0 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/MesDvCheckRecordRespVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/MesDvCheckRecordRespVO.java @@ -64,7 +64,7 @@ public class MesDvCheckRecordRespVO { @Schema(description = "规格型号", example = "X-100") @ExcelProperty("规格型号") - private String machinerySpec; + private String machinerySpecification; @Schema(description = "点检时间", requiredMode = Schema.RequiredMode.REQUIRED) @ExcelProperty("点检时间") diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/MesDvMachineryController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/MesDvMachineryController.java index e6d89e54d..932db2695 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/MesDvMachineryController.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/MesDvMachineryController.java @@ -48,10 +48,8 @@ public class MesDvMachineryController { @Resource private MesDvMachineryService machineryService; - @Resource private MesDvMachineryTypeService machineryTypeService; - @Resource private MesMdWorkshopService workshopService; @@ -126,7 +124,7 @@ public class MesDvMachineryController { // 手动创建导出 demo List list = Collections.singletonList( MesDvMachineryImportExcelVO.builder().code("EQ-001").name("示例设备") - .brand("示例品牌").spec("型号A").machineryTypeCode("MT-001") + .brand("示例品牌").specification("型号A").machineryTypeCode("MT-001") .workshopCode("WS-001").status(0).build() ); // 输出 diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryImportExcelVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryImportExcelVO.java index 64f8d824c..82b236455 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryImportExcelVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryImportExcelVO.java @@ -28,7 +28,7 @@ public class MesDvMachineryImportExcelVO { private String brand; @ExcelProperty("规格型号") - private String spec; + private String specification; @ExcelProperty("设备类型编码") private String machineryTypeCode; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryRespVO.java index 5e29fa881..5d46e4329 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryRespVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryRespVO.java @@ -33,7 +33,7 @@ public class MesDvMachineryRespVO { @Schema(description = "规格型号", example = "S7-300") @ExcelProperty("规格型号") - private String spec; + private String specification; @Schema(description = "设备类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") private Long machineryTypeId; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachinerySaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachinerySaveReqVO.java index 9ff0c5d84..e2aaad1b7 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachinerySaveReqVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachinerySaveReqVO.java @@ -26,7 +26,7 @@ public class MesDvMachinerySaveReqVO { private String brand; @Schema(description = "规格型号", example = "S7-300") - private String spec; + private String specification; @Schema(description = "设备类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") @NotNull(message = "设备类型不能为空") diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/MesDvMaintenRecordController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/MesDvMaintenRecordController.java index 5a9400c87..9ac93646c 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/MesDvMaintenRecordController.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/MesDvMaintenRecordController.java @@ -46,10 +46,8 @@ public class MesDvMaintenRecordController { @Resource private MesDvMaintenRecordService maintenRecordService; - @Resource private MesDvCheckPlanService checkPlanService; - @Resource private MesDvMachineryService machineryService; @@ -146,7 +144,7 @@ public class MesDvMaintenRecordController { .setPlanCycleCount(plan.getCycleCount())); MapUtils.findAndThen(machineryMap, vo.getMachineryId(), machinery -> vo .setMachineryCode(machinery.getCode()).setMachineryName(machinery.getName()) - .setMachineryBrand(machinery.getBrand()).setMachinerySpec(machinery.getSpec())); + .setMachineryBrand(machinery.getBrand()).setMachinerySpecification(machinery.getSpecification())); MapUtils.findAndThen(userMap, vo.getUserId(), user -> vo.setNickname(user.getNickname())); }); diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/MesDvMaintenRecordRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/MesDvMaintenRecordRespVO.java index 7b8d96266..a2448efbc 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/MesDvMaintenRecordRespVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/MesDvMaintenRecordRespVO.java @@ -64,7 +64,7 @@ public class MesDvMaintenRecordRespVO { @Schema(description = "规格型号", example = "X-100") @ExcelProperty("规格型号") - private String machinerySpec; + private String machinerySpecification; @Schema(description = "保养时间", requiredMode = Schema.RequiredMode.REQUIRED) @ExcelProperty("保养时间") diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/MesDvRepairController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/MesDvRepairController.java index 7b958cef8..2f7287df0 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/MesDvRepairController.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/MesDvRepairController.java @@ -48,7 +48,6 @@ public class MesDvRepairController { @Resource private MesDvRepairService repairService; - @Resource private MesDvMachineryService machineryService; @@ -160,7 +159,7 @@ public class MesDvRepairController { return BeanUtils.toBean(list, MesDvRepairRespVO.class, vo -> { MapUtils.findAndThen(machineryMap, vo.getMachineryId(), machinery -> vo .setMachineryCode(machinery.getCode()).setMachineryName(machinery.getName()) - .setMachineryBrand(machinery.getBrand()).setMachinerySpec(machinery.getSpec())); + .setMachineryBrand(machinery.getBrand()).setMachinerySpecification(machinery.getSpecification())); MapUtils.findAndThen(userMap, vo.getAcceptedUserId(), user -> vo.setAcceptedUserNickname(user.getNickname())); MapUtils.findAndThen(userMap, vo.getConfirmUserId(), diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/MesDvRepairRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/MesDvRepairRespVO.java index 48338084c..2a621ca8d 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/MesDvRepairRespVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/MesDvRepairRespVO.java @@ -44,7 +44,7 @@ public class MesDvRepairRespVO { @Schema(description = "规格型号", example = "X-100") @ExcelProperty("规格型号") - private String machinerySpec; + private String machinerySpecification; @Schema(description = "报修日期") @ExcelProperty("报修日期") diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientImportExcelVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientImportExcelVO.java index 64f5c1251..ee99e1ce7 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientImportExcelVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientImportExcelVO.java @@ -37,6 +37,39 @@ public class MesMdClientImportExcelVO { @ExcelProperty("客户邮箱地址") private String email; + @ExcelProperty("客户英文名称") + private String englishName; + + @ExcelProperty("客户简介") + private String description; + + @ExcelProperty("客户地址") + private String address; + + @ExcelProperty("客户官网地址") + private String website; + + @ExcelProperty("联系人1") + private String contact1Name; + + @ExcelProperty("联系人1-电话") + private String contact1Telephone; + + @ExcelProperty("联系人1-邮箱") + private String contact1Email; + + @ExcelProperty("联系人2") + private String contact2Name; + + @ExcelProperty("联系人2-电话") + private String contact2Telephone; + + @ExcelProperty("联系人2-邮箱") + private String contact2Email; + + @ExcelProperty("统一社会信用代码") + private String creditCode; + @ExcelProperty(value = "状态", converter = DictConvert.class) @DictFormat(cn.iocoder.yudao.module.system.enums.DictTypeConstants.COMMON_STATUS) private Integer status; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientSaveReqVO.java index 1e751837e..2166f927f 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientSaveReqVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientSaveReqVO.java @@ -1,8 +1,10 @@ package cn.iocoder.yudao.module.mes.controller.admin.md.client.vo; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; import lombok.Data; @Schema(description = "管理后台 - MES 客户新增/修改 Request VO") @@ -14,22 +16,28 @@ public class MesMdClientSaveReqVO { @Schema(description = "客户编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "C00184") @NotEmpty(message = "客户编码不能为空") + @Size(max = 64, message = "客户编码长度不能超过 64 个字符") private String code; @Schema(description = "客户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "比亚迪") @NotEmpty(message = "客户名称不能为空") + @Size(max = 255, message = "客户名称长度不能超过 255 个字符") private String name; @Schema(description = "客户简称", example = "比亚迪") + @Size(max = 255, message = "客户简称长度不能超过 255 个字符") private String nickname; @Schema(description = "客户英文名称", example = "BYD") + @Size(max = 255, message = "客户英文名称长度不能超过 255 个字符") private String englishName; @Schema(description = "客户简介", example = "比亚迪品牌诞生于深圳") + @Size(max = 500, message = "客户简介长度不能超过 500 个字符") private String description; @Schema(description = "客户LOGO地址", example = "https://xxx.com/logo.png") + @Size(max = 255, message = "客户LOGO地址长度不能超过 255 个字符") private String logo; @Schema(description = "客户类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @@ -37,36 +45,50 @@ public class MesMdClientSaveReqVO { private Integer type; @Schema(description = "客户地址", example = "深圳南山区") + @Size(max = 500, message = "客户地址长度不能超过 500 个字符") private String address; @Schema(description = "客户官网地址", example = "https://www.bydglobal.com") + @Size(max = 255, message = "客户官网地址长度不能超过 255 个字符") private String website; @Schema(description = "客户邮箱地址", example = "salse@bydglobal.com") + @Size(max = 255, message = "客户邮箱地址长度不能超过 255 个字符") + @Email(message = "客户邮箱地址格式不正确") private String email; @Schema(description = "客户电话", example = "123432222") + @Size(max = 64, message = "客户电话长度不能超过 64 个字符") private String telephone; @Schema(description = "联系人1", example = "张三") + @Size(max = 64, message = "联系人1长度不能超过 64 个字符") private String contact1Name; @Schema(description = "联系人1-电话", example = "122212312") + @Size(max = 64, message = "联系人1-电话长度不能超过 64 个字符") private String contact1Telephone; @Schema(description = "联系人1-邮箱", example = "s1@bydglobal.com") + @Size(max = 255, message = "联系人1-邮箱长度不能超过 255 个字符") + @Email(message = "联系人1-邮箱格式不正确") private String contact1Email; @Schema(description = "联系人2", example = "李四") + @Size(max = 64, message = "联系人2长度不能超过 64 个字符") private String contact2Name; @Schema(description = "联系人2-电话", example = "1132323232") + @Size(max = 64, message = "联系人2-电话长度不能超过 64 个字符") private String contact2Telephone; @Schema(description = "联系人2-邮箱", example = "s2@bydglobal.com") + @Size(max = 255, message = "联系人2-邮箱长度不能超过 255 个字符") + @Email(message = "联系人2-邮箱格式不正确") private String contact2Email; @Schema(description = "统一社会信用代码", example = "11212121") + @Size(max = 64, message = "统一社会信用代码长度不能超过 64 个字符") private String creditCode; @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") @@ -74,6 +96,7 @@ public class MesMdClientSaveReqVO { private Integer status; @Schema(description = "备注", example = "备注") + @Size(max = 500, message = "备注长度不能超过 500 个字符") private String remark; } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorImportExcelVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorImportExcelVO.java index 44aaa35cc..237e60385 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorImportExcelVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorImportExcelVO.java @@ -37,6 +37,39 @@ public class MesMdVendorImportExcelVO { @ExcelProperty("供应商邮箱地址") private String email; + @ExcelProperty("供应商英文名称") + private String englishName; + + @ExcelProperty("供应商简介") + private String description; + + @ExcelProperty("供应商地址") + private String address; + + @ExcelProperty("供应商官网地址") + private String website; + + @ExcelProperty("联系人1") + private String contact1Name; + + @ExcelProperty("联系人1-电话") + private String contact1Telephone; + + @ExcelProperty("联系人1-邮箱") + private String contact1Email; + + @ExcelProperty("联系人2") + private String contact2Name; + + @ExcelProperty("联系人2-电话") + private String contact2Telephone; + + @ExcelProperty("联系人2-邮箱") + private String contact2Email; + + @ExcelProperty("统一社会信用代码") + private String creditCode; + @ExcelProperty(value = "状态", converter = DictConvert.class) @DictFormat(cn.iocoder.yudao.module.system.enums.DictTypeConstants.COMMON_STATUS) private Integer status; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorSaveReqVO.java index 1a95f40c2..c17c653bf 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorSaveReqVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorSaveReqVO.java @@ -1,8 +1,10 @@ package cn.iocoder.yudao.module.mes.controller.admin.md.vendor.vo; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; import lombok.Data; @Schema(description = "管理后台 - MES 供应商新增/修改 Request VO") @@ -14,61 +16,82 @@ public class MesMdVendorSaveReqVO { @Schema(description = "供应商编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "V00101") @NotEmpty(message = "供应商编码不能为空") + @Size(max = 64, message = "供应商编码长度不能超过 64 个字符") private String code; @Schema(description = "供应商名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "海力德电子") @NotEmpty(message = "供应商名称不能为空") + @Size(max = 255, message = "供应商名称长度不能超过 255 个字符") private String name; @Schema(description = "供应商简称", example = "海力德") + @Size(max = 255, message = "供应商简称长度不能超过 255 个字符") private String nickname; @Schema(description = "供应商英文名称", example = "HLD Electronics") + @Size(max = 255, message = "供应商英文名称长度不能超过 255 个字符") private String englishName; @Schema(description = "供应商简介", example = "专业从事电子元器件生产与销售") + @Size(max = 500, message = "供应商简介长度不能超过 500 个字符") private String description; @Schema(description = "供应商LOGO地址", example = "https://xxx.com/logo.png") + @Size(max = 255, message = "供应商LOGO地址长度不能超过 255 个字符") private String logo; @Schema(description = "供应商等级", example = "A") + @Size(max = 64, message = "供应商等级长度不能超过 64 个字符") private String level; @Schema(description = "供应商评分", example = "95") private Integer score; @Schema(description = "供应商地址", example = "深圳市宝安区") + @Size(max = 500, message = "供应商地址长度不能超过 500 个字符") private String address; @Schema(description = "供应商官网地址", example = "https://www.hld-elec.com") + @Size(max = 255, message = "供应商官网地址长度不能超过 255 个字符") private String website; @Schema(description = "供应商邮箱地址", example = "info@hld-elec.com") + @Size(max = 255, message = "供应商邮箱地址长度不能超过 255 个字符") + @Email(message = "供应商邮箱地址格式不正确") private String email; @Schema(description = "供应商电话", example = "0755-12345678") + @Size(max = 64, message = "供应商电话长度不能超过 64 个字符") private String telephone; @Schema(description = "联系人1", example = "王经理") + @Size(max = 64, message = "联系人1长度不能超过 64 个字符") private String contact1Name; @Schema(description = "联系人1-电话", example = "13800138001") + @Size(max = 64, message = "联系人1-电话长度不能超过 64 个字符") private String contact1Telephone; @Schema(description = "联系人1-邮箱", example = "wang@hld-elec.com") + @Size(max = 255, message = "联系人1-邮箱长度不能超过 255 个字符") + @Email(message = "联系人1-邮箱格式不正确") private String contact1Email; @Schema(description = "联系人2", example = "赵助理") + @Size(max = 64, message = "联系人2长度不能超过 64 个字符") private String contact2Name; @Schema(description = "联系人2-电话", example = "13800138002") + @Size(max = 64, message = "联系人2-电话长度不能超过 64 个字符") private String contact2Telephone; @Schema(description = "联系人2-邮箱", example = "zhao@hld-elec.com") + @Size(max = 255, message = "联系人2-邮箱长度不能超过 255 个字符") + @Email(message = "联系人2-邮箱格式不正确") private String contact2Email; @Schema(description = "统一社会信用代码", example = "91440300MA5EXAMPLE") + @Size(max = 64, message = "统一社会信用代码长度不能超过 64 个字符") private String creditCode; @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") @@ -76,6 +99,7 @@ public class MesMdVendorSaveReqVO { private Integer status; @Schema(description = "备注", example = "备注") + @Size(max = 500, message = "备注长度不能超过 500 个字符") private String remark; } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/MesMdWorkshopController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/MesMdWorkshopController.java index ff825f7c1..04e3cb08d 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/MesMdWorkshopController.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/MesMdWorkshopController.java @@ -77,7 +77,11 @@ public class MesMdWorkshopController { @PreAuthorize("@ss.hasPermission('mes:md-workshop:query')") public CommonResult getWorkshop(@RequestParam("id") Long id) { MesMdWorkshopDO workshop = workshopService.getWorkshop(id); - return success(BeanUtils.toBean(workshop, MesMdWorkshopRespVO.class)); + if (workshop == null) { + return success(null); + } + List voList = buildWorkshopRespVOList(Collections.singletonList(workshop)); + return success(voList.get(0)); } @GetMapping("/page") @@ -92,8 +96,19 @@ public class MesMdWorkshopController { @Operation(summary = "获得车间精简列表", description = "只包含被开启的车间,主要用于前端的下拉选项") public CommonResult> getWorkshopSimpleList() { List list = workshopService.getWorkshopListByStatus(CommonStatusEnum.ENABLE.getStatus()); - return success(convertList(list, ws -> new MesMdWorkshopRespVO() - .setId(ws.getId()).setCode(ws.getCode()).setName(ws.getName()).setArea(ws.getArea()))); + if (CollUtil.isEmpty(list)) { + return success(Collections.emptyList()); + } + // 批量获取负责人信息 + Map userMap = adminUserApi.getUserMap( + convertSet(list, MesMdWorkshopDO::getChargeUserId)); + return success(convertList(list, ws -> { + MesMdWorkshopRespVO vo = new MesMdWorkshopRespVO() + .setId(ws.getId()).setCode(ws.getCode()).setName(ws.getName()).setArea(ws.getArea()); + MapUtils.findAndThen(userMap, ws.getChargeUserId(), + user -> vo.setChargeUserName(user.getNickname())); + return vo; + })); } @GetMapping("/export-excel") diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/MesProCardController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/MesProCardController.java index 1fe17f526..288f36bd1 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/MesProCardController.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/MesProCardController.java @@ -47,13 +47,10 @@ public class MesProCardController { @Resource private MesProCardService cardService; - @Resource private MesProWorkOrderService workOrderService; - @Resource private MesMdItemService itemService; - @Resource private MesMdUnitMeasureService unitMeasureService; @@ -128,12 +125,6 @@ public class MesProCardController { return success(new PageResult<>(buildCardRespVOList(pageResult.getList()), pageResult.getTotal())); } - @GetMapping("/simple-list") - @Operation(summary = "获得生产流转卡精简列表", description = "主要用于前端的下拉选项") - public CommonResult> getCardSimpleList() { - List list = cardService.getCardSimpleList(); - return success(buildCardRespVOList(list)); - } @GetMapping("/export-excel") @Operation(summary = "导出生产流转卡 Excel") diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/vo/MesProCardRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/vo/MesProCardRespVO.java index 59e2c7e68..4e3fca97b 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/vo/MesProCardRespVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/vo/MesProCardRespVO.java @@ -32,13 +32,13 @@ public class MesProCardRespVO { @ExcelProperty("工单名称") private String workOrderName; + @Schema(description = "产品物料编号", example = "200") + private Long itemId; + @Schema(description = "批次号", example = "BATCH-001") @ExcelProperty("批次号") private String batchCode; - @Schema(description = "产品物料编号", example = "200") - private Long itemId; - @Schema(description = "产品编码", example = "P-001") @ExcelProperty("产品编码") private String itemCode; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/vo/MesProCardSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/vo/MesProCardSaveReqVO.java index be96ca15c..812f58186 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/vo/MesProCardSaveReqVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/vo/MesProCardSaveReqVO.java @@ -22,13 +22,13 @@ public class MesProCardSaveReqVO { @NotNull(message = "生产工单不能为空") private Long workOrderId; - @Schema(description = "批次号", example = "BATCH-001") - private String batchCode; - @Schema(description = "产品物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "200") @NotNull(message = "产品物料不能为空") private Long itemId; + @Schema(description = "批次号", example = "BATCH-001") + private String batchCode; + @Schema(description = "流转数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") @NotNull(message = "流转数量不能为空") private BigDecimal transferedQuantity; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/MesProFeedbackController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/MesProFeedbackController.java index f601f05c9..787c3bd01 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/MesProFeedbackController.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/MesProFeedbackController.java @@ -49,7 +49,7 @@ import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPOR import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + @Tag(name = "管理后台 - MES 生产报工") @RestController @@ -158,7 +158,7 @@ public class MesProFeedbackController { @Parameter(name = "id", description = "编号", required = true) @PreAuthorize("@ss.hasPermission('mes:pro-feedback:approve')") public CommonResult approveFeedback(@RequestParam("id") Long id) { - return success(feedbackService.approveFeedback(id, getLoginUserId())); + return success(feedbackService.approveFeedback(id)); } // ==================== 拼接 VO ==================== diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/MesProTaskController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/MesProTaskController.java index e43f327a7..20fbfb94d 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/MesProTaskController.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/MesProTaskController.java @@ -39,12 +39,13 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProcessDO; +import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteProcessService; + import java.io.IOException; import java.math.BigDecimal; import java.math.RoundingMode; -import java.util.Collections; -import java.util.List; -import java.util.Map; +import java.util.*; import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -59,24 +60,20 @@ public class MesProTaskController { @Resource private MesProTaskService taskService; - @Resource private MesProWorkOrderService workOrderService; - @Resource private MesMdWorkstationService workstationService; - @Resource private MesProProcessService processService; - @Resource private MesMdItemService itemService; - @Resource private MesMdClientService clientService; - @Resource private MesMdUnitMeasureService unitMeasureService; + @Resource + private MesProRouteProcessService routeProcessService; @PostMapping("/create") @Operation(summary = "创建生产任务") @@ -122,18 +119,6 @@ public class MesProTaskController { return success(new PageResult<>(buildTaskRespVOList(pageResult.getList()), pageResult.getTotal())); } - @GetMapping("/simple-list") - @Operation(summary = "获得生产任务精简列表", description = "主要用于前端的下拉选项") - public CommonResult> getTaskSimpleList( - @RequestParam(value = "workOrderId", required = false) Long workOrderId) { - List list = taskService.getTaskListByWorkOrderId(workOrderId); - return success(convertList(list, task -> new MesProTaskRespVO() - .setId(task.getId()).setCode(task.getCode()).setName(task.getName()) - .setWorkOrderId(task.getWorkOrderId()).setWorkstationId(task.getWorkstationId()) - .setRouteId(task.getRouteId()).setProcessId(task.getProcessId()) - .setItemId(task.getItemId()).setStatus(task.getStatus()))); - } - @GetMapping("/gantt-list") @Operation(summary = "获得甘特图任务列表", description = "后端组装工单=project + 任务=task 列表") @PreAuthorize("@ss.hasPermission('mes:pro-task:query')") @@ -229,11 +214,24 @@ public class MesProTaskController { Map workstationMap = workstationService.getWorkstationMap( convertSet(list, MesProTaskDO::getWorkstationId)); Map processMap = processService.getProcessMap( - new java.util.ArrayList<>(convertSet(list, MesProTaskDO::getProcessId))); + new ArrayList<>(convertSet(list, MesProTaskDO::getProcessId))); Map itemMap = itemService.getItemMap( convertSet(list, MesProTaskDO::getItemId)); + Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); Map clientMap = clientService.getClientMap( convertSet(list, MesProTaskDO::getClientId)); + // 工序的 checkFlag:批量查询后构建 routeId -> processId -> checkFlag 的双层 Map + Set routeIds = convertSet(list, MesProTaskDO::getRouteId); + Map> routeProcessCheckFlagMap = new HashMap<>(); + if (CollUtil.isNotEmpty(routeIds)) { + List allRouteProcesses = routeProcessService.getRouteProcessListByRouteIds(routeIds); + for (MesProRouteProcessDO rp : allRouteProcesses) { + routeProcessCheckFlagMap + .computeIfAbsent(rp.getRouteId(), k -> new HashMap<>()) + .put(rp.getProcessId(), Boolean.TRUE.equals(rp.getCheckFlag())); + } + } // 拼接 VO return convertList(list, task -> { MesProTaskRespVO vo = BeanUtils.toBean(task, MesProTaskRespVO.class); @@ -243,10 +241,15 @@ public class MesProTaskController { vo.setWorkstationCode(ws.getCode()).setWorkstationName(ws.getName())); findAndThen(processMap, task.getProcessId(), p -> vo.setProcessName(p.getName())); - findAndThen(itemMap, task.getItemId(), item -> - vo.setItemCode(item.getCode()).setItemName(item.getName()).setItemSpec(item.getSpecification())); + findAndThen(itemMap, task.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()).setItemSpecification(item.getSpecification()); + findAndThen(unitMeasureMap, item.getUnitMeasureId(), unit -> + vo.setUnitMeasureName(unit.getName())); + }); findAndThen(clientMap, task.getClientId(), c -> vo.setClientName(c.getName())); + findAndThen(routeProcessCheckFlagMap, task.getRouteId(), processCheckMap -> + findAndThen(processCheckMap, task.getProcessId(), vo::setCheckFlag)); return vo; }); } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/MesProTaskIssueController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/MesProTaskIssueController.java index 00fa9b52f..2ffb4d8be 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/MesProTaskIssueController.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/MesProTaskIssueController.java @@ -40,10 +40,8 @@ public class MesProTaskIssueController { @Resource private MesProTaskIssueService taskIssueService; - @Resource private MesMdItemService itemService; - @Resource private MesMdUnitMeasureService unitMeasureService; @@ -115,7 +113,7 @@ public class MesProTaskIssueController { return cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList(list, issue -> { MesProTaskIssueRespVO vo = BeanUtils.toBean(issue, MesProTaskIssueRespVO.class); findAndThen(itemMap, issue.getItemId(), item -> - vo.setItemCode(item.getCode()).setItemName(item.getName()).setItemSpec(item.getSpecification())); + vo.setItemCode(item.getCode()).setItemName(item.getName()).setItemSpecification(item.getSpecification())); findAndThen(unitMap, issue.getUnitMeasureId(), unit -> vo.setUnitMeasureName(unit.getName())); return vo; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskIssueRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskIssueRespVO.java index 74e68369f..6e0833eb5 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskIssueRespVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskIssueRespVO.java @@ -22,21 +22,21 @@ public class MesProTaskIssueRespVO { @Schema(description = "工作站编号", example = "1") private Long workstationId; + @Schema(description = "来源单据类型", example = "MATERIAL_ISSUE") + private String sourceDocType; + @Schema(description = "来源单据编号", example = "1") private Long sourceDocId; + @Schema(description = "来源单据行编号", example = "1") + private Long sourceLineId; + @Schema(description = "来源单据编码", example = "DOC-001") private String sourceDocCode; - @Schema(description = "来源单据类型", example = "MATERIAL_ISSUE") - private String sourceDocType; - @Schema(description = "投料批次", example = "BATCH-001") private String batchCode; - @Schema(description = "来源单据行编号", example = "1") - private Long sourceLineId; - @Schema(description = "产品物料编号", example = "100") private Long itemId; @@ -47,7 +47,7 @@ public class MesProTaskIssueRespVO { private String itemName; @Schema(description = "规格型号", example = "100x200mm") - private String itemSpec; + private String itemSpecification; @Schema(description = "单位编号", example = "1") private Long unitMeasureId; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskIssueSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskIssueSaveReqVO.java index 7c2339a1f..e97df77ef 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskIssueSaveReqVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskIssueSaveReqVO.java @@ -23,22 +23,22 @@ public class MesProTaskIssueSaveReqVO { @Schema(description = "工作站编号", example = "1") private Long workstationId; + @Schema(description = "来源单据类型", example = "MATERIAL_ISSUE") + private String sourceDocType; + @Schema(description = "来源单据编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @NotNull(message = "来源单据编号不能为空") private Long sourceDocId; + @Schema(description = "来源单据行编号", example = "1") + private Long sourceLineId; + @Schema(description = "来源单据编码", example = "DOC-001") private String sourceDocCode; - @Schema(description = "来源单据类型", example = "MATERIAL_ISSUE") - private String sourceDocType; - @Schema(description = "投料批次", example = "BATCH-001") private String batchCode; - @Schema(description = "来源单据行编号", example = "1") - private Long sourceLineId; - @Schema(description = "产品物料编号", example = "100") private Long itemId; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskPageReqVO.java index b38b80148..28b4c060c 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskPageReqVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskPageReqVO.java @@ -8,6 +8,7 @@ import lombok.ToString; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; +import java.util.List; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @@ -38,6 +39,12 @@ public class MesProTaskPageReqVO extends PageParam { @Schema(description = "任务状态", example = "0") private Integer status; + @Schema(description = "任务状态列表(IN 查询)", example = "[0, 1, 2]") + private List statuses; + + @Schema(description = "是否质检(关联工艺路线工序)", example = "true") + private Boolean checkFlag; + @Schema(description = "创建时间") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) private LocalDateTime[] createTime; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskRespVO.java index 743ece81b..468636fdc 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskRespVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/vo/MesProTaskRespVO.java @@ -56,7 +56,10 @@ public class MesProTaskRespVO { private String itemName; @Schema(description = "规格型号", example = "100x200mm") - private String itemSpec; + private String itemSpecification; + + @Schema(description = "计量单位名称", example = "个") + private String unitMeasureName; @Schema(description = "排产数量", example = "100.00") private BigDecimal quantity; @@ -103,6 +106,9 @@ public class MesProTaskRespVO { @Schema(description = "任务状态", example = "0") private Integer status; + @Schema(description = "是否质检(派生自工艺路线工序 checkFlag)", example = "true") + private Boolean checkFlag; + @Schema(description = "备注", example = "备注") private String remark; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/MesProWorkOrderBomController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/MesProWorkOrderBomController.java index c28878c87..c2d586cde 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/MesProWorkOrderBomController.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/MesProWorkOrderBomController.java @@ -43,16 +43,12 @@ public class MesProWorkOrderBomController { @Resource private MesProWorkOrderBomService workOrderBomService; - @Resource private MesMdItemService itemService; - @Resource private MesMdUnitMeasureService unitMeasureService; - @Resource private MesMdItemTypeService itemTypeService; - @Resource private MesMdProductBomService productBomService; @@ -122,6 +118,8 @@ public class MesProWorkOrderBomController { Map itemMap = itemService.getItemMap(leafItems.keySet()); Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + Map itemTypeMap = itemTypeService.getItemTypeMap( + convertSet(itemMap.values(), MesMdItemDO::getItemTypeId)); List result = new ArrayList<>(leafItems.size()); for (Map.Entry entry : leafItems.entrySet()) { MesMdItemDO item = itemMap.get(entry.getKey()); @@ -130,9 +128,11 @@ public class MesProWorkOrderBomController { } MesProWorkOrderItemRespVO vo = new MesProWorkOrderItemRespVO() .setItemId(item.getId()).setQuantity(entry.getValue()) - .setItemCode(item.getCode()).setItemName(item.getName()).setItemSpec(item.getSpecification()); + .setItemCode(item.getCode()).setItemName(item.getName()).setItemSpecification(item.getSpecification()); MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName())); + MapUtils.findAndThen(itemTypeMap, item.getItemTypeId(), + itemType -> vo.setItemOrProduct(itemType.getItemOrProduct())); result.add(vo); } return success(result); @@ -155,7 +155,7 @@ public class MesProWorkOrderBomController { return BeanUtils.toBean(list, MesProWorkOrderBomRespVO.class, vo -> { MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { vo.setItemName(item.getName()).setItemCode(item.getCode()) - .setItemSpec(item.getSpecification()); + .setItemSpecification(item.getSpecification()); MapUtils.findAndThen(itemTypeMap, item.getItemTypeId(), itemType -> vo.setItemOrProduct(itemType.getItemOrProduct())); MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/MesProWorkOrderController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/MesProWorkOrderController.java index f13810b4a..152502e55 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/MesProWorkOrderController.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/MesProWorkOrderController.java @@ -47,16 +47,12 @@ public class MesProWorkOrderController { @Resource private MesProWorkOrderService workOrderService; - @Resource private MesMdItemService itemService; - @Resource private MesMdClientService clientService; - @Resource private MesMdVendorService vendorService; - @Resource private MesMdUnitMeasureService unitMeasureService; @@ -165,7 +161,7 @@ public class MesProWorkOrderController { return BeanUtils.toBean(list, MesProWorkOrderRespVO.class, vo -> { MapUtils.findAndThen(itemMap, vo.getProductId(), item -> { vo.setProductName(item.getName()).setProductCode(item.getCode()) - .setProductSpec(item.getSpecification()); + .setProductSpecification(item.getSpecification()); MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName())); }); diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderItemRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderItemRespVO.java index efd077f79..922bc243a 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderItemRespVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderItemRespVO.java @@ -19,7 +19,7 @@ public class MesProWorkOrderItemRespVO { private String itemName; @Schema(description = "规格型号", example = "0603") - private String itemSpec; + private String itemSpecification; @Schema(description = "单位名称", example = "个") private String unitMeasureName; @@ -27,4 +27,7 @@ public class MesProWorkOrderItemRespVO { @Schema(description = "需求数量", example = "1000.00") private BigDecimal quantity; + @Schema(description = "物料/产品标识", example = "ITEM") + private String itemOrProduct; + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderPageReqVO.java index 357fc314f..cc17629c9 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderPageReqVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderPageReqVO.java @@ -35,6 +35,9 @@ public class MesProWorkOrderPageReqVO extends PageParam { @Schema(description = "客户编号", example = "300") private Long clientId; + @Schema(description = "工单状态", example = "1") + private Integer status; + @Schema(description = "需求日期") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) private LocalDateTime[] requestDate; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderRespVO.java index a42d36b33..70e1530a9 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderRespVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderRespVO.java @@ -55,7 +55,7 @@ public class MesProWorkOrderRespVO { @Schema(description = "规格型号", example = "100x200mm") @ExcelProperty("规格型号") - private String productSpec; + private String productSpecification; @Schema(description = "单位名称", example = "个") @ExcelProperty("单位") diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/bom/MesProWorkOrderBomRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/bom/MesProWorkOrderBomRespVO.java index ca4e31eeb..140e49eef 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/bom/MesProWorkOrderBomRespVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/bom/MesProWorkOrderBomRespVO.java @@ -33,7 +33,7 @@ public class MesProWorkOrderBomRespVO { @Schema(description = "规格型号", example = "10K 0603") @ExcelProperty("规格型号") - private String itemSpec; + private String itemSpecification; @Schema(description = "单位编号", example = "300") private Long unitMeasureId; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defect/vo/MesQcDefectPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defect/vo/MesQcDefectPageReqVO.java index 7f2638cd9..dbd1b7a88 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defect/vo/MesQcDefectPageReqVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defect/vo/MesQcDefectPageReqVO.java @@ -18,8 +18,8 @@ public class MesQcDefectPageReqVO extends PageParam { @Schema(description = "缺陷描述", example = "外观缺陷") private String name; - @Schema(description = "检测项类型", example = "APPEARANCE") - private String type; + @Schema(description = "检测项类型", example = "2") + private Integer type; @Schema(description = "缺陷等级", example = "1") private Integer level; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defect/vo/MesQcDefectRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defect/vo/MesQcDefectRespVO.java index 37cb917a1..aee621184 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defect/vo/MesQcDefectRespVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defect/vo/MesQcDefectRespVO.java @@ -27,10 +27,10 @@ public class MesQcDefectRespVO { @ExcelProperty("缺陷描述") private String name; - @Schema(description = "检测项类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "APPEARANCE") + @Schema(description = "检测项类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") @ExcelProperty(value = "检测项类型", converter = DictConvert.class) @DictFormat(DictTypeConstants.MES_DEFECT_TYPE) - private String type; + private Integer type; @Schema(description = "缺陷等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @ExcelProperty(value = "缺陷等级", converter = DictConvert.class) diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defect/vo/MesQcDefectSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defect/vo/MesQcDefectSaveReqVO.java index 7fb00a5e2..0ff1b1ba0 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defect/vo/MesQcDefectSaveReqVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defect/vo/MesQcDefectSaveReqVO.java @@ -22,9 +22,9 @@ public class MesQcDefectSaveReqVO { @NotEmpty(message = "缺陷描述不能为空") private String name; - @Schema(description = "检测项类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "APPEARANCE") - @NotEmpty(message = "检测项类型不能为空") - private String type; + @Schema(description = "检测项类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @NotNull(message = "检测项类型不能为空") + private Integer type; @Schema(description = "缺陷等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @NotNull(message = "缺陷等级不能为空") @@ -34,4 +34,4 @@ public class MesQcDefectSaveReqVO { @Schema(description = "备注", example = "备注") private String remark; - } +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defectrecord/MesQcDefectRecordController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defectrecord/MesQcDefectRecordController.java index 0c60a5c39..604b395d3 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defectrecord/MesQcDefectRecordController.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defectrecord/MesQcDefectRecordController.java @@ -46,7 +46,7 @@ public class MesQcDefectRecordController { @DeleteMapping("/delete") @Operation(summary = "删除质检缺陷记录") @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('mes:qc-defect:update')") + @PreAuthorize("@ss.hasPermission('mes:qc-defect:delete')") public CommonResult deleteDefectRecord(@RequestParam("id") Long id) { defectRecordService.deleteDefectRecord(id); return success(true); diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicator/MesQcIndicatorController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicator/MesQcIndicatorController.java index e225452c1..14f49fefd 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicator/MesQcIndicatorController.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicator/MesQcIndicatorController.java @@ -77,13 +77,6 @@ public class MesQcIndicatorController { return success(BeanUtils.toBean(pageResult, MesQcIndicatorRespVO.class)); } - @GetMapping("/simple-list") - @Operation(summary = "获得质检指标精简列表", description = "主要用于前端的下拉选项") - public CommonResult> getIndicatorSimpleList() { - List list = indicatorService.getIndicatorList(); - return success(BeanUtils.toBean(list, MesQcIndicatorRespVO.class)); - } - @GetMapping("/export-excel") @Operation(summary = "导出质检指标 Excel") @PreAuthorize("@ss.hasPermission('mes:qc-indicator:export')") diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicator/vo/MesQcIndicatorPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicator/vo/MesQcIndicatorPageReqVO.java index 773814e28..ff92db5fd 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicator/vo/MesQcIndicatorPageReqVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicator/vo/MesQcIndicatorPageReqVO.java @@ -18,8 +18,8 @@ public class MesQcIndicatorPageReqVO extends PageParam { @Schema(description = "检测项名称", example = "长度") private String name; - @Schema(description = "检测项类型", example = "SIZE") - private String type; + @Schema(description = "检测项类型", example = "1") + private Integer type; @Schema(description = "结果值类型", example = "1") private Integer resultType; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicator/vo/MesQcIndicatorRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicator/vo/MesQcIndicatorRespVO.java index f4b7f9c34..f3f599566 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicator/vo/MesQcIndicatorRespVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicator/vo/MesQcIndicatorRespVO.java @@ -27,10 +27,10 @@ public class MesQcIndicatorRespVO { @ExcelProperty("检测项名称") private String name; - @Schema(description = "检测项类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "SIZE") + @Schema(description = "检测项类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @ExcelProperty(value = "检测项类型", converter = DictConvert.class) @DictFormat(DictTypeConstants.MES_INDICATOR_TYPE) - private String type; + private Integer type; @Schema(description = "检测工具", example = "卡尺") @ExcelProperty("检测工具") diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicator/vo/MesQcIndicatorSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicator/vo/MesQcIndicatorSaveReqVO.java index 6c692ef05..d7fa865d2 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicator/vo/MesQcIndicatorSaveReqVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicator/vo/MesQcIndicatorSaveReqVO.java @@ -20,9 +20,9 @@ public class MesQcIndicatorSaveReqVO { @NotEmpty(message = "检测项名称不能为空") private String name; - @Schema(description = "检测项类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "SIZE") - @NotEmpty(message = "检测项类型不能为空") - private String type; + @Schema(description = "检测项类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "检测项类型不能为空") + private Integer type; @Schema(description = "检测工具", example = "卡尺") private String tool; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/MesQcIpqcRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/MesQcIpqcRespVO.java index 10bd8a3a7..469076dd5 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/MesQcIpqcRespVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/MesQcIpqcRespVO.java @@ -34,12 +34,12 @@ public class MesQcIpqcRespVO { // ========== 来源单据 ========== - @Schema(description = "来源单据 ID", example = "200") - private Long sourceDocId; - @Schema(description = "来源单据类型", example = "304") private Integer sourceDocType; + @Schema(description = "来源单据 ID", example = "200") + private Long sourceDocId; + @Schema(description = "来源单据行 ID", example = "300") private Long sourceLineId; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/line/MesQcIpqcLineRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/line/MesQcIpqcLineRespVO.java index dba702073..8fab393ee 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/line/MesQcIpqcLineRespVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/line/MesQcIpqcLineRespVO.java @@ -27,8 +27,8 @@ public class MesQcIpqcLineRespVO { @Schema(description = "检测指标名称", example = "外观") private String indicatorName; - @Schema(description = "检测指标类型", example = "QUANTITATIVE") - private String indicatorType; + @Schema(description = "检测指标类型", example = "1") + private Integer indicatorType; @Schema(description = "检测工具", example = "卡尺") private String tool; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/MesQcIqcRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/MesQcIqcRespVO.java index ab51d361b..0c19e1c18 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/MesQcIqcRespVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/MesQcIqcRespVO.java @@ -30,12 +30,12 @@ public class MesQcIqcRespVO { // ========== 来源单据 ========== - @Schema(description = "来源单据 ID", example = "200") - private Long sourceDocId; - @Schema(description = "来源单据类型", example = "100") private Integer sourceDocType; + @Schema(description = "来源单据 ID", example = "200") + private Long sourceDocId; + @Schema(description = "来源单据行 ID", example = "300") private Long sourceLineId; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/line/MesQcIqcLineRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/line/MesQcIqcLineRespVO.java index d8170aee9..508dcbfd5 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/line/MesQcIqcLineRespVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/line/MesQcIqcLineRespVO.java @@ -27,8 +27,8 @@ public class MesQcIqcLineRespVO { @Schema(description = "检测指标名称", example = "外观") private String indicatorName; - @Schema(description = "检测指标类型", example = "QUANTITATIVE") - private String indicatorType; + @Schema(description = "检测指标类型", example = "1") + private Integer indicatorType; @Schema(description = "检测工具", example = "卡尺") private String tool; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/MesQcOqcRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/MesQcOqcRespVO.java index 8c314bb02..79d9bed32 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/MesQcOqcRespVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/MesQcOqcRespVO.java @@ -30,12 +30,12 @@ public class MesQcOqcRespVO { // ========== 来源单据 ========== - @Schema(description = "来源单据 ID", example = "200") - private Long sourceDocId; - @Schema(description = "来源单据类型", example = "118") private Integer sourceDocType; + @Schema(description = "来源单据 ID", example = "200") + private Long sourceDocId; + @Schema(description = "来源单据行 ID", example = "300") private Long sourceLineId; @@ -51,12 +51,12 @@ public class MesQcOqcRespVO { @ExcelProperty("客户简称") private String clientNickname; + // ========== 物料 ========== + @Schema(description = "批次号", example = "BC20250101") @ExcelProperty("批次号") private String batchCode; - // ========== 物料 ========== - @Schema(description = "产品物料 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "20") private Long itemId; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/MesQcOqcSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/MesQcOqcSaveReqVO.java index d4ecc07d2..98c20eb6b 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/MesQcOqcSaveReqVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/MesQcOqcSaveReqVO.java @@ -26,12 +26,12 @@ public class MesQcOqcSaveReqVO { // ========== 来源单据 ========== - @Schema(description = "来源单据 ID", example = "200") - private Long sourceDocId; - @Schema(description = "来源单据类型", example = "118") private Integer sourceDocType; + @Schema(description = "来源单据 ID", example = "200") + private Long sourceDocId; + @Schema(description = "来源单据行 ID", example = "300") private Long sourceLineId; @@ -41,11 +41,11 @@ public class MesQcOqcSaveReqVO { @NotNull(message = "客户不能为空") private Long clientId; + // ========== 物料 ========== + @Schema(description = "批次号", example = "BC20250101") private String batchCode; - // ========== 物料 ========== - @Schema(description = "产品物料 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "20") @NotNull(message = "产品物料不能为空") private Long itemId; @@ -74,9 +74,8 @@ public class MesQcOqcSaveReqVO { // ========== 检验 ========== - @Schema(description = "检测人员用户 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "检测人员不能为空") - private Long inspectorUserId; + @Schema(description = "检测结果", example = "1") + private Integer checkResult; @Schema(description = "出货日期", requiredMode = Schema.RequiredMode.REQUIRED) @NotNull(message = "出货日期不能为空") @@ -86,8 +85,9 @@ public class MesQcOqcSaveReqVO { @NotNull(message = "检测日期不能为空") private LocalDateTime inspectDate; - @Schema(description = "检测结果", example = "1") - private Integer checkResult; + @Schema(description = "检测人员用户 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "检测人员不能为空") + private Long inspectorUserId; @Schema(description = "备注", example = "备注") private String remark; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/line/MesQcOqcLineRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/line/MesQcOqcLineRespVO.java index ae69409a6..39cf91177 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/line/MesQcOqcLineRespVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/line/MesQcOqcLineRespVO.java @@ -27,8 +27,8 @@ public class MesQcOqcLineRespVO { @Schema(description = "检测指标名称", example = "外观") private String indicatorName; - @Schema(description = "检测指标类型", example = "QUANTITATIVE") - private String indicatorType; + @Schema(description = "检测指标类型", example = "1") + private Integer indicatorType; @Schema(description = "检测工具", example = "卡尺") private String tool; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/pendinginspect/vo/MesQcPendingInspectRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/pendinginspect/vo/MesQcPendingInspectRespVO.java index 6e7f5c9a6..effe2a558 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/pendinginspect/vo/MesQcPendingInspectRespVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/pendinginspect/vo/MesQcPendingInspectRespVO.java @@ -10,17 +10,16 @@ import java.time.LocalDateTime; @Data public class MesQcPendingInspectRespVO { - @Schema(description = "来源单据 ID", example = "100") - private Long sourceDocId; - @Schema(description = "来源单据类型(MesBizTypeConstants)", example = "100") private Integer sourceDocType; - @Schema(description = "来源单据编号", example = "AN2025001") - private String sourceDocCode; + @Schema(description = "来源单据 ID", example = "100") + private Long sourceDocId; @Schema(description = "来源单据行 ID", example = "200") private Long sourceLineId; + @Schema(description = "来源单据编号", example = "AN2025001") + private String sourceDocCode; @Schema(description = "检验类型(MesQcTypeEnum)", example = "1") private Integer qcType; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/vo/MesQcRqcRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/vo/MesQcRqcRespVO.java index df8d1bc98..d6cf18485 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/vo/MesQcRqcRespVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/vo/MesQcRqcRespVO.java @@ -30,12 +30,12 @@ public class MesQcRqcRespVO { // ========== 来源单据 ========== - @Schema(description = "来源单据 ID", example = "200") - private Long sourceDocId; - @Schema(description = "来源单据类型", example = "116") private Integer sourceDocType; + @Schema(description = "来源单据 ID", example = "200") + private Long sourceDocId; + @Schema(description = "来源单据行 ID", example = "300") private Long sourceLineId; @@ -85,6 +85,26 @@ public class MesQcRqcRespVO { @ExcelProperty("不合格数量") private BigDecimal unqualifiedQuantity; + // ========== 缺陷统计 ========== + + @Schema(description = "致命缺陷率(%)", example = "5.00") + private BigDecimal criticalRate; + + @Schema(description = "严重缺陷率(%)", example = "10.00") + private BigDecimal majorRate; + + @Schema(description = "轻微缺陷率(%)", example = "15.00") + private BigDecimal minorRate; + + @Schema(description = "致命缺陷数量", example = "5") + private Integer criticalQuantity; + + @Schema(description = "严重缺陷数量", example = "10") + private Integer majorQuantity; + + @Schema(description = "轻微缺陷数量", example = "15") + private Integer minorQuantity; + // ========== 检验 ========== @Schema(description = "检测结果", example = "1") @@ -110,26 +130,6 @@ public class MesQcRqcRespVO { @ExcelProperty("备注") private String remark; - // ========== 缺陷统计 ========== - - @Schema(description = "致命缺陷数量", example = "5") - private Integer criticalQuantity; - - @Schema(description = "严重缺陷数量", example = "10") - private Integer majorQuantity; - - @Schema(description = "轻微缺陷数量", example = "15") - private Integer minorQuantity; - - @Schema(description = "致命缺陷率(%)", example = "5.00") - private BigDecimal criticalRate; - - @Schema(description = "严重缺陷率(%)", example = "10.00") - private BigDecimal majorRate; - - @Schema(description = "轻微缺陷率(%)", example = "15.00") - private BigDecimal minorRate; - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) @ExcelProperty("创建时间") private LocalDateTime createTime; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/vo/MesQcRqcSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/vo/MesQcRqcSaveReqVO.java index 3b9fbf1d1..ae9629dd9 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/vo/MesQcRqcSaveReqVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/vo/MesQcRqcSaveReqVO.java @@ -32,12 +32,12 @@ public class MesQcRqcSaveReqVO { // ========== 来源单据 ========== - @Schema(description = "来源单据 ID", example = "200") - private Long sourceDocId; - @Schema(description = "来源单据类型", example = "116") private Integer sourceDocType; + @Schema(description = "来源单据 ID", example = "200") + private Long sourceDocId; + @Schema(description = "来源单据行 ID", example = "300") private Long sourceLineId; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/vo/line/MesQcRqcLineRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/vo/line/MesQcRqcLineRespVO.java index da3874772..2f785ce9b 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/vo/line/MesQcRqcLineRespVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/vo/line/MesQcRqcLineRespVO.java @@ -27,8 +27,8 @@ public class MesQcRqcLineRespVO { @Schema(description = "检测指标名称", example = "外观") private String indicatorName; - @Schema(description = "检测指标类型", example = "QUANTITATIVE") - private String indicatorType; + @Schema(description = "检测指标类型", example = "1") + private Integer indicatorType; @Schema(description = "检测工具", example = "卡尺") private String tool; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/MesQcTemplateController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/MesQcTemplateController.java index 735c9d3c6..3bd5e72cc 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/MesQcTemplateController.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/MesQcTemplateController.java @@ -77,13 +77,6 @@ public class MesQcTemplateController { return success(BeanUtils.toBean(pageResult, MesQcTemplateRespVO.class)); } - @GetMapping("/simple-list") - @Operation(summary = "获得质检方案精简列表", description = "主要用于前端的下拉选项") - public CommonResult> getTemplateSimpleList() { - List list = templateService.getTemplateList(); - return success(BeanUtils.toBean(list, MesQcTemplateRespVO.class)); - } - @GetMapping("/export-excel") @Operation(summary = "导出质检方案 Excel") @PreAuthorize("@ss.hasPermission('mes:qc-template:export')") diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/indicator/MesQcTemplateIndicatorRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/indicator/MesQcTemplateIndicatorRespVO.java index 67d38388f..e32be8704 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/indicator/MesQcTemplateIndicatorRespVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/indicator/MesQcTemplateIndicatorRespVO.java @@ -63,9 +63,9 @@ public class MesQcTemplateIndicatorRespVO { @ExcelProperty("检测项名称") private String indicatorName; - @Schema(description = "检测项类型(字典 mes_index_type)", example = "SIZE") + @Schema(description = "检测项类型", example = "1") @ExcelProperty("检测项类型") - private String indicatorType; + private Integer indicatorType; @Schema(description = "检测工具", example = "卡尺") @ExcelProperty("检测工具") diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/MesTmToolPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/MesTmToolPageReqVO.java index b51082ee2..d411be8e5 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/MesTmToolPageReqVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/MesTmToolPageReqVO.java @@ -25,7 +25,7 @@ public class MesTmToolPageReqVO extends PageParam { private String brand; @Schema(description = "型号规格", example = "M5-100") - private String spec; + private String specification; @Schema(description = "状态", example = "1") private Integer status; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/MesTmToolRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/MesTmToolRespVO.java index edbec15fa..dbe4b44f5 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/MesTmToolRespVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/MesTmToolRespVO.java @@ -33,7 +33,7 @@ public class MesTmToolRespVO { @Schema(description = "型号规格", example = "M5-100") @ExcelProperty("型号规格") - private String spec; + private String specification; @Schema(description = "工具类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") private Long toolTypeId; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/MesTmToolSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/MesTmToolSaveReqVO.java index 1ba1b3293..b0e51c154 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/MesTmToolSaveReqVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/MesTmToolSaveReqVO.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.mes.controller.admin.tm.tool.vo; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; import lombok.Data; import java.time.LocalDateTime; @@ -16,17 +17,21 @@ public class MesTmToolSaveReqVO { @Schema(description = "工具编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "T-001") @NotEmpty(message = "工具编码不能为空") + @Size(max = 64, message = "工具编码长度不能超过 64 个字符") private String code; @Schema(description = "工具名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "5mm 铣刀") @NotEmpty(message = "工具名称不能为空") + @Size(max = 255, message = "工具名称长度不能超过 255 个字符") private String name; @Schema(description = "品牌", example = "三菱") + @Size(max = 255, message = "品牌长度不能超过 255 个字符") private String brand; @Schema(description = "型号规格", example = "M5-100") - private String spec; + @Size(max = 255, message = "型号规格长度不能超过 255 个字符") + private String specification; @Schema(description = "工具类型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") @NotNull(message = "工具类型不能为空") @@ -36,7 +41,8 @@ public class MesTmToolSaveReqVO { @NotNull(message = "数量不能为空") private Integer quantity; - @Schema(description = "可用数量", example = "1") + @Schema(description = "可用数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "可用数量不能为空") private Integer availableQuantity; @Schema(description = "保养维护类型", example = "1") @@ -53,6 +59,7 @@ public class MesTmToolSaveReqVO { private Integer status; @Schema(description = "备注", example = "备注") + @Size(max = 500, message = "备注长度不能超过 500 个字符") private String remark; - } +} \ No newline at end of file diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/type/MesTmToolTypeSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/type/MesTmToolTypeSaveReqVO.java index e331930f4..49305c8cd 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/type/MesTmToolTypeSaveReqVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/type/MesTmToolTypeSaveReqVO.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.mes.controller.admin.tm.tool.vo.type; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; import lombok.Data; @Schema(description = "管理后台 - MES 工具类型新增/修改 Request VO") @@ -14,10 +15,12 @@ public class MesTmToolTypeSaveReqVO { @Schema(description = "类型编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "TT-001") @NotEmpty(message = "类型编码不能为空") + @Size(max = 64, message = "类型编码长度不能超过 64 个字符") private String code; @Schema(description = "类型名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "铣刀") @NotEmpty(message = "类型名称不能为空") + @Size(max = 255, message = "类型名称长度不能超过 255 个字符") private String name; @Schema(description = "是否编码管理", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") @@ -31,6 +34,7 @@ public class MesTmToolTypeSaveReqVO { private Integer maintenPeriod; @Schema(description = "备注", example = "备注") + @Size(max = 500, message = "备注长度不能超过 500 个字符") private String remark; - } +} \ No newline at end of file diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/MesWmArrivalNoticeController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/MesWmArrivalNoticeController.java index cece976a4..b8e4f89e2 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/MesWmArrivalNoticeController.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/MesWmArrivalNoticeController.java @@ -42,7 +42,6 @@ public class MesWmArrivalNoticeController { @Resource private MesWmArrivalNoticeService arrivalNoticeService; - @Resource private MesMdVendorService vendorService; @@ -112,15 +111,6 @@ public class MesWmArrivalNoticeController { return success(true); } - @GetMapping("/simple-list") - @Operation(summary = "获得到货通知单精简列表") - @Parameter(name = "status", description = "状态", example = "2") - public CommonResult> getArrivalNoticeSimpleList( - @RequestParam(value = "status", required = false) Integer status) { - List list = arrivalNoticeService.getArrivalNoticeListByStatus(status); - return success(buildRespVOList(list)); - } - // ==================== 拼接 VO ==================== private List buildRespVOList(List list) { diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/MesWmArrivalNoticeLineController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/MesWmArrivalNoticeLineController.java index d0743a8c6..10a853a68 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/MesWmArrivalNoticeLineController.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/MesWmArrivalNoticeLineController.java @@ -40,13 +40,10 @@ public class MesWmArrivalNoticeLineController { @Resource private MesWmArrivalNoticeLineService arrivalNoticeLineService; - @Resource private MesMdItemService itemService; - @Resource private MesMdUnitMeasureService unitMeasureService; - @Resource private MesQcIqcService iqcService; @@ -95,16 +92,6 @@ public class MesWmArrivalNoticeLineController { return success(new PageResult<>(buildRespVOList(pageResult.getList()), pageResult.getTotal())); } - @GetMapping("/list-by-notice-id") - @Operation(summary = "获得到货通知单行列表") - @Parameter(name = "noticeId", description = "到货通知单编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('mes:wm-arrival-notice:query')") - public CommonResult> getArrivalNoticeLineListByNoticeId( - @RequestParam("noticeId") Long noticeId) { - List list = arrivalNoticeLineService.getArrivalNoticeLineListByNoticeId(noticeId); - return success(buildRespVOList(list)); - } - // ==================== 拼接 VO ==================== private List buildRespVOList(List list) { diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemconsume/vo/MesWmItemConsumeLinePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemconsume/vo/MesWmItemConsumeLinePageReqVO.java index 7cfdbdac8..000554f96 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemconsume/vo/MesWmItemConsumeLinePageReqVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemconsume/vo/MesWmItemConsumeLinePageReqVO.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.mes.controller.admin.wm.itemconsume.vo; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; @@ -13,6 +14,7 @@ import lombok.ToString; public class MesWmItemConsumeLinePageReqVO extends PageParam { @Schema(description = "报工记录编号", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "报工记录编号不能为空") private Long feedbackId; } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/MesWmItemReceiptLineController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/MesWmItemReceiptLineController.java index 7d7307bd3..0d4438f21 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/MesWmItemReceiptLineController.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/MesWmItemReceiptLineController.java @@ -10,10 +10,12 @@ import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.line.MesWm import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.line.MesWmItemReceiptLineSaveReqVO; import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptLineDO; import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService; import cn.iocoder.yudao.module.mes.service.wm.itemreceipt.MesWmItemReceiptLineService; +import cn.iocoder.yudao.module.mes.service.wm.itemreceipt.MesWmItemReceiptService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -38,12 +40,12 @@ public class MesWmItemReceiptLineController { @Resource private MesWmItemReceiptLineService itemReceiptLineService; - @Resource private MesMdItemService itemService; - @Resource private MesMdUnitMeasureService unitMeasureService; + @Resource + private MesWmItemReceiptService itemReceiptService; @PostMapping("/create") @Operation(summary = "创建采购入库单行") @@ -101,6 +103,8 @@ public class MesWmItemReceiptLineController { convertSet(list, MesWmItemReceiptLineDO::getItemId)); Map unitMeasureMap = unitMeasureService.getUnitMeasureMap( convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + Map receiptMap = itemReceiptService.getItemReceiptMap( + convertSet(list, MesWmItemReceiptLineDO::getReceiptId)); // 2. 构建结果 return BeanUtils.toBean(list, MesWmItemReceiptLineRespVO.class, vo -> { MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { @@ -108,6 +112,8 @@ public class MesWmItemReceiptLineController { MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName())); }); + MapUtils.findAndThen(receiptMap, vo.getReceiptId(), receipt -> + vo.setReceiptCode(receipt.getCode()).setPurchaseOrderCode(receipt.getPurchaseOrderCode())); }); } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/line/MesWmItemReceiptLineRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/line/MesWmItemReceiptLineRespVO.java index 25596dbdc..98a824852 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/line/MesWmItemReceiptLineRespVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/line/MesWmItemReceiptLineRespVO.java @@ -16,6 +16,12 @@ public class MesWmItemReceiptLineRespVO { @Schema(description = "入库单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Long receiptId; + @Schema(description = "入库单编码", example = "IR2026020001") + private String receiptCode; + + @Schema(description = "采购订单号", example = "PO20260201") + private String purchaseOrderCode; + @Schema(description = "到货通知单行编号", example = "1") private Long arrivalNoticeLineId; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/materialstock/MesWmMaterialStockController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/materialstock/MesWmMaterialStockController.java index bd40c070a..16ce9b807 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/materialstock/MesWmMaterialStockController.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/materialstock/MesWmMaterialStockController.java @@ -52,22 +52,16 @@ public class MesWmMaterialStockController { @Resource private MesWmMaterialStockService materialStockService; - @Resource private MesMdItemService itemService; - @Resource private MesMdUnitMeasureService unitMeasureService; - @Resource private MesWmWarehouseService warehouseService; - @Resource private MesWmWarehouseLocationService locationService; - @Resource private MesWmWarehouseAreaService areaService; - @Resource private MesMdVendorService vendorService; @@ -139,8 +133,8 @@ public class MesWmMaterialStockController { MapUtils.findAndThen(unitMeasureMap, item.getUnitMeasureId(), unitMeasure -> vo.setUnitMeasureName(unitMeasure.getName())); }); - MapUtils.findAndThen(warehouseMap, vo.getWarehouseId(), - warehouse -> vo.setWarehouseName(warehouse.getName())); + MapUtils.findAndThen(warehouseMap, vo.getWarehouseId(), warehouse -> + vo.setWarehouseCode(warehouse.getCode()).setWarehouseName(warehouse.getName())); MapUtils.findAndThen(locationMap, vo.getLocationId(), location -> vo.setLocationName(location.getName())); MapUtils.findAndThen(areaMap, vo.getAreaId(), diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/materialstock/vo/MesWmMaterialStockPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/materialstock/vo/MesWmMaterialStockPageReqVO.java index 0a880e230..b5a18ac4f 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/materialstock/vo/MesWmMaterialStockPageReqVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/materialstock/vo/MesWmMaterialStockPageReqVO.java @@ -12,6 +12,18 @@ import lombok.ToString; @ToString(callSuper = true) public class MesWmMaterialStockPageReqVO extends PageParam { + /** + * 虚拟仓过滤模式 - 排除虚拟仓 + */ + public static final String VIRTUAL_FILTER_EXCLUDE = "exclude"; + /** + * 虚拟仓过滤模式 - 只看虚拟仓 + */ + public static final String VIRTUAL_FILTER_ONLY = "only"; + + @Schema(description = "虚拟仓过滤模式", example = "exclude") + private String virtualFilter; + @Schema(description = "物料分类编号", example = "1") private Long itemTypeId; @@ -21,6 +33,9 @@ public class MesWmMaterialStockPageReqVO extends PageParam { @Schema(description = "批次号", example = "B20260101") private String batchCode; + @Schema(description = "批次编号", example = "1") + private Long batchId; + @Schema(description = "仓库编号", example = "1") private Long warehouseId; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/materialstock/vo/MesWmMaterialStockRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/materialstock/vo/MesWmMaterialStockRespVO.java index 366e64f9b..03349b347 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/materialstock/vo/MesWmMaterialStockRespVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/materialstock/vo/MesWmMaterialStockRespVO.java @@ -49,6 +49,9 @@ public class MesWmMaterialStockRespVO { @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Long warehouseId; + @Schema(description = "仓库编码", example = "WH001") + private String warehouseCode; + @Schema(description = "仓库名称", example = "原料仓") @ExcelProperty("仓库") private String warehouseName; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/MesWmMiscIssueRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/MesWmMiscIssueRespVO.java index cbab9242d..63cc75214 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/MesWmMiscIssueRespVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/MesWmMiscIssueRespVO.java @@ -21,15 +21,14 @@ public class MesWmMiscIssueRespVO { @Schema(description = "杂项类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Integer type; + @Schema(description = "来源单据类型", example = "PURCHASE_ORDER") + private String sourceDocType; @Schema(description = "来源单据ID", example = "1") private Long sourceDocId; @Schema(description = "来源单据编号", example = "DOC20260302001") private String sourceDocCode; - @Schema(description = "来源单据类型", example = "PURCHASE_ORDER") - private String sourceDocType; - @Schema(description = "出库日期", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime issueDate; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/MesWmMiscIssueSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/MesWmMiscIssueSaveReqVO.java index 2758b7ef2..61922d9d7 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/MesWmMiscIssueSaveReqVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscissue/vo/MesWmMiscIssueSaveReqVO.java @@ -26,15 +26,14 @@ public class MesWmMiscIssueSaveReqVO { @NotNull(message = "杂项类型不能为空") private Integer type; + @Schema(description = "来源单据类型", example = "PURCHASE_ORDER") + private String sourceDocType; @Schema(description = "来源单据ID", example = "1") private Long sourceDocId; @Schema(description = "来源单据编号", example = "DOC20260302001") private String sourceDocCode; - @Schema(description = "来源单据类型", example = "PURCHASE_ORDER") - private String sourceDocType; - @Schema(description = "出库日期", requiredMode = Schema.RequiredMode.REQUIRED) @NotNull(message = "出库日期不能为空") private LocalDateTime issueDate; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/vo/MesWmMiscReceiptRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/vo/MesWmMiscReceiptRespVO.java index e29fc879d..effeabf89 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/vo/MesWmMiscReceiptRespVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/vo/MesWmMiscReceiptRespVO.java @@ -21,15 +21,14 @@ public class MesWmMiscReceiptRespVO { @Schema(description = "杂项类型", example = "1") private Integer type; + @Schema(description = "来源单据类型", example = "WORK_ORDER") + private String sourceDocType; @Schema(description = "来源单据 ID", example = "1") private Long sourceDocId; @Schema(description = "来源单据编码", example = "WO2026030001") private String sourceDocCode; - @Schema(description = "来源单据类型", example = "WORK_ORDER") - private String sourceDocType; - @Schema(description = "入库日期") private LocalDateTime receiptDate; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/vo/MesWmMiscReceiptSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/vo/MesWmMiscReceiptSaveReqVO.java index 1815c0513..40db6f709 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/vo/MesWmMiscReceiptSaveReqVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/miscreceipt/vo/MesWmMiscReceiptSaveReqVO.java @@ -26,15 +26,14 @@ public class MesWmMiscReceiptSaveReqVO { @NotNull(message = "杂项类型不能为空") private Integer type; + @Schema(description = "来源单据类型", example = "WORK_ORDER") + private String sourceDocType; @Schema(description = "来源单据 ID", example = "1") private Long sourceDocId; @Schema(description = "来源单据编码", example = "WO2026030001") private String sourceDocCode; - @Schema(description = "来源单据类型", example = "WORK_ORDER") - private String sourceDocType; - @Schema(description = "入库日期", requiredMode = Schema.RequiredMode.REQUIRED) @NotNull(message = "入库日期不能为空") private LocalDateTime receiptDate; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/MesWmPackageController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/MesWmPackageController.java index 70b4d0f1b..805a9b1fd 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/MesWmPackageController.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/MesWmPackageController.java @@ -50,6 +50,7 @@ public class MesWmPackageController { private MesMdClientService clientService; @Resource private MesMdUnitMeasureService unitMeasureService; + @Resource private AdminUserApi adminUserApi; @@ -125,20 +126,6 @@ public class MesWmPackageController { return success(true); } - @GetMapping("/childable-simple-list") - @Operation(summary = "可添加为子箱的装箱单精简列表") - @PreAuthorize("@ss.hasPermission('mes:wm-package:query')") - public CommonResult> getChildablePackageSimpleList() { - List list = packageService.getChildablePackageList(); - return success(buildRespVOList(list)); - } - - @GetMapping("/simple-list") - @Operation(summary = "获得装箱单精简列表", description = "主要用于前端的下拉选项") - public CommonResult> getPackageSimpleList() { - List list = packageService.getPackageSimpleList(); - return success(buildRespVOList(list)); - } // ========== 私有方法 ========== diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/vo/MesWmPackagePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/vo/MesWmPackagePageReqVO.java index 08cb21953..f5dec9e62 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/vo/MesWmPackagePageReqVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/vo/MesWmPackagePageReqVO.java @@ -32,4 +32,7 @@ public class MesWmPackagePageReqVO extends PageParam { @Schema(description = "检查员用户 ID", example = "1") private Long inspectorUserId; + @Schema(description = "单据状态", example = "1") + private Integer status; + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/vo/line/MesWmPackageLineSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/vo/line/MesWmPackageLineSaveReqVO.java index 5e257eeea..1be70a794 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/vo/line/MesWmPackageLineSaveReqVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/vo/line/MesWmPackageLineSaveReqVO.java @@ -36,10 +36,10 @@ public class MesWmPackageLineSaveReqVO { @DecimalMin(value = "0.01", message = "装箱数量必须大于 0") private BigDecimal quantity; - @Schema(description = "生产工单 ID", example = "1") + @Schema(description = "生产工单 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "生产工单不能为空") private Long workOrderId; - // DONE @AI:时间都是 LocalDateTIme; @Schema(description = "有效期") private LocalDateTime expireDate; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/detail/MesWmProductIssueDetailSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/detail/MesWmProductIssueDetailSaveReqVO.java index de2a2b962..d598289b1 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productissue/vo/detail/MesWmProductIssueDetailSaveReqVO.java +++ b/yudao-module-mes/yudao-module-mes-server/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/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/vo/line/MesWmProductReceiptLineSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/vo/line/MesWmProductReceiptLineSaveReqVO.java index 86d133d99..7b086922f 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/vo/line/MesWmProductReceiptLineSaveReqVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/vo/line/MesWmProductReceiptLineSaveReqVO.java @@ -7,7 +7,7 @@ import lombok.Data; import java.math.BigDecimal; -@Schema(description = "管理后台 - MES 产品收货单行新增/修改 Request VO") +@Schema(description = "管理后台 - MES 产品入库单行新增/修改 Request VO") @Data public class MesWmProductReceiptLineSaveReqVO { diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/MesWmProductSalesController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/MesWmProductSalesController.java index f50624dd1..cdd84a883 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/MesWmProductSalesController.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/MesWmProductSalesController.java @@ -43,7 +43,6 @@ public class MesWmProductSalesController { @Resource private MesWmProductSalesService productSalesService; - @Resource private MesMdClientService clientService; @Resource @@ -174,7 +173,7 @@ public class MesWmProductSalesController { MapUtils.findAndThen(clientMap, vo.getClientId(), client -> vo.setClientName(client.getName()).setClientCode(client.getCode())); MapUtils.findAndThen(noticeMap, vo.getNoticeId(), - notice -> vo.setNoticeCode(notice.getNoticeCode())); + notice -> vo.setNoticeCode(notice.getCode())); }); } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/line/MesWmProductSalesLineRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/line/MesWmProductSalesLineRespVO.java index 19eff6578..67e244b6d 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/line/MesWmProductSalesLineRespVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/line/MesWmProductSalesLineRespVO.java @@ -16,6 +16,9 @@ public class MesWmProductSalesLineRespVO { @Schema(description = "出库单ID", example = "1") private Long salesId; + @Schema(description = "发货通知单行ID", example = "1") + private Long noticeLineId; + @Schema(description = "物料ID", example = "1") private Long itemId; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/line/MesWmProductSalesLineSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/line/MesWmProductSalesLineSaveReqVO.java index 444c2b8bd..67e7c3b90 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/line/MesWmProductSalesLineSaveReqVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/line/MesWmProductSalesLineSaveReqVO.java @@ -17,6 +17,9 @@ public class MesWmProductSalesLineSaveReqVO { @NotNull(message = "出库单ID不能为空") private Long salesId; + @Schema(description = "发货通知单行ID", example = "1") + private Long noticeLineId; + @Schema(description = "物料ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @NotNull(message = "物料不能为空") private Long itemId; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/vo/detail/MesWmReturnIssueDetailSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/vo/detail/MesWmReturnIssueDetailSaveReqVO.java index 6659bf498..e5ff4346a 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnissue/vo/detail/MesWmReturnIssueDetailSaveReqVO.java +++ b/yudao-module-mes/yudao-module-mes-server/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/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/detail/MesWmReturnSalesDetailSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/detail/MesWmReturnSalesDetailSaveReqVO.java index 7991a82bd..2c7b81c2e 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/detail/MesWmReturnSalesDetailSaveReqVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/detail/MesWmReturnSalesDetailSaveReqVO.java @@ -39,6 +39,9 @@ public class MesWmReturnSalesDetailSaveReqVO { @Schema(description = "批次ID", example = "1") private Long batchId; + @Schema(description = "批次号", example = "B20250101") + private String batchCode; + @Schema(description = "仓库ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @NotNull(message = "仓库ID不能为空") private Long warehouseId; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/line/MesWmReturnSalesLineSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/line/MesWmReturnSalesLineSaveReqVO.java index 7184248e4..46d2c1e84 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/line/MesWmReturnSalesLineSaveReqVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnsales/vo/line/MesWmReturnSalesLineSaveReqVO.java @@ -32,9 +32,12 @@ public class MesWmReturnSalesLineSaveReqVO { @DecimalMin(value = "0", inclusive = false, message = "退货数量必须大于 0") private BigDecimal quantity; - @Schema(description = "批次号", example = "B20250101") + @Schema(description = "批次ID", example = "1") private Long batchId; + @Schema(description = "批次号", example = "B20250101") + private String batchCode; + @Schema(description = "是否需要质检", example = "true") private Boolean rqcCheckFlag; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/detail/MesWmReturnVendorDetailSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/detail/MesWmReturnVendorDetailSaveReqVO.java index b4aa8bdf0..b09695d43 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/detail/MesWmReturnVendorDetailSaveReqVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/returnvendor/vo/detail/MesWmReturnVendorDetailSaveReqVO.java @@ -14,21 +14,20 @@ public class MesWmReturnVendorDetailSaveReqVO { @Schema(description = "编号", example = "1024") private Long id; + @Schema(description = "退货单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "退货单编号不能为空") + private Long returnId; @Schema(description = "退货单行编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @NotNull(message = "退货单行编号不能为空") private Long lineId; - @Schema(description = "退货单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "退货单编号不能为空") - private Long returnId; + @Schema(description = "库存记录编号", example = "1") + private Long materialStockId; @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @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/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/MesWmSalesNoticeController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/MesWmSalesNoticeController.java index 1d9f51b12..7b4a03f2c 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/MesWmSalesNoticeController.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/MesWmSalesNoticeController.java @@ -42,7 +42,6 @@ public class MesWmSalesNoticeController { @Resource private MesWmSalesNoticeService salesNoticeService; - @Resource private MesMdClientService clientService; @@ -112,15 +111,6 @@ public class MesWmSalesNoticeController { return success(true); } - @GetMapping("/simple-list") - @Operation(summary = "获得发货通知单精简列表") - @Parameter(name = "status", description = "状态", example = "1") - public CommonResult> getSalesNoticeSimpleList( - @RequestParam(value = "status", required = false) Integer status) { - List list = salesNoticeService.getSalesNoticeListByStatus(status); - return success(buildRespVOList(list)); - } - // ==================== 拼接 VO ==================== private List buildRespVOList(List list) { diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/vo/MesWmSalesNoticePageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/vo/MesWmSalesNoticePageReqVO.java index d7568df34..3dee41cea 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/vo/MesWmSalesNoticePageReqVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/vo/MesWmSalesNoticePageReqVO.java @@ -13,10 +13,10 @@ import lombok.ToString; public class MesWmSalesNoticePageReqVO extends PageParam { @Schema(description = "通知单编码", example = "SN202603010001") - private String noticeCode; + private String code; @Schema(description = "通知单名称", example = "测试发货通知") - private String noticeName; + private String name; @Schema(description = "销售订单编号", example = "SO202603010001") private String salesOrderCode; @@ -24,4 +24,7 @@ public class MesWmSalesNoticePageReqVO extends PageParam { @Schema(description = "客户编号", example = "1") private Long clientId; + @Schema(description = "状态", example = "3") + private Integer status; + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/vo/MesWmSalesNoticeRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/vo/MesWmSalesNoticeRespVO.java index bf453e634..473de9920 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/vo/MesWmSalesNoticeRespVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/vo/MesWmSalesNoticeRespVO.java @@ -18,11 +18,11 @@ public class MesWmSalesNoticeRespVO { @Schema(description = "通知单编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "SN202603010001") @ExcelProperty("通知单编码") - private String noticeCode; + private String code; @Schema(description = "通知单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "测试发货通知") @ExcelProperty("通知单名称") - private String noticeName; + private String name; @Schema(description = "销售订单编号", example = "SO202603010001") @ExcelProperty("销售订单编号") diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/vo/MesWmSalesNoticeSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/vo/MesWmSalesNoticeSaveReqVO.java index ee7b87b72..b3ad25a4c 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/vo/MesWmSalesNoticeSaveReqVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/vo/MesWmSalesNoticeSaveReqVO.java @@ -16,11 +16,11 @@ public class MesWmSalesNoticeSaveReqVO { @Schema(description = "通知单编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "SN202603010001") @NotEmpty(message = "通知单编码不能为空") - private String noticeCode; + private String code; @Schema(description = "通知单名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "测试发货通知") @NotEmpty(message = "通知单名称不能为空") - private String noticeName; + private String name; @Schema(description = "销售订单编号", example = "SO202603010001") private String salesOrderCode; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/sn/MesWmSnController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/sn/MesWmSnController.java index e9c19b489..63d5afe9b 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/sn/MesWmSnController.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/sn/MesWmSnController.java @@ -13,7 +13,9 @@ import cn.iocoder.yudao.module.mes.controller.admin.wm.sn.vo.MesWmSnGroupRespVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.sn.vo.MesWmSnPageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.sn.vo.MesWmSnRespVO; import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO; import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService; import cn.iocoder.yudao.module.mes.service.wm.sn.MesWmSnService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -44,6 +46,8 @@ public class MesWmSnController { private MesWmSnService snService; @Resource private MesMdItemService itemService; + @Resource + private MesMdUnitMeasureService unitMeasureService; @PostMapping("/generate") @Operation(summary = "生成 SN 码") @@ -103,8 +107,12 @@ public class MesWmSnController { return; } Map itemMap = itemService.getItemMap(convertSet(list, MesWmSnGroupRespVO::getItemId)); - list.forEach(vo -> MapUtils.findAndThen(itemMap, vo.getItemId(), item -> - vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification()))); + Map unitMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + list.forEach(vo -> MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification()); + MapUtils.findAndThen(unitMap, item.getUnitMeasureId(), unit -> vo.setUnitName(unit.getName())); + })); } private void buildItemInfo(List list) { @@ -112,8 +120,12 @@ public class MesWmSnController { return; } Map itemMap = itemService.getItemMap(convertSet(list, MesWmSnRespVO::getItemId)); - list.forEach(vo -> MapUtils.findAndThen(itemMap, vo.getItemId(), item -> - vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification()))); + Map unitMap = unitMeasureService.getUnitMeasureMap( + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); + list.forEach(vo -> MapUtils.findAndThen(itemMap, vo.getItemId(), item -> { + vo.setItemCode(item.getCode()).setItemName(item.getName()).setSpecification(item.getSpecification()); + MapUtils.findAndThen(unitMap, item.getUnitMeasureId(), unit -> vo.setUnitName(unit.getName())); + })); } } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/sn/vo/MesWmSnGroupRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/sn/vo/MesWmSnGroupRespVO.java index ed2883050..05e2b5e0e 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/sn/vo/MesWmSnGroupRespVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/sn/vo/MesWmSnGroupRespVO.java @@ -34,6 +34,10 @@ public class MesWmSnGroupRespVO { @ExcelProperty("规格型号") private String specification; + @Schema(description = "单位", example = "个") + @ExcelProperty("单位") + private String unitName; + @Schema(description = "批次号", example = "BATCH001") @ExcelProperty("批次号") private String batchCode; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/sn/vo/MesWmSnRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/sn/vo/MesWmSnRespVO.java index f42011180..d831b2d2c 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/sn/vo/MesWmSnRespVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/sn/vo/MesWmSnRespVO.java @@ -37,6 +37,10 @@ public class MesWmSnRespVO { @ExcelProperty("规格型号") private String specification; + @Schema(description = "单位", example = "个") + @ExcelProperty("单位") + private String unitName; + @Schema(description = "批次号", example = "BATCH001") @ExcelProperty("批次号") private String batchCode; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/plan/MesWmStockTakingPlanController.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/plan/MesWmStockTakingPlanController.java index f010a6b2c..33ba8ce24 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/plan/MesWmStockTakingPlanController.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/plan/MesWmStockTakingPlanController.java @@ -1,7 +1,6 @@ package cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.plan; import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog; -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -24,7 +23,6 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.io.IOException; -import java.util.List; import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -104,13 +102,4 @@ public class MesWmStockTakingPlanController { BeanUtils.toBean(pageResult.getList(), MesWmStockTakingPlanRespVO.class)); } - @GetMapping("/simple-list") - @Operation(summary = "获得已启用的盘点方案精简列表") - @PreAuthorize("@ss.hasPermission('mes:wm-stock-taking-task:query')") - public CommonResult> getEnabledStockTakingPlanSimpleList() { - List list = stockTakingPlanService.getStockTakingPlanListByStatus( - CommonStatusEnum.ENABLE.getStatus()); - return success(BeanUtils.toBean(list, MesWmStockTakingPlanRespVO.class)); - } - } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/plan/vo/MesWmStockTakingPlanPageReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/plan/vo/MesWmStockTakingPlanPageReqVO.java index e4153a5c2..bda1fa137 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/plan/vo/MesWmStockTakingPlanPageReqVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/plan/vo/MesWmStockTakingPlanPageReqVO.java @@ -19,4 +19,7 @@ public class MesWmStockTakingPlanPageReqVO extends PageParam { @Schema(description = "盘点类型", example = "1") private Integer type; + @Schema(description = "状态", example = "0") + private Integer status; + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/transfer/vo/line/MesWmTransferLineSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/transfer/vo/line/MesWmTransferLineSaveReqVO.java index 96f776305..ddd09087b 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/transfer/vo/line/MesWmTransferLineSaveReqVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/transfer/vo/line/MesWmTransferLineSaveReqVO.java @@ -18,7 +18,8 @@ public class MesWmTransferLineSaveReqVO { @NotNull(message = "转移单编号不能为空") private Long transferId; - @Schema(description = "库存记录编号", example = "1") + @Schema(description = "库存记录编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "库存记录编号不能为空") private Long materialStockId; @Schema(description = "物料编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/location/MesWmWarehouseLocationRespVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/location/MesWmWarehouseLocationRespVO.java index c593a33bc..922868530 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/location/MesWmWarehouseLocationRespVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/location/MesWmWarehouseLocationRespVO.java @@ -36,10 +36,6 @@ public class MesWmWarehouseLocationRespVO { @ExcelProperty("面积") private BigDecimal area; - @Schema(description = "库位管理状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") - @ExcelProperty("库位管理状态") - private Integer areaStatus; - @Schema(description = "是否冻结", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") @ExcelProperty("是否冻结") private Boolean frozen; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/location/MesWmWarehouseLocationSaveReqVO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/location/MesWmWarehouseLocationSaveReqVO.java index d3bb7a5cf..21214f9c5 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/location/MesWmWarehouseLocationSaveReqVO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/location/MesWmWarehouseLocationSaveReqVO.java @@ -29,10 +29,6 @@ public class MesWmWarehouseLocationSaveReqVO { @Schema(description = "面积", example = "500.00") private BigDecimal area; - @Schema(description = "库位管理状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") - @NotNull(message = "库位管理状态不能为空") - private Integer areaStatus; - @Schema(description = "是否冻结", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") @NotNull(message = "是否冻结不能为空") private Boolean frozen; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/cal/plan/MesCalPlanDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/cal/plan/MesCalPlanDO.java index 5ead025bd..15eb13bd8 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/cal/plan/MesCalPlanDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/cal/plan/MesCalPlanDO.java @@ -10,6 +10,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; import java.time.LocalDateTime; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 排班计划 DO @@ -54,12 +55,14 @@ public class MesCalPlanDO extends BaseDO { /** * 轮班方式 * + * 字典 {@link DictTypeConstants#MES_CAL_SHIFT_TYPE} * 枚举 {@link MesCalShiftTypeEnum} */ private Integer shiftType; /** * 倒班方式 * + * 字典 {@link DictTypeConstants#MES_CAL_SHIFT_METHOD} * 枚举 {@link MesCalShiftMethodEnum} */ private Integer shiftMethod; @@ -70,6 +73,7 @@ public class MesCalPlanDO extends BaseDO { /** * 状态 * + * 字典 {@link DictTypeConstants#MES_CAL_PLAN_STATUS} * 枚举 {@link MesCalPlanStatusEnum} */ private Integer status; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/checkplan/MesDvCheckPlanDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/checkplan/MesDvCheckPlanDO.java index 1fa287b25..681f2ea90 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/checkplan/MesDvCheckPlanDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/checkplan/MesDvCheckPlanDO.java @@ -65,6 +65,7 @@ public class MesDvCheckPlanDO extends BaseDO { /** * 状态 * + * 字典 {@link DictTypeConstants#MES_DV_CHECK_PLAN_STATUS} * 枚举 {@link MesDvCheckPlanStatusEnum} */ private Integer status; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/checkrecord/MesDvCheckRecordDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/checkrecord/MesDvCheckRecordDO.java index 8e66d5bca..f3e322395 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/checkrecord/MesDvCheckRecordDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/checkrecord/MesDvCheckRecordDO.java @@ -10,6 +10,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; import java.time.LocalDateTime; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 设备点检记录 DO @@ -56,6 +57,7 @@ public class MesDvCheckRecordDO extends BaseDO { /** * 状态 * + * 字典 {@link DictTypeConstants#MES_DV_CHECK_RECORD_STATUS} * 枚举 {@link MesDvCheckRecordStatusEnum} */ private Integer status; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/checkrecord/MesDvCheckRecordLineDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/checkrecord/MesDvCheckRecordLineDO.java index 732c60fa7..3f5c5fa20 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/checkrecord/MesDvCheckRecordLineDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/checkrecord/MesDvCheckRecordLineDO.java @@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 设备点检记录明细 DO @@ -43,6 +44,7 @@ public class MesDvCheckRecordLineDO extends BaseDO { /** * 点检结果 * + * 字典 {@link DictTypeConstants#MES_DV_CHECK_RESULT} * 枚举 {@link MesDvCheckResultEnum} */ private Integer checkStatus; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/machinery/MesDvMachineryDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/machinery/MesDvMachineryDO.java index 940734dad..bb6594117 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/machinery/MesDvMachineryDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/machinery/MesDvMachineryDO.java @@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; import java.time.LocalDateTime; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 设备台账 DO @@ -43,7 +44,7 @@ public class MesDvMachineryDO extends BaseDO { /** * 规格型号 */ - private String spec; + private String specification; /** * 设备类型编号 * @@ -59,6 +60,7 @@ public class MesDvMachineryDO extends BaseDO { /** * 设备状态 * + * 字典 {@link DictTypeConstants#MES_DV_MACHINERY_STATUS} * 枚举 {@link cn.iocoder.yudao.module.mes.enums.dv.MesDvMachineryStatusEnum} */ private Integer status; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/maintenrecord/MesDvMaintenRecordDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/maintenrecord/MesDvMaintenRecordDO.java index 555b6b5a3..7a38aa299 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/maintenrecord/MesDvMaintenRecordDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/maintenrecord/MesDvMaintenRecordDO.java @@ -10,6 +10,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; import java.time.LocalDateTime; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 设备保养记录 DO @@ -56,8 +57,8 @@ public class MesDvMaintenRecordDO extends BaseDO { /** * 状态 * + * 字典 {@link DictTypeConstants#MES_MAINTEN_RECORD_STATUS} * 枚举 {@link MesDvMaintenRecordStatusEnum} - * 字典类型 mes_mainten_record_status */ private Integer status; /** diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/maintenrecord/MesDvMaintenRecordLineDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/maintenrecord/MesDvMaintenRecordLineDO.java index 224902da6..4de462402 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/maintenrecord/MesDvMaintenRecordLineDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/maintenrecord/MesDvMaintenRecordLineDO.java @@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 设备保养记录明细 DO @@ -43,8 +44,8 @@ public class MesDvMaintenRecordLineDO extends BaseDO { /** * 保养结果 * + * 字典 {@link DictTypeConstants#MES_MAINTEN_STATUS} * 枚举 {@link MesDvMaintenStatusEnum} - * 字典类型 mes_mainten_status */ private Integer status; /** diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/repair/MesDvRepairDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/repair/MesDvRepairDO.java index 25f7cca86..8632a1d2c 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/repair/MesDvRepairDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/repair/MesDvRepairDO.java @@ -10,6 +10,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; import java.time.LocalDateTime; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 维修工单 DO @@ -60,6 +61,7 @@ public class MesDvRepairDO extends BaseDO { /** * 维修结果 * + * 字典 {@link DictTypeConstants#MES_DV_REPAIR_RESULT} * 枚举 {@link MesDvRepairResultEnum} */ private Integer result; @@ -91,6 +93,7 @@ public class MesDvRepairDO extends BaseDO { /** * 状态 * + * 字典 {@link DictTypeConstants#MES_DV_REPAIR_STATUS} * 枚举 {@link MesDvRepairStatusEnum} */ private Integer status; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/autocode/MesMdAutoCodePartDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/autocode/MesMdAutoCodePartDO.java index a76fc5009..e7225e51d 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/autocode/MesMdAutoCodePartDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/autocode/MesMdAutoCodePartDO.java @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 编码规则组成 DO @@ -36,26 +37,17 @@ public class MesMdAutoCodePartDO extends BaseDO { * 分段序号 */ private Integer sort; - /** - * 分段长度 - */ - private Integer length; - /** - * 备注 - */ - private String remark; /** * 分段类型 * + * 字典 {@link DictTypeConstants#MES_MD_AUTO_CODE_PART_TYPE} * 枚举 {@link cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodePartTypeEnum} */ private Integer type; - - // ========== 当 MesMdAutoCodePartTypeEnum#INPUT_CHAR 时,使用 ========== /** - * 固定字符 + * 分段长度 */ - private String fixCharacter; + private Integer length; // ========== 当 MesMdAutoCodePartTypeEnum#DATE 时,使用 ========== /** @@ -65,6 +57,12 @@ public class MesMdAutoCodePartDO extends BaseDO { */ private String dateFormat; + // ========== 当 MesMdAutoCodePartTypeEnum#INPUT_CHAR 时,使用 ========== + /** + * 固定字符 + */ + private String fixCharacter; + // ========== 当 MesMdAutoCodePartTypeEnum#SERIAL_NUMBER 时,使用 ========== /** * 流水号起始值 @@ -81,8 +79,14 @@ public class MesMdAutoCodePartDO extends BaseDO { /** * 循环方式 * + * 字典 {@link DictTypeConstants#MES_MD_AUTO_CODE_CYCLE_METHOD} * 枚举 {@link cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodeCycleMethodEnum} */ private Integer cycleMethod; + /** + * 备注 + */ + private String remark; + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/autocode/MesMdAutoCodeRecordDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/autocode/MesMdAutoCodeRecordDO.java index e2079e934..e66e5fceb 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/autocode/MesMdAutoCodeRecordDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/autocode/MesMdAutoCodeRecordDO.java @@ -37,15 +37,15 @@ public class MesMdAutoCodeRecordDO extends BaseDO { * 生成的编码 */ private String result; - /** - * 传入的参数 - */ - private String inputChar; /** * 生成的流水号 * * 当规则组成中包含流水号分段({@link MesMdAutoCodePartTypeEnum#SERIAL_NUMBER})时记录,方便追溯和调试 */ private Long serialNo; + /** + * 传入的参数 + */ + private String inputChar; } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/autocode/MesMdAutoCodeRuleDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/autocode/MesMdAutoCodeRuleDO.java index c198f9b51..fc11ce75d 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/autocode/MesMdAutoCodeRuleDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/autocode/MesMdAutoCodeRuleDO.java @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 编码规则 DO @@ -53,6 +54,7 @@ public class MesMdAutoCodeRuleDO extends BaseDO { /** * 补齐方式 * + * 字典 {@link DictTypeConstants#MES_MD_AUTO_CODE_PADDED_METHOD} * 枚举 {@link cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodePaddedMethodEnum} */ private Integer paddedMethod; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/item/MesMdItemTypeDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/item/MesMdItemTypeDO.java index c70933081..6a5f65ec7 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/item/MesMdItemTypeDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/item/MesMdItemTypeDO.java @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 物料产品分类 DO @@ -43,6 +44,7 @@ public class MesMdItemTypeDO extends BaseDO { /** * 物料/产品标识 * + * 字典 {@link DictTypeConstants#MES_MD_ITEM_OR_PRODUCT} * 枚举 {@link cn.iocoder.yudao.module.mes.enums.md.MesMdItemTypeEnum} */ private String itemOrProduct; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/item/MesMdProductBomDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/item/MesMdProductBomDO.java index 77e6a47c7..a5a93c5c8 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/item/MesMdProductBomDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/md/item/MesMdProductBomDO.java @@ -9,7 +9,7 @@ import lombok.*; import java.math.BigDecimal; /** - * MES 产品BOM DO + * MES 产品 BOM DO * * @author 芋道源码 */ diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/andon/MesProAndonConfigDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/andon/MesProAndonConfigDO.java index c5c96250c..ef1a8e1d3 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/andon/MesProAndonConfigDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/andon/MesProAndonConfigDO.java @@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 安灯呼叫配置 DO @@ -34,6 +35,7 @@ public class MesProAndonConfigDO extends BaseDO { /** * 级别 * + * 字典 {@link DictTypeConstants#MES_PRO_ANDON_LEVEL} * 枚举 {@link MesProAndonLevelEnum} */ private Integer level; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/andon/MesProAndonRecordDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/andon/MesProAndonRecordDO.java index 663d3b8d8..52d945eb1 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/andon/MesProAndonRecordDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/andon/MesProAndonRecordDO.java @@ -12,6 +12,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; import java.time.LocalDateTime; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 安灯呼叫记录 DO @@ -70,12 +71,14 @@ public class MesProAndonRecordDO extends BaseDO { /** * 级别(快照值) * + * 字典 {@link DictTypeConstants#MES_PRO_ANDON_LEVEL} * 枚举 {@link MesProAndonLevelEnum} */ private Integer level; /** * 处置状态 * + * 字典 {@link DictTypeConstants#MES_PRO_ANDON_STATUS} * 枚举 {@link MesProAndonStatusEnum} */ private Integer status; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/card/MesProCardDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/card/MesProCardDO.java index 750ad47d8..97676e1b9 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/card/MesProCardDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/card/MesProCardDO.java @@ -9,6 +9,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; import java.math.BigDecimal; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 生产流转卡 DO @@ -57,6 +58,7 @@ public class MesProCardDO extends BaseDO { /** * 状态 * + * 字典 {@link DictTypeConstants#MES_PRO_WORK_ORDER_STATUS} * 枚举 {@link cn.iocoder.yudao.module.mes.enums.pro.MesProWorkOrderStatusEnum} */ private Integer status; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/feedback/MesProFeedbackDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/feedback/MesProFeedbackDO.java index 840d2da06..20177f442 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/feedback/MesProFeedbackDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/feedback/MesProFeedbackDO.java @@ -15,6 +15,7 @@ import lombok.*; import java.math.BigDecimal; import java.time.LocalDateTime; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 生产报工 DO @@ -43,6 +44,7 @@ public class MesProFeedbackDO extends BaseDO { /** * 报工类型 * + * 字典 {@link DictTypeConstants#MES_PRO_FEEDBACK_TYPE} * 枚举 {@link MesProFeedbackTypeEnum} */ private Integer type; @@ -149,6 +151,7 @@ public class MesProFeedbackDO extends BaseDO { /** * 状态 * + * 字典 {@link DictTypeConstants#MES_PRO_FEEDBACK_STATUS} * 枚举 {@link MesProFeedbackStatusEnum} */ private Integer status; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/task/MesProTaskDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/task/MesProTaskDO.java index 1a14001b5..d8c06bde8 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/task/MesProTaskDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/task/MesProTaskDO.java @@ -15,6 +15,7 @@ import lombok.*; import java.math.BigDecimal; import java.time.LocalDateTime; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 生产任务 DO @@ -130,6 +131,7 @@ public class MesProTaskDO extends BaseDO { /** * 任务状态 * + * 字典 {@link DictTypeConstants#MES_PRO_TASK_STATUS} * 枚举 {@link MesProTaskStatusEnum} */ private Integer status; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/task/MesProTaskIssueDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/task/MesProTaskIssueDO.java index 54b57a48c..65033585f 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/task/MesProTaskIssueDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/task/MesProTaskIssueDO.java @@ -50,26 +50,26 @@ public class MesProTaskIssueDO extends BaseDO { * 关联 {@link MesMdWorkstationDO#getId()} */ private Long workstationId; + /** + * 来源单据类型 + */ + private String sourceDocType; /** * 来源单据编号 */ private Long sourceDocId; + /** + * 来源单据行编号 + */ + private Long sourceLineId; /** * 来源单据编码 */ private String sourceDocCode; - /** - * 来源单据类型 - */ - private String sourceDocType; /** * 投料批次 */ private String batchCode; - /** - * 来源单据行编号 - */ - private Long sourceLineId; /** * 产品物料编号 * diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/workorder/MesProWorkOrderDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/workorder/MesProWorkOrderDO.java index 6ff101a7c..578cfd9b6 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/workorder/MesProWorkOrderDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/workorder/MesProWorkOrderDO.java @@ -14,6 +14,7 @@ import lombok.*; import java.math.BigDecimal; import java.time.LocalDateTime; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 生产工单 DO @@ -51,12 +52,14 @@ public class MesProWorkOrderDO extends BaseDO { /** * 工单类型 * + * 字典 {@link DictTypeConstants#MES_PRO_WORK_ORDER_TYPE} * 枚举 {@link MesProWorkOrderTypeEnum} */ private Integer type; /** * 来源类型 * + * 字典 {@link DictTypeConstants#MES_PRO_WORK_ORDER_SOURCE_TYPE} * 枚举 {@link MesProWorkOrderSourceTypeEnum} */ private Integer orderSourceType; @@ -123,6 +126,7 @@ public class MesProWorkOrderDO extends BaseDO { /** * 工单状态 * + * 字典 {@link DictTypeConstants#MES_PRO_WORK_ORDER_STATUS} * 枚举 {@link MesProWorkOrderStatusEnum} */ private Integer status; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/workrecord/MesProWorkRecordDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/workrecord/MesProWorkRecordDO.java index 43d755b9c..fc541a9de 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/workrecord/MesProWorkRecordDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/workrecord/MesProWorkRecordDO.java @@ -2,11 +2,10 @@ package cn.iocoder.yudao.module.mes.dal.dataobject.pro.workrecord; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; -import com.baomidou.mybatisplus.annotation.FieldStrategy; import lombok.*; import java.time.LocalDateTime; @@ -46,6 +45,7 @@ public class MesProWorkRecordDO extends BaseDO { /** * 当前状态 * + * 字典 {@link DictTypeConstants#MES_PRO_WORK_RECORD_TYPE} * 枚举 {@link cn.iocoder.yudao.module.mes.enums.pro.MesProWorkRecordTypeEnum} */ private Integer type; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/workrecord/MesProWorkRecordLogDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/workrecord/MesProWorkRecordLogDO.java index 84cfcd962..8f2035508 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/workrecord/MesProWorkRecordLogDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/workrecord/MesProWorkRecordLogDO.java @@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 上下工记录流水 DO @@ -43,6 +44,7 @@ public class MesProWorkRecordLogDO extends BaseDO { /** * 操作类型 * + * 字典 {@link DictTypeConstants#MES_PRO_WORK_RECORD_TYPE} * 枚举 {@link MesProWorkRecordTypeEnum} */ private Integer type; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/defect/MesQcDefectDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/defect/MesQcDefectDO.java index ee835c7e4..26679aec1 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/defect/MesQcDefectDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/defect/MesQcDefectDO.java @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 缺陷类型 DO @@ -39,10 +40,11 @@ public class MesQcDefectDO extends BaseDO { * * 字典类型 {@link cn.iocoder.yudao.module.mes.enums.DictTypeConstants#MES_DEFECT_TYPE} */ - private String type; + private Integer type; /** * 缺陷等级 * + * 字典 {@link DictTypeConstants#MES_DEFECT_LEVEL} * 枚举 {@link cn.iocoder.yudao.module.mes.enums.qc.MesQcDefectLevelEnum} */ private Integer level; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/defectrecord/MesQcDefectRecordDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/defectrecord/MesQcDefectRecordDO.java index 51d1836ea..bd0143c38 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/defectrecord/MesQcDefectRecordDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/defectrecord/MesQcDefectRecordDO.java @@ -11,6 +11,7 @@ import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 质检缺陷记录 DO @@ -37,6 +38,7 @@ public class MesQcDefectRecordDO extends BaseDO { /** * 检验类型 * + * 字典 {@link DictTypeConstants#MES_QC_TYPE} * 枚举 {@link MesQcTypeEnum} */ private Integer qcType; @@ -61,6 +63,7 @@ public class MesQcDefectRecordDO extends BaseDO { /** * 缺陷等级 * + * 字典 {@link DictTypeConstants#MES_DEFECT_LEVEL} * 枚举 {@link MesQcDefectLevelEnum} */ private Integer level; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/indicator/MesQcIndicatorDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/indicator/MesQcIndicatorDO.java index a338ba356..7f99dd1fb 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/indicator/MesQcIndicatorDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/indicator/MesQcIndicatorDO.java @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 质检指标 DO @@ -39,7 +40,7 @@ public class MesQcIndicatorDO extends BaseDO { * * 枚举 {@link cn.iocoder.yudao.module.mes.enums.DictTypeConstants#MES_INDICATOR_TYPE} */ - private String type; + private Integer type; /** * 检测工具 */ @@ -47,6 +48,7 @@ public class MesQcIndicatorDO extends BaseDO { /** * 结果值类型 * + * 字典 {@link DictTypeConstants#MES_QC_RESULT_TYPE} * 枚举 {@link cn.iocoder.yudao.module.mes.enums.qc.MesQcResultValueTypeEnum} */ private Integer resultType; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/indicatorresult/MesQcIndicatorResultDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/indicatorresult/MesQcIndicatorResultDO.java index cb8343a63..45fc965b5 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/indicatorresult/MesQcIndicatorResultDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/indicatorresult/MesQcIndicatorResultDO.java @@ -11,6 +11,7 @@ import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 检验结果记录 DO @@ -48,6 +49,7 @@ public class MesQcIndicatorResultDO extends BaseDO { /** * 质检类型 * + * 字典 {@link DictTypeConstants#MES_QC_TYPE} * 枚举 {@link MesQcTypeEnum} */ private Integer qcType; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/ipqc/MesQcIpqcDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/ipqc/MesQcIpqcDO.java index 53e9222bc..244c34757 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/ipqc/MesQcIpqcDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/ipqc/MesQcIpqcDO.java @@ -15,6 +15,7 @@ import lombok.*; import java.math.BigDecimal; import java.time.LocalDateTime; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 过程检验单(IPQC, In-Process Quality Control) DO @@ -62,6 +63,7 @@ public class MesQcIpqcDO extends BaseDO { /** * 来源单据类型 * + * 字典 {@link DictTypeConstants#MES_QC_SOURCE_DOC_TYPE} * 枚举 {@link MesQcSourceDocTypeEnum} */ private Integer sourceDocType; @@ -179,6 +181,7 @@ public class MesQcIpqcDO extends BaseDO { /** * 检测结果 * + * 字典 {@link DictTypeConstants#MES_QC_CHECK_RESULT} * 枚举 {@link cn.iocoder.yudao.module.mes.enums.qc.MesQcCheckResultEnum} */ private Integer checkResult; @@ -195,6 +198,7 @@ public class MesQcIpqcDO extends BaseDO { /** * 状态 * + * 字典 {@link DictTypeConstants#MES_ORDER_STATUS} * 枚举 {@link MesQcStatusEnum} */ private Integer status; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/iqc/MesQcIqcDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/iqc/MesQcIqcDO.java index d0a02017b..9ccc71bfd 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/iqc/MesQcIqcDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/iqc/MesQcIqcDO.java @@ -16,6 +16,7 @@ import lombok.*; import java.math.BigDecimal; import java.time.LocalDateTime; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 来料检验单(IQC, Incoming Quality Control) DO @@ -57,6 +58,7 @@ public class MesQcIqcDO extends BaseDO { /** * 来源单据类型 * + * 字典 {@link DictTypeConstants#MES_QC_SOURCE_DOC_TYPE} * 枚举 {@link MesQcSourceDocTypeEnum} */ private Integer sourceDocType; @@ -152,6 +154,7 @@ public class MesQcIqcDO extends BaseDO { /** * 检测结果 * + * 字典 {@link DictTypeConstants#MES_QC_CHECK_RESULT} * 枚举 {@link MesQcCheckResultEnum} */ private Integer checkResult; @@ -172,6 +175,7 @@ public class MesQcIqcDO extends BaseDO { /** * 状态 * + * 字典 {@link DictTypeConstants#MES_ORDER_STATUS} * 枚举 {@link MesQcStatusEnum} */ private Integer status; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/oqc/MesQcOqcDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/oqc/MesQcOqcDO.java index ce7a97eed..62efd792b 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/oqc/MesQcOqcDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/oqc/MesQcOqcDO.java @@ -11,6 +11,7 @@ import lombok.*; import java.math.BigDecimal; import java.time.LocalDateTime; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 出货检验单(OQC, Outgoing Quality Control) DO @@ -49,6 +50,13 @@ public class MesQcOqcDO extends BaseDO { // ========== 来源单据 ========== + /** + * 来源单据类型 + * + * 字典 {@link DictTypeConstants#MES_QC_SOURCE_DOC_TYPE} + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.qc.MesQcSourceDocTypeEnum} + */ + private Integer sourceDocType; /** * 来源单据 ID * @@ -56,12 +64,6 @@ public class MesQcOqcDO extends BaseDO { * 1. {@link cn.iocoder.yudao.module.mes.enums.qc.MesQcSourceDocTypeEnum#PRODUCT_SALES} 时,关联 {@link cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesDO#getId()} */ private Long sourceDocId; - /** - * 来源单据类型 - * - * 枚举 {@link cn.iocoder.yudao.module.mes.enums.qc.MesQcSourceDocTypeEnum} - */ - private Integer sourceDocType; /** * 来源单据行 ID * @@ -155,6 +157,7 @@ public class MesQcOqcDO extends BaseDO { /** * 检测结果 * + * 字典 {@link DictTypeConstants#MES_QC_CHECK_RESULT} * 枚举 {@link cn.iocoder.yudao.module.mes.enums.qc.MesQcCheckResultEnum} */ private Integer checkResult; @@ -175,6 +178,7 @@ public class MesQcOqcDO extends BaseDO { /** * 状态 * + * 字典 {@link DictTypeConstants#MES_ORDER_STATUS} * 枚举 {@link cn.iocoder.yudao.module.mes.enums.qc.MesQcStatusEnum} */ private Integer status; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/rqc/MesQcRqcDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/rqc/MesQcRqcDO.java index 868f4c91c..4dfcaae82 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/rqc/MesQcRqcDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/rqc/MesQcRqcDO.java @@ -11,6 +11,7 @@ import lombok.*; import java.math.BigDecimal; import java.time.LocalDateTime; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 退货检验单(RQC, Return Quality Control) DO @@ -49,16 +50,16 @@ public class MesQcRqcDO extends BaseDO { // ========== 来源单据 ========== - /** - * 来源单据 ID - */ - private Long sourceDocId; /** * 来源单据类型 * * 关联 {@link cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants} */ private Integer sourceDocType; + /** + * 来源单据 ID + */ + private Long sourceDocId; /** * 来源单据行 ID */ @@ -105,11 +106,39 @@ public class MesQcRqcDO extends BaseDO { */ private BigDecimal unqualifiedQuantity; + // ========== 缺陷统计 ========== + + /** + * 致命缺陷率(%) + */ + private BigDecimal criticalRate; + /** + * 严重缺陷率(%) + */ + private BigDecimal majorRate; + /** + * 轻微缺陷率(%) + */ + private BigDecimal minorRate; + /** + * 致命缺陷数量 + */ + private Integer criticalQuantity; + /** + * 严重缺陷数量 + */ + private Integer majorQuantity; + /** + * 轻微缺陷数量 + */ + private Integer minorQuantity; + // ========== 检验 ========== /** * 检测结果 * + * 字典 {@link DictTypeConstants#MES_QC_CHECK_RESULT} * 枚举 {@link cn.iocoder.yudao.module.mes.enums.qc.MesQcCheckResultEnum} */ private Integer checkResult; @@ -126,6 +155,7 @@ public class MesQcRqcDO extends BaseDO { /** * 状态 * + * 字典 {@link DictTypeConstants#MES_ORDER_STATUS} * 枚举 {@link MesQcStatusEnum} */ private Integer status; @@ -134,31 +164,4 @@ public class MesQcRqcDO extends BaseDO { */ private String remark; - // ========== 缺陷统计 ========== - - /** - * 致命缺陷数量 - */ - private Integer criticalQuantity; - /** - * 严重缺陷数量 - */ - private Integer majorQuantity; - /** - * 轻微缺陷数量 - */ - private Integer minorQuantity; - /** - * 致命缺陷率(%) - */ - private BigDecimal criticalRate; - /** - * 严重缺陷率(%) - */ - private BigDecimal majorRate; - /** - * 轻微缺陷率(%) - */ - private BigDecimal minorRate; - } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/tm/tool/MesTmToolDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/tm/tool/MesTmToolDO.java index b48a74277..165cff12c 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/tm/tool/MesTmToolDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/tm/tool/MesTmToolDO.java @@ -9,6 +9,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; import java.time.LocalDateTime; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 工具台账 DO @@ -45,7 +46,7 @@ public class MesTmToolDO extends BaseDO { /** * 型号规格 */ - private String spec; + private String specification; /** * 工具类型编号 * @@ -63,6 +64,7 @@ public class MesTmToolDO extends BaseDO { /** * 保养维护类型 * + * 字典 {@link DictTypeConstants#MES_TM_MAINTEN_TYPE} * 枚举 {@link MesTmMaintenTypeEnum} */ private Integer maintenType; @@ -77,6 +79,7 @@ public class MesTmToolDO extends BaseDO { /** * 状态 * + * 字典 {@link DictTypeConstants#MES_TM_TOOL_STATUS} * 枚举 {@link MesTmToolStatusEnum} */ private Integer status; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/tm/tool/MesTmToolTypeDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/tm/tool/MesTmToolTypeDO.java index c261ba8f3..a3f8d09fb 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/tm/tool/MesTmToolTypeDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/tm/tool/MesTmToolTypeDO.java @@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 工具类型 DO @@ -42,6 +43,7 @@ public class MesTmToolTypeDO extends BaseDO { /** * 保养维护类型 * + * 字典 {@link DictTypeConstants#MES_TM_MAINTEN_TYPE} * 枚举 {@link MesTmMaintenTypeEnum} */ private Integer maintenType; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/arrivalnotice/MesWmArrivalNoticeDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/arrivalnotice/MesWmArrivalNoticeDO.java index 41e232c56..a3defc0c4 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/arrivalnotice/MesWmArrivalNoticeDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/arrivalnotice/MesWmArrivalNoticeDO.java @@ -9,6 +9,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; import java.time.LocalDateTime; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 到货通知单 DO @@ -61,6 +62,7 @@ public class MesWmArrivalNoticeDO extends BaseDO { /** * 状态 * + * 字典 {@link DictTypeConstants#MES_WM_ARRIVAL_NOTICE_STATUS} * 枚举 {@link MesWmArrivalNoticeStatusEnum} */ private Integer status; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/barcode/MesWmBarcodeConfigDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/barcode/MesWmBarcodeConfigDO.java index 0d44f133a..e1c39d7ed 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/barcode/MesWmBarcodeConfigDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/barcode/MesWmBarcodeConfigDO.java @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 条码配置 DO @@ -34,12 +35,14 @@ public class MesWmBarcodeConfigDO extends BaseDO { /** * 条码格式 * + * 字典 {@link DictTypeConstants#MES_BARCODE_FORMAT} * 枚举 {@link cn.iocoder.yudao.module.mes.enums.wm.BarcodeFormatEnum} */ private Integer format; /** * 业务类型 * + * 字典 {@link DictTypeConstants#MES_BARCODE_BIZ_TYPE} * 枚举 {@link cn.iocoder.yudao.module.mes.enums.wm.BarcodeBizTypeEnum} */ private Integer bizType; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/barcode/MesWmBarcodeDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/barcode/MesWmBarcodeDO.java index 2205bb9bd..15a5b6047 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/barcode/MesWmBarcodeDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/barcode/MesWmBarcodeDO.java @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 条码清单 DO @@ -35,12 +36,14 @@ public class MesWmBarcodeDO extends BaseDO { /** * 条码格式 * + * 字典 {@link DictTypeConstants#MES_BARCODE_FORMAT} * 枚举 {@link cn.iocoder.yudao.module.mes.enums.wm.BarcodeFormatEnum} */ private Integer format; /** * 业务类型 * + * 字典 {@link DictTypeConstants#MES_BARCODE_BIZ_TYPE} * 枚举 {@link cn.iocoder.yudao.module.mes.enums.wm.BarcodeBizTypeEnum} */ private Integer bizType; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemconsume/MesWmItemConsumeDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemconsume/MesWmItemConsumeDO.java index 577cf8d4a..65e2f0ca9 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemconsume/MesWmItemConsumeDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemconsume/MesWmItemConsumeDO.java @@ -12,6 +12,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; import java.time.LocalDateTime; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 物料消耗记录 DO @@ -71,6 +72,7 @@ public class MesWmItemConsumeDO extends BaseDO { /** * 状态 * + * 字典 {@link DictTypeConstants#MES_WM_ITEM_CONSUME_STATUS} * 枚举 {@link cn.iocoder.yudao.module.mes.enums.wm.MesWmItemConsumeStatusEnum} */ private Integer status; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemreceipt/MesWmItemReceiptDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemreceipt/MesWmItemReceiptDO.java index 1dea8d232..3b3e25764 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemreceipt/MesWmItemReceiptDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/itemreceipt/MesWmItemReceiptDO.java @@ -11,6 +11,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; import java.time.LocalDateTime; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 采购入库单 DO @@ -69,6 +70,7 @@ public class MesWmItemReceiptDO extends BaseDO { /** * 状态 * + * 字典 {@link DictTypeConstants#MES_WM_ITEM_RECEIPT_STATUS} * 枚举 {@link MesWmItemReceiptStatusEnum} */ private Integer status; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/materialstock/MesWmMaterialStockDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/materialstock/MesWmMaterialStockDO.java index 502884144..95b7c5fe6 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/materialstock/MesWmMaterialStockDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/materialstock/MesWmMaterialStockDO.java @@ -34,23 +34,6 @@ public class MesWmMaterialStockDO extends BaseDO { */ @TableId private Long id; - - /** - * 在库数量 - */ - private BigDecimal quantity; - /** - * 入库时间 - */ - private LocalDateTime receiptTime; - - /** - * 供应商编号 - * - * 关联 {@link MesMdVendorDO#getId()} - */ - private Long vendorId; - // ==================== 物料维度 ==================== /** @@ -99,6 +82,23 @@ public class MesWmMaterialStockDO extends BaseDO { */ private Long areaId; + // ==================== 供应商 & 数量 ==================== + + /** + * 供应商编号 + * + * 关联 {@link MesMdVendorDO#getId()} + */ + private Long vendorId; + /** + * 在库数量 + */ + private BigDecimal quantity; + /** + * 入库时间 + */ + private LocalDateTime receiptTime; + // ==================== 状态 ==================== /** diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscissue/MesWmMiscIssueDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscissue/MesWmMiscIssueDO.java index cd722a04a..a93ed5bd4 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscissue/MesWmMiscIssueDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscissue/MesWmMiscIssueDO.java @@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; import java.time.LocalDateTime; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 杂项出库单 DO @@ -38,22 +39,23 @@ public class MesWmMiscIssueDO extends BaseDO { /** * 杂项类型 * + * 字典 {@link DictTypeConstants#MES_WM_MISC_ISSUE_TYPE} * 枚举 {@link cn.iocoder.yudao.module.mes.enums.wm.MesWmMiscIssueTypeEnum} */ private Integer type; // TODO @芋艿:这里还没定,关联哪些; /** - * 来源单据ID + * 来源单据类型 + */ + private String sourceDocType; + /** + * 来源单据 ID */ private Long sourceDocId; /** * 来源单据编号 */ private String sourceDocCode; - /** - * 来源单据类型 - */ - private String sourceDocType; /** * 出库日期 */ @@ -61,6 +63,7 @@ public class MesWmMiscIssueDO extends BaseDO { /** * 状态 * + * 字典 {@link DictTypeConstants#MES_WM_MISC_ISSUE_STATUS} * 枚举 {@link MesWmMiscIssueStatusEnum} */ private Integer status; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscreceipt/MesWmMiscReceiptDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscreceipt/MesWmMiscReceiptDO.java index 635ca292f..0fb63807c 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscreceipt/MesWmMiscReceiptDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscreceipt/MesWmMiscReceiptDO.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscreceipt; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; import cn.iocoder.yudao.module.mes.enums.wm.MesWmMiscReceiptStatusEnum; -import cn.iocoder.yudao.module.mes.enums.wm.MesWmMiscReceiptTypeEnum; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; @@ -41,9 +41,13 @@ public class MesWmMiscReceiptDO extends BaseDO { /** * 杂项类型 * - * 枚举 {@link MesWmMiscReceiptTypeEnum} + * 字典 {@link DictTypeConstants#MES_WM_MISC_RECEIPT_TYPE} */ private Integer type; + /** + * 来源单据类型 + */ + private String sourceDocType; /** * 来源单据 ID */ @@ -52,10 +56,6 @@ public class MesWmMiscReceiptDO extends BaseDO { * 来源单据编码 */ private String sourceDocCode; - /** - * 来源单据类型 - */ - private String sourceDocType; /** * 入库日期 */ @@ -63,6 +63,7 @@ public class MesWmMiscReceiptDO extends BaseDO { /** * 状态 * + * 字典 {@link DictTypeConstants#MES_WM_MISC_RECEIPT_STATUS} * 枚举 {@link MesWmMiscReceiptStatusEnum} */ private Integer status; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourceissue/MesWmOutsourceIssueDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourceissue/MesWmOutsourceIssueDO.java index a74915721..e69f65939 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourceissue/MesWmOutsourceIssueDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourceissue/MesWmOutsourceIssueDO.java @@ -10,6 +10,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; import java.time.LocalDateTime; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 外协发料单 DO @@ -58,6 +59,7 @@ public class MesWmOutsourceIssueDO extends BaseDO { /** * 单据状态 * + * 字典 {@link DictTypeConstants#MES_WM_OUTSOURCE_ISSUE_STATUS} * 枚举 {@link MesWmOutsourceIssueStatusEnum} */ private Integer status; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourcereceipt/MesWmOutsourceReceiptDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourcereceipt/MesWmOutsourceReceiptDO.java index 589721fb8..cf1a903fd 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourcereceipt/MesWmOutsourceReceiptDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourcereceipt/MesWmOutsourceReceiptDO.java @@ -9,6 +9,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; import java.time.LocalDateTime; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 外协入库单 DO @@ -55,6 +56,7 @@ public class MesWmOutsourceReceiptDO extends BaseDO { /** * 状态 * + * 字典 {@link DictTypeConstants#MES_WM_OUTSOURCE_RECEIPT_STATUS} * 枚举 {@link MesWmOutsourceReceiptStatusEnum} */ private Integer status; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourcereceipt/MesWmOutsourceReceiptLineDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourcereceipt/MesWmOutsourceReceiptLineDO.java index 30dd611c0..8f23a5372 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourcereceipt/MesWmOutsourceReceiptLineDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/outsourcereceipt/MesWmOutsourceReceiptLineDO.java @@ -11,6 +11,7 @@ import lombok.*; import java.math.BigDecimal; import java.time.LocalDateTime; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 外协入库单行 DO @@ -87,6 +88,7 @@ public class MesWmOutsourceReceiptLineDO extends BaseDO { /** * 质量状态 * + * 字典 {@link DictTypeConstants#MES_WM_QUALITY_STATUS} * 枚举 {@link cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum} */ private Integer qualityStatus; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/packages/MesWmPackageDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/packages/MesWmPackageDO.java index bef8c8207..bfb2d8778 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/packages/MesWmPackageDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/packages/MesWmPackageDO.java @@ -10,6 +10,7 @@ import lombok.*; import java.math.BigDecimal; import java.time.LocalDateTime; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 装箱单 DO @@ -97,6 +98,7 @@ public class MesWmPackageDO extends BaseDO { /** * 状态 * + * 字典 {@link DictTypeConstants#MES_WM_PACKAGE_STATUS} * 枚举 {@link cn.iocoder.yudao.module.mes.enums.wm.MesWmPackageStatusEnum} */ private Integer status; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productissue/MesWmProductIssueDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productissue/MesWmProductIssueDO.java index 83f414c6e..b6de8d957 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productissue/MesWmProductIssueDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productissue/MesWmProductIssueDO.java @@ -11,6 +11,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; import java.time.LocalDateTime; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 领料出库单 DO @@ -69,6 +70,7 @@ public class MesWmProductIssueDO extends BaseDO { /** * 状态 * + * 字典 {@link DictTypeConstants#MES_WM_PRODUCT_ISSUE_STATUS} * 枚举 {@link MesWmProductIssueStatusEnum} */ private Integer status; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productproduce/MesWmProductProduceDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productproduce/MesWmProductProduceDO.java index 4d29666c9..5d06054e3 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productproduce/MesWmProductProduceDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productproduce/MesWmProductProduceDO.java @@ -13,6 +13,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; import java.time.LocalDateTime; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 生产入库单 DO @@ -71,6 +72,7 @@ public class MesWmProductProduceDO extends BaseDO { /** * 状态 * + * 字典 {@link DictTypeConstants#MES_WM_PRODUCT_PRODUCE_STATUS} * 枚举 {@link MesWmProductProduceStatusEnum} */ private Integer status; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productproduce/MesWmProductProduceLineDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productproduce/MesWmProductProduceLineDO.java index fb2733eca..7c6dd8410 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productproduce/MesWmProductProduceLineDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productproduce/MesWmProductProduceLineDO.java @@ -10,6 +10,7 @@ import lombok.*; import java.math.BigDecimal; import java.time.LocalDateTime; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 生产入库单行 DO @@ -72,6 +73,7 @@ public class MesWmProductProduceLineDO extends BaseDO { /** * 质量状态 * + * 字典 {@link DictTypeConstants#MES_WM_QUALITY_STATUS} * 枚举 {@link cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum} */ private Integer qualityStatus; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productreceipt/MesWmProductReceiptDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productreceipt/MesWmProductReceiptDO.java index df832998f..c9a99e491 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productreceipt/MesWmProductReceiptDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productreceipt/MesWmProductReceiptDO.java @@ -10,6 +10,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; import java.time.LocalDateTime; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 产品收货(入库)单 DO @@ -56,6 +57,7 @@ public class MesWmProductReceiptDO extends BaseDO { /** * 状态 * + * 字典 {@link DictTypeConstants#MES_WM_PRODUCT_RECEIPT_STATUS} * 枚举 {@link MesWmProductReceiptStatusEnum} */ private Integer status; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productsales/MesWmProductSalesDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productsales/MesWmProductSalesDO.java index c86fb3a3d..818579b61 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productsales/MesWmProductSalesDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productsales/MesWmProductSalesDO.java @@ -10,6 +10,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; import java.time.LocalDateTime; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 销售出库单 DO @@ -49,17 +50,16 @@ public class MesWmProductSalesDO extends BaseDO { * 销售订单号 */ private String salesOrderCode; - /** - * 出库日期 - */ - private LocalDateTime salesDate; - /** * 发货通知单 ID * * 关联 {@link MesWmSalesNoticeDO#getId()} */ private Long noticeId; + /** + * 出库日期 + */ + private LocalDateTime salesDate; /** * 联系人 @@ -86,6 +86,7 @@ public class MesWmProductSalesDO extends BaseDO { /** * 状态 * + * 字典 {@link DictTypeConstants#MES_WM_PRODUCT_SALES_STATUS} * 枚举 {@link MesWmProductSalesStatusEnum} */ private Integer status; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productsales/MesWmProductSalesLineDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productsales/MesWmProductSalesLineDO.java index cf390f754..ec0405f5e 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productsales/MesWmProductSalesLineDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/productsales/MesWmProductSalesLineDO.java @@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; import cn.iocoder.yudao.module.mes.dal.dataobject.qc.oqc.MesQcOqcDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.salesnotice.MesWmSalesNoticeLineDO; import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; @@ -12,6 +13,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; import java.math.BigDecimal; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 销售出库单行 DO @@ -39,6 +41,12 @@ public class MesWmProductSalesLineDO extends BaseDO { * 关联 {@link MesWmProductSalesDO#getId()} */ private Long salesId; + /** + * 发货通知单行ID + * + * 关联 {@link MesWmSalesNoticeLineDO#getId()} + */ + private Long noticeLineId; /** * 物料ID * @@ -80,6 +88,7 @@ public class MesWmProductSalesLineDO extends BaseDO { /** * 质量状态 * + * 字典 {@link DictTypeConstants#MES_WM_QUALITY_STATUS} * 枚举 {@link MesWmQualityStatusEnum} */ private Integer qualityStatus; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnissue/MesWmReturnIssueDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnissue/MesWmReturnIssueDO.java index d0acb3700..dc08306db 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnissue/MesWmReturnIssueDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnissue/MesWmReturnIssueDO.java @@ -10,6 +10,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; import java.time.LocalDateTime; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 生产退料单 DO @@ -52,6 +53,7 @@ public class MesWmReturnIssueDO extends BaseDO { /** * 退料类型 * + * 字典 {@link DictTypeConstants#MES_WM_RETURN_ISSUE_TYPE} * 枚举 {@link cn.iocoder.yudao.module.mes.enums.wm.MesWmReturnIssueTypeEnum} */ private Integer type; @@ -62,6 +64,7 @@ public class MesWmReturnIssueDO extends BaseDO { /** * 状态 * + * 字典 {@link DictTypeConstants#MES_WM_RETURN_ISSUE_STATUS} * 枚举 {@link MesWmReturnIssueStatusEnum} */ private Integer status; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnissue/MesWmReturnIssueLineDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnissue/MesWmReturnIssueLineDO.java index 00b3ca16b..1a7a787aa 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnissue/MesWmReturnIssueLineDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnissue/MesWmReturnIssueLineDO.java @@ -11,6 +11,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; import java.math.BigDecimal; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 生产退料单行 DO @@ -77,6 +78,7 @@ public class MesWmReturnIssueLineDO extends BaseDO { /** * 质量状态 * + * 字典 {@link DictTypeConstants#MES_WM_QUALITY_STATUS} * 枚举 {@link cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum} */ private Integer qualityStatus; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnsales/MesWmReturnSalesDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnsales/MesWmReturnSalesDO.java index bb4c0975a..679a81bfb 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnsales/MesWmReturnSalesDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnsales/MesWmReturnSalesDO.java @@ -9,6 +9,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; import java.time.LocalDateTime; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 销售退货单 DO @@ -59,6 +60,7 @@ public class MesWmReturnSalesDO extends BaseDO { /** * 状态 * + * 字典 {@link DictTypeConstants#MES_WM_RETURN_SALES_STATUS} * 枚举 {@link MesWmReturnSalesStatusEnum} */ private Integer status; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnsales/MesWmReturnSalesDetailDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnsales/MesWmReturnSalesDetailDO.java index 1a3fad65e..85e70b41b 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnsales/MesWmReturnSalesDetailDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnsales/MesWmReturnSalesDetailDO.java @@ -58,6 +58,10 @@ public class MesWmReturnSalesDetailDO extends BaseDO { * 批次 ID */ private Long batchId; + /** + * 批次号 + */ + private String batchCode; /** * 仓库 ID * diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnsales/MesWmReturnSalesLineDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnsales/MesWmReturnSalesLineDO.java index 635409244..4f39b7ff4 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnsales/MesWmReturnSalesLineDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnsales/MesWmReturnSalesLineDO.java @@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; import java.math.BigDecimal; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 销售退货单行 DO @@ -49,6 +50,10 @@ public class MesWmReturnSalesLineDO extends BaseDO { * 批次 ID */ private Long batchId; + /** + * 批次号 + */ + private String batchCode; /** * 退货检验单 ID */ @@ -60,6 +65,7 @@ public class MesWmReturnSalesLineDO extends BaseDO { /** * 质量状态 * + * 字典 {@link DictTypeConstants#MES_WM_QUALITY_STATUS} * 枚举 {@link cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum} */ private Integer qualityStatus; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnvendor/MesWmReturnVendorDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnvendor/MesWmReturnVendorDO.java index 1f307e375..779b0e5ce 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnvendor/MesWmReturnVendorDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/returnvendor/MesWmReturnVendorDO.java @@ -9,6 +9,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; import java.time.LocalDateTime; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 供应商退货单 DO @@ -65,6 +66,7 @@ public class MesWmReturnVendorDO extends BaseDO { /** * 状态 * + * 字典 {@link DictTypeConstants#MES_WM_RETURN_VENDOR_STATUS} * 枚举 {@link MesWmReturnVendorStatusEnum} */ private Integer status; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/salesnotice/MesWmSalesNoticeDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/salesnotice/MesWmSalesNoticeDO.java index 01a3ea7dd..f38280dd5 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/salesnotice/MesWmSalesNoticeDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/salesnotice/MesWmSalesNoticeDO.java @@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; import java.time.LocalDateTime; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 发货通知单 DO @@ -30,11 +31,11 @@ public class MesWmSalesNoticeDO extends BaseDO { /** * 通知单编码 */ - private String noticeCode; + private String code; /** * 通知单名称 */ - private String noticeName; + private String name; /** * 销售订单编号 */ @@ -64,6 +65,7 @@ public class MesWmSalesNoticeDO extends BaseDO { /** * 状态 * + * 字典 {@link DictTypeConstants#MES_WM_SALES_NOTICE_STATUS} * 枚举 {@link cn.iocoder.yudao.module.mes.enums.wm.MesWmSalesNoticeStatusEnum} */ private Integer status; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/stocktaking/plan/MesWmStockTakingPlanDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/stocktaking/plan/MesWmStockTakingPlanDO.java index 0f2a21915..9359f6cb6 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/stocktaking/plan/MesWmStockTakingPlanDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/stocktaking/plan/MesWmStockTakingPlanDO.java @@ -9,6 +9,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; import java.time.LocalDateTime; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 盘点方案 DO @@ -44,6 +45,7 @@ public class MesWmStockTakingPlanDO extends BaseDO { /** * 盘点类型 * + * 字典 {@link DictTypeConstants#MES_WM_STOCK_TAKING_TYPE} * 枚举 {@link MesWmStockTakingTypeEnum} */ private Integer type; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/stocktaking/plan/MesWmStockTakingPlanParamDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/stocktaking/plan/MesWmStockTakingPlanParamDO.java index e01edaa34..0a580a05a 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/stocktaking/plan/MesWmStockTakingPlanParamDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/stocktaking/plan/MesWmStockTakingPlanParamDO.java @@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 盘点方案参数 DO @@ -37,6 +38,7 @@ public class MesWmStockTakingPlanParamDO extends BaseDO { /** * 参数值类型 * + * 字典 {@link DictTypeConstants#MES_WM_STOCK_TAKING_PLAN_PARAM_TYPE} * 枚举 {@link MesWmStockTakingPlanParamTypeEnum} */ private Integer type; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/stocktaking/task/MesWmStockTakingTaskDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/stocktaking/task/MesWmStockTakingTaskDO.java index 7c42087ad..d2028dabd 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/stocktaking/task/MesWmStockTakingTaskDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/stocktaking/task/MesWmStockTakingTaskDO.java @@ -10,6 +10,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; import java.time.LocalDateTime; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 盘点任务 DO @@ -47,6 +48,7 @@ public class MesWmStockTakingTaskDO extends BaseDO { /** * 盘点类型 * + * 字典 {@link DictTypeConstants#MES_WM_STOCK_TAKING_TYPE} * 枚举 {@link MesWmStockTakingTypeEnum} */ private Integer type; @@ -85,6 +87,7 @@ public class MesWmStockTakingTaskDO extends BaseDO { /** * 任务状态 * + * 字典 {@link DictTypeConstants#MES_WM_STOCK_TAKING_TASK_STATUS} * 枚举 {@link MesWmStockTakingTaskStatusEnum} */ private Integer status; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/stocktaking/task/MesWmStockTakingTaskLineDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/stocktaking/task/MesWmStockTakingTaskLineDO.java index 004ddfd92..f13686dba 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/stocktaking/task/MesWmStockTakingTaskLineDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/stocktaking/task/MesWmStockTakingTaskLineDO.java @@ -12,6 +12,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; import java.math.BigDecimal; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 盘点任务行 DO @@ -91,6 +92,7 @@ public class MesWmStockTakingTaskLineDO extends BaseDO { /** * 盘点状态 * + * 字典 {@link DictTypeConstants#MES_WM_STOCK_TAKING_TASK_LINE_STATUS} * 枚举 {@link MesWmStockTakingTaskLineStatusEnum} */ private Integer status; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/transaction/MesWmTransactionDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/transaction/MesWmTransactionDO.java index b1c317681..f574a36f4 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/transaction/MesWmTransactionDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/transaction/MesWmTransactionDO.java @@ -16,6 +16,7 @@ import lombok.*; import java.math.BigDecimal; import java.time.LocalDateTime; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 库存事务流水 DO @@ -43,15 +44,10 @@ public class MesWmTransactionDO extends BaseDO { /** * 事务类型 * + * 字典 {@link DictTypeConstants#MES_WM_TRANSACTION_TYPE} * 枚举 {@link MesWmTransactionTypeEnum} */ private Integer type; - /** - * 本次变动数量 - * - * 正数=入库,负数=出库 - */ - private BigDecimal quantity; /** * 业务类型 @@ -93,6 +89,12 @@ public class MesWmTransactionDO extends BaseDO { * 关联 {@link MesMdItemDO#getId()} */ private Long itemId; + /** + * 本次变动数量 + * + * 正数=入库,负数=出库 + */ + private BigDecimal quantity; /** * 批次 ID * diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/transfer/MesWmTransferDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/transfer/MesWmTransferDO.java index d593a3eba..64ed37afa 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/transfer/MesWmTransferDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/transfer/MesWmTransferDO.java @@ -9,6 +9,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; import java.time.LocalDateTime; +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; /** * MES 转移单 DO @@ -41,6 +42,7 @@ public class MesWmTransferDO extends BaseDO { /** * 转移单类型 * + * 字典 {@link DictTypeConstants#MES_WM_TRANSFER_TYPE} * 枚举 {@link MesWmTransferTypeEnum} */ private Integer type; @@ -82,6 +84,7 @@ public class MesWmTransferDO extends BaseDO { /** * 状态 * + * 字典 {@link DictTypeConstants#MES_WM_TRANSFER_STATUS} * 枚举 {@link MesWmTransferStatusEnum} */ private Integer status; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/warehouse/MesWmWarehouseLocationDO.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/warehouse/MesWmWarehouseLocationDO.java index bf062ce5d..1c68ff87f 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/warehouse/MesWmWarehouseLocationDO.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/warehouse/MesWmWarehouseLocationDO.java @@ -49,12 +49,6 @@ public class MesWmWarehouseLocationDO extends BaseDO { * 面积 */ private BigDecimal area; - /** - * 库位管理状态 - * - * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} - */ - private Integer areaStatus; /** * 是否冻结 */ diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/unitmeasure/MesMdUnitMeasureMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/unitmeasure/MesMdUnitMeasureMapper.java index cb9a2bf03..7b9fda792 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/unitmeasure/MesMdUnitMeasureMapper.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/unitmeasure/MesMdUnitMeasureMapper.java @@ -33,4 +33,8 @@ public interface MesMdUnitMeasureMapper extends BaseMapperX return selectList(MesMdUnitMeasureDO::getStatus, status); } + default Long selectCountByPrimaryId(Long primaryId) { + return selectCount(MesMdUnitMeasureDO::getPrimaryId, primaryId); + } + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/workstation/MesMdWorkstationMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/workstation/MesMdWorkstationMapper.java index 8819cf60c..43c403a06 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/workstation/MesMdWorkstationMapper.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/workstation/MesMdWorkstationMapper.java @@ -39,6 +39,10 @@ public interface MesMdWorkstationMapper extends BaseMapperX return selectList(MesMdWorkstationDO::getStatus, status); } + default Long selectCountByWorkshopId(Long workshopId) { + return selectCount(MesMdWorkstationDO::getWorkshopId, workshopId); + } + default Long selectCountByWarehouseId(Long warehouseId) { return selectCount(MesMdWorkstationDO::getWarehouseId, warehouseId); } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/workstation/MesMdWorkstationToolMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/workstation/MesMdWorkstationToolMapper.java index fcb8268f6..c1ac2f44c 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/workstation/MesMdWorkstationToolMapper.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/md/workstation/MesMdWorkstationToolMapper.java @@ -29,4 +29,8 @@ public interface MesMdWorkstationToolMapper extends BaseMapperX { .orderByDesc(MesProTaskIssueDO::getId)); } + default Long selectCountByUnitMeasureId(Long unitMeasureId) { + return selectCount(MesProTaskIssueDO::getUnitMeasureId, unitMeasureId); + } + default List selectListByTaskId(Long taskId) { return selectList(new LambdaQueryWrapperX() .eq(MesProTaskIssueDO::getTaskId, taskId) diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/task/MesProTaskMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/task/MesProTaskMapper.java index ade7495a8..21b9f4455 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/task/MesProTaskMapper.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/task/MesProTaskMapper.java @@ -3,7 +3,9 @@ package cn.iocoder.yudao.module.mes.dal.mysql.pro.task; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProcessDO; import cn.iocoder.yudao.module.mes.dal.dataobject.pro.task.MesProTaskDO; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; @@ -20,16 +22,26 @@ import java.util.List; public interface MesProTaskMapper extends BaseMapperX { default PageResult selectPage(MesProTaskPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .likeIfPresent(MesProTaskDO::getCode, reqVO.getCode()) + MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); + query.selectAll(MesProTaskDO.class); + // 当需要按 checkFlag 过滤时,LEFT JOIN pro_route_process + if (reqVO.getCheckFlag() != null) { + query.leftJoin(MesProRouteProcessDO.class, on -> on + .eq(MesProRouteProcessDO::getRouteId, MesProTaskDO::getRouteId) + .eq(MesProRouteProcessDO::getProcessId, MesProTaskDO::getProcessId)); + query.eq(MesProRouteProcessDO::getCheckFlag, reqVO.getCheckFlag()); + } + query.likeIfPresent(MesProTaskDO::getCode, reqVO.getCode()) .likeIfPresent(MesProTaskDO::getName, reqVO.getName()) .eqIfPresent(MesProTaskDO::getWorkOrderId, reqVO.getWorkOrderId()) .eqIfPresent(MesProTaskDO::getRouteId, reqVO.getRouteId()) .eqIfPresent(MesProTaskDO::getProcessId, reqVO.getProcessId()) .eqIfPresent(MesProTaskDO::getWorkstationId, reqVO.getWorkstationId()) .eqIfPresent(MesProTaskDO::getStatus, reqVO.getStatus()) + .inIfPresent(MesProTaskDO::getStatus, reqVO.getStatuses()) .betweenIfPresent(MesProTaskDO::getCreateTime, reqVO.getCreateTime()) - .orderByDesc(MesProTaskDO::getId)); + .orderByDesc(MesProTaskDO::getId); + return selectPage(reqVO, query); } default List selectListByWorkOrderId(Long workOrderId) { diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/workorder/MesProWorkOrderMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/workorder/MesProWorkOrderMapper.java index b6f9b0961..e9352b851 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/workorder/MesProWorkOrderMapper.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/workorder/MesProWorkOrderMapper.java @@ -26,6 +26,7 @@ public interface MesProWorkOrderMapper extends BaseMapperX { .likeIfPresent(MesProWorkOrderDO::getOrderSourceCode, reqVO.getOrderSourceCode()) .eqIfPresent(MesProWorkOrderDO::getProductId, reqVO.getProductId()) .eqIfPresent(MesProWorkOrderDO::getClientId, reqVO.getClientId()) + .eqIfPresent(MesProWorkOrderDO::getStatus, reqVO.getStatus()) .betweenIfPresent(MesProWorkOrderDO::getRequestDate, reqVO.getRequestDate()) .orderByDesc(MesProWorkOrderDO::getId)); } @@ -40,4 +41,8 @@ public interface MesProWorkOrderMapper extends BaseMapperX { .setSql("quantity_produced = IFNULL(quantity_produced, 0) + " + incrQuantityProduced)); } + default Long selectCountByVendorId(Long vendorId) { + return selectCount(MesProWorkOrderDO::getVendorId, vendorId); + } + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/indicatorresult/MesQcIndicatorResultMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/indicatorresult/MesQcIndicatorResultMapper.java index 265ba1218..b134d961e 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/indicatorresult/MesQcIndicatorResultMapper.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/indicatorresult/MesQcIndicatorResultMapper.java @@ -24,4 +24,10 @@ public interface MesQcIndicatorResultMapper extends BaseMapperX() + .eq(MesQcIndicatorResultDO::getQcId, qcId) + .eq(MesQcIndicatorResultDO::getQcType, qcType)); + } + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/ipqc/MesQcIpqcLineMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/ipqc/MesQcIpqcLineMapper.java index 4dad4b940..37b4a0951 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/ipqc/MesQcIpqcLineMapper.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/ipqc/MesQcIpqcLineMapper.java @@ -32,4 +32,8 @@ public interface MesQcIpqcLineMapper extends BaseMapperX { .eq(MesQcIpqcLineDO::getIpqcId, ipqcId)); } + default Long selectCountByUnitMeasureId(Long unitMeasureId) { + return selectCount(MesQcIpqcLineDO::getUnitMeasureId, unitMeasureId); + } + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/iqc/MesQcIqcLineMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/iqc/MesQcIqcLineMapper.java index d238845c1..761b54d6e 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/iqc/MesQcIqcLineMapper.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/iqc/MesQcIqcLineMapper.java @@ -32,4 +32,8 @@ public interface MesQcIqcLineMapper extends BaseMapperX { .eq(MesQcIqcLineDO::getIqcId, iqcId)); } + default Long selectCountByUnitMeasureId(Long unitMeasureId) { + return selectCount(MesQcIqcLineDO::getUnitMeasureId, unitMeasureId); + } + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/iqc/MesQcIqcMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/iqc/MesQcIqcMapper.java index 50a50e91a..07000d619 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/iqc/MesQcIqcMapper.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/iqc/MesQcIqcMapper.java @@ -32,4 +32,8 @@ public interface MesQcIqcMapper extends BaseMapperX { return selectOne(MesQcIqcDO::getCode, code); } + default Long selectCountByVendorId(Long vendorId) { + return selectCount(MesQcIqcDO::getVendorId, vendorId); + } + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/oqc/MesQcOqcLineMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/oqc/MesQcOqcLineMapper.java index 34031d0c7..a3907c736 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/oqc/MesQcOqcLineMapper.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/oqc/MesQcOqcLineMapper.java @@ -32,4 +32,8 @@ public interface MesQcOqcLineMapper extends BaseMapperX { .eq(MesQcOqcLineDO::getOqcId, oqcId)); } + default Long selectCountByUnitMeasureId(Long unitMeasureId) { + return selectCount(MesQcOqcLineDO::getUnitMeasureId, unitMeasureId); + } + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/rqc/MesQcRqcLineMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/rqc/MesQcRqcLineMapper.java index 1fc134dfc..e3d48d852 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/rqc/MesQcRqcLineMapper.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/rqc/MesQcRqcLineMapper.java @@ -32,4 +32,8 @@ public interface MesQcRqcLineMapper extends BaseMapperX { .eq(MesQcRqcLineDO::getRqcId, rqcId)); } + default Long selectCountByUnitMeasureId(Long unitMeasureId) { + return selectCount(MesQcRqcLineDO::getUnitMeasureId, unitMeasureId); + } + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/template/MesQcTemplateIndicatorMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/template/MesQcTemplateIndicatorMapper.java index 94b2ae2e1..1e4313382 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/template/MesQcTemplateIndicatorMapper.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/template/MesQcTemplateIndicatorMapper.java @@ -27,6 +27,10 @@ public interface MesQcTemplateIndicatorMapper extends BaseMapperX() .eq(MesQcTemplateIndicatorDO::getTemplateId, templateId)); diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/tm/tool/MesTmToolMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/tm/tool/MesTmToolMapper.java index f2f256b59..582957fa5 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/tm/tool/MesTmToolMapper.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/tm/tool/MesTmToolMapper.java @@ -21,7 +21,7 @@ public interface MesTmToolMapper extends BaseMapperX { .likeIfPresent(MesTmToolDO::getName, reqVO.getName()) .eqIfPresent(MesTmToolDO::getToolTypeId, reqVO.getToolTypeId()) .likeIfPresent(MesTmToolDO::getBrand, reqVO.getBrand()) - .likeIfPresent(MesTmToolDO::getSpec, reqVO.getSpec()) + .likeIfPresent(MesTmToolDO::getSpecification, reqVO.getSpecification()) .eqIfPresent(MesTmToolDO::getStatus, reqVO.getStatus()) .orderByDesc(MesTmToolDO::getId)); } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/arrivalnotice/MesWmArrivalNoticeMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/arrivalnotice/MesWmArrivalNoticeMapper.java index 38119a9ec..12dddc1a2 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/arrivalnotice/MesWmArrivalNoticeMapper.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/arrivalnotice/MesWmArrivalNoticeMapper.java @@ -7,8 +7,6 @@ import cn.iocoder.yudao.module.mes.controller.admin.wm.arrivalnotice.vo.MesWmArr import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalNoticeDO; import org.apache.ibatis.annotations.Mapper; -import java.util.List; - /** * MES 到货通知单 Mapper */ @@ -30,10 +28,6 @@ public interface MesWmArrivalNoticeMapper extends BaseMapperX selectListByStatus(Integer status) { - return selectList(MesWmArrivalNoticeDO::getStatus, status); - } - default Long selectCountByVendorId(Long vendorId) { return selectCount(MesWmArrivalNoticeDO::getVendorId, vendorId); } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/batch/MesWmBatchMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/batch/MesWmBatchMapper.java index 195858cc8..db221d87b 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/batch/MesWmBatchMapper.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/batch/MesWmBatchMapper.java @@ -24,6 +24,10 @@ public interface MesWmBatchMapper extends BaseMapperX { return selectOne(MesWmBatchDO:: getCode, code); } + default Long selectCountByToolId(Long toolId) { + return selectCount(MesWmBatchDO::getToolId, toolId); + } + default PageResult selectPage(MesWmBatchPageReqVO reqVO) { return selectPage(reqVO, new LambdaQueryWrapperX() .likeIfPresent(MesWmBatchDO::getCode, reqVO.getCode()) diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/materialstock/MesWmMaterialStockMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/materialstock/MesWmMaterialStockMapper.java index 178717cbe..2810c054b 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/materialstock/MesWmMaterialStockMapper.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/materialstock/MesWmMaterialStockMapper.java @@ -21,18 +21,29 @@ public interface MesWmMaterialStockMapper extends BaseMapperX selectPage(MesWmMaterialStockPageReqVO reqVO, Collection itemTypeIds, - Collection itemIds) { - return selectPage(reqVO, new LambdaQueryWrapperX() + Collection itemIds, + Long virtualWarehouseId) { + LambdaQueryWrapperX wrapper = new LambdaQueryWrapperX() .inIfPresent(MesWmMaterialStockDO::getItemTypeId, itemTypeIds) .inIfPresent(MesWmMaterialStockDO::getItemId, itemIds) .likeIfPresent(MesWmMaterialStockDO::getBatchCode, reqVO.getBatchCode()) + .eqIfPresent(MesWmMaterialStockDO::getBatchId, reqVO.getBatchId()) .eqIfPresent(MesWmMaterialStockDO::getWarehouseId, reqVO.getWarehouseId()) .eqIfPresent(MesWmMaterialStockDO::getLocationId, reqVO.getLocationId()) .eqIfPresent(MesWmMaterialStockDO::getAreaId, reqVO.getAreaId()) .eqIfPresent(MesWmMaterialStockDO::getVendorId, reqVO.getVendorId()) - .eqIfPresent(MesWmMaterialStockDO::getFrozen, reqVO.getFrozen()) - .ne(MesWmMaterialStockDO::getQuantity, BigDecimal.ZERO) - .orderByAsc(MesWmMaterialStockDO::getReceiptTime)); + .eqIfPresent(MesWmMaterialStockDO::getFrozen, reqVO.getFrozen()); + wrapper.ne(MesWmMaterialStockDO::getQuantity, BigDecimal.ZERO) + .orderByAsc(MesWmMaterialStockDO::getReceiptTime); + // 虚拟仓过滤(Service 层已将 virtualFilter 解析为 virtualWarehouseId) + if (virtualWarehouseId != null) { + if (MesWmMaterialStockPageReqVO.VIRTUAL_FILTER_ONLY.equals(reqVO.getVirtualFilter())) { + wrapper.eq(MesWmMaterialStockDO::getWarehouseId, virtualWarehouseId); + } else if (MesWmMaterialStockPageReqVO.VIRTUAL_FILTER_EXCLUDE.equals(reqVO.getVirtualFilter())) { + wrapper.ne(MesWmMaterialStockDO::getWarehouseId, virtualWarehouseId); + } + } + return selectPage(reqVO, wrapper); } default Long selectCountByWarehouseId(Long warehouseId) { diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/outsourceissue/MesWmOutsourceIssueMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/outsourceissue/MesWmOutsourceIssueMapper.java index 48b285515..fc696d52e 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/outsourceissue/MesWmOutsourceIssueMapper.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/outsourceissue/MesWmOutsourceIssueMapper.java @@ -29,4 +29,8 @@ public interface MesWmOutsourceIssueMapper extends BaseMapperX { .eqIfPresent(MesWmPackageDO::getClientId, reqVO.getClientId()) .eqIfPresent(MesWmPackageDO::getParentId, reqVO.getParentId()) .eqIfPresent(MesWmPackageDO::getInspectorUserId, reqVO.getInspectorUserId()) + .eqIfPresent(MesWmPackageDO::getStatus, reqVO.getStatus()) .orderByDesc(MesWmPackageDO::getId)); } @@ -42,11 +43,5 @@ public interface MesWmPackageMapper extends BaseMapperX { .in(MesWmPackageDO::getParentId, parentIds)); } - default List selectChildableList() { - return selectList(new LambdaQueryWrapperX() - .eq(MesWmPackageDO::getParentId, MesWmPackageDO.PARENT_ID_ROOT) - .eq(MesWmPackageDO::getStatus, MesWmPackageStatusEnum.FINISHED.getStatus()) - .orderByDesc(MesWmPackageDO::getId)); - } } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/salesnotice/MesWmSalesNoticeMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/salesnotice/MesWmSalesNoticeMapper.java index de0477749..a4256f0f2 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/salesnotice/MesWmSalesNoticeMapper.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/salesnotice/MesWmSalesNoticeMapper.java @@ -7,8 +7,6 @@ import cn.iocoder.yudao.module.mes.controller.admin.wm.salesnotice.vo.MesWmSales import cn.iocoder.yudao.module.mes.dal.dataobject.wm.salesnotice.MesWmSalesNoticeDO; import org.apache.ibatis.annotations.Mapper; -import java.util.List; - /** * MES 发货通知单 Mapper */ @@ -17,19 +15,16 @@ public interface MesWmSalesNoticeMapper extends BaseMapperX default PageResult selectPage(MesWmSalesNoticePageReqVO reqVO) { return selectPage(reqVO, new LambdaQueryWrapperX() - .likeIfPresent(MesWmSalesNoticeDO::getNoticeCode, reqVO.getNoticeCode()) - .likeIfPresent(MesWmSalesNoticeDO::getNoticeName, reqVO.getNoticeName()) + .likeIfPresent(MesWmSalesNoticeDO::getCode, reqVO.getCode()) + .likeIfPresent(MesWmSalesNoticeDO::getName, reqVO.getName()) .likeIfPresent(MesWmSalesNoticeDO::getSalesOrderCode, reqVO.getSalesOrderCode()) .eqIfPresent(MesWmSalesNoticeDO::getClientId, reqVO.getClientId()) + .eqIfPresent(MesWmSalesNoticeDO::getStatus, reqVO.getStatus()) .orderByDesc(MesWmSalesNoticeDO::getId)); } - default MesWmSalesNoticeDO selectByNoticeCode(String noticeCode) { - return selectOne(MesWmSalesNoticeDO::getNoticeCode, noticeCode); - } - - default List selectListByStatus(Integer status) { - return selectList(MesWmSalesNoticeDO::getStatus, status); + default MesWmSalesNoticeDO selectByCode(String code) { + return selectOne(MesWmSalesNoticeDO::getCode, code); } } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/stocktaking/plan/MesWmStockTakingPlanMapper.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/stocktaking/plan/MesWmStockTakingPlanMapper.java index b7cd7339a..fbfc19102 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/stocktaking/plan/MesWmStockTakingPlanMapper.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/stocktaking/plan/MesWmStockTakingPlanMapper.java @@ -7,7 +7,6 @@ import cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.plan.vo.MesWm import cn.iocoder.yudao.module.mes.dal.dataobject.wm.stocktaking.plan.MesWmStockTakingPlanDO; import org.apache.ibatis.annotations.Mapper; -import java.util.List; /** * MES 盘点方案 Mapper @@ -26,12 +25,7 @@ public interface MesWmStockTakingPlanMapper extends BaseMapperX selectListByStatus(Integer status) { - return selectList(new LambdaQueryWrapperX() - .eqIfPresent(MesWmStockTakingPlanDO::getStatus, status) + .eqIfPresent(MesWmStockTakingPlanDO::getStatus, reqVO.getStatus()) .orderByDesc(MesWmStockTakingPlanDO::getId)); } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanService.java index bfb1fe2f7..c681d7ef5 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanService.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanService.java @@ -62,6 +62,15 @@ public interface MesDvCheckPlanService { */ void validateCheckPlanExists(Long id); + /** + * 校验点检保养方案存在、类型匹配,且方案已启用 + * + * @param id 方案编号 + * @param type 期望的方案类型 + * @return 方案 + */ + MesDvCheckPlanDO validateCheckPlanExistsAndType(Long id, Integer type); + /** * 校验点检保养方案为草稿状态 * diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanServiceImpl.java index 644a149f2..fde9b0cd2 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanServiceImpl.java @@ -33,6 +33,7 @@ public class MesDvCheckPlanServiceImpl implements MesDvCheckPlanService { @Resource private MesDvCheckPlanMapper checkPlanMapper; + @Resource @Lazy private MesDvCheckPlanMachineryService checkPlanMachineryService; @@ -149,6 +150,20 @@ 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); + } + // 校验方案已启用 + if (ObjUtil.notEqual(MesDvCheckPlanStatusEnum.ENABLED.getStatus(), plan.getStatus())) { + throw exception(DV_CHECK_PLAN_NOT_ENABLED_FOR_RECORD); + } + return plan; + } + private void validateCheckPlanCodeUnique(Long id, String code) { MesDvCheckPlanDO plan = checkPlanMapper.selectByCode(code); if (plan == null) { diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanSubjectServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanSubjectServiceImpl.java index e0aa10a71..4ebc7f627 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanSubjectServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkplan/MesDvCheckPlanSubjectServiceImpl.java @@ -26,6 +26,7 @@ public class MesDvCheckPlanSubjectServiceImpl implements MesDvCheckPlanSubjectSe @Resource private MesDvCheckPlanSubjectMapper checkPlanSubjectMapper; + @Resource @Lazy private MesDvCheckPlanService checkPlanService; @@ -37,7 +38,7 @@ public class MesDvCheckPlanSubjectServiceImpl implements MesDvCheckPlanSubjectSe // 1.1 校验方案草稿状态 checkPlanService.validateCheckPlanPrepare(createReqVO.getPlanId()); // 1.2 校验项目存在 - subjectService.validateSubjectExists(createReqVO.getSubjectId()); + subjectService.validateSubjectExistsAndEnable(createReqVO.getSubjectId()); // 1.3 校验同一方案下项目不重复 if (checkPlanSubjectMapper.selectByPlanIdAndSubjectId(createReqVO.getPlanId(), createReqVO.getSubjectId()) != null) { throw exception(DV_CHECK_PLAN_SUBJECT_DUPLICATE); diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkrecord/MesDvCheckRecordLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkrecord/MesDvCheckRecordLineServiceImpl.java index 25f29e199..a0eab04f1 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkrecord/MesDvCheckRecordLineServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkrecord/MesDvCheckRecordLineServiceImpl.java @@ -58,13 +58,10 @@ public class MesDvCheckRecordLineServiceImpl implements MesDvCheckRecordLineServ @Override public void deleteCheckRecordLine(Long id) { // 1. 校验存在 - // TODO @AI:复用 validateCheckRecordLineExists 方法; - MesDvCheckRecordLineDO line = checkRecordLineMapper.selectById(id); - if (line == null) { - throw exception(DV_CHECK_RECORD_LINE_NOT_EXISTS); - } + validateCheckRecordLineExists(id); // 2. 校验父记录为草稿状态 + MesDvCheckRecordLineDO line = checkRecordLineMapper.selectById(id); checkRecordService.validateCheckRecordDraft(line.getRecordId()); // 3. 删除 checkRecordLineMapper.deleteById(id); diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkrecord/MesDvCheckRecordServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkrecord/MesDvCheckRecordServiceImpl.java index 22be2b84f..6eca888cc 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/checkrecord/MesDvCheckRecordServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/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,8 +38,10 @@ import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; @Validated public class MesDvCheckRecordServiceImpl implements MesDvCheckRecordService { + @Resource private MesDvCheckRecordMapper checkRecordMapper; + @Resource @Lazy private MesDvCheckRecordLineService checkRecordLineService; @@ -48,6 +51,7 @@ public class MesDvCheckRecordServiceImpl implements MesDvCheckRecordService { private MesDvCheckPlanService checkPlanService; @Resource private MesDvCheckPlanSubjectService checkPlanSubjectService; + @Resource private AdminUserApi adminUserApi; @@ -95,6 +99,7 @@ public class MesDvCheckRecordServiceImpl implements MesDvCheckRecordService { } @Override + @Transactional(rollbackFor = Exception.class) public void submitCheckRecord(Long id) { // 1.1 校验状态为草稿 validateCheckRecordDraft(id); @@ -105,9 +110,15 @@ public class MesDvCheckRecordServiceImpl implements MesDvCheckRecordService { } // 2. 状态改为已完成 + MesDvCheckRecordDO record = checkRecordMapper.selectById(id); MesDvCheckRecordDO updateObj = new MesDvCheckRecordDO() .setId(id).setStatus(MesDvCheckRecordStatusEnum.FINISHED.getStatus()); checkRecordMapper.updateById(updateObj); + + // 3. 回写设备台账的【最近点检时间】 + if (record.getCheckTime() != null) { + machineryService.updateMachineryLastCheckTime(record.getMachineryId(), record.getCheckTime()); + } } @Override @@ -162,7 +173,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/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/machinery/MesDvMachineryService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/machinery/MesDvMachineryService.java index cc4dac3a8..5a5588d87 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/machinery/MesDvMachineryService.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/machinery/MesDvMachineryService.java @@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.MesDvMachine import cn.iocoder.yudao.module.mes.dal.dataobject.dv.machinery.MesDvMachineryDO; import jakarta.validation.Valid; +import java.time.LocalDateTime; import java.util.Collection; import java.util.List; import java.util.Map; @@ -99,6 +100,22 @@ public interface MesDvMachineryService { return convertMap(getMachineryList(ids), MesDvMachineryDO::getId); } + /** + * 更新设备的最近点检时间 + * + * @param machineryId 设备编号 + * @param lastCheckTime 最近点检时间 + */ + void updateMachineryLastCheckTime(Long machineryId, LocalDateTime lastCheckTime); + + /** + * 更新设备的最近保养时间 + * + * @param machineryId 设备编号 + * @param lastMaintenTime 最近保养时间 + */ + void updateMachineryLastMaintenTime(Long machineryId, LocalDateTime lastMaintenTime); + /** * 导入设备列表 * diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/machinery/MesDvMachineryServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/machinery/MesDvMachineryServiceImpl.java index 9da51df85..9e74cf637 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/machinery/MesDvMachineryServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/machinery/MesDvMachineryServiceImpl.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.mes.service.dv.machinery; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.MesDvMachineryImportExcelVO; @@ -26,6 +27,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; +import java.time.LocalDateTime; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; @@ -48,26 +50,20 @@ public class MesDvMachineryServiceImpl implements MesDvMachineryService { @Resource @Lazy // 延迟加载,避免循环依赖 private MesDvMachineryTypeService machineryTypeService; - @Resource @Lazy private MesMdWorkshopService workshopService; - @Resource private MesWmBarcodeService barcodeService; - @Resource @Lazy private MesDvCheckPlanMachineryService checkPlanMachineryService; - @Resource @Lazy private MesDvCheckRecordService checkRecordService; - @Resource @Lazy private MesDvMaintenRecordService maintenRecordService; - @Resource @Lazy private MesDvRepairService repairService; @@ -173,6 +169,16 @@ public class MesDvMachineryServiceImpl implements MesDvMachineryService { return machineryMapper.selectCountByMachineryTypeId(machineryTypeId); } + @Override + public void updateMachineryLastCheckTime(Long machineryId, LocalDateTime lastCheckTime) { + machineryMapper.updateById(new MesDvMachineryDO().setId(machineryId).setLastCheckTime(lastCheckTime)); + } + + @Override + public void updateMachineryLastMaintenTime(Long machineryId, LocalDateTime lastMaintenTime) { + machineryMapper.updateById(new MesDvMachineryDO().setId(machineryId).setLastMaintenTime(lastMaintenTime)); + } + @Override public List getMachineryList() { return machineryMapper.selectList(); diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/maintenrecord/MesDvMaintenRecordLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/maintenrecord/MesDvMaintenRecordLineServiceImpl.java index 01bb05e94..618fe64e5 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/maintenrecord/MesDvMaintenRecordLineServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/maintenrecord/MesDvMaintenRecordLineServiceImpl.java @@ -73,7 +73,7 @@ public class MesDvMaintenRecordLineServiceImpl implements MesDvMaintenRecordLine // 校验保养记录为草稿状态 maintenRecordService.validateMaintenRecordDraft(reqVO.getRecordId()); // 校验保养项目是否存在 - subjectService.validateSubjectExists(reqVO.getSubjectId()); + subjectService.validateSubjectExistsAndEnable(reqVO.getSubjectId()); } private MesDvMaintenRecordLineDO validateMaintenRecordLineExists(Long id) { diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/maintenrecord/MesDvMaintenRecordServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/maintenrecord/MesDvMaintenRecordServiceImpl.java index afb44b91d..b3640414b 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/maintenrecord/MesDvMaintenRecordServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/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; @@ -34,6 +35,7 @@ public class MesDvMaintenRecordServiceImpl implements MesDvMaintenRecordService @Resource private MesDvMaintenRecordMapper maintenRecordMapper; + @Resource @Lazy private MesDvMaintenRecordLineService maintenRecordLineService; @@ -67,6 +69,7 @@ public class MesDvMaintenRecordServiceImpl implements MesDvMaintenRecordService } @Override + @Transactional(rollbackFor = Exception.class) public void submitMaintenRecord(Long id) { // 1.1 校验状态为草稿 validateMaintenRecordDraft(id); @@ -77,10 +80,16 @@ public class MesDvMaintenRecordServiceImpl implements MesDvMaintenRecordService } // 2. 状态改为已提交 + MesDvMaintenRecordDO record = maintenRecordMapper.selectById(id); MesDvMaintenRecordDO updateObj = new MesDvMaintenRecordDO(); updateObj.setId(id); updateObj.setStatus(MesDvMaintenRecordStatusEnum.SUBMITTED.getStatus()); maintenRecordMapper.updateById(updateObj); + + // 3. 回写设备台账的【最近保养时间】 + if (record.getMaintenTime() != null) { + machineryService.updateMachineryLastMaintenTime(record.getMachineryId(), record.getMaintenTime()); + } } @Override @@ -100,7 +109,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/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/repair/MesDvRepairLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/repair/MesDvRepairLineServiceImpl.java index 09ee904c6..abd31fda6 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/repair/MesDvRepairLineServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/repair/MesDvRepairLineServiceImpl.java @@ -79,7 +79,7 @@ public class MesDvRepairLineServiceImpl implements MesDvRepairLineService { repairService.validateRepairExists(reqVO.getRepairId()); // 校验点检保养项目是否存在(可选) if (reqVO.getSubjectId() != null) { - subjectService.validateSubjectExists(reqVO.getSubjectId()); + subjectService.validateSubjectExistsAndEnable(reqVO.getSubjectId()); } } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/subject/MesDvSubjectService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/subject/MesDvSubjectService.java index c2c613ebd..adcf15b06 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/subject/MesDvSubjectService.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/subject/MesDvSubjectService.java @@ -64,6 +64,13 @@ public interface MesDvSubjectService { */ void validateSubjectExists(Long id); + /** + * 校验点检保养项目存在且启用 + * + * @param id 编号 + */ + void validateSubjectExistsAndEnable(Long id); + /** * 获得点检保养项目列表 * diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/subject/MesDvSubjectServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/subject/MesDvSubjectServiceImpl.java index d47fb075b..60c1839a9 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/subject/MesDvSubjectServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/dv/subject/MesDvSubjectServiceImpl.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.mes.service.dv.subject; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.mes.controller.admin.dv.subject.vo.MesDvSubjectPageReqVO; @@ -32,7 +33,7 @@ public class MesDvSubjectServiceImpl implements MesDvSubjectService { @Resource private MesDvSubjectMapper subjectMapper; - // DONE @AI:调用对方的 service + @Resource @Lazy private MesDvCheckPlanSubjectService checkPlanSubjectService; @@ -80,6 +81,17 @@ public class MesDvSubjectServiceImpl implements MesDvSubjectService { } } + @Override + public void validateSubjectExistsAndEnable(Long id) { + MesDvSubjectDO subject = subjectMapper.selectById(id); + if (subject == null) { + throw exception(DV_SUBJECT_NOT_EXISTS); + } + if (ObjUtil.notEqual(CommonStatusEnum.ENABLE.getStatus(), subject.getStatus())) { + throw exception(DV_SUBJECT_IS_DISABLE); + } + } + private void validateSubjectCodeUnique(Long id, String code) { if (code == null) { return; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/client/MesMdClientService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/client/MesMdClientService.java index 7c86f42da..f0887d19f 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/client/MesMdClientService.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/client/MesMdClientService.java @@ -84,6 +84,13 @@ public interface MesMdClientService { */ void validateClientExists(Long id); + /** + * 校验客户存在且启用 + * + * @param id 编号 + */ + void validateClientExistsAndEnable(Long id); + /** * 批量导入客户 * diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/client/MesMdClientServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/client/MesMdClientServiceImpl.java index 03b53b971..516058f84 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/client/MesMdClientServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/client/MesMdClientServiceImpl.java @@ -10,6 +10,7 @@ import cn.iocoder.yudao.module.mes.controller.admin.md.client.vo.MesMdClientImpo import cn.iocoder.yudao.module.mes.controller.admin.md.client.vo.MesMdClientImportRespVO; import cn.iocoder.yudao.module.mes.controller.admin.md.client.vo.MesMdClientPageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.md.client.vo.MesMdClientSaveReqVO; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.module.mes.dal.dataobject.md.client.MesMdClientDO; import cn.iocoder.yudao.module.mes.dal.mysql.md.client.MesMdClientMapper; import cn.iocoder.yudao.module.mes.enums.wm.BarcodeBizTypeEnum; @@ -95,6 +96,17 @@ public class MesMdClientServiceImpl implements MesMdClientService { } } + @Override + public void validateClientExistsAndEnable(Long id) { + MesMdClientDO client = clientMapper.selectById(id); + if (client == null) { + throw exception(MD_CLIENT_NOT_EXISTS); + } + if (ObjUtil.notEqual(CommonStatusEnum.ENABLE.getStatus(), client.getStatus())) { + throw exception(MD_CLIENT_IS_DISABLE); + } + } + private void validateClientCodeUnique(Long id, String code) { MesMdClientDO client = clientMapper.selectByCode(code); if (client == null) { diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemService.java index d35cc4bc6..83834706a 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemService.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemService.java @@ -67,6 +67,14 @@ public interface MesMdItemService { */ MesMdItemDO validateItemExists(Long id); + /** + * 校验物料产品存在且启用 + * + * @param id 编号 + * @return 物料产品 + */ + MesMdItemDO validateItemExistsAndEnable(Long id); + /** * 获得物料产品分页 * @@ -110,4 +118,12 @@ public interface MesMdItemService { */ MesMdItemImportRespVO importItemList(List importItems, boolean updateSupport); + /** + * 基于计量单位编号,获得物料数量 + * + * @param unitMeasureId 计量单位编号 + * @return 物料数量 + */ + Long getItemCountByUnitMeasureId(Long unitMeasureId); + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemServiceImpl.java index 47af46b49..81f2dee3b 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdItemServiceImpl.java @@ -17,8 +17,10 @@ import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemTypeDO; import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO; import cn.iocoder.yudao.module.mes.dal.mysql.md.item.MesMdItemMapper; import cn.iocoder.yudao.module.mes.enums.md.MesMdItemTypeEnum; +import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodeRuleCodeEnum; import cn.iocoder.yudao.module.mes.enums.wm.BarcodeBizTypeEnum; import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService; +import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodeRecordService; import cn.iocoder.yudao.module.mes.service.wm.barcode.MesWmBarcodeService; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; @@ -59,6 +61,8 @@ public class MesMdItemServiceImpl implements MesMdItemService { private MesMdProductSipService productSipService; @Resource private MesWmBarcodeService barcodeService; + @Resource + private MesMdAutoCodeRecordService autoCodeRecordService; @Override public Long createItem(MesMdItemSaveReqVO createReqVO) { @@ -150,6 +154,15 @@ public class MesMdItemServiceImpl implements MesMdItemService { return item; } + @Override + public MesMdItemDO validateItemExistsAndEnable(Long id) { + MesMdItemDO item = validateItemExists(id); + if (ObjUtil.notEqual(CommonStatusEnum.ENABLE.getStatus(), item.getStatus())) { + throw exception(MD_ITEM_IS_DISABLE); + } + return item; + } + private void validateItemCodeUnique(Long id, String code) { MesMdItemDO item = itemMapper.selectByCode(code); if (item == null) { @@ -174,6 +187,11 @@ public class MesMdItemServiceImpl implements MesMdItemService { if (itemTypeService.getItemType(itemTypeId) == null) { throw exception(MD_ITEM_TYPE_NOT_EXISTS); } + // 校验必须是叶子分类(没有子分类) + List children = itemTypeService.getItemTypeChildrenList(itemTypeId); + if (CollUtil.isNotEmpty(children)) { + throw exception(MD_ITEM_TYPE_NOT_LEAF); + } } private void validateUnitMeasureExists(Long unitMeasureId) { @@ -251,6 +269,11 @@ public class MesMdItemServiceImpl implements MesMdItemService { return itemMapper.selectCountByItemTypeId(itemTypeId); } + @Override + public Long getItemCountByUnitMeasureId(Long unitMeasureId) { + return itemMapper.selectCountByUnitMeasureId(unitMeasureId); + } + @Override @Transactional(rollbackFor = Exception.class) public MesMdItemImportRespVO importItemList(List importItems, boolean updateSupport) { @@ -267,11 +290,11 @@ public class MesMdItemServiceImpl implements MesMdItemService { importItems.forEach(importItem -> { int currentIndex = index.getAndIncrement(); // 2.1 校验字段 - String key = StrUtil.blankToDefault(importItem.getCode(), "第 " + currentIndex + " 行"); if (StrUtil.isBlank(importItem.getCode())) { - respVO.getFailureCodes().put(key, "物料编码不能为空"); - return; + // 空编码时自动生成 + importItem.setCode(autoCodeRecordService.generateAutoCode(MesMdAutoCodeRuleCodeEnum.MD_ITEM_CODE.getCode())); } + String key = importItem.getCode(); if (StrUtil.isBlank(importItem.getName())) { respVO.getFailureCodes().put(key, "物料名称不能为空"); return; diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdProductSipServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdProductSipServiceImpl.java index f6963e340..6cea0fb52 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdProductSipServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdProductSipServiceImpl.java @@ -59,7 +59,7 @@ public class MesMdProductSipServiceImpl implements MesMdProductSipService { validateSortUnique(reqVO.getItemId(), reqVO.getSort(), excludeId); // 校验工序存在 if (reqVO.getProcessId() != null) { - processService.validateProcessExists(reqVO.getProcessId()); + processService.validateProcessExistsAndEnable(reqVO.getProcessId()); } } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdProductSopServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdProductSopServiceImpl.java index 3bbd330b7..e957a7c47 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdProductSopServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/item/MesMdProductSopServiceImpl.java @@ -59,7 +59,7 @@ public class MesMdProductSopServiceImpl implements MesMdProductSopService { validateSortUnique(reqVO.getItemId(), reqVO.getSort(), excludeId); // 校验工序存在 if (reqVO.getProcessId() != null) { - processService.validateProcessExists(reqVO.getProcessId()); + processService.validateProcessExistsAndEnable(reqVO.getProcessId()); } } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/unitmeasure/MesMdUnitMeasureServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/unitmeasure/MesMdUnitMeasureServiceImpl.java index 1d90ae3a5..139fb121a 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/unitmeasure/MesMdUnitMeasureServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/unitmeasure/MesMdUnitMeasureServiceImpl.java @@ -6,8 +6,15 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.mes.controller.admin.md.unitmeasure.vo.MesMdUnitMeasurePageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.md.unitmeasure.vo.MesMdUnitMeasureSaveReqVO; import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO; -import cn.iocoder.yudao.module.mes.dal.mysql.md.item.MesMdItemMapper; import cn.iocoder.yudao.module.mes.dal.mysql.md.unitmeasure.MesMdUnitMeasureMapper; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.pro.task.MesProTaskIssueService; +import cn.iocoder.yudao.module.mes.service.qc.ipqc.MesQcIpqcLineService; +import cn.iocoder.yudao.module.mes.service.qc.iqc.MesQcIqcLineService; +import cn.iocoder.yudao.module.mes.service.qc.oqc.MesQcOqcLineService; +import cn.iocoder.yudao.module.mes.service.qc.rqc.MesQcRqcLineService; +import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateIndicatorService; +import org.springframework.context.annotation.Lazy; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -33,7 +40,26 @@ public class MesMdUnitMeasureServiceImpl implements MesMdUnitMeasureService { private MesMdUnitMeasureMapper unitMeasureMapper; @Resource - private MesMdItemMapper itemMapper; + @Lazy + private MesMdItemService itemService; + @Resource + @Lazy + private MesProTaskIssueService taskIssueService; + @Resource + @Lazy + private MesQcTemplateIndicatorService templateIndicatorService; + @Resource + @Lazy + private MesQcIqcLineService iqcLineService; + @Resource + @Lazy + private MesQcOqcLineService oqcLineService; + @Resource + @Lazy + private MesQcIpqcLineService ipqcLineService; + @Resource + @Lazy + private MesQcRqcLineService rqcLineService; @Override public Long createUnitMeasure(MesMdUnitMeasureSaveReqVO createReqVO) { @@ -62,10 +88,30 @@ public class MesMdUnitMeasureServiceImpl implements MesMdUnitMeasureService { public void deleteUnitMeasure(Long id) { // 校验存在 validateUnitMeasureExists(id); + // 校验是否存在以此为主单位的辅单位 + if (unitMeasureMapper.selectCountByPrimaryId(id) > 0) { + throw exception(MD_UNIT_MEASURE_HAS_SECONDARY); + } // 校验是否被物料引用 - if (itemMapper.selectCountByUnitMeasureId(id) > 0) { + if (itemService.getItemCountByUnitMeasureId(id) > 0) { throw exception(MD_UNIT_MEASURE_HAS_ITEM); } + // 校验是否被生产任务投料引用 + if (taskIssueService.getTaskIssueCountByUnitMeasureId(id) > 0) { + throw exception(MD_UNIT_MEASURE_HAS_TASK_ISSUE); + } + // 校验是否被质检方案指标项引用 + if (templateIndicatorService.getTemplateIndicatorCountByUnitMeasureId(id) > 0) { + throw exception(MD_UNIT_MEASURE_HAS_QC_TEMPLATE_INDICATOR); + } + // 校验是否被质检单据行引用(IQC/OQC/IPQC/RQC) + if (iqcLineService.getIqcLineCountByUnitMeasureId(id) > 0 + || oqcLineService.getOqcLineCountByUnitMeasureId(id) > 0 + || ipqcLineService.getIpqcLineCountByUnitMeasureId(id) > 0 + || rqcLineService.getRqcLineCountByUnitMeasureId(id) > 0) { + throw exception(MD_UNIT_MEASURE_HAS_QC_LINE); + } + // 删除 unitMeasureMapper.deleteById(id); } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/vendor/MesMdVendorService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/vendor/MesMdVendorService.java index 4e86e4b52..375635acf 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/vendor/MesMdVendorService.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/vendor/MesMdVendorService.java @@ -59,6 +59,14 @@ public interface MesMdVendorService { */ MesMdVendorDO validateVendorExists(Long id); + /** + * 校验供应商存在且启用 + * + * @param id 供应商 ID + * @return 供应商 + */ + MesMdVendorDO validateVendorExistsAndEnable(Long id); + /** * 获得供应商分页 * diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/vendor/MesMdVendorServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/vendor/MesMdVendorServiceImpl.java index d1baab9de..8efcee83a 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/vendor/MesMdVendorServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/vendor/MesMdVendorServiceImpl.java @@ -10,12 +10,17 @@ import cn.iocoder.yudao.module.mes.controller.admin.md.vendor.vo.MesMdVendorImpo import cn.iocoder.yudao.module.mes.controller.admin.md.vendor.vo.MesMdVendorImportRespVO; import cn.iocoder.yudao.module.mes.controller.admin.md.vendor.vo.MesMdVendorPageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.md.vendor.vo.MesMdVendorSaveReqVO; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO; import cn.iocoder.yudao.module.mes.dal.mysql.md.vendor.MesMdVendorMapper; import cn.iocoder.yudao.module.mes.enums.wm.BarcodeBizTypeEnum; +import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; +import cn.iocoder.yudao.module.mes.service.qc.iqc.MesQcIqcService; import cn.iocoder.yudao.module.mes.service.wm.arrivalnotice.MesWmArrivalNoticeService; import cn.iocoder.yudao.module.mes.service.wm.barcode.MesWmBarcodeService; import cn.iocoder.yudao.module.mes.service.wm.itemreceipt.MesWmItemReceiptService; +import cn.iocoder.yudao.module.mes.service.wm.outsourceissue.MesWmOutsourceIssueService; +import cn.iocoder.yudao.module.mes.service.wm.outsourcereceipt.MesWmOutsourceReceiptService; import cn.iocoder.yudao.module.mes.service.wm.returnvendor.MesWmReturnVendorService; import jakarta.annotation.Resource; import org.springframework.context.annotation.Lazy; @@ -56,6 +61,18 @@ public class MesMdVendorServiceImpl implements MesMdVendorService { @Resource @Lazy private MesWmReturnVendorService returnVendorService; + @Resource + @Lazy + private MesQcIqcService iqcService; + @Resource + @Lazy + private MesProWorkOrderService workOrderService; + @Resource + @Lazy + private MesWmOutsourceIssueService outsourceIssueService; + @Resource + @Lazy + private MesWmOutsourceReceiptService outsourceReceiptService; @Override public Long createVendor(MesMdVendorSaveReqVO createReqVO) { @@ -103,6 +120,15 @@ public class MesMdVendorServiceImpl implements MesMdVendorService { return vendor; } + @Override + public MesMdVendorDO validateVendorExistsAndEnable(Long id) { + MesMdVendorDO vendor = validateVendorExists(id); + if (ObjUtil.notEqual(CommonStatusEnum.ENABLE.getStatus(), vendor.getStatus())) { + throw exception(MD_VENDOR_IS_DISABLE); + } + return vendor; + } + private void validateVendorSaveData(MesMdVendorSaveReqVO reqVO) { // 校验编码唯一 validateVendorCodeUnique(reqVO.getId(), reqVO.getCode()); @@ -148,7 +174,11 @@ public class MesMdVendorServiceImpl implements MesMdVendorService { private void validateVendorNotReferenced(Long id) { if (itemReceiptService.getItemReceiptCountByVendorId(id) > 0 || arrivalNoticeService.getArrivalNoticeCountByVendorId(id) > 0 - || returnVendorService.getReturnVendorCountByVendorId(id) > 0) { + || returnVendorService.getReturnVendorCountByVendorId(id) > 0 + || iqcService.getIqcCountByVendorId(id) > 0 + || workOrderService.getWorkOrderCountByVendorId(id) > 0 + || outsourceIssueService.getOutsourceIssueCountByVendorId(id) > 0 + || outsourceReceiptService.getOutsourceReceiptCountByVendorId(id) > 0) { throw exception(MD_VENDOR_HAS_REFERENCE); } } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkshopServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkshopServiceImpl.java index e54f88afc..57e953875 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkshopServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkshopServiceImpl.java @@ -7,9 +7,7 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.workshop.MesMdWorkshopPageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.workshop.MesMdWorkshopSaveReqVO; import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkshopDO; -import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; import cn.iocoder.yudao.module.mes.dal.mysql.md.workstation.MesMdWorkshopMapper; -import cn.iocoder.yudao.module.mes.dal.mysql.md.workstation.MesMdWorkstationMapper; import cn.iocoder.yudao.module.mes.enums.wm.BarcodeBizTypeEnum; import cn.iocoder.yudao.module.mes.service.wm.barcode.MesWmBarcodeService; import jakarta.annotation.Resource; @@ -38,8 +36,7 @@ public class MesMdWorkshopServiceImpl implements MesMdWorkshopService { @Resource @Lazy - private MesMdWorkstationMapper workstationMapper; - + private MesMdWorkstationService workstationService; @Resource private MesWmBarcodeService barcodeService; @@ -79,7 +76,7 @@ public class MesMdWorkshopServiceImpl implements MesMdWorkshopService { // 校验存在 validateWorkshopExists(id); // 校验车间下是否存在工作站 - Long count = workstationMapper.selectCount(MesMdWorkstationDO::getWorkshopId, id); + Long count = workstationService.getWorkstationCountByWorkshopId(id); if (count > 0) { throw exception(MD_WORKSHOP_HAS_WORKSTATION); } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationMachineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationMachineServiceImpl.java index 9ac239f9c..b970352ac 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationMachineServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationMachineServiceImpl.java @@ -5,9 +5,9 @@ import cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.machine.Me import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO; import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationMachineDO; import cn.iocoder.yudao.module.mes.dal.mysql.md.workstation.MesMdWorkstationMachineMapper; -import cn.iocoder.yudao.module.mes.dal.mysql.md.workstation.MesMdWorkstationMapper; import cn.iocoder.yudao.module.mes.service.dv.machinery.MesDvMachineryService; import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -29,8 +29,8 @@ public class MesMdWorkstationMachineServiceImpl implements MesMdWorkstationMachi private MesMdWorkstationMachineMapper workstationMachineMapper; @Resource - private MesMdWorkstationMapper workstationMapper; - + @Lazy + private MesMdWorkstationService workstationService; @Resource private MesDvMachineryService machineryService; @@ -51,7 +51,7 @@ public class MesMdWorkstationMachineServiceImpl implements MesMdWorkstationMachi // 校验该设备是否已分配到其他工作站(一台设备只能分配到一个工作站) MesMdWorkstationMachineDO existing = workstationMachineMapper.selectByMachineryId(reqVO.getMachineryId()); if (existing != null) { - MesMdWorkstationDO workstation = workstationMapper.selectById(existing.getWorkstationId()); + MesMdWorkstationDO workstation = workstationService.getWorkstation(existing.getWorkstationId()); throw exception(MD_WORKSTATION_MACHINE_EXISTS, workstation != null ? workstation.getName() : String.valueOf(existing.getWorkstationId())); } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationService.java index 752796259..3a3b39504 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationService.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationService.java @@ -49,6 +49,14 @@ public interface MesMdWorkstationService { */ MesMdWorkstationDO validateWorkstationExists(Long id); + /** + * 校验工作站存在且启用 + * + * @param id 编号 + * @return 工作站 + */ + MesMdWorkstationDO validateWorkstationExistsAndEnable(Long id); + /** * 获得工作站 * @@ -97,6 +105,14 @@ public interface MesMdWorkstationService { */ Long getWorkstationCountByAreaId(Long areaId); + /** + * 获得指定车间下的工作站数量 + * + * @param workshopId 车间编号 + * @return 工作站数量 + */ + Long getWorkstationCountByWorkshopId(Long workshopId); + /** * 获得工作站列表 * diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationServiceImpl.java index 5b2dbc8f8..647177a05 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationServiceImpl.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.mes.service.md.workstation; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.MesMdWorkstationPageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.MesMdWorkstationSaveReqVO; @@ -19,6 +20,7 @@ import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationSe import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService; import cn.iocoder.yudao.module.mes.service.pro.process.MesProProcessService; import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -43,12 +45,12 @@ public class MesMdWorkstationServiceImpl implements MesMdWorkstationService { private MesMdWorkstationMapper workstationMapper; @Resource + @Lazy private MesMdWorkstationMachineService workstationMachineService; @Resource private MesMdWorkstationToolService workstationToolService; @Resource private MesMdWorkstationWorkerService workstationWorkerService; - @Resource private MesMdWorkshopService workshopService; @Resource @@ -97,7 +99,7 @@ public class MesMdWorkstationServiceImpl implements MesMdWorkstationService { // 校验车间存在 validateWorkshopExists(reqVO.getWorkshopId()); // 校验工序存在 - processService.validateProcessExists(reqVO.getProcessId()); + processService.validateProcessExistsAndEnable(reqVO.getProcessId()); // 处理仓库层级(未指定仓库时自动设置虚拟线边库) handleWarehouseHierarchy(reqVO); } @@ -125,6 +127,15 @@ public class MesMdWorkstationServiceImpl implements MesMdWorkstationService { return workstation; } + @Override + public MesMdWorkstationDO validateWorkstationExistsAndEnable(Long id) { + MesMdWorkstationDO workstation = validateWorkstationExists(id); + if (ObjUtil.notEqual(CommonStatusEnum.ENABLE.getStatus(), workstation.getStatus())) { + throw exception(MD_WORKSTATION_IS_DISABLE); + } + return workstation; + } + private void validateWorkshopExists(Long workshopId) { MesMdWorkshopDO workshop = workshopService.getWorkshop(workshopId); if (workshop == null) { @@ -232,6 +243,11 @@ public class MesMdWorkstationServiceImpl implements MesMdWorkstationService { return workstationMapper.selectListByStatus(status); } + @Override + public Long getWorkstationCountByWorkshopId(Long workshopId) { + return workstationMapper.selectCountByWorkshopId(workshopId); + } + @Override public Long getWorkstationCountByWarehouseId(Long warehouseId) { return workstationMapper.selectCountByWarehouseId(warehouseId); diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationToolService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationToolService.java index bf5160d2e..9ed871bed 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationToolService.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationToolService.java @@ -50,4 +50,12 @@ public interface MesMdWorkstationToolService { */ void deleteWorkstationToolByWorkstationId(Long workstationId); + /** + * 获得指定工具类型的工装夹具资源数量 + * + * @param toolTypeId 工具类型编号 + * @return 数量 + */ + Long getWorkstationToolCountByToolTypeId(Long toolTypeId); + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationToolServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationToolServiceImpl.java index a8f5d51eb..5b2885425 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationToolServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/md/workstation/MesMdWorkstationToolServiceImpl.java @@ -89,4 +89,9 @@ public class MesMdWorkstationToolServiceImpl implements MesMdWorkstationToolServ workstationToolMapper.deleteByWorkstationId(workstationId); } + @Override + public Long getWorkstationToolCountByToolTypeId(Long toolTypeId) { + return workstationToolMapper.selectCountByToolTypeId(toolTypeId); + } + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/andon/MesProAndonRecordServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/andon/MesProAndonRecordServiceImpl.java index db7e6add6..e49bf9c21 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/andon/MesProAndonRecordServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/andon/MesProAndonRecordServiceImpl.java @@ -34,13 +34,10 @@ public class MesProAndonRecordServiceImpl implements MesProAndonRecordService { @Resource private MesMdWorkstationService workstationService; - @Resource private MesProWorkOrderService workOrderService; - @Resource private MesProProcessService processService; - @Resource private MesProAndonConfigService andonConfigService; @@ -50,10 +47,10 @@ public class MesProAndonRecordServiceImpl implements MesProAndonRecordService { MesProAndonConfigDO config = andonConfigService.validateAndonConfigExists(createReqVO.getConfigId()); workstationService.validateWorkstationExists(createReqVO.getWorkstationId()); if (createReqVO.getWorkOrderId() != null) { - workOrderService.validateWorkOrderExists(createReqVO.getWorkOrderId()); + workOrderService.validateWorkOrderConfirmed(createReqVO.getWorkOrderId()); } if (createReqVO.getProcessId() != null) { - processService.validateProcessExists(createReqVO.getProcessId()); + processService.validateProcessExistsAndEnable(createReqVO.getProcessId()); } // 2. 插入记录 diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/card/MesProCardProcessServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/card/MesProCardProcessServiceImpl.java index 5803bfda5..de34fb211 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/card/MesProCardProcessServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/card/MesProCardProcessServiceImpl.java @@ -30,13 +30,12 @@ public class MesProCardProcessServiceImpl implements MesProCardProcessService { @Resource @Lazy private MesProCardService cardService; - @Resource private MesProProcessService processService; @Override public Long createCardProcess(MesProCardProcessSaveReqVO createReqVO) { - // 1. 校验关联数据 + // 1. 校验关联数据(含流转卡草稿状态校验) validateCardProcessSaveData(createReqVO); // 2. 插入 @@ -49,7 +48,7 @@ public class MesProCardProcessServiceImpl implements MesProCardProcessService { public void updateCardProcess(MesProCardProcessSaveReqVO updateReqVO) { // 1.1 校验存在 validateCardProcessExists(updateReqVO.getId()); - // 1.2 校验关联数据 + // 1.2 校验关联数据(含流转卡草稿状态校验) validateCardProcessSaveData(updateReqVO); // 2. 更新 @@ -60,9 +59,14 @@ public class MesProCardProcessServiceImpl implements MesProCardProcessService { @Override public void deleteCardProcess(Long id) { // 1. 校验存在 - validateCardProcessExists(id); + MesProCardProcessDO cardProcess = cardProcessMapper.selectById(id); + if (cardProcess == null) { + throw exception(PRO_CARD_PROCESS_NOT_EXISTS); + } + // 2. 校验流转卡为草稿状态 + cardService.validateCardExistsAndPrepare(cardProcess.getCardId()); - // 2. 删除 + // 3. 删除 cardProcessMapper.deleteById(id); } @@ -85,11 +89,11 @@ public class MesProCardProcessServiceImpl implements MesProCardProcessService { } private void validateCardProcessSaveData(MesProCardProcessSaveReqVO reqVO) { - // 校验流转卡存在 - cardService.validateCardExists(reqVO.getCardId()); + // 校验流转卡存在 + 草稿状态 + cardService.validateCardExistsAndPrepare(reqVO.getCardId()); // 校验工序存在 if (reqVO.getProcessId() != null) { - processService.validateProcessExists(reqVO.getProcessId()); + processService.validateProcessExistsAndEnable(reqVO.getProcessId()); } } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/card/MesProCardService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/card/MesProCardService.java index a8af47cc3..b43e7421e 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/card/MesProCardService.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/card/MesProCardService.java @@ -6,8 +6,6 @@ import cn.iocoder.yudao.module.mes.controller.admin.pro.card.vo.MesProCardSaveRe import cn.iocoder.yudao.module.mes.dal.dataobject.pro.card.MesProCardDO; import jakarta.validation.Valid; -import java.util.List; - /** * MES 生产流转卡 Service 接口 * @@ -44,6 +42,13 @@ public interface MesProCardService { */ void validateCardExists(Long id); + /** + * 校验生产流转卡存在,且为草稿状态 + * + * @param id 编号 + */ + void validateCardExistsAndPrepare(Long id); + /** * 获得生产流转卡 * @@ -60,13 +65,6 @@ public interface MesProCardService { */ PageResult getCardPage(MesProCardPageReqVO pageReqVO); - /** - * 获得生产流转卡精简列表 - * - * @return 流转卡列表 - */ - List getCardSimpleList(); - /** * 提交生产流转卡(草稿 → 已确认) * diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/card/MesProCardServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/card/MesProCardServiceImpl.java index 3be908bf7..86eb479ed 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/card/MesProCardServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/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; @@ -19,8 +20,6 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; 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.*; @@ -36,11 +35,9 @@ public class MesProCardServiceImpl implements MesProCardService { @Resource private MesProCardMapper cardMapper; - // DONE @AI:会用对应的 service @Resource @Lazy private MesProCardProcessService cardProcessService; - @Resource private MesProWorkOrderService workOrderService; @Resource @@ -66,8 +63,8 @@ public class MesProCardServiceImpl implements MesProCardService { @Override public void updateCard(MesProCardSaveReqVO updateReqVO) { - // 1.1 校验存在 - validateCardExists(updateReqVO.getId()); + // 1.1 校验存在 + 草稿状态 + validateCardExistsAndPrepare(updateReqVO.getId()); // 1.2 校验关联数据 validateCardSaveData(updateReqVO); @@ -79,8 +76,8 @@ public class MesProCardServiceImpl implements MesProCardService { @Override @Transactional(rollbackFor = Exception.class) public void deleteCard(Long id) { - // 1. 校验存在 - validateCardExists(id); + // 1. 校验存在 + 草稿状态 + validateCardExistsAndPrepare(id); // 2. 删除流转卡 + 级联删除工序记录 cardMapper.deleteById(id); @@ -97,11 +94,6 @@ public class MesProCardServiceImpl implements MesProCardService { return cardMapper.selectPage(pageReqVO); } - @Override - public List getCardSimpleList() { - return cardMapper.selectList(); - } - @Override public void submitCard(Long id) { // 1. 校验存在 + 草稿状态 @@ -145,6 +137,14 @@ public class MesProCardServiceImpl implements MesProCardService { validateCardExistsInternal(id); } + @Override + public void validateCardExistsAndPrepare(Long id) { + MesProCardDO card = validateCardExistsInternal(id); + if (ObjUtil.notEqual(MesProWorkOrderStatusEnum.PREPARE.getStatus(), card.getStatus())) { + throw exception(PRO_CARD_NOT_PREPARE); + } + } + private MesProCardDO validateCardExistsInternal(Long id) { MesProCardDO card = cardMapper.selectById(id); if (card == null) { @@ -178,9 +178,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/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackService.java index 2729b1059..b528c35e6 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackService.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackService.java @@ -45,6 +45,14 @@ public interface MesProFeedbackService { */ MesProFeedbackDO getFeedback(Long id); + /** + * 校验生产报工存在 + * + * @param id 编号 + * @return 生产报工 + */ + MesProFeedbackDO validateFeedbackExists(Long id); + /** * 获得生产报工分页 * @@ -83,11 +91,10 @@ public interface MesProFeedbackService { * * * - * @param id 报工单编号 - * @param userId 当前操作用户编号(审核人) + * @param id 报工单编号 * @return true=已完成, false=待检验(需等质检回调) */ - boolean approveFeedback(Long id, Long userId); + boolean approveFeedback(Long id); /** * IPQC 完成后回调:完成报工单并更新任务/工单进度 @@ -96,13 +103,15 @@ public interface MesProFeedbackService { * 并根据检验结果回写合格/不合格/废品数量,同时更新任务/工单的已生产数量。 * * @param feedbackId 报工记录 ID + * @param sourceLineId 来源产出行 ID(用于直接定位待检行) * @param qualifiedQty 合格品数量 * @param unqualifiedQty 不合格品数量 * @param laborScrapQty 工废数量 * @param materialScrapQty 料废数量 * @param otherScrapQty 其他废品数量 */ - void updateProFeedbackWhenIpqcFinish(Long feedbackId, BigDecimal qualifiedQty, BigDecimal unqualifiedQty, + void updateProFeedbackWhenIpqcFinish(Long feedbackId, Long sourceLineId, + BigDecimal qualifiedQty, BigDecimal unqualifiedQty, BigDecimal laborScrapQty, BigDecimal materialScrapQty, BigDecimal otherScrapQty); } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImpl.java index b631427d8..e7148ee97 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/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; @@ -29,11 +31,9 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import java.math.BigDecimal; -import java.time.LocalDateTime; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; /** @@ -114,11 +114,9 @@ public class MesProFeedbackServiceImpl implements MesProFeedbackService { // 1. 校验存在 + 草稿状态 validateFeedbackStatusPrepare(id); - // 2. 更新状态为审批中,记录报工人和报工时间 + // 2. 更新状态为审批中(报工人和报工时间由表单保存时确定,提交不覆盖) feedbackMapper.updateById(new MesProFeedbackDO().setId(id) - .setStatus(MesProFeedbackStatusEnum.APPROVING.getStatus()) - .setFeedbackUserId(getLoginUserId()) - .setFeedbackTime(LocalDateTime.now())); + .setStatus(MesProFeedbackStatusEnum.APPROVING.getStatus())); } @Override @@ -133,33 +131,34 @@ public class MesProFeedbackServiceImpl implements MesProFeedbackService { @Override @Transactional(rollbackFor = Exception.class) - public boolean approveFeedback(Long id, Long userId) { - // 1.1.a 校验存在 + 审批中状态 + public boolean approveFeedback(Long id) { + // 1.1 校验存在 + 审批中状态 MesProFeedbackDO feedback = validateFeedbackStatusApproving(id); - // 1.1.b 校验报工数量 > 0 + // 1.2 校验报工数量 > 0 if (feedback.getFeedbackQuantity() == null || feedback.getFeedbackQuantity().compareTo(BigDecimal.ZERO) <= 0) { throw exception(PRO_FEEDBACK_QUANTITY_MUST_POSITIVE); } - // 1.2.a 校验任务未完成 + // 1.3 校验任务未完成 taskService.validateTaskNotFinished(feedback.getTaskId()); - // 1.2.b 仍有待检数量时不能执行 - if (feedback.getUncheckQuantity() != null - && feedback.getUncheckQuantity().compareTo(BigDecimal.ZERO) > 0) { - throw exception(PRO_FEEDBACK_UNCHECK_QUANTITY_EXISTS, feedback.getUncheckQuantity()); - } - // 2. 物料消耗:根据工序 BOM 生成消耗记录并执行扣减 - MesWmItemConsumeDO itemConsume = itemConsumeService.generateItemConsume(feedback); - if (itemConsume != null) { - itemConsumeService.finishItemConsume(itemConsume.getId()); - } - - // 3. 查询工序的关键工序标识 + 检验标识 + // 2.1 查询工序的关键工序标识 + 检验标识(需在 uncheckQuantity 校验之前,因为质检工序允许 uncheckQuantity > 0) MesProRouteProcessDO routeProcess = routeProcessService.getRouteProcessByRouteIdAndProcessId( feedback.getRouteId(), feedback.getProcessId()); boolean keyFlag = routeProcess != null && Boolean.TRUE.equals(routeProcess.getKeyFlag()); boolean checkFlag = routeProcess != null && Boolean.TRUE.equals(routeProcess.getCheckFlag()); + // 2.2 非质检工序:仍有待检数量时不能审批(质检工序的 uncheckQuantity > 0 是正常状态,不做拦截) + if (!checkFlag + && feedback.getUncheckQuantity() != null + && feedback.getUncheckQuantity().compareTo(BigDecimal.ZERO) > 0) { + throw exception(PRO_FEEDBACK_UNCHECK_QUANTITY_EXISTS, feedback.getUncheckQuantity()); + } + + // 3. 物料消耗:根据工序 BOM 生成消耗记录并执行扣减 + MesWmItemConsumeDO itemConsume = itemConsumeService.generateItemConsume(feedback); + if (itemConsume != null) { + itemConsumeService.finishItemConsume(itemConsume.getId()); + } // 4. 关键工序:生成产出单,并根据是否需要检验决定入库方式 if (keyFlag) { @@ -177,10 +176,10 @@ public class MesProFeedbackServiceImpl implements MesProFeedbackService { updateTaskAndWorkOrderByFeedback(feedback); } - // 5. 非关键工序:不生成产出单,不更新任务/工单数量,直接完成 + // 5. 非关键工序 / 关键非质检工序:直接完成(清零 uncheckQuantity 防止 !key+check 留脏数据) feedbackMapper.updateById(new MesProFeedbackDO().setId(id) .setStatus(MesProFeedbackStatusEnum.FINISHED.getStatus()) - .setApproveUserId(userId)); + .setUncheckQuantity(BigDecimal.ZERO)); return true; // 已完成 } @@ -219,7 +218,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 +251,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,15 +280,38 @@ 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 @Transactional(rollbackFor = Exception.class) - public void updateProFeedbackWhenIpqcFinish(Long feedbackId, BigDecimal qualifiedQty, BigDecimal unqualifiedQty, + public void updateProFeedbackWhenIpqcFinish(Long feedbackId, Long sourceLineId, + BigDecimal qualifiedQty, BigDecimal unqualifiedQty, BigDecimal laborScrapQty, BigDecimal materialScrapQty, BigDecimal otherScrapQty) { // 1. 校验报工单存在且为待检验状态 MesProFeedbackDO feedback = validateFeedbackExists(feedbackId); @@ -294,7 +320,7 @@ public class MesProFeedbackServiceImpl implements MesProFeedbackService { } // 2. 拆分待检产出行(合格/不合格),生成明细,完成产出入库 - productProduceService.splitPendingAndFinishProduce(feedbackId, qualifiedQty, unqualifiedQty); + productProduceService.splitPendingAndFinishProduce(feedbackId, sourceLineId, qualifiedQty, unqualifiedQty); // 3. 回写合格/不合格/废品数量,更新状态为已完成 feedbackMapper.updateById(new MesProFeedbackDO().setId(feedbackId) diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/process/MesProProcessService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/process/MesProProcessService.java index 7d7c9b392..74a9353b1 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/process/MesProProcessService.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/process/MesProProcessService.java @@ -81,6 +81,13 @@ public interface MesProProcessService { */ void validateProcessExists(Long id); + /** + * 校验工序存在且启用 + * + * @param id 编号 + */ + void validateProcessExistsAndEnable(Long id); + /** * 获得工序 Map * diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/process/MesProProcessServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/process/MesProProcessServiceImpl.java index 838d4b4eb..27023cb82 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/process/MesProProcessServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/process/MesProProcessServiceImpl.java @@ -1,6 +1,8 @@ package cn.iocoder.yudao.module.mes.service.pro.process; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.mes.controller.admin.pro.process.vo.MesProProcessPageReqVO; @@ -35,7 +37,6 @@ public class MesProProcessServiceImpl implements MesProProcessService { @Resource private MesProProcessContentService processContentService; - @Resource @Lazy private MesProRouteProcessService routeProcessService; @@ -86,6 +87,17 @@ public class MesProProcessServiceImpl implements MesProProcessService { } } + @Override + public void validateProcessExistsAndEnable(Long id) { + MesProProcessDO process = processMapper.selectById(id); + if (process == null) { + throw exception(PRO_PROCESS_NOT_EXISTS); + } + if (ObjUtil.notEqual(CommonStatusEnum.ENABLE.getStatus(), process.getStatus())) { + throw exception(PRO_PROCESS_IS_DISABLE); + } + } + private void validateProcessCodeUnique(Long id, String code) { MesProProcessDO process = processMapper.selectByCode(code); if (process == null) { diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteProcessServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteProcessServiceImpl.java index 20fca3e98..ec5aae1a7 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteProcessServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteProcessServiceImpl.java @@ -191,8 +191,6 @@ public class MesProRouteProcessServiceImpl implements MesProRouteProcessService // 1. 根据产品查找关联的工艺路线产品记录 MesProRouteProductDO routeProduct = routeProductService.getRouteProductByItemId(productId); if (routeProduct == null) { - // TODO @芋艿:会不会存在配置了多个的情况??? - // TODO @AI:会有这个情况么? return Collections.emptyList(); } // 2. 返回该工艺路线的工序列表 diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteProductBomServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteProductBomServiceImpl.java index 24aca4b52..7b3ec2aa9 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/route/MesProRouteProductBomServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/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/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskIssueService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskIssueService.java index 68835683b..2c52261a3 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskIssueService.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskIssueService.java @@ -61,4 +61,12 @@ public interface MesProTaskIssueService { */ List getTaskIssueListByTaskId(Long taskId); + /** + * 获取指定计量单位的投料记录数量 + * + * @param unitMeasureId 计量单位编号 + * @return 投料记录数量 + */ + Long getTaskIssueCountByUnitMeasureId(Long unitMeasureId); + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskIssueServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskIssueServiceImpl.java index 713ca6583..5104a79c4 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskIssueServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskIssueServiceImpl.java @@ -30,7 +30,6 @@ public class MesProTaskIssueServiceImpl implements MesProTaskIssueService { @Resource private MesProTaskService taskService; - @Resource private MesMdItemService itemService; @@ -84,6 +83,11 @@ public class MesProTaskIssueServiceImpl implements MesProTaskIssueService { return taskIssueMapper.selectListByTaskId(taskId); } + @Override + public Long getTaskIssueCountByUnitMeasureId(Long unitMeasureId) { + return taskIssueMapper.selectCountByUnitMeasureId(unitMeasureId); + } + private void validateTaskIssueExists(Long id) { if (taskIssueMapper.selectById(id) == null) { throw exception(PRO_TASK_ISSUE_NOT_EXISTS); diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskService.java index a65fa82e1..058ec8360 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskService.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskService.java @@ -58,14 +58,6 @@ public interface MesProTaskService { */ PageResult getTaskPage(MesProTaskPageReqVO pageReqVO); - /** - * 获得生产任务精简列表 - * - * @param workOrderId 工单编号(可选) - * @return 生产任务列表 - */ - List getTaskListByWorkOrderId(Long workOrderId); - /** * 根据工单编号列表,批量获得生产任务列表 * diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskServiceImpl.java index a976aa49e..4052b07af 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskServiceImpl.java @@ -69,7 +69,7 @@ public class MesProTaskServiceImpl implements MesProTaskService { MesProWorkOrderDO workOrder = workOrderService.validateWorkOrderExists(createReqVO.getWorkOrderId()); workstationService.validateWorkstationExists(createReqVO.getWorkstationId()); routeService.validateRouteExists(createReqVO.getRouteId()); - processService.validateProcessExists(createReqVO.getProcessId()); + processService.validateProcessExistsAndEnable(createReqVO.getProcessId()); MesMdItemDO item = itemService.validateItemExists(createReqVO.getItemId()); // 2.1 构建任务 DO:自动填充客户信息 @@ -100,7 +100,7 @@ public class MesProTaskServiceImpl implements MesProTaskService { routeService.validateRouteExists(updateReqVO.getRouteId()); } if (updateReqVO.getProcessId() != null) { - processService.validateProcessExists(updateReqVO.getProcessId()); + processService.validateProcessExistsAndEnable(updateReqVO.getProcessId()); } MesMdItemDO item; if (updateReqVO.getItemId() != null) { @@ -149,11 +149,6 @@ public class MesProTaskServiceImpl implements MesProTaskService { return taskMapper.selectPage(pageReqVO); } - @Override - public List getTaskListByWorkOrderId(Long workOrderId) { - return taskMapper.selectListByWorkOrderId(workOrderId); - } - @Override public List getTaskListByWorkOrderIds(Collection workOrderIds) { if (CollUtil.isEmpty(workOrderIds)) { diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderBomServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderBomServiceImpl.java index f995cd0e4..40d0777f9 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderBomServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/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/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderService.java index 9aa713e45..31d2581bb 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderService.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderService.java @@ -129,4 +129,12 @@ public interface MesProWorkOrderService { */ void updateProducedQuantity(Long id, BigDecimal incrQuantityProduced); + /** + * 根据供应商 ID 统计工单数量 + * + * @param vendorId 供应商 ID + * @return 数量 + */ + Long getWorkOrderCountByVendorId(Long vendorId); + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderServiceImpl.java index 431b08493..99332dd2a 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkOrderServiceImpl.java @@ -245,4 +245,9 @@ public class MesProWorkOrderServiceImpl implements MesProWorkOrderService { workOrderMapper.updateProducedQuantity(id, incrQuantityProduced); } + @Override + public Long getWorkOrderCountByVendorId(Long vendorId) { + return workOrderMapper.selectCountByVendorId(vendorId); + } + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workrecord/MesProWorkRecordServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workrecord/MesProWorkRecordServiceImpl.java index cc02b9144..1669d922f 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workrecord/MesProWorkRecordServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workrecord/MesProWorkRecordServiceImpl.java @@ -33,6 +33,7 @@ public class MesProWorkRecordServiceImpl implements MesProWorkRecordService { private MesProWorkRecordLogMapper workRecordLogMapper; @Resource private MesProWorkRecordMapper workRecordMapper; + @Resource private MesMdWorkstationService workstationService; @@ -70,7 +71,7 @@ public class MesProWorkRecordServiceImpl implements MesProWorkRecordService { } else { workRecordMapper.updateById(new MesProWorkRecordDO().setId(record.getId()) .setWorkstationId(workstationId).setType(MesProWorkRecordTypeEnum.CLOCK_IN.getType()) - .setClockInTime(LocalDateTime.now()).setClockOutTime(null)); + .setClockInTime(LocalDateTime.now())); } return log.getId(); } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicator/MesQcIndicatorService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicator/MesQcIndicatorService.java index 8a9f5cba1..7d6078e43 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicator/MesQcIndicatorService.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicator/MesQcIndicatorService.java @@ -82,4 +82,12 @@ public interface MesQcIndicatorService { return convertMap(getIndicatorList(ids), MesQcIndicatorDO::getId); } + /** + * 批量校验质检指标是否都存在 + * + * @param ids 编号数组 + * @return 质检指标 Map + */ + Map validateIndicatorListExists(Collection ids); + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicator/MesQcIndicatorServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicator/MesQcIndicatorServiceImpl.java index b72cdc143..c3c6819a6 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicator/MesQcIndicatorServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicator/MesQcIndicatorServiceImpl.java @@ -18,8 +18,10 @@ import org.springframework.validation.annotation.Validated; import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Map; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; /** @@ -132,4 +134,13 @@ public class MesQcIndicatorServiceImpl implements MesQcIndicatorService { return indicatorMapper.selectByIds(ids); } + @Override + public Map validateIndicatorListExists(Collection ids) { + List indicators = getIndicatorList(ids); + if (indicators.size() != ids.size()) { + throw exception(QC_INDICATOR_NOT_EXISTS); + } + return convertMap(indicators, MesQcIndicatorDO::getId); + } + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcIndicatorResultService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcIndicatorResultService.java index ea4f2c7ba..e4a8c71cc 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcIndicatorResultService.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcIndicatorResultService.java @@ -62,4 +62,21 @@ public interface MesQcIndicatorResultService { */ List getIndicatorResultDetailListByResultId(Long resultId); + /** + * 获取指定质检单下的检验结果数量 + * + * @param qcId 质检单 ID + * @param qcType 质检类型 + * @return 结果数量 + */ + Long getIndicatorResultCountByQcIdAndType(Long qcId, Integer qcType); + + /** + * 校验指定质检单下至少存在一条检验结果 + * + * @param qcId 质检单 ID + * @param qcType 质检类型 + */ + void validateIndicatorResultExistsByQcIdAndType(Long qcId, Integer qcType); + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcIndicatorResultServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcIndicatorResultServiceImpl.java index 3791a980f..c6b162f44 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcIndicatorResultServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcIndicatorResultServiceImpl.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.mes.service.qc.indicatorresult; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult.vo.MesQcIndicatorResultPageReqVO; @@ -8,23 +9,27 @@ import cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult.vo.MesQcI import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO; import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicatorresult.MesQcIndicatorResultDO; import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicatorresult.MesQcIndicatorResultDetailDO; -import cn.iocoder.yudao.module.mes.dal.dataobject.qc.iqc.MesQcIqcDO; import cn.iocoder.yudao.module.mes.dal.dataobject.qc.ipqc.MesQcIpqcDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.iqc.MesQcIqcDO; import cn.iocoder.yudao.module.mes.dal.dataobject.qc.oqc.MesQcOqcDO; import cn.iocoder.yudao.module.mes.dal.dataobject.qc.rqc.MesQcRqcDO; import cn.iocoder.yudao.module.mes.dal.mysql.qc.indicatorresult.MesQcIndicatorResultMapper; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcResultValueTypeEnum; import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum; import cn.iocoder.yudao.module.mes.service.qc.indicator.MesQcIndicatorService; import cn.iocoder.yudao.module.mes.service.qc.ipqc.MesQcIpqcService; import cn.iocoder.yudao.module.mes.service.qc.iqc.MesQcIqcService; import cn.iocoder.yudao.module.mes.service.qc.oqc.MesQcOqcService; import cn.iocoder.yudao.module.mes.service.qc.rqc.MesQcRqcService; +import cn.iocoder.yudao.module.system.api.dict.DictDataApi; import jakarta.annotation.Resource; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; +import java.math.BigDecimal; +import java.net.URI; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; @@ -42,9 +47,9 @@ public class MesQcIndicatorResultServiceImpl implements MesQcIndicatorResultServ @Resource private MesQcIndicatorResultMapper resultMapper; + @Resource private MesQcIndicatorResultDetailService resultDetailService; - @Resource private MesQcIndicatorService indicatorService; @Resource @@ -59,13 +64,16 @@ public class MesQcIndicatorResultServiceImpl implements MesQcIndicatorResultServ @Lazy private MesQcRqcService rqcService; + @Resource + private DictDataApi dictDataApi; + @Override @Transactional(rollbackFor = Exception.class) public Long createIndicatorResult(MesQcIndicatorResultSaveReqVO createReqVO) { // 1.1 根据 qcType 查询源质检单,获取 itemId Long itemId = getItemIdFromQcDoc(createReqVO.getQcId(), createReqVO.getQcType()); - // 1.2 校验所有明细的 indicatorId 是否存在 - validateIndicatorIds(createReqVO.getItems()); + // 1.2 校验明细数据(indicatorId 存在性 + 值格式) + validateItemsSaveData(createReqVO.getItems()); // 2.1 插入主表 MesQcIndicatorResultDO result = BeanUtils.toBean(createReqVO, MesQcIndicatorResultDO.class); @@ -82,11 +90,14 @@ public class MesQcIndicatorResultServiceImpl implements MesQcIndicatorResultServ @Override @Transactional(rollbackFor = Exception.class) public void updateIndicatorResult(MesQcIndicatorResultSaveReqVO updateReqVO) { - // 1. 校验存在 + // 1.1 校验存在 validateIndicatorResultExists(updateReqVO.getId()); + // 1.2 校验明细数据(indicatorId 存在性 + 值格式) + validateItemsSaveData(updateReqVO.getItems()); - // 2.1 更新主表 + // 2.1 更新主表(锁定 qcId/qcType/itemId,不允许改挂到其他质检单) MesQcIndicatorResultDO updateObj = BeanUtils.toBean(updateReqVO, MesQcIndicatorResultDO.class); + updateObj.setQcId(null).setQcType(null).setItemId(null); resultMapper.updateById(updateObj); // 2.2 批量更新明细 List details = BeanUtils.toBean(updateReqVO.getItems(), @@ -121,6 +132,19 @@ public class MesQcIndicatorResultServiceImpl implements MesQcIndicatorResultServ return resultDetailService.getDetailListByResultId(resultId); } + @Override + public Long getIndicatorResultCountByQcIdAndType(Long qcId, Integer qcType) { + return resultMapper.selectCountByQcIdAndType(qcId, qcType); + } + + @Override + public void validateIndicatorResultExistsByQcIdAndType(Long qcId, Integer qcType) { + Long resultCount = getIndicatorResultCountByQcIdAndType(qcId, qcType); + if (resultCount == 0) { + throw exception(QC_FINISH_INDICATOR_RESULT_REQUIRED); + } + } + // ==================== 私有方法 ==================== private MesQcIndicatorResultDO validateIndicatorResultExists(Long id) { @@ -132,18 +156,87 @@ public class MesQcIndicatorResultServiceImpl implements MesQcIndicatorResultServ } /** - * 校验所有明细的 indicatorId 是否存在 + * 校验明细保存数据(indicatorId 存在性 + 值格式) */ - private void validateIndicatorIds(List items) { + private void validateItemsSaveData(List items) { + // 校验所有明细的 indicatorId 是否存在 + Map indicatorMap = validateIndicatorIds(items); + // 校验明细值格式是否符合指标的 resultType + validateDetailValues(items, indicatorMap); + } + + /** + * 校验所有明细的 indicatorId 是否存在 + * + * @return indicatorId -> MesQcIndicatorDO 映射,供后续值格式校验使用 + */ + private Map validateIndicatorIds(List items) { + if (CollUtil.isEmpty(items)) { + return Collections.emptyMap(); + } + Set indicatorIds = convertSet(items, MesQcIndicatorResultSaveReqVO.Item::getIndicatorId); + return indicatorService.validateIndicatorListExists(indicatorIds); + } + + /** + * 按检测项的 resultType 校验明细值格式 + * + *

FLOAT → 必须可解析为 BigDecimal;INTEGER → 必须可解析为整数; + * DICT → 必须属于字典值域;FILE → 必须为 http/https URL;TEXT → 放行 + */ + private void validateDetailValues(List items, + Map indicatorMap) { if (CollUtil.isEmpty(items)) { return; } - Set indicatorIds = convertSet(items, MesQcIndicatorResultSaveReqVO.Item::getIndicatorId); - List indicators = indicatorService.getIndicatorList(indicatorIds); - if (indicators.size() != indicatorIds.size()) { - Set existIds = convertSet(indicators, MesQcIndicatorDO::getId); - indicatorIds.removeAll(existIds); - throw exception(QC_INDICATOR_NOT_EXISTS); + for (MesQcIndicatorResultSaveReqVO.Item item : items) { + if (item.getIndicatorId() == null || StrUtil.isBlank(item.getValue())) { + continue; + } + MesQcIndicatorDO indicator = indicatorMap.get(item.getIndicatorId()); + if (indicator == null || indicator.getResultType() == null) { + continue; + } + Integer resultType = indicator.getResultType(); + if (Objects.equals(resultType, MesQcResultValueTypeEnum.FLOAT.getType())) { + try { + new BigDecimal(item.getValue()); + } catch (NumberFormatException e) { + throw exception(QC_RESULT_VALUE_FORMAT_INVALID, + "检测项[" + indicator.getName() + "]要求浮点数,实际值=" + item.getValue()); + } + } else if (Objects.equals(resultType, MesQcResultValueTypeEnum.INTEGER.getType())) { + try { + Long.parseLong(item.getValue()); + } catch (NumberFormatException e) { + throw exception(QC_RESULT_VALUE_FORMAT_INVALID, + "检测项[" + indicator.getName() + "]要求整数,实际值=" + item.getValue()); + } + } + // DICT:校验值属于对应字典类型 + if (Objects.equals(resultType, MesQcResultValueTypeEnum.DICT.getType())) { + String dictType = indicator.getResultSpecification(); + if (StrUtil.isNotBlank(dictType)) { + dictDataApi.validateDictDataList(dictType, Collections.singleton(item.getValue())); + } + } + if (Objects.equals(resultType, MesQcResultValueTypeEnum.FILE.getType()) + && !isHttpUrl(item.getValue())) { + throw exception(QC_RESULT_VALUE_FORMAT_INVALID, + "检测项[" + indicator.getName() + "]要求文件 URL,实际值=" + item.getValue()); + } + // TEXT 不做格式校验 + } + } + + private boolean isHttpUrl(String value) { + try { + URI uri = URI.create(value); + String scheme = uri.getScheme(); + return StrUtil.isNotBlank(uri.getHost()) + && ("http".equalsIgnoreCase(scheme) || "https".equalsIgnoreCase(scheme)); + } catch (IllegalArgumentException e) { + return false; } } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcLineService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcLineService.java index df2d09e49..677c098b4 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcLineService.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcLineService.java @@ -69,4 +69,12 @@ public interface MesQcIpqcLineService { */ void deleteListByIpqcId(Long ipqcId); + /** + * 统计使用指定计量单位的过程检验行数量 + * + * @param unitMeasureId 计量单位编号 + * @return 引用数量 + */ + Long getIpqcLineCountByUnitMeasureId(Long unitMeasureId); + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcLineServiceImpl.java index f3cff4ef1..03bd3ebc5 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcLineServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcLineServiceImpl.java @@ -9,9 +9,9 @@ import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO; import cn.iocoder.yudao.module.mes.dal.dataobject.qc.ipqc.MesQcIpqcLineDO; import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateIndicatorDO; import cn.iocoder.yudao.module.mes.dal.mysql.qc.ipqc.MesQcIpqcLineMapper; -import cn.iocoder.yudao.module.mes.dal.mysql.qc.template.MesQcTemplateIndicatorMapper; import cn.iocoder.yudao.module.mes.enums.qc.MesQcDefectLevelEnum; import cn.iocoder.yudao.module.mes.service.qc.indicator.MesQcIndicatorService; +import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateIndicatorService; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -37,11 +37,11 @@ public class MesQcIpqcLineServiceImpl implements MesQcIpqcLineService { @Resource private MesQcIpqcLineMapper ipqcLineMapper; - @Resource - private MesQcTemplateIndicatorMapper templateIndicatorMapper; @Resource private MesQcIndicatorService indicatorService; + @Resource + private MesQcTemplateIndicatorService templateIndicatorService; @Override public MesQcIpqcLineDO validateIpqcLineExists(Long id) { @@ -64,7 +64,7 @@ public class MesQcIpqcLineServiceImpl implements MesQcIpqcLineService { @Override public void createLinesFromTemplate(Long ipqcId, Long templateId) { - List templateIndicators = templateIndicatorMapper.selectListByTemplateId(templateId); + List templateIndicators = templateIndicatorService.getTemplateIndicatorListByTemplateId(templateId); if (CollUtil.isEmpty(templateIndicators)) { return; } @@ -127,4 +127,9 @@ public class MesQcIpqcLineServiceImpl implements MesQcIpqcLineService { ipqcLineMapper.deleteByIpqcId(ipqcId); } + @Override + public Long getIpqcLineCountByUnitMeasureId(Long unitMeasureId) { + return ipqcLineMapper.selectCountByUnitMeasureId(unitMeasureId); + } + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImpl.java index 98cc65586..543ef0efa 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImpl.java @@ -3,11 +3,14 @@ package cn.iocoder.yudao.module.mes.service.qc.ipqc; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceLineDO; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.MesQcIpqcPageReqVO; 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,9 +26,12 @@ 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.indicatorresult.MesQcIndicatorResultService; import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateItemService; +import cn.iocoder.yudao.module.mes.service.wm.productproduce.MesWmProductProduceLineService; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import jakarta.annotation.Resource; import org.springframework.context.annotation.Lazy; @@ -76,12 +82,21 @@ public class MesQcIpqcServiceImpl implements MesQcIpqcService { @Resource @Lazy private MesProRouteProcessService routeProcessService; - @Resource - private AdminUserApi adminUserApi; + @Lazy + private MesProTaskService taskService; @Resource @Lazy private MesProFeedbackService feedbackService; + @Resource + @Lazy + private MesQcIndicatorResultService indicatorResultService; + @Resource + @Lazy + private MesWmProductProduceLineService productProduceLineService; + + @Resource + private AdminUserApi adminUserApi; @Override @Transactional(rollbackFor = Exception.class) @@ -96,7 +111,7 @@ public class MesQcIpqcServiceImpl implements MesQcIpqcService { Long templateId = templateItem.getTemplateId(); // 1.4 获取来源单据编号 String sourceDocCode = validateAndGetSourceDocCode( - createReqVO.getSourceDocType(), createReqVO.getSourceDocId()); + createReqVO.getSourceDocType(), createReqVO.getSourceDocId(), createReqVO.getSourceLineId()); // 2. 插入主表 MesQcIpqcDO ipqc = BeanUtils.toBean(createReqVO, MesQcIpqcDO.class) @@ -136,9 +151,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) { @@ -148,6 +193,8 @@ public class MesQcIpqcServiceImpl implements MesQcIpqcService { if (ipqc.getCheckResult() == null) { throw exception(QC_IPQC_CHECK_RESULT_EMPTY); } + // 1.3 校验至少存在一条检测结果 + indicatorResultService.validateIndicatorResultExistsByQcIdAndType(id, MesQcTypeEnum.IPQC.getType()); // 2. 更新状态为已完成 ipqcMapper.updateById(new MesQcIpqcDO() @@ -174,7 +221,7 @@ public class MesQcIpqcServiceImpl implements MesQcIpqcService { } if (Objects.equals(ipqc.getSourceDocType(), MesBizTypeConstants.PRO_FEEDBACK)) { - feedbackService.updateProFeedbackWhenIpqcFinish(ipqc.getSourceDocId(), + feedbackService.updateProFeedbackWhenIpqcFinish(ipqc.getSourceDocId(), ipqc.getSourceLineId(), ObjectUtil.defaultIfNull(ipqc.getQualifiedQuantity(), BigDecimal.ZERO), ObjectUtil.defaultIfNull(ipqc.getUnqualifiedQuantity(), BigDecimal.ZERO), ObjectUtil.defaultIfNull(ipqc.getLaborScrapQuantity(), BigDecimal.ZERO), @@ -233,15 +280,30 @@ public class MesQcIpqcServiceImpl implements MesQcIpqcService { } } - private String validateAndGetSourceDocCode(Integer sourceDocType, Long sourceDocId) { + private String validateAndGetSourceDocCode(Integer sourceDocType, Long sourceDocId, Long sourceLineId) { if (sourceDocType == null || sourceDocId == null) { 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); + // 校验 sourceLineId 必填 + if (sourceLineId == null) { + throw exception(QC_IPQC_SOURCE_LINE_REQUIRED); + } + // 校验 sourceLineId 存在,且属于该报工的产出行 + MesWmProductProduceLineDO targetLine = productProduceLineService + .validateProductProduceLineExists(sourceLineId); + if (ObjUtil.notEqual(targetLine.getFeedbackId(), sourceDocId)) { + throw exception(QC_IPQC_SOURCE_LINE_NOT_BELONG); + } + // 校验该产出行为待检验状态 + if (ObjUtil.notEqual(targetLine.getQualityStatus(), MesWmQualityStatusEnum.PENDING.getStatus())) { + throw exception(QC_IPQC_SOURCE_LINE_NOT_PENDING); + } + return feedback.getCode(); } - return null; + // 未知来源类型应报错,而不是静默忽略 + throw exception(QC_IPQC_SOURCE_DOC_TYPE_UNKNOWN); } /** diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcLineService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcLineService.java index 544d46bcc..023ad80e9 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcLineService.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcLineService.java @@ -70,4 +70,12 @@ public interface MesQcIqcLineService { */ void deleteListByIqcId(Long iqcId); + /** + * 统计使用指定计量单位的来料检验行数量 + * + * @param unitMeasureId 计量单位编号 + * @return 引用数量 + */ + Long getIqcLineCountByUnitMeasureId(Long unitMeasureId); + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcLineServiceImpl.java index 268f9b103..f5420e19d 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcLineServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcLineServiceImpl.java @@ -9,9 +9,9 @@ import cn.iocoder.yudao.module.mes.dal.dataobject.qc.iqc.MesQcIqcLineDO; import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO; import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateIndicatorDO; import cn.iocoder.yudao.module.mes.dal.mysql.qc.iqc.MesQcIqcLineMapper; -import cn.iocoder.yudao.module.mes.dal.mysql.qc.template.MesQcTemplateIndicatorMapper; import cn.iocoder.yudao.module.mes.enums.qc.MesQcDefectLevelEnum; import cn.iocoder.yudao.module.mes.service.qc.indicator.MesQcIndicatorService; +import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateIndicatorService; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -37,11 +37,11 @@ public class MesQcIqcLineServiceImpl implements MesQcIqcLineService { @Resource private MesQcIqcLineMapper iqcLineMapper; - @Resource - private MesQcTemplateIndicatorMapper templateIndicatorMapper; @Resource private MesQcIndicatorService indicatorService; + @Resource + private MesQcTemplateIndicatorService templateIndicatorService; @Override public MesQcIqcLineDO validateIqcLineExists(Long id) { @@ -64,7 +64,7 @@ public class MesQcIqcLineServiceImpl implements MesQcIqcLineService { @Override public void createLinesFromTemplate(Long iqcId, Long templateId) { - List templateIndicators = templateIndicatorMapper.selectListByTemplateId(templateId); + List templateIndicators = templateIndicatorService.getTemplateIndicatorListByTemplateId(templateId); if (CollUtil.isEmpty(templateIndicators)) { return; } @@ -127,4 +127,9 @@ public class MesQcIqcLineServiceImpl implements MesQcIqcLineService { iqcLineMapper.deleteByIqcId(iqcId); } + @Override + public Long getIqcLineCountByUnitMeasureId(Long unitMeasureId) { + return iqcLineMapper.selectCountByUnitMeasureId(unitMeasureId); + } + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcService.java index 49de3f234..e9c80dbd6 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcService.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcService.java @@ -87,4 +87,12 @@ public interface MesQcIqcService { */ Map getIqcMap(Collection ids); + /** + * 根据供应商 ID 统计来料检验单数量 + * + * @param vendorId 供应商 ID + * @return 数量 + */ + Long getIqcCountByVendorId(Long vendorId); + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcServiceImpl.java index 3efd44b8c..b6715ff50 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcServiceImpl.java @@ -18,11 +18,13 @@ import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum; import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; import cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService; import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService; +import cn.iocoder.yudao.module.mes.service.qc.indicatorresult.MesQcIndicatorResultService; import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateItemService; import cn.iocoder.yudao.module.mes.service.wm.arrivalnotice.MesWmArrivalNoticeService; import cn.iocoder.yudao.module.mes.service.wm.outsourcereceipt.MesWmOutsourceReceiptService; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -62,6 +64,9 @@ public class MesQcIqcServiceImpl implements MesQcIqcService { private MesMdVendorService vendorService; @Resource private MesMdItemService itemService; + @Resource + @Lazy + private MesQcIndicatorResultService indicatorResultService; @Resource private AdminUserApi adminUserApi; @@ -125,6 +130,8 @@ public class MesQcIqcServiceImpl implements MesQcIqcService { if (iqc.getCheckResult() == null) { throw exception(QC_IQC_CHECK_RESULT_EMPTY); } + // 1.2 校验至少存在一条检测结果 + indicatorResultService.validateIndicatorResultExistsByQcIdAndType(id, MesQcTypeEnum.IQC.getType()); // 2. 更新状态为已完成 MesQcIqcDO updateObj = new MesQcIqcDO() @@ -296,4 +303,9 @@ public class MesQcIqcServiceImpl implements MesQcIqcService { return convertMap(list, MesQcIqcDO::getId); } + @Override + public Long getIqcCountByVendorId(Long vendorId) { + return iqcMapper.selectCountByVendorId(vendorId); + } + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcLineService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcLineService.java index 1f8fbb2b4..26de52409 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcLineService.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcLineService.java @@ -69,4 +69,12 @@ public interface MesQcOqcLineService { */ void recalculateLineDefectStats(Long oqcId, List records); + /** + * 统计使用指定计量单位的出货检验行数量 + * + * @param unitMeasureId 计量单位编号 + * @return 引用数量 + */ + Long getOqcLineCountByUnitMeasureId(Long unitMeasureId); + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcLineServiceImpl.java index e4f02ffe4..cc4135bed 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcLineServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcLineServiceImpl.java @@ -9,9 +9,9 @@ import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO; import cn.iocoder.yudao.module.mes.dal.dataobject.qc.oqc.MesQcOqcLineDO; import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateIndicatorDO; import cn.iocoder.yudao.module.mes.dal.mysql.qc.oqc.MesQcOqcLineMapper; -import cn.iocoder.yudao.module.mes.dal.mysql.qc.template.MesQcTemplateIndicatorMapper; import cn.iocoder.yudao.module.mes.enums.qc.MesQcDefectLevelEnum; import cn.iocoder.yudao.module.mes.service.qc.indicator.MesQcIndicatorService; +import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateIndicatorService; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -37,10 +37,11 @@ public class MesQcOqcLineServiceImpl implements MesQcOqcLineService { @Resource private MesQcOqcLineMapper oqcLineMapper; - @Resource - private MesQcTemplateIndicatorMapper templateIndicatorMapper; + @Resource private MesQcIndicatorService indicatorService; + @Resource + private MesQcTemplateIndicatorService templateIndicatorService; @Override public MesQcOqcLineDO validateOqcLineExists(Long id) { @@ -63,7 +64,7 @@ public class MesQcOqcLineServiceImpl implements MesQcOqcLineService { @Override public void createLinesFromTemplate(Long oqcId, Long templateId) { - List templateIndicators = templateIndicatorMapper.selectListByTemplateId(templateId); + List templateIndicators = templateIndicatorService.getTemplateIndicatorListByTemplateId(templateId); if (CollUtil.isEmpty(templateIndicators)) { return; } @@ -124,4 +125,9 @@ public class MesQcOqcLineServiceImpl implements MesQcOqcLineService { oqcLineMapper.deleteByOqcId(oqcId); } + @Override + public Long getOqcLineCountByUnitMeasureId(Long unitMeasureId) { + return oqcLineMapper.selectCountByUnitMeasureId(unitMeasureId); + } + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcServiceImpl.java index 6e276aab4..ba304b96a 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcServiceImpl.java @@ -16,6 +16,7 @@ import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService; import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService; +import cn.iocoder.yudao.module.mes.service.qc.indicatorresult.MesQcIndicatorResultService; import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateItemService; import cn.iocoder.yudao.module.mes.service.wm.productsales.MesWmProductSalesLineService; import cn.iocoder.yudao.module.mes.service.wm.productsales.MesWmProductSalesService; @@ -47,6 +48,7 @@ public class MesQcOqcServiceImpl implements MesQcOqcService { @Resource private MesQcOqcMapper oqcMapper; + @Resource private MesQcTemplateItemService templateItemService; @Resource @@ -66,6 +68,9 @@ public class MesQcOqcServiceImpl implements MesQcOqcService { @Resource @Lazy private MesWmProductSalesService productSalesService; + @Resource + @Lazy + private MesQcIndicatorResultService indicatorResultService; @Resource private AdminUserApi adminUserApi; @@ -128,6 +133,8 @@ public class MesQcOqcServiceImpl implements MesQcOqcService { if (oqc.getCheckResult() == null) { throw exception(QC_OQC_CHECK_RESULT_EMPTY); } + // 1.3 校验至少存在一条检测结果 + indicatorResultService.validateIndicatorResultExistsByQcIdAndType(id, MesQcTypeEnum.OQC.getType()); // 2. 更新状态为已完成 MesQcOqcDO updateObj = new MesQcOqcDO() @@ -221,13 +228,15 @@ public class MesQcOqcServiceImpl implements MesQcOqcService { return null; } if (Objects.equals(sourceDocType, MesBizTypeConstants.WM_PRODUCT_SALES)) { - MesWmProductSalesLineDO salesLine = productSalesLineService.getProductSalesLine(sourceLineId); - if (salesLine != null && salesLine.getSalesId() != null) { + MesWmProductSalesLineDO salesLine = productSalesLineService.validateProductSalesLineExists(sourceLineId); + if (salesLine.getSalesId() != null) { MesWmProductSalesDO sales = productSalesService.getProductSales(salesLine.getSalesId()); return sales != null ? sales.getCode() : null; } + return null; } - return null; + // 未知来源类型应报错,而不是静默忽略 + throw exception(QC_OQC_SOURCE_DOC_TYPE_UNKNOWN); } @Override diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/rqc/MesQcRqcLineService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/rqc/MesQcRqcLineService.java index 299233580..64c504efd 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/rqc/MesQcRqcLineService.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/rqc/MesQcRqcLineService.java @@ -69,4 +69,12 @@ public interface MesQcRqcLineService { */ void deleteByRqcId(Long rqcId); + /** + * 统计使用指定计量单位的退货检验行数量 + * + * @param unitMeasureId 计量单位编号 + * @return 引用数量 + */ + Long getRqcLineCountByUnitMeasureId(Long unitMeasureId); + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/rqc/MesQcRqcLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/rqc/MesQcRqcLineServiceImpl.java index f4351f228..a14001d5f 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/rqc/MesQcRqcLineServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/rqc/MesQcRqcLineServiceImpl.java @@ -9,9 +9,9 @@ import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO; import cn.iocoder.yudao.module.mes.dal.dataobject.qc.rqc.MesQcRqcLineDO; import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateIndicatorDO; import cn.iocoder.yudao.module.mes.dal.mysql.qc.rqc.MesQcRqcLineMapper; -import cn.iocoder.yudao.module.mes.dal.mysql.qc.template.MesQcTemplateIndicatorMapper; import cn.iocoder.yudao.module.mes.enums.qc.MesQcDefectLevelEnum; import cn.iocoder.yudao.module.mes.service.qc.indicator.MesQcIndicatorService; +import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateIndicatorService; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -37,11 +37,11 @@ public class MesQcRqcLineServiceImpl implements MesQcRqcLineService { @Resource private MesQcRqcLineMapper rqcLineMapper; - @Resource - private MesQcTemplateIndicatorMapper templateIndicatorMapper; @Resource private MesQcIndicatorService indicatorService; + @Resource + private MesQcTemplateIndicatorService templateIndicatorService; @Override public MesQcRqcLineDO validateRqcLineExists(Long id) { @@ -64,7 +64,7 @@ public class MesQcRqcLineServiceImpl implements MesQcRqcLineService { @Override public void createLinesFromTemplate(Long rqcId, Long templateId) { - List templateIndicators = templateIndicatorMapper.selectListByTemplateId(templateId); + List templateIndicators = templateIndicatorService.getTemplateIndicatorListByTemplateId(templateId); if (CollUtil.isEmpty(templateIndicators)) { return; } @@ -125,4 +125,9 @@ public class MesQcRqcLineServiceImpl implements MesQcRqcLineService { rqcLineMapper.deleteByRqcId(rqcId); } + @Override + public Long getRqcLineCountByUnitMeasureId(Long unitMeasureId) { + return rqcLineMapper.selectCountByUnitMeasureId(unitMeasureId); + } + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/rqc/MesQcRqcServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/rqc/MesQcRqcServiceImpl.java index 0d1d0bfac..0273c7529 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/rqc/MesQcRqcServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/rqc/MesQcRqcServiceImpl.java @@ -15,6 +15,7 @@ import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum; import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService; +import cn.iocoder.yudao.module.mes.service.qc.indicatorresult.MesQcIndicatorResultService; import cn.iocoder.yudao.module.mes.service.wm.returnissue.MesWmReturnIssueService; import cn.iocoder.yudao.module.mes.service.wm.returnsales.MesWmReturnSalesService; import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateItemService; @@ -46,6 +47,7 @@ public class MesQcRqcServiceImpl implements MesQcRqcService { @Resource private MesQcRqcMapper rqcMapper; + @Resource private MesQcTemplateItemService templateItemService; @Resource @@ -68,6 +70,9 @@ public class MesQcRqcServiceImpl implements MesQcRqcService { @Resource @Lazy private MesWmReturnSalesService returnSalesService; + @Resource + @Lazy + private MesQcIndicatorResultService indicatorResultService; @Resource private AdminUserApi adminUserApi; @@ -137,6 +142,8 @@ public class MesQcRqcServiceImpl implements MesQcRqcService { throw exception(QC_RQC_QUANTITY_MISMATCH); } } + // 1.4 校验至少存在一条检测结果 + indicatorResultService.validateIndicatorResultExistsByQcIdAndType(id, MesQcTypeEnum.RQC.getType()); // 2. 更新状态为已完成 MesQcRqcDO updateObj = new MesQcRqcDO().setId(id).setStatus(MesQcStatusEnum.FINISHED.getStatus()); diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateIndicatorService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateIndicatorService.java index 9e28f4113..1d7f91099 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateIndicatorService.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateIndicatorService.java @@ -6,6 +6,8 @@ import cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo.indicator.Mes import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateIndicatorDO; import jakarta.validation.Valid; +import java.util.List; + /** * MES 质检方案-检测指标项 Service 接口 * @@ -58,4 +60,20 @@ public interface MesQcTemplateIndicatorService { */ void deleteTemplateIndicatorByTemplateId(Long templateId); + /** + * 根据方案编号,获得检测指标项列表 + * + * @param templateId 质检方案编号 + * @return 检测指标项列表 + */ + List getTemplateIndicatorListByTemplateId(Long templateId); + + /** + * 获取指定计量单位的检测指标项数量 + * + * @param unitMeasureId 计量单位编号 + * @return 检测指标项数量 + */ + Long getTemplateIndicatorCountByUnitMeasureId(Long unitMeasureId); + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateIndicatorServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateIndicatorServiceImpl.java index afe355ee2..667226f06 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateIndicatorServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateIndicatorServiceImpl.java @@ -11,6 +11,8 @@ import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; 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.QC_TEMPLATE_INDICATOR_NOT_EXISTS; @@ -80,4 +82,14 @@ public class MesQcTemplateIndicatorServiceImpl implements MesQcTemplateIndicator templateIndicatorMapper.deleteByTemplateId(templateId); } + @Override + public List getTemplateIndicatorListByTemplateId(Long templateId) { + return templateIndicatorMapper.selectListByTemplateId(templateId); + } + + @Override + public Long getTemplateIndicatorCountByUnitMeasureId(Long unitMeasureId) { + return templateIndicatorMapper.selectCountByUnitMeasureId(unitMeasureId); + } + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/tm/tool/MesTmToolService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/tm/tool/MesTmToolService.java index 243faf276..149fecae2 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/tm/tool/MesTmToolService.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/tm/tool/MesTmToolService.java @@ -64,6 +64,14 @@ public interface MesTmToolService { */ List getToolList(); + /** + * 获得指定工具类型下的工具数量 + * + * @param toolTypeId 工具类型编号 + * @return 工具数量 + */ + Long getToolCountByToolTypeId(Long toolTypeId); + /** * 获得工具列表 * diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/tm/tool/MesTmToolServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/tm/tool/MesTmToolServiceImpl.java index c3bf911db..21bfc6c66 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/tm/tool/MesTmToolServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/tm/tool/MesTmToolServiceImpl.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.mes.service.tm.tool; -import java.util.Collections; import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; @@ -11,18 +10,19 @@ import cn.iocoder.yudao.module.mes.dal.mysql.tm.tool.MesTmToolMapper; import cn.iocoder.yudao.module.mes.enums.tm.MesTmMaintenTypeEnum; import cn.iocoder.yudao.module.mes.enums.wm.BarcodeBizTypeEnum; import cn.iocoder.yudao.module.mes.service.wm.barcode.MesWmBarcodeService; +import cn.iocoder.yudao.module.mes.service.wm.batch.MesWmBatchService; import jakarta.annotation.Resource; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Objects; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.TM_TOOL_CODE_DUPLICATE; -import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.TM_TOOL_NOT_EXISTS; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; /** * MES 工具台账 Service 实现类 @@ -39,9 +39,11 @@ public class MesTmToolServiceImpl implements MesTmToolService { @Resource @Lazy // 延迟加载,避免循环依赖 private MesTmToolTypeService toolTypeService; - @Resource private MesWmBarcodeService barcodeService; + @Resource + @Lazy + private MesWmBatchService batchService; @Override public Long createTool(MesTmToolSaveReqVO createReqVO) { @@ -87,6 +89,11 @@ public class MesTmToolServiceImpl implements MesTmToolService { public void deleteTool(Long id) { // 校验存在 validateToolExists(id); + // 校验是否被批次引用 + if (batchService.getBatchCountByToolId(id) > 0) { + throw exception(TM_TOOL_HAS_BATCH); + } + // 删除 toolMapper.deleteById(id); } @@ -120,6 +127,11 @@ public class MesTmToolServiceImpl implements MesTmToolService { return toolMapper.selectPage(pageReqVO); } + @Override + public Long getToolCountByToolTypeId(Long toolTypeId) { + return toolMapper.selectCountByToolTypeId(toolTypeId); + } + @Override public List getToolList() { return toolMapper.selectList(); diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/tm/tool/MesTmToolTypeServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/tm/tool/MesTmToolTypeServiceImpl.java index 6a5d1f610..4737ddca3 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/tm/tool/MesTmToolTypeServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/tm/tool/MesTmToolTypeServiceImpl.java @@ -6,9 +6,10 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.mes.controller.admin.tm.tool.vo.type.MesTmToolTypePageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.tm.tool.vo.type.MesTmToolTypeSaveReqVO; import cn.iocoder.yudao.module.mes.dal.dataobject.tm.tool.MesTmToolTypeDO; -import cn.iocoder.yudao.module.mes.dal.mysql.tm.tool.MesTmToolMapper; import cn.iocoder.yudao.module.mes.dal.mysql.tm.tool.MesTmToolTypeMapper; +import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationToolService; import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -34,7 +35,11 @@ public class MesTmToolTypeServiceImpl implements MesTmToolTypeService { private MesTmToolTypeMapper toolTypeMapper; @Resource - private MesTmToolMapper toolMapper; + @Lazy + private MesTmToolService toolService; + @Resource + @Lazy + private MesMdWorkstationToolService workstationToolService; @Override public Long createToolType(MesTmToolTypeSaveReqVO createReqVO) { @@ -71,9 +76,13 @@ public class MesTmToolTypeServiceImpl implements MesTmToolTypeService { // 校验存在 validateToolTypeExists(id); // 校验是否被工具引用 - if (toolMapper.selectCountByToolTypeId(id) > 0) { + if (toolService.getToolCountByToolTypeId(id) > 0) { throw exception(TM_TOOL_TYPE_HAS_TOOL); } + // 校验是否被工作站工装资源引用 + if (workstationToolService.getWorkstationToolCountByToolTypeId(id) > 0) { + throw exception(TM_TOOL_TYPE_HAS_WORKSTATION_TOOL); + } // 删除 toolTypeMapper.deleteById(id); diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeLineServiceImpl.java index b181cac04..b8d84a9b8 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeLineServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeLineServiceImpl.java @@ -66,7 +66,7 @@ public class MesWmArrivalNoticeLineServiceImpl implements MesWmArrivalNoticeLine // 校验父单据存在且为草稿状态 arrivalNoticeService.validateArrivalNoticeExistsAndDraft(reqVO.getNoticeId()); // 校验物料存在 - itemService.validateItemExists(reqVO.getItemId()); + itemService.validateItemExistsAndEnable(reqVO.getItemId()); } /** diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeService.java index 04109ce61..aaea87d9e 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeService.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeService.java @@ -117,12 +117,13 @@ public interface MesWmArrivalNoticeService { void validateArrivalNoticeAndLineExists(Long noticeId, Long lineId); /** - * 按状态获得到货通知单列表 + * 校验到货通知单已就绪可被采购入库引用 + *

校验状态为待入库 + 所有需检行都已完成 IQC

* - * @param status 状态 - * @return 到货通知单列表 + * @param id 到货通知单编号 + * @return 到货通知单 */ - List getArrivalNoticeListByStatus(Integer status); + MesWmArrivalNoticeDO validateArrivalNoticeReadyForReceipt(Long id); /** * 查询指定供应商的到货通知单数量 diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeServiceImpl.java index 0e41cea03..3b5a79e53 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeServiceImpl.java @@ -38,11 +38,13 @@ public class MesWmArrivalNoticeServiceImpl implements MesWmArrivalNoticeService @Resource private MesWmArrivalNoticeLineService arrivalNoticeLineService; + @Resource + private cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService vendorService; @Override public Long createArrivalNotice(MesWmArrivalNoticeSaveReqVO createReqVO) { - // 校验编码唯一 - validateCodeUnique(null, createReqVO.getCode()); + // 校验数据 + validateArrivalNoticeSaveData(createReqVO); // 插入 MesWmArrivalNoticeDO notice = BeanUtils.toBean(createReqVO, MesWmArrivalNoticeDO.class); @@ -55,14 +57,21 @@ public class MesWmArrivalNoticeServiceImpl implements MesWmArrivalNoticeService public void updateArrivalNotice(MesWmArrivalNoticeSaveReqVO updateReqVO) { // 校验存在 + 草稿状态 validateArrivalNoticeExistsAndDraft(updateReqVO.getId()); - // 校验编码唯一 - validateCodeUnique(updateReqVO.getId(), updateReqVO.getCode()); + // 校验数据 + validateArrivalNoticeSaveData(updateReqVO); // 更新 MesWmArrivalNoticeDO updateObj = BeanUtils.toBean(updateReqVO, MesWmArrivalNoticeDO.class); arrivalNoticeMapper.updateById(updateObj); } + private void validateArrivalNoticeSaveData(MesWmArrivalNoticeSaveReqVO reqVO) { + // 校验编码唯一 + validateCodeUnique(reqVO.getId(), reqVO.getCode()); + // 校验供应商存在且启用 + vendorService.validateVendorExistsAndEnable(reqVO.getVendorId()); + } + @Override @Transactional(rollbackFor = Exception.class) public void deleteArrivalNotice(Long id) { @@ -144,6 +153,13 @@ public class MesWmArrivalNoticeServiceImpl implements MesWmArrivalNoticeService if (ObjUtil.notEqual(MesWmArrivalNoticeStatusEnum.PENDING_RECEIPT.getStatus(), notice.getStatus())) { throw exception(WM_ARRIVAL_NOTICE_STATUS_NOT_PENDING_RECEIPT); } + // 行级防御校验:确保所有需检行都已完成 IQC + List lines = arrivalNoticeLineService.getArrivalNoticeLineListByNoticeId(id); + boolean hasUnchecked = CollectionUtils.anyMatch(lines, + line -> Boolean.TRUE.equals(line.getIqcCheckFlag()) && line.getIqcId() == null); + if (hasUnchecked) { + throw exception(WM_ARRIVAL_NOTICE_IQC_PENDING); + } // 完成 arrivalNoticeMapper.updateById(new MesWmArrivalNoticeDO() @@ -158,14 +174,6 @@ public class MesWmArrivalNoticeServiceImpl implements MesWmArrivalNoticeService return arrivalNoticeMapper.selectByIds(ids); } - @Override - public List getArrivalNoticeListByStatus(Integer status) { - if (status == null) { - return arrivalNoticeMapper.selectList(); - } - return arrivalNoticeMapper.selectListByStatus(status); - } - @Override public void validateArrivalNoticeAndLineExists(Long noticeId, Long lineId) { // 1. 校验通知单存在 @@ -202,6 +210,23 @@ public class MesWmArrivalNoticeServiceImpl implements MesWmArrivalNoticeService return notice; } + @Override + public MesWmArrivalNoticeDO validateArrivalNoticeReadyForReceipt(Long id) { + // 1. 校验到货通知单存在且状态为待入库 + MesWmArrivalNoticeDO notice = validateArrivalNoticeExists(id); + if (ObjUtil.notEqual(MesWmArrivalNoticeStatusEnum.PENDING_RECEIPT.getStatus(), notice.getStatus())) { + throw exception(WM_ARRIVAL_NOTICE_STATUS_NOT_PENDING_RECEIPT); + } + // 2. 行级防御校验:确保所有需检行都已完成 IQC + List lines = arrivalNoticeLineService.getArrivalNoticeLineListByNoticeId(id); + boolean hasUnchecked = CollectionUtils.anyMatch(lines, + line -> Boolean.TRUE.equals(line.getIqcCheckFlag()) && line.getIqcId() == null); + if (hasUnchecked) { + throw exception(WM_ARRIVAL_NOTICE_IQC_PENDING); + } + return notice; + } + private void validateCodeUnique(Long id, String code) { MesWmArrivalNoticeDO notice = arrivalNoticeMapper.selectByCode(code); if (notice == null) { diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/batch/MesWmBatchService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/batch/MesWmBatchService.java index 2fafc2568..258bb9c3e 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/batch/MesWmBatchService.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/batch/MesWmBatchService.java @@ -69,10 +69,31 @@ public interface MesWmBatchService { List getBackwardBatchList(String code); /** - * 获取批次列表 + * 校验批次存在,并校验批次与物料的归属关系 * - * @return 批次列表 + * @param batchId 批次ID + * @param itemId 物料ID + * @return 批次记录 */ - List getBatchList(); + MesWmBatchDO validateBatchExists(Long batchId, Long itemId); + + /** + * 校验批次存在,并校验批次与物料、客户/供应商的归属关系 + * + * @param batchId 批次ID + * @param itemId 物料ID + * @param clientId 客户ID(可选,不为空时校验) + * @param vendorId 供应商ID(可选,不为空时校验) + * @return 批次记录 + */ + MesWmBatchDO validateBatchExists(Long batchId, Long itemId, Long clientId, Long vendorId); + + /** + * 获取指定工具的批次数量 + * + * @param toolId 工具编号 + * @return 批次数量 + */ + Long getBatchCountByToolId(Long toolId); } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/batch/MesWmBatchServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/batch/MesWmBatchServiceImpl.java index b3a2df1d8..35d0a18cf 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/batch/MesWmBatchServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/batch/MesWmBatchServiceImpl.java @@ -39,8 +39,14 @@ import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; @Slf4j public class MesWmBatchServiceImpl implements MesWmBatchService { + /** + * 批次追溯最大递归深度,防止极端场景下性能问题 + */ + private static final int MAX_TRACE_DEPTH = 20; + @Resource private MesWmBatchMapper batchMapper; + @Resource private MesMdItemService itemService; @Resource @@ -196,11 +202,11 @@ public class MesWmBatchServiceImpl implements MesWmBatchService { @Override public List getForwardBatchList(String code) { - return getForwardBatchList(code, new HashSet<>()); + return getForwardBatchList(code, new HashSet<>(), 0); } - private List getForwardBatchList(String code, Set visited) { - if (code == null || !visited.add(code)) { + private List getForwardBatchList(String code, Set visited, int depth) { + if (code == null || !visited.add(code) || depth >= MAX_TRACE_DEPTH) { return new ArrayList<>(); } List list = batchMapper.selectListByForward(code); @@ -210,18 +216,18 @@ public class MesWmBatchServiceImpl implements MesWmBatchService { // 继续递归查询下游批次 List results = new ArrayList<>(list); for (MesWmBatchDO batch : list) { - results.addAll(getForwardBatchList(batch.getCode(), visited)); + results.addAll(getForwardBatchList(batch.getCode(), visited, depth + 1)); } return results; } @Override public List getBackwardBatchList(String code) { - return getBackwardBatchList(code, new HashSet<>()); + return getBackwardBatchList(code, new HashSet<>(), 0); } - private List getBackwardBatchList(String code, Set visited) { - if (code == null || !visited.add(code)) { + private List getBackwardBatchList(String code, Set visited, int depth) { + if (code == null || !visited.add(code) || depth >= MAX_TRACE_DEPTH) { return new ArrayList<>(); } List list = batchMapper.selectListByBackward(code); @@ -231,14 +237,38 @@ public class MesWmBatchServiceImpl implements MesWmBatchService { // 继续递归查询上游批次 List results = new ArrayList<>(list); for (MesWmBatchDO batch : list) { - results.addAll(getBackwardBatchList(batch.getCode(), visited)); + results.addAll(getBackwardBatchList(batch.getCode(), visited, depth + 1)); } return results; } @Override - public List getBatchList() { - return batchMapper.selectList(); + public MesWmBatchDO validateBatchExists(Long batchId, Long itemId) { + MesWmBatchDO batch = batchMapper.selectById(batchId); + if (batch == null) { + throw exception(WM_BATCH_NOT_EXISTS); + } + if (ObjUtil.notEqual(batch.getItemId(), itemId)) { + throw exception(WM_BATCH_ITEM_MISMATCH); + } + return batch; + } + + @Override + public MesWmBatchDO validateBatchExists(Long batchId, Long itemId, Long clientId, Long vendorId) { + MesWmBatchDO batch = validateBatchExists(batchId, itemId); + if (clientId != null && ObjUtil.notEqual(batch.getClientId(), clientId)) { + throw exception(WM_BATCH_CLIENT_MISMATCH); + } + if (vendorId != null && ObjUtil.notEqual(batch.getVendorId(), vendorId)) { + throw exception(WM_BATCH_VENDOR_MISMATCH); + } + return batch; + } + + @Override + public Long getBatchCountByToolId(Long toolId) { + return batchMapper.selectCountByToolId(toolId); } } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptService.java index 17bc00eb9..eecab63f4 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptService.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptService.java @@ -5,8 +5,11 @@ import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.MesWmItemR import cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo.MesWmItemReceiptSaveReqVO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptDO; import jakarta.validation.Valid; - +import java.util.Collection; import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; /** * MES 采购入库单 Service 接口 @@ -103,4 +106,22 @@ public interface MesWmItemReceiptService { */ List getItemReceiptListByVendorId(Long vendorId); + /** + * 批量获得采购入库单列表 + * + * @param ids 编号数组 + * @return 入库单列表 + */ + List getItemReceiptList(Collection ids); + + /** + * 批量获得采购入库单 Map + * + * @param ids 编号数组 + * @return 入库单 Map + */ + default Map getItemReceiptMap(Collection ids) { + return convertMap(getItemReceiptList(ids), MesWmItemReceiptDO::getId); + } + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptServiceImpl.java index 6690cb798..0875cbd44 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptServiceImpl.java @@ -8,6 +8,7 @@ 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; @@ -27,6 +28,7 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import java.math.BigDecimal; +import java.util.Collection; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; @@ -55,7 +57,6 @@ public class MesWmItemReceiptServiceImpl implements MesWmItemReceiptService { @Resource @Lazy private MesQcIqcService iqcService; - @Resource private MesWmTransactionService wmTransactionService; @@ -87,10 +88,13 @@ public class MesWmItemReceiptServiceImpl implements MesWmItemReceiptService { // 校验编码唯一 validateCodeUnique(reqVO.getId(), reqVO.getCode()); // 校验供应商存在 - vendorService.validateVendorExists(reqVO.getVendorId()); + vendorService.validateVendorExistsAndEnable(reqVO.getVendorId()); // 校验到货通知单存在 if (reqVO.getNoticeId() != null) { - arrivalNoticeService.validateArrivalNoticeExists(reqVO.getNoticeId()); + MesWmArrivalNoticeDO notice = arrivalNoticeService.validateArrivalNoticeReadyForReceipt(reqVO.getNoticeId()); + if (ObjUtil.notEqual(notice.getVendorId(), reqVO.getVendorId())) { + throw exception(WM_ARRIVAL_NOTICE_VENDOR_MISMATCH); + } } // 校验来料检验单存在 if (reqVO.getIqcId() != null) { @@ -263,4 +267,9 @@ public class MesWmItemReceiptServiceImpl implements MesWmItemReceiptService { return itemReceiptMapper.selectListByVendorId(vendorId); } + @Override + public List getItemReceiptList(Collection ids) { + return itemReceiptMapper.selectByIds(ids); + } + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/materialstock/MesWmMaterialStockService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/materialstock/MesWmMaterialStockService.java index 9d02bdf59..a6e667c71 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/materialstock/MesWmMaterialStockService.java +++ b/yudao-module-mes/yudao-module-mes-server/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/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/materialstock/MesWmMaterialStockServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/materialstock/MesWmMaterialStockServiceImpl.java index 249b5ee2d..50405b650 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/materialstock/MesWmMaterialStockServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/materialstock/MesWmMaterialStockServiceImpl.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.mes.service.wm.materialstock; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.SetUtils; @@ -11,11 +12,14 @@ import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemTypeDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; import cn.iocoder.yudao.module.mes.dal.mysql.wm.materialstock.MesWmMaterialStockMapper; import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemTypeService; import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService; import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -43,6 +47,9 @@ public class MesWmMaterialStockServiceImpl implements MesWmMaterialStockService private MesMdItemTypeService itemTypeService; @Resource private MesWmWarehouseAreaService areaService; + @Resource + @Lazy + private MesWmWarehouseService warehouseService; @Override public MesWmMaterialStockDO getMaterialStock(Long id) { @@ -77,9 +84,19 @@ public class MesWmMaterialStockServiceImpl implements MesWmMaterialStockService if (pageReqVO.getItemId() != null) { itemIds = SetUtils.asSet(pageReqVO.getItemId()); } + // 1.3 解析 virtualFilter:转换为虚拟仓 warehouseId + Long virtualWarehouseId = null; + String virtualFilter = pageReqVO.getVirtualFilter(); + if (MesWmMaterialStockPageReqVO.VIRTUAL_FILTER_EXCLUDE.equals(virtualFilter) + || MesWmMaterialStockPageReqVO.VIRTUAL_FILTER_ONLY.equals(virtualFilter)) { + MesWmWarehouseDO virtualWarehouse = warehouseService.getWarehouseByCode( + MesWmWarehouseDO.WIP_VIRTUAL_WAREHOUSE); + Assert.notNull(virtualWarehouse, "虚拟仓库(WIP_VIRTUAL_WAREHOUSE)不存在"); + virtualWarehouseId = virtualWarehouse.getId(); + } // 2. 分页查询 - return materialStockMapper.selectPage(pageReqVO, itemTypeIds, itemIds); + return materialStockMapper.selectPage(pageReqVO, itemTypeIds, itemIds, virtualWarehouseId); } @Override @@ -185,4 +202,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/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscissue/MesWmMiscIssueLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscissue/MesWmMiscIssueLineServiceImpl.java index 92936f9bf..ddf7ba476 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscissue/MesWmMiscIssueLineServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscissue/MesWmMiscIssueLineServiceImpl.java @@ -32,14 +32,11 @@ public class MesWmMiscIssueLineServiceImpl implements MesWmMiscIssueLineService @Resource @Lazy private MesWmMiscIssueService miscIssueService; - @Resource @Lazy private MesWmMiscIssueDetailService miscIssueDetailService; - @Resource private MesMdItemService itemService; - @Resource private MesWmWarehouseAreaService warehouseAreaService; @@ -132,7 +129,7 @@ public class MesWmMiscIssueLineServiceImpl implements MesWmMiscIssueLineService // 校验父单据存在且为可编辑状态 miscIssueService.validateMiscIssueEditable(issueId); // 校验物料存在 - itemService.validateItemExists(reqVO.getItemId()); + itemService.validateItemExistsAndEnable(reqVO.getItemId()); // 校验仓库、库区、库位的父子关系 warehouseAreaService.validateWarehouseAreaExists(reqVO.getWarehouseId(), reqVO.getLocationId(), reqVO.getAreaId()); diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscissue/MesWmMiscIssueServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscissue/MesWmMiscIssueServiceImpl.java index 749731bcb..8861bc8eb 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscissue/MesWmMiscIssueServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscissue/MesWmMiscIssueServiceImpl.java @@ -132,6 +132,7 @@ public class MesWmMiscIssueServiceImpl implements MesWmMiscIssueService { wmTransactionService.createTransactionList(convertList(lines, line -> new MesWmTransactionSaveReqDTO() .setType(MesWmTransactionTypeEnum.OUT.getType()).setItemId(line.getItemId()) .setQuantity(line.getQuantity().negate()) // 出库数量为负数 + .setBatchId(line.getBatchId()).setBatchCode(line.getBatchCode()) .setWarehouseId(line.getWarehouseId()).setLocationId(line.getLocationId()).setAreaId(line.getAreaId()) .setBizType(MesBizTypeConstants.WM_MISC_ISSUE).setBizId(issue.getId()).setBizCode(issue.getCode()).setBizLineId(line.getId()))); } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptLineServiceImpl.java index a659f5856..ed156b3c7 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptLineServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/miscreceipt/MesWmMiscReceiptLineServiceImpl.java @@ -125,7 +125,7 @@ public class MesWmMiscReceiptLineServiceImpl implements MesWmMiscReceiptLineServ // 校验父单据存在且为可编辑状态 miscReceiptService.validateMiscReceiptEditable(reqVO.getReceiptId()); // 校验物料存在 - itemService.validateItemExists(reqVO.getItemId()); + itemService.validateItemExistsAndEnable(reqVO.getItemId()); // 校验仓库层级关系(仓库 - 库位 - 库区) warehouseAreaService.validateWarehouseAreaExists(reqVO.getWarehouseId(), reqVO.getLocationId(), reqVO.getAreaId()); diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueDetailServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueDetailServiceImpl.java index 8ad07979b..9a149367f 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueDetailServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/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 实现类 @@ -26,11 +30,16 @@ public class MesWmOutsourceIssueDetailServiceImpl implements MesWmOutsourceIssue @Resource 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 +104,26 @@ public class MesWmOutsourceIssueDetailServiceImpl implements MesWmOutsourceIssue } private void validateOutsourceIssueDetailSaveData(MesWmOutsourceIssueDetailSaveReqVO saveReqVO) { - // 校验关联的发料单存在 - outsourceIssueService.getOutsourceIssue(saveReqVO.getIssueId()); - // 校验关联的物料存在 - itemService.validateItemExists(saveReqVO.getItemId()); + // 校验父数据(行)存在 + 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.validateItemExistsAndEnable(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/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueLineServiceImpl.java index a556cd5b1..236ee941d 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueLineServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueLineServiceImpl.java @@ -121,7 +121,7 @@ public class MesWmOutsourceIssueLineServiceImpl implements MesWmOutsourceIssueLi throw exception(WM_OUTSOURCE_ISSUE_NOT_EXISTS); } // 校验关联的物料存在 - itemService.validateItemExists(saveReqVO.getItemId()); + itemService.validateItemExistsAndEnable(saveReqVO.getItemId()); // 校验物料是否在工单 BOM 中 validateItemInWorkOrderBom(issue.getWorkOrderId(), saveReqVO.getItemId()); } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueService.java index 042bad18c..a68e9f901 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueService.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueService.java @@ -87,4 +87,12 @@ public interface MesWmOutsourceIssueService { */ Boolean checkOutsourceIssueQuantity(Long id); + /** + * 根据供应商 ID 统计外协发料单数量 + * + * @param vendorId 供应商 ID + * @return 数量 + */ + Long getOutsourceIssueCountByVendorId(Long vendorId); + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueServiceImpl.java index 5b53c2b50..68154fe3d 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourceissue/MesWmOutsourceIssueServiceImpl.java @@ -259,10 +259,10 @@ public class MesWmOutsourceIssueServiceImpl implements MesWmOutsourceIssueServic validateCodeUnique(saveReqVO.getId(), saveReqVO.getCode()); // 校验供应商存在 if (saveReqVO.getVendorId() != null) { - vendorService.validateVendorExists(saveReqVO.getVendorId()); + vendorService.validateVendorExistsAndEnable(saveReqVO.getVendorId()); } // 校验工单存在且类型为外协(代工) - MesProWorkOrderDO workOrder = workOrderService.validateWorkOrderExists(saveReqVO.getWorkOrderId()); + MesProWorkOrderDO workOrder = workOrderService.validateWorkOrderConfirmed(saveReqVO.getWorkOrderId()); if (ObjUtil.notEqual(workOrder.getType(), MesProWorkOrderTypeEnum.OUTSOURCE.getType())) { throw exception(WM_OUTSOURCE_ISSUE_WORK_ORDER_TYPE_INVALID); } @@ -281,4 +281,9 @@ public class MesWmOutsourceIssueServiceImpl implements MesWmOutsourceIssueServic } } + @Override + public Long getOutsourceIssueCountByVendorId(Long vendorId) { + return outsourceIssueMapper.selectCountByVendorId(vendorId); + } + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptDetailServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptDetailServiceImpl.java index 60e4934fa..e59639bdd 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptDetailServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptDetailServiceImpl.java @@ -6,8 +6,6 @@ import cn.iocoder.yudao.module.mes.dal.dataobject.wm.outsourcereceipt.MesWmOutso import cn.iocoder.yudao.module.mes.dal.mysql.wm.outsourcereceipt.MesWmOutsourceReceiptDetailMapper; import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; -import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseLocationService; -import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -29,30 +27,13 @@ public class MesWmOutsourceReceiptDetailServiceImpl implements MesWmOutsourceRec @Resource private MesMdItemService itemService; - - @Resource - private MesWmWarehouseService warehouseService; - - @Resource - private MesWmWarehouseLocationService locationService; - @Resource private MesWmWarehouseAreaService areaService; @Override public Long createOutsourceReceiptDetail(MesWmOutsourceReceiptDetailSaveReqVO createReqVO) { - // 校验物料存在 - itemService.validateItemExists(createReqVO.getItemId()); - // 校验仓库、库区、库位存在 - if (createReqVO.getWarehouseId() != null) { - warehouseService.validateWarehouseExists(createReqVO.getWarehouseId()); - } - if (createReqVO.getLocationId() != null) { - locationService.validateWarehouseLocationExists(createReqVO.getLocationId()); - } - if (createReqVO.getAreaId() != null) { - areaService.validateWarehouseAreaExists(createReqVO.getAreaId()); - } + // 校验数据 + validateDetailSaveData(createReqVO); // 插入 MesWmOutsourceReceiptDetailDO detail = BeanUtils.toBean(createReqVO, MesWmOutsourceReceiptDetailDO.class); @@ -64,18 +45,8 @@ public class MesWmOutsourceReceiptDetailServiceImpl implements MesWmOutsourceRec public void updateOutsourceReceiptDetail(MesWmOutsourceReceiptDetailSaveReqVO updateReqVO) { // 校验存在 validateOutsourceReceiptDetailExists(updateReqVO.getId()); - // 校验物料存在 - itemService.validateItemExists(updateReqVO.getItemId()); - // 校验仓库、库区、库位存在 - if (updateReqVO.getWarehouseId() != null) { - warehouseService.validateWarehouseExists(updateReqVO.getWarehouseId()); - } - if (updateReqVO.getLocationId() != null) { - locationService.validateWarehouseLocationExists(updateReqVO.getLocationId()); - } - if (updateReqVO.getAreaId() != null) { - areaService.validateWarehouseAreaExists(updateReqVO.getAreaId()); - } + // 校验数据 + validateDetailSaveData(updateReqVO); // 更新 MesWmOutsourceReceiptDetailDO updateObj = BeanUtils.toBean(updateReqVO, MesWmOutsourceReceiptDetailDO.class); @@ -115,6 +86,16 @@ public class MesWmOutsourceReceiptDetailServiceImpl implements MesWmOutsourceRec detailMapper.deleteByLineId(lineId); } + /** + * 校验保存时的关联数据 + */ + private void validateDetailSaveData(MesWmOutsourceReceiptDetailSaveReqVO reqVO) { + // 校验物料存在 + itemService.validateItemExistsAndEnable(reqVO.getItemId()); + // 校验仓库、库区、库位的层级关系 + areaService.validateWarehouseAreaExists(reqVO.getWarehouseId(), reqVO.getLocationId(), reqVO.getAreaId()); + } + private void validateOutsourceReceiptDetailExists(Long id) { if (detailMapper.selectById(id) == null) { throw exception(WM_OUTSOURCE_RECEIPT_DETAIL_NOT_EXISTS); diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptLineServiceImpl.java index 2c81a7632..5559ce921 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptLineServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptLineServiceImpl.java @@ -37,26 +37,22 @@ public class MesWmOutsourceReceiptLineServiceImpl implements MesWmOutsourceRecei @Resource private MesMdItemService itemService; - @Resource @Lazy private MesWmOutsourceReceiptDetailService outsourceReceiptDetailService; - @Resource @Lazy private MesWmOutsourceReceiptService outsourceReceiptService; - @Resource @Lazy private MesProWorkOrderService workOrderService; - @Resource private MesWmBatchService batchService; @Override public Long createOutsourceReceiptLine(MesWmOutsourceReceiptLineSaveReqVO createReqVO) { // 校验物料存在 - itemService.validateItemExists(createReqVO.getItemId()); + itemService.validateItemExistsAndEnable(createReqVO.getItemId()); // 插入 MesWmOutsourceReceiptLineDO line = BeanUtils.toBean(createReqVO, MesWmOutsourceReceiptLineDO.class); @@ -76,7 +72,7 @@ public class MesWmOutsourceReceiptLineServiceImpl implements MesWmOutsourceRecei // 校验存在 validateOutsourceReceiptLineExists(updateReqVO.getId()); // 校验物料存在 - itemService.validateItemExists(updateReqVO.getItemId()); + itemService.validateItemExistsAndEnable(updateReqVO.getItemId()); // 更新 MesWmOutsourceReceiptLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmOutsourceReceiptLineDO.class); diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptService.java index 01b93990c..990f02e6b 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptService.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptService.java @@ -99,4 +99,12 @@ public interface MesWmOutsourceReceiptService { */ void validateOutsourceReceiptAndLineExists(Long receiptId, Long lineId); + /** + * 根据供应商 ID 统计外协入库单数量 + * + * @param vendorId 供应商 ID + * @return 数量 + */ + Long getOutsourceReceiptCountByVendorId(Long vendorId); + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptServiceImpl.java index c67b0d885..67cb907c0 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/outsourcereceipt/MesWmOutsourceReceiptServiceImpl.java @@ -64,14 +64,8 @@ public class MesWmOutsourceReceiptServiceImpl implements MesWmOutsourceReceiptSe @Override public Long createOutsourceReceipt(MesWmOutsourceReceiptSaveReqVO createReqVO) { - // 校验编码唯一 - validateCodeUnique(null, createReqVO.getCode()); - // 校验供应商存在 - vendorService.validateVendorExists(createReqVO.getVendorId()); - // 校验外协工单存在 - if (createReqVO.getWorkOrderId() != null) { - workOrderService.validateWorkOrderExists(createReqVO.getWorkOrderId()); - } + // 校验数据 + validateOutsourceReceiptSaveData(null, createReqVO); // 插入 MesWmOutsourceReceiptDO receipt = BeanUtils.toBean(createReqVO, MesWmOutsourceReceiptDO.class); @@ -84,14 +78,8 @@ public class MesWmOutsourceReceiptServiceImpl implements MesWmOutsourceReceiptSe public void updateOutsourceReceipt(MesWmOutsourceReceiptSaveReqVO updateReqVO) { // 校验存在 + 草稿状态 validateOutsourceReceiptExistsAndDraft(updateReqVO.getId()); - // 校验编码唯一 - validateCodeUnique(updateReqVO.getId(), updateReqVO.getCode()); - // 校验供应商存在 - vendorService.validateVendorExists(updateReqVO.getVendorId()); - // 校验外协工单存在 - if (updateReqVO.getWorkOrderId() != null) { - workOrderService.validateWorkOrderExists(updateReqVO.getWorkOrderId()); - } + // 校验数据 + validateOutsourceReceiptSaveData(updateReqVO.getId(), updateReqVO); // 更新 MesWmOutsourceReceiptDO updateObj = BeanUtils.toBean(updateReqVO, MesWmOutsourceReceiptDO.class); @@ -172,7 +160,7 @@ public class MesWmOutsourceReceiptServiceImpl implements MesWmOutsourceReceiptSe MesWmOutsourceReceiptDetailDO::getQuantity, BigDecimal::add, BigDecimal.ZERO); // 对比行数量与明细总数量,不满足直接抛出 if (line.getQuantity().compareTo(totalDetailQuantity) > 0) { - MesMdItemDO item = itemService.validateItemExists(line.getItemId()); + MesMdItemDO item = itemService.validateItemExistsAndEnable(line.getItemId()); throw exception(WM_OUTSOURCE_RECEIPT_DETAIL_QUANTITY_MISMATCH, item.getCode() + " " + item.getName() + " 未完成上架"); } @@ -317,6 +305,17 @@ public class MesWmOutsourceReceiptServiceImpl implements MesWmOutsourceReceiptSe return receipt; } + private void validateOutsourceReceiptSaveData(Long id, MesWmOutsourceReceiptSaveReqVO reqVO) { + // 校验编码唯一 + validateCodeUnique(id, reqVO.getCode()); + // 校验供应商存在 + vendorService.validateVendorExistsAndEnable(reqVO.getVendorId()); + // 校验外协工单存在 + if (reqVO.getWorkOrderId() != null) { + workOrderService.validateWorkOrderConfirmed(reqVO.getWorkOrderId()); + } + } + private void validateCodeUnique(Long id, String code) { MesWmOutsourceReceiptDO receipt = outsourceReceiptMapper.selectByCode(code); if (receipt == null) { @@ -327,4 +326,9 @@ public class MesWmOutsourceReceiptServiceImpl implements MesWmOutsourceReceiptSe } } + @Override + public Long getOutsourceReceiptCountByVendorId(Long vendorId) { + return outsourceReceiptMapper.selectCountByVendorId(vendorId); + } + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/packages/MesWmPackageLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/packages/MesWmPackageLineServiceImpl.java index 4be0675d0..a04cd6ba6 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/packages/MesWmPackageLineServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/packages/MesWmPackageLineServiceImpl.java @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo.line.MesWmPac import cn.iocoder.yudao.module.mes.dal.dataobject.wm.packages.MesWmPackageLineDO; import cn.iocoder.yudao.module.mes.dal.mysql.wm.packages.MesWmPackageLineMapper; import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; import jakarta.annotation.Resource; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; @@ -28,18 +29,19 @@ public class MesWmPackageLineServiceImpl implements MesWmPackageLineService { @Resource private MesWmPackageLineMapper packageLineMapper; + @Resource @Lazy private MesWmPackageService packageService; @Resource private MesMdItemService itemService; + @Resource + private MesProWorkOrderService workOrderService; @Override public Long createPackageLine(MesWmPackageLineSaveReqVO createReqVO) { - // 校验装箱单状态为草稿 - packageService.validatePackageStatusDraft(createReqVO.getPackageId()); - // 校验产品物料存在 - itemService.validateItemExists(createReqVO.getItemId()); + // 校验数据 + validateLineSaveData(createReqVO); // 插入 MesWmPackageLineDO line = BeanUtils.toBean(createReqVO, MesWmPackageLineDO.class); @@ -51,10 +53,9 @@ public class MesWmPackageLineServiceImpl implements MesWmPackageLineService { public void updatePackageLine(MesWmPackageLineSaveReqVO updateReqVO) { // 校验存在 MesWmPackageLineDO line = validatePackageLineExists(updateReqVO.getId()); - // 校验装箱单状态为草稿 - packageService.validatePackageStatusDraft(line.getPackageId()); - // 校验产品物料存在 - itemService.validateItemExists(updateReqVO.getItemId()); + // 校验数据 + updateReqVO.setPackageId(line.getPackageId()); + validateLineSaveData(updateReqVO); // 更新 MesWmPackageLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmPackageLineDO.class); @@ -93,6 +94,18 @@ public class MesWmPackageLineServiceImpl implements MesWmPackageLineService { // ========== 校验方法 ========== + /** + * 校验保存时的关联数据 + */ + private void validateLineSaveData(MesWmPackageLineSaveReqVO reqVO) { + // 校验装箱单状态为草稿 + packageService.validatePackageStatusDraft(reqVO.getPackageId()); + // 校验产品物料存在 + itemService.validateItemExistsAndEnable(reqVO.getItemId()); + // 校验工单已确认 + workOrderService.validateWorkOrderConfirmed(reqVO.getWorkOrderId()); + } + private MesWmPackageLineDO validatePackageLineExists(Long id) { MesWmPackageLineDO line = packageLineMapper.selectById(id); if (line == null) { diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/packages/MesWmPackageService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/packages/MesWmPackageService.java index aab8124c9..288ea624b 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/packages/MesWmPackageService.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/packages/MesWmPackageService.java @@ -82,19 +82,6 @@ public interface MesWmPackageService { */ void removeChildPackage(Long childId); - /** - * 可添加为子箱的装箱单列表(无父箱 + 已完成状态) - * - * @return 装箱单列表 - */ - List getChildablePackageList(); - - /** - * 获得装箱单精简列表 - * - * @return 装箱单列表 - */ - List getPackageSimpleList(); /** * 获取指定装箱单及其所有子孙箱的 ID 列表 diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/packages/MesWmPackageServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/packages/MesWmPackageServiceImpl.java index 24a206fce..b5b9b2283 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/packages/MesWmPackageServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/packages/MesWmPackageServiceImpl.java @@ -34,6 +34,7 @@ public class MesWmPackageServiceImpl implements MesWmPackageService { @Resource private MesWmPackageMapper packageMapper; + @Resource private MesWmPackageLineService packageLineService; @Resource @@ -137,16 +138,6 @@ public class MesWmPackageServiceImpl implements MesWmPackageService { packageMapper.updateById(new MesWmPackageDO().setId(childId).setParentId(MesWmPackageDO.PARENT_ID_ROOT)); } - @Override - public List getChildablePackageList() { - return packageMapper.selectChildableList(); - } - - @Override - public List getPackageSimpleList() { - return packageMapper.selectList(); - } - @Override public List getPackageAndDescendantIds(Long packageId) { List result = CollUtil.newArrayList(packageId); diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueDetailServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueDetailServiceImpl.java index be75e99d6..55d188768 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueDetailServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/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,23 @@ 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); + } + // 校验主单状态为待拣货(只有 APPROVING 状态才允许新增/修改明细) + MesWmProductIssueDO issue = issueService.validateProductIssueExists(line.getIssueId()); + if (ObjUtil.notEqual(MesWmProductIssueStatusEnum.APPROVING.getStatus(), issue.getStatus())) { + throw exception(WM_PRODUCT_ISSUE_STATUS_INVALID); + } // 校验物料匹配(明细 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 +151,3 @@ public class MesWmProductIssueDetailServiceImpl implements MesWmProductIssueDeta } } - diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueLineServiceImpl.java index 4612b6099..374a2cea0 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueLineServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueLineServiceImpl.java @@ -109,10 +109,12 @@ public class MesWmProductIssueLineServiceImpl implements MesWmProductIssueLineSe * 校验保存时的关联数据 */ private void validateProductIssueLineSaveData(MesWmProductIssueLineSaveReqVO reqVO) { - // 校验父数据存在 + 校验物料在工单 BOM 中 + // 校验父数据存在 + 草稿状态才允许新增/修改行 + issueService.validateProductIssueExistsAndPrepare(reqVO.getIssueId()); + // 校验物料在工单 BOM 中 validateItemInWorkOrderBom(reqVO.getIssueId(), reqVO.getItemId()); // 校验物料存在 - itemService.validateItemExists(reqVO.getItemId()); + itemService.validateItemExistsAndEnable(reqVO.getItemId()); } private void validateItemInWorkOrderBom(Long issueId, Long itemId) { diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueServiceImpl.java index ea45bf331..e7940785b 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productissue/MesWmProductIssueServiceImpl.java @@ -138,6 +138,11 @@ public class MesWmProductIssueServiceImpl implements MesWmProductIssueService { if (ObjUtil.notEqual(MesWmProductIssueStatusEnum.APPROVING.getStatus(), issue.getStatus())) { throw exception(WM_PRODUCT_ISSUE_STATUS_INVALID); } + // 校验拣货明细闭环:行数量 = 明细数量 + if (!checkProductIssueQuantity(id)) { + throw exception(WM_PRODUCT_ISSUE_DETAIL_QUANTITY_MISMATCH); + } + // 执行拣货(待拣货 → 待执行领出) issueMapper.updateById(new MesWmProductIssueDO() .setId(id).setStatus(MesWmProductIssueStatusEnum.APPROVED.getStatus())); @@ -151,6 +156,15 @@ public class MesWmProductIssueServiceImpl implements MesWmProductIssueService { if (ObjUtil.notEqual(MesWmProductIssueStatusEnum.APPROVED.getStatus(), issue.getStatus())) { throw exception(WM_PRODUCT_ISSUE_STATUS_INVALID); } + // 校验至少有一条明细 + List details = issueDetailService.getProductIssueDetailListByIssueId(id); + if (CollUtil.isEmpty(details)) { + throw exception(WM_PRODUCT_ISSUE_NO_DETAIL); + } + // 校验行数量 = 明细数量 + if (!checkProductIssueQuantity(id)) { + throw exception(WM_PRODUCT_ISSUE_DETAIL_QUANTITY_MISMATCH); + } // 2. 遍历所有明细,创建库存事务(扣减库存 + 记录流水) createTransactionList(issue); @@ -260,9 +274,9 @@ public class MesWmProductIssueServiceImpl implements MesWmProductIssueService { */ private void validateProductIssueSaveData(MesWmProductIssueSaveReqVO reqVO) { validateCodeUnique(reqVO.getId(), reqVO.getCode()); - workOrderService.validateWorkOrderExists(reqVO.getWorkOrderId()); + workOrderService.validateWorkOrderConfirmed(reqVO.getWorkOrderId()); if (reqVO.getWorkstationId() != null) { - workstationService.validateWorkstationExists(reqVO.getWorkstationId()); + workstationService.validateWorkstationExistsAndEnable(reqVO.getWorkstationId()); } } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceLineService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceLineService.java index 3623070c2..874ed3d32 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceLineService.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceLineService.java @@ -18,6 +18,14 @@ public interface MesWmProductProduceLineService { */ void createProductProduceLine(MesWmProductProduceLineDO line); + /** + * 校验生产入库单行存在 + * + * @param id 行 ID + * @return 行数据 + */ + MesWmProductProduceLineDO validateProductProduceLineExists(Long id); + /** * 更新生产入库单行(内部使用) * diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceLineServiceImpl.java index e88a352f6..77e6f9fd8 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceLineServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceLineServiceImpl.java @@ -10,6 +10,9 @@ 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.*; + /** * MES 生产入库单行 Service 实现类 */ @@ -25,6 +28,15 @@ public class MesWmProductProduceLineServiceImpl implements MesWmProductProduceLi productProduceLineMapper.insert(line); } + @Override + public MesWmProductProduceLineDO validateProductProduceLineExists(Long id) { + MesWmProductProduceLineDO line = productProduceLineMapper.selectById(id); + if (line == null) { + throw exception(WM_PRODUCT_PRODUCE_LINE_NOT_EXISTS); + } + return line; + } + @Override public void updateProductProduceLine(MesWmProductProduceLineDO line) { productProduceLineMapper.updateById(line); diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceService.java index d612272c0..76188cf29 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceService.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceService.java @@ -41,9 +41,11 @@ public interface MesWmProductProduceService { * 待检产出({@code checkFlag=true})按检验结果拆分行,并执行入库。 * * @param feedbackId 报工记录 ID + * @param sourceLineId 来源产出行 ID(直接定位待检行) * @param qualifiedQty 合格品数量 * @param unqualifiedQty 不合格品数量 */ - void splitPendingAndFinishProduce(Long feedbackId, BigDecimal qualifiedQty, BigDecimal unqualifiedQty); + void splitPendingAndFinishProduce(Long feedbackId, Long sourceLineId, + BigDecimal qualifiedQty, BigDecimal unqualifiedQty); } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceServiceImpl.java index f4a1f15c2..fd6f98a5b 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceServiceImpl.java @@ -222,7 +222,8 @@ public class MesWmProductProduceServiceImpl implements MesWmProductProduceServic @Override @Transactional(rollbackFor = Exception.class) - public void splitPendingAndFinishProduce(Long feedbackId, BigDecimal qualifiedQty, BigDecimal unqualifiedQty) { + public void splitPendingAndFinishProduce(Long feedbackId, Long sourceLineId, + BigDecimal qualifiedQty, BigDecimal unqualifiedQty) { // 1.1 查询产出单 MesWmProductProduceDO produce = productProduceMapper.selectByFeedbackId(feedbackId); if (produce == null) { @@ -233,13 +234,8 @@ public class MesWmProductProduceServiceImpl implements MesWmProductProduceServic MesWmWarehouseLocationDO virtualLocation = locationService.getWarehouseLocationByCode(MesWmWarehouseLocationDO.WIP_VIRTUAL_LOCATION); MesWmWarehouseAreaDO virtualArea = areaService.getWarehouseAreaByCode(MesWmWarehouseAreaDO.WIP_VIRTUAL_AREA); - // 2. 查找待检验行(checkFlag=true 时只有一行 PENDING) - List lines = productProduceLineService.getProductProduceLineListByProduceId(produce.getId()); - MesWmProductProduceLineDO pendingLine = CollUtil.findOne(lines, - l -> ObjUtil.equal(l.getQualityStatus(), MesWmQualityStatusEnum.PENDING.getStatus())); - if (pendingLine == null) { - throw exception(WM_PRODUCT_PRODUCE_LINE_NOT_EXISTS); - } + // 2. 通过 sourceLineId 直接定位待检验行 + MesWmProductProduceLineDO pendingLine = productProduceLineService.validateProductProduceLineExists(sourceLineId); // 3A. 情况一:存在不合格品数量,需要拆分行 if (unqualifiedQty != null && unqualifiedQty.compareTo(BigDecimal.ZERO) > 0) { diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productreceipt/MesWmProductReceiptLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productreceipt/MesWmProductReceiptLineServiceImpl.java index 4582437d9..b22b8fc2f 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productreceipt/MesWmProductReceiptLineServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productreceipt/MesWmProductReceiptLineServiceImpl.java @@ -31,10 +31,8 @@ public class MesWmProductReceiptLineServiceImpl implements MesWmProductReceiptLi @Resource @Lazy private MesWmProductReceiptService productReceiptService; - @Resource private MesWmProductReceiptDetailService productReceiptDetailService; - @Resource private MesMdItemService itemService; @@ -111,7 +109,7 @@ public class MesWmProductReceiptLineServiceImpl implements MesWmProductReceiptLi // 校验父单据存在且为可编辑状态 productReceiptService.validateProductReceiptEditable(reqVO.getReceiptId()); // 校验物料存在 - itemService.validateItemExists(reqVO.getItemId()); + itemService.validateItemExistsAndEnable(reqVO.getItemId()); } } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productreceipt/MesWmProductReceiptServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productreceipt/MesWmProductReceiptServiceImpl.java index 7e9689cf9..100627f03 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productreceipt/MesWmProductReceiptServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productreceipt/MesWmProductReceiptServiceImpl.java @@ -48,13 +48,10 @@ public class MesWmProductReceiptServiceImpl implements MesWmProductReceiptServic @Resource private MesWmProductReceiptLineService productReceiptLineService; - @Resource private MesWmProductReceiptDetailService productReceiptDetailService; - @Resource private MesWmTransactionService wmTransactionService; - @Resource private MesProWorkOrderService workOrderService; @Resource @@ -267,7 +264,7 @@ public class MesWmProductReceiptServiceImpl implements MesWmProductReceiptServic validateCodeUnique(reqVO.getId(), reqVO.getCode()); // 校验工单存在 return reqVO.getWorkOrderId() != null ? - workOrderService.validateWorkOrderExists(reqVO.getWorkOrderId()) : null; + workOrderService.validateWorkOrderConfirmed(reqVO.getWorkOrderId()) : null; } private void validateCodeUnique(Long id, String code) { diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesDetailServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesDetailServiceImpl.java index 3f2657bc7..8cb2e81a2 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesDetailServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesDetailServiceImpl.java @@ -1,12 +1,16 @@ 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.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -29,17 +33,18 @@ public class MesWmProductSalesDetailServiceImpl implements MesWmProductSalesDeta @Resource private MesMdItemService itemService; - + @Resource + @Lazy + 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 +56,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 +105,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.validateItemExistsAndEnable(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/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesLineService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesLineService.java index f1327bc7d..54e2b1919 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesLineService.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesLineService.java @@ -68,6 +68,14 @@ public interface MesWmProductSalesLineService { */ PageResult getProductSalesLinePage(MesWmProductSalesLinePageReqVO pageReqVO); + /** + * 校验销售出库单行存在 + * + * @param id 编号 + * @return 销售出库单行 + */ + MesWmProductSalesLineDO validateProductSalesLineExists(Long id); + /** * OQC 检验完成后,更新销售出库单行的 OQC 质检状态 * diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesLineServiceImpl.java index c9cff119b..5d112b8c7 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesLineServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesLineServiceImpl.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.mes.service.wm.productsales; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; +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.line.MesWmProductSalesLinePageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo.line.MesWmProductSalesLineSaveReqVO; @@ -14,6 +15,8 @@ import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum; import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; import cn.iocoder.yudao.module.mes.service.wm.batch.MesWmBatchService; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.salesnotice.MesWmSalesNoticeLineDO; +import cn.iocoder.yudao.module.mes.service.wm.salesnotice.MesWmSalesNoticeLineService; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Lazy; @@ -26,7 +29,7 @@ import java.util.Objects; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; -import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.WM_PRODUCT_SALES_LINE_NOT_EXISTS; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; /** * MES 销售出库单行 Service 实现类 @@ -40,6 +43,7 @@ public class MesWmProductSalesLineServiceImpl implements MesWmProductSalesLineSe @Resource private MesWmProductSalesLineMapper productSalesLineMapper; + @Resource private MesWmProductSalesDetailService productSalesDetailService; @Resource @@ -49,13 +53,14 @@ public class MesWmProductSalesLineServiceImpl implements MesWmProductSalesLineSe @Resource @Lazy private MesWmProductSalesService productSalesService; + @Resource + @Lazy + private MesWmSalesNoticeLineService salesNoticeLineService; @Override public Long createProductSalesLine(MesWmProductSalesLineSaveReqVO createReqVO) { - // 校验物料存在 - itemService.validateItemExists(createReqVO.getItemId()); - // 根据 batchCode 解析 batchId - fillBatchId(createReqVO); + // 校验数据 + validateLineSaveData(createReqVO); // 新增 MesWmProductSalesLineDO line = BeanUtils.toBean(createReqVO, MesWmProductSalesLineDO.class); @@ -66,11 +71,10 @@ public class MesWmProductSalesLineServiceImpl implements MesWmProductSalesLineSe @Override public void updateProductSalesLine(MesWmProductSalesLineSaveReqVO updateReqVO) { // 校验存在 - validateProductSalesLineExists(updateReqVO.getId()); - // 校验物料存在 - itemService.validateItemExists(updateReqVO.getItemId()); - // 根据 batchCode 解析 batchId - fillBatchId(updateReqVO); + MesWmProductSalesLineDO oldLine = validateProductSalesLineExists(updateReqVO.getId()); + // 校验数据 + updateReqVO.setSalesId(oldLine.getSalesId()); + validateLineSaveData(updateReqVO); // 更新 MesWmProductSalesLineDO updateObj = BeanUtils.toBean(updateReqVO, MesWmProductSalesLineDO.class); @@ -81,7 +85,9 @@ public class MesWmProductSalesLineServiceImpl implements MesWmProductSalesLineSe @Transactional(rollbackFor = Exception.class) public void deleteProductSalesLine(Long id) { // 校验存在 - validateProductSalesLineExists(id); + MesWmProductSalesLineDO line = validateProductSalesLineExists(id); + // 校验主单为草稿状态才允许删除行 + productSalesService.validateProductSalesExistsAndDraft(line.getSalesId()); // 级联删除明细 productSalesDetailService.deleteProductSalesDetailByLineId(id); @@ -119,7 +125,8 @@ public class MesWmProductSalesLineServiceImpl implements MesWmProductSalesLineSe return productSalesLineMapper.selectPage(pageReqVO); } - private MesWmProductSalesLineDO validateProductSalesLineExists(Long id) { + @Override + public MesWmProductSalesLineDO validateProductSalesLineExists(Long id) { MesWmProductSalesLineDO line = productSalesLineMapper.selectById(id); if (line == null) { throw exception(WM_PRODUCT_SALES_LINE_NOT_EXISTS); @@ -139,6 +146,60 @@ public class MesWmProductSalesLineServiceImpl implements MesWmProductSalesLineSe reqVO.setBatchId(batch != null ? batch.getId() : null); } + /** + * 校验保存时的关联数据 + */ + private void validateLineSaveData(MesWmProductSalesLineSaveReqVO reqVO) { + // 校验主单存在且为草稿状态 + MesWmProductSalesDO sales = productSalesService.validateProductSalesExistsAndDraft(reqVO.getSalesId()); + // 校验物料存在 + itemService.validateItemExistsAndEnable(reqVO.getItemId()); + // 校验关联发货通知单行(存在性 + 归属 + 字段一致性) + validateSalesNoticeLine(sales, reqVO); + // 根据 batchCode 解析 batchId + fillBatchId(reqVO); + } + + /** + * 校验发货通知单行 + * + * @param sales 出库单 + * @param reqVO 出库行请求 + */ + private void validateSalesNoticeLine(MesWmProductSalesDO sales, MesWmProductSalesLineSaveReqVO reqVO) { + Long noticeLineId = reqVO.getNoticeLineId(); + // 情况一:如果出库单关联了发货通知单,则必须关联发货通知单行 + if (sales.getNoticeId() != null) { + if (noticeLineId == null) { + throw exception(WM_PRODUCT_SALES_LINE_SALES_NOTICE_LINE_REQUIRED); + } + MesWmSalesNoticeLineDO noticeLine = salesNoticeLineService.validateSalesNoticeLineExists( + noticeLineId, sales.getNoticeId()); + // 校验关键字段一致性:物料、数量、批次号、OQC 检验标识 + if (ObjUtil.notEqual(reqVO.getItemId(), noticeLine.getItemId())) { + throw exception(WM_PRODUCT_SALES_LINE_NOTICE_LINE_ITEM_MISMATCH); + } + if (noticeLine.getQuantity() != null && reqVO.getQuantity() != null + && reqVO.getQuantity().compareTo(noticeLine.getQuantity()) != 0) { + throw exception(WM_PRODUCT_SALES_LINE_NOTICE_LINE_QUANTITY_MISMATCH); + } + if (StrUtil.isNotBlank(noticeLine.getBatchCode()) + && ObjUtil.notEqual(reqVO.getBatchCode(), noticeLine.getBatchCode())) { + throw exception(WM_PRODUCT_SALES_LINE_NOTICE_LINE_BATCH_MISMATCH); + } + if (noticeLine.getOqcCheckFlag() != null + && ObjUtil.notEqual(reqVO.getOqcCheckFlag(), noticeLine.getOqcCheckFlag())) { + throw exception(WM_PRODUCT_SALES_LINE_NOTICE_LINE_OQC_MISMATCH); + } + return; + } + + // 情况二:如果出库单没有关联发货通知单,则不允许关联发货通知单行 + if (noticeLineId != null) { + throw exception(WM_PRODUCT_SALES_LINE_SALES_NOTICE_LINE_NOT_ALLOWED); + } + } + @Override @Transactional(rollbackFor = Exception.class) public void updateProductSalesLineWhenOqcFinish(Long id, Long oqcId, Integer checkResult) { diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesService.java index 64a3d1ea5..3f24a8e52 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesService.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesService.java @@ -116,4 +116,13 @@ public interface MesWmProductSalesService { */ List getProductSalesListByClientId(Long clientId); + /** + * 校验销售出库单存在且为草稿状态 + * + * @param id 编号 + * @return 销售出库单 + */ + MesWmProductSalesDO validateProductSalesExistsAndDraft(Long id); + } + diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesServiceImpl.java index e92a46ef1..d45aa41c0 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/productsales/MesWmProductSalesServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/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; @@ -46,13 +49,12 @@ public class MesWmProductSalesServiceImpl implements MesWmProductSalesService { @Resource private MesWmProductSalesLineService productSalesLineService; - @Resource private MesWmProductSalesDetailService productSalesDetailService; - @Resource private MesMdClientService clientService; - + @Resource + private MesWmSalesNoticeService salesNoticeService; @Resource private MesWmTransactionService wmTransactionService; @@ -218,7 +220,7 @@ public class MesWmProductSalesServiceImpl implements MesWmProductSalesService { wmTransactionService.createTransactionList(convertList(details, detail -> new MesWmTransactionSaveReqDTO() .setType(MesWmTransactionTypeEnum.OUT.getType()).setItemId(detail.getItemId()) .setQuantity(detail.getQuantity().negate()) // 出库数量为负数 - .setBatchId(detail.getBatchId()) + .setBatchId(detail.getBatchId()).setBatchCode(detail.getBatchCode()) .setWarehouseId(detail.getWarehouseId()).setLocationId(detail.getLocationId()).setAreaId(detail.getAreaId()) .setBizType(MesBizTypeConstants.WM_PRODUCT_SALES).setBizId(sales.getId()) .setBizCode(sales.getCode()).setBizLineId(detail.getLineId()))); @@ -261,7 +263,17 @@ public class MesWmProductSalesServiceImpl implements MesWmProductSalesService { // 校验编码唯一 validateCodeUnique(id, reqVO.getCode()); // 校验客户存在 - clientService.validateClientExists(reqVO.getClientId()); + clientService.validateClientExistsAndEnable(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) { @@ -275,7 +287,8 @@ public class MesWmProductSalesServiceImpl implements MesWmProductSalesService { /** * 校验销售出库单存在且为草稿状态 */ - private MesWmProductSalesDO validateProductSalesExistsAndDraft(Long id) { + @Override + public MesWmProductSalesDO validateProductSalesExistsAndDraft(Long id) { MesWmProductSalesDO sales = validateProductSalesExists(id); if (ObjUtil.notEqual(MesWmProductSalesStatusEnum.PREPARE.getStatus(), sales.getStatus())) { throw exception(WM_PRODUCT_SALES_NOT_PREPARE); diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueDetailServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueDetailServiceImpl.java index f0a8781d1..885df105c 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueDetailServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/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/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueLineServiceImpl.java index 81449acb1..60ef86551 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueLineServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueLineServiceImpl.java @@ -117,7 +117,7 @@ public class MesWmReturnIssueLineServiceImpl implements MesWmReturnIssueLineServ // 校验父数据存在 + 草稿状态 MesWmReturnIssueDO issue = issueService.validateReturnIssueExistsAndPrepare(reqVO.getIssueId()); // 校验物料存在 - itemService.validateItemExists(reqVO.getItemId()); + itemService.validateItemExistsAndEnable(reqVO.getItemId()); return issue; } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueServiceImpl.java index 17b197085..3269ae7db 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnissue/MesWmReturnIssueServiceImpl.java @@ -168,7 +168,7 @@ public class MesWmReturnIssueServiceImpl implements MesWmReturnIssueService { MesWmReturnIssueDetailDO::getQuantity, BigDecimal::add, BigDecimal.ZERO); // 对比行数量与明细总数量,不满足直接抛出 if (line.getQuantity().compareTo(totalDetailQuantity) > 0) { - MesMdItemDO item = itemService.validateItemExists(line.getItemId()); + MesMdItemDO item = itemService.validateItemExistsAndEnable(line.getItemId()); throw exception(WM_RETURN_ISSUE_DETAIL_QUANTITY_MISMATCH, item.getCode() + " " + item.getName() + " 未完成上架"); } @@ -289,9 +289,9 @@ public class MesWmReturnIssueServiceImpl implements MesWmReturnIssueService { */ private void validateReturnIssueSaveData(MesWmReturnIssueSaveReqVO reqVO) { validateCodeUnique(reqVO.getId(), reqVO.getCode()); - workOrderService.validateWorkOrderExists(reqVO.getWorkOrderId()); + workOrderService.validateWorkOrderConfirmed(reqVO.getWorkOrderId()); if (reqVO.getWorkstationId() != null) { - workstationService.validateWorkstationExists(reqVO.getWorkstationId()); + workstationService.validateWorkstationExistsAndEnable(reqVO.getWorkstationId()); } } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesDetailServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesDetailServiceImpl.java index cce30639b..0c649685f 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesDetailServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesDetailServiceImpl.java @@ -1,14 +1,17 @@ package cn.iocoder.yudao.module.mes.service.wm.returnsales; import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.StrUtil; 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.returnsales.vo.detail.MesWmReturnSalesDetailSaveReqVO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesDetailDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesLineDO; import cn.iocoder.yudao.module.mes.dal.mysql.wm.returnsales.MesWmReturnSalesDetailMapper; import cn.iocoder.yudao.module.mes.enums.wm.MesWmReturnSalesStatusEnum; +import cn.iocoder.yudao.module.mes.service.wm.batch.MesWmBatchService; import cn.iocoder.yudao.module.mes.service.wm.materialstock.MesWmMaterialStockService; import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; import jakarta.annotation.Resource; @@ -40,16 +43,17 @@ public class MesWmReturnSalesDetailServiceImpl implements MesWmReturnSalesDetail @Resource @Lazy private MesWmReturnSalesService returnSalesService; - @Resource private MesWmWarehouseAreaService warehouseAreaService; - + @Resource + private MesWmBatchService batchService; @Resource @Lazy private MesWmMaterialStockService materialStockService; @Override public Long createReturnSalesDetail(MesWmReturnSalesDetailSaveReqVO createReqVO) { + // 校验保存数据 validateReturnSalesDetailSaveData(createReqVO); // 插入 @@ -62,6 +66,7 @@ public class MesWmReturnSalesDetailServiceImpl implements MesWmReturnSalesDetail public void updateReturnSalesDetail(MesWmReturnSalesDetailSaveReqVO updateReqVO) { // 校验存在 validateReturnSalesDetailExists(updateReqVO.getId()); + // 校验保存数据 validateReturnSalesDetailSaveData(updateReqVO); // 更新 @@ -138,6 +143,9 @@ public class MesWmReturnSalesDetailServiceImpl implements MesWmReturnSalesDetail materialStockService.checkAreaMixingRule(reqVO.getAreaId(), reqVO.getItemId(), reqVO.getBatchId()); // 校验明细总数量不超过行数量(排除自身) validateDetailQuantityNotExceed(reqVO.getLineId(), reqVO.getQuantity(), reqVO.getId(), line); + + // 根据 batchCode 解析 batchId(必须在混放规则校验之前,因为它依赖 batchId) + fillBatchId(reqVO); } /** @@ -162,4 +170,17 @@ public class MesWmReturnSalesDetailServiceImpl implements MesWmReturnSalesDetail } } + /** + * 根据 batchCode 解析并回填 batchId + */ + private void fillBatchId(MesWmReturnSalesDetailSaveReqVO reqVO) { + if (StrUtil.isBlank(reqVO.getBatchCode())) { + return; + } + MesWmBatchDO batch = batchService.getBatchByCode(reqVO.getBatchCode()); + if (batch != null) { + reqVO.setBatchId(batch.getId()); + } + } + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesLineServiceImpl.java index 634b168d3..0aa1fd8e8 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesLineServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesLineServiceImpl.java @@ -8,10 +8,12 @@ import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.line.MesWm import cn.iocoder.yudao.module.mes.controller.admin.wm.returnsales.vo.line.MesWmReturnSalesLineSaveReqVO; import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesLineDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnsales.MesWmReturnSalesDO; import cn.iocoder.yudao.module.mes.dal.mysql.wm.returnsales.MesWmReturnSalesLineMapper; import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum; import cn.iocoder.yudao.module.mes.enums.wm.MesWmReturnSalesStatusEnum; import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.wm.batch.MesWmBatchService; import jakarta.annotation.Resource; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; @@ -43,6 +45,8 @@ public class MesWmReturnSalesLineServiceImpl implements MesWmReturnSalesLineServ @Resource private MesMdItemService itemService; @Resource + private MesWmBatchService batchService; + @Resource @Lazy private MesWmReturnSalesDetailService returnSalesDetailService; @@ -61,7 +65,9 @@ public class MesWmReturnSalesLineServiceImpl implements MesWmReturnSalesLineServ @Override public void updateReturnSalesLine(MesWmReturnSalesLineSaveReqVO updateReqVO) { // 校验存在 - validateReturnSalesLineExists(updateReqVO.getId()); + MesWmReturnSalesLineDO oldLine = validateReturnSalesLineExists(updateReqVO.getId()); + // 固定父单 ID,防止通过接口篡改 + updateReqVO.setReturnId(oldLine.getReturnId()); validateLineSaveData(updateReqVO); // 更新 @@ -78,7 +84,7 @@ public class MesWmReturnSalesLineServiceImpl implements MesWmReturnSalesLineServ // 校验退货单存在 + 草稿状态 returnSalesService.validateReturnSalesExistsAndPrepare(reqVO.getReturnId()); // 校验物料存在 + 批次管理 - validateItemBatchManagement(reqVO.getItemId(), reqVO.getBatchId()); + validateItemBatchManagement(reqVO.getReturnId(), reqVO.getItemId(), reqVO.getBatchId()); } @Override @@ -144,15 +150,22 @@ public class MesWmReturnSalesLineServiceImpl implements MesWmReturnSalesLineServ /** * 校验物料批次管理 * - * @param itemId 物料ID - * @param batchId 批次ID + * @param returnId 退货单ID + * @param itemId 物料ID + * @param batchId 批次ID */ - private void validateItemBatchManagement(Long itemId, Long batchId) { - MesMdItemDO item = itemService.validateItemExists(itemId); + private void validateItemBatchManagement(Long returnId, Long itemId, Long batchId) { + MesMdItemDO item = itemService.validateItemExistsAndEnable(itemId); // 如果物料启用了批次管理,则必须选择批次 if (Boolean.TRUE.equals(item.getBatchFlag()) && batchId == null) { throw exception(MD_ITEM_BATCH_REQUIRED); } + // 校验批次存在且属于当前物料和客户 + if (batchId != null) { + // 从父单获取客户ID,校验批次归属 + MesWmReturnSalesDO returnSales = returnSalesService.validateReturnSalesExistsAndPrepare(returnId); + batchService.validateBatchExists(batchId, itemId, returnSales.getClientId(), null); + } } @Override diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesServiceImpl.java index 62c983196..a110f3e65 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesServiceImpl.java @@ -170,7 +170,7 @@ public class MesWmReturnSalesServiceImpl implements MesWmReturnSalesService { MesWmReturnSalesDetailDO::getQuantity, BigDecimal::add, BigDecimal.ZERO); // 对比行数量与明细总数量,不满足直接抛出 if (line.getQuantity().compareTo(totalDetailQuantity) > 0) { - MesMdItemDO item = itemService.validateItemExists(line.getItemId()); + MesMdItemDO item = itemService.validateItemExistsAndEnable(line.getItemId()); throw exception(WM_RETURN_SALES_DETAIL_QUANTITY_MISMATCH, item.getCode() + " " + item.getName() + " 未完成上架"); } @@ -190,7 +190,7 @@ public class MesWmReturnSalesServiceImpl implements MesWmReturnSalesService { wmTransactionService.createTransactionList(convertList(details, detail -> new MesWmTransactionSaveReqDTO() .setType(MesWmTransactionTypeEnum.IN.getType()).setItemId(detail.getItemId()) .setQuantity(detail.getQuantity()) // 入库数量为正数 - .setBatchId(detail.getBatchId()) + .setBatchId(detail.getBatchId()).setBatchCode(detail.getBatchCode()) .setWarehouseId(detail.getWarehouseId()).setLocationId(detail.getLocationId()).setAreaId(detail.getAreaId()) .setBizType(MesBizTypeConstants.WM_RETURN_SALES).setBizId(returnSales.getId()) .setBizCode(returnSales.getCode()).setBizLineId(detail.getLineId()))); @@ -272,7 +272,7 @@ public class MesWmReturnSalesServiceImpl implements MesWmReturnSalesService { */ private void validateSaveData(MesWmReturnSalesSaveReqVO reqVO) { validateCodeUnique(reqVO.getId(), reqVO.getCode()); - clientService.validateClientExists(reqVO.getClientId()); + clientService.validateClientExistsAndEnable(reqVO.getClientId()); } } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorDetailServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorDetailServiceImpl.java index 91e4b7c68..985e80f94 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorDetailServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/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()); + itemService.validateItemExistsAndEnable(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/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorLineServiceImpl.java index 71b821321..6b70f9277 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorLineServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorLineServiceImpl.java @@ -5,8 +5,10 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo.line.MesWmReturnVendorLinePageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.returnvendor.vo.line.MesWmReturnVendorLineSaveReqVO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnvendor.MesWmReturnVendorLineDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.returnvendor.MesWmReturnVendorDO; import cn.iocoder.yudao.module.mes.dal.mysql.wm.returnvendor.MesWmReturnVendorLineMapper; import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.wm.batch.MesWmBatchService; import jakarta.annotation.Resource; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; @@ -36,6 +38,8 @@ public class MesWmReturnVendorLineServiceImpl implements MesWmReturnVendorLineSe private MesWmReturnVendorDetailService returnVendorDetailService; @Resource private MesMdItemService itemService; + @Resource + private MesWmBatchService batchService; @Override public Long createReturnVendorLine(MesWmReturnVendorLineSaveReqVO createReqVO) { @@ -51,7 +55,9 @@ public class MesWmReturnVendorLineServiceImpl implements MesWmReturnVendorLineSe @Override public void updateReturnVendorLine(MesWmReturnVendorLineSaveReqVO updateReqVO) { // 校验存在 - validateReturnVendorLineExists(updateReqVO.getId()); + MesWmReturnVendorLineDO oldLine = validateReturnVendorLineExists(updateReqVO.getId()); + // 固定父单 ID,防止通过接口篡改 + updateReqVO.setReturnId(oldLine.getReturnId()); // 校验数据 validateReturnVendorLineSaveData(updateReqVO); @@ -105,9 +111,13 @@ public class MesWmReturnVendorLineServiceImpl implements MesWmReturnVendorLineSe private void validateReturnVendorLineSaveData(MesWmReturnVendorLineSaveReqVO reqVO) { // 校验父数据存在且为草稿状态 - returnVendorService.validateReturnVendorExistsAndPrepare(reqVO.getReturnId()); + MesWmReturnVendorDO returnVendor = returnVendorService.validateReturnVendorExistsAndPrepare(reqVO.getReturnId()); // 校验物料存在 - itemService.validateItemExists(reqVO.getItemId()); + itemService.validateItemExistsAndEnable(reqVO.getItemId()); + // 校验批次存在且属于当前物料和供应商 + if (reqVO.getBatchId() != null) { + batchService.validateBatchExists(reqVO.getBatchId(), reqVO.getItemId(), null, returnVendor.getVendorId()); + } } } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorServiceImpl.java index c7ac68ac3..f6a674a3f 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/returnvendor/MesWmReturnVendorServiceImpl.java @@ -217,7 +217,7 @@ public class MesWmReturnVendorServiceImpl implements MesWmReturnVendorService { validateReturnVendorExistsAndPrepare(reqVO.getId()); } // 校验供应商存在 - vendorService.validateVendorExists(reqVO.getVendorId()); + vendorService.validateVendorExistsAndEnable(reqVO.getVendorId()); // 校验编码唯一 validateCodeUnique(reqVO.getId(), reqVO.getCode()); } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeLineService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeLineService.java index 4fc969da6..70aec1d92 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeLineService.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeLineService.java @@ -66,4 +66,21 @@ public interface MesWmSalesNoticeLineService { */ void deleteSalesNoticeLineByNoticeId(Long noticeId); + /** + * 校验发货通知单行存在 + * + * @param id 行编号 + * @return 发货通知单行 + */ + MesWmSalesNoticeLineDO validateSalesNoticeLineExists(Long id); + + /** + * 校验发货通知单行存在,并且属于指定的通知单 + * + * @param lineId 行编号 + * @param noticeId 通知单编号 + * @return 发货通知单行 + */ + MesWmSalesNoticeLineDO validateSalesNoticeLineExists(Long lineId, Long noticeId); + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeLineServiceImpl.java index d71bffbce..04b8c3794 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeLineServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeLineServiceImpl.java @@ -36,10 +36,8 @@ public class MesWmSalesNoticeLineServiceImpl implements MesWmSalesNoticeLineServ @Resource @Lazy private MesWmSalesNoticeService salesNoticeService; - @Resource private MesWmBatchService batchService; - @Resource private MesMdItemService itemService; @@ -100,7 +98,8 @@ public class MesWmSalesNoticeLineServiceImpl implements MesWmSalesNoticeLineServ salesNoticeLineMapper.deleteByNoticeId(noticeId); } - private MesWmSalesNoticeLineDO validateSalesNoticeLineExists(Long id) { + @Override + public MesWmSalesNoticeLineDO validateSalesNoticeLineExists(Long id) { MesWmSalesNoticeLineDO line = salesNoticeLineMapper.selectById(id); if (line == null) { throw exception(WM_SALES_NOTICE_LINE_NOT_EXISTS); @@ -108,12 +107,22 @@ public class MesWmSalesNoticeLineServiceImpl implements MesWmSalesNoticeLineServ return line; } + @Override + public MesWmSalesNoticeLineDO validateSalesNoticeLineExists(Long lineId, Long noticeId) { + MesWmSalesNoticeLineDO line = validateSalesNoticeLineExists(lineId); + // 进一步校验行的 noticeId 与传入的 noticeId 是否匹配 + if (noticeId != null && ObjUtil.notEqual(line.getNoticeId(), noticeId)) { + throw exception(WM_SALES_NOTICE_LINE_NOT_MATCH); + } + return line; + } + private void validateLineSaveData(MesWmSalesNoticeLineSaveReqVO reqVO) { // 校验父单据存在且为草稿状态 validateNoticeStatusDraft(reqVO.getNoticeId()); // 校验物料存在 if (reqVO.getItemId() != null) { - itemService.validateItemExists(reqVO.getItemId()); + itemService.validateItemExistsAndEnable(reqVO.getItemId()); } } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeService.java index b471b57c7..0a1d84070 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeService.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeService.java @@ -39,6 +39,14 @@ public interface MesWmSalesNoticeService { */ void deleteSalesNotice(Long id); + /** + * 校验发货通知单存在 + * + * @param id 编号 + * @return 发货通知单 + */ + MesWmSalesNoticeDO validateSalesNoticeExists(Long id); + /** * 获得发货通知单 * @@ -80,12 +88,4 @@ public interface MesWmSalesNoticeService { return convertMap(getSalesNoticeList(ids), MesWmSalesNoticeDO::getId); } - /** - * 按状态获得发货通知单列表 - * - * @param status 状态 - * @return 发货通知单列表 - */ - List getSalesNoticeListByStatus(Integer status); - } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeServiceImpl.java index 9e82adc9e..30a27776a 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/salesnotice/MesWmSalesNoticeServiceImpl.java @@ -37,7 +37,6 @@ public class MesWmSalesNoticeServiceImpl implements MesWmSalesNoticeService { @Resource private MesWmSalesNoticeLineService salesNoticeLineService; - @Resource private MesMdClientService clientService; @@ -112,14 +111,7 @@ public class MesWmSalesNoticeServiceImpl implements MesWmSalesNoticeService { } @Override - public List getSalesNoticeListByStatus(Integer status) { - if (status == null) { - return salesNoticeMapper.selectList(); - } - return salesNoticeMapper.selectListByStatus(status); - } - - private MesWmSalesNoticeDO validateSalesNoticeExists(Long id) { + public MesWmSalesNoticeDO validateSalesNoticeExists(Long id) { MesWmSalesNoticeDO notice = salesNoticeMapper.selectById(id); if (notice == null) { throw exception(WM_SALES_NOTICE_NOT_EXISTS); @@ -140,15 +132,15 @@ public class MesWmSalesNoticeServiceImpl implements MesWmSalesNoticeService { private void validateSalesNoticeSave(MesWmSalesNoticeSaveReqVO saveReqVO) { // 校验编码唯一 - validateNoticeCodeUnique(saveReqVO.getId(), saveReqVO.getNoticeCode()); + validateNoticeCodeUnique(saveReqVO.getId(), saveReqVO.getCode()); // 校验客户存在 if (saveReqVO.getClientId() != null) { - clientService.validateClientExists(saveReqVO.getClientId()); + clientService.validateClientExistsAndEnable(saveReqVO.getClientId()); } } - private void validateNoticeCodeUnique(Long id, String noticeCode) { - MesWmSalesNoticeDO notice = salesNoticeMapper.selectByNoticeCode(noticeCode); + private void validateNoticeCodeUnique(Long id, String code) { + MesWmSalesNoticeDO notice = salesNoticeMapper.selectByCode(code); if (notice == null) { return; } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/sn/MesWmSnServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/sn/MesWmSnServiceImpl.java index 85288c635..0f9ebedf5 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/sn/MesWmSnServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/sn/MesWmSnServiceImpl.java @@ -9,6 +9,8 @@ import cn.iocoder.yudao.module.mes.dal.dataobject.wm.sn.MesWmSnDO; import cn.iocoder.yudao.module.mes.dal.mysql.wm.sn.MesWmSnMapper; import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodeRuleCodeEnum; import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodeRecordService; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -30,12 +32,24 @@ public class MesWmSnServiceImpl implements MesWmSnService { @Resource private MesWmSnMapper snMapper; + @Resource private MesMdAutoCodeRecordService autoCodeRecordService; + @Resource + private MesMdItemService itemService; + @Resource + private MesProWorkOrderService workOrderService; @Override @Transactional(rollbackFor = Exception.class) public void generateSnCodes(MesWmSnGenerateReqVO reqVO) { + // 校验物料是否存在 + itemService.validateItemExists(reqVO.getItemId()); + // 校验工单是否存在 + if (reqVO.getWorkOrderId() != null) { + workOrderService.validateWorkOrderExists(reqVO.getWorkOrderId()); + } + List sns = new ArrayList<>(reqVO.getCount()); // 生成批次 UUID String uuid = IdUtil.fastSimpleUUID(); @@ -66,4 +80,4 @@ public class MesWmSnServiceImpl implements MesWmSnService { snMapper.deleteByUuid(uuid); } -} +} \ No newline at end of file diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/plan/MesWmStockTakingPlanService.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/plan/MesWmStockTakingPlanService.java index d9076bea8..de2527350 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/plan/MesWmStockTakingPlanService.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/plan/MesWmStockTakingPlanService.java @@ -107,12 +107,4 @@ public interface MesWmStockTakingPlanService { */ PageResult getStockTakingPlanPage(MesWmStockTakingPlanPageReqVO pageReqVO); - /** - * 根据状态获得盘点方案列表。 - * - * @param status 状态 - * @return 盘点方案列表 - */ - List getStockTakingPlanListByStatus(Integer status); - } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/plan/MesWmStockTakingPlanServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/plan/MesWmStockTakingPlanServiceImpl.java index 81f9589a5..335355195 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/plan/MesWmStockTakingPlanServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/stocktaking/plan/MesWmStockTakingPlanServiceImpl.java @@ -34,6 +34,7 @@ public class MesWmStockTakingPlanServiceImpl implements MesWmStockTakingPlanServ @Resource private MesWmStockTakingPlanMapper stockTakingPlanMapper; + @Resource private MesWmStockTakingPlanParamService stockTakingPlanParamService; @@ -121,11 +122,6 @@ public class MesWmStockTakingPlanServiceImpl implements MesWmStockTakingPlanServ return stockTakingPlanMapper.selectPage(pageReqVO); } - @Override - public List getStockTakingPlanListByStatus(Integer status) { - return stockTakingPlanMapper.selectListByStatus(status); - } - private void validatePlanCodeUnique(Long id, String code) { MesWmStockTakingPlanDO plan = stockTakingPlanMapper.selectByCode(code); if (plan == null) { diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/transfer/MesWmTransferLineServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/transfer/MesWmTransferLineServiceImpl.java index 1028839f6..7bc662a5a 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/transfer/MesWmTransferLineServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/transfer/MesWmTransferLineServiceImpl.java @@ -109,19 +109,17 @@ public class MesWmTransferLineServiceImpl implements MesWmTransferLineService { // 校验父数据可编辑 transferService.validateTransferEditable(reqVO.getTransferId()); // 校验产品存在 - itemService.validateItemExists(reqVO.getItemId()); + itemService.validateItemExistsAndEnable(reqVO.getItemId()); // 校验来源仓库、库区、库位的关联关系 warehouseAreaService.validateWarehouseAreaExists(reqVO.getFromWarehouseId(), reqVO.getFromLocationId(), reqVO.getFromAreaId()); // 校验库存记录存在,且转移数量不超过库存数量 - if (reqVO.getMaterialStockId() != null) { - MesWmMaterialStockDO stock = materialStockService.getMaterialStock(reqVO.getMaterialStockId()); - if (stock == null) { - throw exception(WM_MATERIAL_STOCK_NOT_EXISTS); - } - if (stock.getQuantity() != null && reqVO.getQuantity().compareTo(stock.getQuantity()) > 0) { - throw exception(WM_TRANSFER_LINE_QUANTITY_EXCEED_STOCK); - } + MesWmMaterialStockDO stock = materialStockService.getMaterialStock(reqVO.getMaterialStockId()); + if (stock == null) { + throw exception(WM_MATERIAL_STOCK_NOT_EXISTS); + } + if (stock.getQuantity() != null && reqVO.getQuantity().compareTo(stock.getQuantity()) > 0) { + throw exception(WM_TRANSFER_LINE_QUANTITY_EXCEED_STOCK); } } diff --git a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/warehouse/MesWmWarehouseLocationServiceImpl.java b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/warehouse/MesWmWarehouseLocationServiceImpl.java index d2177b06d..b2f76175e 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/warehouse/MesWmWarehouseLocationServiceImpl.java +++ b/yudao-module-mes/yudao-module-mes-server/src/main/java/cn/iocoder/yudao/module/mes/service/wm/warehouse/MesWmWarehouseLocationServiceImpl.java @@ -6,8 +6,8 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.location.MesWmWarehouseLocationPageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.location.MesWmWarehouseLocationSaveReqVO; -import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; import cn.iocoder.yudao.module.mes.dal.mysql.wm.warehouse.MesWmWarehouseLocationMapper; import cn.iocoder.yudao.module.mes.enums.wm.BarcodeBizTypeEnum; import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService; @@ -190,7 +190,6 @@ public class MesWmWarehouseLocationServiceImpl implements MesWmWarehouseLocation // 2.2 自动初始化 MesWmWarehouseLocationDO newLocation = MesWmWarehouseLocationDO.builder() .warehouseId(warehouse.getId()).code(code).name("虚拟线边库区") - .areaStatus(cn.iocoder.yudao.framework.common.enums.CommonStatusEnum.ENABLE.getStatus()) .frozen(false).remark("系统自动初始化的虚拟线边库区") .build(); locationMapper.insert(newLocation); diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/task/MesProTaskMapperTest.java b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/task/MesProTaskMapperTest.java new file mode 100644 index 000000000..60c057094 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/task/MesProTaskMapperTest.java @@ -0,0 +1,280 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.pro.task; + +import cn.hutool.core.collection.ListUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProcessDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.task.MesProTaskDO; +import cn.iocoder.yudao.module.mes.dal.mysql.pro.route.MesProRouteProcessMapper; +import jakarta.annotation.Resource; +import org.junit.jupiter.api.Test; + +import java.math.BigDecimal; +import java.util.List; +import java.util.function.Consumer; + +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * {@link MesProTaskMapper#selectPage(MesProTaskPageReqVO)} 的单元测试 + * + * @author 芋道源码 + */ +public class MesProTaskMapperTest extends BaseDbUnitTest { + + @Resource + private MesProTaskMapper taskMapper; + + @Resource + private MesProRouteProcessMapper routeProcessMapper; + + /** + * 创建 Task 时统一设置 BigDecimal 字段为 2 位小数,避免 H2 decimal(14,2) 精度不匹配 + */ + private MesProTaskDO createTaskPojo(Consumer consumer) { + return randomPojo(MesProTaskDO.class, o -> { + o.setQuantity(new BigDecimal("10.00")); + o.setProducedQuantity(new BigDecimal("5.00")); + o.setQualifyQuantity(new BigDecimal("4.00")); + o.setUnqualifyQuantity(new BigDecimal("1.00")); + o.setChangedQuantity(new BigDecimal("0.00")); + consumer.accept(o); + }); + } + + // ==================== selectPage 基础过滤 ==================== + + @Test + public void testSelectPage_byCode() { + MesProTaskDO matchTask = createTaskPojo(o -> { + o.setCode("PT202501010001"); + o.setStatus(0); + }); + taskMapper.insert(matchTask); + taskMapper.insert(cloneIgnoreId(matchTask, o -> o.setCode("OTHER_CODE"))); + + MesProTaskPageReqVO reqVO = new MesProTaskPageReqVO(); + reqVO.setCode("PT2025"); + PageResult result = taskMapper.selectPage(reqVO); + + assertEquals(1, result.getTotal()); + assertPojoEquals(matchTask, result.getList().get(0)); + } + + @Test + public void testSelectPage_byName() { + MesProTaskDO matchTask = createTaskPojo(o -> { + o.setName("注塑任务-A"); + o.setStatus(0); + }); + taskMapper.insert(matchTask); + taskMapper.insert(cloneIgnoreId(matchTask, o -> o.setName("OTHER_NAME"))); + + MesProTaskPageReqVO reqVO = new MesProTaskPageReqVO(); + reqVO.setName("注塑"); + PageResult result = taskMapper.selectPage(reqVO); + + assertEquals(1, result.getTotal()); + assertPojoEquals(matchTask, result.getList().get(0)); + } + + @Test + public void testSelectPage_byWorkOrderId() { + MesProTaskDO matchTask = createTaskPojo(o -> { + o.setWorkOrderId(100L); + o.setStatus(0); + }); + taskMapper.insert(matchTask); + taskMapper.insert(cloneIgnoreId(matchTask, o -> o.setWorkOrderId(999L))); + + MesProTaskPageReqVO reqVO = new MesProTaskPageReqVO(); + reqVO.setWorkOrderId(100L); + PageResult result = taskMapper.selectPage(reqVO); + + assertEquals(1, result.getTotal()); + assertPojoEquals(matchTask, result.getList().get(0)); + } + + @Test + public void testSelectPage_byStatus() { + MesProTaskDO matchTask = createTaskPojo(o -> o.setStatus(1)); + taskMapper.insert(matchTask); + taskMapper.insert(cloneIgnoreId(matchTask, o -> o.setStatus(2))); + + MesProTaskPageReqVO reqVO = new MesProTaskPageReqVO(); + reqVO.setStatus(1); + PageResult result = taskMapper.selectPage(reqVO); + + assertEquals(1, result.getTotal()); + assertPojoEquals(matchTask, result.getList().get(0)); + } + + @Test + public void testSelectPage_byStatuses() { + MesProTaskDO task1 = createTaskPojo(o -> o.setStatus(1)); + MesProTaskDO task2 = createTaskPojo(o -> o.setStatus(2)); + MesProTaskDO task3 = createTaskPojo(o -> o.setStatus(3)); + taskMapper.insert(task1); + taskMapper.insert(task2); + taskMapper.insert(task3); + + MesProTaskPageReqVO reqVO = new MesProTaskPageReqVO(); + reqVO.setStatuses(ListUtil.of(1, 2)); + PageResult result = taskMapper.selectPage(reqVO); + + assertEquals(2, result.getTotal()); + } + + @Test + public void testSelectPage_noFilter() { + MesProTaskDO task1 = createTaskPojo(o -> o.setStatus(0)); + MesProTaskDO task2 = createTaskPojo(o -> o.setStatus(1)); + taskMapper.insert(task1); + taskMapper.insert(task2); + + MesProTaskPageReqVO reqVO = new MesProTaskPageReqVO(); + PageResult result = taskMapper.selectPage(reqVO); + + assertEquals(2, result.getTotal()); + } + + // ==================== selectPage + checkFlag (MPJ LEFT JOIN) ==================== + + @Test + public void testSelectPage_checkFlagTrue() { + Long routeId = 10L; + Long processId1 = 100L; + Long processId2 = 200L; + + MesProTaskDO task1 = createTaskPojo(o -> { + o.setRouteId(routeId); + o.setProcessId(processId1); + o.setStatus(0); + }); + MesProTaskDO task2 = createTaskPojo(o -> { + o.setRouteId(routeId); + o.setProcessId(processId2); + o.setStatus(0); + }); + taskMapper.insert(task1); + taskMapper.insert(task2); + + routeProcessMapper.insert(randomPojo(MesProRouteProcessDO.class, o -> { + o.setRouteId(routeId); + o.setProcessId(processId1); + o.setCheckFlag(true); + })); + routeProcessMapper.insert(randomPojo(MesProRouteProcessDO.class, o -> { + o.setRouteId(routeId); + o.setProcessId(processId2); + o.setCheckFlag(false); + })); + + // 查询:checkFlag = true,只返回 task1 + MesProTaskPageReqVO reqVO = new MesProTaskPageReqVO(); + reqVO.setCheckFlag(true); + PageResult result = taskMapper.selectPage(reqVO); + + assertEquals(1, result.getTotal()); + assertPojoEquals(task1, result.getList().get(0)); + } + + @Test + public void testSelectPage_checkFlagFalse() { + Long routeId = 20L; + Long processId1 = 300L; + Long processId2 = 400L; + + MesProTaskDO task1 = createTaskPojo(o -> { + o.setRouteId(routeId); + o.setProcessId(processId1); + o.setStatus(0); + }); + MesProTaskDO task2 = createTaskPojo(o -> { + o.setRouteId(routeId); + o.setProcessId(processId2); + o.setStatus(0); + }); + taskMapper.insert(task1); + taskMapper.insert(task2); + + routeProcessMapper.insert(randomPojo(MesProRouteProcessDO.class, o -> { + o.setRouteId(routeId); + o.setProcessId(processId1); + o.setCheckFlag(true); + })); + routeProcessMapper.insert(randomPojo(MesProRouteProcessDO.class, o -> { + o.setRouteId(routeId); + o.setProcessId(processId2); + o.setCheckFlag(false); + })); + + // 查询:checkFlag = false,只返回 task2 + MesProTaskPageReqVO reqVO = new MesProTaskPageReqVO(); + reqVO.setCheckFlag(false); + PageResult result = taskMapper.selectPage(reqVO); + + assertEquals(1, result.getTotal()); + assertPojoEquals(task2, result.getList().get(0)); + } + + @Test + public void testSelectPage_checkFlagWithOtherFilter() { + Long routeId = 30L; + Long processId = 500L; + + MesProTaskDO taskMatch = createTaskPojo(o -> { + o.setRouteId(routeId); + o.setProcessId(processId); + o.setCode("PT-MATCH-001"); + o.setStatus(0); + }); + MesProTaskDO taskNoMatch = createTaskPojo(o -> { + o.setRouteId(routeId); + o.setProcessId(processId); + o.setCode("OTHER-CODE"); + o.setStatus(0); + }); + taskMapper.insert(taskMatch); + taskMapper.insert(taskNoMatch); + + routeProcessMapper.insert(randomPojo(MesProRouteProcessDO.class, o -> { + o.setRouteId(routeId); + o.setProcessId(processId); + o.setCheckFlag(true); + })); + + // 查询:checkFlag=true 且 code like 'PT-MATCH' + MesProTaskPageReqVO reqVO = new MesProTaskPageReqVO(); + reqVO.setCheckFlag(true); + reqVO.setCode("PT-MATCH"); + PageResult result = taskMapper.selectPage(reqVO); + + assertEquals(1, result.getTotal()); + assertPojoEquals(taskMatch, result.getList().get(0)); + } + + @Test + public void testSelectPage_checkFlagNull_noJoin() { + Long routeId = 40L; + Long processId = 600L; + + MesProTaskDO task = createTaskPojo(o -> { + o.setRouteId(routeId); + o.setProcessId(processId); + o.setStatus(0); + }); + taskMapper.insert(task); + + MesProTaskPageReqVO reqVO = new MesProTaskPageReqVO(); + PageResult result = taskMapper.selectPage(reqVO); + + assertEquals(1, result.getTotal()); + assertPojoEquals(task, result.getList().get(0)); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productsales/MesWmProductSalesDetailMapperTest.java b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productsales/MesWmProductSalesDetailMapperTest.java new file mode 100644 index 000000000..bd080ad66 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/dal/mysql/wm/productsales/MesWmProductSalesDetailMapperTest.java @@ -0,0 +1,220 @@ +package cn.iocoder.yudao.module.mes.dal.mysql.wm.productsales; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productsales.MesWmProductSalesDetailDO; +import jakarta.annotation.Resource; +import org.junit.jupiter.api.Test; + +import java.math.BigDecimal; +import java.util.List; +import java.util.function.Consumer; + +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static org.junit.jupiter.api.Assertions.*; + +/** + * {@link MesWmProductSalesDetailMapper} 的单元测试 + *

+ * 覆盖:selectListByLineId、selectListBySalesId、deleteByLineId、deleteBySalesId + */ +public class MesWmProductSalesDetailMapperTest extends BaseDbUnitTest { + + @Resource + private MesWmProductSalesDetailMapper detailMapper; + + // ==================== 辅助方法 ==================== + + /** + * 创建明细 DO,固定 BigDecimal 精度为 2 位,避免 H2 decimal(14,2) 精度不匹配 + */ + private MesWmProductSalesDetailDO createDetailPojo(Consumer consumer) { + return randomPojo(MesWmProductSalesDetailDO.class, o -> { + o.setQuantity(new BigDecimal("10.00")); + consumer.accept(o); + }); + } + + // ==================== selectListByLineId ==================== + + @Test + public void testSelectListByLineId_match() { + Long lineId = 100L; + MesWmProductSalesDetailDO match = createDetailPojo(o -> { + o.setLineId(lineId); + o.setSalesId(1L); + }); + detailMapper.insert(match); + // 插入另一条不同 lineId 的记录,不应被返回 + detailMapper.insert(cloneIgnoreId(match, o -> o.setLineId(999L))); + + List result = detailMapper.selectListByLineId(lineId); + + assertEquals(1, result.size()); + assertPojoEquals(match, result.get(0)); + } + + @Test + public void testSelectListByLineId_multipleRows() { + Long lineId = 200L; + MesWmProductSalesDetailDO detail1 = createDetailPojo(o -> { + o.setLineId(lineId); + o.setSalesId(2L); + }); + MesWmProductSalesDetailDO detail2 = createDetailPojo(o -> { + o.setLineId(lineId); + o.setSalesId(2L); + }); + detailMapper.insert(detail1); + detailMapper.insert(detail2); + + List result = detailMapper.selectListByLineId(lineId); + + assertEquals(2, result.size()); + } + + @Test + public void testSelectListByLineId_noMatch() { + MesWmProductSalesDetailDO detail = createDetailPojo(o -> { + o.setLineId(300L); + o.setSalesId(3L); + }); + detailMapper.insert(detail); + + List result = detailMapper.selectListByLineId(999L); + + assertTrue(result.isEmpty()); + } + + // ==================== selectListBySalesId ==================== + + @Test + public void testSelectListBySalesId_match() { + Long salesId = 10L; + MesWmProductSalesDetailDO match = createDetailPojo(o -> { + o.setSalesId(salesId); + o.setLineId(1L); + }); + detailMapper.insert(match); + // 插入另一条不同 salesId 的记录 + detailMapper.insert(cloneIgnoreId(match, o -> o.setSalesId(888L))); + + List result = detailMapper.selectListBySalesId(salesId); + + assertEquals(1, result.size()); + assertPojoEquals(match, result.get(0)); + } + + @Test + public void testSelectListBySalesId_multipleRows() { + Long salesId = 20L; + MesWmProductSalesDetailDO detail1 = createDetailPojo(o -> { + o.setSalesId(salesId); + o.setLineId(11L); + }); + MesWmProductSalesDetailDO detail2 = createDetailPojo(o -> { + o.setSalesId(salesId); + o.setLineId(12L); + }); + detailMapper.insert(detail1); + detailMapper.insert(detail2); + + List result = detailMapper.selectListBySalesId(salesId); + + assertEquals(2, result.size()); + } + + @Test + public void testSelectListBySalesId_noMatch() { + MesWmProductSalesDetailDO detail = createDetailPojo(o -> { + o.setSalesId(30L); + o.setLineId(2L); + }); + detailMapper.insert(detail); + + List result = detailMapper.selectListBySalesId(9999L); + + assertTrue(result.isEmpty()); + } + + // ==================== deleteByLineId ==================== + + @Test + public void testDeleteByLineId_deletesOnlyTargetLine() { + Long lineId = 400L; + MesWmProductSalesDetailDO toDelete = createDetailPojo(o -> { + o.setLineId(lineId); + o.setSalesId(4L); + }); + MesWmProductSalesDetailDO toKeep = createDetailPojo(o -> { + o.setLineId(500L); + o.setSalesId(4L); + }); + detailMapper.insert(toDelete); + detailMapper.insert(toKeep); + + detailMapper.deleteByLineId(lineId); + + // lineId=400 的记录已被逻辑删除 + List deletedResult = detailMapper.selectListByLineId(lineId); + assertTrue(deletedResult.isEmpty(), "lineId=400 的记录应被删除"); + + // lineId=500 的记录保留 + List keptResult = detailMapper.selectListByLineId(500L); + assertEquals(1, keptResult.size()); + } + + @Test + public void testDeleteByLineId_multipleRows() { + Long lineId = 600L; + detailMapper.insert(createDetailPojo(o -> { o.setLineId(lineId); o.setSalesId(5L); })); + detailMapper.insert(createDetailPojo(o -> { o.setLineId(lineId); o.setSalesId(5L); })); + + detailMapper.deleteByLineId(lineId); + + List result = detailMapper.selectListByLineId(lineId); + assertTrue(result.isEmpty(), "同 lineId 下的所有记录均应被删除"); + } + + // ==================== deleteBySalesId ==================== + + @Test + public void testDeleteBySalesId_deletesOnlyTargetSales() { + Long salesId = 700L; + MesWmProductSalesDetailDO toDelete = createDetailPojo(o -> { + o.setSalesId(salesId); + o.setLineId(6L); + }); + MesWmProductSalesDetailDO toKeep = createDetailPojo(o -> { + o.setSalesId(800L); + o.setLineId(7L); + }); + detailMapper.insert(toDelete); + detailMapper.insert(toKeep); + + detailMapper.deleteBySalesId(salesId); + + // salesId=700 的记录已被逻辑删除 + List deletedResult = detailMapper.selectListBySalesId(salesId); + assertTrue(deletedResult.isEmpty(), "salesId=700 的记录应被删除"); + + // salesId=800 的记录保留 + List keptResult = detailMapper.selectListBySalesId(800L); + assertEquals(1, keptResult.size()); + } + + @Test + public void testDeleteBySalesId_multipleRows() { + Long salesId = 900L; + detailMapper.insert(createDetailPojo(o -> { o.setSalesId(salesId); o.setLineId(8L); })); + detailMapper.insert(createDetailPojo(o -> { o.setSalesId(salesId); o.setLineId(9L); })); + detailMapper.insert(createDetailPojo(o -> { o.setSalesId(salesId); o.setLineId(10L); })); + + detailMapper.deleteBySalesId(salesId); + + List result = detailMapper.selectListBySalesId(salesId); + assertTrue(result.isEmpty(), "同 salesId 下的所有记录均应被删除"); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanServiceImplTest.java b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanServiceImplTest.java new file mode 100644 index 000000000..9f0016e99 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanServiceImplTest.java @@ -0,0 +1,119 @@ +package cn.iocoder.yudao.module.mes.service.cal.plan; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.MesCalPlanSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanDO; +import cn.iocoder.yudao.module.mes.dal.mysql.cal.plan.MesCalPlanMapper; +import cn.iocoder.yudao.module.mes.enums.cal.MesCalPlanStatusEnum; +import cn.iocoder.yudao.module.mes.enums.cal.MesCalShiftMethodEnum; +import cn.iocoder.yudao.module.mes.enums.cal.MesCalShiftTypeEnum; +import cn.iocoder.yudao.module.mes.service.cal.team.MesCalTeamShiftService; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.bean.override.mockito.MockitoBean; + +import jakarta.annotation.Resource; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +/** + * {@link MesCalPlanServiceImpl} 的单元测试 + * + * @author 芋道源码 + */ +@Import(MesCalPlanServiceImpl.class) +public class MesCalPlanServiceImplTest extends BaseDbUnitTest { + + @Resource + private MesCalPlanServiceImpl planService; + + @Resource + private MesCalPlanMapper planMapper; + + @MockitoBean + private MesCalPlanShiftService planShiftService; + @MockitoBean + private MesCalPlanTeamService planTeamService; + @MockitoBean + private MesCalTeamShiftService teamShiftService; + + @Test + public void testCreatePlan_singleShift_addDefaultShift() { + // 准备参数 + MesCalPlanSaveReqVO reqVO = new MesCalPlanSaveReqVO(); + reqVO.setCode("PLAN-SINGLE-001"); + reqVO.setName("单白班默认班次"); + reqVO.setCalendarType(1); + reqVO.setStartDate(LocalDateTime.of(2026, 4, 1, 0, 0)); + reqVO.setEndDate(LocalDateTime.of(2026, 4, 30, 0, 0)); + reqVO.setShiftType(MesCalShiftTypeEnum.SINGLE.getType()); + reqVO.setShiftMethod(MesCalShiftMethodEnum.DAY.getMethod()); + reqVO.setShiftCount(1); + + // 调用 + Long planId = planService.createPlan(reqVO); + + // 断言 1:计划状态为草稿 + MesCalPlanDO plan = planMapper.selectById(planId); + assertEquals(MesCalPlanStatusEnum.PREPARE.getStatus(), plan.getStatus()); + // 断言 2:自动生成默认班次 + verify(planShiftService).addDefaultPlanShift(planId, MesCalShiftTypeEnum.SINGLE.getType()); + } + + @Test + public void testConfirmPlan_syncGenerateTeamShiftRecords() { + // mock 数据:插入一条草稿状态的排班计划 + MesCalPlanDO plan = randomPojo(MesCalPlanDO.class, o -> { + o.setCalendarType(1); + o.setStartDate(LocalDateTime.of(2026, 4, 1, 0, 0)); + o.setEndDate(LocalDateTime.of(2026, 4, 3, 0, 0)); + o.setStatus(MesCalPlanStatusEnum.PREPARE.getStatus()); + o.setShiftType(MesCalShiftTypeEnum.SINGLE.getType()); + o.setShiftMethod(MesCalShiftMethodEnum.DAY.getMethod()); + o.setShiftCount(1); + }); + planMapper.insert(plan); + // mock 方法:班组数量满足要求 + when(planTeamService.getPlanTeamCountByPlanId(plan.getId())).thenReturn(1L); + + // 调用 + planService.confirmPlan(plan.getId()); + + // 断言 1:计划状态更新为已确认 + MesCalPlanDO updatePlan = planMapper.selectById(plan.getId()); + assertEquals(MesCalPlanStatusEnum.CONFIRMED.getStatus(), updatePlan.getStatus()); + // 断言 2:触发生成班组排班记录 + verify(teamShiftService).generateTeamShiftRecords(plan.getId()); + } + + @Test + public void testDeletePlan_notCascadeDeleteTeamShift() { + // mock 数据:插入一条草稿状态的排班计划 + MesCalPlanDO plan = randomPojo(MesCalPlanDO.class, o -> { + o.setCalendarType(1); + o.setStartDate(LocalDateTime.of(2026, 4, 1, 0, 0)); + o.setEndDate(LocalDateTime.of(2026, 4, 3, 0, 0)); + o.setStatus(MesCalPlanStatusEnum.PREPARE.getStatus()); + o.setShiftType(MesCalShiftTypeEnum.SINGLE.getType()); + o.setShiftMethod(MesCalShiftMethodEnum.DAY.getMethod()); + o.setShiftCount(1); + }); + planMapper.insert(plan); + + // 调用 + planService.deletePlan(plan.getId()); + + // 断言 1:计划被删除 + assertNull(planMapper.selectById(plan.getId())); + // 断言 2:级联删除班次和班组关联 + verify(planShiftService).deletePlanShiftByPlanId(plan.getId()); + verify(planTeamService).deleteByPlanId(plan.getId()); + // 断言 3:不级联删除班组排班记录 + verify(teamShiftService, never()).deleteByPlanId(plan.getId()); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanShiftServiceImplTest.java b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanShiftServiceImplTest.java new file mode 100644 index 000000000..da31e70f6 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanShiftServiceImplTest.java @@ -0,0 +1,53 @@ +package cn.iocoder.yudao.module.mes.service.cal.plan; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanShiftDO; +import cn.iocoder.yudao.module.mes.dal.mysql.cal.plan.MesCalPlanShiftMapper; +import cn.iocoder.yudao.module.mes.enums.cal.MesCalShiftTypeEnum; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.bean.override.mockito.MockitoBean; + +import jakarta.annotation.Resource; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * {@link MesCalPlanShiftServiceImpl} 的单元测试 + * + * @author 芋道源码 + */ +@Import(MesCalPlanShiftServiceImpl.class) +public class MesCalPlanShiftServiceImplTest extends BaseDbUnitTest { + + @Resource + private MesCalPlanShiftServiceImpl planShiftService; + + @Resource + private MesCalPlanShiftMapper planShiftMapper; + + @MockitoBean + private MesCalPlanService planService; + + @Test + public void testAddDefaultPlanShift_singleShift_use18Clock() { + // 准备参数 + Long planId = 1001L; + + // 调用 + planShiftService.addDefaultPlanShift(planId, MesCalShiftTypeEnum.SINGLE.getType()); + + // 断言:生成 1 条默认班次(白班 08:00~18:00) + List shifts = planShiftMapper.selectListByPlanId(planId); + assertEquals(1, shifts.size()); + MesCalPlanShiftDO shift = shifts.get(0); + assertEquals(planId, shift.getPlanId()); + assertEquals(1, shift.getSort()); + assertEquals("白班", shift.getName()); + assertEquals("08:00", shift.getStartTime()); + assertEquals("18:00", shift.getEndTime()); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamShiftServiceImplTest.java b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamShiftServiceImplTest.java new file mode 100644 index 000000000..9f89dd075 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamShiftServiceImplTest.java @@ -0,0 +1,108 @@ +package cn.iocoder.yudao.module.mes.service.cal.team; + +import cn.hutool.core.collection.ListUtil; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanShiftDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanTeamDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamShiftDO; +import cn.iocoder.yudao.module.mes.dal.mysql.cal.team.MesCalTeamShiftMapper; +import cn.iocoder.yudao.module.mes.enums.cal.MesCalShiftMethodEnum; +import cn.iocoder.yudao.module.mes.enums.cal.MesCalShiftTypeEnum; +import cn.iocoder.yudao.module.mes.service.cal.plan.MesCalPlanService; +import cn.iocoder.yudao.module.mes.service.cal.plan.MesCalPlanShiftService; +import cn.iocoder.yudao.module.mes.service.cal.plan.MesCalPlanTeamService; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.bean.override.mockito.MockitoBean; + +import jakarta.annotation.Resource; + +import java.time.LocalDateTime; +import java.util.Comparator; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +/** + * {@link MesCalTeamShiftServiceImpl} 的单元测试 + * + * @author 芋道源码 + */ +@Import(MesCalTeamShiftServiceImpl.class) +public class MesCalTeamShiftServiceImplTest extends BaseDbUnitTest { + + @Resource + private MesCalTeamShiftServiceImpl teamShiftService; + + @Resource + private MesCalTeamShiftMapper teamShiftMapper; + + @MockitoBean + private MesCalPlanService planService; + @MockitoBean + private MesCalPlanShiftService planShiftService; + @MockitoBean + private MesCalPlanTeamService planTeamService; + + @Test + public void testGenerateTeamShiftRecords_threeShift_rotateThreeStates() { + // 准备参数 + Long planId = 3001L; + // mock 方法:排班计划(三班倒、按天轮班、3 天) + MesCalPlanDO plan = MesCalPlanDO.builder() + .id(planId) + .code("PLAN-THREE-001") + .name("三班倒轮转") + .calendarType(1) + .startDate(LocalDateTime.of(2026, 4, 1, 0, 0)) + .endDate(LocalDateTime.of(2026, 4, 3, 0, 0)) + .shiftType(MesCalShiftTypeEnum.THREE.getType()) + .shiftMethod(MesCalShiftMethodEnum.DAY.getMethod()) + .shiftCount(1) + .build(); + List shifts = ListUtil.of( + MesCalPlanShiftDO.builder().id(11L).planId(planId).sort(1).name("白班").startTime("08:00").endTime("16:00").build(), + MesCalPlanShiftDO.builder().id(12L).planId(planId).sort(2).name("中班").startTime("16:00").endTime("00:00").build(), + MesCalPlanShiftDO.builder().id(13L).planId(planId).sort(3).name("夜班").startTime("00:00").endTime("08:00").build() + ); + List teams = ListUtil.of( + MesCalPlanTeamDO.builder().id(21L).planId(planId).teamId(101L).build(), + MesCalPlanTeamDO.builder().id(22L).planId(planId).teamId(102L).build(), + MesCalPlanTeamDO.builder().id(23L).planId(planId).teamId(103L).build() + ); + when(planService.getPlan(planId)).thenReturn(plan); + when(planShiftService.getPlanShiftListByPlanId(planId)).thenReturn(shifts); + when(planTeamService.getPlanTeamListByPlanId(planId)).thenReturn(teams); + + // 调用 + teamShiftService.generateTeamShiftRecords(planId); + + // 断言:3 天 × 3 班次 = 9 条排班记录,班组按天轮转 + List records = teamShiftMapper.selectListByPlanId(planId); + records.sort(Comparator.comparing(MesCalTeamShiftDO::getDay).thenComparing(MesCalTeamShiftDO::getSort)); + assertEquals(9, records.size()); + // 断言:第 1 天(shiftIndex=0):A 白班、B 中班、C 夜班 + assertRecord(records.get(0), LocalDateTime.of(2026, 4, 1, 0, 0), 1, 101L, 11L); + assertRecord(records.get(1), LocalDateTime.of(2026, 4, 1, 0, 0), 2, 102L, 12L); + assertRecord(records.get(2), LocalDateTime.of(2026, 4, 1, 0, 0), 3, 103L, 13L); + // 断言:第 2 天(shiftIndex=1):C 白班、A 中班、B 夜班 + assertRecord(records.get(3), LocalDateTime.of(2026, 4, 2, 0, 0), 1, 103L, 11L); + assertRecord(records.get(4), LocalDateTime.of(2026, 4, 2, 0, 0), 2, 101L, 12L); + assertRecord(records.get(5), LocalDateTime.of(2026, 4, 2, 0, 0), 3, 102L, 13L); + // 断言:第 3 天(shiftIndex=2):B 白班、C 中班、A 夜班 + assertRecord(records.get(6), LocalDateTime.of(2026, 4, 3, 0, 0), 1, 102L, 11L); + assertRecord(records.get(7), LocalDateTime.of(2026, 4, 3, 0, 0), 2, 103L, 12L); + assertRecord(records.get(8), LocalDateTime.of(2026, 4, 3, 0, 0), 3, 101L, 13L); + } + + private static void assertRecord(MesCalTeamShiftDO actual, LocalDateTime day, Integer sort, + Long teamId, Long shiftId) { + assertEquals(day, actual.getDay()); + assertEquals(sort, actual.getSort()); + assertEquals(teamId, actual.getTeamId()); + assertEquals(shiftId, actual.getShiftId()); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImplTest.java b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImplTest.java index 8c2486915..c7e74c5a1 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImplTest.java +++ b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImplTest.java @@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.mes.service.pro.feedback; import cn.hutool.core.collection.ListUtil; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; 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.wm.productproduce.MesWmProductProduceDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceLineDO; import cn.iocoder.yudao.module.mes.dal.mysql.pro.feedback.MesProFeedbackMapper; import cn.iocoder.yudao.module.mes.enums.pro.MesProFeedbackStatusEnum; @@ -23,8 +25,7 @@ import java.math.BigDecimal; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; /** @@ -61,6 +62,7 @@ public class MesProFeedbackServiceImplTest extends BaseDbUnitTest { // 准备数据:插入一条待检验状态的报工单 Long taskId = randomLongId(); Long workOrderId = randomLongId(); + Long sourceLineId = randomLongId(); MesProFeedbackDO feedback = randomPojo(MesProFeedbackDO.class, o -> { o.setStatus(MesProFeedbackStatusEnum.UNCHECK.getStatus()); o.setTaskId(taskId); @@ -87,13 +89,12 @@ public class MesProFeedbackServiceImplTest extends BaseDbUnitTest { BigDecimal laborScrapQty = BigDecimal.valueOf(5); BigDecimal materialScrapQty = BigDecimal.valueOf(10); BigDecimal otherScrapQty = BigDecimal.valueOf(5); - - feedbackService.updateProFeedbackWhenIpqcFinish(feedback.getId(), + feedbackService.updateProFeedbackWhenIpqcFinish(feedback.getId(), sourceLineId, qualifiedQty, unqualifiedQty, laborScrapQty, materialScrapQty, otherScrapQty); // 断言 1:调用了 splitPendingAndFinishProduce verify(productProduceService).splitPendingAndFinishProduce( - eq(feedback.getId()), eq(qualifiedQty), eq(unqualifiedQty)); + eq(feedback.getId()), eq(sourceLineId), eq(qualifiedQty), eq(unqualifiedQty)); // 断言 2:报工单状态更新为已完成 MesProFeedbackDO updatedFeedback = feedbackMapper.selectById(feedback.getId()); @@ -137,7 +138,7 @@ public class MesProFeedbackServiceImplTest extends BaseDbUnitTest { .thenReturn(ListUtil.of(qualifiedLine)); // 调用 - feedbackService.updateProFeedbackWhenIpqcFinish(feedback.getId(), + feedbackService.updateProFeedbackWhenIpqcFinish(feedback.getId(), randomLongId(), BigDecimal.valueOf(50), BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO); @@ -156,7 +157,7 @@ public class MesProFeedbackServiceImplTest extends BaseDbUnitTest { // 调用不存在的 feedbackId,应该抛异常 Long feedbackId = randomLongId(); assertThrows(Exception.class, () -> - feedbackService.updateProFeedbackWhenIpqcFinish(feedbackId, + feedbackService.updateProFeedbackWhenIpqcFinish(feedbackId, randomLongId(), BigDecimal.TEN, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO)); } @@ -171,12 +172,12 @@ public class MesProFeedbackServiceImplTest extends BaseDbUnitTest { // 调用,应该抛异常 assertThrows(Exception.class, () -> - feedbackService.updateProFeedbackWhenIpqcFinish(feedback.getId(), + feedbackService.updateProFeedbackWhenIpqcFinish(feedback.getId(), randomLongId(), BigDecimal.TEN, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO)); // 断言:不应该调用任何产出单方法 - verify(productProduceService, never()).splitPendingAndFinishProduce(anyLong(), any(), any()); + verify(productProduceService, never()).splitPendingAndFinishProduce(anyLong(), anyLong(), any(), any()); } @Test @@ -189,9 +190,208 @@ public class MesProFeedbackServiceImplTest extends BaseDbUnitTest { // 调用,应该抛异常 assertThrows(Exception.class, () -> - feedbackService.updateProFeedbackWhenIpqcFinish(feedback.getId(), + feedbackService.updateProFeedbackWhenIpqcFinish(feedback.getId(), randomLongId(), BigDecimal.TEN, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO)); } + // ==================== approveFeedback 测试 ==================== + + @Test + public void testApproveFeedback_keyNonCheck_success() { + // 准备数据:关键非质检工序,常规审批 + Long routeId = randomLongId(); + Long processId = randomLongId(); + MesProFeedbackDO feedback = randomPojo(MesProFeedbackDO.class, o -> { + o.setStatus(MesProFeedbackStatusEnum.APPROVING.getStatus()); + o.setFeedbackQuantity(BigDecimal.valueOf(100)); + o.setQualifiedQuantity(BigDecimal.valueOf(80)); + o.setUnqualifiedQuantity(BigDecimal.valueOf(20)); + o.setUncheckQuantity(BigDecimal.ZERO); + o.setRouteId(routeId); + o.setProcessId(processId); + }); + feedbackMapper.insert(feedback); + + // mock: 工序配置 key=true, check=false + MesProRouteProcessDO routeProcess = MesProRouteProcessDO.builder() + .routeId(routeId).processId(processId) + .keyFlag(true).checkFlag(false).build(); + when(routeProcessService.getRouteProcessByRouteIdAndProcessId(routeId, processId)) + .thenReturn(routeProcess); + + // mock: 产品产出单 + MesWmProductProduceDO produce = randomPojo(MesWmProductProduceDO.class); + when(productProduceService.generateProductProduce(any(), eq(false))).thenReturn(produce); + + // mock: 产出行(用于 updateTaskAndWorkOrderByFeedback) + MesWmProductProduceLineDO qualifiedLine = MesWmProductProduceLineDO.builder() + .quantity(BigDecimal.valueOf(80)) + .qualityStatus(MesWmQualityStatusEnum.PASS.getStatus()).build(); + when(produceLineService.getProductProduceLineListByFeedbackId(feedback.getId())) + .thenReturn(ListUtil.of(qualifiedLine)); + + // 调用 + boolean result = feedbackService.approveFeedback(feedback.getId()); + + // 断言 1:返回 true(已完成) + assertTrue(result); + + // 断言 2:状态为已完成,uncheckQuantity 清零 + MesProFeedbackDO updated = feedbackMapper.selectById(feedback.getId()); + assertEquals(MesProFeedbackStatusEnum.FINISHED.getStatus(), updated.getStatus()); + assertEquals(0, BigDecimal.ZERO.compareTo(updated.getUncheckQuantity())); + + // 断言 3:调用了产出单生成 + 入库 + 任务/工单更新 + verify(productProduceService).generateProductProduce(any(), eq(false)); + verify(productProduceService).finishProductProduce(produce.getId()); + verify(taskService).updateProducedQuantity(eq(feedback.getTaskId()), + any(BigDecimal.class), any(BigDecimal.class), any(BigDecimal.class)); + verify(workOrderService).updateProducedQuantity(eq(feedback.getWorkOrderId()), + any(BigDecimal.class)); + } + + @Test + public void testApproveFeedback_keyCheck_enterUncheck() { + // 准备数据:关键质检工序,应进入待检验 + Long routeId = randomLongId(); + Long processId = randomLongId(); + MesProFeedbackDO feedback = randomPojo(MesProFeedbackDO.class, o -> { + o.setStatus(MesProFeedbackStatusEnum.APPROVING.getStatus()); + o.setFeedbackQuantity(BigDecimal.valueOf(50)); + o.setUncheckQuantity(BigDecimal.valueOf(50)); // 质检工序 uncheckQuantity > 0 + o.setRouteId(routeId); + o.setProcessId(processId); + }); + feedbackMapper.insert(feedback); + + // mock: key=true, check=true + MesProRouteProcessDO routeProcess = MesProRouteProcessDO.builder() + .routeId(routeId).processId(processId) + .keyFlag(true).checkFlag(true).build(); + when(routeProcessService.getRouteProcessByRouteIdAndProcessId(routeId, processId)) + .thenReturn(routeProcess); + + // 调用 + boolean result = feedbackService.approveFeedback(feedback.getId()); + + // 断言 1:返回 false(待检验) + assertFalse(result); + + // 断言 2:状态为待检验 + MesProFeedbackDO updated = feedbackMapper.selectById(feedback.getId()); + assertEquals(MesProFeedbackStatusEnum.UNCHECK.getStatus(), updated.getStatus()); + + // 断言 3:生成了待检产出单,但没有 finishProductProduce + verify(productProduceService).generateProductProduce(any(), eq(true)); + verify(productProduceService, never()).finishProductProduce(anyLong()); + + // 断言 4:没有更新任务/工单数量(等 IPQC 回调) + verify(taskService, never()).updateProducedQuantity(anyLong(), any(), any(), any()); + verify(workOrderService, never()).updateProducedQuantity(anyLong(), any()); + } + + @Test + public void testApproveFeedback_nonKey_directFinish() { + // 准备数据:非关键工序,直接完结 + Long routeId = randomLongId(); + Long processId = randomLongId(); + MesProFeedbackDO feedback = randomPojo(MesProFeedbackDO.class, o -> { + o.setStatus(MesProFeedbackStatusEnum.APPROVING.getStatus()); + o.setFeedbackQuantity(BigDecimal.valueOf(30)); + o.setUncheckQuantity(BigDecimal.ZERO); + o.setRouteId(routeId); + o.setProcessId(processId); + }); + feedbackMapper.insert(feedback); + + // mock: key=false, check=false + MesProRouteProcessDO routeProcess = MesProRouteProcessDO.builder() + .routeId(routeId).processId(processId) + .keyFlag(false).checkFlag(false).build(); + when(routeProcessService.getRouteProcessByRouteIdAndProcessId(routeId, processId)) + .thenReturn(routeProcess); + + // 调用 + boolean result = feedbackService.approveFeedback(feedback.getId()); + + // 断言 1:返回 true(已完成) + assertTrue(result); + + // 断言 2:状态为已完成 + MesProFeedbackDO updated = feedbackMapper.selectById(feedback.getId()); + assertEquals(MesProFeedbackStatusEnum.FINISHED.getStatus(), updated.getStatus()); + + // 断言 3:不生成产出单,不更新任务/工单 + verify(productProduceService, never()).generateProductProduce(any(), anyBoolean()); + verify(taskService, never()).updateProducedQuantity(anyLong(), any(), any(), any()); + } + + @Test + public void testApproveFeedback_nonCheck_uncheckQuantityReject() { + // 准备数据:非质检工序,但 uncheckQuantity > 0(异常数据),应被拦截 + Long routeId = randomLongId(); + Long processId = randomLongId(); + MesProFeedbackDO feedback = randomPojo(MesProFeedbackDO.class, o -> { + o.setStatus(MesProFeedbackStatusEnum.APPROVING.getStatus()); + o.setFeedbackQuantity(BigDecimal.valueOf(10)); + o.setUncheckQuantity(BigDecimal.valueOf(10)); // 非质检工序不应有待检数量 + o.setRouteId(routeId); + o.setProcessId(processId); + }); + feedbackMapper.insert(feedback); + + // mock: key=true, check=false(非质检) + MesProRouteProcessDO routeProcess = MesProRouteProcessDO.builder() + .routeId(routeId).processId(processId) + .keyFlag(true).checkFlag(false).build(); + when(routeProcessService.getRouteProcessByRouteIdAndProcessId(routeId, processId)) + .thenReturn(routeProcess); + + // 调用,应该抛异常 + assertThrows(Exception.class, () -> + feedbackService.approveFeedback(feedback.getId())); + + // 断言:不应该执行任何后续操作 + verify(productProduceService, never()).generateProductProduce(any(), anyBoolean()); + verify(itemConsumeService, never()).generateItemConsume(any()); + } + + @Test + public void testApproveFeedback_nonKeyCheck_directFinishAndCleanUncheck() { + // 准备数据:非关键 + 质检工序(!key+check),uncheckQuantity > 0 + // 应放行(checkFlag=true 不拦截 uncheckQuantity),直接完结并清零 uncheckQuantity + Long routeId = randomLongId(); + Long processId = randomLongId(); + MesProFeedbackDO feedback = randomPojo(MesProFeedbackDO.class, o -> { + o.setStatus(MesProFeedbackStatusEnum.APPROVING.getStatus()); + o.setFeedbackQuantity(BigDecimal.valueOf(20)); + o.setUncheckQuantity(BigDecimal.valueOf(20)); + o.setRouteId(routeId); + o.setProcessId(processId); + }); + feedbackMapper.insert(feedback); + + // mock: key=false, check=true + MesProRouteProcessDO routeProcess = MesProRouteProcessDO.builder() + .routeId(routeId).processId(processId) + .keyFlag(false).checkFlag(true).build(); + when(routeProcessService.getRouteProcessByRouteIdAndProcessId(routeId, processId)) + .thenReturn(routeProcess); + + // 调用 + boolean result = feedbackService.approveFeedback(feedback.getId()); + + // 断言 1:返回 true(直接完成,不走 UNCHECK) + assertTrue(result); + + // 断言 2:状态为已完成,uncheckQuantity 被清零 + MesProFeedbackDO updated = feedbackMapper.selectById(feedback.getId()); + assertEquals(MesProFeedbackStatusEnum.FINISHED.getStatus(), updated.getStatus()); + assertEquals(0, BigDecimal.ZERO.compareTo(updated.getUncheckQuantity())); + + // 断言 3:非关键工序不生成产出单 + verify(productProduceService, never()).generateProductProduce(any(), anyBoolean()); + } + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcIndicatorResultServiceImplTest.java b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcIndicatorResultServiceImplTest.java new file mode 100644 index 000000000..008a90d0a --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcIndicatorResultServiceImplTest.java @@ -0,0 +1,288 @@ +package cn.iocoder.yudao.module.mes.service.qc.indicatorresult; + +import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.map.MapUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult.vo.MesQcIndicatorResultPageReqVO; +import cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult.vo.MesQcIndicatorResultSaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicatorresult.MesQcIndicatorResultDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.iqc.MesQcIqcDO; +import cn.iocoder.yudao.module.mes.dal.mysql.qc.indicatorresult.MesQcIndicatorResultMapper; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcResultValueTypeEnum; +import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum; +import cn.iocoder.yudao.module.mes.service.qc.indicator.MesQcIndicatorService; +import cn.iocoder.yudao.module.mes.service.qc.ipqc.MesQcIpqcService; +import cn.iocoder.yudao.module.mes.service.qc.iqc.MesQcIqcService; +import cn.iocoder.yudao.module.mes.service.qc.oqc.MesQcOqcService; +import cn.iocoder.yudao.module.mes.service.qc.rqc.MesQcRqcService; +import cn.iocoder.yudao.module.system.api.dict.DictDataApi; +import jakarta.annotation.Resource; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.bean.override.mockito.MockitoBean; + +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.ArgumentMatchers.anySet; +import static org.mockito.Mockito.*; + +/** + * {@link MesQcIndicatorResultServiceImpl} 的单元测试 + * + * @author 芋道源码 + */ +@Import(MesQcIndicatorResultServiceImpl.class) +public class MesQcIndicatorResultServiceImplTest extends BaseDbUnitTest { + + @Resource + private MesQcIndicatorResultServiceImpl indicatorResultService; + + @Resource + private MesQcIndicatorResultMapper resultMapper; + + @MockitoBean + private MesQcIndicatorResultDetailService resultDetailService; + @MockitoBean + private MesQcIndicatorService indicatorService; + @MockitoBean + private MesQcIqcService iqcService; + @MockitoBean + private MesQcIpqcService ipqcService; + @MockitoBean + private MesQcOqcService oqcService; + @MockitoBean + private MesQcRqcService rqcService; + @MockitoBean + private DictDataApi dictDataApi; + + @Test + public void testCreateIndicatorResult_success() { + // 准备参数 + MesQcIndicatorResultSaveReqVO reqVO = buildReqVO("plain text value", MesQcResultValueTypeEnum.TEXT.getType()); + // mock 方法 + mockIqcAndIndicator(reqVO, MesQcResultValueTypeEnum.TEXT.getType()); + + // 调用 + Long resultId = indicatorResultService.createIndicatorResult(reqVO); + + // 断言 + assertNotNull(resultId); + MesQcIndicatorResultDO dbResult = resultMapper.selectById(resultId); + assertNotNull(dbResult); + assertEquals(reqVO.getCode(), dbResult.getCode()); + assertEquals(reqVO.getQcId(), dbResult.getQcId()); + assertEquals(reqVO.getQcType(), dbResult.getQcType()); + assertEquals(100L, dbResult.getItemId()); // 从 mock IQC 获取 + verify(resultDetailService).createDetailList(anyList()); + } + + @Test + public void testCreateIndicatorResult_fileValueInvalid() { + // 准备参数 + MesQcIndicatorResultSaveReqVO reqVO = buildReqVO("not-a-url", MesQcResultValueTypeEnum.FILE.getType()); + // mock 方法 + mockIqcAndIndicator(reqVO, MesQcResultValueTypeEnum.FILE.getType()); + + // 调用,并断言异常 + assertServiceException(() -> indicatorResultService.createIndicatorResult(reqVO), + QC_RESULT_VALUE_FORMAT_INVALID, "检测项[检测项A]要求文件 URL,实际值=not-a-url"); + + // 断言:未入库 + assertEquals(0, resultMapper.selectCount()); + verify(resultDetailService, never()).createDetailList(anyList()); + } + + @Test + public void testUpdateIndicatorResult_success() { + // mock 数据 + MesQcIndicatorResultDO dbResult = randomPojo(MesQcIndicatorResultDO.class, o -> { + o.setQcType(MesQcTypeEnum.IQC.getType()); + }); + resultMapper.insert(dbResult); + // 准备参数 + MesQcIndicatorResultSaveReqVO reqVO = buildReqVO("updated text", MesQcResultValueTypeEnum.TEXT.getType()); + reqVO.setId(dbResult.getId()); + // mock 方法 + MesQcIndicatorDO indicator = new MesQcIndicatorDO(); + indicator.setId(reqVO.getItems().get(0).getIndicatorId()); + indicator.setName("检测项A"); + indicator.setResultType(MesQcResultValueTypeEnum.TEXT.getType()); + when(indicatorService.validateIndicatorListExists(anySet())) + .thenReturn(MapUtil.of(indicator.getId(), indicator)); + + // 调用 + indicatorResultService.updateIndicatorResult(reqVO); + + // 断言 + MesQcIndicatorResultDO updatedResult = resultMapper.selectById(dbResult.getId()); + assertEquals(reqVO.getCode(), updatedResult.getCode()); + // qcId/qcType/itemId 不允许改挂,应保持原值 + assertEquals(dbResult.getQcId(), updatedResult.getQcId()); + assertEquals(dbResult.getQcType(), updatedResult.getQcType()); + assertEquals(dbResult.getItemId(), updatedResult.getItemId()); + verify(resultDetailService).createOrUpdateDetailList(anyList()); + } + + @Test + public void testUpdateIndicatorResult_notExists() { + // 准备参数 + MesQcIndicatorResultSaveReqVO reqVO = buildReqVO("text", MesQcResultValueTypeEnum.TEXT.getType()); + reqVO.setId(randomLongId()); + + // 调用,并断言异常 + assertServiceException(() -> indicatorResultService.updateIndicatorResult(reqVO), + QC_RESULT_NOT_EXISTS); + } + + @Test + public void testDeleteIndicatorResult_success() { + // mock 数据 + MesQcIndicatorResultDO dbResult = randomPojo(MesQcIndicatorResultDO.class); + resultMapper.insert(dbResult); + + // 调用 + indicatorResultService.deleteIndicatorResult(dbResult.getId()); + + // 断言 + assertNull(resultMapper.selectById(dbResult.getId())); + verify(resultDetailService).deleteDetailByResultId(dbResult.getId()); + } + + @Test + public void testDeleteIndicatorResult_notExists() { + // 调用,并断言异常 + assertServiceException(() -> indicatorResultService.deleteIndicatorResult(randomLongId()), + QC_RESULT_NOT_EXISTS); + } + + @Test + public void testGetIndicatorResult() { + // mock 数据 + MesQcIndicatorResultDO dbResult = randomPojo(MesQcIndicatorResultDO.class); + resultMapper.insert(dbResult); + + // 调用 + MesQcIndicatorResultDO result = indicatorResultService.getIndicatorResult(dbResult.getId()); + + // 断言 + assertPojoEquals(dbResult, result); + } + + @Test + public void testGetIndicatorResultPage() { + // mock 数据 + MesQcIndicatorResultDO dbResult = randomPojo(MesQcIndicatorResultDO.class, o -> { + o.setQcId(1L); + o.setQcType(MesQcTypeEnum.IQC.getType()); + o.setCode("SPL-001"); + o.setItemId(100L); + }); + resultMapper.insert(dbResult); + // 测试 qcId 不匹配 + resultMapper.insert(cloneIgnoreId(dbResult, o -> o.setQcId(2L))); + // 测试 qcType 不匹配 + resultMapper.insert(cloneIgnoreId(dbResult, o -> o.setQcType(MesQcTypeEnum.IPQC.getType()))); + // 测试 code 不匹配 + resultMapper.insert(cloneIgnoreId(dbResult, o -> o.setCode("SPL-999"))); + // 测试 itemId 不匹配 + resultMapper.insert(cloneIgnoreId(dbResult, o -> o.setItemId(999L))); + // 准备参数 + MesQcIndicatorResultPageReqVO pageReqVO = new MesQcIndicatorResultPageReqVO(); + pageReqVO.setQcId(1L); + pageReqVO.setQcType(MesQcTypeEnum.IQC.getType()); + pageReqVO.setCode("SPL-001"); + pageReqVO.setItemId(100L); + + // 调用 + PageResult pageResult = indicatorResultService.getIndicatorResultPage(pageReqVO); + + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbResult, pageResult.getList().get(0)); + } + + @Test + public void testGetIndicatorResultCountByQcIdAndType() { + // mock 数据 + MesQcIndicatorResultDO result1 = randomPojo(MesQcIndicatorResultDO.class, o -> { + o.setQcId(1L); + o.setQcType(MesQcTypeEnum.IQC.getType()); + }); + resultMapper.insert(result1); + MesQcIndicatorResultDO result2 = randomPojo(MesQcIndicatorResultDO.class, o -> { + o.setQcId(1L); + o.setQcType(MesQcTypeEnum.IQC.getType()); + }); + resultMapper.insert(result2); + // 不匹配 + resultMapper.insert(randomPojo(MesQcIndicatorResultDO.class, o -> { + o.setQcId(2L); + o.setQcType(MesQcTypeEnum.IPQC.getType()); + })); + + // 调用 + Long count = indicatorResultService.getIndicatorResultCountByQcIdAndType(1L, MesQcTypeEnum.IQC.getType()); + + // 断言 + assertEquals(2L, count); + } + + @Test + public void testValidateIndicatorResultExistsByQcIdAndType_success() { + // mock 数据 + resultMapper.insert(randomPojo(MesQcIndicatorResultDO.class, o -> { + o.setQcId(1L); + o.setQcType(MesQcTypeEnum.IQC.getType()); + })); + + // 调用(不抛异常即通过) + indicatorResultService.validateIndicatorResultExistsByQcIdAndType(1L, MesQcTypeEnum.IQC.getType()); + } + + @Test + public void testValidateIndicatorResultExistsByQcIdAndType_notExists() { + // 调用,并断言异常 + assertServiceException( + () -> indicatorResultService.validateIndicatorResultExistsByQcIdAndType(randomLongId(), MesQcTypeEnum.IQC.getType()), + QC_FINISH_INDICATOR_RESULT_REQUIRED); + } + + // ==================== 辅助方法 ==================== + + private void mockIqcAndIndicator(MesQcIndicatorResultSaveReqVO reqVO, Integer resultType) { + MesQcIqcDO iqc = new MesQcIqcDO(); + iqc.setId(reqVO.getQcId()); + iqc.setItemId(100L); + when(iqcService.validateIqcExists(reqVO.getQcId())).thenReturn(iqc); + + MesQcIndicatorDO indicator = new MesQcIndicatorDO(); + indicator.setId(reqVO.getItems().get(0).getIndicatorId()); + indicator.setName("检测项A"); + indicator.setResultType(resultType); + when(indicatorService.validateIndicatorListExists(anySet())) + .thenReturn(MapUtil.of(indicator.getId(), indicator)); + } + + private MesQcIndicatorResultSaveReqVO buildReqVO(String value, Integer resultType) { + MesQcIndicatorResultSaveReqVO.Item item = new MesQcIndicatorResultSaveReqVO.Item(); + item.setIndicatorId(10L); + item.setValue(value); + + MesQcIndicatorResultSaveReqVO reqVO = new MesQcIndicatorResultSaveReqVO(); + reqVO.setCode("SPL-001"); + reqVO.setQcId(1L); + reqVO.setQcType(MesQcTypeEnum.IQC.getType()); + reqVO.setItems(ListUtil.of(item)); + return reqVO; + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImplTest.java b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImplTest.java index 98471d337..b41b2edb8 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImplTest.java +++ b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImplTest.java @@ -1,16 +1,32 @@ package cn.iocoder.yudao.module.mes.service.qc.ipqc; +import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +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.feedback.MesProFeedbackDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProcessDO; +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.qc.ipqc.MesQcIpqcDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateItemDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceLineDO; import cn.iocoder.yudao.module.mes.dal.mysql.qc.ipqc.MesQcIpqcMapper; import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; import cn.iocoder.yudao.module.mes.enums.qc.MesQcStatusEnum; +import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum; import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService; 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.indicatorresult.MesQcIndicatorResultService; import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateItemService; +import cn.iocoder.yudao.module.mes.service.wm.productproduce.MesWmProductProduceLineService; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import jakarta.annotation.Resource; import org.junit.jupiter.api.Test; @@ -21,6 +37,7 @@ import java.math.BigDecimal; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; @@ -54,11 +71,22 @@ public class MesQcIpqcServiceImplTest extends BaseDbUnitTest { private AdminUserApi adminUserApi; @MockitoBean private MesProFeedbackService feedbackService; + @MockitoBean + private MesProRouteProductService routeProductService; + @MockitoBean + private MesProRouteProcessService routeProcessService; + @MockitoBean + private MesProTaskService taskService; + @MockitoBean + private MesQcIndicatorResultService indicatorResultService; + @MockitoBean + private MesWmProductProduceLineService productProduceLineService; @Test public void testFinishIpqc_writeBack_feedback() { // 准备数据:插入一条草稿状态的 IPQC 单,来源为报工单(PRO_FEEDBACK=304) Long sourceDocId = randomLongId(); + Long sourceLineId = randomLongId(); BigDecimal qualifiedQty = BigDecimal.valueOf(80); BigDecimal unqualifiedQty = BigDecimal.valueOf(20); BigDecimal laborScrapQty = BigDecimal.valueOf(5); @@ -70,7 +98,7 @@ public class MesQcIpqcServiceImplTest extends BaseDbUnitTest { o.setCheckResult(1); // 非空,满足 finishIpqc 的校验 o.setSourceDocType(MesBizTypeConstants.PRO_FEEDBACK); o.setSourceDocId(sourceDocId); - o.setSourceLineId(null); // 报工场景下预留不使用 + o.setSourceLineId(sourceLineId); o.setQualifiedQuantity(qualifiedQty); o.setUnqualifiedQuantity(unqualifiedQty); o.setLaborScrapQuantity(laborScrapQty); @@ -86,10 +114,11 @@ public class MesQcIpqcServiceImplTest extends BaseDbUnitTest { MesQcIpqcDO updatedIpqc = ipqcMapper.selectById(ipqc.getId()); assertEquals(MesQcStatusEnum.FINISHED.getStatus(), updatedIpqc.getStatus()); - // 断言 2:调用了 feedbackService.completeFeedbackFromIpqc,传递正确参数 + // 断言 2:调用了 feedbackService,传递 sourceLineId // 注意:数量经过 DB 存取后 scale 可能变化(例如 80 → 80.00),所以用 any() 匹配 verify(feedbackService).updateProFeedbackWhenIpqcFinish( eq(sourceDocId), + eq(sourceLineId), any(BigDecimal.class), any(BigDecimal.class), any(BigDecimal.class), @@ -101,12 +130,13 @@ public class MesQcIpqcServiceImplTest extends BaseDbUnitTest { public void testFinishIpqc_writeBack_feedback_withNullQuantities() { // 准备数据:合格品/不合格品/废品数量为 null 的场景,应该 defaultIfNull 为 0 Long sourceDocId = randomLongId(); + Long sourceLineId = randomLongId(); MesQcIpqcDO ipqc = randomPojo(MesQcIpqcDO.class, o -> { o.setStatus(MesQcStatusEnum.DRAFT.getStatus()); o.setCheckResult(1); o.setSourceDocType(MesBizTypeConstants.PRO_FEEDBACK); o.setSourceDocId(sourceDocId); - o.setSourceLineId(null); + o.setSourceLineId(sourceLineId); o.setQualifiedQuantity(null); o.setUnqualifiedQuantity(null); o.setLaborScrapQuantity(null); @@ -121,6 +151,7 @@ public class MesQcIpqcServiceImplTest extends BaseDbUnitTest { // 断言:所有数量参数都是 BigDecimal.ZERO(defaultIfNull 处理) verify(feedbackService).updateProFeedbackWhenIpqcFinish( eq(sourceDocId), + eq(sourceLineId), eq(BigDecimal.ZERO), eq(BigDecimal.ZERO), eq(BigDecimal.ZERO), @@ -149,7 +180,7 @@ public class MesQcIpqcServiceImplTest extends BaseDbUnitTest { // 断言 2:不应该调用 feedbackService verify(feedbackService, never()).updateProFeedbackWhenIpqcFinish( - anyLong(), any(), any(), any(), any(), any()); + anyLong(), anyLong(), any(), any(), any(), any(), any()); } @Test @@ -211,4 +242,355 @@ public class MesQcIpqcServiceImplTest extends BaseDbUnitTest { assertThrows(Exception.class, () -> ipqcService.finishIpqc(ipqc.getId())); } + // ==================== processId 推导行为测试 ==================== + + /** + * 工位有工序 + 该工序在产品工艺路线中 → processId 应该被设置为工位工序 + */ + @Test + public void testCreateIpqc_processId_workstationHasProcess() { + // 准备参数 + Long workstationId = randomLongId(); + Long workOrderId = randomLongId(); + Long productId = randomLongId(); + Long processId = randomLongId(); + Long routeId = randomLongId(); + Long templateId = randomLongId(); + + MesQcIpqcSaveReqVO reqVO = new MesQcIpqcSaveReqVO(); + reqVO.setCode("IPQC-TEST-001"); + reqVO.setWorkstationId(workstationId); + reqVO.setWorkOrderId(workOrderId); + reqVO.setInspectorUserId(randomLongId()); + + // mock 工位返回有工序 + MesMdWorkstationDO workstation = new MesMdWorkstationDO(); + workstation.setId(workstationId); + workstation.setProcessId(processId); + when(workstationService.validateWorkstationExists(workstationId)).thenReturn(workstation); + // mock 工单 + MesProWorkOrderDO workOrder = new MesProWorkOrderDO(); + workOrder.setId(workOrderId); + workOrder.setProductId(productId); + when(workOrderService.validateWorkOrderExists(workOrderId)).thenReturn(workOrder); + when(workOrderService.validateWorkOrderConfirmed(workOrderId)).thenReturn(workOrder); + // mock 模板匹配 + MesQcTemplateItemDO templateItem = new MesQcTemplateItemDO(); + templateItem.setTemplateId(templateId); + when(templateItemService.getRequiredTemplateByItemIdAndType(eq(productId), anyInt())).thenReturn(templateItem); + // mock 工艺路线 + MesProRouteProductDO routeProduct = new MesProRouteProductDO(); + routeProduct.setRouteId(routeId); + when(routeProductService.getRouteProductByItemId(productId)).thenReturn(routeProduct); + // mock 工序在路线中 + when(routeProcessService.getRouteProcessByRouteIdAndProcessId(routeId, processId)) + .thenReturn(new MesProRouteProcessDO()); + + // 调用 + Long ipqcId = ipqcService.createIpqc(reqVO); + + // 断言:processId 应该是工位工序 + MesQcIpqcDO ipqc = ipqcMapper.selectById(ipqcId); + assertEquals(processId, ipqc.getProcessId()); + } + + /** + * 工位没有工序(processId=null)→ processId 应该留 null(不回退到任务工序) + */ + @Test + public void testCreateIpqc_processId_workstationNoProcess_shouldBeNull() { + // 准备参数 + Long workstationId = randomLongId(); + Long workOrderId = randomLongId(); + Long productId = randomLongId(); + Long taskId = randomLongId(); + Long templateId = randomLongId(); + + MesQcIpqcSaveReqVO reqVO = new MesQcIpqcSaveReqVO(); + reqVO.setCode("IPQC-TEST-002"); + reqVO.setWorkstationId(workstationId); + reqVO.setWorkOrderId(workOrderId); + reqVO.setTaskId(taskId); // 故意传入 taskId,验证不会回退 + reqVO.setInspectorUserId(randomLongId()); + + // mock 工位没有工序 + MesMdWorkstationDO workstation = new MesMdWorkstationDO(); + workstation.setId(workstationId); + workstation.setProcessId(null); // 无工序 + when(workstationService.validateWorkstationExists(workstationId)).thenReturn(workstation); + // mock 工单 + MesProWorkOrderDO workOrder = new MesProWorkOrderDO(); + workOrder.setId(workOrderId); + workOrder.setProductId(productId); + when(workOrderService.validateWorkOrderExists(workOrderId)).thenReturn(workOrder); + when(workOrderService.validateWorkOrderConfirmed(workOrderId)).thenReturn(workOrder); + // mock 任务 + MesProTaskDO task = new MesProTaskDO(); + task.setId(taskId); + task.setWorkOrderId(workOrderId); + task.setWorkstationId(workstationId); + task.setItemId(productId); + when(taskService.validateTaskNotFinished(taskId)).thenReturn(task); + // mock 模板匹配 + MesQcTemplateItemDO templateItem = new MesQcTemplateItemDO(); + templateItem.setTemplateId(templateId); + when(templateItemService.getRequiredTemplateByItemIdAndType(eq(productId), anyInt())).thenReturn(templateItem); + + // 调用 + Long ipqcId = ipqcService.createIpqc(reqVO); + + // 断言:processId 应该是 null,即使传入了 taskId 也不应该回退 + MesQcIpqcDO ipqc = ipqcMapper.selectById(ipqcId); + assertNull(ipqc.getProcessId(), + "工位无工序时 processId 应为 null,不应回退到任务工序"); + // 断言:不应该读取任务的 processId + verify(routeProductService, never()).getRouteProductByItemId(any()); + } + + /** + * 工位有工序但该工序不在产品工艺路线中 → processId 应该留 null + */ + @Test + public void testCreateIpqc_processId_processNotInRoute() { + // 准备参数 + Long workstationId = randomLongId(); + Long workOrderId = randomLongId(); + Long productId = randomLongId(); + Long processId = randomLongId(); + Long routeId = randomLongId(); + Long templateId = randomLongId(); + + MesQcIpqcSaveReqVO reqVO = new MesQcIpqcSaveReqVO(); + reqVO.setCode("IPQC-TEST-003"); + reqVO.setWorkstationId(workstationId); + reqVO.setWorkOrderId(workOrderId); + reqVO.setInspectorUserId(randomLongId()); + + // mock 工位有工序 + MesMdWorkstationDO workstation = new MesMdWorkstationDO(); + workstation.setId(workstationId); + workstation.setProcessId(processId); + when(workstationService.validateWorkstationExists(workstationId)).thenReturn(workstation); + // mock 工单 + MesProWorkOrderDO workOrder = new MesProWorkOrderDO(); + workOrder.setId(workOrderId); + workOrder.setProductId(productId); + when(workOrderService.validateWorkOrderExists(workOrderId)).thenReturn(workOrder); + when(workOrderService.validateWorkOrderConfirmed(workOrderId)).thenReturn(workOrder); + // mock 模板匹配 + MesQcTemplateItemDO templateItem = new MesQcTemplateItemDO(); + templateItem.setTemplateId(templateId); + when(templateItemService.getRequiredTemplateByItemIdAndType(eq(productId), anyInt())).thenReturn(templateItem); + // mock 工艺路线存在 + MesProRouteProductDO routeProduct = new MesProRouteProductDO(); + routeProduct.setRouteId(routeId); + when(routeProductService.getRouteProductByItemId(productId)).thenReturn(routeProduct); + // mock 工序不在路线中 + when(routeProcessService.getRouteProcessByRouteIdAndProcessId(routeId, processId)) + .thenReturn(null); + + // 调用 + Long ipqcId = ipqcService.createIpqc(reqVO); + + // 断言:processId 应该是 null + MesQcIpqcDO ipqc = ipqcMapper.selectById(ipqcId); + assertNull(ipqc.getProcessId()); + } + + // ==================== sourceLineId 校验测试 ==================== + + /** + * sourceDocType=PRO_FEEDBACK 时 sourceLineId 为空 → 创建失败 + */ + @Test + public void testCreateIpqc_sourceLineId_required() { + // 准备参数 + Long workstationId = randomLongId(); + Long workOrderId = randomLongId(); + Long productId = randomLongId(); + Long feedbackId = randomLongId(); + Long templateId = randomLongId(); + + MesQcIpqcSaveReqVO reqVO = new MesQcIpqcSaveReqVO(); + reqVO.setCode("IPQC-SL-001"); + reqVO.setWorkstationId(workstationId); + reqVO.setWorkOrderId(workOrderId); + reqVO.setInspectorUserId(randomLongId()); + reqVO.setSourceDocType(MesBizTypeConstants.PRO_FEEDBACK); + reqVO.setSourceDocId(feedbackId); + reqVO.setSourceLineId(null); // 不传 sourceLineId + + // mock + MesMdWorkstationDO workstation = new MesMdWorkstationDO(); + workstation.setId(workstationId); + workstation.setProcessId(null); + when(workstationService.validateWorkstationExists(workstationId)).thenReturn(workstation); + MesProWorkOrderDO workOrder = new MesProWorkOrderDO(); + workOrder.setId(workOrderId); + workOrder.setProductId(productId); + when(workOrderService.validateWorkOrderExists(workOrderId)).thenReturn(workOrder); + when(workOrderService.validateWorkOrderConfirmed(workOrderId)).thenReturn(workOrder); + MesQcTemplateItemDO templateItem = new MesQcTemplateItemDO(); + templateItem.setTemplateId(templateId); + when(templateItemService.getRequiredTemplateByItemIdAndType(eq(productId), anyInt())).thenReturn(templateItem); + when(feedbackService.validateFeedbackExists(feedbackId)).thenReturn(new MesProFeedbackDO()); + + // 调用,断言异常 + ServiceException ex = assertThrows(ServiceException.class, () -> ipqcService.createIpqc(reqVO)); + assertEquals(QC_IPQC_SOURCE_LINE_REQUIRED.getCode(), ex.getCode()); + } + + /** + * sourceLineId 不属于该报工的产出行 → 创建失败 + */ + @Test + public void testCreateIpqc_sourceLineId_notBelong() { + // 准备参数 + Long workstationId = randomLongId(); + Long workOrderId = randomLongId(); + Long productId = randomLongId(); + Long feedbackId = randomLongId(); + Long sourceLineId = randomLongId(); + Long templateId = randomLongId(); + + MesQcIpqcSaveReqVO reqVO = new MesQcIpqcSaveReqVO(); + reqVO.setCode("IPQC-SL-002"); + reqVO.setWorkstationId(workstationId); + reqVO.setWorkOrderId(workOrderId); + reqVO.setInspectorUserId(randomLongId()); + reqVO.setSourceDocType(MesBizTypeConstants.PRO_FEEDBACK); + reqVO.setSourceDocId(feedbackId); + reqVO.setSourceLineId(sourceLineId); + + // mock + MesMdWorkstationDO workstation = new MesMdWorkstationDO(); + workstation.setId(workstationId); + workstation.setProcessId(null); + when(workstationService.validateWorkstationExists(workstationId)).thenReturn(workstation); + MesProWorkOrderDO workOrder = new MesProWorkOrderDO(); + workOrder.setId(workOrderId); + workOrder.setProductId(productId); + when(workOrderService.validateWorkOrderExists(workOrderId)).thenReturn(workOrder); + when(workOrderService.validateWorkOrderConfirmed(workOrderId)).thenReturn(workOrder); + MesQcTemplateItemDO templateItem = new MesQcTemplateItemDO(); + templateItem.setTemplateId(templateId); + when(templateItemService.getRequiredTemplateByItemIdAndType(eq(productId), anyInt())).thenReturn(templateItem); + when(feedbackService.validateFeedbackExists(feedbackId)).thenReturn(new MesProFeedbackDO()); + // mock:产出行存在但 feedbackId 不匹配 + MesWmProductProduceLineDO line = new MesWmProductProduceLineDO(); + line.setId(sourceLineId); + line.setFeedbackId(randomLongId()); // 不同的 feedbackId + line.setQualityStatus(MesWmQualityStatusEnum.PENDING.getStatus()); + when(productProduceLineService.validateProductProduceLineExists(sourceLineId)).thenReturn(line); + + // 调用,断言异常 + ServiceException ex = assertThrows(ServiceException.class, () -> ipqcService.createIpqc(reqVO)); + assertEquals(QC_IPQC_SOURCE_LINE_NOT_BELONG.getCode(), ex.getCode()); + } + + /** + * sourceLineId 对应的产出行不是待检验状态 → 创建失败 + */ + @Test + public void testCreateIpqc_sourceLineId_notPending() { + // 准备参数 + Long workstationId = randomLongId(); + Long workOrderId = randomLongId(); + Long productId = randomLongId(); + Long feedbackId = randomLongId(); + Long sourceLineId = randomLongId(); + Long templateId = randomLongId(); + + MesQcIpqcSaveReqVO reqVO = new MesQcIpqcSaveReqVO(); + reqVO.setCode("IPQC-SL-003"); + reqVO.setWorkstationId(workstationId); + reqVO.setWorkOrderId(workOrderId); + reqVO.setInspectorUserId(randomLongId()); + reqVO.setSourceDocType(MesBizTypeConstants.PRO_FEEDBACK); + reqVO.setSourceDocId(feedbackId); + reqVO.setSourceLineId(sourceLineId); + + // mock + MesMdWorkstationDO workstation = new MesMdWorkstationDO(); + workstation.setId(workstationId); + workstation.setProcessId(null); + when(workstationService.validateWorkstationExists(workstationId)).thenReturn(workstation); + MesProWorkOrderDO workOrder = new MesProWorkOrderDO(); + workOrder.setId(workOrderId); + workOrder.setProductId(productId); + when(workOrderService.validateWorkOrderExists(workOrderId)).thenReturn(workOrder); + when(workOrderService.validateWorkOrderConfirmed(workOrderId)).thenReturn(workOrder); + MesQcTemplateItemDO templateItem = new MesQcTemplateItemDO(); + templateItem.setTemplateId(templateId); + when(templateItemService.getRequiredTemplateByItemIdAndType(eq(productId), anyInt())).thenReturn(templateItem); + when(feedbackService.validateFeedbackExists(feedbackId)).thenReturn(new MesProFeedbackDO()); + // mock:产出行存在且归属正确,但不是 PENDING 状态 + MesWmProductProduceLineDO line = new MesWmProductProduceLineDO(); + line.setId(sourceLineId); + line.setFeedbackId(feedbackId); + line.setQualityStatus(MesWmQualityStatusEnum.PASS.getStatus()); // 已合格,非待检 + when(productProduceLineService.validateProductProduceLineExists(sourceLineId)).thenReturn(line); + + // 调用,断言异常 + ServiceException ex = assertThrows(ServiceException.class, () -> ipqcService.createIpqc(reqVO)); + assertEquals(QC_IPQC_SOURCE_LINE_NOT_PENDING.getCode(), ex.getCode()); + } + + /** + * sourceLineId 校验全部通过 → 创建成功 + */ + @Test + public void testCreateIpqc_sourceLineId_success() { + // 准备参数 + Long workstationId = randomLongId(); + Long workOrderId = randomLongId(); + Long productId = randomLongId(); + Long feedbackId = randomLongId(); + Long sourceLineId = randomLongId(); + Long templateId = randomLongId(); + + MesQcIpqcSaveReqVO reqVO = new MesQcIpqcSaveReqVO(); + reqVO.setCode("IPQC-SL-004"); + reqVO.setWorkstationId(workstationId); + reqVO.setWorkOrderId(workOrderId); + reqVO.setInspectorUserId(randomLongId()); + reqVO.setSourceDocType(MesBizTypeConstants.PRO_FEEDBACK); + reqVO.setSourceDocId(feedbackId); + reqVO.setSourceLineId(sourceLineId); + + // mock + MesMdWorkstationDO workstation = new MesMdWorkstationDO(); + workstation.setId(workstationId); + workstation.setProcessId(null); + when(workstationService.validateWorkstationExists(workstationId)).thenReturn(workstation); + MesProWorkOrderDO workOrder = new MesProWorkOrderDO(); + workOrder.setId(workOrderId); + workOrder.setProductId(productId); + when(workOrderService.validateWorkOrderExists(workOrderId)).thenReturn(workOrder); + when(workOrderService.validateWorkOrderConfirmed(workOrderId)).thenReturn(workOrder); + MesQcTemplateItemDO templateItem = new MesQcTemplateItemDO(); + templateItem.setTemplateId(templateId); + when(templateItemService.getRequiredTemplateByItemIdAndType(eq(productId), anyInt())).thenReturn(templateItem); + MesProFeedbackDO feedback = new MesProFeedbackDO(); + feedback.setId(feedbackId); + feedback.setCode("FB-001"); + when(feedbackService.validateFeedbackExists(feedbackId)).thenReturn(feedback); + // mock:产出行存在、归属正确、PENDING 状态 + MesWmProductProduceLineDO line = new MesWmProductProduceLineDO(); + line.setId(sourceLineId); + line.setFeedbackId(feedbackId); + line.setQualityStatus(MesWmQualityStatusEnum.PENDING.getStatus()); + when(productProduceLineService.validateProductProduceLineExists(sourceLineId)).thenReturn(line); + + // 调用 + Long ipqcId = ipqcService.createIpqc(reqVO); + + // 断言:创建成功,sourceDocCode 回写 + MesQcIpqcDO ipqc = ipqcMapper.selectById(ipqcId); + assertNotNull(ipqc); + assertEquals(feedbackId, ipqc.getSourceDocId()); + assertEquals(sourceLineId, ipqc.getSourceLineId()); + assertEquals("FB-001", ipqc.getSourceDocCode()); + } + } diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcServiceImplTest.java b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcServiceImplTest.java index 64c794cce..0d78c6b33 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcServiceImplTest.java +++ b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcServiceImplTest.java @@ -11,6 +11,7 @@ import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordServ import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateItemService; import cn.iocoder.yudao.module.mes.service.wm.arrivalnotice.MesWmArrivalNoticeService; import cn.iocoder.yudao.module.mes.service.wm.outsourcereceipt.MesWmOutsourceReceiptService; +import cn.iocoder.yudao.module.mes.service.qc.indicatorresult.MesQcIndicatorResultService; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; @@ -55,6 +56,8 @@ public class MesQcIqcServiceImplTest extends BaseDbUnitTest { private MesQcTemplateItemService templateItemService; @MockitoBean private AdminUserApi adminUserApi; + @MockitoBean + private MesQcIndicatorResultService indicatorResultService; @Test public void testFinishIqc_writeBack_arrivalNotice() { diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcServiceImplTest.java b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcServiceImplTest.java index 19b18ccb0..7c8a8c8c1 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcServiceImplTest.java +++ b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcServiceImplTest.java @@ -11,6 +11,7 @@ import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordServ import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateItemService; import cn.iocoder.yudao.module.mes.service.wm.productsales.MesWmProductSalesLineService; import cn.iocoder.yudao.module.mes.service.wm.productsales.MesWmProductSalesService; +import cn.iocoder.yudao.module.mes.service.qc.indicatorresult.MesQcIndicatorResultService; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import jakarta.annotation.Resource; import org.junit.jupiter.api.Test; @@ -55,6 +56,8 @@ public class MesQcOqcServiceImplTest extends BaseDbUnitTest { private MesQcDefectRecordService defectRecordService; @MockitoBean private AdminUserApi adminUserApi; + @MockitoBean + private MesQcIndicatorResultService indicatorResultService; @Test public void testFinishOqc_writeBack_productSales() { diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/qc/rqc/MesQcRqcServiceImplTest.java b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/qc/rqc/MesQcRqcServiceImplTest.java index b7139522a..eddad06e0 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/qc/rqc/MesQcRqcServiceImplTest.java +++ b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/qc/rqc/MesQcRqcServiceImplTest.java @@ -10,6 +10,7 @@ import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordServ import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateItemService; import cn.iocoder.yudao.module.mes.service.wm.returnissue.MesWmReturnIssueLineService; import cn.iocoder.yudao.module.mes.service.wm.returnsales.MesWmReturnSalesLineService; +import cn.iocoder.yudao.module.mes.service.qc.indicatorresult.MesQcIndicatorResultService; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import jakarta.annotation.Resource; import org.junit.jupiter.api.Test; @@ -56,6 +57,8 @@ public class MesQcRqcServiceImplTest extends BaseDbUnitTest { private MesQcDefectRecordService defectRecordService; @MockitoBean private AdminUserApi adminUserApi; + @MockitoBean + private MesQcIndicatorResultService indicatorResultService; @Test public void testFinishRqc_successWithReturnIssue() { diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeServiceImplTest.java b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeServiceImplTest.java index a742b4d6c..b5dacf8ac 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeServiceImplTest.java +++ b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeServiceImplTest.java @@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalN import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalNoticeLineDO; import cn.iocoder.yudao.module.mes.dal.mysql.wm.arrivalnotice.MesWmArrivalNoticeMapper; import cn.iocoder.yudao.module.mes.enums.wm.MesWmArrivalNoticeStatusEnum; +import cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; import org.springframework.test.context.bean.override.mockito.MockitoBean; @@ -38,6 +39,8 @@ public class MesWmArrivalNoticeServiceImplTest extends BaseDbUnitTest { @MockitoBean private MesWmArrivalNoticeLineService arrivalNoticeLineService; + @MockitoBean + private MesMdVendorService vendorService; @Test public void testUpdateArrivalNoticeWhenIqcFinish_success_allLinesChecked() { diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/materialstock/MesWmMaterialStockServiceImplTest.java b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/materialstock/MesWmMaterialStockServiceImplTest.java new file mode 100644 index 000000000..5814c4ce9 --- /dev/null +++ b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/materialstock/MesWmMaterialStockServiceImplTest.java @@ -0,0 +1,110 @@ +package cn.iocoder.yudao.module.mes.service.wm.materialstock; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.mes.controller.admin.wm.materialstock.vo.MesWmMaterialStockPageReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; +import cn.iocoder.yudao.module.mes.dal.mysql.wm.materialstock.MesWmMaterialStockMapper; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemTypeService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService; +import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService; +import jakarta.annotation.Resource; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.bean.override.mockito.MockitoBean; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.function.Consumer; + +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.when; + +/** + * {@link MesWmMaterialStockServiceImpl} 的单元测试 + * + * @author 芋道源码 + */ +@Import(MesWmMaterialStockServiceImpl.class) +public class MesWmMaterialStockServiceImplTest extends BaseDbUnitTest { + + @Resource + private MesWmMaterialStockServiceImpl materialStockService; + + @Resource + private MesWmMaterialStockMapper materialStockMapper; + + @MockitoBean + private MesMdItemService itemService; + @MockitoBean + private MesMdItemTypeService itemTypeService; + @MockitoBean + private MesWmWarehouseAreaService areaService; + @MockitoBean + private MesWmWarehouseService warehouseService; + + @Test + public void testGetMaterialStockPage_virtualFilterOnly() { + // 准备数据:虚拟仓库存 + 普通仓库存 + Long virtualWarehouseId = 100L; + Long normalWarehouseId = 200L; + MesWmMaterialStockDO virtualStock = createMaterialStockPojo(o -> o.setWarehouseId(virtualWarehouseId)); + MesWmMaterialStockDO normalStock = createMaterialStockPojo(o -> o.setWarehouseId(normalWarehouseId)); + materialStockMapper.insert(virtualStock); + materialStockMapper.insert(normalStock); + mockVirtualWarehouse(virtualWarehouseId); + + // 调用:只看虚拟仓 + MesWmMaterialStockPageReqVO reqVO = new MesWmMaterialStockPageReqVO(); + reqVO.setVirtualFilter(MesWmMaterialStockPageReqVO.VIRTUAL_FILTER_ONLY); + PageResult result = materialStockService.getMaterialStockPage(reqVO); + + // 断言:只返回虚拟仓库存,且 total 与列表一致 + assertEquals(1, result.getTotal()); + assertEquals(1, result.getList().size()); + assertEquals(virtualStock.getId(), result.getList().get(0).getId()); + } + + @Test + public void testGetMaterialStockPage_virtualFilterExclude() { + // 准备数据:虚拟仓库存 + 普通仓库存 + Long virtualWarehouseId = 100L; + Long normalWarehouseId = 200L; + MesWmMaterialStockDO virtualStock = createMaterialStockPojo(o -> o.setWarehouseId(virtualWarehouseId)); + MesWmMaterialStockDO normalStock = createMaterialStockPojo(o -> o.setWarehouseId(normalWarehouseId)); + materialStockMapper.insert(virtualStock); + materialStockMapper.insert(normalStock); + mockVirtualWarehouse(virtualWarehouseId); + + // 调用:排除虚拟仓 + MesWmMaterialStockPageReqVO reqVO = new MesWmMaterialStockPageReqVO(); + reqVO.setVirtualFilter(MesWmMaterialStockPageReqVO.VIRTUAL_FILTER_EXCLUDE); + PageResult result = materialStockService.getMaterialStockPage(reqVO); + + // 断言:只返回普通仓库存,且 total 与列表一致 + assertEquals(1, result.getTotal()); + assertEquals(1, result.getList().size()); + assertEquals(normalStock.getId(), result.getList().get(0).getId()); + } + + private MesWmMaterialStockDO createMaterialStockPojo(Consumer consumer) { + return randomPojo(MesWmMaterialStockDO.class, o -> { + o.setQuantity(new BigDecimal("10.00")); + o.setReceiptTime(LocalDateTime.of(2026, 1, 1, 0, 0)); + o.setFrozen(false); + o.setDeleted(false); + consumer.accept(o); + }); + } + + private void mockVirtualWarehouse(Long virtualWarehouseId) { + MesWmWarehouseDO virtualWarehouse = new MesWmWarehouseDO(); + virtualWarehouse.setId(virtualWarehouseId); + when(warehouseService.getWarehouseByCode(MesWmWarehouseDO.WIP_VIRTUAL_WAREHOUSE)) + .thenReturn(virtualWarehouse); + } + +} diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceServiceImplTest.java b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceServiceImplTest.java index 3ea0824e2..e7bf99a86 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceServiceImplTest.java +++ b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/productproduce/MesWmProductProduceServiceImplTest.java @@ -1,8 +1,10 @@ package cn.iocoder.yudao.module.mes.service.wm.productproduce; +import cn.hutool.core.collection.ListUtil; +import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceDetailDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceDetailDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceLineDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; @@ -23,10 +25,10 @@ import org.springframework.context.annotation.Import; import org.springframework.test.context.bean.override.mockito.MockitoBean; import java.math.BigDecimal; -import java.util.List; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; @@ -65,6 +67,7 @@ public class MesWmProductProduceServiceImplTest extends BaseDbUnitTest { public void testSplitPendingAndFinishProduce_withUnqualified() { // 准备数据:插入一个 PREPARE 状态的产出单 Long feedbackId = randomLongId(); + Long sourceLineId = 100L; Long itemId = randomLongId(); Long batchId = randomLongId(); String batchCode = "BATCH-001"; @@ -84,19 +87,17 @@ public class MesWmProductProduceServiceImplTest extends BaseDbUnitTest { when(locationService.getWarehouseLocationByCode(MesWmWarehouseLocationDO.WIP_VIRTUAL_LOCATION)).thenReturn(loc); when(areaService.getWarehouseAreaByCode(MesWmWarehouseAreaDO.WIP_VIRTUAL_AREA)).thenReturn(area); - // mock: 返回一条 PENDING 的产出行 + // mock: 通过 sourceLineId 直接定位 PENDING 产出行 MesWmProductProduceLineDO pendingLine = MesWmProductProduceLineDO.builder() - .id(100L).produceId(produce.getId()).feedbackId(feedbackId) + .id(sourceLineId).produceId(produce.getId()).feedbackId(feedbackId) .itemId(itemId).quantity(BigDecimal.valueOf(100)) .batchId(batchId).batchCode(batchCode) .qualityStatus(MesWmQualityStatusEnum.PENDING.getStatus()) .build(); - when(productProduceLineService.getProductProduceLineListByProduceId(produce.getId())) - .thenReturn(List.of(pendingLine)); + when(productProduceLineService.validateProductProduceLineExists(sourceLineId)) + .thenReturn(pendingLine); - // mock: finishProductProduce 内部会再查一次行和明细(用于创建库存事务) - // 由于 finishProductProduce 在拆分行后调用,此时行已经变了,但由于 line/detail 是 mock 的, - // 我们需要 mock 已拆分后的行给 finishProductProduce + // mock: finishProductProduce 内部查行和明细(用于创建库存事务) MesWmProductProduceLineDO qualifiedLine = MesWmProductProduceLineDO.builder() .id(100L).produceId(produce.getId()).itemId(itemId) .quantity(BigDecimal.valueOf(80)) @@ -107,10 +108,8 @@ public class MesWmProductProduceServiceImplTest extends BaseDbUnitTest { .quantity(BigDecimal.valueOf(20)) .qualityStatus(MesWmQualityStatusEnum.FAIL.getStatus()) .build(); - // finishProductProduce 内部第二次调用 getProductProduceLineListByProduceId when(productProduceLineService.getProductProduceLineListByProduceId(produce.getId())) - .thenReturn(List.of(pendingLine)) // 第 1 次:splitPendingAndFinishProduce 查待检行 - .thenReturn(List.of(qualifiedLine, unqualifiedLine)); // 第 2 次:finishProductProduce 查所有行 + .thenReturn(ListUtil.of(qualifiedLine, unqualifiedLine)); // mock: finishProductProduce 中按行查明细 MesWmProductProduceDetailDO qualifiedDetail = MesWmProductProduceDetailDO.builder() @@ -118,12 +117,13 @@ public class MesWmProductProduceServiceImplTest extends BaseDbUnitTest { MesWmProductProduceDetailDO unqualifiedDetail = MesWmProductProduceDetailDO.builder() .lineId(101L).quantity(BigDecimal.valueOf(20)).build(); when(productProduceDetailService.getProductProduceDetailListByLineId(100L)) - .thenReturn(List.of(qualifiedDetail)); + .thenReturn(ListUtil.of(qualifiedDetail)); when(productProduceDetailService.getProductProduceDetailListByLineId(101L)) - .thenReturn(List.of(unqualifiedDetail)); + .thenReturn(ListUtil.of(unqualifiedDetail)); // 调用 - productProduceService.splitPendingAndFinishProduce(feedbackId, BigDecimal.valueOf(80), BigDecimal.valueOf(20)); + productProduceService.splitPendingAndFinishProduce(feedbackId, sourceLineId, + BigDecimal.valueOf(80), BigDecimal.valueOf(20)); // 断言 1:不合格品行 - 新建了一行 ArgumentCaptor lineCaptor = ArgumentCaptor.forClass(MesWmProductProduceLineDO.class); @@ -155,6 +155,7 @@ public class MesWmProductProduceServiceImplTest extends BaseDbUnitTest { public void testSplitPendingAndFinishProduce_allQualified() { // 准备数据:全部合格品场景 Long feedbackId = randomLongId(); + Long sourceLineId = 200L; Long itemId = randomLongId(); MesWmProductProduceDO produce = randomPojo(MesWmProductProduceDO.class, o -> { @@ -172,30 +173,31 @@ public class MesWmProductProduceServiceImplTest extends BaseDbUnitTest { when(locationService.getWarehouseLocationByCode(any())).thenReturn(loc); when(areaService.getWarehouseAreaByCode(any())).thenReturn(area); + // mock: 通过 sourceLineId 直接定位 PENDING 产出行 MesWmProductProduceLineDO pendingLine = MesWmProductProduceLineDO.builder() - .id(200L).produceId(produce.getId()).feedbackId(feedbackId) + .id(sourceLineId).produceId(produce.getId()).feedbackId(feedbackId) .itemId(itemId).quantity(BigDecimal.valueOf(50)) .qualityStatus(MesWmQualityStatusEnum.PENDING.getStatus()) .build(); + when(productProduceLineService.validateProductProduceLineExists(sourceLineId)) + .thenReturn(pendingLine); - // 第 1 次查行(拆分阶段)返回 PENDING 行;第 2 次查行(finishProductProduce)返回已更新的合格行 + // mock: finishProductProduce 查行和明细 MesWmProductProduceLineDO qualifiedLine = MesWmProductProduceLineDO.builder() .id(200L).produceId(produce.getId()).itemId(itemId) .quantity(BigDecimal.valueOf(50)) .qualityStatus(MesWmQualityStatusEnum.PASS.getStatus()) .build(); when(productProduceLineService.getProductProduceLineListByProduceId(produce.getId())) - .thenReturn(List.of(pendingLine)) - .thenReturn(List.of(qualifiedLine)); - - // mock: finishProductProduce 中按行查明细 + .thenReturn(ListUtil.of(qualifiedLine)); MesWmProductProduceDetailDO detail = MesWmProductProduceDetailDO.builder() .lineId(200L).quantity(BigDecimal.valueOf(50)).build(); when(productProduceDetailService.getProductProduceDetailListByLineId(200L)) - .thenReturn(List.of(detail)); + .thenReturn(ListUtil.of(detail)); // 调用:不合格品数量 = 0 - productProduceService.splitPendingAndFinishProduce(feedbackId, BigDecimal.valueOf(50), BigDecimal.ZERO); + productProduceService.splitPendingAndFinishProduce(feedbackId, sourceLineId, + BigDecimal.valueOf(50), BigDecimal.ZERO); // 断言 1:没有新建行(不合格品数量为 0) verify(productProduceLineService, never()).createProductProduceLine(any()); @@ -217,14 +219,18 @@ public class MesWmProductProduceServiceImplTest extends BaseDbUnitTest { public void testSplitPendingAndFinishProduce_produceNotExists() { // 调用不存在的 feedbackId,应该抛异常 Long feedbackId = randomLongId(); - assertThrows(Exception.class, () -> - productProduceService.splitPendingAndFinishProduce(feedbackId, BigDecimal.TEN, BigDecimal.ZERO)); + Long sourceLineId = randomLongId(); + ServiceException ex = assertThrows(ServiceException.class, () -> + productProduceService.splitPendingAndFinishProduce(feedbackId, sourceLineId, + BigDecimal.TEN, BigDecimal.ZERO)); + assertEquals(WM_PRODUCT_PRODUCE_NOT_EXISTS.getCode(), ex.getCode()); } @Test - public void testSplitPendingAndFinishProduce_noPendingLine() { - // 准备数据:产出单存在,但没有 PENDING 行 + public void testSplitPendingAndFinishProduce_lineNotExists() { + // 准备数据:产出单存在,但 sourceLineId 对应的行不存在 Long feedbackId = randomLongId(); + Long sourceLineId = randomLongId(); MesWmProductProduceDO produce = randomPojo(MesWmProductProduceDO.class, o -> { o.setFeedbackId(feedbackId); o.setStatus(MesWmProductProduceStatusEnum.PREPARE.getStatus()); @@ -239,17 +245,15 @@ public class MesWmProductProduceServiceImplTest extends BaseDbUnitTest { when(locationService.getWarehouseLocationByCode(any())).thenReturn(loc); when(areaService.getWarehouseAreaByCode(any())).thenReturn(area); - // mock: 返回一条 PASS 状态的行(不是 PENDING) - MesWmProductProduceLineDO passLine = MesWmProductProduceLineDO.builder() - .id(300L).produceId(produce.getId()) - .qualityStatus(MesWmQualityStatusEnum.PASS.getStatus()) - .build(); - when(productProduceLineService.getProductProduceLineListByProduceId(produce.getId())) - .thenReturn(List.of(passLine)); + // mock: validateProductProduceLineExists 抛异常 + when(productProduceLineService.validateProductProduceLineExists(sourceLineId)) + .thenThrow(new ServiceException(WM_PRODUCT_PRODUCE_LINE_NOT_EXISTS)); - // 调用,应该抛异常(找不到 PENDING 行) - assertThrows(Exception.class, () -> - productProduceService.splitPendingAndFinishProduce(feedbackId, BigDecimal.TEN, BigDecimal.ZERO)); + // 调用,应该抛异常 + ServiceException ex = assertThrows(ServiceException.class, () -> + productProduceService.splitPendingAndFinishProduce(feedbackId, sourceLineId, + BigDecimal.TEN, BigDecimal.ZERO)); + assertEquals(WM_PRODUCT_PRODUCE_LINE_NOT_EXISTS.getCode(), ex.getCode()); } } diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesLineServiceImplTest.java b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesLineServiceImplTest.java index e93ffac9c..674a1d432 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesLineServiceImplTest.java +++ b/yudao-module-mes/yudao-module-mes-server/src/test/java/cn/iocoder/yudao/module/mes/service/wm/returnsales/MesWmReturnSalesLineServiceImplTest.java @@ -11,6 +11,7 @@ import org.springframework.context.annotation.Import; import org.springframework.test.context.bean.override.mockito.MockitoBean; import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; +import cn.iocoder.yudao.module.mes.service.wm.batch.MesWmBatchService; import java.math.BigDecimal; import java.util.List; @@ -39,6 +40,12 @@ public class MesWmReturnSalesLineServiceImplTest extends BaseDbUnitTest { @MockitoBean private MesMdItemService itemService; + @MockitoBean + private MesWmBatchService batchService; + + @MockitoBean + private MesWmReturnSalesDetailService returnSalesDetailService; + @Test public void testUpdateReturnSalesLineWhenRqcFinish_allPass() { // 准备参数:全部合格 diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/resources/sql/clean.sql b/yudao-module-mes/yudao-module-mes-server/src/test/resources/sql/clean.sql index eda0d8c6d..8cb28c31e 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/test/resources/sql/clean.sql +++ b/yudao-module-mes/yudao-module-mes-server/src/test/resources/sql/clean.sql @@ -1,3 +1,7 @@ +DELETE FROM "mes_cal_team_shift"; +DELETE FROM "mes_cal_plan_team"; +DELETE FROM "mes_cal_plan_shift"; +DELETE FROM "mes_cal_plan"; DELETE FROM "mes_md_auto_code_rule"; DELETE FROM "mes_md_auto_code_part"; DELETE FROM "mes_md_auto_code_record"; @@ -13,3 +17,7 @@ DELETE FROM "mes_wm_item_receipt"; DELETE FROM "mes_wm_item_receipt_line"; DELETE FROM "mes_wm_item_receipt_detail"; DELETE FROM "mes_wm_batch"; +DELETE FROM "mes_wm_material_stock"; +DELETE FROM "mes_pro_task"; +DELETE FROM "mes_pro_route_process"; +DELETE FROM "mes_qc_indicator_result"; diff --git a/yudao-module-mes/yudao-module-mes-server/src/test/resources/sql/create_tables.sql b/yudao-module-mes/yudao-module-mes-server/src/test/resources/sql/create_tables.sql index a37c9e977..fd7361362 100644 --- a/yudao-module-mes/yudao-module-mes-server/src/test/resources/sql/create_tables.sql +++ b/yudao-module-mes/yudao-module-mes-server/src/test/resources/sql/create_tables.sql @@ -1,3 +1,84 @@ +-- ---------------------------- +-- MES 排班计划 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "mes_cal_plan" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "code" varchar(64) DEFAULT NULL, + "name" varchar(255) DEFAULT NULL, + "calendar_type" tinyint DEFAULT NULL, + "start_date" timestamp DEFAULT NULL, + "end_date" timestamp DEFAULT NULL, + "shift_type" tinyint DEFAULT NULL, + "shift_method" tinyint DEFAULT NULL, + "shift_count" int DEFAULT NULL, + "status" tinyint DEFAULT NULL, + "remark" varchar(500) DEFAULT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT 0, + PRIMARY KEY ("id") +); + +-- ---------------------------- +-- MES 排班计划班次 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "mes_cal_plan_shift" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "plan_id" bigint DEFAULT NULL, + "sort" int DEFAULT NULL, + "name" varchar(64) DEFAULT NULL, + "start_time" varchar(10) DEFAULT NULL, + "end_time" varchar(10) DEFAULT NULL, + "remark" varchar(500) DEFAULT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT 0, + PRIMARY KEY ("id") +); + +-- ---------------------------- +-- MES 排班计划班组 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "mes_cal_plan_team" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "plan_id" bigint DEFAULT NULL, + "team_id" bigint DEFAULT NULL, + "remark" varchar(500) DEFAULT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT 0, + PRIMARY KEY ("id") +); + +-- ---------------------------- +-- MES 班组排班 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "mes_cal_team_shift" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "plan_id" bigint DEFAULT NULL, + "team_id" bigint DEFAULT NULL, + "shift_id" bigint DEFAULT NULL, + "day" timestamp DEFAULT NULL, + "sort" int DEFAULT NULL, + "remark" varchar(500) DEFAULT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT 0, + PRIMARY KEY ("id") +); + -- ---------------------------- -- MES 编码规则表 -- ---------------------------- @@ -300,7 +381,6 @@ CREATE TABLE IF NOT EXISTS "mes_wm_product_produce_detail" ( PRIMARY KEY ("id") ); - -- ---------------------------- -- MES 出货检验单(OQC) -- ---------------------------- @@ -309,8 +389,8 @@ CREATE TABLE IF NOT EXISTS "mes_qc_oqc" ( "code" varchar(64) NOT NULL, "name" varchar(500) NOT NULL, "template_id" bigint NOT NULL, - "source_doc_id" bigint DEFAULT NULL, "source_doc_type" int DEFAULT NULL, + "source_doc_id" bigint DEFAULT NULL, "source_line_id" bigint DEFAULT NULL, "source_doc_code" varchar(64) DEFAULT NULL, "client_id" bigint NOT NULL, @@ -351,8 +431,8 @@ CREATE TABLE IF NOT EXISTS "mes_qc_rqc" ( "code" varchar(64) NOT NULL, "name" varchar(500) NOT NULL, "template_id" bigint NOT NULL, - "source_doc_id" bigint DEFAULT NULL, "source_doc_type" int DEFAULT NULL, + "source_doc_id" bigint DEFAULT NULL, "source_line_id" bigint DEFAULT NULL, "source_doc_code" varchar(64) DEFAULT NULL, "type" int DEFAULT NULL, @@ -361,17 +441,17 @@ CREATE TABLE IF NOT EXISTS "mes_qc_rqc" ( "check_quantity" decimal(14,2) DEFAULT NULL, "qualified_quantity" decimal(14,2) DEFAULT 0.00, "unqualified_quantity" decimal(14,2) DEFAULT 0.00, + "critical_rate" decimal(14,2) DEFAULT 0.00, + "major_rate" decimal(14,2) DEFAULT 0.00, + "minor_rate" decimal(14,2) DEFAULT 0.00, + "critical_quantity" int DEFAULT 0, + "major_quantity" int DEFAULT 0, + "minor_quantity" int DEFAULT 0, "check_result" tinyint DEFAULT NULL, "inspect_date" timestamp DEFAULT NULL, "inspector_user_id" bigint DEFAULT NULL, "status" tinyint NOT NULL DEFAULT 0, "remark" varchar(500) DEFAULT '', - "critical_quantity" int DEFAULT 0, - "major_quantity" int DEFAULT 0, - "minor_quantity" int DEFAULT 0, - "critical_rate" decimal(14,2) DEFAULT 0.00, - "major_rate" decimal(14,2) DEFAULT 0.00, - "minor_rate" decimal(14,2) DEFAULT 0.00, "creator" varchar(64) DEFAULT '', "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, "updater" varchar(64) DEFAULT '', @@ -387,6 +467,7 @@ CREATE TABLE IF NOT EXISTS "mes_qc_rqc" ( CREATE TABLE IF NOT EXISTS "mes_wm_product_sales_line" ( "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, "sales_id" bigint NOT NULL, + "notice_line_id" bigint DEFAULT NULL, "item_id" bigint NOT NULL, "quantity" decimal(20,6) NOT NULL, "batch_id" bigint DEFAULT NULL, @@ -438,6 +519,7 @@ CREATE TABLE IF NOT EXISTS "mes_wm_return_sales_line" ( "item_id" bigint NOT NULL, "quantity" decimal(12,2) NOT NULL DEFAULT 0.00, "batch_id" bigint DEFAULT NULL, + "batch_code" varchar(255) DEFAULT NULL, "rqc_id" bigint DEFAULT NULL, "rqc_check_flag" bit NOT NULL DEFAULT FALSE, "quality_status" int DEFAULT NULL, @@ -618,3 +700,133 @@ CREATE TABLE IF NOT EXISTS "mes_wm_batch" ( "tenant_id" bigint NOT NULL DEFAULT 0, PRIMARY KEY ("id") ); + +-- ---------------------------- +-- MES 库存台账 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "mes_wm_material_stock" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "item_type_id" bigint DEFAULT NULL, + "item_id" bigint DEFAULT NULL, + "batch_id" bigint DEFAULT NULL, + "batch_code" varchar(255) DEFAULT NULL, + "warehouse_id" bigint DEFAULT NULL, + "location_id" bigint DEFAULT NULL, + "area_id" bigint DEFAULT NULL, + "vendor_id" bigint DEFAULT NULL, + "quantity" decimal(14,2) DEFAULT NULL, + "receipt_time" timestamp DEFAULT NULL, + "frozen" bit DEFAULT FALSE, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT 0, + PRIMARY KEY ("id") +); + +-- ---------------------------- +-- MES 生产任务 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "mes_pro_task" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "code" varchar(64) DEFAULT NULL, + "name" varchar(255) DEFAULT NULL, + "work_order_id" bigint DEFAULT NULL, + "workstation_id" bigint DEFAULT NULL, + "route_id" bigint DEFAULT NULL, + "process_id" bigint DEFAULT NULL, + "item_id" bigint DEFAULT NULL, + "quantity" decimal(14,2) DEFAULT NULL, + "produced_quantity" decimal(14,2) DEFAULT NULL, + "qualify_quantity" decimal(14,2) DEFAULT NULL, + "unqualify_quantity" decimal(14,2) DEFAULT NULL, + "changed_quantity" decimal(14,2) DEFAULT NULL, + "client_id" bigint DEFAULT NULL, + "start_time" timestamp DEFAULT NULL, + "duration" int DEFAULT NULL, + "end_time" timestamp DEFAULT NULL, + "color_code" varchar(20) DEFAULT NULL, + "finish_date" timestamp DEFAULT NULL, + "cancel_date" timestamp DEFAULT NULL, + "status" int DEFAULT NULL, + "remark" varchar(500) DEFAULT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT 0, + PRIMARY KEY ("id") +); + +-- ---------------------------- +-- MES 工艺路线工序 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "mes_pro_route_process" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "route_id" bigint DEFAULT NULL, + "process_id" bigint DEFAULT NULL, + "sort" int DEFAULT NULL, + "next_process_id" bigint DEFAULT NULL, + "link_type" int DEFAULT NULL, + "prepare_time" int DEFAULT NULL, + "wait_time" int DEFAULT NULL, + "color_code" varchar(20) DEFAULT NULL, + "key_flag" bit DEFAULT FALSE, + "check_flag" bit DEFAULT FALSE, + "remark" varchar(500) DEFAULT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT 0, + PRIMARY KEY ("id") +); + +-- ---------------------------- +-- MES 销售出库明细 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "mes_wm_product_sales_detail" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "line_id" bigint NOT NULL, + "sales_id" bigint NOT NULL, + "item_id" bigint NOT NULL, + "quantity" decimal(14,2) DEFAULT NULL, + "material_stock_id" bigint DEFAULT NULL, + "batch_id" bigint DEFAULT NULL, + "batch_code" varchar(255) DEFAULT NULL, + "warehouse_id" bigint DEFAULT NULL, + "location_id" bigint DEFAULT NULL, + "area_id" bigint DEFAULT NULL, + "remark" varchar(500) DEFAULT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT 0, + PRIMARY KEY ("id") +); + +-- ---------------------------- +-- MES 检验结果记录 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "mes_qc_indicator_result" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "code" varchar(64) DEFAULT NULL, + "qc_id" bigint DEFAULT NULL, + "qc_type" int DEFAULT NULL, + "item_id" bigint DEFAULT NULL, + "sn" varchar(128) DEFAULT NULL, + "remark" varchar(500) DEFAULT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT 0, + PRIMARY KEY ("id") +);