Explorar el Código

docs(进件): Task 4 修复轮 1 - license_stt 两页说明列逐字落进代码 + LABELS 不覆盖的理由(零行为改动)

(a) 实缺陷:LsyMerchantUpdateDTO.licenseStt 的 javadoc 原写「本页说明与 license_expire
**逐字相同** ⇒ 语义**不明**」—— 两句都不成立。自量转写件:
  _txt-196236557.md:42  license_stt     =「营业执照有效期(格式YYYYMMDD)」
  _txt-196236557.md:43  license_expire  =「营业执照有效期(格式YYYYMMDD)长期传20991231」
  _txt-196236555.md:46  license_stt     =「营业执照开始(格式YYYYMMDD)」
  _txt-196236555.md:47  license_expire  =「营业执照结束(格式YYYYMMDD)长期传20991231」
⇒ 更新页两行不是同一句(expire 多「长期传20991231」);且创建页对同名两字段明文写开始/结束
⇒ 语义并不「不明」。改法:把两页四行逐字落进 javadoc,并写明**仍读作「开始」的两条独立依据**
(① expire 那行带「长期传20991231」——「长期」只在结束日期上讲得通;② 创建页的 开始/结束)。
随带记入计划 §0.5 那行与同份计划 §0.3c(:131「license_stt | 营业执照开始」)自相矛盾的溯源
(主控已订正计划那行,R52)。

★ **行为一个字未变**:仍原样透传、**不做 YYYYMMDD 校验**。javadoc 里把这条理由与已被推翻的
「语义不明」拆开写清 —— 理由是「本模块 50 多个进件字段一个都不做格式校验」,
给这一个字段单独加校验会让它成为唯一例外。licenseExpire 处补一句指向 licenseStt(唯一落点)。

(c) 轻项:commitMerchantInfo 的 javadoc 补上「这六个 label 为什么是字面量而不是 LABELS」——
那张表是创建页 26 项的翻译表,六个键在 LsyMerchantRequiredFields 里命中数实测全 0
(中文标签同样 0),走 LABELS.get(...) 只会在运行时抛它自己的 IllegalStateException。
并要求不要为「统一」往那张表里塞本页字段(会动到必填矩阵的覆盖面断言)。

(d) 轻项:newLegs_missingCredentials 用例里的硬编码 5 补出来源(missingOnboardingCredentials()
的五项,源码 LeshouyingProperties:228-245),并写明**不**改成从实现取数的理由:
期望值与被测实现同源会让「集合缩到 1 项」也照样绿;将来集合变了应两处一起红。

验证:git diff 非注释改动行 = 0(-U0 过滤 javadoc 行后输出为空);
全量 547 → 548,0 fail / 0 error / 0 skipped,BUILD SUCCESS。
alphaH hace 3 semanas
padre
commit
7f008fb1c2

+ 31 - 4
java/src/main/java/com/payment/platform/module/payment/leshouying/dto/LsyMerchantUpdateDTO.java

@@ -93,13 +93,40 @@ public class LsyMerchantUpdateDTO {
     /**
      * 营业执照有效期起(上游 {@code license_stt})。
      *
-     * <p>★ 本页的说明列写的是「营业执照有效期(格式YYYYMMDD)」,与 {@link #licenseExpire} 的说明
-     * **逐字相同**(计划 §0.5:该页两行的说明重复)⇒ 本字段的确切语义**不明**。
-     * 按 §0.5 的裁定**原样透传、不加校验**(校验就是猜)。
+     * <p>★ <b>同一个字段名在两页的说明列写法不同</b>,两页逐字如下
+     * (转写件 {@code _txt-196236557.md:42-43} 与 {@code _txt-196236555.md:46-47}):
+     * <ul>
+     *   <li><b>本页(更新,196236557)</b>:{@code license_stt} 的说明是
+     *       「营业执照有效期(格式YYYYMMDD)」;{@code license_expire} 的说明是
+     *       「营业执照有效期(格式YYYYMMDD)<b>长期传20991231</b>」——
+     *       ⇒ 两行**不是同一句**,{@code license_expire} 那行多出「长期传20991231」。</li>
+     *   <li><b>创建页(196236555)</b>:同名两个字段的说明分别是
+     *       「营业执照<b>开始</b>(格式YYYYMMDD)」与「营业执照<b>结束</b>(格式YYYYMMDD)长期传20991231」
+     *       —— **明文写着开始 / 结束**。</li>
+     * </ul>
+     *
+     * <p><b>为什么仍读作「开始」</b>(两条互相独立的依据):① 本页 {@code license_expire} 那行带
+     * 「长期传20991231」——「长期」只在**结束**日期上讲得通,故同一行里的 {@code license_stt}
+     * 只能是**开始**;② 创建页对同名两个字段明文写「开始 / 结束」。
+     * 本页说明列含糊的原因是它把「营业执照有效期」当成了两个字段**共用的抬头**,而不是两行重复。
+     *
+     * <p>★ <b>但行为不变:原样透传、不做 {@code YYYYMMDD} 格式校验。</b>
+     * 注意这条理由与「语义不明」**无关**(那个理由已被上面推翻):本模块 50 多个进件字段
+     * **一个都不做格式校验**,单独给这一个字段加校验会让它成为唯一的例外,而上游加码或放宽格式
+     * 是预期内的事 —— 本地拒绝的代价是拒绝服务。
+     * (溯源:计划 §0.5 那行原把两行概括成「说明都是『营业执照有效期』(重复文案)」,
+     * 与**同一份计划** §0.3c 自己记的「{@code license_stt} | 营业执照开始」自相矛盾;
+     * 逐字转写件才是权威。主控 2026-09-23 已订正计划那行(R52),并明确**只推翻前提、
+     * 不推翻「不加校验」这个结论**。)
      */
     private String licenseStt;
 
-    /** 营业执照有效期止(上游 {@code license_expire})——「长期传20991231」。 */
+    /**
+     * 营业执照有效期止(上游 {@code license_expire})——「长期传20991231」。
+     *
+     * <p>本字段与 {@link #licenseStt} 的说明列在**两页上的写法差异**(含为何仍读作「止」)
+     * 逐字记在 {@link #licenseStt} 的 javadoc 里,那里是**唯一落点**,不要在这里复述第二份。
+     */
     private String licenseExpire;
 
     // ===== 结算信息 =====

+ 12 - 0
java/src/main/java/com/payment/platform/module/payment/leshouying/service/LsyOnboardingService.java

@@ -539,6 +539,18 @@ public class LsyOnboardingService {
      * 上游那边只会回一句笼统的「参数不合法」,从它看不出是哪个参数)。
      * <br>★ 与 {@link #updateMerchant} 的取舍**不同是有意的**:那边只校验两项,因为该页的
      * 「必填=是」与「增量更新」互相矛盾(裁定 R39/R40)。
+     * <br>★ <b>这六个 {@code label} 为什么是字面量而不是 {@link LsyMerchantRequiredFields#LABELS}</b>:
+     * 那张表是**创建页**(196236555)那 26 项的翻译表,**不覆盖**本页的六个字段 ——
+     * 实测 {@code mcht_aptitude} / {@code mcht_aptitude_note} / {@code store_Loca} /
+     * {@code mcht_Landuse} / {@code longitude} / {@code latitude} 六个键在
+     * {@code LsyMerchantRequiredFields} 里**命中数全是 0**(六个中文标签同样 0 命中)。
+     * ⇒ 在这里走 {@code LABELS.get(...)} 只会在运行时抛它自己那条
+     * {@code IllegalStateException}(「没登记标签」),所以取字面量,
+     * 与 {@link #createShop} 同款;**不要**为了「统一」把本页六个字段塞进那张表
+     * (那张表的 26 项与必填矩阵一一对应,塞进去会动到矩阵的覆盖面断言)。
+     * <br>★ {@code label} 一律**逐字**取该页说明列(含上游错字「营业地址维度」),
+     * 与 {@code LABELS} 那条「标签逐字取说明列」的规则同源 —— 照抄而不是顺手正字,
+     * 理由见下方 {@code latitude} 那一行旁边的注释。
      *
      * <p><b>【③ 组装:9 个键,键名照参数表逐字】</b>
      * {@code mchNoParams} 产出的 {@code merchant_no} + {@code trace_no},加配置的 {@code channel_id},

+ 6 - 0
java/src/test/java/com/payment/platform/module/payment/leshouying/service/LsyOnboardingServiceTest.java

@@ -2429,6 +2429,12 @@ class LsyOnboardingServiceTest {
         BusinessException report = assertThrows(BusinessException.class,
                 () -> service.reportQuery(MCH_NO), "入网状态腿缺凭据时必须被拒");
 
+        // 下面的 5 = `missingOnboardingCredentials()` 的**全部五项**(源码 `LeshouyingProperties:228-245`):
+        // channel-id / bd-id / channel-type / rate-code / onboarding-notify-url。
+        // ★ 不走「从实现取数」(`props.missingOnboardingCredentials().size()`):那会让期望值与
+        // 被测实现同源 —— 配置集合缩到 1 项时它也照样绿,而本用例要钉的正是「五项全缺都拦住」。
+        // 将来集合真的变了,红的是**两个**硬编码 5(本处与 `createMerchant_missingCredentials_throws400ListingAll`
+        // 的 `:1486`),两处一起红就是「集合变了」的指纹;只红一处才是断言写错了。
         for (BusinessException e : new BusinessException[]{update, commit, report}) {
             assertEquals(400, e.getCode(), "凭据缺失一律 400,实际: " + e.getMessage());
             // 文案必须是凭据闸那套:若这里是「商户号不能为空」,说明 400 来自 mchNoParams,