库存平均单价计算逻辑说明.md
4.59 KB
库存平均单价计算逻辑说明
概述
采用加权平均成本法(Weighted Average Cost Method)来计算库存的平均单价,用于出库计价。
核心原则
- 入库时:根据当前平均单价和入库单价,计算新的平均单价
- 出库时:使用当前平均单价,出库后平均单价不变
- 平均单价维护:存储在
lq_product.F_AveragePrice字段中
计算公式
入库时计算新平均单价
新平均单价 = (当前平均单价 × 当前可用库存数量 + 入库单价 × 入库数量) / (当前可用库存数量 + 入库数量)
其中:
- 当前可用库存数量 = 总库存数量 - 已领取数量
- 入库单价:
- 采购入库:使用采购单价(
F_PurchaseUnitPrice) - 普通入库:使用产品价格(
F_Price)
- 采购入库:使用采购单价(
出库时使用平均单价
出库单价 = 产品平均单价(F_AveragePrice)
出库总金额 = 出库单价 × 出库数量
注意:出库后,平均单价不变(因为已经领取的库存已经按照当时的平均单价计价了)
示例说明
示例1:基本流程
初始状态:
- 商品A:当前平均单价 = 150
- 库存A:数量1,单价100
- 库存B:数量1,单价200
步骤1:领取1个
- 使用平均单价:150
- 领取后剩余:1个库存
- 平均单价不变:150
步骤2:再次入库1个,单价50
- 当前可用库存数量:1
- 当前库存总金额:150 × 1 = 150
- 入库金额:50 × 1 = 50
- 新平均单价 = (150 + 50) / (1 + 1) = 100
示例2:多次入库
初始状态:
- 商品B:当前平均单价 = 100,当前可用库存 = 10
步骤1:采购入库5个,单价120
- 当前库存总金额:100 × 10 = 1000
- 入库金额:120 × 5 = 600
- 新平均单价 = (1000 + 600) / (10 + 5) = 106.67
步骤2:领取3个
- 使用平均单价:106.67
- 领取后剩余:12个库存
- 平均单价不变:106.67
步骤3:再次采购入库8个,单价110
- 当前可用库存数量:12
- 当前库存总金额:106.67 × 12 = 1280.04
- 入库金额:110 × 8 = 880
- 新平均单价 = (1280.04 + 880) / (12 + 8) = 108.00
数据库字段
产品表(lq_product)
F_AveragePrice:平均单价(加权平均成本,用于出库计价)
库存表(lq_inventory)
F_PurchaseUnitPrice:采购单价(采购入库时使用)F_FinalAmount:产品最终金额(优先用于计算单价)F_Quantity:库存数量
库存使用记录表(lq_inventory_usage)
F_UnitPrice:使用时的单价(从产品平均单价获取)F_TotalAmount:使用总金额(单价 × 数量)
实现逻辑
1. 入库时(LqInventoryService.CreateAsync / UpdateAsync)
// 计算当前可用库存数量
var currentAvailableQuantity = totalInventoryQuantity - totalUsageQuantity;
// 确定入库单价
decimal incomingPrice = stockInType == 2 && purchaseUnitPrice.HasValue
? purchaseUnitPrice.Value // 采购入库
: product.Price; // 普通入库
// 计算新平均单价
if (currentAvailableQuantity <= 0)
{
newAveragePrice = incomingPrice; // 没有库存时,直接使用入库单价
}
else
{
var currentTotalAmount = product.AveragePrice * currentAvailableQuantity;
var incomingAmount = incomingPrice * incomingQuantity;
newAveragePrice = (currentTotalAmount + incomingAmount) / (currentAvailableQuantity + incomingQuantity);
}
// 更新产品平均单价
product.AveragePrice = newAveragePrice;
2. 出库时(LqInventoryUsageService.CreateAsync / ConfirmReceiveAsync)
// 使用产品的平均单价
var unitPrice = product.AveragePrice > 0 ? product.AveragePrice : product.Price;
var totalAmount = unitPrice * usageQuantity;
// 创建使用记录(平均单价不变)
usageEntity.UnitPrice = unitPrice;
usageEntity.TotalAmount = totalAmount;
初始化历史数据
对于已有库存的产品,根据当前库存计算初始平均单价:
平均单价 = SUM(库存金额) / SUM(库存数量)
其中,库存金额优先使用 F_FinalAmount,其次使用 F_PurchaseUnitPrice × F_Quantity。
注意事项
- 平均单价维护:每次入库时自动更新,出库时不变
- 可用库存计算:需要考虑已领取的数量
- 普通入库:如果没有采购单价,使用产品价格作为入库单价
- 历史数据初始化:首次添加字段时,需要根据现有库存计算初始平均单价
- 数据一致性:确保入库和出库操作在事务中执行,保证平均单价的一致性