Files
KCGL/db_migrations/phase4e_borrow_transfer_reject_notice.sql
yueli f24797ff1f feat(borrow): 拒收须告知发起方(责任回到他手上,不能静默)
背景
----
双向握手补上了「接收人确认」,却只做了单向告知:接收人能看到待办,发起方却
对结果一无所知。**被拒绝时物品责任仍在发起方手上** —— 他若不主动查列表,
就会误以为已经交接出去,责任链出现静默断点。

(ACCEPTED 不需要告知:东西已经交出去了,发起方无需动作。)

改动
----
· trans_borrow_transfer 新增 reject_seen_at(NULL 且 REJECTED = 尚未告知)。
  ★ 为什么需要持久标记而不是前端去重:换台电脑、换个浏览器就会重新提醒;
    而这条信息的分量(责任归属)值得一个持久标记。
  ★ 存量已拒绝的流水一律标记为已告知:它们产生于本功能上线之前,
    追溯提醒只会打扰(实测仅 1 条:#22,验收时的测试数据)。
· get_unseen_rejects(user_id):返回「我发起、被拒、尚未告知我」的转交,
  并批量解析物料名 —— 只说「某笔转交被拒」发起方仍不知是哪件东西还在
  自己手上,必须让他一眼认出来。
· ack_rejects(user_id, ids):发起方确认后写 reject_seen_at,幂等。
· GET .../transfer/pending-count 的响应并入 rejects:与待接收数量共用同一次
  轮询,前端不必多打一个请求。
· POST .../transfer/reject-ack:无 permission_required,同 accept/reject。

顺带补一处同源显示缺口
----
流转时间线里,被拒绝的转交与成功的长得一模一样 —— 发起方翻记录时同样会
误判。现将转交状态一并带出时间线事件。

验证(15 项断言全通过)
----
发起方收到待告知的拒绝(含物料名/接收人/拒绝原因);接收人与无关人看不到;
ack 后不再提醒且幂等;ACCEPTED 不产生告知;None/非法 user_id 均安全返回;
库存零副作用、数据零残留。
2026-09-17 10:44:00 +08:00

76 lines
3.4 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.

-- =============================================================================
-- 借库转交 · 拒收须告知发起方
--
-- 背景
-- 双向握手补上了「接收人确认」这一环,但只做了单向告知:接收人能看到待办,
-- 发起方却对结果一无所知 —— 尤其是**被拒绝**时,物品责任仍在发起方手上,
-- 他若不查列表就会误以为已经交接出去,责任链出现静默断点。
--
-- ---------------------------------------------------------------------------
-- 为什么需要 reject_seen_at 这一列
-- ACCEPTED 不需要告知(东西已经交出去了,发起方无需动作);
-- REJECTED 必须告知,且**必须能标记「已告知」** —— 否则发起方每次登录
-- 都会收到同一条提醒,从「提醒」退化成「骚扰」。
--
-- 不宜用前端 sessionStorage 去重:换台电脑、换个浏览器就会重新提醒,
-- 而这条信息的分量(责任归属)值得一个持久标记。
--
-- 语义
-- reject_seen_at IS NULL 且 status='REJECTED' → 尚未告知发起方
-- 发起方在前端看到提醒并确认后,写当前时间
--
-- ★ 存量已拒绝的流水一律标记为「已告知」
-- 它们产生于本功能上线之前,追溯提醒只会打扰(实测仅 1 条:
-- #22 测试 → 小龙虾,是验收时的测试数据)。新产生的拒绝才会触发提醒。
--
-- 幂等:带 IF NOT EXISTS可重复执行。
-- 执行docker exec -i inventory_db psql -U test -d inventory_system < 本文件
-- =============================================================================
BEGIN;
ALTER TABLE trans_borrow_transfer
ADD COLUMN IF NOT EXISTS reject_seen_at timestamp without time zone;
COMMENT ON COLUMN trans_borrow_transfer.reject_seen_at IS
'发起方看到「被拒绝」提醒并确认的时间。NULL 且 status=REJECTED 表示尚未告知';
-- 存量已拒绝的流转为已告知(本功能上线前的历史,不追溯打扰)
UPDATE trans_borrow_transfer
SET reject_seen_at = CURRENT_TIMESTAMP
WHERE status = 'REJECTED'
AND reject_seen_at IS NULL;
-- 支撑「待告知发起方的拒绝」查询
CREATE INDEX IF NOT EXISTS ix_trans_borrow_transfer_from_status
ON trans_borrow_transfer (from_user_id, status);
COMMIT;
-- =============================================================================
-- 执行后核对
-- =============================================================================
\echo '--- 1) 新列已就位 ---'
SELECT column_name, data_type FROM information_schema.columns
WHERE table_name = 'trans_borrow_transfer' AND column_name = 'reject_seen_at';
\echo '--- 2) 拒绝流水均已标记为已告知(应为 0 行待告知)---'
SELECT id, borrow_no, status, from_user_name, to_user_name, reject_seen_at
FROM trans_borrow_transfer
WHERE status = 'REJECTED' AND reject_seen_at IS NULL;
\echo '--- 3) 全部流水一览 ---'
SELECT id, status, from_user_name, to_user_name,
CASE WHEN reject_seen_at IS NULL THEN '' ELSE '已告知' END AS
FROM trans_borrow_transfer ORDER BY id;
-- =============================================================================
-- 回滚段
-- =============================================================================
-- BEGIN;
-- DROP INDEX IF EXISTS ix_trans_borrow_transfer_from_status;
-- ALTER TABLE trans_borrow_transfer DROP COLUMN IF EXISTS reject_seen_at;
-- COMMIT;