-- 乐收赢商户映射 —— review_status 本地词表写进列注释(Task 8 / 三-B,计划 §0.9-1) -- -- ★★ 2026-09-23 执行记录:**已在本机所连的 payment_platform_java 上执行完毕**。 -- 执行前注释是旧文案(不含 PENDING/REJECTED),执行后三个词齐全;列的 DDL 与数据分布均未变 -- (默认值仍是 'APPROVED'::character varying / NOT NULL / VARCHAR(32))。读数见 logs/_lsy_comment_exec.py 的输出, -- (脚本只 print 到 stdout、不落盘;原写作 _lsy-comment-exec.txt,2026-09-23 订正)。只读复核见 logs/_lsy_comment_readonly.py。重跑安全:只说一遍 COMMENT,幂等。 -- -- 【原注,保留】执行由用户做。**只改注释,不动任何数据、不动表结构** ⇒ 可安全重复执行。 -- -- ── 为什么要有这个脚本 ──────────────────────────────────────────────── -- V1.8 建表时把这一列写成 `review_status VARCHAR(32) NOT NULL DEFAULT 'APPROVED'`, -- 但当时**没有定义 B 阶段的词表**:列注释只说「B 阶段由进件写入口与上游审核通知回写」, -- 没有任何地方枚举过 B 阶段该写什么值。三-B 把这三个值定下来了(计划 §0.9-1 的裁定), -- 本脚本把词表落进**数据库自己的元数据**里 —— 让以后直接看库的人不必回去翻代码。 -- -- ★ **本脚本不改变任何行为**。真正的约束在 Java 侧:`LsyMerchantReviewStatus` 的三个常量, -- 有 `LsyMerchantReviewStatusTest` 钉着字面值。本脚本只是把同一份词表抄进注释。 -- -- ── ★ 这一列的真实危险:DEFAULT 'APPROVED' ───────────────────────────── -- `NOT NULL DEFAULT 'APPROVED'` 意味着**任何不显式给值的 INSERT 都会静默拿到 APPROVED**, -- 也就是「刚进件、还没审核」在管理端被读成「已通过」。 -- 进件写入口(`LeshouyingOnboardingController.create` → `LsyMerchantService.createOnboardingRow`) -- **必须显式写 PENDING**,不得依赖列默认值;也不得复用 `LsyMerchantService.save` 的新增分支 -- (那一路正是把 review_status 钉成 APPROVED 的地方,计划 §0.9-3)。 -- 本条**不是**本脚本能保证的,这里写下来是因为「改注释的人」正是最该知道它的人。 -- -- ── 词表三个值的来源(每个词都不是新造的)──────────────────────────── -- PENDING —— 本批次(三-B)**新引入**:进件写入口用它。 -- APPROVED —— 沿用**同一份 DDL 的默认值**里的那个词(逐字 'APPROVED',不是新词)。 -- REJECTED —— 沿用同模块 `pay_lsy_notify_log.process_status` **已在用的**那个词 -- (该列注释逐字列着 RECEIVED/APPLIED/DUPLICATE/REJECTED/..., -- 且 `LsyNotifyService` 在验签失败分支上写的就是字面量 "REJECTED")。 -- -- ★ 这**不是** spec §6.4 禁的那种「归一化」。那条禁的是把上游**三套** reviewed_status -- 值域互相猜着合并;这里是给**本地**一列定词表,且只从上游 556 这一套推导。 -- 上游值域 → 本地词表的映射**只此一处**,在 `LsyOnboardingReviewStatus`。 COMMENT ON COLUMN pay_lsy_merchant.review_status IS '进件审核状态(本地词表,VARCHAR(32))。三种取值:' 'PENDING=待审核(三-B 新引入,进件写入口写入;新行**不得**落到本列默认值 APPROVED 上);' 'APPROVED=审核通过(沿用本列 DDL 默认值里的那个词);' 'REJECTED=审核驳回(沿用同模块 pay_lsy_notify_log.process_status 已在用的那个词)。' '字面值由 LsyMerchantReviewStatus 常量钉住;上游审核状态到本词表的映射只在 LsyOnboardingReviewStatus 一处,别的类不许各写一份。'; -- ── 只读核对(执行后手工跑一遍)────────────────────────────────────── -- -- 1) 注释是否落上(**逐字**比对上面那段,注意 psql 会把多行字符串拼成一行) -- SELECT col_description('pay_lsy_merchant'::regclass, -- (SELECT ordinal_position FROM information_schema.columns -- WHERE table_name = 'pay_lsy_merchant' AND column_name = 'review_status')); -- 期望:一段含 'PENDING'、'APPROVED'、'REJECTED' 三个词的文本。 -- -- 2) 列的默认值**仍然是 APPROVED**(本脚本**故意不改它**) -- SELECT column_default, is_nullable, character_maximum_length -- FROM information_schema.columns -- WHERE table_name = 'pay_lsy_merchant' AND column_name = 'review_status'; -- 期望:`'APPROVED'::character varying | NO | 32`。 -- ★ 若这里被改成了别的值,说明有人动过 DDL —— 那与 `LsyMerchantReviewStatus` 的 -- APPROVED 常量、以及 V1.8 的存量行口径都不一致,需要先裁定再继续。 -- -- 3) 库里的值**是否只在词表内**(本脚本执行前后都可跑;只读) -- SELECT review_status, count(*) FROM pay_lsy_merchant GROUP BY review_status ORDER BY 1; -- 期望:出现的值都落在 {PENDING, APPROVED, REJECTED} 内。出现别的值 ⇒ 有写入口没走常量。