shinnosuke
2026-08-21 bc2efbdb52190fe2e7be9920bbed6902d4ee28aa
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package com.talentcard.server.business.portal;
 
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
 
import com.alibaba.fastjson.JSON;
import com.talentcard.server.business.DatabaseRows;
import com.talentcard.server.common.BusinessException;
import com.talentcard.server.common.ErrorCode;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
 
@Service
public class FinanceMerchantPortalService {
 
    private final JdbcTemplate jdbc;
 
    public FinanceMerchantPortalService(JdbcTemplate jdbc) {
        this.jdbc = jdbc;
    }
 
    @Transactional(readOnly = true)
    public Map<String, Object> detail(Long merchantId, Long talentId) {
        if (merchantId == null || merchantId <= 0) throw new BusinessException(ErrorCode.BAD_REQUEST, "金融机构信息不能为空");
        Map<String, Object> row = one("""
                select m.id, m.merchant_name, m.cover_url, m.service_label, m.address, m.contact_mobile, m.contact_name,
                       m.rights_text, m.merchant_rights_config,
                       m.longitude, m.latitude, m.status as merchant_status, detail_config.talent_levels,
                       detail_config.benefit_detail, detail_config.advisor_id, detail_config.advisor_name,
                       detail_config.advisor_department, detail_config.advisor_mobile, detail_config.advisor_service_time,
                       detail_config.advisor_available, detail_config.unavailable_reason, detail_config.status as detail_status
                from merchant m
                left join finance_service_detail detail_config on detail_config.merchant_id = m.id and detail_config.deleted = 0
                where m.id = ? and m.merchant_type_code = 'finance' and m.deleted = 0
                order by detail_config.id asc limit 1
                """, merchantId);
        boolean available = number(row.get("merchantStatus")) == 1 && (row.get("detailStatus") == null || number(row.get("detailStatus")) == 1);
        Map<String, Object> matchedRight = matchedRight(row.get("merchantRightsConfig"), activeCardLevel(talentId));
        Map<String, Object> result = new LinkedHashMap<>();
        result.put("merchantId", row.get("id"));
        result.put("merchantName", row.get("merchantName"));
        result.put("coverUrl", row.get("coverUrl"));
        result.put("benefitSummary", text(row.get("serviceLabel"), "请咨询服务专员"));
        result.put("applicableCards", text(matchedRight.get("tag"), text(row.get("talentLevels"), "请咨询服务专员")));
        result.put("address", text(row.get("address"), "暂未配置机构地址"));
        result.put("contactMobile", text(row.get("contactMobile"), ""));
        result.put("longitude", row.get("longitude"));
        result.put("latitude", row.get("latitude"));
        result.put("benefitDetail", text(matchedRight.get("detail"), text(row.get("benefitDetail"), text(row.get("rightsText"), "以服务专员说明为准"))));
        result.put("available", available);
        result.put("unavailableReason", available ? "" : text(row.get("unavailableReason"), "该金融服务当前不可用"));
        Map<String, Object> advisor = new LinkedHashMap<>();
        advisor.put("advisorId", row.get("advisorId"));
        advisor.put("name", text(row.get("advisorName"), text(row.get("contactName"), "金融服务专员")));
        advisor.put("department", text(row.get("advisorDepartment"), ""));
        advisor.put("mobile", text(row.get("advisorMobile"), text(row.get("contactMobile"), "")));
        advisor.put("serviceTime", text(row.get("advisorServiceTime"), ""));
        advisor.put("available", (row.get("advisorAvailable") == null ? !text(row.get("contactMobile"), "").isEmpty() : number(row.get("advisorAvailable")) == 1) && !text(row.get("advisorMobile"), text(row.get("contactMobile"), "")).isEmpty());
        result.put("advisor", advisor);
        return result;
    }
 
    private Map<String, Object> matchedRight(Object value, String cardLevel) {
        if (cardLevel.isBlank() || value == null) return Map.of();
        try {
            List<Map<String, Object>> rights = JSON.parseObject(String.valueOf(value), new com.alibaba.fastjson.TypeReference<>() {});
            if (rights != null) {
                for (Map<String, Object> right : rights) {
                    if (booleanValue(right.get("enabled")) && cardLevel.equals(text(right.get("level"), ""))) return right;
                }
            }
        } catch (RuntimeException ignored) {
            // Use the legacy finance detail fields when merchant rights are unavailable.
        }
        return Map.of();
    }
 
    private String activeCardLevel(Long talentId) {
        if (talentId == null || talentId <= 0) return "";
        List<Map<String, Object>> cards = jdbc.queryForList("""
                select card_level from talent_card
                where talent_id = ? and deleted = 0 and card_type = 'PERSONAL' and status = 1
                  and (valid_end is null or valid_end >= current_date)
                order by id desc limit 1
                """, talentId).stream().map(DatabaseRows::normalize).toList();
        return cards.isEmpty() ? "" : text(cards.get(0).get("cardLevel"), "");
    }
 
    private boolean booleanValue(Object value) {
        if (value instanceof Boolean bool) return bool;
        if (value instanceof Number number) return number.intValue() != 0;
        String result = text(value, "");
        return "true".equalsIgnoreCase(result) || "1".equals(result) || "yes".equalsIgnoreCase(result);
    }
 
    private Map<String, Object> one(String sql, Object... args) {
        List<Map<String, Object>> rows = jdbc.queryForList(sql, args).stream().map(DatabaseRows::normalize).toList();
        if (rows.isEmpty()) throw new BusinessException(ErrorCode.NOT_FOUND, "金融服务详情不存在");
        return rows.get(0);
    }
 
    private int number(Object value) {
        return value instanceof Number number ? number.intValue() : 0;
    }
 
    private String text(Object value, String fallback) {
        if (value == null) return fallback;
        String result = String.valueOf(value).trim();
        return result.isEmpty() ? fallback : result;
    }
}