-- ============================================================================= -- 借库转交 · 粒度下沉到明细行(部分转交) -- -- 背景(业务方推翻上一轮约束) -- 上一轮按「一张单同时只能有一个持有人」实现了**整单转交**,并把「单内出现 -- 多个持有人」当作 bug 去修。业务方验收后明确纠正: -- 物理现场经常只转交部分工具(借了 2 件,只把 1 件转给别人), -- **单内多持有人才是符合现实的正常状态**。 -- 故转交粒度从 borrow_no 下沉回 trans_borrow.id(明细行)。 -- -- --------------------------------------------------------------------------- -- 本次改动的实质 -- 代码层:transfer_borrow / accept_transfer 只操作**一行**明细, -- 唯一性约束从「单号最多一条 PENDING」改为「明细行最多一条 PENDING」。 -- 数据层:**无需改动任何表结构** —— borrow_id(明细行)本就是流水的主键 -- 关联列,borrow_no 继续保留作单据归属与展示分组用。 -- 仅补一个复合索引,支撑「按明细行查待接收流水」这一新查询路径。 -- -- ★ 为什么不需要新的列 -- 转交粒度既然回到明细行,覆盖范围就是 borrow_id 指向的那一行本身 —— -- 不需要额外的「覆盖清单」来表达范围,borrow_no 退化为分组/展示用途。 -- -- ★ 存量数据不动(业务方选择) -- BOR-20260917-0001 的「测试 / 杜邢宸」双持有人状态予以保留: -- 它现在不再是 bug,而是「部分转交」的正常业务形态。 -- -- 幂等:带 IF NOT EXISTS,可重复执行。 -- 执行:docker exec -i inventory_db psql -U test -d inventory_system < 本文件 -- ============================================================================= BEGIN; -- 支撑「该明细行是否已有待接收流水」的唯一性检查,以及按明细行批量取待接收 CREATE INDEX IF NOT EXISTS ix_trans_borrow_transfer_borrow_status ON trans_borrow_transfer (borrow_id, status); COMMENT ON COLUMN trans_borrow_transfer.borrow_no IS '借用单号。仅用于单据归属与列表分组展示;转交的**覆盖范围**是 borrow_id 指向的单个明细行'; COMMENT ON COLUMN trans_borrow_transfer.borrow_id IS '转交目标明细行ID(trans_borrow.id)。转交粒度 = 明细行,一行最多一条待接收流水'; COMMIT; -- ============================================================================= -- 执行后核对 -- ============================================================================= \echo '--- 1) 复合索引已就位 ---' SELECT indexname FROM pg_indexes WHERE tablename = 'trans_borrow_transfer' AND indexname = 'ix_trans_borrow_transfer_borrow_status'; \echo '--- 2) 存量流水(borrow_id / borrow_no / status)---' SELECT id, borrow_id, borrow_no, status, from_user_name, to_user_name FROM trans_borrow_transfer ORDER BY id; \echo '--- 3) 各明细行的待接收流水数(应全部 <= 1)---' SELECT borrow_id, count(*) AS 待接收数 FROM trans_borrow_transfer WHERE status = 'PENDING' GROUP BY borrow_id HAVING count(*) > 1; \echo '--- 4) 单内多持有人的单号(现在属正常业务形态,不再视为异常)---' SELECT borrow_no, count(DISTINCT current_holder_id) AS 持有人数, string_agg(DISTINCT coalesce(current_holder_name,'NULL'), ', ') AS 持有人 FROM trans_borrow WHERE is_returned = FALSE GROUP BY borrow_no HAVING count(DISTINCT current_holder_id) > 1; -- ============================================================================= -- 回滚段 -- ============================================================================= -- BEGIN; -- DROP INDEX IF EXISTS ix_trans_borrow_transfer_borrow_status; -- COMMIT;