Browse Source

docs(进件): 交付说明补三件 —— F2 结案、10 字段裁定、模板覆盖面订正

只改文档,零代码变更(本次唯一的代码动作是一次探针注入,已在同一步内还原并复核 sha256)。

§六-2 把「上游已建号、本地无行」拆成两个成因分别处置,此前它一直挂在「只换了出口」里:
(A) 上游那次 HTTP 建号失败 ⇒ 判「修不了」而不是「没修」—— 本地无从判断上游建没建,
    判据只在对面;出口已由 R-7b 闭掉。
(B) 本地落库失败 ⇒ 补偿是手工的、而路是通的(LeshouyingMerchantController:46 →
    LsyMerchantService.save:456 新增分支),三个环节逐个实读。
    尖角一处:save:480-482 只在 review_status 空白时才默认 APPROVED,而进件腿落行写的是
    PENDING(createOnboardingRow:391)⇒ 补行必须显式带 review_status:"PENDING",
    否则那行会声称「上游已审核」而该商户连提交入网都没做。
本批不做自动补偿/对账/重试:(A) 结构上做不到;(B) 要新开孤儿表 + 对账腿 = 又一份要用户执行的 SQL。

§七 新增更新腿 10 个「无入口」字段的裁定(本批不补)与权威数据表 —— 6 个正是 §0.3d 那一族
通道条件字段,而 §0.3d 本身就是待用户裁定项,先做 UI 等于替用户做裁定;另 4 个各有一个
必须先答的问题。不补是安全的:上游更新是增量语义,没入口 = 不改这一项,不会抹掉已有值
⇒ 能力缺口,不是正确性缺口。逐字说明/类型/必填/取值线索取自上游 page 196236557 已落档,
将来补时是转录不是重新调研;并记上游文档自身三处缺陷(转录前必读)。

§七 另订正我此前「模板本身未被验证」的说法 —— vue-tsc 会检查该页模板表达式
(往模板注入一处类型错 ⇒ ts:check 287→289,两条都点名 onboarding/index.vue(99,52)/(163,52))
⇒ 那条「与本改动前逐字节相同的 287」顺带证明模板表达式类型干净。
并补记模板三处字段渲染点(:99 / :163 / :242)全部走 visibleFields(s),无残留 s.fields ——
这条台子看不见:台子驱动的是函数,函数再对而模板仍遍历 s.fields,台子照样 43 绿。

未删任何东西。
alphaH 3 weeks ago
parent
commit
a2ccfe7149
1 changed files with 73 additions and 3 deletions
  1. 73 3
      .claude/plan/2026-09-23-lsy-onboarding-B-交付说明.md

+ 73 - 3
.claude/plan/2026-09-23-lsy-onboarding-B-交付说明.md

@@ -121,6 +121,10 @@
    (`reg_capital` / `fSettle_account_type` / `actual_addr` / `business_scope` / `check_code` /
    (`reg_capital` / `fSettle_account_type` / `actual_addr` / `business_scope` / `check_code` /
    `lease_contract` / `p_cashier` 等)**没进必填矩阵**;字段照常进 DTO、照常上送(**不收 ≠ 放行**)。
    `lease_contract` / `p_cashier` 等)**没进必填矩阵**;字段照常进 DTO、照常上送(**不收 ≠ 放行**)。
    **代价若判错**:通道落定后操作者漏填会被**上游**拒(报错点在上游,请求体在日志里,可当场比对补)。
    **代价若判错**:通道落定后操作者漏填会被**上游**拒(报错点在上游,请求体在日志里,可当场比对补)。
+   ★ **裁定这一项要用到的数据已备齐**:这 6 个(加上另外 4 个更新腿独有的)字段的上游原文说明、
+   类型、必填标记与取值线索,以及**上游文档自身的三处缺陷**,都在 **§七**里(2026-09-23 取自上游
+   page 196236557)。同时那里记着一条相关的语义不对称待你一并裁:`account_type` 建号腿**由类别派生**、
+   更新腿**可单独改**。
 2. **§0.7 —— `/api/info/bank` 选择器要不要补。** `account_bank_code` 已从「平台级凭据」改正为
 2. **§0.7 —— `/api/info/bank` 选择器要不要补。** `account_bank_code` 已从「平台级凭据」改正为
    **商户自己的结算账户开户支行**(逐商户填)。本批次**不实现**该接口,联行号**手工录入**。
    **商户自己的结算账户开户支行**(逐商户填)。本批次**不实现**该接口,联行号**手工录入**。
 3. **§0.8 —— `rate_code` 的归属未定:平台级还是逐商户。** 现按**平台级配置项**实现(DTO 里留了可覆盖字段)。
 3. **§0.8 —— `rate_code` 的归属未定:平台级还是逐商户。** 现按**平台级配置项**实现(DTO 里留了可覆盖字段)。
@@ -155,9 +159,23 @@
 
 
 1. ~~**tenant 2 的功能性阻塞**(§1.2)~~ —— **★ 2026-09-23 已解除**:重复行已去重(删 A `id=1`)、
 1. ~~**tenant 2 的功能性阻塞**(§1.2)~~ —— **★ 2026-09-23 已解除**:重复行已去重(删 A `id=1`)、
    `uk_lsy_merchant_mch_no` 已建成并通电验证。本条原读数是「**今天仍开着**(我量:那 2 行还在)」,**那是当时的真读数**;读数见 §1.2 后记。
    `uk_lsy_merchant_mch_no` 已建成并通电验证。本条原读数是「**今天仍开着**(我量:那 2 行还在)」,**那是当时的真读数**;读数见 §1.2 后记。
-2. **「上游已建号、本地无行」** —— 上轮修复把**本地落库失败**的出口从 catch-all 500 改成 409 + 带上游商户号 + 日志带 `tenantId`/`mchNo`;
-   但上游那次 HTTP 建号**不能纳入本地事务**(出站调用不回滚)⇒ **这个状态依然可能出现**。
-   本轮**没有**补偿、**没有**对账、**没有**自动重试;运维只能靠**人**走既有 `save` 手工补一行。要真正关闭需**新开任务**。
+2. **「上游已建号、本地无行」** —— **★ 2026-09-23 结案:一半判「修不了」,另一半给出可执行的手工闭环。**
+   这个状态有**两个成因**,代价与出路都不同,此前一直混在同一句话里:
+
+   - **(A) 上游那次 HTTP 建号失败**(超时 / 连接错)⇒ 本地**无从判断上游到底建没建**。
+     这不是「没修」,是**修不了** —— 判据所需的信息只在对面,本地无论怎么查都是猜。
+     **出口**已由 R-7b 闭掉(非 GET 回「不得当作失败直接重试」),不再是一个诱导重试的 500。
+     ⇒ 成因 (A) **到此为止**,不再作为待办挂着。
+   - **(B) 上游已建号、本地落库失败** ⇒ **商户号已知**(409 应答里带着,日志里也带着)。
+     出口由 R1-A 闭掉;**补偿是手工的,而这条路是通的** —— 我实读代码核对过三个环节,不是推测:
+     管理端「商户映射」→ `POST /payment/collection/merchant`(权限串 `…:leshouying:merchant:list`)
+     → `LsyMerchantService.save` 的新增分支。
+     ★ **一处尖角**:`save` 只在 `reviewStatus` **空白时**才默认成 `APPROVED`,而进件腿的自动落行写的是
+     `PENDING`。⇒ 补行时**必须显式带上** `review_status: "PENDING"`,否则这一行会声称「上游已审核」,
+     而该商户其实**连提交入网都还没做**。(`save` 只在空白时才兜默认值 ⇒ 显式传的值会被原样采纳。)
+
+   本批**不做**自动补偿 / 对账 / 重试:(A) 结构上做不到;(B) 要做就得新开一张孤儿表 + 一条对账腿
+   (新 schema ⇒ 又是一份要用户执行的 SQL),而现有的手工路径已经把商户号交到操作员眼前。
 3. ~~**上游调用失败仍是 HTTP 500(R-7b)**~~ —— **★★ 2026-09-23 已修复**(提交 `5290d84`,
 3. ~~**上游调用失败仍是 HTTP 500(R-7b)**~~ —— **★★ 2026-09-23 已修复**(提交 `5290d84`,
    测试 647 绿;两向变异 4 条逐条读数见 `.superpowers/sdd/2026-09-23-lsy-onboarding-B` 的**加记 86**)。
    测试 647 绿;两向变异 4 条逐条读数见 `.superpowers/sdd/2026-09-23-lsy-onboarding-B` 的**加记 86**)。
    **修法**:在 `LeshouyingOnboardingController` 上加控制器局部的
    **修法**:在 `LeshouyingOnboardingController` 上加控制器局部的
@@ -241,6 +259,47 @@
   `account_idcard_stt` / `reg_capital` / `fSettle_account_type` / `actual_addr` / `business_scope` /
   `account_idcard_stt` / `reg_capital` / `fSettle_account_type` / `actual_addr` / `business_scope` /
   `check_code` / `p_cashier`)—— 不是漏做:后端那张中文标签表是**创建页** 62 个参数的表,
   `check_code` / `p_cashier`)—— 不是漏做:后端那张中文标签表是**创建页** 62 个参数的表,
   它的键集被一条 `assertEquals` 钉死,这 10 个键一个都不在里面。要补得先从更新页参数表逐个转录。
   它的键集被一条 `assertEquals` 钉死,这 10 个键一个都不在里面。要补得先从更新页参数表逐个转录。
+  ★ **2026-09-23 裁定:本批不补这 10 个入口**,两条理由:
+  ① 其中 **6 个正是 §0.3d 那一族通道条件字段**(`reg_capital` / `fSettle_account_type` /
+     `actual_addr` / `business_scope` / `check_code` / `p_cashier`),而 §0.3d **本身就是 §四 待用户裁定
+     的第 1 项** ⇒ 先替用户把 UI 做出来,等于替他做了那个裁定;
+  ② 剩下 4 个各有一个**必须先答的问题**:三个 `*_stt`(`license_stt` / `legal_cert_stt` /
+     `account_idcard_stt`)的语义在上游文档里**自相矛盾**(见下);`account_type` 在**建号腿是从
+     `category` 派生**的(实测 `LsyOnboardingService:1190`
+     `p.put("account_type", dto.getCategory().getAccountType())`),更新腿却是 **DTO 直取**
+     (`:480` `putIfNotBlank(p, "account_type", dto.getAccountType())`)⇒ 更新腿能造出**与商户类别不符**
+     的结算类型,而建号腿不能。这是**要不要允许**的选择,不是一个默认值。
+  ★ **不补是安全的**:上游更新是增量语义「有值则更新,无值则保持原数据」⇒ 没有入口 = **不改这一项**,
+     不会把已有值抹掉。所以这是**能力缺口**,不是正确性缺口。
+  ★ **转录用的权威数据已取回**(上游 page 196236557,2026-09-23 用 showdoc JSON 接口取全文)。
+     将来裁定「补」时不必再查文档,逐字如下:
+
+     | 键 | 上游说明(逐字) | 类型列 | 必填列 |
+     |---|---|---|---|
+     | `license_stt` | 营业执照有效期(格式YYYYMMDD) | String(8) | |
+     | `account_type` | 账户类型 | String(4) | 是 |
+     | `legal_cert_stt` | 法人证件起始日(格式YYYYMMDD | String(30) | |
+     | `account_idcard_stt` | 持卡人身份证起始日(格式YYYYMMDD) | String(8) | |
+     | `reg_capital` | 注册资本 | String(25) | C |
+     | `fSettle_account_type` | 结算账户类型 | String(2) | C |
+     | `actual_addr` | 营业地址 | String(2) | C |
+     | `business_scope` | 营业范围 | String(2) | C |
+     | `check_code` | 安心签验证码 | String(2) | C |
+     | `p_cashier` | 收银台照 | String(255) | |
+
+     取值线索在同表的**示例列**(不是说明列):`account_type` = `1对公结算 2法人对私结算 3非法人对私结算`;
+     `reg_capital` = `1000000 单位元 平安收银宝必填`;`fSettle_account_type` = `1-我行对公 2-我行对私 平安收银宝必填`;
+     `actual_addr` = `省市区+详细地址 平安收银宝必填`;`business_scope` = `营业执照上的 平安收银宝必填`;
+     `check_code` = `485225 星驿付必填`。
+  ★★ **上游文档本身有三处缺陷,转录前必须知道**,否则会把缺陷抄成我们的标签:
+     ① `license_stt` 的说明与 **`license_expire` 逐字撞车**(两个都写「营业执照有效期(格式YYYYMMDD)」,
+        后者多一句「长期传20991231」)。按 `_stt` / `_expire` 的命名、以及另两个同族字段
+        (`legal_cert_stt` = 法人证件**起始日**、`account_idcard_stt` = 持卡人身份证**起始日**)判断,
+        `license_stt` 应当是**起始日** —— **但这是我的推断,不是文档写的**,转录前要向上游确认。
+     ② `legal_cert_stt` 的说明**缺右括号**(「(格式YYYYMMDD」)—— 已按原文照录,未替它补。
+     ③ `actual_addr` / `business_scope` / `check_code` 的**类型列都写 `String(2)`**,而它们的示例分别是
+        「省市区+详细地址」「营业执照上的」「485225」⇒ 类型列与示例**互相矛盾**,`String(2)` 一个都装不下。
+        ⇒ **不要照类型列做长度校验。**
   ⇒ **后端收 50 个**,两支独立量法逐位同值:① `updateMerchant` 方法体内 `putIfNotBlank`
   ⇒ **后端收 50 个**,两支独立量法逐位同值:① `updateMerchant` 方法体内 `putIfNotBlank`
   调用点 = **50**(正控:全文件 `putIfNotBlank(` 出现 51 次 = 定义 1 处 + 调用 50 处,
   调用点 = **50**(正控:全文件 `putIfNotBlank(` 出现 51 次 = 定义 1 处 + 调用 50 处,
   且没有调用落在 `updateMerchant` 之外);② `LsyMerchantUpdateDTO` 的 `private String`
   且没有调用落在 `updateMerchant` 之外);② `LsyMerchantUpdateDTO` 的 `private String`
@@ -251,6 +310,17 @@
   ★ 这 39 个与后端那 50 个做过**跨端键名核对**(`fe-update-keycheck.mjs`,把两边键集放在
   ★ 这 39 个与后端那 50 个做过**跨端键名核对**(`fe-update-keycheck.mjs`,把两边键集放在
   **同一个 node 进程**里做集合运算):前端键集 ⊆ 后端键集,**多出 0 个**。这条不能省 ——
   **同一个 node 进程**里做集合运算):前端键集 ⊆ 后端键集,**多出 0 个**。这条不能省 ——
   前端键名拼错**不会当场报错**,只会变成线上 HTTP 500。
   前端键名拼错**不会当场报错**,只会变成线上 HTTP 500。
+  ★ **两处本轮新做的检查,以及一处对我此前说法的订正**:
+  - **模板的三处字段渲染点全部接了投影函数**(`:99` 纯文本组 / `:163` 地址组 / `:242` 上传组
+    **都**是 `v-for="f in visibleFields(s)"`,没有残留的 `s.fields`)。这条必须单看 ——
+    执行级台子驱动的是**函数**,模板有没有调用它,台子**看不见**:投影函数写得再对,
+    模板若仍遍历 `s.fields`,「更新模式不渲染那两个键」就是一句空话,而台子照样 43 绿。
+  - **订正我此前的说法**:我写过「模板本身未被验证」。**实测不成立。** `vue-tsc` **会**检查本文件的
+    **模板表达式** —— 往模板里注入一处类型错,`pnpm ts:check` 从 **287** 变 **289**,两条都点名
+    `onboarding/index.vue(99,52)` 与 `(163,52)`、报的就是我注入的那个属性名。
+    ⇒ 那条「与本改动前**逐字节相同**的 287」因此**顺带证明模板表达式类型干净**
+    (无未定义标识符、无错键访问、无类型不符),而不是只证明了脚本部分。
+    **仍未验**的只剩**运行时渲染**(台子是 `inlineTemplate: false`)与**浏览器表现**(§5.1)。
 
 
 ---
 ---