From 242917765d2711b723e98764396054acef2a7297 Mon Sep 17 00:00:00 2001
From: yeg <1347747024@qq.com>
Date: 星期三, 16 九月 2026 00:47:50 +0800
Subject: [PATCH] feat(merchant): 分阶段开通对所有商户生效

---
 talent-card-server/src/main/java/com/talentcard/server/business/merchant/MerchantOnboardingProgressService.java |   38 +++++++++++++++++++++++++++-----------
 1 files changed, 27 insertions(+), 11 deletions(-)

diff --git a/talent-card-server/src/main/java/com/talentcard/server/business/merchant/MerchantOnboardingProgressService.java b/talent-card-server/src/main/java/com/talentcard/server/business/merchant/MerchantOnboardingProgressService.java
index 07fe25b..69ba5eb 100644
--- a/talent-card-server/src/main/java/com/talentcard/server/business/merchant/MerchantOnboardingProgressService.java
+++ b/talent-card-server/src/main/java/com/talentcard/server/business/merchant/MerchantOnboardingProgressService.java
@@ -16,8 +16,6 @@
 /** Six independent evidence-backed stages; provider calls never hold application row locks. */
 @Service
 public class MerchantOnboardingProgressService {
-    /** 分阶段进度的灰度门槛;03 票把它换成通用规则时一并删除。 */
-    public static final String RECOVERY_HUIFU_ID = "6666000241335656";
     private static final Map<String,String> LABELS = new LinkedHashMap<>();
     static {
         LABELS.put("basic", "基础审核"); LABELS.put("wechat", "微信支付");
@@ -29,20 +27,28 @@
     public MerchantOnboardingProgressService(JdbcTemplate jdbc, HuifuOnboardingProgressGateway gateway) { this.jdbc=jdbc; this.gateway=gateway; }
 
     /**
-     * 分阶段进度当前只对指定存量商户放行。
+     * 分阶段进度适用于「已关联结算银行卡、且未被整体拒绝」的申请。
      *
-     * <p><b>这仍是一道灰度门槛,不是通用规则。</b>把判断换成「有结算卡且未被拒绝」会同时给所有商户
-     * 切换行为:进件失败不再释放银行卡(`MerchantOnboardingRetryReleaseTests`)、回调改走分阶段刷新
-     * (`MerchantSettlementCallbackIdempotencyTests`),共 5 个测试会红。那是策略变更,属于 03 票
-     * 「分阶段手动推进 + 局部失败保留原商户号和银行卡」,不在 04 的清理范围内。
+     * <p>原先这里按 huifu_id 白名单只放行一张指定存量商户,新商户走不进这套视图。现在按申请自身的
+     * 状态判断:银行卡关联是分阶段视图核实原卡的前提({@code application()} 也用它做条件);
+     * 而被拒绝的申请仍留在旧的单状态模型,商户端才有重新提交的入口。
+     *
+     * <p>这一条同时决定「进件失败后不重建商户与银行卡」的适用范围:支持的申请走局部刷新与重试,
+     * 不支持的才允许关闭重来。旧策略里「通道配置失败就释放银行卡、让商户整单重提」已被规格
+     * 明确取代——基本进件成功后要保留原商户号和银行卡。
      */
-    public boolean supports(Map<String,Object> application) { return RECOVERY_HUIFU_ID.equals(text(application.get("providerHuifuId"))); }
+    public boolean supports(Map<String,Object> application) {
+        return application.get("initialBankCardId") != null && !"rejected".equals(text(application.get("status")));
+    }
 
     public Map<String,Object> view(Long id) { return view(application(id)); }
 
     @org.springframework.transaction.annotation.Transactional(propagation = org.springframework.transaction.annotation.Propagation.NOT_SUPPORTED)
     public Map<String,Object> refresh(Long applicationId, boolean retry) {
         Map<String,Object> application=application(applicationId);
+        // 被拒绝的申请不归分阶段模型管:刷下去会把它从 rejected 翻回 pending,商户端的
+        // 「重新提交」入口就没了(supports() 对 rejected 返回 false,正是为了让出那个入口)。
+        if (!supports(application)) return view(application);
         jdbc.update("insert ignore into merchant_onboarding_progress(application_id,stages_json) values (?, '{}')", applicationId);
         String owner=UUID.randomUUID().toString();
         if(jdbc.update("update merchant_onboarding_progress set sync_owner=?,sync_until=date_add(now(),interval 5 minute) where application_id=? and (sync_owner is null or sync_until<now())", owner, applicationId)==0) return view(application);
@@ -123,11 +129,17 @@
                     advanceDelay(applicationId,text(application.get("providerHuifuId")),owner,stages,retry);
                 }
                 jdbc.update("update merchant_onboarding_progress set stages_json=? where application_id=? and sync_owner=?",JSON.toJSONString(stages),applicationId,owner);
+                // 基本资料被通道驳回时要落到 rejected:一是让商户端出现「重新提交」入口(supports() 对
+                // rejected 返回 false,交回旧的单状态模型),二是别把一次明确拒绝一直显示成「审核中」。
+                // 后续配置失败不算拒绝——那种情况保留原商户号和银行卡,局部重试即可。
+                boolean basicRejected = "failed".equals(text(stages.get("basic")));
+                String applicationStatus = basicRejected ? "rejected" : complete(stages) ? "approved" : "pending";
                 jdbc.update("""
                         update merchant_onboarding_application a join merchant_onboarding_progress p on p.application_id=a.id
                         set a.status=?,a.reviewed_at=case when ? then now() else null end
                         where a.id=? and p.sync_owner=?
-                        """,complete(stages) ? "approved" : "pending",complete(stages),applicationId,owner);
+                        """,applicationStatus,!"pending".equals(applicationStatus),applicationId,owner);
+                if (basicRejected) jdbc.update("update merchant_onboarding_application set reject_reason=? where id=?","基本资料审核未通过,请核对资料后重新提交",applicationId);
             }
         } catch (RuntimeException exception) {
             jdbc.update("update merchant_onboarding_progress set sync_error=? where application_id=? and sync_owner=?","查询结果暂未确认,已保留最后有效进度,请稍后刷新",applicationId,owner);
@@ -225,10 +237,14 @@
             progress.add(Map.of("key",entry.getKey(),"label",entry.getValue(),"status",status,"reason",stageReason(entry.getKey(),status),
                     "qrCode", "realname".equals(entry.getKey()) ? text(stages.get("realnameQr")) : ""));
         }
+        // 被通道明确驳回基本资料的申请仍显示 rejected(并带通道给的驳回原因),不能被阶段计算
+        // 盖成 pending——那样商户端看不到「重新提交」。
+        boolean rejected = "rejected".equals(text(application.get("status")));
         result.put("stages",progress); result.put("reason","请刷新进度,核实原申请与各项能力");
         result.put("retryable", "failed".equals(stages.get("delay")));
-        result.put("status",complete(stages) ? "approved" : "pending");
-        result.put("reason",complete(stages) ? "收款能力已核实,沿用原商户号和结算银行卡" : "请刷新进度核实各项能力,并按待办理项补齐缺失能力");
+        result.put("status",rejected ? "rejected" : complete(stages) ? "approved" : "pending");
+        result.put("reason",rejected ? text(application.get("rejectReason"))
+                : complete(stages) ? "收款能力已核实,沿用原商户号和结算银行卡" : "请刷新进度核实各项能力,并按待办理项补齐缺失能力");
         return result;
     }
 

--
Gitblit v1.7.1