feat(backend): 出入库定价字段消歧 + 总利润落库 + 成本仅管理员可见

- 字段重命名(旧列弃用保留,启动幂等回填 BackfillPricingColumns):
  入库 unit_price/total_price/total_amount → cost_price/cost_amount/cost_total;
  出库同前缀 + 新增 sale_amount(售价小计)/ sale_total(应收)/ profit_total(总利润)
- 建单落三值;确认售价联动重算 sale_amount/sale_total/profit_total;
  确认进价回填成本后联动重算受影响出库单利润(recalcStockOutProfit)
- 出库 List/Get 对 operator/readonly 抹零成本与利润(stripStockOutCost 服务端兜底)
- 兼容一版:Create/Update 接受旧 key unit_price 回落(v1.0.87 及之前客户端)
- SUM 聚合/价格趋势/导入/种子工具同步切新列;测试全量改名 + 6 个新回归

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JJ1g8XV1YhhmHRzhwWEW7o
This commit is contained in:
wangjia
2026-07-03 12:44:22 +08:00
parent 607b8aa763
commit 4fd0bb8b83
24 changed files with 601 additions and 135 deletions
+3 -3
View File
@@ -137,7 +137,7 @@ func (h *InventoryHandler) List(c *gin.Context) {
COALESCE(NULLIF(p.spec,''), NULLIF(sii.spec,''), inv.spec, '') AS spec,
COALESCE(NULLIF(p.unit,''), inv.unit, '') AS unit,
COALESCE(NULLIF(w.name,''), inv.warehouse_name, '') AS warehouse_name,
COALESCE(sii.unit_price, inv.unit_price, p.purchase_price) AS unit_price,
COALESCE(sii.cost_price, inv.unit_price, p.purchase_price) AS unit_price,
p.sale_price AS sale_price,
COALESCE(DATE(sii.production_date), DATE(inv.production_date)) AS production_date,
COALESCE(NULLIF(sii.batch_no,''), inv.batch_no, '') AS batch_no,
@@ -187,13 +187,13 @@ func (h *InventoryHandler) Summary(c *gin.Context) {
const sql = `
SELECT
COUNT(*) AS sku_count,
COALESCE(SUM(inv.quantity * COALESCE(sii.unit_price, inv.unit_price, p.purchase_price)), 0) AS stock_value,
COALESCE(SUM(inv.quantity * COALESCE(sii.cost_price, inv.unit_price, p.purchase_price)), 0) AS stock_value,
COALESCE(SUM(inv.quantity), 0) AS in_stock_qty,
COALESCE(SUM(CASE WHEN inv.quantity <= 0 THEN 1 ELSE 0 END), 0) AS shortage_count,
COALESCE(SUM(CASE WHEN inv.quantity > 0 AND p.min_stock IS NOT NULL AND inv.quantity < p.min_stock THEN 1 ELSE 0 END), 0) AS warning_count,
COALESCE(SUM(CASE WHEN inv.created_at < ? THEN 1 ELSE 0 END), 0) AS last_month_sku,
COALESCE(SUM(CASE WHEN inv.created_at < ? THEN inv.quantity - COALESCE(lg.net, 0) ELSE 0 END), 0) AS last_month_qty,
COALESCE(SUM(CASE WHEN inv.created_at < ? THEN (inv.quantity - COALESCE(lg.net, 0)) * COALESCE(sii.unit_price, inv.unit_price, p.purchase_price) ELSE 0 END), 0) AS last_month_value
COALESCE(SUM(CASE WHEN inv.created_at < ? THEN (inv.quantity - COALESCE(lg.net, 0)) * COALESCE(sii.cost_price, inv.unit_price, p.purchase_price) ELSE 0 END), 0) AS last_month_value
FROM inventories inv
LEFT JOIN stock_in_items sii ON sii.id = inv.stock_in_item_id
LEFT JOIN products p ON p.id = inv.product_id AND p.deleted_at IS NULL