feat: 实现子卷包装关系分组批量保存接口
This commit is contained in:
@@ -38,6 +38,14 @@ public class SubPackageRelationController {
|
|||||||
@Resource
|
@Resource
|
||||||
private SubPackageRelationService subPackageRelationService;
|
private SubPackageRelationService subPackageRelationService;
|
||||||
|
|
||||||
|
@PostMapping("/batch-create")
|
||||||
|
@Operation(summary = "批量创建子卷包装关系")
|
||||||
|
@PreAuthorize("@ss.hasPermission('lms:sub-package-relation:create')")
|
||||||
|
public CommonResult<SubPackageRelationBatchCreateRespVO> batchCreateSubPackageRelation(
|
||||||
|
@Valid @RequestBody SubPackageRelationBatchCreateReqVO reqVO) {
|
||||||
|
return success(subPackageRelationService.batchCreateSubPackageRelation(reqVO));
|
||||||
|
}
|
||||||
|
|
||||||
@PostMapping("/create")
|
@PostMapping("/create")
|
||||||
@Operation(summary = "创建子卷包装关系")
|
@Operation(summary = "创建子卷包装关系")
|
||||||
@PreAuthorize("@ss.hasPermission('lms:sub-package-relation:create')")
|
@PreAuthorize("@ss.hasPermission('lms:sub-package-relation:create')")
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ public class SubPackageRelationBatchCreateRespVO {
|
|||||||
@Schema(description = "客户端唯一标识")
|
@Schema(description = "客户端唯一标识")
|
||||||
private String clientKey;
|
private String clientKey;
|
||||||
|
|
||||||
/** 数据行号 */
|
/** 数据行号,从 1 开始 */
|
||||||
@Schema(description = "数据行号")
|
@Schema(description = "数据行号,从 1 开始")
|
||||||
private Integer rowIndex;
|
private Integer rowIndex;
|
||||||
|
|
||||||
/** 错误编码 */
|
/** 错误编码 */
|
||||||
|
|||||||
@@ -14,6 +14,14 @@ import cn.code.nl.framework.common.pojo.PageParam;
|
|||||||
*/
|
*/
|
||||||
public interface SubPackageRelationService {
|
public interface SubPackageRelationService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量创建子卷包装关系
|
||||||
|
*
|
||||||
|
* @param reqVO 批量创建信息
|
||||||
|
* @return 批量创建结果
|
||||||
|
*/
|
||||||
|
SubPackageRelationBatchCreateRespVO batchCreateSubPackageRelation(SubPackageRelationBatchCreateReqVO reqVO);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建子卷包装关系
|
* 创建子卷包装关系
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,23 +1,25 @@
|
|||||||
package cn.code.nl.module.lms.service.subpackagerelation;
|
package cn.code.nl.module.lms.service.subpackagerelation;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
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 org.springframework.stereotype.Service;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import java.util.*;
|
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.controller.admin.subpackagerelation.vo.*;
|
||||||
import cn.code.nl.module.lms.dal.dataobject.subpackagerelation.SubPackageRelationDO;
|
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.PageResult;
|
||||||
import cn.code.nl.framework.common.pojo.PageParam;
|
|
||||||
import cn.code.nl.framework.common.util.object.BeanUtils;
|
import cn.code.nl.framework.common.util.object.BeanUtils;
|
||||||
|
|
||||||
import cn.code.nl.module.lms.dal.mysql.subpackagerelation.SubPackageRelationMapper;
|
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.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.*;
|
import static cn.code.nl.module.lms.enums.ErrorCodeConstants.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -27,11 +29,161 @@ import static cn.code.nl.module.lms.enums.ErrorCodeConstants.*;
|
|||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
@Validated
|
@Validated
|
||||||
|
@Slf4j
|
||||||
public class SubPackageRelationServiceImpl implements SubPackageRelationService {
|
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
|
@Resource
|
||||||
private SubPackageRelationMapper subPackageRelationMapper;
|
private SubPackageRelationMapper subPackageRelationMapper;
|
||||||
|
|
||||||
|
/** 木箱类型数据访问对象 */
|
||||||
|
@Resource
|
||||||
|
private BoxTypeMapper boxTypeMapper;
|
||||||
|
|
||||||
|
/** 子卷包装关系分组独立事务保存服务 */
|
||||||
|
@Resource
|
||||||
|
private SubPackageRelationBatchSaveService batchSaveService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按木箱唯一码和木箱料号分组批量创建子卷包装关系
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public SubPackageRelationBatchCreateRespVO batchCreateSubPackageRelation(SubPackageRelationBatchCreateReqVO reqVO) {
|
||||||
|
List<SubPackageRelationBatchCreateRespVO.Failure> failures = new ArrayList<>();
|
||||||
|
List<BatchItemContext> 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<String> 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<String> boxTypes = validItems.stream()
|
||||||
|
.map(context -> context.item().getBoxType())
|
||||||
|
.collect(Collectors.toCollection(LinkedHashSet::new));
|
||||||
|
Map<String, BoxTypeDO> boxTypeMap = boxTypeMapper.selectListByBoxTypes(boxTypes).stream()
|
||||||
|
.collect(Collectors.toMap(BoxTypeDO::getBoxType, Function.identity()));
|
||||||
|
Map<GroupKey, List<BatchItemContext>> 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<GroupKey, List<BatchItemContext>> entry : groups.entrySet()) {
|
||||||
|
GroupKey key = entry.getKey();
|
||||||
|
List<BatchItemContext> 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<SubPackageRelationDO> 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
|
@Override
|
||||||
public Long createSubPackageRelation(SubPackageRelationSaveReqVO createReqVO) {
|
public Long createSubPackageRelation(SubPackageRelationSaveReqVO createReqVO) {
|
||||||
// 插入
|
// 插入
|
||||||
@@ -82,4 +234,16 @@ public class SubPackageRelationServiceImpl implements SubPackageRelationService
|
|||||||
return subPackageRelationMapper.selectPage(pageReqVO);
|
return subPackageRelationMapper.selectPage(pageReqVO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量创建数据及其原始行号
|
||||||
|
*/
|
||||||
|
private record BatchItemContext(SubPackageRelationBatchCreateItemReqVO item, int rowIndex) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 子卷包装关系分组键
|
||||||
|
*/
|
||||||
|
private record GroupKey(String packageBoxSn, String boxType) {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user