Files
order_site/docs/寄卖系统迁移079上库前检查.sql
T
yml2213 5d11bf2012 fix(consignment): 补齐指派补偿与规格复检,封闭寄卖资金/货物不一致窗口
- 指派失败改为完整补偿:取消指派(解冻打手押金 + 工单退回大厅 + 解绑现货)→ 兜底释放占用 →
  摘除工单寄售标记。此前只把现货放回在库池,一旦"指派已提交、写 material 失败",工单会停在
  in_progress + 押金冻结却不带寄售记录,现货还回到可匹配池,同一件货会被第二张单占用。
- 电子凭证核销失败写 consignment_fulfill_voucher_consume_failed 事件,前端按 voucherConsume.ok
  弹警告并提示人工核销,不再无条件报成功(核销走快手外部接口,无法与数据库事务合并回滚)。
- 匹配规格改为 match/mismatch/unknown 三态,钻级兜底由 || 1 改 || 0:订单规格信息不全一律不进
  "精确匹配",降级 partial 并在原因里列出缺失字段,消除"任意现货都 100 分精确匹配"的错发根因。
- 履约与指派在占库前做服务端规格复检:冲突 409 consignment_spec_mismatch;非 exact 必须显式
  传 allowPartial(前端在部分匹配候选上先危险确认),高配充低配保留但不可误触。
- 人工解绑守卫由"状态黑名单"收窄为只拦交付中三态(与撤销白名单对齐),修复
  "工单未开始 + 现货仍绑定"没有任何人工出口的问题。
- 新增 detachConsignmentMaterialFromWorkOrderWithClient,解绑回库/人工退回复库/作废同步摘掉
  工单寄售标记,消除"已回库却仍显示寄卖履约"的陈旧痕迹。
- 回归测试新增 8 例(后端 410 例 / 407 通过),附迁移 079 上库前检查脚本。
2026-09-16 20:12:14 +08:00

136 lines
5.4 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- 迁移 079 上库前 / 上库后检查脚本(只读,可直接在生产库执行)
--
-- 迁移文件:apps/backend/src/db/migrations/079_drop_consignment_collect_links.sql
-- 已在全新空库验证:001 → 079 可一次性跑通(79 条迁移全部记录在 schema_migrations)。
-- 生产库上库前请先跑完「上库前」四段检查。
-- ============================ 上库前 ============================
-- 1. 同一张工单被多件现货同时绑定?
-- 会让唯一索引 uniq_consignment_inventories_bound_work_order 创建失败。
-- 迁移自带清理(保留工单 material 里记录的那一件,其余解绑回库),
-- 但有数据时请先确认"保留哪一件"与工单 material.consignment.inventoryId 一致。
-- 期望:0 行。
SELECT
ci.bound_work_order_id,
COUNT(*) AS bound_rows,
ARRAY_AGG(ci.id ORDER BY ci.id) AS inventory_ids,
MAX(NULLIF(wo.material_json -> 'consignment' ->> 'inventoryId', '')) AS material_inventory_id
FROM consignment_inventories ci
JOIN work_orders wo ON wo.id = ci.bound_work_order_id
WHERE ci.bound_work_order_id IS NOT NULL
AND ci.status = 'consumed'
GROUP BY ci.bound_work_order_id
HAVING COUNT(*) > 1;
-- 2. 同一提报单重复冻结了发布押金?
-- 会让唯一索引 uniq_worker_wallet_ledgers_consignment_publish_freeze 创建失败。
-- 期望:0 行。若有行,需人工决定保留哪笔冻结(多冻的部分按 deposit_release 冲正)。
SELECT
payload_json ->> 'consignmentSubmissionId' AS submission_id,
COUNT(*) AS freeze_rows,
SUM(ABS(amount)) AS frozen_fen
FROM worker_wallet_ledgers
WHERE ledger_type = 'deposit_freeze'
AND payload_json ->> 'kind' = 'consignment_publish'
GROUP BY 1
HAVING COUNT(*) > 1;
-- 3. 待删除对象的影响面(收集链接渠道下线)。
-- 用 DO 块 + 动态 SQL,保证"表/列已被删掉"时脚本也能跑(否则会直接报错中断)。
DO $$
DECLARE
n bigint;
BEGIN
IF to_regclass('public.consignment_collect_links') IS NOT NULL THEN
EXECUTE 'SELECT COUNT(*) FROM consignment_collect_links' INTO n;
RAISE NOTICE '[3.1] 收集链接表仍存在,共 % 行;删除后不可恢复', n;
ELSE
RAISE NOTICE '[3.1] 收集链接表不存在(079 已执行或从未创建)';
END IF;
IF EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = 'consignment_submissions' AND column_name = 'link_id'
) THEN
EXECUTE 'SELECT COUNT(*) FROM consignment_submissions WHERE link_id IS NOT NULL' INTO n;
RAISE NOTICE '[3.2] 提报单 link_id 仍存在,共 % 行有引用;删除后不可恢复', n;
ELSE
RAISE NOTICE '[3.2] 提报单 link_id 不存在(079 已执行或从未创建)';
END IF;
END
$$;
-- 3.3 来源枚举分布(迁移会把 collection_link 归并为 worker_portal)
SELECT source_type, COUNT(*) FROM consignment_inventories GROUP BY source_type ORDER BY 1;
-- 4. 历史遗留的"已出库但无工单绑定"现货(079 之前 worker_deposit 占库不写绑定)
-- 这些行不会随撤单自动解绑,需要运营在寄卖仓库手动【退回复库】。
SELECT COUNT(*) AS legacy_consumed_without_binding
FROM consignment_inventories
WHERE status = 'consumed' AND bound_work_order_id IS NULL;
-- ============================ 上库后 ============================
-- 5. 结构校验:新列 / 新索引 / 枚举约束是否就位
SELECT
EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = 'consignment_inventories' AND column_name = 'assigned_worker_id'
) AS has_assigned_worker_id,
EXISTS (
SELECT 1 FROM pg_indexes WHERE indexname = 'uniq_consignment_inventories_bound_work_order'
) AS has_bound_work_order_unique,
EXISTS (
SELECT 1 FROM pg_indexes
WHERE indexname = 'uniq_worker_wallet_ledgers_consignment_publish_freeze'
) AS has_ledger_freeze_unique,
EXISTS (
SELECT 1 FROM information_schema.tables WHERE table_name = 'consignment_collect_links'
) AS collect_links_table_still_exists,
EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = 'consignment_submissions' AND column_name = 'link_id'
) AS submissions_link_id_still_exists;
SELECT pg_get_constraintdef(oid) AS source_type_check
FROM pg_constraint
WHERE conname = 'consignment_inventories_source_type_check';
-- 6. 绑定一致性总览(上库后运营巡检用)
SELECT
ci.id,
ci.inventory_no,
ci.status,
ci.bound_work_order_id,
wo.status AS work_order_status,
ci.allocation_status,
ci.assigned_worker_id,
ci.worker_id AS seller_worker_id
FROM consignment_inventories ci
LEFT JOIN work_orders wo ON wo.id = ci.bound_work_order_id
WHERE ci.status = 'consumed'
ORDER BY ci.updated_at DESC
LIMIT 50;
-- 7. 发布押金挂账巡检:台账未释放金额是否超过钱包冻结额(按打手)
WITH ledger AS (
SELECT
worker_id,
COALESCE(SUM(CASE WHEN ledger_type = 'deposit_freeze' THEN ABS(amount) ELSE 0 END), 0)
- COALESCE(SUM(CASE WHEN ledger_type = 'deposit_release' THEN ABS(amount) ELSE 0 END), 0)
- COALESCE(SUM(CASE WHEN ledger_type = 'deposit_deduction' THEN ABS(amount) ELSE 0 END), 0)
AS outstanding_fen
FROM worker_wallet_ledgers
WHERE payload_json ->> 'kind' = 'consignment_publish'
GROUP BY worker_id
)
SELECT
l.worker_id,
l.outstanding_fen,
w.frozen_deposit_amount AS wallet_frozen_fen
FROM ledger l
JOIN worker_wallets w ON w.worker_id = l.worker_id
WHERE l.outstanding_fen > 0
AND l.outstanding_fen > w.frozen_deposit_amount;