feat(backend): 库存三态落库(stock/on_sale/sold)——挂售可控 + 卖光留痕

- inventories 加 status 枚举列(默认 stock,AutoMigrate 存量即全部「库存」)+ 索引
- 出库审核扣光置 sold 不再软删(留痕台账);退单恢复行置回 stock;盘亏仍软删
- 新接口 PUT /inventory/:id/status(仅收 stock/on_sale,已售行拒改,租户校验)
- List 默认排除已售(显式 status=sold 才显示)+ status 多值筛选
- Summary:SKU/货值/数量排除已售,新增 sold_count
- 公开店铺页/API 只列 on_sale——酒单从全量裸奔改为人工精选
- 测试:卖光置售/部分不改/退单回库/接口边界/跨租户/汇总口径 8 用例
- 设计方案 docs/design/inventory-sale-status.html + db-schema/CLAUDE.md 同步

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-07 13:35:03 +08:00
parent b0b38db39f
commit 73955a139c
15 changed files with 386 additions and 9 deletions
+2 -1
View File
@@ -411,7 +411,8 @@ func (s *StockService) ApproveStockOut(shopID, orderID, reviewerID uint64) error
b := &batches[i]
if b.Quantity <= remaining {
remaining -= b.Quantity
tx.Model(b).Updates(map[string]interface{}{"quantity": 0, "deleted_at": now})
// 卖光的批次置「已售」留痕(2026-07-07 三态改造:不再软删)
tx.Model(b).Updates(map[string]interface{}{"quantity": 0, "status": "sold"})
} else {
tx.Model(b).Update("quantity", gorm.Expr("quantity - ?", remaining))
remaining = 0