@@ -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 < 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
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 ) {
}
}