shinnosuke
2026-08-04 ff4babc2be1809f6ce03eb48c23f55920f447125
talent-card-server/src/main/java/com/talentcard/server/business/admin/MerchantSettlementAdminService.java
@@ -1,5 +1,6 @@
package com.talentcard.server.business.admin;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -20,11 +21,20 @@
    public MerchantSettlementAdminService(JdbcTemplate jdbc, HuifuMerchantWithdrawalService withdrawalService) { this.jdbc = jdbc; this.withdrawalService = withdrawalService; }
    @Transactional(readOnly = true)
    public PageResult<Map<String, Object>> onboardings(int page, int size) { return page("select a.*, m.merchant_name, s.store_name from merchant_onboarding_application a join merchant m on m.id = a.merchant_id join merchant_store s on s.id = a.store_id", "select count(*) from merchant_onboarding_application", page, size); }
    public PageResult<Map<String, Object>> onboardings(int page, int size, String merchantName, String contactMobile, String merchantType, String status, String startDate, String endDate) {
        return page("select a.*, m.merchant_name, m.merchant_type, m.contact_mobile, s.store_name from merchant_onboarding_application a join merchant m on m.id = a.merchant_id join merchant_store s on s.id = a.store_id", "select count(*) from merchant_onboarding_application a join merchant m on m.id = a.merchant_id join merchant_store s on s.id = a.store_id", "a", page, size, merchantName, contactMobile, merchantType, status, startDate, endDate);
    }
    @Transactional(readOnly = true)
    public PageResult<Map<String, Object>> bankCards(int page, int size) { return page("select c.*, m.merchant_name, s.store_name from merchant_bank_card c join merchant m on m.id = c.merchant_id join merchant_store s on s.id = c.store_id", "select count(*) from merchant_bank_card", page, size); }
    public PageResult<Map<String, Object>> bankCards(int page, int size, String merchantName, String contactMobile, String merchantType, String status, String startDate, String endDate) {
        return page("select c.*, m.merchant_name, m.merchant_type, m.contact_mobile, s.store_name from merchant_bank_card c join merchant m on m.id = c.merchant_id join merchant_store s on s.id = c.store_id", "select count(*) from merchant_bank_card c join merchant m on m.id = c.merchant_id join merchant_store s on s.id = c.store_id", "c", page, size, merchantName, contactMobile, merchantType, status, startDate, endDate);
    }
    @Transactional(readOnly = true)
    public PageResult<Map<String, Object>> withdrawals(int page, int size) { return page("select w.*, c.bank_name, c.card_masked, m.merchant_name, s.store_name from merchant_withdrawal w join merchant_bank_card c on c.id = w.bank_card_id join merchant m on m.id = w.merchant_id join merchant_store s on s.id = w.store_id", "select count(*) from merchant_withdrawal", page, size); }
    public PageResult<Map<String, Object>> withdrawals(int page, int size, String merchantName, String contactMobile, String merchantType, String status, String startDate, String endDate) {
        String available = "greatest(0, coalesce((select sum(o.pay_amount) from benefit_order o where o.merchant_id = w.merchant_id and (o.store_id is null or o.store_id = w.store_id) and o.order_status = 1 and o.verify_status = 1 and o.deleted = 0), 0) - coalesce((select sum(w2.amount_cents) from merchant_withdrawal w2 where w2.merchant_id = w.merchant_id and w2.store_id = w.store_id and w2.status in ('pending', 'processing', 'paid')), 0))";
        String select = "select w.*, c.bank_name, c.card_masked, m.merchant_name, m.merchant_type, m.contact_mobile, s.store_name, " + available + " as available_amount_cents from merchant_withdrawal w join merchant_bank_card c on c.id = w.bank_card_id join merchant m on m.id = w.merchant_id join merchant_store s on s.id = w.store_id";
        String count = "select count(*) from merchant_withdrawal w join merchant_bank_card c on c.id = w.bank_card_id join merchant m on m.id = w.merchant_id join merchant_store s on s.id = w.store_id";
        return page(select, count, "w", page, size, merchantName, contactMobile, merchantType, status, startDate, endDate);
    }
    @Transactional public Map<String, Object> reviewOnboarding(Long id, String status, String reason, String huifuId) { return reviewOnboardingInternal(id, status, reason, huifuId); }
    @Transactional public Map<String, Object> reviewBankCard(Long id, String status, String reason, String tokenNo) { return reviewBankCardInternal(id, status, reason, tokenNo); }
@@ -35,7 +45,27 @@
    private String reviewStatus(String status) { String value=status==null?"":status.trim().toLowerCase(); if(!List.of("approved","rejected").contains(value))throw new BusinessException(ErrorCode.BAD_REQUEST,"Invalid review status");return value; }
    private String normalizeWithdrawalStatus(String status) { String value=status==null?"":status.trim().toLowerCase(); if(!List.of("paid","failed").contains(value))throw new BusinessException(ErrorCode.BAD_REQUEST,"Invalid withdrawal status");return value; }
    private PageResult<Map<String, Object>> page(String query, String count, int page, int size) { int current = Math.max(1, page); int limit = Math.min(Math.max(1, size), 100); List<Map<String, Object>> values = rows(query + " order by id desc limit ? offset ?", limit, (current - 1) * limit); Long total = jdbc.queryForObject(count, Long.class); return new PageResult<>(values, current, limit, total == null ? 0 : total); }
    private PageResult<Map<String, Object>> page(String query, String count, String tableAlias, int page, int size, String merchantName, String contactMobile, String merchantType, String status, String startDate, String endDate) {
        int current = Math.max(1, page);
        int limit = Math.min(Math.max(1, size), 100);
        StringBuilder where = new StringBuilder(" where 1 = 1");
        List<Object> args = new ArrayList<>();
        addLike(where, args, "m.merchant_name", merchantName);
        addLike(where, args, "m.contact_mobile", contactMobile);
        addEqual(where, args, "m.merchant_type", merchantType);
        addEqual(where, args, tableAlias + ".status", status);
        addDate(where, args, tableAlias + ".created_at", startDate, true);
        addDate(where, args, tableAlias + ".created_at", endDate, false);
        List<Object> rowArgs = new ArrayList<>(args);
        rowArgs.add(limit);
        rowArgs.add((current - 1) * limit);
        List<Map<String, Object>> values = rows(query + where + " order by " + tableAlias + ".id desc limit ? offset ?", rowArgs.toArray());
        Long total = jdbc.queryForObject(count + where, Long.class, args.toArray());
        return new PageResult<>(values, current, limit, total == null ? 0 : total);
    }
    private void addLike(StringBuilder where, List<Object> args, String column, String value) { if (value != null && !value.trim().isEmpty()) { where.append(" and ").append(column).append(" like ?"); args.add("%" + value.trim() + "%"); } }
    private void addEqual(StringBuilder where, List<Object> args, String column, String value) { if (value != null && !value.trim().isEmpty()) { where.append(" and ").append(column).append(" = ?"); args.add(value.trim()); } }
    private void addDate(StringBuilder where, List<Object> args, String column, String value, boolean start) { if (value != null && value.matches("\\d{4}-\\d{2}-\\d{2}")) { where.append(" and ").append(column).append(start ? " >= ?" : " < date_add(?, interval 1 day)"); args.add(value); } }
    private Map<String, Object> update(String table, Long id, String status, String reason, String label) {
        String value = status == null ? "" : status.trim().toLowerCase();
        if (!List.of("approved", "rejected", "paid", "failed").contains(value)) throw new BusinessException(ErrorCode.BAD_REQUEST, "审核状态无效");