longz
2026-07-30 d83061ad5d5088eb32c71c32d21dd5db278d503a
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/util/task/TaskUtil.java
@@ -13,6 +13,7 @@
import com.ruoyi.account.api.model.TAppUserIntegralChange;
import com.ruoyi.chargingPile.api.feignClient.ChargingGunClient;
import com.ruoyi.chargingPile.api.feignClient.SiteClient;
import com.ruoyi.chargingPile.api.model.Partner;
import com.ruoyi.chargingPile.api.model.Site;
import com.ruoyi.chargingPile.api.model.TChargingGun;
import com.ruoyi.common.core.domain.R;
@@ -39,10 +40,13 @@
import com.ruoyi.other.api.vo.ExchangeCodeConsumeResultVO;
import com.ruoyi.payment.api.feignClient.AliPaymentClient;
import com.ruoyi.payment.api.feignClient.H5AliPaymentClient;
import com.ruoyi.payment.api.feignClient.IcbcPaymentClient;
import com.ruoyi.payment.api.feignClient.WxPaymentClient;
import com.ruoyi.payment.api.model.RefundReq;
import com.ruoyi.payment.api.model.RefundResp;
import com.ruoyi.payment.api.model.WxPaymentRefundModel;
import com.ruoyi.payment.api.vo.IcbcRefundReq;
import com.ruoyi.payment.api.vo.IcbcRefundResp;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
@@ -140,6 +144,9 @@
    private WxPaymentClient wxPaymentClient;
    @Resource
    private IcbcPaymentClient icbcPaymentClient;
    @Resource
    private AliPaymentClient aliPaymentClient;
    @Resource
    private H5AliPaymentClient h5AliPaymentClient;
@@ -188,6 +195,12 @@
        BigDecimal thirdPayAmount = money(order.getThirdPayAmount());
        if (thirdPayAmount.compareTo(BigDecimal.ZERO) > 0) {
            return thirdPayAmount;
        }
        if ("ICBC".equalsIgnoreCase(order.getSourceName())) {
            return money(order.getRechargeAmount())
                    .subtract(money(order.getBalancePayAmount()))
                    .max(BigDecimal.ZERO)
                    .setScale(2, RoundingMode.HALF_UP);
        }
        if (Integer.valueOf(3).equals(order.getPayMethod())) {
            return money(order.getRechargeAmount());
@@ -266,7 +279,7 @@
    @Scheduled(fixedRate = 1000 * 60)
    public void taskOneMinutes() {
        if(null != port && port == 5400){
        if (isScheduledTaskPort(port)) {
            List<TChargingOrder> upStatusChargingOrder = chargingOrderService.findUpStatusChargingOrder();
            log.info("定时任务执行,查询需要手动修改状态的订单数量:{}", upStatusChargingOrder.size());
            for (TChargingOrder order : upStatusChargingOrder) {
@@ -284,7 +297,7 @@
    //十分钟循环执行的定时任务
    @Scheduled(fixedRate = 1000 * 60 * 10)
    public void taskTenMinutes() {
        if(null != port && port == 5400){
        if (isScheduledTaskPort(port)) {
            List<TChargingOrder> failedStartupOrder = chargingOrderService.findFailedStartupOrder();
            log.info("定时任务执行,查询到启动失败的订单数量:{}", failedStartupOrder.size());
            for (TChargingOrder order : failedStartupOrder) {
@@ -411,7 +424,7 @@
    //定时任务添加结算账单汇总数据
    @Scheduled(cron = "0 30 0 * * ?")
    public void taskMonth() {
        if(null != port && port == 5400){
        if (isScheduledTaskPort(port)) {
            //推送三方引流平台数据
            pushOrderDrainagePlatform();
            //添加充电算账单汇总数据
@@ -424,7 +437,7 @@
    // 每个月最后一天23点执行的定时任务
    @Scheduled(cron = "0 0 23 * * ?")
    public void taskLastDay() {
        if(null != port && port == 5400){
        if (isScheduledTaskPort(port)) {
            try {
                int dayOfMonth = LocalDate.now().getDayOfMonth();
                int lastDayOfMonth = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth()).getDayOfMonth();
@@ -447,6 +460,10 @@
    public void onApplicationEvent(WebServerInitializedEvent event) {
        port = event.getWebServer().getPort();
        System.out.println("端口号:" + port);
    }
    static boolean isScheduledTaskPort(Integer serverPort) {
        return Integer.valueOf(5400).equals(serverPort) || Integer.valueOf(9400).equals(serverPort);
    }
@@ -789,28 +806,24 @@
                        //开始构建退款费用
                        refundAmount = refundAmount.setScale(2, RoundingMode.HALF_EVEN);
                        BigDecimal refundableThirdPayAmount = getRefundableThirdPayAmount(order);
                        BigDecimal refundableAmount = refundableThirdPayAmount.add(money(order.getBalancePayAmount())).setScale(2, RoundingMode.HALF_UP);
                        BigDecimal remainingThirdAmount = refundableThirdPayAmount
                                .subtract(money(order.getThirdRefundAmount())).max(BigDecimal.ZERO);
                        BigDecimal remainingBalanceAmount = money(order.getBalancePayAmount())
                                .subtract(money(order.getBalanceRefundAmount())).max(BigDecimal.ZERO);
                        BigDecimal refundableAmount = remainingThirdAmount.add(remainingBalanceAmount).setScale(2, RoundingMode.HALF_UP);
                        // 白名单全部免费只记录预估预充金额,实际渠道退款金额保持0,防止补偿任务重复发起退款。
                        BigDecimal recordedRefundAmount = isWhitelistAllFreeOrder(order) ? money(order.getRechargeAmount()) : refundAmount;
                        BigDecimal channelRefundAmount = isWhitelistAllFreeOrder(order)
                                ? BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP)
                                : refundAmount.min(refundableAmount).setScale(2, RoundingMode.HALF_UP);
                        Integer rechargePaymentType = order.getRechargePaymentType();
                        Integer payMethod = order.getPayMethod();
                        BigDecimal thirdRefundAmount = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
                        BigDecimal balanceRefundAmount = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
                        if (Integer.valueOf(1).equals(payMethod)) {
                            balanceRefundAmount = channelRefundAmount.min(money(order.getBalancePayAmount())).setScale(2, RoundingMode.HALF_UP);
                        } else if (Integer.valueOf(2).equals(payMethod)) {
                            thirdRefundAmount = channelRefundAmount.min(refundableThirdPayAmount).setScale(2, RoundingMode.HALF_UP);
                            balanceRefundAmount = channelRefundAmount.subtract(thirdRefundAmount).min(money(order.getBalancePayAmount())).setScale(2, RoundingMode.HALF_UP);
                        } else {
                            thirdRefundAmount = channelRefundAmount.min(refundableThirdPayAmount).setScale(2, RoundingMode.HALF_UP);
                        }
                        BigDecimal thirdRefundAmount = channelRefundAmount.min(remainingThirdAmount).setScale(2, RoundingMode.HALF_UP);
                        BigDecimal balanceRefundAmount = channelRefundAmount.subtract(thirdRefundAmount)
                                .min(remainingBalanceAmount).setScale(2, RoundingMode.HALF_UP);
                        if (channelRefundAmount.compareTo(BigDecimal.ZERO) > 0) {
                            refundAmount = thirdRefundAmount.add(balanceRefundAmount).setScale(2, RoundingMode.HALF_UP);
                            order.setThirdRefundAmount(thirdRefundAmount);
                            order.setBalanceRefundAmount(balanceRefundAmount);
                            order.setThirdRefundAmount(money(order.getThirdRefundAmount()).add(thirdRefundAmount));
                            order.setBalanceRefundAmount(money(order.getBalanceRefundAmount()).add(balanceRefundAmount));
                            order.setRefundAmount(recordedRefundAmount);
                            order.setRefundStatus(refundAmount.compareTo(BigDecimal.ZERO) > 0 ? 1 : 2);
                            chargingOrderService.updateById(order);
@@ -840,6 +853,25 @@
                                order.setRefundStatus(2);
                                order.setRefundTime(LocalDateTime.now());
                                chargingOrderService.updateById(order);
                            } else if ("ICBC".equalsIgnoreCase(order.getSourceName())) {
                                IcbcRefundReq req = new IcbcRefundReq();
                                req.setOutTradeNo(order.getCode());
                                req.setOrderId(order.getRechargeSerialNumber());
                                req.setOutRefundNo(chargingOrderRefund.getRefundCode());
                                req.setRefundAmount(thirdRefundAmount);
                                req.setTotalAmount(getRefundableThirdPayAmount(order));
                                req.setReason("充电完成退款");
                                R<IcbcRefundResp> result = icbcPaymentClient.refund(req);
                                IcbcRefundResp resp = result == null ? null : result.getData();
                                if (result != null && result.getCode() == 200 && resp != null && "SUCCESS".equals(resp.getStatus())) {
                                    chargingOrderRefundService.save(chargingOrderRefund);
                                    String refundId = StringUtils.isNotEmpty(resp.getRefundId()) ? resp.getRefundId() : resp.getOutRefundNo();
                                    chargingOrderService.chargingOrderStartupFailureWxRefund(
                                            chargingOrderRefund.getRefundCode(), refundId, "SUCCESS", resp.getRefundTime());
                                } else {
                                    log.error("工行充电完成退款失败,订单号:{},退款单号:{},返回:{}",
                                            order.getCode(), chargingOrderRefund.getRefundCode(), result == null ? null : result.getMsg());
                                }
                            } else if (1 == rechargePaymentType) {
                                WxPaymentRefundModel model = new WxPaymentRefundModel();
                                model.setOut_trade_no(order.getCode());
@@ -961,29 +993,36 @@
     * 添加充电算账单汇总数据
     */
    public void addChargingSettlementBill(){
        int day = LocalDate.now().getDayOfMonth();
        int lastDay = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth()).getDayOfMonth();
        if (2 <= day && day <= lastDay) {
            refreshChargingSettlementBill(LocalDate.now());
        }
    }
    /**
     * 主动刷新指定月份的充电结算账单。只重建该月未出账数据,已出账数据不受影响。
     */
    public synchronized void refreshChargingSettlementBill(LocalDate billingMonth){
        try {
            int day = LocalDate.now().getDayOfMonth();
            int lastDay = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth()).getDayOfMonth();
            //时间在当月的2号到当月的最后一天才执行汇总数据和生成新的汇总数据(中间有修改数据的情况)
            if(2 <= day && day <= lastDay){
                // 获取上个月的开始和结束日期
                LocalDate firstDayOfLastMonth = LocalDate.now().minusMonths(1).
                        withDayOfMonth(2);
                String string = firstDayOfLastMonth.toString();
            if (billingMonth == null) {
                throw new IllegalArgumentException("账单月份不能为空");
            }
                LocalDate firstDayOfBillingMonth = billingMonth.withDayOfMonth(2);
                String string = firstDayOfBillingMonth.toString();
                // 将-替换为空字符串
                string = string.replace("-", "");
                //上个月
                String lastMonth = LocalDate.now().minusMonths(1).format(DateTimeFormatter.ofPattern("yyyy-MM"));
                String targetMonth = billingMonth.format(DateTimeFormatter.ofPattern("yyyy-MM"));
                //统计数据的开始时间
                String startTime = lastMonth + "-01 00:00:00";
                String startTime = targetMonth + "-01 00:00:00";
                //统计数据的结束时间
                int lasDay = LocalDate.now().minusMonths(1).with(TemporalAdjusters.lastDayOfMonth()).getDayOfMonth();
                String endTime = lastMonth + "-" + String.format("%02d", lasDay) + " 23:59:59";
                LocalDateTime createTime = LocalDateTime.parse(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM")) + "-02 00:00:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                int lastDay = billingMonth.with(TemporalAdjusters.lastDayOfMonth()).getDayOfMonth();
                String endTime = targetMonth + "-" + String.format("%02d", lastDay) + " 23:59:59";
                LocalDateTime createTime = LocalDateTime.now();
                //删除之前生成的汇总数据,在添加最新的汇总数据
                String format = firstDayOfLastMonth.format(DateTimeFormatter.ofPattern("yyyy-MM"));
                String format = firstDayOfBillingMonth.format(DateTimeFormatter.ofPattern("yyyy-MM"));
                chargingSettlementBillService.remove(new QueryWrapper<TChargingSettlementBill>().eq("status", 1).last(" and DATE_FORMAT(billing_cycle, '%Y-%m') = '" + format + "'"));
                //循环生成按照开始时间和结束时间分别统计的汇总数据
@@ -996,7 +1035,7 @@
                            .collect(Collectors.joining()); // 将其连接成一个字符串
                    chargingSettlementBill.setSiteId(0);
                    chargingSettlementBill.setStatisticalDateType(i);
                    chargingSettlementBill.setBillingCycle(firstDayOfLastMonth);
                    chargingSettlementBill.setBillingCycle(firstDayOfBillingMonth);
                    chargingSettlementBill.setStatus(1);
                    chargingSettlementBill.setCode("JSD"+string+randomDigits);
@@ -1031,7 +1070,7 @@
                                .collect(Collectors.joining()); // 将其连接成一个字符串
                        chargingSettlementBill1.setSiteId(Integer.valueOf(map.get("siteId").toString()));
                        chargingSettlementBill1.setStatisticalDateType(i);
                        chargingSettlementBill1.setBillingCycle(firstDayOfLastMonth);
                        chargingSettlementBill1.setBillingCycle(firstDayOfBillingMonth);
                        chargingSettlementBill1.setStatus(1);
                        chargingSettlementBill1.setCode("JSD"+string+randomDigits1);
                        chargingSettlementBill1.setChargingDuration(charging_duration);
@@ -1073,9 +1112,9 @@
                    chargingSettlementBillService.save(chargingSettlementBill);
                    chargingSettlementBillService.saveBatch(list);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("生成{}充电结算账单失败", billingMonth, e);
            throw new RuntimeException("生成充电结算账单失败", e);
        }
    }
@@ -1085,33 +1124,42 @@
     * 添加账户结算账单数据
     */
    public void addAccountSettlementStatement(){
        int day = LocalDate.now().getDayOfMonth();
        int lastDay = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth()).getDayOfMonth();
        //时间在当月的2号到当月的最后一天才执行汇总数据和生成新的汇总数据(中间有修改数据的情况)
        if (2 <= day && day <= lastDay) {
            refreshAccountSettlementStatement(LocalDate.now().minusMonths(1));
        }
    }
    /**
     * 主动刷新指定月份的账户结算账单。只重建该月未出账数据,已出账数据不受影响。
     */
    public synchronized void refreshAccountSettlementStatement(LocalDate billingMonth) {
        try {
            int day = LocalDate.now().getDayOfMonth();
            int lastDay = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth()).getDayOfMonth();
            //时间在当月的2号到当月的最后一天才执行汇总数据和生成新的汇总数据(中间有修改数据的情况)
            if(2 <= day && day <= lastDay){
                // 获取上个月的开始和结束日期
                LocalDate firstDayOfLastMonth = LocalDate.now().minusMonths(1).
                        withDayOfMonth(2);
                String string = firstDayOfLastMonth.toString();
                if (billingMonth == null) {
                    throw new IllegalArgumentException("账单月份不能为空");
                }
                LocalDate firstDayOfBillingMonth = billingMonth.withDayOfMonth(2);
                String string = firstDayOfBillingMonth.toString();
                // 将-替换为空字符串
                string = string.replace("-", "");
                //上个月
                String lastMonth = LocalDate.now().minusMonths(1).format(DateTimeFormatter.ofPattern("yyyy-MM"));
                String targetMonth = billingMonth.format(DateTimeFormatter.ofPattern("yyyy-MM"));
                //统计数据的开始时间
                String startTime = lastMonth + "-01 00:00:00";
                String startTime = targetMonth + "-01 00:00:00";
                //统计数据的结束时间
                int lasDay = LocalDate.now().minusMonths(1).with(TemporalAdjusters.lastDayOfMonth()).getDayOfMonth();
                String endTime = lastMonth + "-" + String.format("%02d", lasDay) + " 23:59:59";
                LocalDateTime createTime = LocalDateTime.parse(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM")) + "-02 00:00:00", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                int targetLastDay = billingMonth.with(TemporalAdjusters.lastDayOfMonth()).getDayOfMonth();
                String endTime = targetMonth + "-" + String.format("%02d", targetLastDay) + " 23:59:59";
                LocalDateTime createTime = LocalDateTime.now();
                //删除之前生成的汇总数据,在添加最新的汇总数据
                String format = firstDayOfLastMonth.format(DateTimeFormatter.ofPattern("yyyy-MM"));
                String format = firstDayOfBillingMonth.format(DateTimeFormatter.ofPattern("yyyy-MM"));
                accountSettlementStatementService.remove(new QueryWrapper<TAccountSettlementStatement>().eq("status", 1).last(" and DATE_FORMAT(billing_cycle, '%Y-%m') = '" + format + "'"));
                //循环生成账户类型分别统计的汇总数据
                for (int i = 1; i < 3; i++) {
                Map<Integer, BigDecimal> siteServiceShareRatioMap = loadSiteServiceShareRatioMap();
                // V2.0 账户类型统一为工商银行商户,只生成明星充电小程序订单账单。
                for (int i = 3; i < 4; i++) {
                    TAccountSettlementStatement accountSettlementStatement = new TAccountSettlementStatement();
                    // 订单生成规则JSD+20231201(账单所属月份)+1131304205(随机10位数)+001(当月账单序号,每月重置)
                    Random random = new Random();
@@ -1120,47 +1168,54 @@
                            .collect(Collectors.joining()); // 将其连接成一个字符串
                    accountSettlementStatement.setSiteId(0);
                    accountSettlementStatement.setAccountType(i);
                    accountSettlementStatement.setBillingCycle(firstDayOfLastMonth);
                    accountSettlementStatement.setBillingCycle(firstDayOfBillingMonth);
                    accountSettlementStatement.setStatus(1);
                    accountSettlementStatement.setCode("JSD"+string+randomDigits);
                    //根据业务订单查询汇总数据
                    List<Map<String, Object>> mapList = chargingOrderService.getAccountSettlementStatement(startTime, endTime, i);
                    List<Map<String, Object>> mapList = chargingOrderService.getAccountSettlementStatement(startTime, endTime);
                    BigDecimal rechargeAmount = BigDecimal.ZERO;
                    BigDecimal refundAmount = BigDecimal.ZERO;
                    BigDecimal platformFee = BigDecimal.ZERO;
                    BigDecimal tripartiteCommission = BigDecimal.ZERO;
                    BigDecimal recordedAmount = BigDecimal.ZERO;
                    BigDecimal platformIncome = BigDecimal.ZERO;
                    BigDecimal partnerIncome = BigDecimal.ZERO;
                    List<TAccountSettlementStatement> list = new ArrayList<>();
                    for (Map<String, Object> map : mapList) {
                        Integer siteId = Integer.valueOf(map.get("siteId").toString());
                        BigDecimal recharge_amount = null == map.get("rechargeAmount") ? BigDecimal.ZERO : new BigDecimal(map.get("rechargeAmount").toString());
                        BigDecimal refund_amount = null == map.get("refundAmount") ? BigDecimal.ZERO : new BigDecimal(map.get("refundAmount").toString());
                        BigDecimal platform_fee = null == map.get("platformFee") ? BigDecimal.ZERO : new BigDecimal(map.get("platformFee").toString());
                        BigDecimal tripartite_commission = null == map.get("tripartiteCommission") ? BigDecimal.ZERO : new BigDecimal(map.get("tripartiteCommission").toString());
                        BigDecimal recorded_amount = recharge_amount.subtract(refund_amount).subtract(platform_fee).subtract(tripartite_commission);
                        BigDecimal service_amount = null == map.get("serviceAmount") ? BigDecimal.ZERO : new BigDecimal(map.get("serviceAmount").toString());
                        BigDecimal partner_income = calculateAccountPartnerIncome(
                                service_amount, siteServiceShareRatioMap.get(siteId), false);
                        BigDecimal platform_income = calculateAccountPlatformIncome(recharge_amount, partner_income);
                        BigDecimal recorded_amount = recharge_amount.subtract(refund_amount);
                        //构建每个站点的汇总数据
                        TAccountSettlementStatement accountSettlementStatement1 = new TAccountSettlementStatement();
                        String randomDigits1 = random.ints(10, 0, 10) // 生成10个随机数字,范围在0-9
                                .mapToObj(String::valueOf)
                                .collect(Collectors.joining()); // 将其连接成一个字符串
                        accountSettlementStatement1.setSiteId(Integer.valueOf(map.get("siteId").toString()));
                        accountSettlementStatement1.setSiteId(siteId);
                        accountSettlementStatement1.setAccountType(i);
                        accountSettlementStatement1.setBillingCycle(firstDayOfLastMonth);
                        accountSettlementStatement1.setBillingCycle(firstDayOfBillingMonth);
                        accountSettlementStatement1.setStatus(1);
                        accountSettlementStatement1.setCode("JSD"+string+randomDigits1);
                        accountSettlementStatement1.setRechargeAmount(recharge_amount.setScale(2, RoundingMode.HALF_EVEN));
                        accountSettlementStatement1.setRefundAmount(refund_amount.setScale(2, RoundingMode.HALF_EVEN));
                        accountSettlementStatement1.setPlatformFee(platform_fee.setScale(2, RoundingMode.HALF_EVEN));
                        accountSettlementStatement1.setTripartiteCommission(tripartite_commission.setScale(2, RoundingMode.HALF_EVEN));
                        accountSettlementStatement1.setPlatformFee(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_EVEN));
                        accountSettlementStatement1.setTripartiteCommission(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_EVEN));
                        accountSettlementStatement1.setRecordedAmount(recorded_amount.setScale(2, RoundingMode.HALF_EVEN));
                        accountSettlementStatement1.setPlatformIncome(platform_income.setScale(2, RoundingMode.HALF_UP));
                        accountSettlementStatement1.setPartnerIncome(partner_income.setScale(2, RoundingMode.HALF_UP));
                        accountSettlementStatement1.setCreateTime(createTime);
                        list.add(accountSettlementStatement1);
                        //计算全站汇总数据
                        rechargeAmount = rechargeAmount.add(recharge_amount);
                        refundAmount = refundAmount.add(refund_amount);
                        platformFee = platformFee.add(platform_fee);
                        tripartiteCommission = tripartiteCommission.add(tripartite_commission);
                        recordedAmount = recordedAmount.add(recorded_amount);
                        platformIncome = platformIncome.add(platform_income);
                        partnerIncome = partnerIncome.add(partner_income);
                    }
                    accountSettlementStatement.setRechargeAmount(rechargeAmount.setScale(2, RoundingMode.HALF_EVEN));
@@ -1168,16 +1223,55 @@
                    accountSettlementStatement.setPlatformFee(platformFee.setScale(2, RoundingMode.HALF_EVEN));
                    accountSettlementStatement.setTripartiteCommission(tripartiteCommission.setScale(2, RoundingMode.HALF_EVEN));
                    accountSettlementStatement.setRecordedAmount(recordedAmount.setScale(2, RoundingMode.HALF_EVEN));
                    accountSettlementStatement.setPlatformIncome(platformIncome.setScale(2, RoundingMode.HALF_UP));
                    accountSettlementStatement.setPartnerIncome(partnerIncome.setScale(2, RoundingMode.HALF_UP));
                    accountSettlementStatement.setCreateTime(createTime);
                    accountSettlementStatementService.save(accountSettlementStatement);
                    accountSettlementStatementService.saveBatch(list);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("生成{}账户结算账单失败", billingMonth, e);
            throw new RuntimeException("生成账户结算账单失败", e);
        }
    }
    static BigDecimal calculateAccountPartnerIncome(BigDecimal paidServiceAmount, BigDecimal serviceShareRatio,
                                                     boolean thirdPartyOrder) {
        if (thirdPartyOrder || paidServiceAmount == null || serviceShareRatio == null
                || serviceShareRatio.compareTo(BigDecimal.ZERO) <= 0) {
            return BigDecimal.ZERO;
        }
        return paidServiceAmount.multiply(serviceShareRatio)
                .divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
    }
    static BigDecimal calculateAccountPlatformIncome(BigDecimal paymentAmount, BigDecimal partnerIncome) {
        BigDecimal paid = paymentAmount == null ? BigDecimal.ZERO : paymentAmount;
        BigDecimal partner = partnerIncome == null ? BigDecimal.ZERO : partnerIncome;
        return paid.subtract(partner).setScale(2, RoundingMode.HALF_UP);
    }
    private Map<Integer, BigDecimal> loadSiteServiceShareRatioMap() {
        List<Site> sites = Optional.ofNullable(siteClient.getSiteAll())
                .map(R::getData).orElse(Collections.emptyList());
        List<Partner> partners = Optional.ofNullable(siteClient.getAllPartner())
                .map(R::getData).orElse(Collections.emptyList());
        Map<Integer, Partner> partnerMap = partners.stream()
                .filter(partner -> partner != null && partner.getId() != null)
                .collect(Collectors.toMap(Partner::getId, partner -> partner, (left, right) -> left));
        Map<Integer, BigDecimal> ratioMap = new HashMap<>();
        for (Site site : sites) {
            if (site == null || site.getId() == null || site.getPartnerId() == null) {
                continue;
            }
            Partner partner = partnerMap.get(site.getPartnerId());
            if (partner != null && partner.getServiceShareRatio() != null) {
                ratioMap.put(site.getId(), partner.getServiceShareRatio());
            }
        }
        return ratioMap;
    }
    /**
     * 推送三方引流平台充电数据