From 75e20ed49063feac161beca13aba24147424d5a7 Mon Sep 17 00:00:00 2001
From: yeg <1347747024@qq.com>
Date: 星期四, 17 九月 2026 18:43:03 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/main'

---
 talent-card-server/src/main/java/com/talentcard/server/service/BenefitQuotaService.java |   32 +++++++++++++++++++++++++++-----
 1 files changed, 27 insertions(+), 5 deletions(-)

diff --git a/talent-card-server/src/main/java/com/talentcard/server/service/BenefitQuotaService.java b/talent-card-server/src/main/java/com/talentcard/server/service/BenefitQuotaService.java
index b0bc1b1..38fe3e3 100644
--- a/talent-card-server/src/main/java/com/talentcard/server/service/BenefitQuotaService.java
+++ b/talent-card-server/src/main/java/com/talentcard/server/service/BenefitQuotaService.java
@@ -381,9 +381,9 @@
         List<String> candidates = cardLevelCandidates(cardLevel, primary.sourceAreaType());
         try {
             List<Map<String, Object>> rights = JSON_MAPPER.readValue(config, RIGHTS_TYPE);
-            matched = matchingMerchantRight(rights, candidates, true);
+            matched = matchingMerchantRight(rights, candidates, true, primary.sourceAreaType());
             if (matched == null) {
-                disabledMatched = matchingMerchantRight(rights, candidates, false);
+                disabledMatched = matchingMerchantRight(rights, candidates, false, primary.sourceAreaType());
             }
         } catch (Exception exception) {
             throw new BusinessException(ErrorCode.INTERNAL_ERROR, "酒店商户权益配置格式不正确");
@@ -439,24 +439,46 @@
         return cardLevel == null || cardLevel.isBlank() ? List.of() : List.of(cardLevel);
     }
 
-    private Map<String, Object> matchingMerchantRight(List<Map<String, Object>> rights, List<String> candidates, boolean requireEnabled) {
+    private Map<String, Object> matchingMerchantRight(List<Map<String, Object>> rights, List<String> candidates, boolean requireEnabled, String sourceAreaType) {
         if (rights == null || rights.isEmpty() || candidates == null || candidates.isEmpty()) {
             return null;
         }
+        // 第一轮:完整等级名匹配,按“(本地)/(外地)”分开配置时命中对应地区的那一条。
         for (String candidate : candidates) {
             for (Map<String, Object> right : rights) {
                 if (requireEnabled && !booleanValue(right.get("enabled"))) {
                     continue;
                 }
                 String configured = text(right.get("level"));
-                if (candidate.equals(configured) || sameCardLevel(configured, candidate)) {
-                    return right;
+                if (candidate.equals(configured)) return right;
+            }
+        }
+        // 第二轮:退化成只比等级,但人才地区已知时不能用地区对不上的配置。
+        String area = normalizedSourceAreaType(sourceAreaType);
+        for (String candidate : candidates) {
+            for (Map<String, Object> right : rights) {
+                if (requireEnabled && !booleanValue(right.get("enabled"))) {
+                    continue;
                 }
+                String configured = text(right.get("level"));
+                if (!sameCardLevel(configured, candidate)) continue;
+                if (!areaMatchesConfiguredLevel(configured, area)) continue;
+                return right;
             }
         }
         return null;
     }
 
+    /** 人才地区已知时,带“(本地)/(外地)”后缀的商家配置必须与人才地区一致;没带后缀的配置不受限制。 */
+    private boolean areaMatchesConfiguredLevel(String configuredLevel, String area) {
+        if (area == null || area.isBlank()) return true;
+        String level = text(configuredLevel).toUpperCase(Locale.ROOT);
+        boolean configuredOutside = level.contains("外地") || level.contains("OUTSIDE");
+        boolean configuredLocal = level.contains("本地") || level.contains("LOCAL");
+        if (!configuredOutside && !configuredLocal) return true;
+        return "OUTSIDE".equals(area) ? configuredOutside : ("LOCAL".equals(area) && configuredLocal);
+    }
+
     private Object firstValue(Map<String, Object> values, String... keys) {
         for (String key : keys) {
             Object value = values.get(key);

--
Gitblit v1.7.1