From c5da270de155e5d29ea078b6c443a8484fdbf3e8 Mon Sep 17 00:00:00 2001 From: wuzongyong <13203449218@163.com> Date: Thu, 8 Jan 2026 17:23:00 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat(material):=20=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E7=89=A9=E6=96=99=E4=BF=A1=E6=81=AF=E5=93=8D=E5=BA=94DTO?= =?UTF-8?q?=E7=9A=84JSON=E5=BA=8F=E5=88=97=E5=8C=96=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=EF=BC=8C=E8=A7=A3=E5=86=B3=E9=97=AE=E9=A2=98=E4=BD=BF=E7=94=A8?= =?UTF-8?q?id=E8=B0=83=E7=94=A8feign=E6=8E=A5=E5=8F=A3=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E8=BF=94=E5=9B=9E=E4=B8=BAnull=E7=9A=84=E9=97=AE=E9=A2=98?= =?UTF-8?q?=EF=BC=8C=E4=BB=BB=E5=8A=A1id690?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 为ID、编码、名称、分类ID、备注和创建时间字段添加JsonProperty注解 - 将flatAttributes字段初始化为LinkedHashMap以保证顺序 - 添加JsonAnySetter注解和addAttribute方法处理动态属性 - 移除原flatAttributes字段的序列化展开说明 --- .../dto/MaterialInfomationRespDTO.java | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialinfomation/dto/MaterialInfomationRespDTO.java b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialinfomation/dto/MaterialInfomationRespDTO.java index eeb1ba5d..c92a8207 100644 --- a/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialinfomation/dto/MaterialInfomationRespDTO.java +++ b/zt-module-base/zt-module-base-api/src/main/java/com/zt/plat/module/base/api/materialinfomation/dto/MaterialInfomationRespDTO.java @@ -1,11 +1,14 @@ package com.zt.plat.module.base.api.materialinfomation.dto; import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.time.LocalDateTime; +import java.util.LinkedHashMap; import java.util.Map; /** @@ -14,36 +17,44 @@ import java.util.Map; @Data public class MaterialInfomationRespDTO { - @JsonIgnore + @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) @Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "3326") private Long id; - @JsonIgnore + @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) @Schema(description = "物料编码", requiredMode = Schema.RequiredMode.REQUIRED) private String code; - @JsonIgnore + @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) @Schema(description = "物料名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三") private String name; - @JsonIgnore + @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) @Schema(description = "分类ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") private Long classesId; - @JsonIgnore + @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) @Schema(description = "备注", requiredMode = Schema.RequiredMode.REQUIRED) private String remark; - @JsonIgnore + @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; @JsonIgnore - @Schema(description = "物料基础字段 + 属性编码->原值的动态键值,基础字段优先,序列化时直接展开为顶层字段") - private Map flatAttributes; + @Schema(description = "物料基础字段 + 属性编码->原值的动态键值") + private Map flatAttributes = new LinkedHashMap<>(); @JsonAnyGetter public Map getFlatAttributes() { return flatAttributes; } + + @JsonAnySetter + public void addAttribute(String key, Object value) { + if (flatAttributes == null) { + flatAttributes = new LinkedHashMap<>(); + } + flatAttributes.put(key, value); + } } \ No newline at end of file From 47b256c8d01525eb8294d972cb036d7bf0d61e8f 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: Thu, 8 Jan 2026 17:58:14 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=BA=93=E4=BD=8D?= =?UTF-8?q?=E6=96=B0=E8=A1=A8=E7=9A=84=E7=9B=B8=E5=85=B3=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=EF=BC=8C=E4=BF=AE=E5=A4=8D=E5=90=88=E5=90=8C=E6=94=B6=E5=8F=91?= =?UTF-8?q?=E8=B4=A7=E8=A7=84=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/dto/contract/DetailRespDTO.java | 29 ++++ .../api/vo/contract/DetailRespVO.java | 31 +++++ .../api/vo/contract/DetailSaveReqVO.java | 29 ++++ .../enums/ErrorCodeConstants.java | 1 + .../util/ContractReceiveSendValidator.java | 131 ++++++++++++++++++ .../dataobject/contract/ContractDetailDO.java | 29 ++++ .../service/contract/ContractServiceImpl.java | 10 +- 7 files changed, 259 insertions(+), 1 deletion(-) create mode 100644 zt-module-contract-order/zt-module-contract-order-server/src/main/java/com/zt/plat/module/contractorder/controller/admin/contract/util/ContractReceiveSendValidator.java diff --git a/zt-module-contract-order/zt-module-contract-order-api/src/main/java/com/zt/plat/module/contractorder/api/dto/contract/DetailRespDTO.java b/zt-module-contract-order/zt-module-contract-order-api/src/main/java/com/zt/plat/module/contractorder/api/dto/contract/DetailRespDTO.java index f927c5a2..1d98118c 100644 --- a/zt-module-contract-order/zt-module-contract-order-api/src/main/java/com/zt/plat/module/contractorder/api/dto/contract/DetailRespDTO.java +++ b/zt-module-contract-order/zt-module-contract-order-api/src/main/java/com/zt/plat/module/contractorder/api/dto/contract/DetailRespDTO.java @@ -59,6 +59,35 @@ public class DetailRespDTO { @Schema(description = "长度") private String length; + // 中文牌名 + @Schema(description = "中文牌名") + private String chineseNo; + + // 英文牌名 + @Schema(description = "英文牌名") + private String englishNo; + + // 技术规格 + @Schema(description = "技术规格") + private String technicalSpecification; + + // 技术标准1 + @Schema(description = "技术标准1") + private String technicalStandard1; + + // 技术标准2 + @Schema(description = "技术标准2") + private String technicalStandard2; + + // 线别 + @Schema(description = "线别") + private String lineLevel; + + // 包装 + @Schema(description = "包装") + private String pack; + + @Schema(description = "交货计划") private List plans; } diff --git a/zt-module-contract-order/zt-module-contract-order-api/src/main/java/com/zt/plat/module/contractorder/api/vo/contract/DetailRespVO.java b/zt-module-contract-order/zt-module-contract-order-api/src/main/java/com/zt/plat/module/contractorder/api/vo/contract/DetailRespVO.java index c88720b0..6a8b5e21 100644 --- a/zt-module-contract-order/zt-module-contract-order-api/src/main/java/com/zt/plat/module/contractorder/api/vo/contract/DetailRespVO.java +++ b/zt-module-contract-order/zt-module-contract-order-api/src/main/java/com/zt/plat/module/contractorder/api/vo/contract/DetailRespVO.java @@ -1,5 +1,6 @@ package com.zt.plat.module.contractorder.api.vo.contract; +import com.baomidou.mybatisplus.annotation.TableField; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -59,6 +60,36 @@ public class DetailRespVO { @Schema(description = "长度") private String length; + + // 中文牌名 + @Schema(description = "中文牌名") + private String chineseNo; + + // 英文牌名 + @Schema(description = "英文牌名") + private String englishNo; + + // 技术规格 + @Schema(description = "技术规格") + private String technicalSpecification; + + // 技术标准1 + @Schema(description = "技术标准1") + private String technicalStandard1; + + // 技术标准2 + @Schema(description = "技术标准2") + private String technicalStandard2; + + // 线别 + @Schema(description = "线别") + private String lineLevel; + + // 包装 + @Schema(description = "包装") + private String pack; + // 交货计划 + @Schema(description = "交货计划") private List plans; } diff --git a/zt-module-contract-order/zt-module-contract-order-api/src/main/java/com/zt/plat/module/contractorder/api/vo/contract/DetailSaveReqVO.java b/zt-module-contract-order/zt-module-contract-order-api/src/main/java/com/zt/plat/module/contractorder/api/vo/contract/DetailSaveReqVO.java index 6e06339c..6044a56b 100644 --- a/zt-module-contract-order/zt-module-contract-order-api/src/main/java/com/zt/plat/module/contractorder/api/vo/contract/DetailSaveReqVO.java +++ b/zt-module-contract-order/zt-module-contract-order-api/src/main/java/com/zt/plat/module/contractorder/api/vo/contract/DetailSaveReqVO.java @@ -55,6 +55,35 @@ public class DetailSaveReqVO { @Schema(description = "长度") private String length; + // 中文牌名 + @Schema(description = "中文牌名") + private String chineseNo; + + // 英文牌名 + @Schema(description = "英文牌名") + private String englishNo; + + // 技术规格 + @Schema(description = "技术规格") + private String technicalSpecification; + + // 技术标准1 + @Schema(description = "技术标准1") + private String technicalStandard1; + + // 技术标准2 + @Schema(description = "技术标准2") + private String technicalStandard2; + + // 线别 + @Schema(description = "线别") + private String lineLevel; + + // 包装 + @Schema(description = "包装") + private String pack; + + // 交货计划 private List plans; } \ No newline at end of file diff --git a/zt-module-contract-order/zt-module-contract-order-api/src/main/java/com/zt/plat/module/contractorder/enums/ErrorCodeConstants.java b/zt-module-contract-order/zt-module-contract-order-api/src/main/java/com/zt/plat/module/contractorder/enums/ErrorCodeConstants.java index efa7b425..28ed73c3 100644 --- a/zt-module-contract-order/zt-module-contract-order-api/src/main/java/com/zt/plat/module/contractorder/enums/ErrorCodeConstants.java +++ b/zt-module-contract-order/zt-module-contract-order-api/src/main/java/com/zt/plat/module/contractorder/enums/ErrorCodeConstants.java @@ -19,6 +19,7 @@ public interface ErrorCodeConstants { ErrorCode CONTRACT_ID_NOT_EXISTS = new ErrorCode(1_027_000_004, "合同主键为空"); ErrorCode CONTRACT_STATUS_NOT_UPDATE = new ErrorCode(1_027_000_005, "{}状态合同不允许修改"); ErrorCode CONTRACT_DATA_NOT_EXISTS = new ErrorCode(1_027_000_006, "{}不存在"); + ErrorCode CONTRACT_PARAMS_ERROR = new ErrorCode(1_027_000_100, "{}"); ErrorCode CONTRACT_STATUS_NOT_SUBMIT_APPROVAL = new ErrorCode(1_027_000_007, "{}状态合同不允许提交审核"); ErrorCode CONTRACT_STATUS_NOT_APPROVAL = new ErrorCode(1_027_000_008, "{}状态合同不允许审核"); ErrorCode CONTRACT_ERP_COMPANY_PLEASE_BIND = new ErrorCode(1_027_000_009, "请先绑定{}ERP公司信息"); diff --git a/zt-module-contract-order/zt-module-contract-order-server/src/main/java/com/zt/plat/module/contractorder/controller/admin/contract/util/ContractReceiveSendValidator.java b/zt-module-contract-order/zt-module-contract-order-server/src/main/java/com/zt/plat/module/contractorder/controller/admin/contract/util/ContractReceiveSendValidator.java new file mode 100644 index 00000000..8f8d98e6 --- /dev/null +++ b/zt-module-contract-order/zt-module-contract-order-server/src/main/java/com/zt/plat/module/contractorder/controller/admin/contract/util/ContractReceiveSendValidator.java @@ -0,0 +1,131 @@ +package com.zt.plat.module.contractorder.controller.admin.contract.util; + +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import com.zt.plat.module.contractorder.api.vo.contract.ContractReceiveSendSaveReqVO; +import io.swagger.v3.oas.annotations.media.Schema; +import java.lang.reflect.Field; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; + +// 补充项目自定义异常相关的import +import static com.zt.plat.framework.common.exception.util.ServiceExceptionUtil.exception; +import static com.zt.plat.module.contractorder.enums.ErrorCodeConstants.CONTRACT_PARAMS_ERROR; + +public class ContractReceiveSendValidator { + + /** + * 校验收发货规则列表的合法性(无返回值,校验失败直接抛异常) + * 规则:排除id和继承字段,需校验字段要么全有值/全为空;报错显示@Schema的description + */ + public static void validateContractReceiveSend(List contractReceiveSends) { + // 列表为空时,无需校验,直接结束方法 + if (CollectionUtils.isEmpty(contractReceiveSends)) { + return; + } + + // 遍历列表逐个校验 + for (int index = 0; index < contractReceiveSends.size(); index++) { + ContractReceiveSendSaveReqVO vo = contractReceiveSends.get(index); + validateSingleVO(vo, index); + } + } + + /** + * 校验单个VO对象(核心:获取@Schema的description并替换字段名) + */ + private static void validateSingleVO(ContractReceiveSendSaveReqVO vo, int index) { + if (vo == null) { + return; // 单个对象为null,视为全空,合法 + } + + Class clazz = vo.getClass(); + Field[] declaredFields = clazz.getDeclaredFields(); + List targetFields = new ArrayList<>(); + + // 过滤:排除id字段,保留自有非id字段 + for (Field field : declaredFields) { + if (!"id".equals(field.getName())) { + targetFields.add(field); + } + } + + // 统计有值/空值的字段描述(@Schema的description) + List nonNullFieldDescs = new ArrayList<>(); // 有值字段的描述 + List nullFieldDescs = new ArrayList<>(); // 空值字段的描述 + + for (Field field : targetFields) { + field.setAccessible(true); + String fieldName = field.getName(); + // 1. 获取字段@Schema注解的description + String fieldDesc = getFieldSchemaDescription(field); + + try { + Object value = field.get(vo); + // 判断是否为“有值” + boolean hasValue = false; + if (value != null) { + if (value instanceof String) { + hasValue = !((String) value).trim().isEmpty(); + } else { + hasValue = true; + } + } + + // 2. 根据值是否为空,将描述加入对应列表 + if (hasValue) { + nonNullFieldDescs.add(fieldDesc); + } else { + nullFieldDescs.add(fieldDesc); + } + } catch (IllegalAccessException e) { + throw new RuntimeException("反射获取字段[" + fieldName + "]值失败", e); + } + } + + // 校验规则:有值字段数>0 且 <总校验字段数 → 不合法,抛自定义异常 + int totalTargetCount = targetFields.size(); + int nonNullCount = nonNullFieldDescs.size(); + if (nonNullCount > 0 && nonNullCount < totalTargetCount) { + // 拼接错误提示信息 + String errorMsg = String.format("列表中第%d个收发货规则对象不符合规则!" + + "需校验字段中,有值字段:%s;空值字段:%s。" + + "规则要求:要么所有需校验字段都有值,要么都为空。", + index, nonNullFieldDescs, nullFieldDescs); + // 抛项目自定义异常 + throw exception(CONTRACT_PARAMS_ERROR, errorMsg); + } + } + + /** + * 获取字段上@Schema注解的description值,无注解则返回字段名 + */ + private static String getFieldSchemaDescription(Field field) { + // 检查字段是否有@Schema注解 + if (field.isAnnotationPresent(Schema.class)) { + Schema schema = field.getAnnotation(Schema.class); + String description = schema.description(); + // 若description为空(如注解只写了example),仍返回字段名 + return description == null || description.trim().isEmpty() ? field.getName() : description; + } + // 无@Schema注解,返回字段名兜底 + return field.getName(); + } + + // 测试示例 + public static void main(String[] args) { + // 测试:部分有值 → 抛自定义异常 + List list = new ArrayList<>(); + ContractReceiveSendSaveReqVO vo = new ContractReceiveSendSaveReqVO(); + vo.setId(1L); + vo.setMaterialName("ZT"); // 物料名称有值 + list.add(vo); + + try { + validateContractReceiveSend(list); // 无返回值,仅执行校验 + } catch (Exception e) { + // 输出报错信息 + System.out.println(e.getMessage()); + } + } +} \ No newline at end of file diff --git a/zt-module-contract-order/zt-module-contract-order-server/src/main/java/com/zt/plat/module/contractorder/dal/dataobject/contract/ContractDetailDO.java b/zt-module-contract-order/zt-module-contract-order-server/src/main/java/com/zt/plat/module/contractorder/dal/dataobject/contract/ContractDetailDO.java index fae854c0..1c7b94bc 100644 --- a/zt-module-contract-order/zt-module-contract-order-server/src/main/java/com/zt/plat/module/contractorder/dal/dataobject/contract/ContractDetailDO.java +++ b/zt-module-contract-order/zt-module-contract-order-server/src/main/java/com/zt/plat/module/contractorder/dal/dataobject/contract/ContractDetailDO.java @@ -98,4 +98,33 @@ public class ContractDetailDO extends BusinessBaseDO { */ @TableField("LEN") private String length; + + + // 中文牌名 + @TableField("CHS_NO") + private String chineseNo; + + // 英文牌名 + @TableField("EN_NO") + private String englishNo; + + // 技术规格 + @TableField("TCHI_SPEC") + private String technicalSpecification; + + // 技术标准1 + @TableField("TCHL_STD1") + private String technicalStandard1; + + // 技术标准2 + @TableField("TCHI_STD2") + private String technicalStandard2; + + // 线别 + @TableField("LINE_LVL") + private String lineLevel; + + // 包装 + @TableField("PACK") + private String pack; } diff --git a/zt-module-contract-order/zt-module-contract-order-server/src/main/java/com/zt/plat/module/contractorder/service/contract/ContractServiceImpl.java b/zt-module-contract-order/zt-module-contract-order-server/src/main/java/com/zt/plat/module/contractorder/service/contract/ContractServiceImpl.java index 53ed1f91..96bff704 100644 --- a/zt-module-contract-order/zt-module-contract-order-server/src/main/java/com/zt/plat/module/contractorder/service/contract/ContractServiceImpl.java +++ b/zt-module-contract-order/zt-module-contract-order-server/src/main/java/com/zt/plat/module/contractorder/service/contract/ContractServiceImpl.java @@ -126,11 +126,19 @@ public class ContractServiceImpl implements ContractService { public PageResult getContractPage(ContractPageReqVO pageReqVO) { return contractMainMapper.selectContractPage(pageReqVO); } + boolean isContractReceiveSendValid(List contractReceiveSends){ + if (CollectionUtils.isEmpty(contractReceiveSends)) { + return true; + } + return false; + + } @Transactional @Override public Long createContract(ContractSaveReqVO reqVO) { - + //校验收发货的规则的合法性 + isContractReceiveSendValid(reqVO.getContractReceiveSends()); // 校验合同名称是否存在 ContractMainDO contract = contractMainMapper .selectOne(TableFieldConstants.BSE_CTRT_MAIN_CTRT_NAME, reqVO.getContractName());