Files
KCGL/db_migrations/phase4b_borrow_dispatch_operator.sql
yueli b998b00889 feat(borrow): 借库转交一期数据层(迁移、转交/归还流水表、发货操作人列)
背景
----
原 trans_borrow 是单行记录模式,身份维度只有 borrower_name 一个字符串:
「谁借的」与「谁现在还拿着」是同一个字段,无法表达持有权变更;归还时
return_time/return_operator/return_signature 被逐次覆盖,部分归还下
「谁在什么时候还了多少」永久丢失。

本次改动(全部增量,无破坏性 DDL,可回滚)
----
1) trans_borrow 补列
   · borrower_id / current_holder_id / current_holder_name —— 身份锚点
   · dispatch_operator —— 执行借出的库管(operator_name 形参此前被接收却从未落库)
2) 新建 trans_borrow_transfer —— 转交流水,一行=一次转交,不做覆盖式更新
3) 新建 trans_borrow_return   —— 归还流水,逐次记录,根治部分归还失忆症
4) 历史回填(已执行):85 行中 84 行 borrower_id 唯一命中 sys_user;
   未归还的 32 行全部绑定 current_holder
5) 注册 borrow_transfer 权限码(无冒号形式,避免 _expand_operation_perms
   前缀桥接把权限放大给所有持有 op_borrow:operation 的角色)

设计取舍
----
· current_holder 只回填「未归还」行:已归还=物品已回库、无人持有,保持 NULL。
  这样「current_holder_id IS NOT NULL」本身就是「仍在某人手上」的有效信号,
  归还校验不会对已结清单据误触发。
· 三张表都不建外键:与 trans_return / trans_defective_goods 一致 ——
  库存行会被入库模块物理删除(实测已有悬空),台账必须能独立存活。
· dispatch_operator 不回填历史:执行人信息从未被采集,系统中不存在可回填的
  数据源;用申请人或借用人冒充实物交接人比留空更危险。

验证:迁移已对 inventory_db 执行,核对段全部通过。
2026-09-17 09:17:51 +08:00

59 lines
2.9 KiB
PL/PgSQL
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.

-- =============================================================================
-- 借库转交一期收口trans_borrow 补 dispatch_operator发货操作人
--
-- 背景
-- 责任链上「谁借的 / 谁现在拿着 / 谁还的」在此前改造中已全部锚定到 ID
-- 唯独**执行借出的库管操作人**一直没落库 —— execute_dispatch 的
-- operator_name 形参被接收后从未写入任何字段(首轮调研已标记该缺口)。
-- 本迁移补齐最后一环,使一次借出在台账上能回答四个问题:
-- 借用人 borrower_id / 当前持有人 current_holder_id /
-- 发货操作人 dispatch_operator / 归还人 trans_borrow_return.returner_id
--
-- ---------------------------------------------------------------------------
-- ★ 为什么存「姓名」而不是 ID
-- execute_dispatch 的 operator_name 由 API 层经 _current_username() 取得,
-- 本身就是展示口径的字符串(与 trans_borrow_return.operator_name 一致)。
-- 该字段仅用于台账展示与追溯,不参与任何权限判定或持有人校验,
-- 故不引入 ID —— 需要精确到人时审计日志audit_listener另有记录。
--
-- ★ 为什么不回填历史值
-- 改造前的执行人信息**从未被采集**,系统中不存在任何可回填的数据源
-- trans_borrow 没有对应列TransBorrow 也没有其它操作人字段)。
-- 刻意留空而非猜测填充 —— 用申请人或借用人冒充实物交接人,
-- 比留空更危险。NULL 即表示「本次借出发生在该字段上线之前」。
--
-- 幂等:带 IF NOT EXISTS可重复执行。
-- 执行docker exec -i inventory_db psql -U test -d inventory_system < 本文件
-- =============================================================================
BEGIN;
ALTER TABLE trans_borrow
ADD COLUMN IF NOT EXISTS dispatch_operator varchar(100);
COMMENT ON COLUMN trans_borrow.dispatch_operator IS
'执行借出(扫码发货)的库管操作人姓名。仅展示/追溯用,不参与权限判定;'
'该列上线前的历史记录为 NULL';
COMMIT;
-- =============================================================================
-- 执行后核对
-- =============================================================================
\echo '--- 1) 新列已就位 ---'
SELECT column_name, data_type, character_maximum_length
FROM information_schema.columns
WHERE table_name = 'trans_borrow' AND column_name = 'dispatch_operator';
\echo '--- 2) 存量行均为 NULL预期全部为 NULL历史数据无从回填---'
SELECT count(*) AS total, count(dispatch_operator) AS filled FROM trans_borrow;
-- =============================================================================
-- 回滚段
-- =============================================================================
-- BEGIN;
-- ALTER TABLE trans_borrow DROP COLUMN IF EXISTS dispatch_operator;
-- COMMIT;