删除(整篇已被代码淘汰 / 重复副本 / 与仓库无关):
- cloudflared_tunnel.txt:全仓无 cloudflared 配置,个人终端记录,无任何引用
- 履约配置/工程债-lewan拆分与短链.md:文中 services/kuaishou-cloud 与 kuaishou-cloud-executor 已删除
- 履约配置/快手Cloud领取mock.md:mock:claim / mock:feifei 与 dev-mock 卡片已移除(只剩 mock:open91)
- 行业电子凭证/解决方案/技术方案/1.基础技术.md(+ 其孤立 image.png):0.基础技术.md 的 75 行截断副本
- 寄卖库存功能设计与实施方案.md:手工入库已 409 停用、收集链接表已随 079 删除、统计看板未实现
- 服务器图片迁移到阿里云OSS.md:MinIO→OSS 迁移已完成(生产 STORAGE_MODE=oss)
- pgBackRest备份方案分析.md:全仓无 pgBackRest 落地痕迹,文档自述暂缓实施
- finance-implementation-plan.md:财务模块已落地(072 迁移 / RBAC / 页面接口),已实现部分与代码重复
(未落地的二期三期路线图可从本提交的历史版本取回)
改写为与代码一致(已下线通道不再当作现行能力):
- 履约配置/多发货平台与电子凭证整体链路.md:kuaishou-cloud / kuaishou-feifei 标注为已下线 legacy stub,
现行自动通道 affiliate-dash、人工 manual_dispatch;核销时机与券表按实现校正
- 履约配置/{UID领取与旧单兼容, open91请求, TypeScript类型收紧}.md:lewan/feifei/cloudtentacles 表述改为
现行 affiliate-dash 链路;normalize 具名类型 KuaishouCloudFlow/FeifeiFlow → AffiliateDashFlow
- affiliate_dash_发货平台/affiliate-dash对接.md:§13/§14/§19/§21/§24/§25 的已删文件与已下线通道引用校正,
§21/§22 加「当时快照 / 落地后现状」横幅,回调去重表按 013_affiliate_dash_webhook_events.sql 改写
- 91卡券/{3.异步卡密下单, 5.当前项目对接配置, 6.开发设计}.md:删掉不存在的后台入口、
cloudtentacles/kuaishou_ct_assisted 依赖、cardsEncoding 与 .js 代码落点校正
- 行业电子凭证/技术方案.md:checklist 指向不存在的 测试用例.md → gen-test-cases.ts + 5.测试指南.md
- 履约配置/cloudtentacles发货平台.md:补「本仓库未接入该通道」说明(保持外部参考)
- 部署启动与数据库重建.md:补齐生产必需变量 APP_DOMAIN / CORS_ALLOWED_ORIGINS / STORAGE_MODE / STORAGE_OSS_*
其它:
- README.md:迁移序号范围 002~009 → 002~080
- 寄卖系统迁移079上库前检查.sql:第 2 段注释按批次 Y 的自动去重更新;新增 2.1「重复退款风险」只读排查
(已在一次性 PostgreSQL 16 上跑通 001→080 迁移:整份脚本 exit=0,脏数据下 2/2.1 均按预期报警)
- 寄卖系统优化方案.md:删掉链路图里已下线的「客服手工录入」,去掉指向已删设计稿的引用
192 lines
7.9 KiB
SQL
192 lines
7.9 KiB
SQL
-- 迁移 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 行。注意 079 自身会先去重再建索引——每组(打手+提报单)保留最早一条冻结流水,
|
||
-- 多余行改 payload 标记 kind=consignment_publish_superseded(移出押金口径与索引范围,
|
||
-- 原行留审计)并按 LEAST(多冻总额, 冻结池实有) 退还押金、写 consignment_publish_dedup_refund
|
||
-- 修正流水。所以有行也能建起索引;但若该提报单的押金此前已被释放/没收过,
|
||
-- 自动退款会重复退(见 2.1),必须先人工确认。
|
||
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;
|
||
|
||
-- 2.1(只读)重复退款风险:同提报单有多条冻结流水,且该提报单的押金已经被释放/没收过。
|
||
-- 判据:already_settled_fen > 0 时,079 的自动退款会把「已经退过的钱」再退一次——
|
||
-- 钱从同一打手其它提报单的冻结额里出,之后那张单释放/没收会因为
|
||
-- frozen < outstanding 抛 consignment_deposit_balance_inconsistent(接口 500)。
|
||
-- 命中就必须先人工处理,不要直接上库。safe_refund_should_be_fen = 应当退还的金额。
|
||
-- 期望:0 行。
|
||
WITH fr AS (
|
||
SELECT worker_id, payload_json ->> 'consignmentSubmissionId' AS sub, id, ABS(amount) AS amt
|
||
FROM worker_wallet_ledgers
|
||
WHERE ledger_type = 'deposit_freeze'
|
||
AND COALESCE(payload_json ->> 'kind', '') = 'consignment_publish'
|
||
AND COALESCE(payload_json ->> 'consignmentSubmissionId', '') <> ''
|
||
),
|
||
g AS (
|
||
SELECT
|
||
worker_id,
|
||
sub,
|
||
COUNT(*) AS freeze_rows,
|
||
SUM(amt) AS freeze_total_fen,
|
||
(ARRAY_AGG(amt ORDER BY id ASC))[1] AS kept_fen
|
||
FROM fr
|
||
GROUP BY 1, 2
|
||
),
|
||
s AS (
|
||
SELECT
|
||
worker_id,
|
||
payload_json ->> 'consignmentSubmissionId' AS sub,
|
||
COALESCE(SUM(CASE WHEN ledger_type IN ('deposit_release', 'deposit_deduction')
|
||
THEN ABS(amount) ELSE 0 END), 0) AS settled_fen
|
||
FROM worker_wallet_ledgers
|
||
WHERE COALESCE(payload_json ->> 'kind', '') = 'consignment_publish'
|
||
AND COALESCE(payload_json ->> 'consignmentSubmissionId', '') <> ''
|
||
GROUP BY 1, 2
|
||
)
|
||
SELECT
|
||
g.worker_id,
|
||
g.sub AS submission_id,
|
||
g.freeze_rows,
|
||
g.freeze_total_fen - g.kept_fen AS dup_fen,
|
||
COALESCE(s.settled_fen, 0) AS already_settled_fen,
|
||
COALESCE(w.frozen_deposit_amount, 0) AS wallet_frozen_fen,
|
||
LEAST(g.freeze_total_fen - g.kept_fen, COALESCE(w.frozen_deposit_amount, 0))
|
||
AS migration_will_refund_fen,
|
||
GREATEST(0, (g.freeze_total_fen - COALESCE(s.settled_fen, 0)) - g.kept_fen)
|
||
AS safe_refund_should_be_fen
|
||
FROM g
|
||
LEFT JOIN s ON s.worker_id = g.worker_id AND s.sub = g.sub
|
||
LEFT JOIN worker_wallets w ON w.worker_id = g.worker_id
|
||
WHERE g.freeze_rows > 1
|
||
AND COALESCE(s.settled_fen, 0) > 0
|
||
ORDER BY 1, 2;
|
||
|
||
-- 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;
|