fix(consignment): 下线 H5 收集链接渠道并封闭寄卖履约状态机
下线定向收集链接(H5 填报)整条线,提报统一走接单平台打手端: - 删除前端 ConsignmentCollectPage、consignment-public 服务与 /consignment-collect/:token 路由 - 删除后端公开路由 routes/consignment.ts、consignment-public-service 与管理端 /consignment/links 三接口 - 迁移 079 删表 consignment_collect_links、删列 consignment_submissions.link_id, source_type 的 collection_link 归并为 worker_portal 并替换 CHECK 修复手工入库/编辑的凭据与截图静默丢失:后端统一按 credentialsJson ?? credentials、 screenshotsJson ?? screenshots 读取(入库/编辑/审核入库三个入口)。 按"已验收一律禁止撤销"封闭状态机: - 撤销寄售履约加状态白名单(in_progress|pending_acceptance|problem)+ 事务内 FOR UPDATE 锁单 + UPDATE 带 status 条件(0 行 409)+ 原因必填 + 清空指派/时限/验收草稿痕迹 - 库存改状态一律带条件:撤销要求 bound_work_order_id 命中本工单;作废/回库要求未被 进行中工单占用(被挡时提示具体工单号);079 加部分唯一索引并清理历史重复绑定 - 工单终止统一解绑回库:打手撤单/取消指派/退回大厅/撤单/打手退单申请/超时处置接入 releaseConsignmentInventoryBindingForWorkOrderWithClient(售后不改工单状态,无需接入) - 回库路径保留运营的 allow_matching 开关设置(不再强制开启),前端文案同步更正 顺带修掉资金与归属的同源缺陷: - 押金归属与重冻金额改取不可变的冻结核销行,审核改派不再"退给错人/向错人扣款" - 新增 assigned_worker_id 拆开"卖家"与"被指派履约人",占库不再覆盖卖家 - PUT /inventories/:id 禁止直接改 status;发布接口补 requireActiveWorker - 押金冻结/释放后补推钱包实时事件;迁移 079 给发布冻结加台账幂等唯一索引 验证:后端 401 测试/398 通过/3 skip(新增 5 例回归),前端 16 通过; 两侧 typecheck、lint:check、format:check 与 check:sql、build 全绿。 迁移 079 未经真实数据库执行(本环境无 Postgres),上库前请先 dry-run。
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
-- 079_drop_consignment_collect_links.sql —— 下线「定向收集链接 / H5 填报」渠道
|
||||
--
|
||||
-- 背景:寄卖提报统一走接单平台(打手端提报道),对外收集链接这条线整条移除:
|
||||
-- - 前端:ConsignmentCollectPage、services/consignment-public.ts、/consignment-collect/:token 路由
|
||||
-- - 后端:routes/consignment.ts(公开 link/submit/upload)、consignment-public-service.ts、
|
||||
-- 管理端 /consignment/links 三个接口
|
||||
-- - 数据:consignment_collect_links 表、consignment_submissions.link_id 列
|
||||
-- 历史数据不做兼容处理(测试阶段),source_type 的 collection_link 归并为 worker_portal。
|
||||
|
||||
-- 1) 提报单去掉链接外键列(依赖该列的索引随之删除)
|
||||
ALTER TABLE consignment_submissions
|
||||
DROP COLUMN IF EXISTS link_id;
|
||||
|
||||
-- 2) 收集链接主表下线
|
||||
DROP TABLE IF EXISTS consignment_collect_links;
|
||||
|
||||
-- 3) 库存来源枚举:collection_link -> worker_portal
|
||||
-- 顺序很重要:旧 CHECK 只允许 ('manual','collection_link','recycle'),
|
||||
-- 必须先摘掉旧约束再回填,否则 'worker_portal' 会被旧约束拒绝,整条迁移失败回滚。
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (
|
||||
SELECT 1
|
||||
FROM pg_constraint
|
||||
WHERE conname = 'consignment_inventories_source_type_check'
|
||||
AND conrelid = 'consignment_inventories'::regclass
|
||||
) THEN
|
||||
ALTER TABLE consignment_inventories
|
||||
DROP CONSTRAINT consignment_inventories_source_type_check;
|
||||
END IF;
|
||||
END
|
||||
$$;
|
||||
|
||||
UPDATE consignment_inventories
|
||||
SET source_type = 'worker_portal', updated_at = NOW()
|
||||
WHERE source_type = 'collection_link';
|
||||
|
||||
ALTER TABLE consignment_inventories
|
||||
ADD CONSTRAINT consignment_inventories_source_type_check
|
||||
CHECK (source_type IN ('manual', 'worker_portal', 'recycle'));
|
||||
|
||||
COMMENT ON COLUMN consignment_inventories.source_type IS
|
||||
'入库来源:manual 手工录入 / worker_portal 接单平台提报入库 / recycle 回收';
|
||||
|
||||
COMMENT ON TABLE consignment_submissions IS '打手通过接单平台提交的寄卖提报审核单';
|
||||
|
||||
-- 4) 区分"卖家"与"被指派的履约打手":worker_id 语义固定为卖家,指派结果单独存列,
|
||||
-- 避免占库时覆盖卖家导致「我的寄卖」丢件。
|
||||
ALTER TABLE consignment_inventories
|
||||
ADD COLUMN IF NOT EXISTS assigned_worker_id BIGINT REFERENCES worker_users(id) ON DELETE SET NULL;
|
||||
|
||||
COMMENT ON COLUMN consignment_inventories.worker_id IS '寄卖卖家(提报人)打手ID,入库后不再变更';
|
||||
COMMENT ON COLUMN consignment_inventories.assigned_worker_id IS
|
||||
'被指派执行本次履约的打手ID(仅押金履约模式占用,回库/撤单时清空)';
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_consignment_inventories_assigned_worker_id
|
||||
ON consignment_inventories(assigned_worker_id)
|
||||
WHERE assigned_worker_id IS NOT NULL;
|
||||
|
||||
-- 一件现货同一时刻最多绑定一张工单:防止同一件现货被多张工单占用。
|
||||
-- 先清理历史脏数据:同一工单被多件现货同时绑定时,保留工单 material 里记录的那一件,
|
||||
-- 其余解绑回库(它们是此前"回库后又被另一张单占用"缺陷的产物)。
|
||||
WITH ranked AS (
|
||||
SELECT
|
||||
ci.id,
|
||||
ci.bound_work_order_id,
|
||||
ROW_NUMBER() OVER (
|
||||
PARTITION BY ci.bound_work_order_id
|
||||
ORDER BY
|
||||
(ci.id = COALESCE(NULLIF(wo.material_json -> 'consignment' ->> 'inventoryId', '')::bigint, 0)) DESC,
|
||||
ci.id DESC
|
||||
) AS rn
|
||||
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'
|
||||
)
|
||||
UPDATE consignment_inventories ci
|
||||
SET
|
||||
status = 'in_stock',
|
||||
allocation_status = '待安排',
|
||||
bound_order_id = NULL,
|
||||
bound_work_order_id = NULL,
|
||||
bound_platform_order_id = '',
|
||||
shop_name = '',
|
||||
consumed_at = NULL,
|
||||
remark = remark || ' [重复绑定自动解绑: 工单 ' || ranked.bound_work_order_id || ']',
|
||||
updated_at = NOW()
|
||||
FROM ranked
|
||||
WHERE ci.id = ranked.id
|
||||
AND ranked.rn > 1;
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS uniq_consignment_inventories_bound_work_order
|
||||
ON consignment_inventories(bound_work_order_id)
|
||||
WHERE bound_work_order_id IS NOT NULL AND status = 'consumed';
|
||||
|
||||
-- 5) 寄卖发布押金的冻结核销行幂等键:同一提报单只能有一笔发布冻结,
|
||||
-- 防止未来任何绕过"先读台账再冻结"约定的调用方重复扣款。
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS uniq_worker_wallet_ledgers_consignment_publish_freeze
|
||||
ON worker_wallet_ledgers ((payload_json ->> 'consignmentSubmissionId'))
|
||||
WHERE ledger_type = 'deposit_freeze'
|
||||
AND payload_json ->> 'kind' = 'consignment_publish';
|
||||
Reference in New Issue
Block a user