@@ -42,6 +42,7 @@ public class WmsStockIoServiceImpl implements IWmsStockIoService {
private final WmsStockMapper stockMapper ;
private final WmsProductMapper productMapper ;
private final WmsRawMaterialMapper rawMaterialMapper ;
private final WmsWarehouseMapper warehouseMapper ;
@Resource
private WmsStockLogMapper stockLogMapper ;
@@ -132,6 +133,7 @@ public class WmsStockIoServiceImpl implements IWmsStockIoService {
public void addWithDetail ( WmsStockIoWithDetailBo bo ) {
// 插入主表
WmsStockIo stockIo = BeanUtil . toBean ( bo , WmsStockIo . class ) ;
stockIo . setParentId ( bo . getStockIoId ( ) ) ;
baseMapper . insert ( stockIo ) ;
// 插入明细
if ( bo . getDetails ( ) ! = null & & ! bo . getDetails ( ) . isEmpty ( ) ) {
@@ -186,6 +188,191 @@ public class WmsStockIoServiceImpl implements IWmsStockIoService {
return true ;
}
@Override
@Transactional ( rollbackFor = Exception . class )
public boolean scanReturnStockByBo ( WmsStockIoBo bo ) {
// 退库操作: 根据id查询明细表, 根据parent_id获取原出库单明细, 验证退库数量
if ( bo . getStockIoId ( ) = = null ) {
throw new ServiceException ( " 退库单ID不能为空 " ) ;
}
// 1. 根据id查询退库单明细
WmsStockIoDetail returnDetail = stockIoDetailMapper . selectById ( bo . getStockIoId ( ) ) ;
if ( returnDetail = = null ) {
throw new ServiceException ( " 退库明细不存在 " ) ;
}
// 验证退库数量必须大于0
if ( returnDetail . getQuantity ( ) = = null | | returnDetail . getQuantity ( ) . compareTo ( BigDecimal . ZERO ) < = 0 ) {
throw new ServiceException ( " 退库数量必须大于0 " ) ;
}
// 验证物品类型和物品ID的有效性
if ( returnDetail . getItemType ( ) = = null | | returnDetail . getItemId ( ) = = null ) {
throw new ServiceException ( " 物品类型和物品ID不能为空 " ) ;
}
if ( ! " product " . equals ( returnDetail . getItemType ( ) ) & & ! " raw_material " . equals ( returnDetail . getItemType ( ) ) ) {
throw new ServiceException ( " 物品类型必须是product或raw_material " ) ;
}
// 验证库位ID的有效性
if ( returnDetail . getWarehouseId ( ) = = null ) {
throw new ServiceException ( " 库位ID不能为空 " ) ;
}
// 验证物品是否存在
if ( " product " . equals ( returnDetail . getItemType ( ) ) ) {
WmsProduct product = productMapper . selectById ( returnDetail . getItemId ( ) ) ;
if ( product = = null ) {
throw new ServiceException ( " 产品不存在 " ) ;
}
} else if ( " raw_material " . equals ( returnDetail . getItemType ( ) ) ) {
WmsRawMaterial rawMaterial = rawMaterialMapper . selectById ( returnDetail . getItemId ( ) ) ;
if ( rawMaterial = = null ) {
throw new ServiceException ( " 原材料不存在 " ) ;
}
}
// 验证库位是否存在
WmsWarehouse warehouse = warehouseMapper . selectById ( returnDetail . getWarehouseId ( ) ) ;
if ( warehouse = = null ) {
throw new ServiceException ( " 库位不存在 " ) ;
}
// 验证库位是否启用
if ( warehouse . getIsEnabled ( ) = = null | | warehouse . getIsEnabled ( ) ! = 1 ) {
throw new ServiceException ( " 库位未启用,无法进行退库操作 " ) ;
}
// 2. 获取退库单主表信息
WmsStockIo returnStockIo = baseMapper . selectById ( returnDetail . getStockIoId ( ) ) ;
if ( returnStockIo = = null ) {
throw new ServiceException ( " 退库单不存在 " ) ;
}
// 验证退库单类型必须是入库类型
if ( ! " in " . equals ( returnStockIo . getIoType ( ) ) ) {
throw new ServiceException ( " 退库单类型必须是入库类型 " ) ;
}
// 验证退库单状态必须是已提交或已审核状态
if ( returnStockIo . getStatus ( ) = = null | | ( returnStockIo . getStatus ( ) ! = 1 & & returnStockIo . getStatus ( ) ! = 2 ) ) {
throw new ServiceException ( " 退库单必须是已提交或已审核状态才能执行退库操作 " ) ;
}
// 3. 根据parent_id获取原出库单的所有明细
if ( returnStockIo . getParentId ( ) = = null ) {
throw new ServiceException ( " 退库单未关联原出库单 " ) ;
}
WmsStockIo originalOutStockIo = baseMapper . selectById ( returnStockIo . getParentId ( ) ) ;
if ( originalOutStockIo = = null ) {
throw new ServiceException ( " 原出库单不存在 " ) ;
}
if ( ! " out " . equals ( originalOutStockIo . getIoType ( ) ) ) {
throw new ServiceException ( " 原单据不是出库单 " ) ;
}
// 验证原出库单状态必须是已审核状态
if ( originalOutStockIo . getStatus ( ) = = null | | originalOutStockIo . getStatus ( ) ! = 2 ) {
throw new ServiceException ( " 原出库单必须是已审核状态才能进行退库操作 " ) ;
}
// 4. 获取原出库单的所有明细
List < WmsStockIoDetail > originalOutDetails = stockIoDetailMapper . selectList (
Wrappers . < WmsStockIoDetail > lambdaQuery ( )
. eq ( WmsStockIoDetail : : getStockIoId , returnStockIo . getParentId ( ) )
) ;
if ( originalOutDetails = = null | | originalOutDetails . isEmpty ( ) ) {
throw new ServiceException ( " 原出库单明细不存在 " ) ;
}
// 5. 查找对应的原出库明细( 根据物品类型、物品ID、库位ID匹配)
WmsStockIoDetail originalOutDetail = null ;
for ( WmsStockIoDetail detail : originalOutDetails ) {
if ( detail . getItemType ( ) . equals ( returnDetail . getItemType ( ) ) & &
detail . getItemId ( ) . equals ( returnDetail . getItemId ( ) ) & &
detail . getWarehouseId ( ) . equals ( returnDetail . getWarehouseId ( ) ) ) {
originalOutDetail = detail ;
break ;
}
}
if ( originalOutDetail = = null ) {
throw new ServiceException ( " 未找到对应的原出库明细 " ) ;
}
// 6. 查询该物品已退库的总数量
BigDecimal totalReturnedQty = BigDecimal . ZERO ;
List < WmsStockIo > returnStockIos = baseMapper . selectList (
Wrappers . < WmsStockIo > lambdaQuery ( )
. eq ( WmsStockIo : : getParentId , returnStockIo . getParentId ( ) )
. eq ( WmsStockIo : : getIoType , " in " ) // 退库单类型为入库
) ;
for ( WmsStockIo returnStockIoItem : returnStockIos ) {
// 排除当前正在处理的退库单
if ( returnStockIoItem . getStockIoId ( ) . equals ( returnStockIo . getStockIoId ( ) ) ) {
continue ;
}
List < WmsStockIoDetail > returnDetails = stockIoDetailMapper . selectList (
Wrappers . < WmsStockIoDetail > lambdaQuery ( )
. eq ( WmsStockIoDetail : : getStockIoId , returnStockIoItem . getStockIoId ( ) )
. eq ( WmsStockIoDetail : : getItemType , returnDetail . getItemType ( ) )
. eq ( WmsStockIoDetail : : getItemId , returnDetail . getItemId ( ) )
. eq ( WmsStockIoDetail : : getWarehouseId , returnDetail . getWarehouseId ( ) )
) ;
for ( WmsStockIoDetail detail : returnDetails ) {
totalReturnedQty = totalReturnedQty . add ( detail . getQuantity ( ) ) ;
}
}
// 7. 验证退库数量不能超过原出库数量
BigDecimal remainingQty = originalOutDetail . getQuantity ( ) . subtract ( totalReturnedQty ) ;
if ( returnDetail . getQuantity ( ) . compareTo ( remainingQty ) > 0 ) {
throw new ServiceException ( " 退库数量超过原出库数量,原出库数量: " + originalOutDetail . getQuantity ( ) +
" ,已退库数量: " + totalReturnedQty + " ,剩余可退数量: " + remainingQty +
" ,本次退库数量: " + returnDetail . getQuantity ( ) ) ;
}
// 8. 执行退库操作(增加库存)
String unit = returnDetail . getUnit ( ) ;
// 如果unit为空, 自动查item表补全
if ( unit = = null | | unit . trim ( ) . isEmpty ( ) ) {
if ( " product " . equals ( returnDetail . getItemType ( ) ) ) {
WmsProduct p = productMapper . selectById ( returnDetail . getItemId ( ) ) ;
unit = p ! = null ? p . getUnit ( ) : null ;
} else if ( " raw_material " . equals ( returnDetail . getItemType ( ) ) ) {
WmsRawMaterial r = rawMaterialMapper . selectById ( returnDetail . getItemId ( ) ) ;
unit = r ! = null ? r . getUnit ( ) : null ;
}
}
if ( unit = = null | | unit . trim ( ) . isEmpty ( ) ) {
throw new ServiceException ( " 未能获取到单位 " ) ;
}
// 执行入库操作(退库就是入库)
changeStock ( returnDetail . getWarehouseId ( ) , returnDetail . getItemType ( ) ,
returnDetail . getItemId ( ) , returnDetail . getQuantity ( ) , true , unit ) ;
// 记录退库操作日志
WmsStockLog returnLog = new WmsStockLog ( ) ;
returnLog . setWarehouseId ( returnDetail . getWarehouseId ( ) ) ;
returnLog . setItemType ( returnDetail . getItemType ( ) ) ;
returnLog . setItemId ( returnDetail . getItemId ( ) ) ;
returnLog . setChangeQty ( returnDetail . getQuantity ( ) ) ;
returnLog . setChangeType ( " 退库 " ) ;
returnLog . setChangeTime ( new Date ( ) ) ;
stockLogMapper . insert ( returnLog ) ;
return true ;
}
/**
* 审核出入库/移库单,变更库存,含库存校验