shinnosuke
2026-08-28 103975b43a220ac76408b54ea0e81613f41df15f
又又更新
2个文件已修改
114 ■■■■■ 已修改文件
talent-card-server/src/main/java/com/talentcard/server/business/merchant/ManualConsumptionService.java 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
talent-card-server/src/test/java/com/talentcard/server/business/merchant/ManualConsumptionServiceTests.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
talent-card-server/src/main/java/com/talentcard/server/business/merchant/ManualConsumptionService.java
@@ -157,17 +157,23 @@
    }
    private boolean hasStructuredRightsConfig(Long merchantId) {
        List<Map<String, Object>> merchants = rows("select merchant_rights_config from merchant where id = ? and deleted = 0 limit 1", merchantId);
        if (merchants.isEmpty()) return false;
        Object raw = merchants.get(0).get("merchantRightsConfig");
        return raw != null && !string(raw).isBlank();
        return !rightsConfigs(merchantId).isEmpty();
    }
    private List<Map<String, Object>> configuredRules(Long merchantId, String cardLevel, String sourceAreaType) {
    private List<Map<String, Object>> rightsConfigs(Long merchantId) {
        List<Map<String, Object>> merchants = rows("select merchant_rights_config from merchant where id = ? and deleted = 0 limit 1", merchantId);
        if (merchants.isEmpty()) return List.of();
        Object raw = merchants.get(0).get("merchantRightsConfig");
        if (raw == null) {
            for (Map.Entry<String, Object> entry : merchants.get(0).entrySet()) {
                if (entry.getKey() != null && entry.getKey().toLowerCase().contains("rights")) {
                    raw = entry.getValue();
                    break;
                }
            }
        }
        if (raw == null || string(raw).isBlank()) return List.of();
        String json = raw instanceof byte[] bytes ? new String(bytes, java.nio.charset.StandardCharsets.UTF_8) : string(raw);
        List<Map<String, Object>> configs = new ArrayList<>();
        try {
            if (raw instanceof List<?> list) {
@@ -177,7 +183,7 @@
                    configs.add(value);
                }
            } else {
                for (Object item : JSON.parseArray(string(raw), Map.class)) if (item instanceof Map<?, ?> map) {
                for (Object item : JSON.parseArray(json, Map.class)) if (item instanceof Map<?, ?> map) {
                    Map<String, Object> value = new LinkedHashMap<>();
                    for (Map.Entry<?, ?> entry : map.entrySet()) value.put(String.valueOf(entry.getKey()), entry.getValue());
                    configs.add(value);
@@ -186,7 +192,11 @@
        } catch (Exception ignored) {
            return List.of();
        }
        return configs.stream()
        return configs;
    }
    private List<Map<String, Object>> configuredRules(Long merchantId, String cardLevel, String sourceAreaType) {
        return rightsConfigs(merchantId).stream()
                .filter(right -> booleanValue(right.get("enabled"))
                        && configuredStoreConsumptionEnabled(right)
                        && matchesConfiguredLevel(string(right.get("level")), cardLevel, sourceAreaType))
@@ -374,32 +384,53 @@
    }
    private String benefitText(Long merchantId, String cardLevel, String sourceAreaType) {
        String configuredDescription = consumeDescFromRights(merchantId, cardLevel, sourceAreaType);
        if (!configuredDescription.isBlank()) return configuredDescription;
        List<Map<String, Object>> benefits = rows("""
                select card_level, benefit_text from merchant_card_benefit
                where merchant_id = ? and status = 1 order by sort_no desc, id desc
                """, merchantId);
        String configuredDescription = configuredRules(merchantId, cardLevel, sourceAreaType).stream()
                .map(rule -> string(rule.get("consumeDesc")))
                .filter(value -> !value.isBlank())
                .findFirst()
                .orElse("");
        if (configuredDescription.isBlank()) {
            configuredDescription = configuredRules(merchantId, cardLevel, sourceAreaType).stream()
                    .map(rule -> string(rule.get("merchantDetail")))
                    .filter(value -> !value.isBlank())
                    .findFirst()
                    .orElse("");
        }
        if (configuredDescription.isBlank()) {
            configuredDescription = configuredRules(merchantId, cardLevel, sourceAreaType).stream()
                    .map(rule -> string(rule.get("benefitText")))
                    .filter(value -> !value.isBlank())
                    .findFirst()
                    .orElse("");
        }
        if (!configuredDescription.isBlank()) return configuredDescription;
        return benefits.stream().filter(benefit -> matchesCardLevel(string(benefit.get("cardLevel")), cardLevel))
                .map(benefit -> string(benefit.get("benefitText"))).findFirst().orElse("以当前商户到店消费规则为准");
    }
    private String consumeDescFromRights(Long merchantId, String cardLevel, String sourceAreaType) {
        List<Map<String, Object>> configs = rightsConfigs(merchantId).stream()
                .filter(right -> booleanValue(right.get("enabled")))
                .toList();
        String description = firstRightsText(configs, cardLevel, sourceAreaType, "consumeDesc");
        if (!description.isBlank()) return description;
        return firstRightsText(configs, cardLevel, sourceAreaType, "detail");
    }
    private String firstRightsText(List<Map<String, Object>> configs, String cardLevel, String sourceAreaType, String field) {
        for (Map<String, Object> right : configs) {
            if (!matchesConfiguredLevel(string(right.get("level")), cardLevel, sourceAreaType)) continue;
            String text = string(right.get(field)).trim();
            if (!text.isBlank()) return text;
        }
        if (!sourceAreaKnown(sourceAreaType)) {
            for (Map<String, Object> right : configs) {
                if (!matchesCardLevel(string(right.get("level")), cardLevel)) continue;
                String text = string(right.get(field)).trim();
                if (!text.isBlank()) return text;
            }
        }
        return "";
    }
    private boolean sourceAreaKnown(String sourceAreaType) {
        return localArea(sourceAreaType) || outsideArea(sourceAreaType);
    }
    private boolean localArea(String sourceAreaType) {
        String area = string(sourceAreaType).trim().toUpperCase();
        return area.contains("LOCAL") || area.contains("本地");
    }
    private boolean outsideArea(String sourceAreaType) {
        String area = string(sourceAreaType).trim().toUpperCase();
        return area.contains("OUTSIDE") || area.contains("外地");
    }
    /** Build the displayed benefit from the same structured fields used for pricing. */
@@ -420,10 +451,14 @@
        return benefitText(merchantId, cardLevel, "");
    }
    String benefitTextForMerchant(Long merchantId, String cardLevel, String sourceAreaType) {
        return benefitText(merchantId, cardLevel, sourceAreaType);
    }
    boolean matchesConfiguredLevel(String configured, String actual, String sourceAreaType) {
        if (!"EXCELLENT".equals(normalizedCardLevel(actual))) return matchesCardLevel(configured, actual);
        String configuredUpper = configured.trim().toUpperCase();
        String areaUpper = sourceAreaType.trim().toUpperCase();
        String areaUpper = string(sourceAreaType).trim().toUpperCase();
        if (configuredUpper.contains("本地") || configuredUpper.contains("LOCAL")) {
            return areaUpper.contains("LOCAL") || areaUpper.contains("本地");
        }
talent-card-server/src/test/java/com/talentcard/server/business/merchant/ManualConsumptionServiceTests.java
@@ -126,6 +126,29 @@
        assertThat(service.matchesConfiguredLevel("卓越人才卡(本地)", "卓越人才卡", "LOCAL")).isTrue();
    }
    @Test
    void benefitTextUsesConfiguredConsumeDescForCardLevel() {
        jdbc.execute("""
                create table merchant_card_benefit (
                    id bigint auto_increment primary key,
                    merchant_id bigint not null,
                    card_level varchar(64),
                    benefit_text varchar(500),
                    status tinyint not null default 1,
                    sort_no int not null default 0
                )
                """);
        jdbc.update("insert into merchant(id, merchant_rights_config) values (?, ?)", 88L,
                "[{\"level\":\"卓越人才卡(本地)\",\"enabled\":true,\"storeConsume\":true,\"consumeEnabled\":true,\"consumeDesc\":\"local-excellent-desc\"},"
                        + "{\"level\":\"卓越人才卡(外地)\",\"enabled\":true,\"storeConsume\":true,\"consumeEnabled\":true,\"consumeDesc\":\"outside-excellent-desc\"},"
                        + "{\"level\":\"杰出人才卡\",\"enabled\":true,\"storeConsume\":true,\"consumeEnabled\":true,\"consumeDesc\":\"outstanding-desc\"}]");
        assertThat(service.benefitTextForMerchant(88L, "卓越人才卡", "OUTSIDE")).isEqualTo("outside-excellent-desc");
        assertThat(service.benefitTextForMerchant(88L, "卓越人才卡", "LOCAL")).isEqualTo("local-excellent-desc");
        assertThat(service.benefitTextForMerchant(88L, "杰出人才卡")).isEqualTo("outstanding-desc");
        assertThat(service.benefitTextForMerchant(88L, "卓越人才卡")).isEqualTo("local-excellent-desc");
    }
    private Map<String, Object> configuredRight(String level, String discount) {
        Map<String, Object> right = new LinkedHashMap<>();
        right.put("level", level);