fix(backend): 历史导入出库明细价格错列——售价误落成本列,新增修复工具
Design Source Checks / design-source (push) Successful in 39s

根因:旧系统出库明细「单价/金额」是售价口径(应收侧),import-history 误落
cost_price/cost_amount,sale_price 留 0(整单显示待定价);单头 sale_total
却按售价口径正确落库,明细与单头矛盾。实证:ZXZ027628 出库"成本"14300=售价,
真实进价 13600 在库存/入库侧。

- import-history:出库明细「单价/金额」改落 sale_price/sale_amount(成本留 0 待回查)
- 新增 cmd/fix-history-prices 一次性修复线上数据:售价归位 + 按商品编号
  回查真实进价(①入库明细 ②库存快照 ③商品进价)+ profit_total 同口径重算;
  sale_total 不动(应收不变);默认 dry-run,--apply 落库,幂等可重跑
- 测试:四种成本来源/dry-run 回滚/幂等/非占位明细不波及/利润应收口径

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
wangjia
2026-07-10 16:51:51 +08:00
parent 39a2f14e0b
commit e19c498dba
3 changed files with 473 additions and 3 deletions
+7 -3
View File
@@ -529,13 +529,17 @@ func (ic *importCtx) writeOrder(
TenantBase: model.TenantBase{ShopID: ic.shopID},
OrderNo: orderNo, Type: orderType, WarehouseID: ic.whID,
PartnerID: partnerID, OperatorID: operatorID, CreatorID: creatorID,
// 忠实导入:源「金额」合计沿旧行为落应收合计(sale_price=0 待定价
// 忠实导入:源「金额」合计是售价口径,落应收合计(与明细 sale_* 同口径
ReviewerID: reviewerID, Status: status, OrderDate: orderDate, SaleTotal: totalAmount,
}
if err := tx.Create(&o).Error; err != nil {
return err
}
for _, dr := range details {
// 源出库明细「单价/金额」是售价口径(卖给客户的价,应收侧),落 sale 列;
// 真实成本导入时不可知,留 0(成本待定),事后用 cmd/fix-history-prices
// 按商品编号回查入库价/库存价/商品进价回填。
// 2026-07-10 修正:此前误落 cost_price/cost_amount,线上数据已用同工具修复)
it := model.StockOutItem{
OrderID: o.ID, ShopID: ic.shopID, ProductID: ic.placeholderProductID,
ProductCode: get(dr, dCols, "商品编号"),
@@ -543,8 +547,8 @@ func (ic *importCtx) writeOrder(
Series: get(dr, dCols, "系列"),
Spec: get(dr, dCols, "规格"),
Quantity: parseFloatLoose(get(dr, dCols, "数量")),
CostPrice: parseFloatLoose(get(dr, dCols, "单价")),
CostAmount: parseFloatLoose(get(dr, dCols, "金额")),
SalePrice: parseFloatLoose(get(dr, dCols, "单价")),
SaleAmount: parseFloatLoose(get(dr, dCols, "金额")),
BatchNo: get(dr, dCols, "批次号"),
}
it.ProductionDate = parseDatePtr(get(dr, dCols, "生产日期"))