package service import ( "log" "gorm.io/gorm" "github.com/wangjia/jiu/backend/internal/model" ) // BackfillPricingColumns 2026-07 定价字段消歧的一次性数据迁移(幂等,可反复执行): // - stock_in_items / stock_out_items:unit_price→cost_price、total_price→cost_amount // - stock_in_orders:total_amount→cost_total;stock_out_orders:total_amount→sale_total // - stock_out_items.sale_amount = sale_price×quantity(待定价行保持 0) // - stock_out_orders.profit_total = Σ(sale_price>0 ? (sale_price-cost_price)×qty : 0) // // 只在新列为 0 且旧列非 0 时拷贝,不修改旧列(旧列观察一版后手动 DROP)。 // profit_total 以「为 0 且存在已定价明细」为待回填判据——利润恰为 0 的单重算一次 // 结果不变,幂等。全新安装(schema.sql 已无旧列)时整体跳过。 func BackfillPricingColumns(db *gorm.DB) { // 旧列存在性守卫:四张表的旧列是同批产生的,抽查一张即可 // (model 已无 UnitPrice 字段,HasColumn 会按原始列名探测) if !db.Migrator().HasColumn(&model.StockOutItem{}, "unit_price") { return } stmts := []string{ `UPDATE stock_in_items SET cost_price = unit_price WHERE cost_price = 0 AND unit_price <> 0`, `UPDATE stock_in_items SET cost_amount = total_price WHERE cost_amount = 0 AND total_price <> 0`, `UPDATE stock_in_orders SET cost_total = total_amount WHERE cost_total = 0 AND total_amount <> 0`, `UPDATE stock_out_items SET cost_price = unit_price WHERE cost_price = 0 AND unit_price <> 0`, `UPDATE stock_out_items SET cost_amount = total_price WHERE cost_amount = 0 AND total_price <> 0`, `UPDATE stock_out_items SET sale_amount = sale_price * quantity WHERE sale_amount = 0 AND sale_price > 0`, `UPDATE stock_out_orders SET sale_total = total_amount WHERE sale_total = 0 AND total_amount <> 0`, `UPDATE stock_out_orders SET profit_total = ( SELECT COALESCE(SUM(CASE WHEN i.sale_price > 0 THEN (i.sale_price - i.cost_price) * i.quantity ELSE 0 END), 0) FROM stock_out_items i WHERE i.order_id = stock_out_orders.id ) WHERE profit_total = 0 AND EXISTS ( SELECT 1 FROM stock_out_items i2 WHERE i2.order_id = stock_out_orders.id AND i2.sale_price > 0 )`, } for _, q := range stmts { res := db.Exec(q) if res.Error != nil { log.Printf("backfill pricing columns failed (%.60s...): %v", q, res.Error) } else if res.RowsAffected > 0 { log.Printf("backfill pricing: %d rows (%.60s...)", res.RowsAffected, q) } } }