From ad7608e0505a8b6aa4b1175bf95dbf1ceb7e5814 Mon Sep 17 00:00:00 2001 From: liyongde <1419499670@qq.com> Date: Mon, 17 Aug 2026 21:09:16 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=9E=E7=8E=B0=E5=AD=90=E5=8D=B7?= =?UTF-8?q?=E5=8C=85=E8=A3=85=E5=85=B3=E7=B3=BB=E5=88=86=E7=BB=84=E6=89=B9?= =?UTF-8?q?=E9=87=8F=E4=BF=9D=E5=AD=98=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SubPackageRelationController.java | 8 + .../SubPackageRelationBatchCreateRespVO.java | 4 +- .../SubPackageRelationService.java | 8 + .../SubPackageRelationServiceImpl.java | 172 +++++++++++++++++- 4 files changed, 186 insertions(+), 6 deletions(-) diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/admin/subpackagerelation/SubPackageRelationController.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/admin/subpackagerelation/SubPackageRelationController.java index 2b897e9a..1687cf6b 100644 --- a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/admin/subpackagerelation/SubPackageRelationController.java +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/admin/subpackagerelation/SubPackageRelationController.java @@ -38,6 +38,14 @@ public class SubPackageRelationController { @Resource private SubPackageRelationService subPackageRelationService; + @PostMapping("/batch-create") + @Operation(summary = "批量创建子卷包装关系") + @PreAuthorize("@ss.hasPermission('lms:sub-package-relation:create')") + public CommonResult batchCreateSubPackageRelation( + @Valid @RequestBody SubPackageRelationBatchCreateReqVO reqVO) { + return success(subPackageRelationService.batchCreateSubPackageRelation(reqVO)); + } + @PostMapping("/create") @Operation(summary = "创建子卷包装关系") @PreAuthorize("@ss.hasPermission('lms:sub-package-relation:create')") diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/admin/subpackagerelation/vo/SubPackageRelationBatchCreateRespVO.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/admin/subpackagerelation/vo/SubPackageRelationBatchCreateRespVO.java index 2aaf449f..9a1e3c93 100644 --- a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/admin/subpackagerelation/vo/SubPackageRelationBatchCreateRespVO.java +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/admin/subpackagerelation/vo/SubPackageRelationBatchCreateRespVO.java @@ -41,8 +41,8 @@ public class SubPackageRelationBatchCreateRespVO { @Schema(description = "客户端唯一标识") private String clientKey; - /** 数据行号 */ - @Schema(description = "数据行号") + /** 数据行号,从 1 开始 */ + @Schema(description = "数据行号,从 1 开始") private Integer rowIndex; /** 错误编码 */ diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/subpackagerelation/SubPackageRelationService.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/subpackagerelation/SubPackageRelationService.java index 7b03919c..7c89dcdd 100644 --- a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/subpackagerelation/SubPackageRelationService.java +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/subpackagerelation/SubPackageRelationService.java @@ -14,6 +14,14 @@ import cn.code.nl.framework.common.pojo.PageParam; */ public interface SubPackageRelationService { + /** + * 批量创建子卷包装关系 + * + * @param reqVO 批量创建信息 + * @return 批量创建结果 + */ + SubPackageRelationBatchCreateRespVO batchCreateSubPackageRelation(SubPackageRelationBatchCreateReqVO reqVO); + /** * 创建子卷包装关系 * diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/subpackagerelation/SubPackageRelationServiceImpl.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/subpackagerelation/SubPackageRelationServiceImpl.java index 17d0ea48..ef3fdadb 100644 --- a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/subpackagerelation/SubPackageRelationServiceImpl.java +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/subpackagerelation/SubPackageRelationServiceImpl.java @@ -1,23 +1,25 @@ package cn.code.nl.module.lms.service.subpackagerelation; import cn.hutool.core.collection.CollUtil; +import cn.code.nl.module.lms.dal.dataobject.boxtype.BoxTypeDO; +import cn.code.nl.module.lms.dal.mysql.boxtype.BoxTypeMapper; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import jakarta.annotation.Resource; import org.springframework.validation.annotation.Validated; -import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.StringUtils; import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; import cn.code.nl.module.lms.controller.admin.subpackagerelation.vo.*; import cn.code.nl.module.lms.dal.dataobject.subpackagerelation.SubPackageRelationDO; import cn.code.nl.framework.common.pojo.PageResult; -import cn.code.nl.framework.common.pojo.PageParam; import cn.code.nl.framework.common.util.object.BeanUtils; import cn.code.nl.module.lms.dal.mysql.subpackagerelation.SubPackageRelationMapper; import static cn.code.nl.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.code.nl.framework.common.util.collection.CollectionUtils.convertList; -import static cn.code.nl.framework.common.util.collection.CollectionUtils.diffList; import static cn.code.nl.module.lms.enums.ErrorCodeConstants.*; /** @@ -27,11 +29,161 @@ import static cn.code.nl.module.lms.enums.ErrorCodeConstants.*; */ @Service @Validated +@Slf4j public class SubPackageRelationServiceImpl implements SubPackageRelationService { + /** 必填字段缺失错误码 */ + private static final String REQUIRED_FIELD_MISSING = "REQUIRED_FIELD_MISSING"; + /** 木箱类型不存在错误码 */ + private static final String BOX_TYPE_NOT_FOUND = "BOX_TYPE_NOT_FOUND"; + /** 木箱容量超限错误码 */ + private static final String BOX_CAPACITY_EXCEEDED = "BOX_CAPACITY_EXCEEDED"; + /** 分组保存失败错误码 */ + private static final String GROUP_SAVE_FAILED = "GROUP_SAVE_FAILED"; + + /** 子卷包装关系数据访问对象 */ @Resource private SubPackageRelationMapper subPackageRelationMapper; + /** 木箱类型数据访问对象 */ + @Resource + private BoxTypeMapper boxTypeMapper; + + /** 子卷包装关系分组独立事务保存服务 */ + @Resource + private SubPackageRelationBatchSaveService batchSaveService; + + /** + * 按木箱唯一码和木箱料号分组批量创建子卷包装关系 + */ + @Override + public SubPackageRelationBatchCreateRespVO batchCreateSubPackageRelation(SubPackageRelationBatchCreateReqVO reqVO) { + List failures = new ArrayList<>(); + List validItems = new ArrayList<>(); + for (int index = 0; index < reqVO.getItems().size(); index++) { + SubPackageRelationBatchCreateItemReqVO item = reqVO.getItems().get(index); + int rowIndex = index + 1; + if (item == null) { + failures.add(buildFailure(null, rowIndex, REQUIRED_FIELD_MISSING, "缺失字段:item")); + continue; + } + List missingFields = new ArrayList<>(); + if (!StringUtils.hasText(item.getClientKey())) { + missingFields.add("clientKey"); + } + if (!StringUtils.hasText(item.getPackageBoxSn())) { + missingFields.add("packageBoxSn"); + } + if (!StringUtils.hasText(item.getBoxType())) { + missingFields.add("boxType"); + } + if (!StringUtils.hasText(item.getQualityGuaranPeriod())) { + missingFields.add("qualityGuaranPeriod"); + } + if (!StringUtils.hasText(item.getDateOfFgInbound())) { + missingFields.add("dateOfFgInbound"); + } + if (!StringUtils.hasText(item.getContainerName())) { + missingFields.add("containerName"); + } + if (!StringUtils.hasText(item.getStatus())) { + missingFields.add("status"); + } + if (!CollUtil.isEmpty(missingFields)) { + failures.add(buildFailure(item.getClientKey(), rowIndex, REQUIRED_FIELD_MISSING, + "缺失字段:" + String.join("、", missingFields))); + continue; + } + validItems.add(new BatchItemContext(item, rowIndex)); + } + if (CollUtil.isEmpty(validItems)) { + return SubPackageRelationBatchCreateRespVO.builder() + .successCount(0) + .failureCount(failures.size()) + .failures(failures) + .build(); + } + + Set boxTypes = validItems.stream() + .map(context -> context.item().getBoxType()) + .collect(Collectors.toCollection(LinkedHashSet::new)); + Map boxTypeMap = boxTypeMapper.selectListByBoxTypes(boxTypes).stream() + .collect(Collectors.toMap(BoxTypeDO::getBoxType, Function.identity())); + Map> groups = validItems.stream() + .collect(Collectors.groupingBy(context -> new GroupKey(context.item().getPackageBoxSn(), + context.item().getBoxType()), LinkedHashMap::new, Collectors.toList())); + + int successCount = 0; + for (Map.Entry> entry : groups.entrySet()) { + GroupKey key = entry.getKey(); + List group = entry.getValue(); + BoxTypeDO boxType = boxTypeMap.get(key.boxType()); + if (boxType == null) { + for (BatchItemContext context : group) { + failures.add(buildFailure(context.item().getClientKey(), context.rowIndex(), BOX_TYPE_NOT_FOUND, + "木箱类型 " + key.boxType() + " 不存在")); + } + continue; + } + Long existingCount = subPackageRelationMapper.selectCountByPackageBoxSnAndBoxType( + key.packageBoxSn(), key.boxType()); + if (existingCount + group.size() > boxType.getMaxNum()) { + String message = String.format("木箱 %s(类型 %s)最多容纳 %d 个子卷,已有 %d 个,本次提交 %d 个", + key.packageBoxSn(), key.boxType(), boxType.getMaxNum(), existingCount, group.size()); + for (BatchItemContext context : group) { + failures.add(buildFailure(context.item().getClientKey(), context.rowIndex(), + BOX_CAPACITY_EXCEEDED, message)); + } + continue; + } + + List saveGroup = new ArrayList<>(); + for (BatchItemContext context : group) { + SubPackageRelationBatchCreateItemReqVO item = context.item(); + SubPackageRelationDO relation = new SubPackageRelationDO(); + relation.setPackageBoxSn(item.getPackageBoxSn()); + relation.setBoxType(item.getBoxType()); + relation.setBoxLength(item.getBoxLength()); + relation.setBoxWidth(item.getBoxWidth()); + relation.setBoxHigh(item.getBoxHigh()); + relation.setQualityGuaranPeriod(item.getQualityGuaranPeriod()); + relation.setDateOfFgInbound(item.getDateOfFgInbound()); + relation.setContainerName(item.getContainerName()); + relation.setStatus(item.getStatus()); + saveGroup.add(relation); + } + try { + batchSaveService.saveGroup(saveGroup); + successCount += group.size(); + } catch (Exception exception) { + log.error("木箱 {}(类型 {})保存失败", key.packageBoxSn(), key.boxType(), exception); + String message = String.format("木箱 %s(类型 %s)保存失败", key.packageBoxSn(), key.boxType()); + for (BatchItemContext context : group) { + failures.add(buildFailure(context.item().getClientKey(), context.rowIndex(), GROUP_SAVE_FAILED, + message)); + } + } + } + return SubPackageRelationBatchCreateRespVO.builder() + .successCount(successCount) + .failureCount(failures.size()) + .failures(failures) + .build(); + } + + /** + * 构建批量创建失败信息 + */ + private SubPackageRelationBatchCreateRespVO.Failure buildFailure(String clientKey, int rowIndex, + String errorCode, String message) { + return SubPackageRelationBatchCreateRespVO.Failure.builder() + .clientKey(clientKey) + .rowIndex(rowIndex) + .errorCode(errorCode) + .message(message) + .build(); + } + @Override public Long createSubPackageRelation(SubPackageRelationSaveReqVO createReqVO) { // 插入 @@ -82,4 +234,16 @@ public class SubPackageRelationServiceImpl implements SubPackageRelationService return subPackageRelationMapper.selectPage(pageReqVO); } + /** + * 批量创建数据及其原始行号 + */ + private record BatchItemContext(SubPackageRelationBatchCreateItemReqVO item, int rowIndex) { + } + + /** + * 子卷包装关系分组键 + */ + private record GroupKey(String packageBoxSn, String boxType) { + } + }