From 68af18ffa3457b1b0cdb800989d8f2c5022b7994 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BD=98=E8=8D=A3=E6=99=9F?= <9691125+pan-rongsheng@user.noreply.gitee.com> Date: Mon, 24 Nov 2025 11:32:37 +0800 Subject: [PATCH 1/9] =?UTF-8?q?=E9=87=87=E8=B4=AD=E8=AE=A2=E5=8D=95?= =?UTF-8?q?=E9=9D=9E=E7=A9=BA=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/purchaseorder/PurchaseOrderController.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zt-module-contract-order/zt-module-contract-order-server/src/main/java/com/zt/plat/module/contractorder/controller/admin/purchaseorder/PurchaseOrderController.java b/zt-module-contract-order/zt-module-contract-order-server/src/main/java/com/zt/plat/module/contractorder/controller/admin/purchaseorder/PurchaseOrderController.java index dc9ff7bb..8b09d40a 100644 --- a/zt-module-contract-order/zt-module-contract-order-server/src/main/java/com/zt/plat/module/contractorder/controller/admin/purchaseorder/PurchaseOrderController.java +++ b/zt-module-contract-order/zt-module-contract-order-server/src/main/java/com/zt/plat/module/contractorder/controller/admin/purchaseorder/PurchaseOrderController.java @@ -103,6 +103,9 @@ public class PurchaseOrderController implements BusinessControllerMarker { public CommonResult> getPurchaseOrderPage(@Valid PurchaseOrderPageReqVO pageReqVO) { PageResult pageResult = purchaseOrderService.getPurchaseOrderPage(pageReqVO); PageResult purchaseOrderRespVOPageResult = BeanUtils.toBean(pageResult, PurchaseOrderRespVO.class); + if (purchaseOrderRespVOPageResult.getList().isEmpty()){ + return success(purchaseOrderRespVOPageResult); + } purchaseOrderRespVOPageResult.getList().forEach(purchaseOrderRespVO -> purchaseOrderService.setOrderDetails(purchaseOrderRespVO)); return success(purchaseOrderRespVOPageResult); } From d6eaa44020f8bc4282e91fea842377fee7329ad9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BD=98=E8=8D=A3=E6=99=9F?= <9691125+pan-rongsheng@user.noreply.gitee.com> Date: Mon, 24 Nov 2025 14:31:05 +0800 Subject: [PATCH 2/9] =?UTF-8?q?=E5=88=A0=E9=99=A4dto=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../contractorder/api/dto/order/OrderDTO.java | 101 +++++++++--------- 1 file changed, 50 insertions(+), 51 deletions(-) diff --git a/zt-module-contract-order/zt-module-contract-order-api/src/main/java/com/zt/plat/module/contractorder/api/dto/order/OrderDTO.java b/zt-module-contract-order/zt-module-contract-order-api/src/main/java/com/zt/plat/module/contractorder/api/dto/order/OrderDTO.java index c5077382..5febb22b 100644 --- a/zt-module-contract-order/zt-module-contract-order-api/src/main/java/com/zt/plat/module/contractorder/api/dto/order/OrderDTO.java +++ b/zt-module-contract-order/zt-module-contract-order-api/src/main/java/com/zt/plat/module/contractorder/api/dto/order/OrderDTO.java @@ -15,273 +15,272 @@ public class OrderDTO { /** * 主键 */ - @TableId(type = IdType.ASSIGN_ID) + private Long id; /** * ERP订单号 */ - @TableField("ORD_SAP_NUM") + private String orderSAPNumber; /** * 订单号 */ - @TableField("SYS_ORD_NUM") + private String systemOrderNumber; /** * 公司名称 */ - @TableField("CPN_NAME") + private String cpName; /** * 公司编码;推送ERP(必须) */ - @TableField("CPN_NUM") + private String cpNum; /** * 客商编码;推送ERP(必须) */ - @TableField("SPLR_NUM") + private String supplierNumber; /** * 客商名称 */ - @TableField("SPLR_NAME") + private String supplierName; /** * 订单类型(字典:PRCH_ORD_TP);推送ERP(必须) */ - @TableField("TP") + private String type; /** * 凭证日期;推送ERP(必须) */ - @TableField("VCHR_DT") + private LocalDateTime voucherDate; /** * 采购组织编码;推送ERP(必须) */ - @TableField("PRCH_ORGZ_CD") + private String purchaseOrganizationCustomsDeclaration; /** * 收货工厂名称 */ - @TableField("RCV_FACT_NAME") + private String receiveFactoryName; /** * 收货工厂编码;推送ERP(必须) */ - @TableField("RCV_FACT_NUM") + private String receiveFactoryNumber; /** * 收货库位名称 */ - @TableField("RCV_WRH_NAME") + private String receiveWarehouseName; /** * 收货库位编码;推送ERP */ - @TableField("RCV_WRH_NUM") + private String receiveWarehouseNumber; /** * 采购组编码(字典:PRCH_GRP_TP);推送ERP(必须) */ - @TableField("PRCH_GRP") + private String purchaseGroup; /** * 货币码(字典:CUR);推送ERP(必须) */ - @TableField("CUR_NUM") + private String currencyNumber; /** * 汇率;推送ERP */ - @TableField("EXCH_RTE") + private BigDecimal exchangeRate; /** * 合同纸质合同号;推送ERP(必须) */ - @TableField("PPR_CTRT_NUM") + private String paperContractNumber; /** * 小协议号;推送ERP */ - @TableField("AGR_NUM") + private String agreementNumber; /** * 备注;推送ERP */ - @TableField("RMK") + private String remark; /** * 代理方编码;推送ERP */ - @TableField("AGT_NUM") + private String agentNumber; /** * 代理方名称 */ - @TableField("AGT_NAME") + private String agentName; /** * 系统合同编号 */ - @TableField("CTRT_NUM") + private String contractNumber; /** * 物料编码 */ - @TableField("MTRL_NUM") + private String materialNumber; /** * 物料名称 */ - @TableField("MTRL_NAME") + private String materialName; /** * 合同名称 */ - @TableField("CTRT_NAME") + private String contractName; /** * 小户头号 */ - @TableField("TNT_NUM") + private String tenantNumber; /** * ERP公司编号 */ - @TableField("ERP_PRCH_CPN_NUM") + private String erpPurchaseCompanyNumber; /** * ERP公司名称 */ - @TableField("ERP_PRCH_CPN_NAME") + private String erpPurchaseCompanyName; /** * ERP客商公司编码 */ - @TableField("ERP_SALE_CPN_NUM") + private String erpSalesCompanyNumber; /** * ERP客商公司名称 */ - @TableField("ERP_SALE_CPN_NAME") + private String erpSalesCompanyName; /** * 采购组织名称 */ - @TableField("PRCH_ORGZ_NAME") + private String purchaseOrganizationName; /** * ERP状态(字典: ERP_REQ_STS) */ - @TableField("ERP_STS") + private String erpStatus; /** * 请求ERP失败原因 */ - @TableField("CAUS") + private String cause; /** * 订单状态(字典:PRCH_ORD_STS) */ - @TableField("STS") + private String status; /** * 采购组名称 */ - @TableField("PRCH_GRP_NAME") + private String purchaseGroupName; /** * 流程实例编号 */ - @TableField("PRCS_INSC_ID") + private String processInstanceId; /** * 流程当前任务节点id */ - @TableField("TSK_NDE_ID") + private String taskId; /** * 审批意见 */ - @TableField("RVW_ONN") + private String reviewOpinion; /** * 是否需要审批 */ - @TableField("IS_PUSH") + private int isPush; /** * 计量单位 */ - @TableField("UNT") + private String unt; /** * 物料字典 * */ - @TableField("MTRL_TP") private String mtrlTp; /** * 订单分类 * */ - @TableField("SPLY_BSN_TP") + private String splyBsnTp; /** * 产品组编码 * */ - @TableField("PDT_GRP_CDG") + private String pdtGrpCdg; /** * 产品组名 */ - @TableField("PDT_GRP_NAME") + private String pdtGrpName; /** * 分销聚道编码 * */ - @TableField("SALE_ACS_CDG") + private String saleAcsCdg; /** * 分销聚道名称 * */ - @TableField("SALE_ACS_NAME") + private String saleAcsName; /** * 销售组织编码 * */ - @TableField("SALE_ORGZ_CD") + private String saleOrgzCd; /** * 销售组织名称 * */ - @TableField("SALE_ORGZ_NAME") + private String saleOrgzName; /** * 付款方名称 * */ - @TableField("PYER_NAME") + private String payerName; /** * 付款方编码 * */ - @TableField("PYER_NUM") + private String payerNum; /** * 货权准转移类型 From 26be89f0c7667e77f8bc7705cf30757e101ed2d8 Mon Sep 17 00:00:00 2001 From: qianshijiang <1965297290@qq.com> Date: Mon, 24 Nov 2025 14:42:55 +0800 Subject: [PATCH 3/9] =?UTF-8?q?=E6=97=A5=E5=BF=97=E6=89=93=E5=8D=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application.yml | 2 + .../src/main/resources/logback-spring.xml | 76 +++++++++++++++++++ .../src/main/resources/application.yml | 2 + .../src/main/resources/logback-spring.xml | 10 +-- 4 files changed, 85 insertions(+), 5 deletions(-) create mode 100644 base-server/src/main/resources/logback-spring.xml diff --git a/base-server/src/main/resources/application.yml b/base-server/src/main/resources/application.yml index 7eb362ae..4e9bb026 100644 --- a/base-server/src/main/resources/application.yml +++ b/base-server/src/main/resources/application.yml @@ -72,6 +72,8 @@ knife4j: # MyBatis Plus 的配置项 mybatis-plus: + mapper-locations: + - classpath*:mapper/**/*.xml configuration: map-underscore-to-camel-case: true # 虽然默认为 true ,但是还是显示去指定下。 global-config: diff --git a/base-server/src/main/resources/logback-spring.xml b/base-server/src/main/resources/logback-spring.xml new file mode 100644 index 00000000..2bde9644 --- /dev/null +++ b/base-server/src/main/resources/logback-spring.xml @@ -0,0 +1,76 @@ + + + + + + + + + +       + + + ${PATTERN_DEFAULT} + + + + + + + + + + ${PATTERN_DEFAULT} + + + + ${LOG_FILE} + + + ${LOGBACK_ROLLINGPOLICY_FILE_NAME_PATTERN:-${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz} + + ${LOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START:-false} + + ${LOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE:-10MB} + + ${LOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP:-0} + + ${LOGBACK_ROLLINGPOLICY_MAX_HISTORY:-30} + + + + + + 0 + + 256 + + + + + + + + ${PATTERN_DEFAULT} + + + + + + + + + + + + + + + + + + + + + + diff --git a/zt-module-contract-order/zt-module-contract-order-server/src/main/resources/application.yml b/zt-module-contract-order/zt-module-contract-order-server/src/main/resources/application.yml index ba3ad1bf..5baca3de 100644 --- a/zt-module-contract-order/zt-module-contract-order-server/src/main/resources/application.yml +++ b/zt-module-contract-order/zt-module-contract-order-server/src/main/resources/application.yml @@ -72,6 +72,8 @@ knife4j: # MyBatis Plus 的配置项 mybatis-plus: + mapper-locations: + - classpath*:mapper/**/*.xml configuration: map-underscore-to-camel-case: true # 虽然默认为 true ,但是还是显示去指定下。 global-config: diff --git a/zt-module-contract-order/zt-module-contract-order-server/src/main/resources/logback-spring.xml b/zt-module-contract-order/zt-module-contract-order-server/src/main/resources/logback-spring.xml index 66410855..2bde9644 100644 --- a/zt-module-contract-order/zt-module-contract-order-server/src/main/resources/logback-spring.xml +++ b/zt-module-contract-order/zt-module-contract-order-server/src/main/resources/logback-spring.xml @@ -1,8 +1,8 @@ - - + + @@ -57,7 +57,7 @@ - + @@ -65,8 +65,8 @@ - - + + From 1b9e28be5a79065de93c71ddc74a85ada356c2cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BD=98=E8=8D=A3=E6=99=9F?= <9691125+pan-rongsheng@user.noreply.gitee.com> Date: Tue, 30 Sep 2025 17:35:39 +0800 Subject: [PATCH 4/9] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E4=B8=9A=E5=8A=A1?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/base/MasterDataSyncController.java | 51 ++ .../admin/base/vo/MasterDataSyncReqVO.java | 31 ++ .../masterdata/MdmMaterialCategoryDO.java | 35 ++ .../masterdata/MdmMaterialViewDO.java | 35 ++ .../masterdata/MdmMaterialCategoryMapper.java | 21 + .../masterdata/MdmMaterialViewMapper.java | 27 + .../config/MasterDataSyncConfiguration.java | 24 + .../sync/config/MasterDataSyncProperties.java | 68 +++ .../constant/MasterDataSyncConstants.java | 15 + .../MasterDataCategorySyncService.java | 11 + .../MasterDataCategorySyncServiceImpl.java | 214 ++++++++ .../masterdatasync/MasterDataSyncService.java | 12 + .../MasterDataSyncServiceImpl.java | 488 ++++++++++++++++++ .../dto/MasterDataCategorySyncReport.java | 59 +++ .../dto/MasterDataSyncCommand.java | 33 ++ .../dto/MasterDataSyncReport.java | 104 ++++ .../support/MasterDataPropertyDefinition.java | 52 ++ .../MasterDataSyncNotificationPayload.java | 16 + .../support/MasterDataSyncNotifier.java | 61 +++ .../masterdata/MdmMaterialCategoryMapper.xml | 17 + .../masterdata/MdmMaterialViewMapper.xml | 71 +++ zt-module-base/主数据同步说明.md | 140 +++++ 22 files changed, 1585 insertions(+) create mode 100644 zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/controller/admin/base/MasterDataSyncController.java create mode 100644 zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/controller/admin/base/vo/MasterDataSyncReqVO.java create mode 100644 zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/dal/dataobject/masterdata/MdmMaterialCategoryDO.java create mode 100644 zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/dal/dataobject/masterdata/MdmMaterialViewDO.java create mode 100644 zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/dal/mysql/masterdata/MdmMaterialCategoryMapper.java create mode 100644 zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/dal/mysql/masterdata/MdmMaterialViewMapper.java create mode 100644 zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/framework/sync/config/MasterDataSyncConfiguration.java create mode 100644 zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/framework/sync/config/MasterDataSyncProperties.java create mode 100644 zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/framework/sync/constant/MasterDataSyncConstants.java create mode 100644 zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/MasterDataCategorySyncService.java create mode 100644 zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/MasterDataCategorySyncServiceImpl.java create mode 100644 zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/MasterDataSyncService.java create mode 100644 zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/MasterDataSyncServiceImpl.java create mode 100644 zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/dto/MasterDataCategorySyncReport.java create mode 100644 zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/dto/MasterDataSyncCommand.java create mode 100644 zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/dto/MasterDataSyncReport.java create mode 100644 zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/support/MasterDataPropertyDefinition.java create mode 100644 zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/support/MasterDataSyncNotificationPayload.java create mode 100644 zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/support/MasterDataSyncNotifier.java create mode 100644 zt-module-base/zt-module-base-server/src/main/resources/mapper/masterdata/MdmMaterialCategoryMapper.xml create mode 100644 zt-module-base/zt-module-base-server/src/main/resources/mapper/masterdata/MdmMaterialViewMapper.xml create mode 100644 zt-module-base/主数据同步说明.md diff --git a/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/controller/admin/base/MasterDataSyncController.java b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/controller/admin/base/MasterDataSyncController.java new file mode 100644 index 00000000..be85284f --- /dev/null +++ b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/controller/admin/base/MasterDataSyncController.java @@ -0,0 +1,51 @@ +package com.zt.plat.module.base.controller.admin.base; + +import com.zt.plat.framework.common.pojo.CommonResult; +import com.zt.plat.framework.common.util.object.BeanUtils; +import com.zt.plat.module.base.controller.admin.base.vo.MasterDataSyncReqVO; +import com.zt.plat.module.base.service.masterdatasync.MasterDataCategorySyncService; +import com.zt.plat.module.base.service.masterdatasync.MasterDataSyncService; +import com.zt.plat.module.base.service.masterdatasync.dto.MasterDataSyncCommand; +import com.zt.plat.module.base.service.masterdatasync.dto.MasterDataSyncReport; +import com.zt.plat.module.base.service.masterdatasync.dto.MasterDataCategorySyncReport; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import static com.zt.plat.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - 主数据同步") +@RestController +@RequestMapping("/base/master-data-sync") +@Validated +public class MasterDataSyncController { + + @Resource + private MasterDataSyncService masterDataSyncService; + @Resource + private MasterDataCategorySyncService masterDataCategorySyncService; + + @PostMapping("/execute") + @Operation(summary = "执行主数据同步") + @PreAuthorize("@ss.hasPermission('base:master-data-sync:execute')") + public CommonResult execute(@Valid @RequestBody MasterDataSyncReqVO reqVO) { + MasterDataSyncCommand command = BeanUtils.toBean(reqVO, MasterDataSyncCommand.class); + MasterDataSyncReport report = masterDataSyncService.sync(command); + return success(report); + } + + @PostMapping("/categories") + @Operation(summary = "同步物料分类") + @PreAuthorize("@ss.hasPermission('base:master-data-sync:categories')") + public CommonResult syncCategories() { + MasterDataCategorySyncReport report = masterDataCategorySyncService.syncAll(); + return success(report); + } +} diff --git a/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/controller/admin/base/vo/MasterDataSyncReqVO.java b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/controller/admin/base/vo/MasterDataSyncReqVO.java new file mode 100644 index 00000000..a1559f9a --- /dev/null +++ b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/controller/admin/base/vo/MasterDataSyncReqVO.java @@ -0,0 +1,31 @@ +package com.zt.plat.module.base.controller.admin.base.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Positive; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; +import java.util.List; + +@Data +@Schema(description = "主数据同步请求参数") +public class MasterDataSyncReqVO { + + @Schema(description = "增量同步的起始记录时间,留空执行全量") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private LocalDateTime since; + + @Schema(description = "拉取批大小,不填写则使用配置默认值") + @Positive(message = "batchSize 必须为正数") + private Integer batchSize; + + @Schema(description = "指定要刷新同步的物料编码列表") + private List materialCodes; + + @Schema(description = "可选的本次同步记录数上限,未填写表示不限制") + @Positive(message = "recordLimit 必须为正数") + private Long recordLimit; +} diff --git a/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/dal/dataobject/masterdata/MdmMaterialCategoryDO.java b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/dal/dataobject/masterdata/MdmMaterialCategoryDO.java new file mode 100644 index 00000000..78d8954f --- /dev/null +++ b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/dal/dataobject/masterdata/MdmMaterialCategoryDO.java @@ -0,0 +1,35 @@ +package com.zt.plat.module.base.dal.dataobject.masterdata; + +import lombok.Data; + +/** + * 外部 MDM 分类视图的数据对象。 + */ +@Data +public class MdmMaterialCategoryDO { + + /** + * 分类主键 ID(CODEID)。 + */ + private Long codeId; + + /** + * 分类编码,例如 01 / 0101 / 010101。 + */ + private String code; + + /** + * 分类名称(DESC1)。 + */ + private String name; + + /** + * 备注信息(DESC2)。 + */ + private String remark; + + /** + * 父级分类主键 ID(PARENTID)。 + */ + private Long parentCodeId; +} diff --git a/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/dal/dataobject/masterdata/MdmMaterialViewDO.java b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/dal/dataobject/masterdata/MdmMaterialViewDO.java new file mode 100644 index 00000000..ce5b59ac --- /dev/null +++ b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/dal/dataobject/masterdata/MdmMaterialViewDO.java @@ -0,0 +1,35 @@ +package com.zt.plat.module.base.dal.dataobject.masterdata; + +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 外部 MDM MySQL 物料视图的投影,用于承接同步字段。 + */ +@Data +public class MdmMaterialViewDO { + + private Long codeId; + private String materialCode; + private String categoryCode; + private String categoryName; + private String materialName; + private String baseUnitCode; + private String baseUnitName; + private String shortDescription; + private String longDescription; + private String chalcoCode; + private String majorClassCode; + private String majorClassName; + private String specification; + private String model; + private String texture; + private String drawingNumber; + private String orderNumber; + private String otherParameters; + private String equipmentCategory; + private String manufacturer; + private String source; + private LocalDateTime recordTime; +} diff --git a/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/dal/mysql/masterdata/MdmMaterialCategoryMapper.java b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/dal/mysql/masterdata/MdmMaterialCategoryMapper.java new file mode 100644 index 00000000..ec8770ae --- /dev/null +++ b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/dal/mysql/masterdata/MdmMaterialCategoryMapper.java @@ -0,0 +1,21 @@ +package com.zt.plat.module.base.dal.mysql.masterdata; + +import com.baomidou.dynamic.datasource.annotation.DS; +import com.zt.plat.module.base.dal.dataobject.masterdata.MdmMaterialCategoryDO; +import com.zt.plat.module.base.framework.sync.constant.MasterDataSyncConstants; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 读取外部 MDM 分类视图的 Mapper。 + */ +@Mapper +@DS(MasterDataSyncConstants.DEFAULT_SOURCE_DATASOURCE) +public interface MdmMaterialCategoryMapper { + + /** + * 拉取全部分类档案。 + */ + List selectAll(); +} diff --git a/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/dal/mysql/masterdata/MdmMaterialViewMapper.java b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/dal/mysql/masterdata/MdmMaterialViewMapper.java new file mode 100644 index 00000000..42d88f1c --- /dev/null +++ b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/dal/mysql/masterdata/MdmMaterialViewMapper.java @@ -0,0 +1,27 @@ +package com.zt.plat.module.base.dal.mysql.masterdata; + +import com.baomidou.dynamic.datasource.annotation.DS; +import com.zt.plat.module.base.dal.dataobject.masterdata.MdmMaterialViewDO; +import com.zt.plat.module.base.framework.sync.constant.MasterDataSyncConstants; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.time.LocalDateTime; +import java.util.Collection; +import java.util.List; + +/** + * Mapper that exposes read-only access to the external MDM material view. + */ +@Mapper +@DS(MasterDataSyncConstants.DEFAULT_SOURCE_DATASOURCE) +public interface MdmMaterialViewMapper { + + List selectSlice(@Param("offset") long offset, + @Param("limit") int limit, + @Param("since") LocalDateTime since, + @Param("codes") Collection codes); + + Long countEligible(@Param("since") LocalDateTime since, + @Param("codes") Collection codes); +} diff --git a/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/framework/sync/config/MasterDataSyncConfiguration.java b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/framework/sync/config/MasterDataSyncConfiguration.java new file mode 100644 index 00000000..41fa787a --- /dev/null +++ b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/framework/sync/config/MasterDataSyncConfiguration.java @@ -0,0 +1,24 @@ +package com.zt.plat.module.base.framework.sync.config; + +import okhttp3.OkHttpClient; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * 主数据同步用到的基础配置。 + */ +@Configuration +@EnableConfigurationProperties(MasterDataSyncProperties.class) +public class MasterDataSyncConfiguration { + + @Bean + public OkHttpClient masterDataSyncOkHttpClient(MasterDataSyncProperties properties) { + MasterDataSyncProperties.HttpProperties http = properties.getHttp(); + return new OkHttpClient.Builder() + .connectTimeout(http.getConnectTimeout()) + .readTimeout(http.getReadTimeout()) + .writeTimeout(http.getWriteTimeout()) + .build(); + } +} diff --git a/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/framework/sync/config/MasterDataSyncProperties.java b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/framework/sync/config/MasterDataSyncProperties.java new file mode 100644 index 00000000..2ef02810 --- /dev/null +++ b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/framework/sync/config/MasterDataSyncProperties.java @@ -0,0 +1,68 @@ +package com.zt.plat.module.base.framework.sync.config; + +import com.zt.plat.module.base.framework.sync.constant.MasterDataSyncConstants; +import jakarta.validation.constraints.Min; +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.validation.annotation.Validated; + +import java.time.Duration; +import java.util.HashMap; +import java.util.Map; + +/** + * 主数据同步管道的配置项。 + */ +@Data +@Validated +@ConfigurationProperties(prefix = "base.master-data-sync") +public class MasterDataSyncProperties { + + /** + * 是否允许运行主数据同步。 + */ + private boolean enabled = true; + + /** + * 从外部数据源读取时的默认批量大小。 + */ + @Min(1) + private int batchSize = 500; + + /** + * 指向外部 MDM MySQL 的动态数据源名称。 + */ + private String sourceDatasourceName = MasterDataSyncConstants.DEFAULT_SOURCE_DATASOURCE; + + /** + * 成功是否进行回调通知。 + */ + private boolean notifyOnSuccess = true; + + /** + * 失败是否进行回调通知。 + */ + private boolean notifyOnFailure = true; + + /** + * 可选的回调地址,用于推送同步结果。 + */ + private String callbackUrl; + + /** + * 回调请求需要附加的静态请求头。 + */ + private Map callbackHeaders = new HashMap<>(); + + /** + * HTTP 客户端的超时时间等参数。 + */ + private final HttpProperties http = new HttpProperties(); + + @Data + public static class HttpProperties { + private Duration connectTimeout = Duration.ofSeconds(5); + private Duration readTimeout = Duration.ofSeconds(30); + private Duration writeTimeout = Duration.ofSeconds(30); + } +} diff --git a/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/framework/sync/constant/MasterDataSyncConstants.java b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/framework/sync/constant/MasterDataSyncConstants.java new file mode 100644 index 00000000..4032604d --- /dev/null +++ b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/framework/sync/constant/MasterDataSyncConstants.java @@ -0,0 +1,15 @@ +package com.zt.plat.module.base.framework.sync.constant; + +/** + * 主数据同步相关的通用常量。 + */ +public final class MasterDataSyncConstants { + + private MasterDataSyncConstants() { + } + + /** + * 指向外部 MDM MySQL 的默认数据源名称。 + */ + public static final String DEFAULT_SOURCE_DATASOURCE = "mdm"; +} diff --git a/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/MasterDataCategorySyncService.java b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/MasterDataCategorySyncService.java new file mode 100644 index 00000000..3e33148d --- /dev/null +++ b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/MasterDataCategorySyncService.java @@ -0,0 +1,11 @@ +package com.zt.plat.module.base.service.masterdatasync; + +import com.zt.plat.module.base.service.masterdatasync.dto.MasterDataCategorySyncReport; + +/** + * 物料分类同步服务接口。 + */ +public interface MasterDataCategorySyncService { + + MasterDataCategorySyncReport syncAll(); +} diff --git a/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/MasterDataCategorySyncServiceImpl.java b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/MasterDataCategorySyncServiceImpl.java new file mode 100644 index 00000000..0c0a7e07 --- /dev/null +++ b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/MasterDataCategorySyncServiceImpl.java @@ -0,0 +1,214 @@ +package com.zt.plat.module.base.service.masterdatasync; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import com.zt.plat.framework.common.exception.util.ServiceExceptionUtil; +import com.zt.plat.module.base.dal.dao.materialclasses.MaterialClassesMapper; +import com.zt.plat.module.base.dal.dataobject.materialclasses.MaterialClassesDO; +import com.zt.plat.module.base.dal.dataobject.masterdata.MdmMaterialCategoryDO; +import com.zt.plat.module.base.dal.mysql.masterdata.MdmMaterialCategoryMapper; +import com.zt.plat.module.base.enums.ErrorCodeConstants; +import com.zt.plat.module.base.framework.sync.config.MasterDataSyncProperties; +import com.zt.plat.module.base.service.masterdatasync.dto.MasterDataCategorySyncReport; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * 物料分类同步实现。 + */ +@Slf4j +@Service +public class MasterDataCategorySyncServiceImpl implements MasterDataCategorySyncService { + + private static final long ROOT_CLASS_PARENT_ID = 0L; + + @Resource + private MdmMaterialCategoryMapper mdmMaterialCategoryMapper; + @Resource + private MaterialClassesMapper materialClassesMapper; + @Resource + private MasterDataSyncProperties properties; + + @Override + public MasterDataCategorySyncReport syncAll() { + if (!properties.isEnabled()) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.MASTER_DATA_SYNC_DISABLED); + } + MasterDataCategorySyncReport report = MasterDataCategorySyncReport.start(); + try { + List categories = mdmMaterialCategoryMapper.selectAll(); + if (CollUtil.isEmpty(categories)) { + report.markSuccess(); + return report; + } + categories.sort(Comparator.comparing(MdmMaterialCategoryDO::getCode)); + Map classesByCode = loadExistingClasses(categories); + Map classesById = classesByCode.values().stream() + .filter(item -> item.getId() != null) + .collect(Collectors.toMap(MaterialClassesDO::getId, item -> item, (a, b) -> a, LinkedHashMap::new)); + // 统一收集新增分类,批量写入提升性能 + List pendingClassInserts = new ArrayList<>(); + for (MdmMaterialCategoryDO category : categories) { + Long sourceId = category.getCodeId(); + if (sourceId == null) { + log.warn("分类 {} 缺少主键 CODEID,已跳过", category.getCode()); + continue; + } + String code = normalizeCode(category.getCode()); + if (code == null) { + continue; + } + report.incrementProcessed(1); + long level = determineLevel(code); + Long parentId = resolveParentId(category, classesByCode, classesById, report); + if (parentId == null) { + parentId = ROOT_CLASS_PARENT_ID; + } + String name = StrUtil.emptyIfNull(StrUtil.trim(category.getName())); + String remark = StrUtil.emptyIfNull(StrUtil.trim(category.getRemark())); + MaterialClassesDO current = classesByCode.get(code); + if (current == null) { + MaterialClassesDO created = MaterialClassesDO.builder() + .id(sourceId) + .code(code) + .name(name) + .level(level) + .parentId(parentId) + .remark(remark) + .build(); + pendingClassInserts.add(created); + classesByCode.put(code, created); + if (created.getId() != null) { + classesById.put(created.getId(), created); + } + report.incrementInserted(); + } else { + if (current.getId() == null && sourceId != null) { + current.setId(sourceId); + classesById.put(sourceId, current); + } + boolean needUpdate = false; + MaterialClassesDO update = new MaterialClassesDO(); + update.setId(current.getId()); + if (!Objects.equals(current.getParentId(), parentId)) { + update.setParentId(parentId); + current.setParentId(parentId); + needUpdate = true; + } + if (StrUtil.isNotBlank(name) && !StrUtil.equals(current.getName(), name)) { + update.setName(name); + current.setName(name); + needUpdate = true; + } + if (!Objects.equals(current.getLevel(), level)) { + update.setLevel(level); + current.setLevel(level); + needUpdate = true; + } + if (!Objects.equals(StrUtil.emptyIfNull(current.getRemark()), remark)) { + update.setRemark(remark); + current.setRemark(remark); + needUpdate = true; + } + if (needUpdate) { + materialClassesMapper.updateById(update); + report.incrementUpdated(); + } + } + } + if (CollUtil.isNotEmpty(pendingClassInserts)) { + materialClassesMapper.insertBatch(pendingClassInserts); + } + report.markSuccess(); + return report; + } catch (Throwable ex) { + report.markFailure(ex.getMessage()); + throw ex; + } finally { + report.finish(); + } + } + + private Map loadExistingClasses(List categories) { + Set codes = categories.stream() + .map(MdmMaterialCategoryDO::getCode) + .map(this::normalizeCode) + .filter(Objects::nonNull) + .collect(Collectors.toCollection(LinkedHashSet::new)); + List existing = materialClassesMapper.selectByCodes(codes); + Map result = new LinkedHashMap<>(); + if (existing != null) { + existing.forEach(item -> { + String key = normalizeCode(item.getCode()); + if (key != null) { + result.put(key, item); + } + }); + } + return result; + } + + private Long resolveParentId(MdmMaterialCategoryDO category, + Map classesByCode, + Map classesById, + MasterDataCategorySyncReport report) { + if (category.getParentCodeId() != null && category.getParentCodeId() > 0) { + MaterialClassesDO parent = classesById.get(category.getParentCodeId()); + if (parent != null) { + return parent.getId(); + } + log.warn("分类 {} 指定父级 ID {} 不存在,将尝试按编码推断", category.getCode(), category.getParentCodeId()); + } + String parentCode = resolveParentCode(normalizeCode(category.getCode())); + if (parentCode == null) { + return ROOT_CLASS_PARENT_ID; + } + MaterialClassesDO parent = classesByCode.get(parentCode); + if (parent == null) { + log.warn("分类 {} 缺失父级 {},将挂载到根节点", category.getCode(), parentCode); + if (report != null) { + report.incrementMissingParent(); + } + return null; + } + return parent.getId(); + } + + private String resolveParentCode(String code) { + if (code == null) { + return null; + } + if (code.length() <= 2) { + return null; + } + if (code.length() <= 4) { + return code.substring(0, 2); + } + return code.substring(0, 4); + } + + private long determineLevel(String code) { + if (code.length() <= 2) { + return 1L; + } + if (code.length() <= 4) { + return 2L; + } + return 3L; + } + + private String normalizeCode(String code) { + return StrUtil.isBlank(code) ? null : StrUtil.trim(code); + } +} diff --git a/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/MasterDataSyncService.java b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/MasterDataSyncService.java new file mode 100644 index 00000000..3ffadd3f --- /dev/null +++ b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/MasterDataSyncService.java @@ -0,0 +1,12 @@ +package com.zt.plat.module.base.service.masterdatasync; + +import com.zt.plat.module.base.service.masterdatasync.dto.MasterDataSyncCommand; +import com.zt.plat.module.base.service.masterdatasync.dto.MasterDataSyncReport; + +/** + * 物料主数据同步的服务入口。 + */ +public interface MasterDataSyncService { + + MasterDataSyncReport sync(MasterDataSyncCommand command); +} diff --git a/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/MasterDataSyncServiceImpl.java b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/MasterDataSyncServiceImpl.java new file mode 100644 index 00000000..3fd3f984 --- /dev/null +++ b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/MasterDataSyncServiceImpl.java @@ -0,0 +1,488 @@ +package com.zt.plat.module.base.service.masterdatasync; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.toolkit.IdWorker; +import com.zt.plat.framework.common.exception.util.ServiceExceptionUtil; +import com.zt.plat.module.base.dal.dao.materialclasses.MaterialClassesMapper; +import com.zt.plat.module.base.dal.dao.materialhasclasses.MaterialHasClassesMapper; +import com.zt.plat.module.base.dal.dao.materialhasproperties.MaterialHasPropertiesMapper; +import com.zt.plat.module.base.dal.dao.materialproperties.MaterialPropertiesMapper; +import com.zt.plat.module.base.dal.dataobject.base.MaterialInfomationDO; +import com.zt.plat.module.base.dal.dataobject.materialclasses.MaterialClassesDO; +import com.zt.plat.module.base.dal.dataobject.materialhasclasses.MaterialHasClassesDO; +import com.zt.plat.module.base.dal.dataobject.materialhasproperties.MaterialHasPropertiesDO; +import com.zt.plat.module.base.dal.dataobject.materialproperties.MaterialPropertiesDO; +import com.zt.plat.module.base.dal.dataobject.masterdata.MdmMaterialViewDO; +import com.zt.plat.module.base.dal.mysql.base.MaterialInfomationMapper; +import com.zt.plat.module.base.dal.mysql.masterdata.MdmMaterialViewMapper; +import com.zt.plat.module.base.enums.ErrorCodeConstants; +import com.zt.plat.module.base.framework.sync.config.MasterDataSyncProperties; +import com.zt.plat.module.base.service.masterdatasync.dto.MasterDataSyncCommand; +import com.zt.plat.module.base.service.masterdatasync.dto.MasterDataSyncReport; +import com.zt.plat.module.base.service.masterdatasync.support.MasterDataPropertyDefinition; +import com.zt.plat.module.base.service.masterdatasync.support.MasterDataSyncNotifier; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.support.TransactionTemplate; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.EnumMap; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * 主数据同步核心实现,负责从外部 MDM 视图读取数据并落库到本地 BSE 表。 + */ +@Slf4j +@Service +public class MasterDataSyncServiceImpl implements MasterDataSyncService { + + private static final long ROOT_CLASS_PARENT_ID = 0L; + + @Resource + private MdmMaterialViewMapper mdmMaterialViewMapper; + @Resource + private MaterialInfomationMapper materialInfomationMapper; + @Resource + private MaterialClassesMapper materialClassesMapper; + @Resource + private MaterialHasClassesMapper materialHasClassesMapper; + @Resource + private MaterialPropertiesMapper materialPropertiesMapper; + @Resource + private MaterialHasPropertiesMapper materialHasPropertiesMapper; + @Resource + private TransactionTemplate transactionTemplate; + @Resource + private MasterDataSyncProperties properties; + @Resource + private MasterDataSyncNotifier notifier; + + @Override + public MasterDataSyncReport sync(MasterDataSyncCommand command) { + if (!properties.isEnabled()) { + throw ServiceExceptionUtil.exception(ErrorCodeConstants.MASTER_DATA_SYNC_DISABLED); + } + MasterDataSyncReport report = MasterDataSyncReport.start(command); + List materialCodes = sanitizeCodes(command.getMaterialCodes()); + report.setMaterialCodes(materialCodes); + int batchSize = resolveBatchSize(command.getBatchSize()); + report.setBatchSize(batchSize); + Long recordLimit = resolveRecordLimit(command.getRecordLimit()); + report.setRecordLimit(recordLimit); + LocalDateTime since = command.getSince(); + Map propertyDefinitions = ensurePropertyDefinitions(report); + // 缓存已读取的物料与分类,避免批次间重复查询数据库 + Map materialCacheById = new LinkedHashMap<>(); + Map materialCacheByCode = new LinkedHashMap<>(); + Map categoryCacheByCode = new LinkedHashMap<>(); + + long offset = 0L; + Throwable failure = null; + try { + while (true) { + int fetchSize = batchSize; + if (recordLimit != null) { + long remaining = recordLimit - report.getProcessedRecords(); + if (remaining <= 0) { + break; + } + if (remaining < fetchSize) { + fetchSize = (int) remaining; + } + } + List slice = mdmMaterialViewMapper.selectSlice(offset, fetchSize, since, materialCodes); + if (CollUtil.isEmpty(slice)) { + break; + } + offset += slice.size(); + report.incrementProcessedRecords(slice.size()); + final List batch = slice; + transactionTemplate.executeWithoutResult(status -> processBatch(batch, propertyDefinitions, report, + materialCacheById, materialCacheByCode, categoryCacheByCode)); + } + report.markSuccess(); + return report; + } catch (Throwable ex) { + failure = ex; + report.markFailure(ex.getMessage()); + throw ex; + } finally { + report.finish(); + notifier.dispatch(report, failure); + } + } + + private List sanitizeCodes(List codes) { + if (CollUtil.isEmpty(codes)) { + return Collections.emptyList(); + } + return codes.stream() + .filter(StrUtil::isNotBlank) + .map(code -> StrUtil.trim(code).toUpperCase()) + .distinct() + .collect(Collectors.toList()); + } + + private int resolveBatchSize(Integer requested) { + if (requested != null && requested > 0) { + return requested; + } + return Math.max(1, properties.getBatchSize()); + } + + private Long resolveRecordLimit(Long requested) { + if (requested == null || requested <= 0) { + return null; + } + return requested; + } + + /** + * 确保所有需要的属性定义已经存在,若缺失则自动创建。 + */ + private Map ensurePropertyDefinitions(MasterDataSyncReport report) { + List codes = Arrays.stream(MasterDataPropertyDefinition.values()) + .map(MasterDataPropertyDefinition::getCode) + .toList(); + List existing = materialPropertiesMapper.selectByCodes(codes); + Map existingMap = Optional.ofNullable(existing) + .orElse(Collections.emptyList()) + .stream() + .collect(Collectors.toMap(MaterialPropertiesDO::getCode, Function.identity())); + + Map mapping = new EnumMap<>(MasterDataPropertyDefinition.class); + List pendingInsertDefinitions = new ArrayList<>(); + for (MasterDataPropertyDefinition definition : MasterDataPropertyDefinition.values()) { + MaterialPropertiesDO current = existingMap.get(definition.getCode()); + if (current == null) { + current = MaterialPropertiesDO.builder() + .id(IdWorker.getId()) + .code(definition.getCode()) + .name(definition.getDisplayName()) + .dataType(definition.getDataType()) + .remark("MDM同步自动创建") + .build(); + pendingInsertDefinitions.add(current); + report.incrementInsertedPropertyDefinitions(); + } else { + boolean needUpdate = false; + if (!StrUtil.equals(current.getName(), definition.getDisplayName())) { + current.setName(definition.getDisplayName()); + needUpdate = true; + } + if (!StrUtil.equals(current.getDataType(), definition.getDataType())) { + current.setDataType(definition.getDataType()); + needUpdate = true; + } + if (needUpdate) { + MaterialPropertiesDO update = new MaterialPropertiesDO(); + update.setId(current.getId()); + update.setName(current.getName()); + update.setDataType(current.getDataType()); + materialPropertiesMapper.updateById(update); + report.incrementUpdatedPropertyDefinitions(); + } + } + mapping.put(definition, current); + } + if (CollUtil.isNotEmpty(pendingInsertDefinitions)) { + materialPropertiesMapper.insertBatch(pendingInsertDefinitions); + } + return mapping; + } + + private void processBatch(List batch, + Map propertyDefinitions, + MasterDataSyncReport report, + Map materialCacheById, + Map materialCacheByCode, + Map categoryCacheByCode) { + if (CollUtil.isEmpty(batch)) { + return; + } + // 1. 落库物料主数据 + Map materials = upsertMaterials(batch, report, materialCacheById, materialCacheByCode); + // 2. 读取已存在的分类信息 + Map categoryClasses = loadCategoryClasses(batch, categoryCacheByCode); + // 3. 建立物料与分类的关系 + bindMaterialClasses(batch, materials, categoryClasses, report); + // 4. 写入物料属性及属性值 + upsertMaterialProperties(batch, materials, propertyDefinitions, report); + } + + private Map loadCategoryClasses(List batch, + Map categoryCacheByCode) { + Set requestedCodes = batch.stream() + .map(MdmMaterialViewDO::getCategoryCode) + .map(this::normalizeValue) + .filter(Objects::nonNull) + .collect(Collectors.toCollection(LinkedHashSet::new)); + if (requestedCodes.isEmpty()) { + return Collections.emptyMap(); + } + Map mapping = requestedCodes.stream() + .map(code -> new Object[]{code, categoryCacheByCode.get(code)}) + .filter(pair -> pair[1] != null) + .collect(Collectors.toMap(pair -> (String) pair[0], pair -> (MaterialClassesDO) pair[1], (a, b) -> a, LinkedHashMap::new)); + Set missing = new LinkedHashSet<>(requestedCodes); + missing.removeIf(mapping::containsKey); + if (!missing.isEmpty()) { + List newlyLoaded = materialClassesMapper.selectByCodes(missing); + Optional.ofNullable(newlyLoaded) + .orElse(Collections.emptyList()) + .forEach(item -> { + String code = normalizeValue(item.getCode()); + if (code != null) { + categoryCacheByCode.put(code, item); + mapping.put(code, item); + } + }); + missing.removeIf(mapping::containsKey); + if (!missing.isEmpty()) { + List preview = missing.stream().limit(10).toList(); + log.warn("当前批次存在 {} 个分类未同步,示例: {}", missing.size(), preview); + } + } + return mapping; + } + + private Map upsertMaterials(List batch, + MasterDataSyncReport report, + Map materialCacheById, + Map materialCacheByCode) { + Set sourceIds = batch.stream() + .map(MdmMaterialViewDO::getCodeId) + .filter(Objects::nonNull) + .filter(id -> id > 0) + .collect(Collectors.toCollection(LinkedHashSet::new)); + if (sourceIds.isEmpty()) { + log.warn("本次批次缺少有效 CODEID,无法同步物料主数据"); + return Collections.emptyMap(); + } + Map existingById = sourceIds.stream() + .map(materialCacheById::get) + .filter(Objects::nonNull) + .collect(Collectors.toMap(MaterialInfomationDO::getId, Function.identity(), (a, b) -> a, LinkedHashMap::new)); + Set missingIds = new LinkedHashSet<>(sourceIds); + missingIds.removeIf(existingById::containsKey); + if (!missingIds.isEmpty()) { + List fetched = materialInfomationMapper.selectBatchIds(missingIds); + Optional.ofNullable(fetched) + .orElse(Collections.emptyList()) + .forEach(item -> { + if (item.getId() != null) { + existingById.put(item.getId(), item); + materialCacheById.put(item.getId(), item); + String normalizedCode = normalizeValue(item.getCode()); + if (normalizedCode != null) { + materialCacheByCode.put(normalizedCode, item); + } + } + }); + } + Map mapping = new LinkedHashMap<>(); + List pendingMaterialInserts = new ArrayList<>(); + for (MdmMaterialViewDO item : batch) { + Long codeId = item.getCodeId(); + if (codeId == null || codeId <= 0) { + log.warn("物料 {} 缺少主键 CODEID,已跳过", item.getMaterialCode()); + continue; + } + String code = normalizeValue(item.getMaterialCode()); + if (code == null) { + continue; + } + MaterialInfomationDO current = existingById.get(codeId); + String name = normalizeValue(item.getMaterialName()); + if (current == null) { + MaterialInfomationDO created = MaterialInfomationDO.builder() + .id(codeId) + .code(code) + .name(StrUtil.emptyIfNull(name)) + .remark(null) + .build(); + pendingMaterialInserts.add(created); + existingById.put(codeId, created); + materialCacheById.put(codeId, created); + materialCacheByCode.put(code, created); + mapping.put(code, created); + report.incrementInsertedMaterials(); + continue; + } + + boolean needUpdate = false; + MaterialInfomationDO update = null; + if (!StrUtil.equals(current.getCode(), code)) { + current.setCode(code); + needUpdate = true; + } + if (name != null && !StrUtil.equals(current.getName(), name)) { + current.setName(name); + needUpdate = true; + } + if (needUpdate) { + update = new MaterialInfomationDO(); + update.setId(current.getId()); + update.setCode(current.getCode()); + update.setName(current.getName()); + materialInfomationMapper.updateById(update); + report.incrementUpdatedMaterials(); + } + mapping.put(code, current); + materialCacheByCode.put(code, current); + } + if (CollUtil.isNotEmpty(pendingMaterialInserts)) { + materialInfomationMapper.insertBatch(pendingMaterialInserts); + } + return mapping; + } + + private void bindMaterialClasses(List batch, + Map materials, + Map categoryClasses, + MasterDataSyncReport report) { + if (materials.isEmpty() || categoryClasses.isEmpty()) { + return; + } + List infoIds = batch.stream() + .map(MdmMaterialViewDO::getMaterialCode) + .map(this::normalizeValue) + .map(materials::get) + .filter(Objects::nonNull) + .map(MaterialInfomationDO::getId) + .filter(Objects::nonNull) + .distinct() + .collect(Collectors.toList()); + Map existingRelations = materialHasClassesMapper.selectByInfoIds(infoIds) + .stream() + .collect(Collectors.toMap(MaterialHasClassesDO::getInfomationId, Function.identity(), (a, b) -> a)); + List relationsToInsert = new ArrayList<>(); + for (MdmMaterialViewDO item : batch) { + String materialCode = normalizeValue(item.getMaterialCode()); + MaterialInfomationDO info = materials.get(materialCode); + if (info == null) { + continue; + } + String categoryCode = normalizeValue(item.getCategoryCode()); + MaterialClassesDO cls = categoryClasses.get(categoryCode); + if (cls == null) { + continue; + } + MaterialHasClassesDO relation = existingRelations.get(info.getId()); + if (relation == null) { + MaterialHasClassesDO created = MaterialHasClassesDO.builder() + .infomationId(info.getId()) + .classesId(cls.getId()) + .build(); + relationsToInsert.add(created); + existingRelations.put(info.getId(), created); + report.incrementCreatedClassRelations(); + } else if (!Objects.equals(relation.getClassesId(), cls.getId())) { + MaterialHasClassesDO update = new MaterialHasClassesDO(); + update.setId(relation.getId()); + update.setClassesId(cls.getId()); + materialHasClassesMapper.updateById(update); + relation.setClassesId(cls.getId()); + report.incrementUpdatedClassRelations(); + } + } + if (CollUtil.isNotEmpty(relationsToInsert)) { + materialHasClassesMapper.insertBatch(relationsToInsert); + } + } + + private void upsertMaterialProperties(List batch, + Map materials, + Map propertyDefinitions, + MasterDataSyncReport report) { + if (materials.isEmpty() || propertyDefinitions.isEmpty()) { + return; + } + List infoIds = batch.stream() + .map(MdmMaterialViewDO::getMaterialCode) + .map(this::normalizeValue) + .map(materials::get) + .filter(Objects::nonNull) + .map(MaterialInfomationDO::getId) + .filter(Objects::nonNull) + .distinct() + .collect(Collectors.toList()); + List propertyIds = propertyDefinitions.values().stream() + .map(MaterialPropertiesDO::getId) + .filter(Objects::nonNull) + .distinct() + .collect(Collectors.toList()); + Map existing = materialHasPropertiesMapper + .selectByInfoIdsAndPropertyIds(infoIds, propertyIds) + .stream() + .collect(Collectors.toMap(item -> buildRelationKey(item.getInfomationId(), item.getPropertiesId()), + Function.identity(), (a, b) -> a)); + List propertyRelationsToInsert = new ArrayList<>(); + for (MdmMaterialViewDO item : batch) { + String materialCode = normalizeValue(item.getMaterialCode()); + MaterialInfomationDO info = materials.get(materialCode); + if (info == null || info.getId() == null) { + continue; + } + for (Map.Entry entry : propertyDefinitions.entrySet()) { + MaterialPropertiesDO property = entry.getValue(); + if (property == null || property.getId() == null) { + continue; + } + String value = normalizeValue(entry.getKey().extractValue(item)); + if (value == null) { + continue; + } + String key = buildRelationKey(info.getId(), property.getId()); + MaterialHasPropertiesDO relation = existing.get(key); + if (relation == null) { + MaterialHasPropertiesDO created = MaterialHasPropertiesDO.builder() + .infomationId(info.getId()) + .propertiesId(property.getId()) + .value(value) + .sort(entry.getKey().getSort()) + .isKey(0) + .isMetering(0) + .build(); + propertyRelationsToInsert.add(created); + existing.put(key, created); + report.incrementInsertedPropertyValues(); + } else if (!StrUtil.equals(relation.getValue(), value) + || !Objects.equals(relation.getSort(), entry.getKey().getSort())) { + MaterialHasPropertiesDO update = new MaterialHasPropertiesDO(); + update.setId(relation.getId()); + update.setValue(value); + update.setSort(entry.getKey().getSort()); + materialHasPropertiesMapper.updateById(update); + relation.setValue(value); + relation.setSort(entry.getKey().getSort()); + report.incrementUpdatedPropertyValues(); + } + } + } + if (CollUtil.isNotEmpty(propertyRelationsToInsert)) { + materialHasPropertiesMapper.insertBatch(propertyRelationsToInsert); + } + } + + private String buildRelationKey(Long infoId, Long propertyId) { + return infoId + ":" + propertyId; + } + + private String normalizeValue(String value) { + return StrUtil.isBlank(value) ? null : StrUtil.trim(value); + } +} diff --git a/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/dto/MasterDataCategorySyncReport.java b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/dto/MasterDataCategorySyncReport.java new file mode 100644 index 00000000..50985d12 --- /dev/null +++ b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/dto/MasterDataCategorySyncReport.java @@ -0,0 +1,59 @@ +package com.zt.plat.module.base.service.masterdatasync.dto; + +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 物料分类同步执行结果。 + */ +@Data +public class MasterDataCategorySyncReport { + + private long processedCategories; + private long insertedCategories; + private long updatedCategories; + private long missingParentReferences; + private boolean success; + private String message; + private LocalDateTime startedAt; + private LocalDateTime finishedAt; + + public static MasterDataCategorySyncReport start() { + MasterDataCategorySyncReport report = new MasterDataCategorySyncReport(); + report.setStartedAt(LocalDateTime.now()); + report.setSuccess(false); + report.setMessage("执行中"); + return report; + } + + public void markSuccess() { + this.success = true; + this.message = "执行成功"; + } + + public void markFailure(String message) { + this.success = false; + this.message = message; + } + + public void finish() { + this.finishedAt = LocalDateTime.now(); + } + + public void incrementProcessed(long delta) { + this.processedCategories += delta; + } + + public void incrementInserted() { + this.insertedCategories++; + } + + public void incrementUpdated() { + this.updatedCategories++; + } + + public void incrementMissingParent() { + this.missingParentReferences++; + } +} diff --git a/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/dto/MasterDataSyncCommand.java b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/dto/MasterDataSyncCommand.java new file mode 100644 index 00000000..cbc32777 --- /dev/null +++ b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/dto/MasterDataSyncCommand.java @@ -0,0 +1,33 @@ +package com.zt.plat.module.base.service.masterdatasync.dto; + +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 主数据同步的入参模型。 + */ +@Data +public class MasterDataSyncCommand { + + /** + * 增量同步的起始时间,空值表示全量。 + */ + private LocalDateTime since; + + /** + * 单批拉取的记录数,空值取配置默认值。 + */ + private Integer batchSize; + + /** + * 需要限定同步范围的物料编码集合。 + */ + private List materialCodes; + + /** + * 本次同步允许处理的最大记录数,空值表示不限制。 + */ + private Long recordLimit; +} diff --git a/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/dto/MasterDataSyncReport.java b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/dto/MasterDataSyncReport.java new file mode 100644 index 00000000..aa5300ca --- /dev/null +++ b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/dto/MasterDataSyncReport.java @@ -0,0 +1,104 @@ +package com.zt.plat.module.base.service.masterdatasync.dto; + +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.Collections; +import java.util.List; + +/** + * 主数据同步的执行结果统计。 + */ +@Data +public class MasterDataSyncReport { + + private long processedRecords; + private long insertedMaterials; + private long updatedMaterials; + private long insertedClasses; + private long updatedClasses; + private long createdClassRelations; + private long updatedClassRelations; + private long insertedPropertyDefinitions; + private long updatedPropertyDefinitions; + private long insertedPropertyValues; + private long updatedPropertyValues; + private LocalDateTime startedAt; + private LocalDateTime finishedAt; + private boolean success; + private String message; + private Integer batchSize; + private LocalDateTime since; + private List materialCodes = Collections.emptyList(); + private Long recordLimit; + + public static MasterDataSyncReport start(MasterDataSyncCommand command) { + MasterDataSyncReport report = new MasterDataSyncReport(); + report.setStartedAt(LocalDateTime.now()); + report.setBatchSize(command.getBatchSize()); + report.setSince(command.getSince()); + report.setMaterialCodes(command.getMaterialCodes()); + report.setRecordLimit(command.getRecordLimit()); + report.setSuccess(false); + report.setMessage("执行中"); + return report; + } + + public void finish() { + this.finishedAt = LocalDateTime.now(); + } + + public void markSuccess() { + this.success = true; + this.message = "执行成功"; + } + + public void markFailure(String message) { + this.success = false; + this.message = message; + } + + public void incrementProcessedRecords(long delta) { + this.processedRecords += delta; + } + + public void incrementInsertedMaterials() { + this.insertedMaterials++; + } + + public void incrementUpdatedMaterials() { + this.updatedMaterials++; + } + + public void incrementInsertedClasses() { + this.insertedClasses++; + } + + public void incrementUpdatedClasses() { + this.updatedClasses++; + } + + public void incrementCreatedClassRelations() { + this.createdClassRelations++; + } + + public void incrementUpdatedClassRelations() { + this.updatedClassRelations++; + } + + public void incrementInsertedPropertyDefinitions() { + this.insertedPropertyDefinitions++; + } + + public void incrementUpdatedPropertyDefinitions() { + this.updatedPropertyDefinitions++; + } + + public void incrementInsertedPropertyValues() { + this.insertedPropertyValues++; + } + + public void incrementUpdatedPropertyValues() { + this.updatedPropertyValues++; + } +} diff --git a/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/support/MasterDataPropertyDefinition.java b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/support/MasterDataPropertyDefinition.java new file mode 100644 index 00000000..33545eef --- /dev/null +++ b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/support/MasterDataPropertyDefinition.java @@ -0,0 +1,52 @@ +package com.zt.plat.module.base.service.masterdatasync.support; + +import com.zt.plat.module.base.dal.dataobject.masterdata.MdmMaterialViewDO; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.time.format.DateTimeFormatter; +import java.util.function.Function; + +/** + * 源视图字段与物料属性定义之间的标准映射关系。 + */ +@Getter +@RequiredArgsConstructor +public enum MasterDataPropertyDefinition { + + BASE_UNIT_CODE("MTRL_BASE_UNIT_CODE", "基本计量单位编码", 50L, MdmMaterialViewDO::getBaseUnitCode, "STRING"), + BASE_UNIT_NAME("MTRL_BASE_UNIT_NAME", "基本计量单位描述", 60L, MdmMaterialViewDO::getBaseUnitName, "STRING"), + SHORT_DESCRIPTION("MTRL_SHORT_DESC", "短描述", 70L, MdmMaterialViewDO::getShortDescription, "STRING"), + LONG_DESCRIPTION("MTRL_LONG_DESC", "长描述", 80L, MdmMaterialViewDO::getLongDescription, "STRING"), + CHALCO_CODE("MTRL_CHALCO_CODE", "中铝编码", 90L, MdmMaterialViewDO::getChalcoCode, "STRING"), + SPECIFICATION("MTRL_SPECIFICATION", "规格", 100L, MdmMaterialViewDO::getSpecification, "STRING"), + MODEL("MTRL_MODEL", "型号", 110L, MdmMaterialViewDO::getModel, "STRING"), + TEXTURE("MTRL_TEXTURE", "材质", 120L, MdmMaterialViewDO::getTexture, "STRING"), + DRAWING_NUMBER("MTRL_DRAWING_NUMBER", "图号", 130L, MdmMaterialViewDO::getDrawingNumber, "STRING"), + ORDER_NUMBER("MTRL_ORDER_NUMBER", "订货号", 140L, MdmMaterialViewDO::getOrderNumber, "STRING"), + OTHER_PARAMETERS("MTRL_OTHER_PARAMETERS", "其它参数", 150L, MdmMaterialViewDO::getOtherParameters, "STRING"), + EQUIPMENT_CATEGORY("MTRL_EQUIPMENT_CATEGORY", "设备类别", 160L, MdmMaterialViewDO::getEquipmentCategory, "STRING"), + MANUFACTURER("MTRL_MANUFACTURER", "主机生产商", 170L, MdmMaterialViewDO::getManufacturer, "STRING"), + SOURCE("MTRL_SOURCE", "来源", 180L, MdmMaterialViewDO::getSource, "STRING"), + RECORD_TIME("MTRL_RECORD_TIME", "记录时间", 190L, + source -> source.getRecordTime() == null ? null : source.getRecordTime().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME), + "DATETIME"); + + private final String code; + private final String displayName; + private final long sort; + private final Function extractor; + private final String dataType; + + public String extractValue(MdmMaterialViewDO source) { + if (source == null) { + return null; + } + String value = extractor.apply(source); + if (value == null) { + return null; + } + value = value.trim(); + return value.isEmpty() ? null : value; + } +} diff --git a/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/support/MasterDataSyncNotificationPayload.java b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/support/MasterDataSyncNotificationPayload.java new file mode 100644 index 00000000..995ef43b --- /dev/null +++ b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/support/MasterDataSyncNotificationPayload.java @@ -0,0 +1,16 @@ +package com.zt.plat.module.base.service.masterdatasync.support; + +import com.zt.plat.module.base.service.masterdatasync.dto.MasterDataSyncReport; +import lombok.AllArgsConstructor; +import lombok.Data; + +/** + * 同步结束后推送给下游监听方的 JSON 载荷。 + */ +@Data +@AllArgsConstructor +public class MasterDataSyncNotificationPayload { + + private MasterDataSyncReport report; + private String errorMessage; +} diff --git a/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/support/MasterDataSyncNotifier.java b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/support/MasterDataSyncNotifier.java new file mode 100644 index 00000000..32037ed1 --- /dev/null +++ b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/service/masterdatasync/support/MasterDataSyncNotifier.java @@ -0,0 +1,61 @@ +package com.zt.plat.module.base.service.masterdatasync.support; + +import cn.hutool.core.util.StrUtil; +import com.zt.plat.framework.common.util.json.JsonUtils; +import com.zt.plat.module.base.framework.sync.config.MasterDataSyncProperties; +import com.zt.plat.module.base.service.masterdatasync.dto.MasterDataSyncReport; +import lombok.extern.slf4j.Slf4j; +import okhttp3.MediaType; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Component; + +import java.io.IOException; + +/** + * 在同步结束后发送回调通知。 + */ +@Slf4j +@Component +public class MasterDataSyncNotifier { + + private static final MediaType JSON = MediaType.get("application/json; charset=UTF-8"); + + private final OkHttpClient httpClient; + private final MasterDataSyncProperties properties; + + public MasterDataSyncNotifier(@Qualifier("masterDataSyncOkHttpClient") OkHttpClient httpClient, + MasterDataSyncProperties properties) { + this.httpClient = httpClient; + this.properties = properties; + } + + public void dispatch(MasterDataSyncReport report, Throwable failure) { + if (report == null || StrUtil.isBlank(properties.getCallbackUrl())) { + return; + } + if (report.isSuccess() && !properties.isNotifyOnSuccess()) { + return; + } + if (!report.isSuccess() && !properties.isNotifyOnFailure()) { + return; + } + MasterDataSyncNotificationPayload payload = new MasterDataSyncNotificationPayload(report, + failure == null ? null : failure.getMessage()); + RequestBody body = RequestBody.create(JSON, JsonUtils.toJsonString(payload)); + Request.Builder builder = new Request.Builder() + .url(properties.getCallbackUrl()) + .post(body); + properties.getCallbackHeaders().forEach(builder::addHeader); + try (Response response = httpClient.newCall(builder.build()).execute()) { + if (!response.isSuccessful()) { + log.warn("主数据同步回调响应非成功状态: {}", response.code()); + } + } catch (IOException ex) { + log.warn("调用主数据同步回调接口失败", ex); + } + } +} diff --git a/zt-module-base/zt-module-base-server/src/main/resources/mapper/masterdata/MdmMaterialCategoryMapper.xml b/zt-module-base/zt-module-base-server/src/main/resources/mapper/masterdata/MdmMaterialCategoryMapper.xml new file mode 100644 index 00000000..426986bb --- /dev/null +++ b/zt-module-base/zt-module-base-server/src/main/resources/mapper/masterdata/MdmMaterialCategoryMapper.xml @@ -0,0 +1,17 @@ + + + + + + + diff --git a/zt-module-base/zt-module-base-server/src/main/resources/mapper/masterdata/MdmMaterialViewMapper.xml b/zt-module-base/zt-module-base-server/src/main/resources/mapper/masterdata/MdmMaterialViewMapper.xml new file mode 100644 index 00000000..0e3c31e2 --- /dev/null +++ b/zt-module-base/zt-module-base-server/src/main/resources/mapper/masterdata/MdmMaterialViewMapper.xml @@ -0,0 +1,71 @@ + + + + + + a.codeid AS code_id, + a.code AS material_code, + a.categorycode AS category_code, + a.categoryname AS category_name, + a.desc1 AS material_name, + a.desc6 AS base_unit_code, + a.desc19 AS base_unit_name, + a.descshort AS short_description, + a.desclong AS long_description, + a.desc86 AS chalco_code, + b.pur_class AS major_class_code, + c.desc1 AS major_class_name, + a.desc9 AS specification, + a.desc10 AS model, + a.desc11 AS texture, + a.desc12 AS drawing_number, + a.desc13 AS order_number, + a.desc14 AS other_parameters, + a.desc15 AS equipment_category, + a.desc16 AS manufacturer, + a.desc17 AS source, + a.recordtime AS record_time + + + + mdm_wlzsj_code a + INNER JOIN z_pur_class b ON a.codeid = b.codeid + INNER JOIN mdm_wlfl_code c ON b.pur_class = c.code + + + + + + diff --git a/zt-module-base/主数据同步说明.md b/zt-module-base/主数据同步说明.md new file mode 100644 index 00000000..33881d50 --- /dev/null +++ b/zt-module-base/主数据同步说明.md @@ -0,0 +1,140 @@ +# 主数据同步功能说明 + + +## 功能概述 + +主数据同步由“分类同步 + 物料同步”两条独立链路组成: + +1. 分类同步:从 `mdm_wlfl_code` 全量拉取 `01 / 0101 / 010101` 结构的编码,生成 BSE 三层分类。 +2. 物料同步:从 `mdm_material_view` 拉取物料主数据,依赖已存在的分类信息完成入库。 +3. 物料同步会维护物料与分类绑定关系,并将非主表字段落入属性表。 +4. 同步结束后可选地向外部回调推送执行报告。 + +## 同步入口 + +### 分类同步接口 + +- **接口地址**:`POST /base/master-data-sync/categories` +- **权限点**:`base:master-data-sync:categories` +- **请求体**:无(全量同步) +- **返回体**:`MasterDataCategorySyncReport` + +字段说明: + +- `processedCategories`:本次遍历的分类数量。 +- `insertedCategories` / `updatedCategories`:新增或更新的分类记录数。 +- `missingParentReferences`:外部数据缺失父级时的降级次数(会挂到根节点)。 +- `success`、`message`、`startedAt`、`finishedAt`:同物料同步。 + +> ⚠️ 分类同步需先于物料同步执行,确保 BSE 中已存在三层分类结构。 + +### 物料同步接口 + +- **接口地址**:`POST /base/master-data-sync/execute` +- **权限点**:`base:master-data-sync:execute` +- **请求体**: + + | 字段 | 类型 | 说明 | + | --- | --- | --- | + | `since` | `yyyy-MM-dd HH:mm:ss` | (可选)增量同步起始时间,空值表示全量。 | + | `batchSize` | `Integer` | (可选)单批拉取条数,未填写则使用配置默认值。 | + | `materialCodes` | `List` | (可选)限定仅同步指定物料编码,留空同步全部。 | + | `recordLimit` | `Long` | (可选)本次同步允许处理的最大记录数,留空则不做总量限制。 | + +**返回体**为 `MasterDataSyncReport`,涵盖以下关键指标: + +- `processedRecords`:拉取并处理的记录数。 +- `insertedMaterials` / `updatedMaterials`:新增或更新的物料数量。 +- `createdClassRelations` / `updatedClassRelations`:物料与分类的关系处理次数。 +- `insertedPropertyDefinitions` / `updatedPropertyDefinitions`:属性定义的补齐情况。 +- `insertedPropertyValues` / `updatedPropertyValues`:属性值的写入情况。 +- `success` + `message`:执行状态及提示语。 +- `startedAt` / `finishedAt`:执行起止时间。 +- `recordLimit`:若请求指定了总量限制,会在报告中回显该值。 + +## 数据处理策略 + +1. **属性字典**: + - 程序会检查 `MasterDataPropertyDefinition` 枚举列出的全部属性(例如类别编码、规格、材质等)。 + - 若属性定义不存在即创建,存在但名称/排序有差异会自动更新。 +2. **分类管理**: + - 通过分类同步接口预先写入 `01/0101/010101` 三层数据,物料同步阶段仅检查并使用现有分类,如缺失则记录日志并跳过绑定。 +3. **物料主体**: + - 按 `material_code` 进行 upsert,保留基础字段(物料编码、通用信息等)。 +4. **分类绑定**: + - 若物料已有绑定但分类变化,则更新关系;否则创建新绑定。 +5. **属性值写入**: + - 对比新旧值,仅在有变化或缺失时写入,避免无效更新。 + +## 配置项 + +在 `application-*.yml` 中通过 `base.master-data-sync` 节点进行控制: + +```yaml +base: + master-data-sync: + enabled: true # 是否开放同步入口 + batch-size: 500 # 默认批量大小 + source-datasource-name: mdm # 指向外部 MDM 的动态数据源 + notify-on-success: true # 成功时是否回调 + notify-on-failure: true # 失败时是否回调 + callback-url: http://example/callback + callback-headers: + X-TOKEN: xxx + http: + connect-timeout: 5s + read-timeout: 30s + write-timeout: 30s +``` + +> ⚠️ 请确保在 `datasource.dynamic` 中配置名为 `mdm`(或 `source-datasource-name` 指定值)的数据源,并指向外部 MDM 数据库。 + +## 数据源说明 + +- `master`:默认业务库(BSE 表所在库),所有增删改依旧走 `master` 数据源,这部分无需额外配置。 +- `mdm`:主数据来源库(外部 MySQL)。`MdmMaterialViewMapper`、`MdmMaterialCategoryMapper` 均通过 `@DS("mdm")` 读取该库。 +- `base.master-data-sync.source-datasource-name`:若外部库名称不是 `mdm`,可在此覆盖,示例: + + ```yaml + base: + master-data-sync: + source-datasource-name: mdm + datasource: + dynamic: + datasource: + master: { ...本地库配置... } + mdm: { url: jdbc:mysql://mdm-host/mdm, username: xxx, password: yyy } + ``` + +> ✅ 强调:主数据读取始终走 `mdm`(或你在 `source-datasource-name` 中声明的别名),不要与默认 `master` 数据源混淆。 + +## 回调机制 + +- 当配置了 `callbackUrl` 时,系统会在同步结束后推送 JSON 结果。 +- 推送内容为: + +```json +{ + "report": { ...MasterDataSyncReport... }, + "errorMessage": "可选的错误提示" +} +``` + +- 仅成功/失败分别受 `notifyOnSuccess`、`notifyOnFailure` 控制。 +- `callbackHeaders` 支持附加认证信息,如 Token、租户标识等。 + +## 常见问题排查 + +| 问题 | 检查点 | +| --- | --- | +| 数据源连接失败 | 确认 `mdm` 数据源配置、账号权限、网络可达性。 | +| 同步后未触发回调 | 检查 `callbackUrl`、`notify-on-*` 配置,以及目标地址是否可达。 | +| 属性值未生效 | 查看 `MasterDataPropertyDefinition` 是否包含该字段,或字段值是否为空/仅有空格。 | +| 只需同步单个物料 | 调用接口时在 `materialCodes` 中传入目标编码即可。 | + +## 建议的使用流程 + +1. 配置并验证外部数据源与 `base.master-data-sync` 参数。 +2. 先执行“分类同步接口”,确认三层分类齐全。 +3. 再执行“物料同步接口”,并确认报表数据、回调通知。 +4. 线上场景可定期以 `since` 参数驱动增量物料同步,也可按需指定 `materialCodes` 触发刷新;分类若有改动,可重新全量执行一次分类同步。 From 116f2ba38609ffbb9e6a1705edf23d05722e7a31 Mon Sep 17 00:00:00 2001 From: guojunyun Date: Thu, 9 Oct 2025 09:34:08 +0800 Subject: [PATCH 5/9] =?UTF-8?q?=E5=90=88=E5=90=8C=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E7=BB=93=E6=9E=84=E4=BF=AE=E6=94=B9=E3=80=81=E5=90=88=E5=90=8C?= =?UTF-8?q?=E5=AE=A1=E6=A0=B8=E6=8E=A5=E5=8F=A3=E9=83=A8=E5=88=86=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../enums/contract/AuditResultEnum.java | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 zt-module-contract-order/zt-module-contract-order-api/src/main/java/com/zt/plat/module/contractorder/enums/contract/AuditResultEnum.java diff --git a/zt-module-contract-order/zt-module-contract-order-api/src/main/java/com/zt/plat/module/contractorder/enums/contract/AuditResultEnum.java b/zt-module-contract-order/zt-module-contract-order-api/src/main/java/com/zt/plat/module/contractorder/enums/contract/AuditResultEnum.java new file mode 100644 index 00000000..14da5a35 --- /dev/null +++ b/zt-module-contract-order/zt-module-contract-order-api/src/main/java/com/zt/plat/module/contractorder/enums/contract/AuditResultEnum.java @@ -0,0 +1,46 @@ +package com.zt.plat.module.contractorder.enums.contract; + +/** + * 合同审核结果 + */ +public enum AuditResultEnum { + /** + * 合同状态-草稿 + */ + PASS("通过","PASS", null), + /** + * 合同状态-正在审核 + */ + REJECT("驳回","REJECT",null); + + AuditResultEnum(String label, String code, String remark) { + this.label = label; + this.code = code; + this.remark = remark; + } + + /** + * 标签 + */ + private final String label; + /** + * 编码 + */ + private final String code; + /** + * 备注 + */ + private final String remark; + + public String getLabel() { + return label; + } + + public String getCode() { + return code; + } + + public String getRemark() { + return remark; + } +} From 4f50e517b83004ff7f305c6483d3c7a2eabc99a6 Mon Sep 17 00:00:00 2001 From: chenbowen Date: Mon, 27 Oct 2025 11:41:18 +0800 Subject: [PATCH 6/9] =?UTF-8?q?=E8=B0=83=E6=95=B4=E4=B8=9A=E5=8A=A1?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E7=9A=84=E6=97=B6=E5=8C=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- deployment.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/deployment.yaml b/deployment.yaml index 1da2c085..1d9ccbb6 100644 --- a/deployment.yaml +++ b/deployment.yaml @@ -23,6 +23,9 @@ spec: containers: - name: base-server image: 172.16.46.66:10043/yudao/base-server:VERSION_PLACEHOLDER + env: + - name: TZ + value: Asia/Shanghai readinessProbe: httpGet: path: /actuator/health From 2e65960bf10899cbd357efd4bb535ba8a88f07ba Mon Sep 17 00:00:00 2001 From: chenbowen Date: Thu, 6 Nov 2025 13:41:56 +0800 Subject: [PATCH 7/9] =?UTF-8?q?1.=20=E6=96=B0=E5=A2=9E=E7=89=A9=E6=96=99?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E6=8E=A5=E5=8F=A3=202.=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E9=83=A8=E5=88=86=E6=9C=8D=E5=8A=A1=E5=9B=A0=E4=B8=BA=E5=8C=85?= =?UTF-8?q?=E5=90=8D=E8=AE=BE=E7=BD=AE=E9=94=99=E8=AF=AF=E5=AF=BC=E8=87=B4?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E9=87=87=E9=9B=86=E6=97=A5=E5=BF=97=E7=9A=84?= =?UTF-8?q?=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BusinessDictionaryTypeApi.java | 60 ++++++ .../dto/BusinessDictionaryDataDTO.java | 35 +++ .../dto/BusinessDictionaryTypePageReqDTO.java | 21 ++ .../dto/BusinessDictionaryTypeRespDTO.java | 31 +++ .../dto/BusinessDictionaryTypeSaveReqDTO.java | 38 ++++ .../DepartmentMaterialApi.java | 51 +++++ .../dto/DepartmentMaterialPageReqDTO.java | 49 +++++ .../dto/DepartmentMaterialRespDTO.java | 61 ++++++ .../dto/DepartmentMaterialSaveReqDTO.java | 39 ++++ .../materialclasses/MaterialClassesApi.java | 56 +++++ .../dto/MaterialClassesPageReqDTO.java | 36 ++++ .../dto/MaterialClassesRespDTO.java | 34 +++ .../dto/MaterialClassesSaveReqDTO.java | 33 +++ .../dto/MaterialClassesTreeRespDTO.java | 35 +++ .../MaterialHasClassesApi.java | 51 +++++ .../dto/MaterialHasClassesPageReqDTO.java | 27 +++ .../dto/MaterialHasClassesRespDTO.java | 25 +++ .../dto/MaterialHasClassesSaveReqDTO.java | 23 ++ .../MaterialHasPropertiesApi.java | 51 +++++ .../dto/MaterialHasPropertiesPageReqDTO.java | 42 ++++ .../dto/MaterialHasPropertiesRespDTO.java | 40 ++++ .../dto/MaterialHasPropertiesSaveReqDTO.java | 40 ++++ .../MaterialPropertiesApi.java | 57 +++++ .../dto/MaterialPropertiesPageReqDTO.java | 42 ++++ .../dto/MaterialPropertiesRespDTO.java | 49 +++++ .../dto/MaterialPropertiesSaveReqDTO.java | 38 ++++ .../MaterialPropertiesSimplePageReqDTO.java | 18 ++ .../dto/MaterialPropertiesSimpleRespDTO.java | 35 +++ .../BusinessDictionaryTypeApiImpl.java | 87 ++++++++ .../DepartmentMaterialApiImpl.java | 64 ++++++ .../MaterialClassesApiImpl.java | 97 +++++++++ .../src/main/resources/logback-spring.xml | 4 +- .../BusinessDictionaryTypeApiImplTest.java | 201 ++++++++++++++++++ .../DepartmentMaterialApiImplTest.java | 146 +++++++++++++ .../MaterialClassesApiImplTest.java | 180 ++++++++++++++++ 35 files changed, 1894 insertions(+), 2 deletions(-) create mode 100644 zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/businessdictionarytype/BusinessDictionaryTypeApi.java create mode 100644 zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/businessdictionarytype/dto/BusinessDictionaryDataDTO.java create mode 100644 zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/businessdictionarytype/dto/BusinessDictionaryTypePageReqDTO.java create mode 100644 zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/businessdictionarytype/dto/BusinessDictionaryTypeRespDTO.java create mode 100644 zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/businessdictionarytype/dto/BusinessDictionaryTypeSaveReqDTO.java create mode 100644 zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/departmentmaterial/DepartmentMaterialApi.java create mode 100644 zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/departmentmaterial/dto/DepartmentMaterialPageReqDTO.java create mode 100644 zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/departmentmaterial/dto/DepartmentMaterialRespDTO.java create mode 100644 zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/departmentmaterial/dto/DepartmentMaterialSaveReqDTO.java create mode 100644 zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialclasses/MaterialClassesApi.java create mode 100644 zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialclasses/dto/MaterialClassesPageReqDTO.java create mode 100644 zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialclasses/dto/MaterialClassesRespDTO.java create mode 100644 zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialclasses/dto/MaterialClassesSaveReqDTO.java create mode 100644 zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialclasses/dto/MaterialClassesTreeRespDTO.java create mode 100644 zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialhasclasses/MaterialHasClassesApi.java create mode 100644 zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialhasclasses/dto/MaterialHasClassesPageReqDTO.java create mode 100644 zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialhasclasses/dto/MaterialHasClassesRespDTO.java create mode 100644 zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialhasclasses/dto/MaterialHasClassesSaveReqDTO.java create mode 100644 zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialhasproperties/MaterialHasPropertiesApi.java create mode 100644 zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialhasproperties/dto/MaterialHasPropertiesPageReqDTO.java create mode 100644 zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialhasproperties/dto/MaterialHasPropertiesRespDTO.java create mode 100644 zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialhasproperties/dto/MaterialHasPropertiesSaveReqDTO.java create mode 100644 zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialproperties/MaterialPropertiesApi.java create mode 100644 zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialproperties/dto/MaterialPropertiesPageReqDTO.java create mode 100644 zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialproperties/dto/MaterialPropertiesRespDTO.java create mode 100644 zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialproperties/dto/MaterialPropertiesSaveReqDTO.java create mode 100644 zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialproperties/dto/MaterialPropertiesSimplePageReqDTO.java create mode 100644 zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialproperties/dto/MaterialPropertiesSimpleRespDTO.java create mode 100644 zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/api/businessdictionarytype/BusinessDictionaryTypeApiImpl.java create mode 100644 zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/api/departmentmaterial/DepartmentMaterialApiImpl.java create mode 100644 zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/api/materialclasses/MaterialClassesApiImpl.java create mode 100644 zt-module-base/zt-module-base-server/src/test/java/com/zt/plat/module/base/api/businessdictionarytype/BusinessDictionaryTypeApiImplTest.java create mode 100644 zt-module-base/zt-module-base-server/src/test/java/com/zt/plat/module/base/api/departmentmaterial/DepartmentMaterialApiImplTest.java create mode 100644 zt-module-base/zt-module-base-server/src/test/java/com/zt/plat/module/base/api/materialclasses/MaterialClassesApiImplTest.java diff --git a/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/businessdictionarytype/BusinessDictionaryTypeApi.java b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/businessdictionarytype/BusinessDictionaryTypeApi.java new file mode 100644 index 00000000..197b2817 --- /dev/null +++ b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/businessdictionarytype/BusinessDictionaryTypeApi.java @@ -0,0 +1,60 @@ +package com.zt.plat.module.base.api.businessdictionarytype; + +import com.zt.plat.framework.common.pojo.CommonResult; +import com.zt.plat.framework.common.pojo.PageResult; +import com.zt.plat.module.base.api.businessdictionarytype.dto.BusinessDictionaryDataDTO; +import com.zt.plat.module.base.api.businessdictionarytype.dto.BusinessDictionaryTypePageReqDTO; +import com.zt.plat.module.base.api.businessdictionarytype.dto.BusinessDictionaryTypeRespDTO; +import com.zt.plat.module.base.api.businessdictionarytype.dto.BusinessDictionaryTypeSaveReqDTO; +import com.zt.plat.module.base.enums.ApiConstants; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; + +import java.util.List; + +@FeignClient(name = ApiConstants.NAME) +@Tag(name = "RPC 服务 - 业务字典类型") +public interface BusinessDictionaryTypeApi { + + String PREFIX = ApiConstants.PREFIX + "/business-dictionary-type"; + + @PostMapping(PREFIX + "/create") + @Operation(summary = "创建业务字典类型") + CommonResult createBusinessDictionaryType(@Valid @RequestBody BusinessDictionaryTypeSaveReqDTO createReqDTO); + + @PutMapping(PREFIX + "/update") + @Operation(summary = "更新业务字典类型") + CommonResult updateBusinessDictionaryType(@Valid @RequestBody BusinessDictionaryTypeSaveReqDTO updateReqDTO); + + @DeleteMapping(PREFIX + "/delete") + @Operation(summary = "删除业务字典类型") + CommonResult deleteBusinessDictionaryType(@RequestParam("id") Long id); + + @DeleteMapping(PREFIX + "/delete-list") + @Operation(summary = "批量删除业务字典类型") + CommonResult deleteBusinessDictionaryTypeList(@RequestBody List ids); + + @GetMapping(PREFIX + "/get") + @Operation(summary = "获得业务字典类型") + CommonResult getBusinessDictionaryType(@RequestParam("id") Long id); + + @GetMapping(PREFIX + "/page") + @Operation(summary = "获得业务字典类型分页") + CommonResult> getBusinessDictionaryTypePage(@Valid BusinessDictionaryTypePageReqDTO pageReqDTO); + + @GetMapping(PREFIX + "/business-dictionary-data/list-by-dictionary-type-id") + @Operation(summary = "获得业务字典数据列表") + CommonResult> getBusinessDictionaryDataListByDictionaryTypeId(@RequestParam("dictionaryTypeId") Long dictionaryTypeId); + + @GetMapping(PREFIX + "/business-dictionary-data/list-by-type") + @Operation(summary = "根据字典类型编码获取业务字典数据列表") + CommonResult> getBusinessDictionaryDataListByType(@RequestParam("type") String type); +} diff --git a/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/businessdictionarytype/dto/BusinessDictionaryDataDTO.java b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/businessdictionarytype/dto/BusinessDictionaryDataDTO.java new file mode 100644 index 00000000..1dcf4556 --- /dev/null +++ b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/businessdictionarytype/dto/BusinessDictionaryDataDTO.java @@ -0,0 +1,35 @@ +package com.zt.plat.module.base.api.businessdictionarytype.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 业务字典数据 DTO + */ +@Data +public class BusinessDictionaryDataDTO { + + @Schema(description = "主键ID", example = "1001") + private Long id; + + @Schema(description = "上级字典", example = "2001") + private Long parentId; + + @Schema(description = "字典类型", example = "3001") + private Long dictionaryTypeId; + + @Schema(description = "排序号", example = "10") + private Long sort; + + @Schema(description = "字典标签", example = "状态") + private String label; + + @Schema(description = "字典值", example = "ENABLE") + private String value; + + @Schema(description = "状态(0正常 1停用)", example = "0") + private Long status; + + @Schema(description = "备注", example = "同义词") + private String remark; +} diff --git a/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/businessdictionarytype/dto/BusinessDictionaryTypePageReqDTO.java b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/businessdictionarytype/dto/BusinessDictionaryTypePageReqDTO.java new file mode 100644 index 00000000..03ae629a --- /dev/null +++ b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/businessdictionarytype/dto/BusinessDictionaryTypePageReqDTO.java @@ -0,0 +1,21 @@ +package com.zt.plat.module.base.api.businessdictionarytype.dto; + +import com.zt.plat.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 业务字典类型分页 Request DTO + */ +@Data +public class BusinessDictionaryTypePageReqDTO extends PageParam { + + @Schema(description = "字典名称", example = "物料状态") + private String name; + + @Schema(description = "字典类型", example = "base_material_status") + private String type; + + @Schema(description = "状态(0正常 1停用)", example = "0") + private Long status; +} diff --git a/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/businessdictionarytype/dto/BusinessDictionaryTypeRespDTO.java b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/businessdictionarytype/dto/BusinessDictionaryTypeRespDTO.java new file mode 100644 index 00000000..87f8016f --- /dev/null +++ b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/businessdictionarytype/dto/BusinessDictionaryTypeRespDTO.java @@ -0,0 +1,31 @@ +package com.zt.plat.module.base.api.businessdictionarytype.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 业务字典类型 Response DTO + */ +@Data +public class BusinessDictionaryTypeRespDTO { + + @Schema(description = "主键ID", example = "11771") + private Long id; + + @Schema(description = "字典名称", example = "物料状态") + private String name; + + @Schema(description = "字典类型", example = "base_material_status") + private String type; + + @Schema(description = "状态(0正常 1停用)", example = "0") + private Long status; + + @Schema(description = "备注", example = "基础物料状态") + private String remark; + + @Schema(description = "创建时间") + private LocalDateTime createTime; +} diff --git a/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/businessdictionarytype/dto/BusinessDictionaryTypeSaveReqDTO.java b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/businessdictionarytype/dto/BusinessDictionaryTypeSaveReqDTO.java new file mode 100644 index 00000000..562dd2d7 --- /dev/null +++ b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/businessdictionarytype/dto/BusinessDictionaryTypeSaveReqDTO.java @@ -0,0 +1,38 @@ +package com.zt.plat.module.base.api.businessdictionarytype.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 业务字典类型新增/修改 Request DTO + */ +@Data +public class BusinessDictionaryTypeSaveReqDTO { + + @Schema(description = "主键ID", example = "11771") + private Long id; + + @Schema(description = "字典名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "物料状态") + @NotEmpty(message = "字典名称不能为空") + private String name; + + @Schema(description = "字典类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "base_material_status") + @NotEmpty(message = "字典类型不能为空") + private String type; + + @Schema(description = "状态(0正常 1停用)", example = "0") + private Long status; + + @Schema(description = "备注", example = "基础物料状态") + private String remark; + + @Schema(description = "删除时间") + private LocalDateTime delTime; + + @Schema(description = "业务字典数据列表") + private List businessDictionaryDatas; +} diff --git a/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/departmentmaterial/DepartmentMaterialApi.java b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/departmentmaterial/DepartmentMaterialApi.java new file mode 100644 index 00000000..a737b0da --- /dev/null +++ b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/departmentmaterial/DepartmentMaterialApi.java @@ -0,0 +1,51 @@ +package com.zt.plat.module.base.api.departmentmaterial; + +import com.zt.plat.framework.common.pojo.CommonResult; +import com.zt.plat.framework.common.pojo.PageResult; +import com.zt.plat.module.base.api.departmentmaterial.dto.DepartmentMaterialPageReqDTO; +import com.zt.plat.module.base.api.departmentmaterial.dto.DepartmentMaterialRespDTO; +import com.zt.plat.module.base.api.departmentmaterial.dto.DepartmentMaterialSaveReqDTO; +import com.zt.plat.module.base.enums.ApiConstants; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; + +import java.util.List; + +@FeignClient(name = ApiConstants.NAME) +@Tag(name = "RPC 服务 - 组织架构物料") +public interface DepartmentMaterialApi { + + String PREFIX = ApiConstants.PREFIX + "/department-material"; + + @PostMapping(PREFIX + "/create") + @Operation(summary = "创建组织架构物料") + CommonResult createDepartmentMaterial(@Valid @RequestBody DepartmentMaterialSaveReqDTO createReqDTO); + + @PutMapping(PREFIX + "/update") + @Operation(summary = "更新组织架构物料") + CommonResult updateDepartmentMaterial(@Valid @RequestBody DepartmentMaterialSaveReqDTO updateReqDTO); + + @DeleteMapping(PREFIX + "/delete") + @Operation(summary = "删除组织架构物料") + CommonResult deleteDepartmentMaterial(@RequestParam("id") Long id); + + @DeleteMapping(PREFIX + "/delete-list") + @Operation(summary = "批量删除组织架构物料") + CommonResult deleteDepartmentMaterialList(@RequestBody List ids); + + @GetMapping(PREFIX + "/get") + @Operation(summary = "获得组织架构物料") + CommonResult getDepartmentMaterial(@RequestParam("id") Long id); + + @GetMapping(PREFIX + "/page") + @Operation(summary = "获得组织架构物料分页") + CommonResult> getDepartmentMaterialPage(@Valid DepartmentMaterialPageReqDTO pageReqDTO); +} diff --git a/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/departmentmaterial/dto/DepartmentMaterialPageReqDTO.java b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/departmentmaterial/dto/DepartmentMaterialPageReqDTO.java new file mode 100644 index 00000000..4573034f --- /dev/null +++ b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/departmentmaterial/dto/DepartmentMaterialPageReqDTO.java @@ -0,0 +1,49 @@ +package com.zt.plat.module.base.api.departmentmaterial.dto; + +import com.zt.plat.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; +import java.util.List; + +import static com.zt.plat.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +/** + * 组织架构物料分页 Request DTO + */ +@Data +public class DepartmentMaterialPageReqDTO extends PageParam { + + @Schema(description = "物料信息ID", example = "3923") + private Long infomationId; + + @Schema(description = "物料信息ID集合(内部使用)") + private List infomationIds; + + @Schema(description = "物料分类ID", example = "30114") + private Long classesId; + + @Schema(description = "部门ID", example = "1001") + private Long deptId; + + @Schema(description = "字典数据值-物料类型") + private String dictionaryDataValue; + + @Schema(description = "状态编码", example = "1") + private String status; + + @Schema(description = "物料编码") + private String materialNumber; + + @Schema(description = "物料名称") + private String materialName; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; +} diff --git a/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/departmentmaterial/dto/DepartmentMaterialRespDTO.java b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/departmentmaterial/dto/DepartmentMaterialRespDTO.java new file mode 100644 index 00000000..a7255024 --- /dev/null +++ b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/departmentmaterial/dto/DepartmentMaterialRespDTO.java @@ -0,0 +1,61 @@ +package com.zt.plat.module.base.api.departmentmaterial.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 组织架构物料 Response DTO + */ +@Data +public class DepartmentMaterialRespDTO { + + @Schema(description = "主键ID", example = "5674") + private Long id; + + @Schema(description = "物料信息ID", example = "3923") + private Long infomationId; + + @Schema(description = "物料分类ID", example = "30114") + private Long classesId; + + @Schema(description = "字典数据值-物料类型") + private String dictionaryDataValue; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + + @Schema(description = "部门ID") + private Long deptId; + + @Schema(description = "部门名称") + private String deptName; + + @Schema(description = "物料编码") + private String materialNumber; + + @Schema(description = "物料名称") + private String materialName; + + @Schema(description = "物料大类名称") + private String categoryLargeName; + + @Schema(description = "物料中类名称") + private String categoryMediumName; + + @Schema(description = "物料小类名称") + private String categorySmallName; + + @Schema(description = "物料分类路径") + private String categoryPath; + + @Schema(description = "组织物料类型名称") + private String dictionaryDataLabel; + + @Schema(description = "状态编码") + private String status; +} diff --git a/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/departmentmaterial/dto/DepartmentMaterialSaveReqDTO.java b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/departmentmaterial/dto/DepartmentMaterialSaveReqDTO.java new file mode 100644 index 00000000..a5b0432f --- /dev/null +++ b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/departmentmaterial/dto/DepartmentMaterialSaveReqDTO.java @@ -0,0 +1,39 @@ +package com.zt.plat.module.base.api.departmentmaterial.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * 组织架构物料新增/修改 Request DTO + */ +@Data +public class DepartmentMaterialSaveReqDTO { + + @Schema(description = "主键ID", example = "5674") + private Long id; + + @Schema(description = "部门ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1001") + @NotNull(message = "部门ID不能为空") + private Long deptId; + + @Schema(description = "物料信息ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "3923") + @NotNull(message = "物料信息ID不能为空") + private Long infomationId; + + @Schema(description = "物料分类ID", example = "30114") + private Long classesId; + + @Schema(description = "字典数据值-物料类型", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "字典数据值-物料类型不能为空") + private String dictionaryDataValue; + + @Schema(description = "状态编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotEmpty(message = "状态不能为空") + private String status; + + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "备注不能为空") + private String remark; +} diff --git a/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialclasses/MaterialClassesApi.java b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialclasses/MaterialClassesApi.java new file mode 100644 index 00000000..216a37ed --- /dev/null +++ b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialclasses/MaterialClassesApi.java @@ -0,0 +1,56 @@ +package com.zt.plat.module.base.api.materialclasses; + +import com.zt.plat.framework.common.pojo.CommonResult; +import com.zt.plat.framework.common.pojo.PageResult; +import com.zt.plat.module.base.api.materialclasses.dto.MaterialClassesPageReqDTO; +import com.zt.plat.module.base.api.materialclasses.dto.MaterialClassesRespDTO; +import com.zt.plat.module.base.api.materialclasses.dto.MaterialClassesSaveReqDTO; +import com.zt.plat.module.base.api.materialclasses.dto.MaterialClassesTreeRespDTO; +import com.zt.plat.module.base.enums.ApiConstants; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; + +import java.util.List; + +@FeignClient(name = ApiConstants.NAME) +@Tag(name = "RPC 服务 - 物料分类") +public interface MaterialClassesApi { + + String PREFIX = ApiConstants.PREFIX + "/material-classes"; + + @PostMapping(PREFIX + "/create") + @Operation(summary = "创建物料分类") + CommonResult createMaterialClasses(@Valid @RequestBody MaterialClassesSaveReqDTO createReqDTO); + + @PutMapping(PREFIX + "/update") + @Operation(summary = "更新物料分类") + CommonResult updateMaterialClasses(@Valid @RequestBody MaterialClassesSaveReqDTO updateReqDTO); + + @DeleteMapping(PREFIX + "/delete") + @Operation(summary = "删除物料分类") + CommonResult deleteMaterialClasses(@RequestParam("id") Long id); + + @DeleteMapping(PREFIX + "/delete-list") + @Operation(summary = "批量删除物料分类") + CommonResult deleteMaterialClassesList(@RequestBody List ids); + + @GetMapping(PREFIX + "/get") + @Operation(summary = "获得物料分类") + CommonResult getMaterialClasses(@RequestParam("id") Long id); + + @GetMapping(PREFIX + "/page") + @Operation(summary = "获得物料分类分页") + CommonResult> getMaterialClassesPage(@Valid MaterialClassesPageReqDTO pageReqDTO); + + @GetMapping(PREFIX + "/tree") + @Operation(summary = "获得物料分类树") + CommonResult> getMaterialClassesTree(); +} diff --git a/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialclasses/dto/MaterialClassesPageReqDTO.java b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialclasses/dto/MaterialClassesPageReqDTO.java new file mode 100644 index 00000000..a8390e3e --- /dev/null +++ b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialclasses/dto/MaterialClassesPageReqDTO.java @@ -0,0 +1,36 @@ +package com.zt.plat.module.base.api.materialclasses.dto; + +import com.zt.plat.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static com.zt.plat.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +/** + * 物料分类分页 Request DTO + */ +@Data +public class MaterialClassesPageReqDTO extends PageParam { + + @Schema(description = "父级ID", example = "20706") + private Long parentId; + + @Schema(description = "分类编码") + private String code; + + @Schema(description = "分类名称", example = "原材料") + private String name; + + @Schema(description = "分类级别-用于类别层级(大/中/小类)") + private Long level; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; +} diff --git a/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialclasses/dto/MaterialClassesRespDTO.java b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialclasses/dto/MaterialClassesRespDTO.java new file mode 100644 index 00000000..6a8429ab --- /dev/null +++ b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialclasses/dto/MaterialClassesRespDTO.java @@ -0,0 +1,34 @@ +package com.zt.plat.module.base.api.materialclasses.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 物料分类 Response DTO + */ +@Data +public class MaterialClassesRespDTO { + + @Schema(description = "主键ID", example = "4051") + private Long id; + + @Schema(description = "父级ID", example = "20706") + private Long parentId; + + @Schema(description = "分类编码") + private String code; + + @Schema(description = "分类名称", example = "原材料") + private String name; + + @Schema(description = "分类级别-用于类别层级(大/中/小类)") + private Long level; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "创建时间") + private LocalDateTime createTime; +} diff --git a/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialclasses/dto/MaterialClassesSaveReqDTO.java b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialclasses/dto/MaterialClassesSaveReqDTO.java new file mode 100644 index 00000000..6b5551a3 --- /dev/null +++ b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialclasses/dto/MaterialClassesSaveReqDTO.java @@ -0,0 +1,33 @@ +package com.zt.plat.module.base.api.materialclasses.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import lombok.Data; + +/** + * 物料分类新增/修改 Request DTO + */ +@Data +public class MaterialClassesSaveReqDTO { + + @Schema(description = "主键ID", example = "4051") + private Long id; + + @Schema(description = "父级ID", example = "20706") + private Long parentId; + + @Schema(description = "分类编码", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "分类编码不能为空") + private String code; + + @Schema(description = "分类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "原材料") + @NotEmpty(message = "分类名称不能为空") + private String name; + + @Schema(description = "分类级别-用于类别层级(大/中/小类)") + private Long level; + + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "备注不能为空") + private String remark; +} diff --git a/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialclasses/dto/MaterialClassesTreeRespDTO.java b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialclasses/dto/MaterialClassesTreeRespDTO.java new file mode 100644 index 00000000..6016e51b --- /dev/null +++ b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialclasses/dto/MaterialClassesTreeRespDTO.java @@ -0,0 +1,35 @@ +package com.zt.plat.module.base.api.materialclasses.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; + +/** + * 物料分类树 Response DTO + */ +@Data +public class MaterialClassesTreeRespDTO { + + @Schema(description = "主键ID", example = "1001") + private Long id; + + @Schema(description = "父级ID", example = "0") + private Long parentId; + + @Schema(description = "分类编码", example = "CL-001") + private String code; + + @Schema(description = "分类名称", example = "原材料") + private String name; + + @Schema(description = "分类级别") + private Long level; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "子节点") + private List children = new ArrayList<>(); +} diff --git a/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialhasclasses/MaterialHasClassesApi.java b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialhasclasses/MaterialHasClassesApi.java new file mode 100644 index 00000000..b413ed29 --- /dev/null +++ b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialhasclasses/MaterialHasClassesApi.java @@ -0,0 +1,51 @@ +package com.zt.plat.module.base.api.materialhasclasses; + +import com.zt.plat.framework.common.pojo.CommonResult; +import com.zt.plat.framework.common.pojo.PageResult; +import com.zt.plat.module.base.api.materialhasclasses.dto.MaterialHasClassesPageReqDTO; +import com.zt.plat.module.base.api.materialhasclasses.dto.MaterialHasClassesRespDTO; +import com.zt.plat.module.base.api.materialhasclasses.dto.MaterialHasClassesSaveReqDTO; +import com.zt.plat.module.base.enums.ApiConstants; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; + +import java.util.List; + +@FeignClient(name = ApiConstants.NAME) +@Tag(name = "RPC 服务 - 物料持有分类") +public interface MaterialHasClassesApi { + + String PREFIX = ApiConstants.PREFIX + "/material-has-classes"; + + @PostMapping(PREFIX + "/create") + @Operation(summary = "创建物料持有分类") + CommonResult createMaterialHasClasses(@Valid @RequestBody MaterialHasClassesSaveReqDTO createReqDTO); + + @PutMapping(PREFIX + "/update") + @Operation(summary = "更新物料持有分类") + CommonResult updateMaterialHasClasses(@Valid @RequestBody MaterialHasClassesSaveReqDTO updateReqDTO); + + @DeleteMapping(PREFIX + "/delete") + @Operation(summary = "删除物料持有分类") + CommonResult deleteMaterialHasClasses(@RequestParam("id") Long id); + + @DeleteMapping(PREFIX + "/delete-list") + @Operation(summary = "批量删除物料持有分类") + CommonResult deleteMaterialHasClassesList(@RequestBody List ids); + + @GetMapping(PREFIX + "/get") + @Operation(summary = "获得物料持有分类") + CommonResult getMaterialHasClasses(@RequestParam("id") Long id); + + @GetMapping(PREFIX + "/page") + @Operation(summary = "获得物料持有分类分页") + CommonResult> getMaterialHasClassesPage(@Valid MaterialHasClassesPageReqDTO pageReqDTO); +} diff --git a/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialhasclasses/dto/MaterialHasClassesPageReqDTO.java b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialhasclasses/dto/MaterialHasClassesPageReqDTO.java new file mode 100644 index 00000000..d553e209 --- /dev/null +++ b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialhasclasses/dto/MaterialHasClassesPageReqDTO.java @@ -0,0 +1,27 @@ +package com.zt.plat.module.base.api.materialhasclasses.dto; + +import com.zt.plat.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static com.zt.plat.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +/** + * 物料持有分类分页 Request DTO + */ +@Data +public class MaterialHasClassesPageReqDTO extends PageParam { + + @Schema(description = "物料信息ID", example = "31031") + private Long infomationId; + + @Schema(description = "分类ID", example = "5914") + private Long classesId; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; +} diff --git a/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialhasclasses/dto/MaterialHasClassesRespDTO.java b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialhasclasses/dto/MaterialHasClassesRespDTO.java new file mode 100644 index 00000000..40ff0e7e --- /dev/null +++ b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialhasclasses/dto/MaterialHasClassesRespDTO.java @@ -0,0 +1,25 @@ +package com.zt.plat.module.base.api.materialhasclasses.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 物料持有分类 Response DTO + */ +@Data +public class MaterialHasClassesRespDTO { + + @Schema(description = "主键ID", example = "16228") + private Long id; + + @Schema(description = "物料信息ID", example = "31031") + private Long infomationId; + + @Schema(description = "分类ID", example = "5914") + private Long classesId; + + @Schema(description = "创建时间") + private LocalDateTime createTime; +} diff --git a/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialhasclasses/dto/MaterialHasClassesSaveReqDTO.java b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialhasclasses/dto/MaterialHasClassesSaveReqDTO.java new file mode 100644 index 00000000..3e0c2a61 --- /dev/null +++ b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialhasclasses/dto/MaterialHasClassesSaveReqDTO.java @@ -0,0 +1,23 @@ +package com.zt.plat.module.base.api.materialhasclasses.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * 物料持有分类新增/修改 Request DTO + */ +@Data +public class MaterialHasClassesSaveReqDTO { + + @Schema(description = "主键ID", example = "16228") + private Long id; + + @Schema(description = "物料信息ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "31031") + @NotNull(message = "物料信息ID不能为空") + private Long infomationId; + + @Schema(description = "分类ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "5914") + @NotNull(message = "分类ID不能为空") + private Long classesId; +} diff --git a/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialhasproperties/MaterialHasPropertiesApi.java b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialhasproperties/MaterialHasPropertiesApi.java new file mode 100644 index 00000000..bc93490c --- /dev/null +++ b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialhasproperties/MaterialHasPropertiesApi.java @@ -0,0 +1,51 @@ +package com.zt.plat.module.base.api.materialhasproperties; + +import com.zt.plat.framework.common.pojo.CommonResult; +import com.zt.plat.framework.common.pojo.PageResult; +import com.zt.plat.module.base.api.materialhasproperties.dto.MaterialHasPropertiesPageReqDTO; +import com.zt.plat.module.base.api.materialhasproperties.dto.MaterialHasPropertiesRespDTO; +import com.zt.plat.module.base.api.materialhasproperties.dto.MaterialHasPropertiesSaveReqDTO; +import com.zt.plat.module.base.enums.ApiConstants; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; + +import java.util.List; + +@FeignClient(name = ApiConstants.NAME) +@Tag(name = "RPC 服务 - 物料持有属性") +public interface MaterialHasPropertiesApi { + + String PREFIX = ApiConstants.PREFIX + "/material-has-properties"; + + @PostMapping(PREFIX + "/create") + @Operation(summary = "创建物料持有属性") + CommonResult createMaterialHasProperties(@Valid @RequestBody MaterialHasPropertiesSaveReqDTO createReqDTO); + + @PutMapping(PREFIX + "/update") + @Operation(summary = "更新物料持有属性") + CommonResult updateMaterialHasProperties(@Valid @RequestBody MaterialHasPropertiesSaveReqDTO updateReqDTO); + + @DeleteMapping(PREFIX + "/delete") + @Operation(summary = "删除物料持有属性") + CommonResult deleteMaterialHasProperties(@RequestParam("id") Long id); + + @DeleteMapping(PREFIX + "/delete-list") + @Operation(summary = "批量删除物料持有属性") + CommonResult deleteMaterialHasPropertiesList(@RequestBody List ids); + + @GetMapping(PREFIX + "/get") + @Operation(summary = "获得物料持有属性") + CommonResult getMaterialHasProperties(@RequestParam("id") Long id); + + @GetMapping(PREFIX + "/page") + @Operation(summary = "获得物料持有属性分页") + CommonResult> getMaterialHasPropertiesPage(@Valid MaterialHasPropertiesPageReqDTO pageReqDTO); +} diff --git a/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialhasproperties/dto/MaterialHasPropertiesPageReqDTO.java b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialhasproperties/dto/MaterialHasPropertiesPageReqDTO.java new file mode 100644 index 00000000..a9999a3c --- /dev/null +++ b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialhasproperties/dto/MaterialHasPropertiesPageReqDTO.java @@ -0,0 +1,42 @@ +package com.zt.plat.module.base.api.materialhasproperties.dto; + +import com.zt.plat.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static com.zt.plat.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +/** + * 物料持有属性分页 Request DTO + */ +@Data +public class MaterialHasPropertiesPageReqDTO extends PageParam { + + @Schema(description = "物料信息ID", example = "2614") + private Long infomationId; + + @Schema(description = "属性ID", example = "8607") + private Long propertiesId; + + @Schema(description = "计量单位ID-默认计量单位", example = "23731") + private Long unitId; + + @Schema(description = "属性值") + private String value; + + @Schema(description = "是否关键属性-关键属性表示物料唯一性") + private Integer isKey; + + @Schema(description = "是否计量定价") + private Integer isMetering; + + @Schema(description = "排序号") + private Long sort; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; +} diff --git a/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialhasproperties/dto/MaterialHasPropertiesRespDTO.java b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialhasproperties/dto/MaterialHasPropertiesRespDTO.java new file mode 100644 index 00000000..5569ea8b --- /dev/null +++ b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialhasproperties/dto/MaterialHasPropertiesRespDTO.java @@ -0,0 +1,40 @@ +package com.zt.plat.module.base.api.materialhasproperties.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 物料持有属性 Response DTO + */ +@Data +public class MaterialHasPropertiesRespDTO { + + @Schema(description = "主键ID", example = "6800") + private Long id; + + @Schema(description = "物料信息ID", example = "2614") + private Long infomationId; + + @Schema(description = "属性ID", example = "8607") + private Long propertiesId; + + @Schema(description = "计量单位ID-默认计量单位", example = "23731") + private Long unitId; + + @Schema(description = "属性值") + private String value; + + @Schema(description = "是否关键属性-关键属性表示物料唯一性") + private Integer isKey; + + @Schema(description = "是否计量定价") + private Integer isMetering; + + @Schema(description = "排序号") + private Long sort; + + @Schema(description = "创建时间") + private LocalDateTime createTime; +} diff --git a/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialhasproperties/dto/MaterialHasPropertiesSaveReqDTO.java b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialhasproperties/dto/MaterialHasPropertiesSaveReqDTO.java new file mode 100644 index 00000000..30f4372f --- /dev/null +++ b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialhasproperties/dto/MaterialHasPropertiesSaveReqDTO.java @@ -0,0 +1,40 @@ +package com.zt.plat.module.base.api.materialhasproperties.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * 物料持有属性新增/修改 Request DTO + */ +@Data +public class MaterialHasPropertiesSaveReqDTO { + + @Schema(description = "主键ID", example = "6800") + private Long id; + + @Schema(description = "物料信息ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "2614") + @NotNull(message = "物料信息ID不能为空") + private Long infomationId; + + @Schema(description = "属性ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "8607") + @NotNull(message = "属性ID不能为空") + private Long propertiesId; + + @Schema(description = "计量单位ID-默认计量单位", example = "23731") + private Long unitId; + + @Schema(description = "属性值", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "属性值不能为空") + private String value; + + @Schema(description = "是否关键属性-关键属性表示物料唯一性") + private Integer isKey; + + @Schema(description = "是否计量定价") + private Integer isMetering; + + @Schema(description = "排序号") + private Long sort; +} diff --git a/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialproperties/MaterialPropertiesApi.java b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialproperties/MaterialPropertiesApi.java new file mode 100644 index 00000000..a6d97604 --- /dev/null +++ b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialproperties/MaterialPropertiesApi.java @@ -0,0 +1,57 @@ +package com.zt.plat.module.base.api.materialproperties; + +import com.zt.plat.framework.common.pojo.CommonResult; +import com.zt.plat.framework.common.pojo.PageResult; +import com.zt.plat.module.base.api.materialproperties.dto.MaterialPropertiesPageReqDTO; +import com.zt.plat.module.base.api.materialproperties.dto.MaterialPropertiesRespDTO; +import com.zt.plat.module.base.api.materialproperties.dto.MaterialPropertiesSaveReqDTO; +import com.zt.plat.module.base.api.materialproperties.dto.MaterialPropertiesSimplePageReqDTO; +import com.zt.plat.module.base.api.materialproperties.dto.MaterialPropertiesSimpleRespDTO; +import com.zt.plat.module.base.enums.ApiConstants; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; + +import java.util.List; + +@FeignClient(name = ApiConstants.NAME) +@Tag(name = "RPC 服务 - 物料属性") +public interface MaterialPropertiesApi { + + String PREFIX = ApiConstants.PREFIX + "/material-properties"; + + @PostMapping(PREFIX + "/create") + @Operation(summary = "创建物料属性") + CommonResult createMaterialProperties(@Valid @RequestBody MaterialPropertiesSaveReqDTO createReqDTO); + + @PutMapping(PREFIX + "/update") + @Operation(summary = "更新物料属性") + CommonResult updateMaterialProperties(@Valid @RequestBody MaterialPropertiesSaveReqDTO updateReqDTO); + + @DeleteMapping(PREFIX + "/delete") + @Operation(summary = "删除物料属性") + CommonResult deleteMaterialProperties(@RequestParam("id") Long id); + + @DeleteMapping(PREFIX + "/delete-list") + @Operation(summary = "批量删除物料属性") + CommonResult deleteMaterialPropertiesList(@RequestBody List ids); + + @GetMapping(PREFIX + "/get") + @Operation(summary = "获得物料属性") + CommonResult getMaterialProperties(@RequestParam("id") Long id); + + @GetMapping(PREFIX + "/page") + @Operation(summary = "获得物料属性分页") + CommonResult> getMaterialPropertiesPage(@Valid MaterialPropertiesPageReqDTO pageReqDTO); + + @GetMapping(PREFIX + "/simple-page") + @Operation(summary = "获得物料属性精简分页") + CommonResult> getMaterialPropertiesSimplePage(@Valid MaterialPropertiesSimplePageReqDTO pageReqDTO); +} diff --git a/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialproperties/dto/MaterialPropertiesPageReqDTO.java b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialproperties/dto/MaterialPropertiesPageReqDTO.java new file mode 100644 index 00000000..f670d50e --- /dev/null +++ b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialproperties/dto/MaterialPropertiesPageReqDTO.java @@ -0,0 +1,42 @@ +package com.zt.plat.module.base.api.materialproperties.dto; + +import com.zt.plat.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static com.zt.plat.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +/** + * 物料属性分页 Request DTO + */ +@Data +public class MaterialPropertiesPageReqDTO extends PageParam { + + @Schema(description = "属性编码") + private String code; + + @Schema(description = "属性名称", example = "含量") + private String name; + + @Schema(description = "关键字(编码/名称模糊匹配)") + private String keyword; + + @Schema(description = "计量单位量ID", example = "30468") + private Long unitQuantityId; + + @Schema(description = "属性类型") + private String dictionaryDataValue; + + @Schema(description = "数据类型", example = "1") + private String dataType; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; +} diff --git a/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialproperties/dto/MaterialPropertiesRespDTO.java b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialproperties/dto/MaterialPropertiesRespDTO.java new file mode 100644 index 00000000..4494d55b --- /dev/null +++ b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialproperties/dto/MaterialPropertiesRespDTO.java @@ -0,0 +1,49 @@ +package com.zt.plat.module.base.api.materialproperties.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 物料属性 Response DTO + */ +@Data +public class MaterialPropertiesRespDTO { + + @Schema(description = "主键ID", example = "10591") + private Long id; + + @Schema(description = "属性编码") + private String code; + + @Schema(description = "属性名称", example = "含量") + private String name; + + @Schema(description = "计量单位量ID", example = "30468") + private Long unitQuantityId; + + @Schema(description = "属性类型") + private String dictionaryDataValue; + + @Schema(description = "属性类型名称") + private String dictionaryDataLabel; + + @Schema(description = "数据类型", example = "1") + private String dataType; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "量纲名称") + private String unitQuantityName; + + @Schema(description = "计量单位名称") + private String unitName; + + @Schema(description = "计量单位符号") + private String unitSymbol; + + @Schema(description = "创建时间") + private LocalDateTime createTime; +} diff --git a/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialproperties/dto/MaterialPropertiesSaveReqDTO.java b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialproperties/dto/MaterialPropertiesSaveReqDTO.java new file mode 100644 index 00000000..f7432f11 --- /dev/null +++ b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialproperties/dto/MaterialPropertiesSaveReqDTO.java @@ -0,0 +1,38 @@ +package com.zt.plat.module.base.api.materialproperties.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import lombok.Data; + +/** + * 物料属性新增/修改 Request DTO + */ +@Data +public class MaterialPropertiesSaveReqDTO { + + @Schema(description = "主键ID", example = "10591") + private Long id; + + @Schema(description = "属性编码", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "属性编码不能为空") + private String code; + + @Schema(description = "属性名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "含量") + @NotEmpty(message = "属性名称不能为空") + private String name; + + @Schema(description = "计量单位量ID", example = "30468") + private Long unitQuantityId; + + @Schema(description = "属性类型(业务字典数据值)", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "属性类型不能为空") + private String dictionaryDataValue; + + @Schema(description = "数据类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotEmpty(message = "数据类型不能为空") + private String dataType; + + @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "备注不能为空") + private String remark; +} diff --git a/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialproperties/dto/MaterialPropertiesSimplePageReqDTO.java b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialproperties/dto/MaterialPropertiesSimplePageReqDTO.java new file mode 100644 index 00000000..cd6df70d --- /dev/null +++ b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialproperties/dto/MaterialPropertiesSimplePageReqDTO.java @@ -0,0 +1,18 @@ +package com.zt.plat.module.base.api.materialproperties.dto; + +import com.zt.plat.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 物料属性精简分页 Request DTO + */ +@Data +public class MaterialPropertiesSimplePageReqDTO extends PageParam { + + @Schema(description = "关键字(编码/名称模糊匹配)") + private String keyword; + + @Schema(description = "属性类型") + private String dictionaryDataValue; +} diff --git a/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialproperties/dto/MaterialPropertiesSimpleRespDTO.java b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialproperties/dto/MaterialPropertiesSimpleRespDTO.java new file mode 100644 index 00000000..4a9db2e1 --- /dev/null +++ b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialproperties/dto/MaterialPropertiesSimpleRespDTO.java @@ -0,0 +1,35 @@ +package com.zt.plat.module.base.api.materialproperties.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 物料属性精简 Response DTO + */ +@Data +public class MaterialPropertiesSimpleRespDTO { + + @Schema(description = "物料属性ID", example = "1001") + private Long id; + + @Schema(description = "属性编码") + private String code; + + @Schema(description = "属性名称") + private String name; + + @Schema(description = "数据类型") + private String dataType; + + @Schema(description = "单位名称") + private String unitName; + + @Schema(description = "单位符号") + private String unitSymbol; + + @Schema(description = "属性类型") + private String dictionaryDataValue; + + @Schema(description = "属性类型名称") + private String dictionaryDataLabel; +} diff --git a/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/api/businessdictionarytype/BusinessDictionaryTypeApiImpl.java b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/api/businessdictionarytype/BusinessDictionaryTypeApiImpl.java new file mode 100644 index 00000000..21db9cd0 --- /dev/null +++ b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/api/businessdictionarytype/BusinessDictionaryTypeApiImpl.java @@ -0,0 +1,87 @@ +package com.zt.plat.module.base.api.businessdictionarytype; + +import com.zt.plat.framework.common.pojo.CommonResult; +import com.zt.plat.framework.common.pojo.PageResult; +import com.zt.plat.framework.common.util.object.BeanUtils; +import com.zt.plat.module.base.api.businessdictionarytype.dto.BusinessDictionaryDataDTO; +import com.zt.plat.module.base.api.businessdictionarytype.dto.BusinessDictionaryTypePageReqDTO; +import com.zt.plat.module.base.api.businessdictionarytype.dto.BusinessDictionaryTypeRespDTO; +import com.zt.plat.module.base.api.businessdictionarytype.dto.BusinessDictionaryTypeSaveReqDTO; +import com.zt.plat.module.base.controller.admin.businessdictionarytype.vo.BusinessDictionaryTypePageReqVO; +import com.zt.plat.module.base.controller.admin.businessdictionarytype.vo.BusinessDictionaryTypeRespVO; +import com.zt.plat.module.base.controller.admin.businessdictionarytype.vo.BusinessDictionaryTypeSaveReqVO; +import com.zt.plat.module.base.dal.dataobject.businessdictionarytype.BusinessDictionaryDataDO; +import com.zt.plat.module.base.dal.dataobject.businessdictionarytype.BusinessDictionaryTypeDO; +import com.zt.plat.module.base.service.businessdictionarytype.BusinessDictionaryTypeService; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +import static com.zt.plat.framework.common.pojo.CommonResult.success; + +@RestController +@Validated +public class BusinessDictionaryTypeApiImpl implements BusinessDictionaryTypeApi { + + @Resource + private BusinessDictionaryTypeService businessDictionaryTypeService; + + @Override + public CommonResult createBusinessDictionaryType(BusinessDictionaryTypeSaveReqDTO createReqDTO) { + BusinessDictionaryTypeRespVO respVO = businessDictionaryTypeService.createBusinessDictionaryType(convertSaveReq(createReqDTO)); + return success(BeanUtils.toBean(respVO, BusinessDictionaryTypeRespDTO.class)); + } + + @Override + public CommonResult updateBusinessDictionaryType(BusinessDictionaryTypeSaveReqDTO updateReqDTO) { + businessDictionaryTypeService.updateBusinessDictionaryType(convertSaveReq(updateReqDTO)); + return success(true); + } + + @Override + public CommonResult deleteBusinessDictionaryType(Long id) { + businessDictionaryTypeService.deleteBusinessDictionaryType(id); + return success(true); + } + + @Override + public CommonResult deleteBusinessDictionaryTypeList(List ids) { + businessDictionaryTypeService.deleteBusinessDictionaryTypeListByIds(ids); + return success(true); + } + + @Override + public CommonResult getBusinessDictionaryType(Long id) { + BusinessDictionaryTypeDO typeDO = businessDictionaryTypeService.getBusinessDictionaryType(id); + return success(BeanUtils.toBean(typeDO, BusinessDictionaryTypeRespDTO.class)); + } + + @Override + public CommonResult> getBusinessDictionaryTypePage(BusinessDictionaryTypePageReqDTO pageReqDTO) { + BusinessDictionaryTypePageReqVO pageReqVO = BeanUtils.toBean(pageReqDTO, BusinessDictionaryTypePageReqVO.class); + PageResult pageResult = businessDictionaryTypeService.getBusinessDictionaryTypePage(pageReqVO); + return success(BeanUtils.toBean(pageResult, BusinessDictionaryTypeRespDTO.class)); + } + + @Override + public CommonResult> getBusinessDictionaryDataListByDictionaryTypeId(Long dictionaryTypeId) { + List list = businessDictionaryTypeService.getBusinessDictionaryDataListByDictionaryTypeId(dictionaryTypeId); + return success(BeanUtils.toBean(list, BusinessDictionaryDataDTO.class)); + } + + @Override + public CommonResult> getBusinessDictionaryDataListByType(String type) { + List list = businessDictionaryTypeService.getBusinessDictionaryDataListByType(type); + return success(BeanUtils.toBean(list, BusinessDictionaryDataDTO.class)); + } + + private BusinessDictionaryTypeSaveReqVO convertSaveReq(BusinessDictionaryTypeSaveReqDTO dto) { + BusinessDictionaryTypeSaveReqVO reqVO = BeanUtils.toBean(dto, BusinessDictionaryTypeSaveReqVO.class); + if (dto.getBusinessDictionaryDatas() != null && !dto.getBusinessDictionaryDatas().isEmpty()) { + reqVO.setBusinessDictionaryDatas(BeanUtils.toBean(dto.getBusinessDictionaryDatas(), BusinessDictionaryDataDO.class)); + } + return reqVO; + } +} diff --git a/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/api/departmentmaterial/DepartmentMaterialApiImpl.java b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/api/departmentmaterial/DepartmentMaterialApiImpl.java new file mode 100644 index 00000000..2c6fdad8 --- /dev/null +++ b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/api/departmentmaterial/DepartmentMaterialApiImpl.java @@ -0,0 +1,64 @@ +package com.zt.plat.module.base.api.departmentmaterial; + +import com.zt.plat.framework.common.pojo.CommonResult; +import com.zt.plat.framework.common.pojo.PageResult; +import com.zt.plat.framework.common.util.object.BeanUtils; +import com.zt.plat.module.base.api.departmentmaterial.dto.DepartmentMaterialPageReqDTO; +import com.zt.plat.module.base.api.departmentmaterial.dto.DepartmentMaterialRespDTO; +import com.zt.plat.module.base.api.departmentmaterial.dto.DepartmentMaterialSaveReqDTO; +import com.zt.plat.module.base.controller.admin.departmentmaterial.vo.DepartmentMaterialPageReqVO; +import com.zt.plat.module.base.controller.admin.departmentmaterial.vo.DepartmentMaterialRespVO; +import com.zt.plat.module.base.controller.admin.departmentmaterial.vo.DepartmentMaterialSaveReqVO; +import com.zt.plat.module.base.service.departmentmaterial.DepartmentMaterialService; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +import static com.zt.plat.framework.common.pojo.CommonResult.success; + +@RestController +@Validated +public class DepartmentMaterialApiImpl implements DepartmentMaterialApi { + + @Resource + private DepartmentMaterialService departmentMaterialService; + + @Override + public CommonResult createDepartmentMaterial(DepartmentMaterialSaveReqDTO createReqDTO) { + DepartmentMaterialRespVO respVO = departmentMaterialService.createDepartmentMaterial(BeanUtils.toBean(createReqDTO, DepartmentMaterialSaveReqVO.class)); + return success(BeanUtils.toBean(respVO, DepartmentMaterialRespDTO.class)); + } + + @Override + public CommonResult updateDepartmentMaterial(DepartmentMaterialSaveReqDTO updateReqDTO) { + departmentMaterialService.updateDepartmentMaterial(BeanUtils.toBean(updateReqDTO, DepartmentMaterialSaveReqVO.class)); + return success(true); + } + + @Override + public CommonResult deleteDepartmentMaterial(Long id) { + departmentMaterialService.deleteDepartmentMaterial(id); + return success(true); + } + + @Override + public CommonResult deleteDepartmentMaterialList(List ids) { + departmentMaterialService.deleteDepartmentMaterialListByIds(ids); + return success(true); + } + + @Override + public CommonResult getDepartmentMaterial(Long id) { + DepartmentMaterialRespVO respVO = departmentMaterialService.getDepartmentMaterial(id); + return success(BeanUtils.toBean(respVO, DepartmentMaterialRespDTO.class)); + } + + @Override + public CommonResult> getDepartmentMaterialPage(DepartmentMaterialPageReqDTO pageReqDTO) { + DepartmentMaterialPageReqVO pageReqVO = BeanUtils.toBean(pageReqDTO, DepartmentMaterialPageReqVO.class); + PageResult pageResult = departmentMaterialService.getDepartmentMaterialPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, DepartmentMaterialRespDTO.class)); + } +} diff --git a/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/api/materialclasses/MaterialClassesApiImpl.java b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/api/materialclasses/MaterialClassesApiImpl.java new file mode 100644 index 00000000..3a1ba044 --- /dev/null +++ b/zt-module-base/zt-module-base-server/src/main/java/com/zt/plat/module/base/api/materialclasses/MaterialClassesApiImpl.java @@ -0,0 +1,97 @@ +package com.zt.plat.module.base.api.materialclasses; + +import com.zt.plat.framework.common.pojo.CommonResult; +import com.zt.plat.framework.common.pojo.PageResult; +import com.zt.plat.framework.common.util.object.BeanUtils; +import com.zt.plat.module.base.api.materialclasses.dto.MaterialClassesPageReqDTO; +import com.zt.plat.module.base.api.materialclasses.dto.MaterialClassesRespDTO; +import com.zt.plat.module.base.api.materialclasses.dto.MaterialClassesSaveReqDTO; +import com.zt.plat.module.base.api.materialclasses.dto.MaterialClassesTreeRespDTO; +import com.zt.plat.module.base.controller.admin.materialclasses.vo.MaterialClassesPageReqVO; +import com.zt.plat.module.base.controller.admin.materialclasses.vo.MaterialClassesRespVO; +import com.zt.plat.module.base.controller.admin.materialclasses.vo.MaterialClassesSaveReqVO; +import com.zt.plat.module.base.dal.dataobject.materialclasses.MaterialClassesDO; +import com.zt.plat.module.base.service.materialclasses.MaterialClassesService; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RestController; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import static com.zt.plat.framework.common.pojo.CommonResult.success; + +@RestController +@Validated +public class MaterialClassesApiImpl implements MaterialClassesApi { + + @Resource + private MaterialClassesService materialClassesService; + + @Override + public CommonResult createMaterialClasses(MaterialClassesSaveReqDTO createReqDTO) { + MaterialClassesRespVO respVO = materialClassesService.createMaterialClasses(BeanUtils.toBean(createReqDTO, MaterialClassesSaveReqVO.class)); + return success(BeanUtils.toBean(respVO, MaterialClassesRespDTO.class)); + } + + @Override + public CommonResult updateMaterialClasses(MaterialClassesSaveReqDTO updateReqDTO) { + materialClassesService.updateMaterialClasses(BeanUtils.toBean(updateReqDTO, MaterialClassesSaveReqVO.class)); + return success(true); + } + + @Override + public CommonResult deleteMaterialClasses(Long id) { + materialClassesService.deleteMaterialClasses(id); + return success(true); + } + + @Override + public CommonResult deleteMaterialClassesList(List ids) { + materialClassesService.deleteMaterialClassesListByIds(ids); + return success(true); + } + + @Override + public CommonResult getMaterialClasses(Long id) { + MaterialClassesDO classesDO = materialClassesService.getMaterialClasses(id); + return success(BeanUtils.toBean(classesDO, MaterialClassesRespDTO.class)); + } + + @Override + public CommonResult> getMaterialClassesPage(MaterialClassesPageReqDTO pageReqDTO) { + MaterialClassesPageReqVO pageReqVO = BeanUtils.toBean(pageReqDTO, MaterialClassesPageReqVO.class); + PageResult pageResult = materialClassesService.getMaterialClassesPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, MaterialClassesRespDTO.class)); + } + + @Override + public CommonResult> getMaterialClassesTree() { + List list = materialClassesService.getMaterialClassesList(); + return success(buildTree(list)); + } + + private List buildTree(List list) { + if (list == null || list.isEmpty()) { + return Collections.emptyList(); + } + Map nodeMap = new LinkedHashMap<>(); + list.stream() + .sorted(Comparator.comparing(MaterialClassesDO::getId)) + .forEach(item -> nodeMap.put(item.getId(), BeanUtils.toBean(item, MaterialClassesTreeRespDTO.class))); + List roots = new ArrayList<>(); + nodeMap.values().forEach(node -> { + Long parentId = node.getParentId(); + if (parentId == null || parentId == 0 || !nodeMap.containsKey(parentId)) { + roots.add(node); + } else { + nodeMap.get(parentId).getChildren().add(node); + } + }); + return roots; + } +} diff --git a/zt-module-base/zt-module-base-server/src/main/resources/logback-spring.xml b/zt-module-base/zt-module-base-server/src/main/resources/logback-spring.xml index b1b9f3fa..0e551414 100644 --- a/zt-module-base/zt-module-base-server/src/main/resources/logback-spring.xml +++ b/zt-module-base/zt-module-base-server/src/main/resources/logback-spring.xml @@ -1,8 +1,8 @@ - - + + diff --git a/zt-module-base/zt-module-base-server/src/test/java/com/zt/plat/module/base/api/businessdictionarytype/BusinessDictionaryTypeApiImplTest.java b/zt-module-base/zt-module-base-server/src/test/java/com/zt/plat/module/base/api/businessdictionarytype/BusinessDictionaryTypeApiImplTest.java new file mode 100644 index 00000000..ab0c7f06 --- /dev/null +++ b/zt-module-base/zt-module-base-server/src/test/java/com/zt/plat/module/base/api/businessdictionarytype/BusinessDictionaryTypeApiImplTest.java @@ -0,0 +1,201 @@ +package com.zt.plat.module.base.api.businessdictionarytype; + +import com.zt.plat.framework.common.pojo.CommonResult; +import com.zt.plat.framework.common.pojo.PageResult; +import com.zt.plat.module.base.api.businessdictionarytype.dto.BusinessDictionaryDataDTO; +import com.zt.plat.module.base.api.businessdictionarytype.dto.BusinessDictionaryTypePageReqDTO; +import com.zt.plat.module.base.api.businessdictionarytype.dto.BusinessDictionaryTypeRespDTO; +import com.zt.plat.module.base.api.businessdictionarytype.dto.BusinessDictionaryTypeSaveReqDTO; +import com.zt.plat.module.base.controller.admin.businessdictionarytype.vo.BusinessDictionaryTypePageReqVO; +import com.zt.plat.module.base.controller.admin.businessdictionarytype.vo.BusinessDictionaryTypeRespVO; +import com.zt.plat.module.base.controller.admin.businessdictionarytype.vo.BusinessDictionaryTypeSaveReqVO; +import com.zt.plat.module.base.dal.dataobject.businessdictionarytype.BusinessDictionaryDataDO; +import com.zt.plat.module.base.dal.dataobject.businessdictionarytype.BusinessDictionaryTypeDO; +import com.zt.plat.module.base.service.businessdictionarytype.BusinessDictionaryTypeService; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.time.LocalDateTime; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class BusinessDictionaryTypeApiImplTest { + + @InjectMocks + private BusinessDictionaryTypeApiImpl api; + + @Mock + private BusinessDictionaryTypeService businessDictionaryTypeService; + + private BusinessDictionaryTypeSaveReqDTO buildSaveReqDTO() { + BusinessDictionaryDataDTO dataDTO = new BusinessDictionaryDataDTO(); + dataDTO.setId(10L); + dataDTO.setLabel("启用"); + dataDTO.setValue("ENABLE"); + dataDTO.setRemark("默认状态"); + BusinessDictionaryTypeSaveReqDTO dto = new BusinessDictionaryTypeSaveReqDTO(); + dto.setId(1L); + dto.setName("状态字典"); + dto.setType("base_material_status"); + dto.setStatus(0L); + dto.setRemark("备注"); + dto.setBusinessDictionaryDatas(List.of(dataDTO)); + return dto; + } + + private BusinessDictionaryTypeRespVO buildRespVO() { + BusinessDictionaryTypeRespVO respVO = new BusinessDictionaryTypeRespVO(); + respVO.setId(1L); + respVO.setName("状态字典"); + respVO.setType("base_material_status"); + respVO.setStatus(0L); + respVO.setRemark("备注"); + respVO.setCreateTime(LocalDateTime.now()); + return respVO; + } + + @Test + void createBusinessDictionaryType_shouldForwardToServiceAndReturnConvertedDto() { + BusinessDictionaryTypeSaveReqDTO reqDTO = buildSaveReqDTO(); + BusinessDictionaryTypeRespVO serviceResp = buildRespVO(); + when(businessDictionaryTypeService.createBusinessDictionaryType(any(BusinessDictionaryTypeSaveReqVO.class))) + .thenReturn(serviceResp); + + CommonResult result = api.createBusinessDictionaryType(reqDTO); + + assertThat(result.isSuccess()).isTrue(); + assertThat(result.getData()).usingRecursiveComparison() + .ignoringFields("createTime") + .isEqualTo(BeanAssertHelper.toRespDTO(serviceResp)); + + ArgumentCaptor captor = ArgumentCaptor.forClass(BusinessDictionaryTypeSaveReqVO.class); + verify(businessDictionaryTypeService).createBusinessDictionaryType(captor.capture()); + BusinessDictionaryTypeSaveReqVO passed = captor.getValue(); + assertThat(passed.getName()).isEqualTo(reqDTO.getName()); + assertThat(passed.getBusinessDictionaryDatas()).hasSize(1); + BusinessDictionaryDataDO dataDO = passed.getBusinessDictionaryDatas().get(0); + assertThat(dataDO.getLabel()).isEqualTo("启用"); + assertThat(dataDO.getValue()).isEqualTo("ENABLE"); + } + + @Test + void updateBusinessDictionaryType_shouldInvokeServiceWithConvertedPayload() { + BusinessDictionaryTypeSaveReqDTO reqDTO = buildSaveReqDTO(); + + CommonResult result = api.updateBusinessDictionaryType(reqDTO); + + assertThat(result.isSuccess()).isTrue(); + assertThat(result.getData()).isTrue(); + ArgumentCaptor captor = ArgumentCaptor.forClass(BusinessDictionaryTypeSaveReqVO.class); + verify(businessDictionaryTypeService).updateBusinessDictionaryType(captor.capture()); + assertThat(captor.getValue().getName()).isEqualTo(reqDTO.getName()); + } + + @Test + void deleteBusinessDictionaryType_shouldInvokeService() { + CommonResult result = api.deleteBusinessDictionaryType(123L); + + assertThat(result.isSuccess()).isTrue(); + assertThat(result.getData()).isTrue(); + verify(businessDictionaryTypeService).deleteBusinessDictionaryType(123L); + } + + @Test + void deleteBusinessDictionaryTypeList_shouldInvokeService() { + List ids = List.of(1L, 2L); + + CommonResult result = api.deleteBusinessDictionaryTypeList(ids); + + assertThat(result.isSuccess()).isTrue(); + assertThat(result.getData()).isTrue(); + verify(businessDictionaryTypeService).deleteBusinessDictionaryTypeListByIds(ids); + } + + @Test + void getBusinessDictionaryType_shouldConvertDoToDto() { + BusinessDictionaryTypeDO typeDO = new BusinessDictionaryTypeDO(); + typeDO.setId(55L); + typeDO.setName("状态字典"); + when(businessDictionaryTypeService.getBusinessDictionaryType(55L)).thenReturn(typeDO); + + CommonResult result = api.getBusinessDictionaryType(55L); + + assertThat(result.isSuccess()).isTrue(); + assertThat(result.getData().getId()).isEqualTo(55L); + assertThat(result.getData().getName()).isEqualTo("状态字典"); + } + + @Test + void getBusinessDictionaryTypePage_shouldConvertPageResult() { + BusinessDictionaryTypeDO typeDO = new BusinessDictionaryTypeDO(); + typeDO.setId(11L); + typeDO.setName("状态"); + PageResult page = new PageResult<>(List.of(typeDO), 1L); + when(businessDictionaryTypeService.getBusinessDictionaryTypePage(any(BusinessDictionaryTypePageReqVO.class))) + .thenReturn(page); + + BusinessDictionaryTypePageReqDTO reqDTO = new BusinessDictionaryTypePageReqDTO(); + reqDTO.setName("状态"); + CommonResult> result = api.getBusinessDictionaryTypePage(reqDTO); + + assertThat(result.isSuccess()).isTrue(); + assertThat(result.getData().getList()).hasSize(1); + assertThat(result.getData().getList().get(0).getName()).isEqualTo("状态"); + assertThat(result.getData().getTotal()).isEqualTo(1L); + } + + @Test + void getBusinessDictionaryDataListByDictionaryTypeId_shouldConvertList() { + BusinessDictionaryDataDO dataDO = new BusinessDictionaryDataDO(); + dataDO.setId(9L); + dataDO.setLabel("启用"); + when(businessDictionaryTypeService.getBusinessDictionaryDataListByDictionaryTypeId(8L)) + .thenReturn(List.of(dataDO)); + + CommonResult> result = api.getBusinessDictionaryDataListByDictionaryTypeId(8L); + + assertThat(result.isSuccess()).isTrue(); + assertThat(result.getData()).hasSize(1); + assertThat(result.getData().get(0).getLabel()).isEqualTo("启用"); + } + + @Test + void getBusinessDictionaryDataListByType_shouldConvertList() { + BusinessDictionaryDataDO dataDO = new BusinessDictionaryDataDO(); + dataDO.setId(9L); + dataDO.setValue("ENABLE"); + when(businessDictionaryTypeService.getBusinessDictionaryDataListByType("base_material_status")) + .thenReturn(List.of(dataDO)); + + CommonResult> result = api.getBusinessDictionaryDataListByType("base_material_status"); + + assertThat(result.isSuccess()).isTrue(); + assertThat(result.getData()).hasSize(1); + assertThat(result.getData().get(0).getValue()).isEqualTo("ENABLE"); + } + + private static final class BeanAssertHelper { + private BeanAssertHelper() { + } + + static BusinessDictionaryTypeRespDTO toRespDTO(BusinessDictionaryTypeRespVO respVO) { + BusinessDictionaryTypeRespDTO dto = new BusinessDictionaryTypeRespDTO(); + dto.setId(respVO.getId()); + dto.setName(respVO.getName()); + dto.setType(respVO.getType()); + dto.setStatus(respVO.getStatus()); + dto.setRemark(respVO.getRemark()); + dto.setCreateTime(respVO.getCreateTime()); + return dto; + } + } +} diff --git a/zt-module-base/zt-module-base-server/src/test/java/com/zt/plat/module/base/api/departmentmaterial/DepartmentMaterialApiImplTest.java b/zt-module-base/zt-module-base-server/src/test/java/com/zt/plat/module/base/api/departmentmaterial/DepartmentMaterialApiImplTest.java new file mode 100644 index 00000000..f068bc77 --- /dev/null +++ b/zt-module-base/zt-module-base-server/src/test/java/com/zt/plat/module/base/api/departmentmaterial/DepartmentMaterialApiImplTest.java @@ -0,0 +1,146 @@ +package com.zt.plat.module.base.api.departmentmaterial; + +import com.zt.plat.framework.common.pojo.CommonResult; +import com.zt.plat.framework.common.pojo.PageResult; +import com.zt.plat.module.base.api.departmentmaterial.dto.DepartmentMaterialPageReqDTO; +import com.zt.plat.module.base.api.departmentmaterial.dto.DepartmentMaterialRespDTO; +import com.zt.plat.module.base.api.departmentmaterial.dto.DepartmentMaterialSaveReqDTO; +import com.zt.plat.module.base.controller.admin.departmentmaterial.vo.DepartmentMaterialPageReqVO; +import com.zt.plat.module.base.controller.admin.departmentmaterial.vo.DepartmentMaterialRespVO; +import com.zt.plat.module.base.controller.admin.departmentmaterial.vo.DepartmentMaterialSaveReqVO; +import com.zt.plat.module.base.service.departmentmaterial.DepartmentMaterialService; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.time.LocalDateTime; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class DepartmentMaterialApiImplTest { + + @InjectMocks + private DepartmentMaterialApiImpl api; + + @Mock + private DepartmentMaterialService departmentMaterialService; + + private DepartmentMaterialSaveReqDTO buildSaveReq() { + DepartmentMaterialSaveReqDTO dto = new DepartmentMaterialSaveReqDTO(); + dto.setId(100L); + dto.setDeptId(200L); + dto.setInfomationId(300L); + dto.setClassesId(400L); + dto.setDictionaryDataValue("TYPE"); + dto.setStatus("ENABLE"); + dto.setRemark("备注"); + return dto; + } + + private DepartmentMaterialRespVO buildRespVO() { + DepartmentMaterialRespVO respVO = new DepartmentMaterialRespVO(); + respVO.setId(100L); + respVO.setDeptId(200L); + respVO.setInfomationId(300L); + respVO.setClassesId(400L); + respVO.setDictionaryDataValue("TYPE"); + respVO.setRemark("备注"); + respVO.setStatus("ENABLE"); + respVO.setMaterialName("原材料"); + respVO.setCreateTime(LocalDateTime.now()); + return respVO; + } + + @Test + void createDepartmentMaterial_shouldForwardToServiceAndReturnConvertedDto() { + DepartmentMaterialSaveReqDTO reqDTO = buildSaveReq(); + DepartmentMaterialRespVO serviceResp = buildRespVO(); + when(departmentMaterialService.createDepartmentMaterial(any(DepartmentMaterialSaveReqVO.class))) + .thenReturn(serviceResp); + + CommonResult result = api.createDepartmentMaterial(reqDTO); + + assertThat(result.isSuccess()).isTrue(); + DepartmentMaterialRespDTO data = result.getData(); + assertThat(data.getId()).isEqualTo(serviceResp.getId()); + assertThat(data.getMaterialName()).isEqualTo("原材料"); + + ArgumentCaptor captor = ArgumentCaptor.forClass(DepartmentMaterialSaveReqVO.class); + verify(departmentMaterialService).createDepartmentMaterial(captor.capture()); + DepartmentMaterialSaveReqVO passed = captor.getValue(); + assertThat(passed.getDeptId()).isEqualTo(reqDTO.getDeptId()); + assertThat(passed.getInfomationId()).isEqualTo(reqDTO.getInfomationId()); + assertThat(passed.getDictionaryDataValue()).isEqualTo(reqDTO.getDictionaryDataValue()); + } + + @Test + void updateDepartmentMaterial_shouldInvokeService() { + DepartmentMaterialSaveReqDTO reqDTO = buildSaveReq(); + + CommonResult result = api.updateDepartmentMaterial(reqDTO); + + assertThat(result.isSuccess()).isTrue(); + assertThat(result.getData()).isTrue(); + ArgumentCaptor captor = ArgumentCaptor.forClass(DepartmentMaterialSaveReqVO.class); + verify(departmentMaterialService).updateDepartmentMaterial(captor.capture()); + assertThat(captor.getValue().getDeptId()).isEqualTo(reqDTO.getDeptId()); + } + + @Test + void deleteDepartmentMaterial_shouldInvokeService() { + CommonResult result = api.deleteDepartmentMaterial(99L); + + assertThat(result.isSuccess()).isTrue(); + assertThat(result.getData()).isTrue(); + verify(departmentMaterialService).deleteDepartmentMaterial(99L); + } + + @Test + void deleteDepartmentMaterialList_shouldInvokeService() { + List ids = List.of(1L, 2L, 3L); + + CommonResult result = api.deleteDepartmentMaterialList(ids); + + assertThat(result.isSuccess()).isTrue(); + assertThat(result.getData()).isTrue(); + verify(departmentMaterialService).deleteDepartmentMaterialListByIds(ids); + } + + @Test + void getDepartmentMaterial_shouldConvertVoToDto() { + DepartmentMaterialRespVO respVO = buildRespVO(); + when(departmentMaterialService.getDepartmentMaterial(11L)).thenReturn(respVO); + + CommonResult result = api.getDepartmentMaterial(11L); + + assertThat(result.isSuccess()).isTrue(); + assertThat(result.getData().getId()).isEqualTo(respVO.getId()); + assertThat(result.getData().getMaterialName()).isEqualTo(respVO.getMaterialName()); + } + + @Test + void getDepartmentMaterialPage_shouldConvertPageResult() { + DepartmentMaterialRespVO respVO = buildRespVO(); + PageResult page = new PageResult<>(List.of(respVO), 1L); + when(departmentMaterialService.getDepartmentMaterialPage(any(DepartmentMaterialPageReqVO.class))) + .thenReturn(page); + + DepartmentMaterialPageReqDTO reqDTO = new DepartmentMaterialPageReqDTO(); + reqDTO.setDeptId(200L); + + CommonResult> result = api.getDepartmentMaterialPage(reqDTO); + + assertThat(result.isSuccess()).isTrue(); + assertThat(result.getData().getList()).hasSize(1); + assertThat(result.getData().getList().get(0).getMaterialName()).isEqualTo("原材料"); + assertThat(result.getData().getTotal()).isEqualTo(1L); + } +} diff --git a/zt-module-base/zt-module-base-server/src/test/java/com/zt/plat/module/base/api/materialclasses/MaterialClassesApiImplTest.java b/zt-module-base/zt-module-base-server/src/test/java/com/zt/plat/module/base/api/materialclasses/MaterialClassesApiImplTest.java new file mode 100644 index 00000000..b5a9cd1d --- /dev/null +++ b/zt-module-base/zt-module-base-server/src/test/java/com/zt/plat/module/base/api/materialclasses/MaterialClassesApiImplTest.java @@ -0,0 +1,180 @@ +package com.zt.plat.module.base.api.materialclasses; + +import com.zt.plat.framework.common.pojo.CommonResult; +import com.zt.plat.framework.common.pojo.PageResult; +import com.zt.plat.module.base.api.materialclasses.dto.MaterialClassesPageReqDTO; +import com.zt.plat.module.base.api.materialclasses.dto.MaterialClassesRespDTO; +import com.zt.plat.module.base.api.materialclasses.dto.MaterialClassesSaveReqDTO; +import com.zt.plat.module.base.api.materialclasses.dto.MaterialClassesTreeRespDTO; +import com.zt.plat.module.base.controller.admin.materialclasses.vo.MaterialClassesPageReqVO; +import com.zt.plat.module.base.controller.admin.materialclasses.vo.MaterialClassesRespVO; +import com.zt.plat.module.base.controller.admin.materialclasses.vo.MaterialClassesSaveReqVO; +import com.zt.plat.module.base.dal.dataobject.materialclasses.MaterialClassesDO; +import com.zt.plat.module.base.service.materialclasses.MaterialClassesService; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.time.LocalDateTime; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class MaterialClassesApiImplTest { + + @InjectMocks + private MaterialClassesApiImpl api; + + @Mock + private MaterialClassesService materialClassesService; + + private MaterialClassesSaveReqDTO buildSaveReq() { + MaterialClassesSaveReqDTO dto = new MaterialClassesSaveReqDTO(); + dto.setId(1L); + dto.setParentId(0L); + dto.setCode("CLS001"); + dto.setName("原材料"); + dto.setLevel(1L); + dto.setRemark("顶级分类"); + return dto; + } + + private MaterialClassesRespVO buildRespVO() { + MaterialClassesRespVO respVO = new MaterialClassesRespVO(); + respVO.setId(1L); + respVO.setParentId(0L); + respVO.setCode("CLS001"); + respVO.setName("原材料"); + respVO.setLevel(1L); + respVO.setRemark("顶级分类"); + respVO.setCreateTime(LocalDateTime.now()); + return respVO; + } + + @Test + void createMaterialClasses_shouldForwardToServiceAndReturnConvertedDto() { + MaterialClassesSaveReqDTO reqDTO = buildSaveReq(); + MaterialClassesRespVO serviceResp = buildRespVO(); + when(materialClassesService.createMaterialClasses(any(MaterialClassesSaveReqVO.class))) + .thenReturn(serviceResp); + + CommonResult result = api.createMaterialClasses(reqDTO); + + assertThat(result.isSuccess()).isTrue(); + assertThat(result.getData().getName()).isEqualTo("原材料"); + + ArgumentCaptor captor = ArgumentCaptor.forClass(MaterialClassesSaveReqVO.class); + verify(materialClassesService).createMaterialClasses(captor.capture()); + MaterialClassesSaveReqVO passed = captor.getValue(); + assertThat(passed.getCode()).isEqualTo(reqDTO.getCode()); + assertThat(passed.getName()).isEqualTo(reqDTO.getName()); + } + + @Test + void updateMaterialClasses_shouldInvokeService() { + MaterialClassesSaveReqDTO reqDTO = buildSaveReq(); + + CommonResult result = api.updateMaterialClasses(reqDTO); + + assertThat(result.isSuccess()).isTrue(); + assertThat(result.getData()).isTrue(); + ArgumentCaptor captor = ArgumentCaptor.forClass(MaterialClassesSaveReqVO.class); + verify(materialClassesService).updateMaterialClasses(captor.capture()); + assertThat(captor.getValue().getCode()).isEqualTo(reqDTO.getCode()); + } + + @Test + void deleteMaterialClasses_shouldInvokeService() { + CommonResult result = api.deleteMaterialClasses(5L); + + assertThat(result.isSuccess()).isTrue(); + assertThat(result.getData()).isTrue(); + verify(materialClassesService).deleteMaterialClasses(5L); + } + + @Test + void deleteMaterialClassesList_shouldInvokeService() { + List ids = List.of(3L, 4L); + + CommonResult result = api.deleteMaterialClassesList(ids); + + assertThat(result.isSuccess()).isTrue(); + assertThat(result.getData()).isTrue(); + verify(materialClassesService).deleteMaterialClassesListByIds(ids); + } + + @Test + void getMaterialClasses_shouldConvertDoToDto() { + MaterialClassesDO classesDO = new MaterialClassesDO(); + classesDO.setId(7L); + classesDO.setName("辅料"); + when(materialClassesService.getMaterialClasses(7L)).thenReturn(classesDO); + + CommonResult result = api.getMaterialClasses(7L); + + assertThat(result.isSuccess()).isTrue(); + assertThat(result.getData().getId()).isEqualTo(7L); + assertThat(result.getData().getName()).isEqualTo("辅料"); + } + + @Test + void getMaterialClassesPage_shouldConvertPageResult() { + MaterialClassesDO classesDO = new MaterialClassesDO(); + classesDO.setId(8L); + classesDO.setName("辅料"); + PageResult page = new PageResult<>(List.of(classesDO), 1L); + when(materialClassesService.getMaterialClassesPage(any(MaterialClassesPageReqVO.class))) + .thenReturn(page); + + MaterialClassesPageReqDTO reqDTO = new MaterialClassesPageReqDTO(); + reqDTO.setName("辅料"); + + CommonResult> result = api.getMaterialClassesPage(reqDTO); + + assertThat(result.isSuccess()).isTrue(); + assertThat(result.getData().getList()).hasSize(1); + assertThat(result.getData().getList().get(0).getName()).isEqualTo("辅料"); + assertThat(result.getData().getTotal()).isEqualTo(1L); + } + + @Test + void getMaterialClassesTree_shouldAssembleHierarchy() { + MaterialClassesDO root = new MaterialClassesDO(); + root.setId(1L); + root.setParentId(0L); + root.setName("根节点"); + + MaterialClassesDO child = new MaterialClassesDO(); + child.setId(2L); + child.setParentId(1L); + child.setName("子节点"); + + MaterialClassesDO orphan = new MaterialClassesDO(); + orphan.setId(3L); + orphan.setParentId(99L); + orphan.setName("孤儿节点"); + + when(materialClassesService.getMaterialClassesList()).thenReturn(List.of(child, root, orphan)); + + CommonResult> result = api.getMaterialClassesTree(); + + assertThat(result.isSuccess()).isTrue(); + List tree = result.getData(); + assertThat(tree).hasSize(2); + MaterialClassesTreeRespDTO rootNode = tree.get(0); + assertThat(rootNode.getId()).isEqualTo(1L); + assertThat(rootNode.getChildren()).hasSize(1); + assertThat(rootNode.getChildren().get(0).getId()).isEqualTo(2L); + + MaterialClassesTreeRespDTO orphanNode = tree.get(1); + assertThat(orphanNode.getId()).isEqualTo(3L); + assertThat(orphanNode.getChildren()).isEmpty(); + } +} From 6adda4ac7270da3a3dc25ff0d6468bebf7484493 Mon Sep 17 00:00:00 2001 From: chenbowen Date: Thu, 6 Nov 2025 14:04:29 +0800 Subject: [PATCH 8/9] =?UTF-8?q?1.=20=E8=B0=83=E6=95=B4=E4=B8=9A=E5=8A=A1?= =?UTF-8?q?=20pod=20=E8=B5=84=E6=BA=90=E6=A3=80=E6=9F=A5=E7=9A=84=E5=BB=B6?= =?UTF-8?q?=E6=97=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- deployment.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deployment.yaml b/deployment.yaml index 1d9ccbb6..dad4a1de 100644 --- a/deployment.yaml +++ b/deployment.yaml @@ -30,14 +30,14 @@ spec: httpGet: path: /actuator/health port: 48100 - initialDelaySeconds: 10 + initialDelaySeconds: 50 periodSeconds: 5 failureThreshold: 3 livenessProbe: httpGet: path: /actuator/health port: 48100 - initialDelaySeconds: 30 + initialDelaySeconds: 50 periodSeconds: 10 failureThreshold: 5 resources: From f4bb887f09bc891230bec02bf9afd2b0976c3e95 Mon Sep 17 00:00:00 2001 From: chenbowen Date: Tue, 25 Nov 2025 09:37:43 +0800 Subject: [PATCH 9/9] =?UTF-8?q?1.=20=E5=8D=87=E7=BA=A7=E7=A7=81=E6=9C=89?= =?UTF-8?q?=E5=8C=85=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e65b2515..a2757fab 100644 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ https://github.com/YunaiV/ruoyi-vue-pro - 3.0.44 + 3.0.45 17 ${java.version}