现状:库存「状态」是显示时派生的(在售/预警/缺货 = 数量 vs 安全库存),数据库无字段;出库扣减到 0 的批次被软删除,从列表彻底消失;公开店铺页展示全部有库存商品(3841 件全裸奔)。
目标:状态落库为三态,门店可控地把商品挂上/撤下公开酒单,卖光的序列号留痕可查。
| 状态 | DB 值 | 语义 | 进入方式 | 公开酒单 |
|---|---|---|---|---|
| 库存 | stock | 在库、不对外展示(默认) | 入库审核默认 / switch 撤售 / 退单恢复 | 不显示 |
| 在售 | on_sale | 在库、公开酒单可见 | 抽屉 switch 手动挂售 | 显示 |
| 已售 | sold | 出库卖光,留痕台账 | 出库审核扣减到 0 自动置入(不再软删) | 不显示 |
流转:stock ⇄ on_sale(手动)→ sold(出库审核自动,不可手动进出);出库退单恢复数量时置回 stock(保守,需重新手动挂售)。盘点盘亏归零维持现状软删(灭失≠售出,不算已售)。
inventories 加列:status enum('stock','on_sale','sold') NOT NULL DEFAULT 'stock' + 索引 idx_inv_shop_status(shop_id, status)。schema.sql 与 model 同步,AutoMigrate 自动加列,存量行落默认值 stock——「现在所有状态改成库存」零迁移脚本达成。deleted_at 今后只表示「行不存在」(盘亏灭失/数据修正),「卖光」不再软删。| # | 位置 | 改动 |
|---|---|---|
| 1 | model/stock.go + schema/schema.sql | Inventory 加 Status 字段;docs/db-schema.html 同步 |
| 2 | service/stock.go:414(出库 FIFO) | 批次扣到 0:quantity=0 + status='sold',不再打 deleted_at;部分扣减不改状态 |
| 3 | service/stock.go(出库退单) | 恢复数量的行若为 sold → 置回 stock(并清 quantity 归还) |
| 4 | 新接口 | PUT /api/v1/inventory/:id/status,body {"status":"on_sale"|"stock"}——只收这两值(sold 拒 400);shop_id 归属校验;受 ReadOnly() 保护,operator 可用(店员挂酒单是日常操作) |
| 5 | 库存 List | 返回 status;新增 status= 筛选参数(可多值逗号分隔);默认排除已售(2026-07-07 用户拍板:仅点「已售」KPI 卡或状态筛选选已售时才显示),显式传 status=sold 才返回已售行 |
| 6 | 库存 Summary | sku_count / in_stock_qty / stock_value / 月初快照 一律排除 sold;新增 sold_count;shortage_count(qty≤0 未删行)语义被 sold 取代 → 保留字段但预期归零 |
| 7 | 公开接口 + SSR 店铺页 | ListShopProducts/queryShopProducts 的库存子查询加 status='on_sale'(qty>0 保留)——公开酒单只剩在售;商品单页不过滤(历史标签扫码永远可看,已售商品批次块自然消失) |
design/prototype/atoms.css 登记 .switch 组件(38×22 pill 轨道 + 圆点滑块,on=--primary、off=--border,禁用态 faint;全走 tokens)+ index.html 组件清单登记;mobile-atoms.css 如需尺寸变体一并登记。client/lib/widgets/ds/ds_switch.dart(颜色单源过 check_ds_code 闸)。inventory.html / m-inventory.html(同步态屏)状态列/徽章文案同步为三态。| # | 位置 | 改动 |
|---|---|---|
| 1 | models/inventory.dart | 加 status 解析(缺省 'stock' 容错旧响应) |
| 2 | 库存列表(桌面+移动) | 状态列/卡片徽章改三态显示;状态筛选改「全部/在售/库存/已售」走后端参数;预警/缺货退出状态列——低于安全库存仍由数量列染色(既有 qty.low)承担;KPI 第四卡「缺货预警」改为「已售」(主数 sold_count,点击筛选已售;副行保留「需补货 N 项」预警数) |
| 3 | product_editor_drawer.dart | 「状态」行 = 三态徽章 + 徽章后紧跟 DsSwitch(在售⇄库存);已售时只显示灰徽章无 switch;切换调 PUT 接口,成功即时更新徽章并刷新列表;readonly 用户 WriteGuard 禁用。桌面 drawer 与移动 sheet 同组件,一处生效 |
| 4 | _openEditor 调用 | 传入库存行 id 与 status(switch 操作对象=该 product 的库存行;序列号模型下 1 product≈1 行) |
| 5 | golden | 库存列表桌面/移动 + 抽屉相关 golden 重录(管理员形态) |