shinnosuke
2026-09-17 38dd07dd9879924e40cdffb75384d5f6bc4669b4
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);