Files
qipai/docs/devlogs/2026-08-11-M09-D1-商品目录与库存底座.md
T

3.6 KiB
Raw Blame History

2026-08-11 M09-D1 商品目录与库存底座

工程结果

  • 工程状态:当前工作树已完成,待以 feat(M09-D1): 完成商品目录与库存流水底座 中文标题提交并取得 SHA。
  • 新增分类、商品、SKU、门店上架、门店销售设置、每周最多 8 段且支持跨日的营业时段;分类/商品/SKU 支持软删除后的代码或条码复用,写操作统一使用 expectedVersion 乐观锁。
  • 新增 TRACKED / UNLIMITED 库存策略、可用/锁定/损耗三类数量,以及入库、调整、盘点、损耗、批量锁定、释放和扣减服务;批量操作同事务完成,任何一个 SKU 失败均整体回滚。
  • 库存请求以租户、门店和大小写敏感 requestId 建立全局幂等记录;请求指纹不一致明确拒绝,锁定归属按业务类型和业务号核对,重复释放、跨订单释放和超额扣减不会改动库存。
  • 每次库存变动写入带 version_after 的不可变流水,数据库双触发器拒绝 UPDATE/DELETE;流水增量与库存最终值可对账,版本唯一键防止遗漏或重复版本。
  • 商品/库存路由接入 Fastify,补 product.catalog.read/writeinventory.read/adjust capability、角色默认授权、服务端菜单和租户/门店范围校验;STAFF 只读、STORE_ADMIN 授权门店、TENANT_ADMIN 与 PLATFORM_ADMIN 边界均有测试。
  • 迁移 runner 改为按单个迁移 marker/checksum 只执行 pending 文件,旧库可直接增量应用 M09-D1interrupted up/down DDL 后可在同一库原地重试,不需要清空或重建。
  • up/verify/down 在同一专用连接上持有按数据库名派生的 MySQL 命名锁,两个发布进程会串行执行;不同构建必须等前一进程完成后再校验 marker/checksum,避免交错 DDL 形成混合 schema。
  • 迁移包含触发器时,runner 在执行任何触发器 DDL 前检查生产前置;binlog 开启时必须启用 log_bin_trust_function_creators=1 并使用独立迁移身份,否则在建表前拒绝执行。

数据库结果

2026081107_m09d1_product_inventory_foundation 新增 9 张表:

  1. qipai_product_categories
  2. qipai_products
  3. qipai_product_skus
  4. qipai_product_store_listings
  5. qipai_product_store_settings
  6. qipai_product_store_hours
  7. qipai_product_inventory
  8. qipai_product_inventory_requests
  9. qipai_product_inventory_ledger

验证证据

  • node scripts/check-m09-d1-product-inventory.mjs:PASS,静态门禁确认迁移、路由、RBAC、服务、真实 MySQL 断言和 Windows/WSL 门禁均已接线。
  • 后端 npm run build、后端全量 npm testPASS。
  • 管理端 npm run buildnpm testPASS。
  • WSL 原生临时副本 + MySQL 8.4.10:完成 up → verify → down → up → verify179 条 up、141 条 verify、171 条 down;双连接迁移锁、interrupted up/down DDL 原地重跑、增量 marker/checksum、触发器生产前置和 cleanup probe 均 PASS。
  • 真实 MySQL 业务用例覆盖门店唯一性、跨日时段、商品/SKU 版本冲突、并发锁定单赢家、重复 requestId 重放与冲突、批量原子回滚、锁定/释放/扣减、损耗/盘点、负库存拒绝、流水对账与不可变触发器。
  • Windows 汇总门禁在全部 M09-D1 与 V5.7 文件显式暂存后执行最终复跑;不得将提交前的未跟踪完整性提示记为功能失败。

阶段结论

M09-D1=DONE。唯一执行游标进入 M09-D2,下一阶段建立商品订单、订单项快照、支付衔接与库存占用生命周期。生产触发器前置属于部署强制条件,不是可绕过的外部阻塞。