Files
KCGL/db_migrations/phase4d_borrow_transfer_item_level.sql

75 lines
3.8 KiB
MySQL
Raw Normal View History

feat(borrow): 转交粒度下沉到明细行,支持部分转交 背景(业务方推翻上一轮约束) ---- 上一轮按「一张单同时只能有一个持有人」实现了**整单转交**,并把「单内出现多个 持有人」当作 bug 去修。业务方验收后明确纠正: 物理现场经常只转交部分工具(借了 2 件、只把 1 件转给别人), 单内多持有人才是符合现实的正常状态。 故转交粒度从 borrow_no 下沉回 trans_borrow.id(明细行)。 改动 ---- · transfer_borrow:只操作传入的那**一行**明细,不再按单号整批覆盖。 转出方 = 该行当前持有人;数量 = 该行待还量。 · accept_transfer:只转移 transfer.borrow_id 指向的那一行 —— 整批改写会把别人手上的东西一并抢过来(部分转交下同单明细分属不同人)。 · 唯一性约束从「单号至多一条 PENDING」下沉为「明细行至多一条」: 同单的其他明细可以同时各自挂着待接收,互不阻塞 —— 这正是部分转交的语义。 · get_records 的 pending_transfer 改按 borrow_id 关联(原按 borrow_no), 否则同单多项待接收会互相覆盖。 · 删除已无用的 _load_slip_for_update。 ★ 数量粒度:一行只支持**整行转交**。一行只能有一个 current_holder_id, 「同一行只转一部分」需要把这行拆成两行 —— 经业务确认,现场场景中 「借 2 件转 1 件」的两件本就是两条明细行,故该限制不影响实际使用; 接口对传入的非整行数量会明确提示「应另立一条明细行」。 数据层 ---- 无需改表结构:borrow_id 本就是流水的关联列,borrow_no 退化为单据归属与 分组展示用。仅补 (borrow_id, status) 复合索引支撑新的查询路径。 存量撕裂数据(BOR-20260917-0001 的「测试 / 杜邢宸」)按业务方选择**保留不动** —— 它现在不再是 bug,而是部分转交的正常形态。 验证(合成 2 明细单,21 项断言全通过) ---- · 只转工具A:工具B 完全不受影响 · 同一张单可同时挂两条待接收,互不阻塞;同一明细重复发起被拒 · accept 工具A 后:A→测试,B 仍是杜邢宸(单内两个持有人) · 两个持有人、以及待接收人,三方各自都能在列表中看到该单 · pending_transfer 挂在正确的明细行上,is_mine 判定正确 · reject 后主表持有人不变;非整行数量被拒并提示拆行 · 全程 available_quantity 无变化,库存精确还原、零残留数据
2026-09-17 10:12:31 +08:00
-- =============================================================================
-- 借库转交 · 粒度下沉到明细行(部分转交)
--
-- 背景(业务方推翻上一轮约束)
-- 上一轮按「一张单同时只能有一个持有人」实现了**整单转交**,并把「单内出现
-- 多个持有人」当作 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;