Files
KCGL/db_migrations/phase4f_borrow_transfer_reject_reason.sql
yueli 681607bd43 feat(borrow): 拒收原因独立成列,与转交备注彻底分离
背景
----
拒收原因此前是**拼进 remark** 的:
    transfer.remark = f"{remark}\n[拒绝原因] {reason}"
前端拿到的是「3333\n[拒绝原因] 5555」这样一坨,时间线上两句挤在一起,
无法分辨哪句是发起备注、哪句是对方拒收的原因。

改动
----
· trans_borrow_transfer 新增 reject_reason text 列;
  reject_transfer 改为写入该列,不再拼进 remark。
· 存量按 '[拒绝原因] ' 标记切分回填(实测仅 #22:
  remark 3333 / reject_reason 5555)。
· 时间线事件带出 reject_reason,前端才能分行展示。

★ 为什么拆列而不是让前端解析字符串
  1) 拼接格式是隐式契约:改分隔符或加前缀,前端解析就静默失效且难排查;
  2) 用户完全可能在备注里自己打出 '[拒绝原因]' 字样,按标记切分必然误判 ——
     已加测试用例锁定该场景;
  3) 结构化字段才能参与查询与统计(如按拒收原因归类)。
  存储层能表达的东西,不该靠字符串约定去还原。

★ 一个迁移期踩到的坑:btrim 默认只去空格、不去换行。
  拼接留下的是 '3333\n',只写 btrim(x) 会残留换行;必须显式给出字符集
  btrim(x, E' \t\r\n')。已修正脚本并对存量做了一次清理。

验证(7 项断言全通过)
  备注不被污染、原因写独立列、无原因时为 None、
  用户备注含同名标记也不误判、库存零副作用、数据零残留。
2026-09-17 10:46:31 +08:00

80 lines
3.7 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.

-- =============================================================================
-- 借库转交 · 拒收原因独立成列
--
-- 背景
-- 拒收原因此前是**拼进 remark** 的:
-- transfer.remark = f"{remark}\n[拒绝原因] {reason}"
-- 结果前端拿到的是「3333\n[拒绝原因] 5555」这样一坨无法区分
-- 「发起时写的转交备注」与「对方拒收的原因」—— 时间线上两者挤在一起,
-- 毫无辨识度。
--
-- ---------------------------------------------------------------------------
-- 为什么改成独立列而不是让前端解析
-- 1) 拼接格式是**隐式契约**:一旦以后有人改拼接方式(换分隔符、加前缀),
-- 前端解析就静默失效,而且很难排查;
-- 2) 备注内容本身可能包含 '[拒绝原因] ' 字样(用户手打),按标记切分会误判;
-- 3) 结构化字段能直接参与查询与统计(例如「统计各类拒收原因」)。
-- 存储层能表达的东西,不要靠字符串约定去还原。
--
-- 存量回填
-- 按 '[拒绝原因] ' 标记切分现有 remark把原因挪到新列并清理 remark。
-- 实测仅 1 条(#22切分结果remark='3333'reject_reason='5555'。
--
-- 幂等:带 IF NOT EXISTS 与 NULL 判断,可重复执行。
-- 执行docker exec -i inventory_db psql -U test -d inventory_system < 本文件
-- =============================================================================
BEGIN;
ALTER TABLE trans_borrow_transfer
ADD COLUMN IF NOT EXISTS reject_reason text;
COMMENT ON COLUMN trans_borrow_transfer.reject_reason IS
'拒收原因,独立成列。此前拼在 remark 里("...\n[拒绝原因] xxx"),前端无法区分转交备注与拒收原因';
-- ★ btrim 默认只去**空格**,不去换行 —— 拼接时留下的是 '3333\n'
-- 只写 btrim(x) 会残留一个换行。必须显式给出要去除的字符集。
UPDATE trans_borrow_transfer
SET reject_reason = nullif(btrim(split_part(remark, '[拒绝原因] ', 2), E' \t\r\n'), ''),
remark = nullif(
btrim(replace(remark,
'[拒绝原因] ' || split_part(remark, '[拒绝原因] ', 2),
''),
E' \t\r\n'),
'')
WHERE status = 'REJECTED'
AND remark LIKE '%[拒绝原因] %'
AND reject_reason IS NULL;
COMMIT;
-- =============================================================================
-- 执行后核对
-- =============================================================================
\echo '--- 1) 新列已就位 ---'
SELECT column_name, data_type FROM information_schema.columns
WHERE table_name = 'trans_borrow_transfer' AND column_name = 'reject_reason';
\echo '--- 2) 备注与拒收原因已分离(#22 应为 remark=3333 / reject_reason=5555---'
SELECT id, status, to_user_name,
coalesce(replace(remark, E'\n', '\\n'), '<空>') AS ,
coalesce(reject_reason, '<无>') AS
FROM trans_borrow_transfer ORDER BY id;
\echo '--- 3) 不应再有残留的拼接痕迹(应为 0---'
SELECT count(*) AS FROM trans_borrow_transfer
WHERE remark LIKE '%[拒绝原因] %';
-- =============================================================================
-- 回滚段
-- =============================================================================
-- BEGIN;
-- UPDATE trans_borrow_transfer
-- SET remark = CASE WHEN remark IS NULL THEN '[拒绝原因] ' || reject_reason
-- ELSE remark || E'\n[拒绝原因] ' || reject_reason END
-- WHERE reject_reason IS NOT NULL;
-- ALTER TABLE trans_borrow_transfer DROP COLUMN IF EXISTS reject_reason;
-- COMMIT;