@@ -2,6 +2,7 @@ package com.peanut.modules.master.service.impl;
import com.alipay.api.domain.Product ;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper ;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper ;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page ;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl ;
import com.github.yulichang.wrapper.MPJLambdaWrapper ;
@@ -228,6 +229,13 @@ public class InventoryManagementServiceImpl extends ServiceImpl<InvStockRecordDa
}
if ( dto . getBiz_type ( ) = = InvStockRecord . BIZ_TYPE_SALE ) {
String outboundType = resolveOutboundType ( dto . getOutboundType ( ) ) ;
ShopProduct saleProduct = shopProductDao . selectById ( dto . getProductId ( ) ) ;
if ( isSetBookProduct ( saleProduct ) ) {
// 套书拆单出库:成本取各单本 FIFO 批次,不用请求里的套书 unitCost
saleSetBook ( dto . getMerchantId ( ) , dto . getQuantity ( ) , saleProduct , outboundType ,
null , dto . getRemark ( ) , null , null , null ) ;
return ;
}
List < CostSplit > splits = deductPurchaseStockFifo ( dto . getProductId ( ) , dto . getMerchantId ( ) , dto . getQuantity ( ) ) ;
for ( CostSplit split : splits ) {
BigDecimal saleUnitCost = ( dto . getUnitCost ( ) ! = null & & dto . getUnitCost ( ) . compareTo ( BigDecimal . ZERO ) > 0 )
@@ -244,6 +252,11 @@ public class InventoryManagementServiceImpl extends ServiceImpl<InvStockRecordDa
throw new RuntimeException ( " 单位成本必须大于0 " ) ;
}
ShopProduct product = shopProductDao . selectById ( dto . getProductId ( ) ) ;
if ( isSetBookProduct ( product ) ) {
throw new RuntimeException ( " 套书不支持入库 " ) ;
}
// 采购:跨商户调拨 = 来源方按成本批次多条出库 + 本商户一条采购(成本取接口传值)
// 灵枢→众秒:灵枢出库 outbound_type=zm; 众秒→灵枢: 众秒出库 outbound_type=ls
if ( isCrossMerchantTransfer ( dto . getMerchantId ( ) , dto . getSource ( ) ) ) {
@@ -261,47 +274,11 @@ public class InventoryManagementServiceImpl extends ServiceImpl<InvStockRecordDa
}
// 普通采购( source=other 等)
ShopProduct product = shopProductDao . selectById ( dto . getProductId ( ) ) ;
if ( isSetBookProduct ( product ) ) {
purchaseSetBook ( dto , product ) ;
return ;
}
insertRecord ( dto . getProductId ( ) , dto . getMerchantId ( ) , normalizeSource ( dto . getSource ( ) ) ,
InvStockRecord . BIZ_TYPE_PURCHASE , dto . getQuantity ( ) , dto . getUnitCost ( ) , dto . getRemark ( ) ) ;
adjustShopProductStock ( dto . getProductId ( ) , dto . getQuantity ( ) ) ;
}
/**
* 套装书采购:套书库存增加,套内每本单品按当前商户 FIFO 出库并扣减 shop_product 库存。
* 套内图书从 shop_product_book 按套书 product_id 关联查询。
*/
private void purchaseSetBook ( InvStockRecordDto dto , ShopProduct setProduct ) {
List < Integer > bookIds = listBookIdsByProductId ( setProduct . getProductId ( ) ) ;
if ( bookIds . isEmpty ( ) ) {
throw new RuntimeException ( " 套书未在shop_product_book中关联图书 " ) ;
}
int merchantId = dto . getMerchantId ( ) ;
int quantity = dto . getQuantity ( ) ;
validateSetBookComponentStock ( bookIds , merchantId , quantity , setProduct . getProductId ( ) ) ;
String saleSource = merchantIdToSource ( merchantId ) ;
String outboundRemark = " 套书采购出库[ " + setProduct . getProductName ( ) + " ,productId= " + setProduct . getProductId ( ) + " ] " ;
Long setPurchaseRecordId = insertRecord ( dto . getProductId ( ) , merchantId , normalizeSource ( dto . getSource ( ) ) ,
null , InvStockRecord . BIZ_TYPE_PURCHASE , quantity , dto . getUnitCost ( ) , dto . getRemark ( ) ,
null , null , null , null , null ) ;
for ( Integer bookId : bookIds ) {
ShopProduct component = findComponentProductByBookId ( bookId , setProduct . getProductId ( ) ) ;
List < CostSplit > splits = deductPurchaseStockFifo ( component . getProductId ( ) , merchantId , quantity ) ;
for ( CostSplit split : splits ) {
insertRecord ( component . getProductId ( ) , merchantId , saleSource , InvStockRecord . OUTBOUND_BOOKS ,
InvStockRecord . BIZ_TYPE_SALE , - split . quantity , split . unitCost , outboundRemark ,
null , null , null , split . purchaseRecordId , setPurchaseRecordId ) ;
}
adjustShopProductStock ( component . getProductId ( ) , - quantity ) ;
}
adjustShopProductStock ( dto . getProductId ( ) , quantity ) ;
}
/** 套书判定: shop_product_book 中关联图书数 > 1 */
private boolean isSetBookProduct ( ShopProduct product ) {
if ( product = = null | | product . getProductId ( ) = = null ) {
@@ -346,7 +323,7 @@ public class InventoryManagementServiceImpl extends ServiceImpl<InvStockRecordDa
if ( candidateId = = null ) {
continue ;
}
// 同一 book_id 可能关联套书与单品,优先取 shop_product_book 中仅关联 1 本书的单品 product_id
// 必须是 shop_product_book 中只绑定了 1 本书的单品 product_id
Long bookCount = shopProductBookDao . selectCount (
new LambdaQueryWrapper < ShopProductBookEntity > ( )
. eq ( ShopProductBookEntity : : getProductId , candidateId )
@@ -355,9 +332,6 @@ public class InventoryManagementServiceImpl extends ServiceImpl<InvStockRecordDa
componentProductId = candidateId ;
break ;
}
if ( componentProductId = = null ) {
componentProductId = candidateId ;
}
}
if ( componentProductId = = null ) {
return null ;
@@ -431,7 +405,13 @@ public class InventoryManagementServiceImpl extends ServiceImpl<InvStockRecordDa
if ( quantity < = 0 ) {
throw new RuntimeException ( " 售出数量必须大于0 " ) ;
}
int merchantId = resolveBookOrderMerchantId ( productId , buyOrder, product , quantity );
int merchantId = resolveBookOrderMerchantId ( buyOrder , product ) ;
if ( isSetBookProduct ( product ) ) {
saleSetBook ( merchantId , quantity , product , InvStockRecord . OUTBOUND_APP ,
null , " 套书订单售出[ " + product . getProductName ( ) + " ,productId= " + productId + " ] " ,
buyOrder , null , null ) ;
return ;
}
List < CostSplit > splits = deductPurchaseStockFifo ( productId , merchantId , quantity ) ;
for ( CostSplit split : splits ) {
@@ -440,11 +420,45 @@ public class InventoryManagementServiceImpl extends ServiceImpl<InvStockRecordDa
}
}
/**
* 套书出库:按 shop_product_book 拆成单本商品,分别 FIFO 扣库存并写售出流水。
* App 订单、手工出库、批量出库共用。
*/
private void saleSetBook ( Integer merchantId , int quantity , ShopProduct setProduct , String outboundType ,
BigDecimal overrideUnitCost , String remark , BuyOrder buyOrder ,
Date createTime , String orderSn ) {
Integer setProductId = setProduct . getProductId ( ) ;
List < Integer > bookIds = listBookIdsByProductId ( setProductId ) ;
if ( bookIds . isEmpty ( ) ) {
throw new RuntimeException ( " 套书未在shop_product_book中关联图书 " ) ;
}
validateSetBookComponentStock ( bookIds , merchantId , quantity , setProductId ) ;
String outboundRemark = ( remark = = null | | remark . isBlank ( ) )
? " 套书出库[ " + setProduct . getProductName ( ) + " ,productId= " + setProductId + " ] "
: remark ;
for ( Integer bookId : bookIds ) {
ShopProduct component = findComponentProductByBookId ( bookId , setProductId ) ;
List < CostSplit > splits = deductPurchaseStockFifo ( component . getProductId ( ) , merchantId , quantity ) ;
for ( CostSplit split : splits ) {
BigDecimal saleUnitCost = ( overrideUnitCost ! = null & & overrideUnitCost . compareTo ( BigDecimal . ZERO ) > 0 )
? overrideUnitCost : split . unitCost ;
insertSaleRecord ( component . getProductId ( ) , merchantId , outboundType ,
- split . quantity , saleUnitCost , outboundRemark , buyOrder , createTime , orderSn ,
split . purchaseRecordId ) ;
}
adjustShopProductStock ( component . getProductId ( ) , - quantity ) ;
}
}
/**
* 按订单回滚出库:出库记录有哪些商品,就回加哪些商品的 remain 与 shop_product。
* @return 已回加 shop 的商品ID, 供取消/退款跳过订单行重复回加
*/
@Override
@Transactional ( rollbackFor = Exception . class )
public void rollbackSaleByOrderId ( Integer orderId ) {
public Set < Integer > rollbackSaleByOrderId ( Integer orderId ) {
if ( orderId = = null ) {
return ;
return Collections . emptySet ( ) ;
}
List < InvStockRecord > saleRecords = invStockRecordDao . selectList (
new LambdaQueryWrapper < InvStockRecord > ( )
@@ -453,43 +467,69 @@ public class InventoryManagementServiceImpl extends ServiceImpl<InvStockRecordDa
. orderByDesc ( InvStockRecord : : getId )
) ;
if ( saleRecords = = null | | saleRecords . isEmpty ( ) ) {
return ;
return Collections . emptySet ( ) ;
}
Map < Integer , Integer > shopRestoreMap = new LinkedHashMap < > ( ) ;
// 先全部回加 remain, 失败则整单回滚, 避免只软删出库流水、库存没加回
for ( InvStockRecord sale : saleRecords ) {
int restoreQty = sale . getQuantity ( ) = = null ? 0 : Math . abs ( sale . getQuantity ( ) ) ;
if ( restoreQty > 0 ) {
if ( sale . getPurchaseRecordId ( ) ! = null ) {
restorePurchaseRemainById ( sale . getPurchaseRecordId ( ) , restoreQty ) ;
} else {
restorePurchaseRemain ( sale . getProductId ( ) , sale . getMerchantId ( ) , sale . getUnitCost ( ) , restoreQty ) ;
}
if ( restoreQty < = 0 ) {
continue ;
}
// @TableLogic: deleteById 将 del_flag 置为 1
if ( sale . getPurchaseRecordId ( ) ! = null ) {
restorePurchaseRemainById ( sale . getPurchaseRecordId ( ) , restoreQty ) ;
} else {
restorePurchaseRemain ( sale . getProductId ( ) , sale . getMerchantId ( ) , sale . getUnitCost ( ) , restoreQty ) ;
}
Integer saleProductId = sale . getProductId ( ) ;
if ( saleProductId ! = null ) {
shopRestoreMap . merge ( saleProductId , restoreQty , Integer : : sum ) ;
}
}
for ( InvStockRecord sale : saleRecords ) {
invStockRecordDao . deleteById ( sale . getId ( ) ) ;
}
for ( Map . Entry < Integer , Integer > entry : shopRestoreMap . entrySet ( ) ) {
adjustShopProductStock ( entry . getKey ( ) , entry . getValue ( ) ) ;
}
return shopRestoreMap . keySet ( ) ;
}
/** 按采购流水ID精确 回加 remain_quantity(不超过该批次原始 quantity) */
/** 按采购流水ID原子 回加 remain_quantity;失败抛错,禁止静默跳过 */
private void restorePurchaseRemainById ( Long purchaseRecordId , int restoreQty ) {
if ( purchaseRecordId = = null | | restoreQty < = 0 ) {
throw new RuntimeException ( " 回滚库存参数无效, purchaseRecordId= " + purchaseRecordId + " , qty= " + restoreQty ) ;
}
// 原子加回,避免 select+updateById 静默不生效
Integer rows = invStockRecordDao . update ( null ,
new LambdaUpdateWrapper < InvStockRecord > ( )
. eq ( InvStockRecord : : getId , purchaseRecordId )
. eq ( InvStockRecord : : getBizType , InvStockRecord . BIZ_TYPE_PURCHASE )
. apply ( " IFNULL(remain_quantity,0) + {0} <= IFNULL(quantity,0) " , restoreQty )
. setSql ( " remain_quantity = IFNULL(remain_quantity,0) + " + restoreQty ) ) ;
if ( rows ! = null & & rows > 0 ) {
return ;
}
InvStockRecord purchase = invStockRecordDao . selectById ( purchaseRecordId ) ;
if ( purchase = = null | | purchase . getBizType ( ) = = null
| | purchase . getBizType ( ) ! = InvStockRecord . BIZ_TYPE_PURCHASE ) {
return ;
| | ! Integer . valueOf ( InvStockRecord . BIZ_TYPE_PURCHASE ) . equals ( purchase . getBizType ( ) ) ) {
throw new RuntimeException ( " 回滚库存失败, 采购流水不存在或类型错误, purchaseRecordId= " + purchaseRecordId ) ;
}
int originQty = purchase . getQuantity ( ) = = null ? 0 : purchase . getQuantity ( ) ;
int remainQty = purchase . getRemainQuantity ( ) = = null ? 0 : purchase . getRemainQuantity ( ) ;
int capacity = Math . max ( 0 , originQty - remainQty ) ;
int add = Math . min ( capacity , restoreQty ) ;
if ( add < = 0 ) {
return ;
if ( add > 0 ) {
Integer updated = invStockRecordDao . update ( null ,
new LambdaUpdateWrapper < InvStockRecord > ( )
. eq ( InvStockRecord : : getId , purchaseRecordId )
. eq ( InvStockRecord : : getBizType , InvStockRecord . BIZ_TYPE_PURCHASE )
. setSql ( " remain_quantity = IFNULL(remain_quantity,0) + " + add ) ) ;
if ( updated = = null | | updated < = 0 ) {
throw new RuntimeException ( " 回滚库存失败, 更新采购剩余未生效, purchaseRecordId= " + purchaseRecordId ) ;
}
}
purchase . setRemainQuantity ( remainQty + add ) ;
invStockRecordDao . updateById ( purchase ) ;
if ( add < restoreQty ) {
// 容量不够时按旧逻辑兜底补足(兼容脏数据)
restorePurchaseRemain ( purchase . getProductId ( ) , purchase . getMerchantId ( ) ,
purchase . getUnitCost ( ) , restoreQty - add ) ;
}
@@ -499,9 +539,12 @@ public class InventoryManagementServiceImpl extends ServiceImpl<InvStockRecordDa
* 按成本单价逆 FIFO 回加采购批次剩余库存(不超过该批次原始 quantity)
*/
private void restorePurchaseRemain ( Integer productId , Integer merchantId , BigDecimal unitCost , int restoreQty ) {
if ( productId = = null | | merchantId = = null | | restoreQty < = 0 ) {
if ( restoreQty < = 0 ) {
return ;
}
if ( productId = = null | | merchantId = = null ) {
throw new RuntimeException ( " 回滚库存失败, 缺少商品或商户, productId= " + productId + " , merchantId= " + merchantId ) ;
}
LambdaQueryWrapper < InvStockRecord > wrapper = new LambdaQueryWrapper < InvStockRecord > ( )
. eq ( InvStockRecord : : getProductId , productId )
. eq ( InvStockRecord : : getMerchantId , merchantId )
@@ -523,8 +566,15 @@ public class InventoryManagementServiceImpl extends ServiceImpl<InvStockRecordDa
continue ;
}
int add = Math . min ( capacity , remaining ) ;
purchase . setRemainQuantity ( remainQty + add ) ;
invStockRecordDao . updateById ( purchase ) ;
Integer updated = invStockRecordDao . update ( null ,
new LambdaUpdateWrapper < InvStockRecord > ( )
. eq ( InvStockRecord : : getId , purchase . getId ( ) )
. eq ( InvStockRecord : : getBizType , InvStockRecord . BIZ_TYPE_PURCHASE )
. apply ( " IFNULL(remain_quantity,0) + {0} <= IFNULL(quantity,0) " , add )
. setSql ( " remain_quantity = IFNULL(remain_quantity,0) + " + add ) ) ;
if ( updated = = null | | updated < = 0 ) {
continue ;
}
remaining - = add ;
}
if ( remaining > 0 & & unitCost ! = null ) {
@@ -541,6 +591,9 @@ public class InventoryManagementServiceImpl extends ServiceImpl<InvStockRecordDa
if ( productId = = null ) {
return false ;
}
if ( isSetBookProduct ( product ) ) {
return hasSetBookComponentInvRecord ( productId , buyOrder ) ;
}
if ( isPeanutCoinPay ( buyOrder ) ) {
return hasInvOnMerchant ( productId , InvStockRecord . MERCHANT_ZM ) ;
}
@@ -551,12 +604,50 @@ public class InventoryManagementServiceImpl extends ServiceImpl<InvStockRecordDa
return count ! = null & & count > 0 ;
}
/** 套书:任一单本组件有流水即进入 inv 校验(天医币只认众秒) */
private boolean hasSetBookComponentInvRecord ( Integer setProductId , BuyOrder buyOrder ) {
List < Integer > bookIds = listBookIdsByProductId ( setProductId ) ;
if ( bookIds . isEmpty ( ) ) {
return false ;
}
boolean peanut = isPeanutCoinPay ( buyOrder ) ;
for ( Integer bookId : bookIds ) {
ShopProduct component = findComponentProductByBookId ( bookId , setProductId ) ;
if ( component = = null | | component . getProductId ( ) = = null ) {
continue ;
}
if ( peanut ) {
if ( hasInvOnMerchant ( component . getProductId ( ) , InvStockRecord . MERCHANT_ZM ) ) {
return true ;
}
} else {
Long count = invStockRecordDao . selectCount (
new LambdaQueryWrapper < InvStockRecord > ( )
. eq ( InvStockRecord : : getProductId , component . getProductId ( ) )
) ;
if ( count ! = null & & count > 0 ) {
return true ;
}
}
}
return false ;
}
@Override
public boolean validateBookInvStock ( Integer productId , int quantity , BuyOrder buyOrder , ShopProduct product ) {
if ( ! hasInvStockRecord ( productId , buyOrder , product ) ) {
return true ;
}
int merchantId = resolveBookOrderMerchantId ( productId , buyOrder, product , quantity );
int merchantId = resolveBookOrderMerchantId ( buyOrder , product ) ;
if ( isSetBookProduct ( product ) ) {
List < Integer > bookIds = listBookIdsByProductId ( productId ) ;
try {
validateSetBookComponentStock ( bookIds , merchantId , quantity , productId ) ;
return true ;
} catch ( RuntimeException ex ) {
return false ;
}
}
int remain = sumRemainStockByMerchant ( productId , merchantId ) ;
return remain > 0 & & remain > = quantity ;
}
@@ -566,35 +657,16 @@ public class InventoryManagementServiceImpl extends ServiceImpl<InvStockRecordDa
return buyOrder ! = null & & Constants . PAYMENT_METHOD_VIRTUAL . equals ( buyOrder . getPaymentMethod ( ) ) ;
}
private int resolveBookOrderMerchantId ( Integer productId , BuyOrder buyOrder , ShopProduct product , int needQty ) {
/**
* 天医币固定众秒;其它支付严格按 payMerchant 映射,不因目标商户剩余为 0 而改扣另一商户。
* payMerchant=1 → 灵枢;否则 → 众秒。
*/
private int resolveBookOrderMerchantId ( BuyOrder buyOrder , ShopProduct product ) {
if ( isPeanutCoinPay ( buyOrder ) ) {
return InvStockRecord . MERCHANT_ZM ;
}
int payMerchant = product = = null | | product . getPayMerchant ( ) = = null ? 0 : product . getPayMerchant ( ) ;
return resolveInvMerchantId ( productId , payMerchant , needQty ) ;
}
/**
* 优先按 payMerchant 对应商户扣库存;该商户剩余不足时,回退到另一商户(兼容入库商户与 pay_merchant 不一致)。
*/
private int resolveInvMerchantId ( Integer productId , int payMerchant , int needQty ) {
int preferred = payMerchant = = 1 ? InvStockRecord . MERCHANT_LS : InvStockRecord . MERCHANT_ZM ;
int other = preferred = = InvStockRecord . MERCHANT_LS ? InvStockRecord . MERCHANT_ZM : InvStockRecord . MERCHANT_LS ;
int preferredRemain = sumRemainStockByMerchant ( productId , preferred ) ;
if ( preferredRemain > = needQty ) {
return preferred ;
}
int otherRemain = sumRemainStockByMerchant ( productId , other ) ;
if ( otherRemain > = needQty ) {
return other ;
}
if ( preferredRemain > 0 | | hasInvOnMerchant ( productId , preferred ) ) {
return preferred ;
}
if ( otherRemain > 0 | | hasInvOnMerchant ( productId , other ) ) {
return other ;
}
return preferred ;
return payMerchant = = 1 ? InvStockRecord . MERCHANT_LS : InvStockRecord . MERCHANT_ZM ;
}
private boolean hasInvOnMerchant ( Integer productId , int merchantId ) {
@@ -874,11 +946,39 @@ public class InventoryManagementServiceImpl extends ServiceImpl<InvStockRecordDa
Map < Integer , Integer > needQtyMap = new LinkedHashMap < > ( ) ;
Map < Integer , String > productNameMap = new HashMap < > ( ) ;
for ( BatchSaleRow row : rows ) {
needQtyMap . merge ( row . productId , row . quantity , Integer : : sum ) ;
if ( row . matchedName ! = null & & ! row . matchedName . isBlank ( ) ) {
productNameMap . putIfAbsent ( row . p roductId, row . matchedName ) ;
ShopProduct matched = shopProductDao . selectById ( row . productId ) ;
if ( isSetBookProduct ( matched ) ) {
List < Integer > bookIds = listBookIdsByP roductId( row . productId ) ;
if ( bookIds . isEmpty ( ) ) {
errors . add ( " 第 " + row . excelRowNum + " 行: 套书未在shop_product_book中关联图书, productId= " + row . productId ) ;
continue ;
}
for ( Integer bookId : bookIds ) {
ShopProduct component = findComponentProductByBookId ( bookId , row . productId ) ;
if ( component = = null | | component . getProductId ( ) = = null ) {
String bookName = resolveBookName ( bookId ) ;
String bookPart = bookName . isBlank ( )
? " 书籍ID[ " + bookId + " ] "
: " 《 " + bookName + " 》(书籍ID: " + bookId + " ) " ;
errors . add ( " 第 " + row . excelRowNum + " 行:套书拆分失败, " + bookPart + " 无只绑1本的单品商品 " ) ;
continue ;
}
needQtyMap . merge ( component . getProductId ( ) , row . quantity , Integer : : sum ) ;
String cName = component . getProductName ( ) ;
if ( cName ! = null & & ! cName . isBlank ( ) ) {
productNameMap . putIfAbsent ( component . getProductId ( ) , cName ) ;
}
}
} else {
needQtyMap . merge ( row . productId , row . quantity , Integer : : sum ) ;
if ( row . matchedName ! = null & & ! row . matchedName . isBlank ( ) ) {
productNameMap . putIfAbsent ( row . productId , row . matchedName ) ;
}
}
}
if ( ! errors . isEmpty ( ) ) {
throw new RuntimeException ( " 全部未入库: " + String . join ( " ; " , errors ) ) ;
}
for ( Map . Entry < Integer , Integer > entry : needQtyMap . entrySet ( ) ) {
int remain = sumRemainStockByMerchant ( entry . getKey ( ) , merchantId ) ;
if ( remain < entry . getValue ( ) ) {
@@ -892,8 +992,14 @@ public class InventoryManagementServiceImpl extends ServiceImpl<InvStockRecordDa
}
for ( BatchSaleRow row : rows ) {
List < CostSplit > splits = deductPurchaseStockFifo ( row . productId , merchantId , row . quantity ) ;
ShopProduct matched = shopProductDao . selectById ( row . productId ) ;
String remark = " 批量导入售出 orderSn= " + row . orderSn ;
if ( isSetBookProduct ( matched ) ) {
saleSetBook ( merchantId , row . quantity , matched , normalizedOutbound ,
null , remark , null , row . createTime , row . orderSn ) ;
continue ;
}
List < CostSplit > splits = deductPurchaseStockFifo ( row . productId , merchantId , row . quantity ) ;
for ( CostSplit split : splits ) {
insertSaleRecord ( row . productId , merchantId , normalizedOutbound ,
- split . quantity , split . unitCost , remark , null , row . createTime , row . orderSn , split . purchaseRecordId ) ;
@@ -1254,7 +1360,7 @@ public class InventoryManagementServiceImpl extends ServiceImpl<InvStockRecordDa
if ( component = = null | | component . getProductId ( ) = = null ) {
continue ;
}
// findComponentProductByBookId 已优先 只绑 1 本书;再兜底确认
// findComponentProductByBookId 已要求 只绑 1 本书;再兜底确认
if ( listBookIdsByProductId ( component . getProductId ( ) ) . size ( ) ! = 1 ) {
continue ;
}