longz
2026-07-30 d83061ad5d5088eb32c71c32d21dd5db278d503a
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/util/task/TaskUtil.java
@@ -1,46 +1,77 @@
package com.ruoyi.order.util.task;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson2.util.UUIDUtils;
import com.alibaba.nacos.common.utils.UuidUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.UpdateChainWrapper;
import com.ruoyi.account.api.feignClient.AppCouponClient;
import com.ruoyi.account.api.feignClient.AppUserClient;
import com.ruoyi.account.api.feignClient.AppUserIntegralChangeClient;
import com.ruoyi.account.api.model.TAppCoupon;
import com.ruoyi.account.api.model.TAppUser;
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;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.integration.api.feignClient.ChargingMessageClient;
import com.ruoyi.integration.api.feignClient.UploadRealTimeMonitoringDataClient;
import com.ruoyi.integration.api.feignClient.ChengDuJianGuanClient;
import com.ruoyi.integration.api.feignClient.TCECClient;
import com.ruoyi.integration.api.model.TransactionRecord;
import com.ruoyi.integration.api.model.UploadRealTimeMonitoringData;
import com.ruoyi.integration.api.vo.ChargingOrderVo;
import com.ruoyi.order.api.model.TChargingBill;
import com.ruoyi.order.api.model.TChargingOrder;
import com.ruoyi.order.api.model.TChargingOrderRefund;
import com.ruoyi.integration.api.vo.NotificationConnectorChargeStatusVo;
import com.ruoyi.order.api.model.*;
import com.ruoyi.order.api.vo.TransactionRecordMessageVO;
import com.ruoyi.order.service.TChargingBillService;
import com.ruoyi.order.service.TChargingOrderRefundService;
import com.ruoyi.order.service.TChargingOrderService;
import com.ruoyi.order.service.*;
import com.ruoyi.order.util.mongodb.service.TransactionRecordService;
import com.ruoyi.order.util.mongodb.service.UploadRealTimeMonitoringDataService;
import com.ruoyi.other.api.domain.TCoupon;
import com.ruoyi.other.api.domain.TIntegralRule;
import com.ruoyi.other.api.domain.TVip;
import com.ruoyi.other.api.dto.ExchangeCodeConsumeDTO;
import com.ruoyi.other.api.feignClient.IntegralRuleClient;
import com.ruoyi.other.api.feignClient.OtherClient;
import com.ruoyi.other.api.feignClient.VipClient;
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.apache.logging.log4j.core.util.UuidUtil;
import org.apache.poi.util.StringUtil;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.context.WebServerInitializedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
@@ -50,9 +81,18 @@
@Slf4j
@Component
public class TaskUtil implements ApplicationListener<WebServerInitializedEvent> {
    private static final int WHITELIST_BENEFIT_ALL_FREE = 1;
    private static final int WHITELIST_BENEFIT_ELECTRIC_FREE = 2;
    private static final int WHITELIST_BENEFIT_SERVICE_FREE = 3;
    @Resource
    private TChargingBillService chargingBillService;
    @Resource
    private ITChargingSettlementBillService chargingSettlementBillService;
    @Resource
    private ITAccountSettlementStatementService accountSettlementStatementService;
    @Resource
    private SiteClient siteClient;
    @Resource
@@ -71,12 +111,193 @@
    private ChargingMessageClient chargingMessageClient;
    
    private Integer port = null;
    @Resource
    private AccountingStrategyDetailOrderService accountingStrategyDetailOrderService;
    @Resource
    private TChargingOrderAccountingStrategyService chargingOrderAccountingStrategyService;
    @Resource
    private AppCouponClient appCouponClient;
    @Resource
    private TCECClient tcecClient;
    @Resource
    private VipClient vipClient;
    @Resource
    private ChargingGunClient chargingGunClient;
    @Resource
    private IntegralRuleClient integralRuleClient;
    @Resource
    private AppUserClient appUserClient;
    @Resource
    private AppUserIntegralChangeClient appUserIntegralChangeClient;
    @Resource
    private OtherClient otherClient;
    @Resource
    private WxPaymentClient wxPaymentClient;
    @Resource
    private IcbcPaymentClient icbcPaymentClient;
    @Resource
    private AliPaymentClient aliPaymentClient;
    @Resource
    private H5AliPaymentClient h5AliPaymentClient;
    @Resource
    private ITChargingOrderSummaryDataService chargingOrderSummaryDataService;
    @Resource
    private ChengDuJianGuanClient chengDuJianGuanClient;
    @Resource
    private RedissonClient redissonClient;
    /**
     * 判断订单是否使用余额或余额组合支付
     *
     * @param payMethod 支付方式
     * @return true=余额相关支付方式
     */
    private boolean isBalancePayMode(Integer payMethod) {
        return payMethod != null && (payMethod == 1 || payMethod == 2);
    }
    /**
     * 将金额空值统一转换为两位小数,避免补偿结算金额计算出现空指针
     *
     * @param amount 原始金额
     * @return 非空两位小数金额
     */
    private BigDecimal money(BigDecimal amount) {
        return amount == null ? BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP) : amount.setScale(2, RoundingMode.HALF_UP);
    }
    /**
     * 获取第三方实付金额,兼容早期未写入third_pay_amount的纯第三方支付订单。
     *
     * @param order 充电订单
     * @return 第三方可退款本金
     */
    private BigDecimal getRefundableThirdPayAmount(TChargingOrder order) {
        if (order == null || isWhitelistAllFreeOrder(order)) {
            return BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
        }
        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());
        }
        return thirdPayAmount;
    }
    /**
     * 判断订单是否为白名单订单
     *
     * @param order 充电订单
     * @return true=白名单订单
     */
    private boolean isWhitelistOrder(TChargingOrder order) {
        return order != null && Integer.valueOf(1).equals(order.getIsWhitelist());
    }
    /**
     * 判断订单是否为白名单全部免费权益
     *
     * @param order 充电订单
     * @return true=全部免费白名单订单
     */
    private boolean isWhitelistAllFreeOrder(TChargingOrder order) {
        return isWhitelistOrder(order)
                && Integer.valueOf(WHITELIST_BENEFIT_ALL_FREE).equals(order.getWhitelistBenefitType());
    }
    /**
     * 按白名单权益拆分补偿结算的电费和服务费减免金额,确保任务补偿与正常结算口径一致
     *
     * @param order 充电订单
     * @param electrovalence 原始电费
     * @param serviceCharge 原始服务费
     * @return 数组下标0=电费减免,下标1=服务费减免
     */
    private BigDecimal[] calculateWhitelistRefundSplit(TChargingOrder order, BigDecimal electrovalence, BigDecimal serviceCharge) {
        BigDecimal electricDiscount = BigDecimal.ZERO;
        BigDecimal serviceDiscount = BigDecimal.ZERO;
        if (!isWhitelistOrder(order)) {
            return new BigDecimal[]{electricDiscount, serviceDiscount};
        }
        if (Integer.valueOf(WHITELIST_BENEFIT_ALL_FREE).equals(order.getWhitelistBenefitType())) {
            electricDiscount = electrovalence == null ? BigDecimal.ZERO : electrovalence;
            serviceDiscount = serviceCharge == null ? BigDecimal.ZERO : serviceCharge;
        } else if (Integer.valueOf(WHITELIST_BENEFIT_ELECTRIC_FREE).equals(order.getWhitelistBenefitType())) {
            electricDiscount = electrovalence == null ? BigDecimal.ZERO : electrovalence;
        } else if (Integer.valueOf(WHITELIST_BENEFIT_SERVICE_FREE).equals(order.getWhitelistBenefitType())) {
            serviceDiscount = serviceCharge == null ? BigDecimal.ZERO : serviceCharge;
        }
        return new BigDecimal[]{electricDiscount, serviceDiscount};
    }
    /**
     * 记录兑换码余额退款流水
     *
     * @param order 充电订单
     * @param refundAmount 退款金额
     * @param refundNo 退款单号
     */
    private void recordBalanceRefund(TChargingOrder order, BigDecimal refundAmount, String refundNo) {
        if (order == null || order.getAppUserId() == null || order.getId() == null
                || refundAmount == null || refundAmount.compareTo(BigDecimal.ZERO) <= 0) {
            return;
        }
        ExchangeCodeConsumeDTO refundDTO = new ExchangeCodeConsumeDTO();
        refundDTO.setUserId(order.getAppUserId());
        refundDTO.setOrderId(order.getId());
        refundDTO.setAmount(refundAmount);
        refundDTO.setRefundNo(refundNo);
        R<ExchangeCodeConsumeResultVO> result = otherClient.refundExchangeCodeBalance(refundDTO);
        if (result == null || result.getCode() != 200) {
            throw new RuntimeException("退还兑换码余额失败");
        }
    }
    @Scheduled(fixedRate = 1000 * 60)
    public void taskOneMinutes() {
        if (isScheduledTaskPort(port)) {
            List<TChargingOrder> upStatusChargingOrder = chargingOrderService.findUpStatusChargingOrder();
            log.info("定时任务执行,查询需要手动修改状态的订单数量:{}", upStatusChargingOrder.size());
            for (TChargingOrder order : upStatusChargingOrder) {
                if(2 == order.getStatus()){
                    order.setStatus(-1);
                }else{
                    order.setStatus(5);
                }
                chargingOrderService.updateById(order);
            }
        }
    }
    //十分钟循环执行的定时任务
    @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) {
@@ -98,12 +319,12 @@
                                break;
                            }
                            try {
                                Thread.sleep(5000);
                                Thread.sleep(1000);
                            } catch (InterruptedException e) {
                                throw new RuntimeException(e);
                            }
                            num++;
                            if(num > 10){
                            if(num > 30){
                                break;
                            }
                        }
@@ -113,6 +334,7 @@
                    }
                }
            }
            //处理退款中的数据
            List<TChargingOrder> stoppedOrder = chargingOrderService.findStoppedOrder();
            log.info("定时任务执行,查询到停止中的订单数量:{}", stoppedOrder.size());
@@ -122,7 +344,13 @@
                if(null != one){
                    log.info("定时任务执行,查询到停止中的订单账单数据:{}", JSON.toJSONString(one));
                    if(null == order.getStartTime()){
                        order.setStartTime(LocalDateTime.parse(one.getStart_time(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SS").withZone(ZoneId.systemDefault())));
                        List<UploadRealTimeMonitoringData> dataList = uploadRealTimeMonitoringDataService.getDataByOrderCode(order.getCode());
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        if(dataList.isEmpty()){
                            order.setStartTime(LocalDateTime.parse(one.getStart_time(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SS").withZone(ZoneId.systemDefault())));
                        }else{
                            order.setStartTime(LocalDateTime.parse(sdf.format(dataList.get(dataList.size() - 1).getCreate_time()), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneId.systemDefault())));
                        }
                    }
                    if(null == order.getEndTime()){
                        order.setEndTime(LocalDateTime.parse(one.getEnd_time(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SS").withZone(ZoneId.systemDefault())));
@@ -132,8 +360,12 @@
                    BeanUtils.copyProperties(one, vo);
                    R r = chargingOrderService.endChargeBillingCharge(vo);
                    log.info("定时任务执行,停止中的订单处理结果:{}", JSON.toJSONString(r));
                }else{
                    endOrder(order);
                }
            }
            //处理状态为充电中,但硬件已完成的订单
            List<TChargingOrder> chargingOrder = chargingOrderService.findChargingOrder();
            log.info("定时任务执行,查询到充电中的订单数量:{}", chargingOrder.size());
@@ -143,7 +375,13 @@
                if(null != one && StringUtils.isNotEmpty(one.getResult())){
                    log.info("定时任务执行,查询到充电中的订单账单数据:{}", JSON.toJSONString(one));
                    if(null == order.getStartTime()){
                        order.setStartTime(LocalDateTime.parse(one.getStart_time(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SS").withZone(ZoneId.systemDefault())));
                        List<UploadRealTimeMonitoringData> dataList = uploadRealTimeMonitoringDataService.getDataByOrderCode(order.getCode());
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        if(dataList.isEmpty()){
                            order.setStartTime(LocalDateTime.parse(one.getStart_time(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SS").withZone(ZoneId.systemDefault())));
                        }else{
                            order.setStartTime(LocalDateTime.parse(sdf.format(dataList.get(dataList.size() - 1).getCreate_time()), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneId.systemDefault())));
                        }
                    }
                    if(null == order.getEndTime()){
                        order.setEndTime(LocalDateTime.parse(one.getEnd_time(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SS").withZone(ZoneId.systemDefault())));
@@ -153,136 +391,901 @@
                    BeanUtils.copyProperties(one, vo);
                    R r = chargingOrderService.endChargeBillingCharge(vo);
                    log.info("定时任务执行,充电中的订单处理结果:{}", JSON.toJSONString(r));
                }else{
                    //判断充电流水超过10分钟没有更新,则判定为充电结束
                    List<UploadRealTimeMonitoringData> dataList = uploadRealTimeMonitoringDataService.getDataByOrderCode(order.getCode());
                    if(!dataList.isEmpty()){
                        UploadRealTimeMonitoringData uploadRealTimeMonitoringData = dataList.get(0);
                        Date createTime = uploadRealTimeMonitoringData.getCreate_time();
                        if(System.currentTimeMillis() - createTime.getTime() - (8 * 60 * 60 * 1000) > 1000 * 60 * 10){
                            endOrder(order);
                        }
                    }
                }
            }
            //处理还未退款,但是订单状态已结束的数据
            List<TChargingOrder> endChargingOrder = chargingOrderService.findEndChargingOrder();
            log.info("定时任务执行,查询到已结束未退款的订单数量:{}", endChargingOrder.size());
            for (TChargingOrder order : endChargingOrder) {
                if(-1 == order.getStatus()){
                    order.setStatus(2);
                }
                if(5 == order.getStatus()){
                    order.setStatus(4);
                }
                chargingOrderService.updateById(order);
            }
        }
    }
    @Scheduled(cron = "0 0 0 2 * ?")
    //定时任务添加结算账单汇总数据
    @Scheduled(cron = "0 30 0 * * ?")
    public void taskMonth() {
        if(null != port && port == 5400){
            try {
                // 获取上个月的开始和结束日期
                LocalDate firstDayOfLastMonth = LocalDate.now().minusMonths(1).
                        withDayOfMonth(2);
                String string = firstDayOfLastMonth.toString();
                // 将-替换为空字符串
                string = string.replace("-", "");
                // 生成一次全站订单
                TChargingBill tChargingBill = new TChargingBill();
                // 订单生成规则JSD+20231201(账单所属月份)+1131304205(随机10位数)+001(当月账单序号,每月重置)
                Random random = new Random();
                String randomDigits = random.ints(10, 0, 10) // 生成10个随机数字,范围在0-9
                        .mapToObj(String::valueOf)
                        .collect(Collectors.joining()); // 将其连接成一个字符串
                tChargingBill.setCode("JSD"+string+randomDigits );
                tChargingBill.setType(1);
                tChargingBill.setSiteId(0);
                tChargingBill.setBillTime(LocalDateTime.now());
                tChargingBill.setStatus(1);
                tChargingBill.setOrderState(2);
                tChargingBill.setBillType(1);
                System.err.println("定时任务生成充电算帐单:全站");
                chargingBillService.save(tChargingBill);
                // 生成一次全站订单
                TChargingBill tChargingBill1 = new TChargingBill();
                // 订单生成规则JSD+20231201(账单所属月份)+1131304205(随机10位数)+001(当月账单序号,每月重置)
                Random random1 = new Random();
                String randomDigits1 = random1.ints(10, 0, 10) // 生成10个随机数字,范围在0-9
                        .mapToObj(String::valueOf)
                        .collect(Collectors.joining()); // 将其连接成一个字符串
                tChargingBill1.setCode("JSD"+string+randomDigits1 );
                tChargingBill1.setType(1);
                tChargingBill1.setSiteId(0);
                tChargingBill1.setBillTime(LocalDateTime.now());
                tChargingBill1.setStatus(1);
                tChargingBill1.setOrderState(2);
                tChargingBill1.setBillType(2);
                System.err.println("定时任务生成账户结算帐单:全站");
                chargingBillService.save(tChargingBill1);
                System.err.println("定时任务生成各个站点结算帐单");
                List<Integer> collect = siteClient.getSiteAll().getData().stream().map(Site::getId).collect(Collectors.toList());
                // 充电算帐单
                List<TChargingBill> tChargingBills = new ArrayList<>();
                // 账户结算账单
                List<TChargingBill> tChargingBills1 = new ArrayList<>();
                for (int i = 0; i < collect.size(); i++) {
                    TChargingBill tChargingBill2 = new TChargingBill();
                    Random random2 = new Random();
                    String randomDigits2 = random2.ints(10, 0, 10) // 生成10个随机数字,范围在0-9
                            .mapToObj(String::valueOf)
                            .collect(Collectors.joining()); // 将其连接成一个字符串
                    tChargingBill2.setCode("JSD"+string+randomDigits2+(i+1) );
                    tChargingBill2.setType(2);
                    List<TChargingOrder> list = chargingOrderService.lambdaQuery()
                            .eq(TChargingOrder::getSiteId, collect.get(i)).list();
                    if (list.isEmpty()){
                        continue;
                    }
                    tChargingBill2.setSiteId(collect.get(i));
                    tChargingBill2.setBillTime(LocalDateTime.now());
                    tChargingBill2.setBillType(1);
                    tChargingBill2.setStatus(1);
                    tChargingBill2.setOrderState(2);
                    tChargingBills.add(tChargingBill2);
                    TChargingBill tChargingBill3 = new TChargingBill();
                    Random random3 = new Random();
                    String randomDigits3 = random3.ints(10, 0, 10) // 生成10个随机数字,范围在0-9
                            .mapToObj(String::valueOf)
                            .collect(Collectors.joining()); // 将其连接成一个字符串
                    tChargingBill3.setCode("JSD"+string+randomDigits3+(i+1) );
                    tChargingBill3.setType(2);
                    tChargingBill3.setSiteId(collect.get(i));
                    tChargingBill3.setBillTime(LocalDateTime.now());
                    tChargingBill3.setBillType(2);
                    tChargingBill3.setStatus(1);
                    tChargingBill3.setOrderState(2);
                    tChargingBills1.add(tChargingBill3);
                }
                System.err.println("列表"+tChargingBills);
                if (!tChargingBills.isEmpty())chargingBillService.saveBatch(tChargingBills);
                if (!tChargingBills1.isEmpty())chargingBillService.saveBatch(tChargingBills1);
            } catch (Exception e) {
                e.printStackTrace();
            }
        if (isScheduledTaskPort(port)) {
            //推送三方引流平台数据
            pushOrderDrainagePlatform();
            //添加充电算账单汇总数据
            addChargingSettlementBill();
            //添加账户结算账单数据
            addAccountSettlementStatement();
        }
    }
    // 每个月最后一天23点执行的定时任务
    @Scheduled(cron = "0 0 23 * * ?")
    public void taskLastDay() {
        if(null != port && port == 5400){
        if (isScheduledTaskPort(port)) {
            try {
                // 获取上个月的开始和结束日期
                LocalDate firstDayOfLastMonth = LocalDate.now().minusMonths(1).
                        withDayOfMonth(1);
                LocalDate lastDayOfLastMonth = LocalDate.now().minusMonths(1).
                        withDayOfMonth(firstDayOfLastMonth.lengthOfMonth());
                // 将 LocalDate 转换为 LocalDateTime,并设定时间为一天的开始
                LocalDateTime startDateTime = firstDayOfLastMonth.atStartOfDay();
                LocalDateTime endDateTime = lastDayOfLastMonth.atTime(23, 59, 59); // 设定到最后一秒
                // 构建查询条件
                LambdaQueryWrapper<TChargingBill> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.ge(TChargingBill::getBillTime,
                                Date.from(startDateTime.atZone(ZoneId.systemDefault()).toInstant()))
                        .le(TChargingBill::getBillTime,
                                Date.from(endDateTime.atZone(ZoneId.systemDefault()).toInstant())); // 使用 le 包括最后一天的记录
                List<TChargingBill> list = chargingBillService.list(queryWrapper);
                for (TChargingBill tChargingBill : list) {
                    tChargingBill.setStatus(2);
                int dayOfMonth = LocalDate.now().getDayOfMonth();
                int lastDayOfMonth = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth()).getDayOfMonth();
                //当月最后一天
                if(dayOfMonth == lastDayOfMonth){
                    //修改充电结算账单为已出账
                    chargingSettlementBillService.update(new UpdateWrapper<TChargingSettlementBill>().set("status", 2).set("create_time", LocalDateTime.now()).eq("status", 1));
                    //修改账户结算账单为已出账
                    accountSettlementStatementService.update(new UpdateWrapper<TAccountSettlementStatement>().set("status", 2).set("create_time", LocalDateTime.now()).eq("status", 1));
                }
                chargingBillService.updateBatchById(list);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    @Override
    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);
    }
    @Transactional
    public void endOrder(TChargingOrder order){
        RLock lock = redissonClient.getLock("endOrder:" + order.getCode());
        try {
            boolean tryLock = lock.tryLock(60, 60, TimeUnit.SECONDS);
            if(tryLock){
                List<UploadRealTimeMonitoringData> dataList = uploadRealTimeMonitoringDataService.getDataByOrderCode(order.getCode());
                if(!dataList.isEmpty()){
                    //获取当前订单的计费规则,然后分段计算总的度数和充电金额
                    List<AccountingStrategyDetailOrder> detailOrders = accountingStrategyDetailOrderService.list(new LambdaQueryWrapper<AccountingStrategyDetailOrder>()
                            .eq(AccountingStrategyDetailOrder::getChargingOrderId, order.getId()).last(" order by start_time"));
                    detailOrders.get(detailOrders.size() - 1).setEndTime("23:59");
                    SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
                    //开始解析每个时段的充电度数
                    BigDecimal decimal = BigDecimal.ZERO;
                    //如果使用优惠券需要判断优惠券是否满足使用条件
                    //退款金额=优惠券金额+剩余充电金额
                    BigDecimal periodElectricPrice_total = BigDecimal.ZERO;
                    BigDecimal periodServicePrice_total = BigDecimal.ZERO;
                    BigDecimal vipDiscountAmount_total = BigDecimal.ZERO;
                    BigDecimal serviceCharge_total = BigDecimal.ZERO;
                    BigDecimal total = BigDecimal.ZERO;
                    //判断实时数据是否跨天
                    SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd");
                    Date end_time = dataList.get(0).getCreate_time();
                    String end = sdf2.format(end_time);
                    Date start_time = dataList.get(dataList.size() - 1).getCreate_time();
                    String start = sdf2.format(start_time);
                    if(!end.equals(start)){
                        List<AccountingStrategyDetailOrder> list = detailOrders.stream().map(s->{
                            AccountingStrategyDetailOrder accountingStrategyDetailOrder = new AccountingStrategyDetailOrder();
                            BeanUtils.copyProperties(s, accountingStrategyDetailOrder);
                            return accountingStrategyDetailOrder;
                        }).collect(Collectors.toList());
                        for (AccountingStrategyDetailOrder detailOrder : detailOrders) {
                            detailOrder.setStartTime(start + " " + detailOrder.getStartTime());
                            detailOrder.setEndTime(start + " " + detailOrder.getEndTime());
                        }
                        for (AccountingStrategyDetailOrder detailOrder : list) {
                            detailOrder.setStartTime(end + " " + detailOrder.getStartTime());
                            detailOrder.setEndTime(end + " " + detailOrder.getEndTime());
                        }
                        detailOrders.addAll(list);
                    }else{
                        for (AccountingStrategyDetailOrder detailOrder : detailOrders) {
                            detailOrder.setStartTime(start + " " + detailOrder.getStartTime());
                            detailOrder.setEndTime(start + " " + detailOrder.getEndTime());
                        }
                    }
                    SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyMMddHHmm");
                    List<TChargingOrderAccountingStrategy> list = new ArrayList<>();
                    for (AccountingStrategyDetailOrder detailOrder : detailOrders) {
                        long startTime = Long.parseLong(detailOrder.getStartTime().replaceAll("-", "").replaceAll(" ", "").replaceAll(":", ""));
                        long endTime = Long.parseLong(detailOrder.getEndTime().replaceAll("-", "").replaceAll(" ", "").replaceAll(":", ""));
                        List<UploadRealTimeMonitoringData> collect = dataList.stream().filter(s -> Long.parseLong(sdf1.format(s.getCreate_time())) > startTime && Long.parseLong(sdf1.format(s.getCreate_time())) <= endTime).collect(Collectors.toList());
                        if(!collect.isEmpty()){
                            //升序排序
                            collect.sort(new Comparator<UploadRealTimeMonitoringData>(){
                                @Override
                                public int compare(UploadRealTimeMonitoringData o1, UploadRealTimeMonitoringData o2) {
                                    return o1.getCharging_degree().compareTo(o2.getCharging_degree());
                                }
                            });
                            UploadRealTimeMonitoringData uploadRealTimeMonitoringData = collect.get(collect.size() - 1);
                            BigDecimal chargingDegree = uploadRealTimeMonitoringData.getCharging_degree();
                            BigDecimal subtract = chargingDegree.subtract(decimal);
                            decimal = chargingDegree;
                            if(subtract.compareTo(BigDecimal.ZERO) > 0){
                                //组装充电明细数据
                                TChargingOrderAccountingStrategy chargingOrderAccountingStrategy = new TChargingOrderAccountingStrategy();
                                chargingOrderAccountingStrategy.setChargingOrderId(order.getId());
                                chargingOrderAccountingStrategy.setAccountingStrategyDetailId(detailOrder.getId());
                                chargingOrderAccountingStrategy.setType(detailOrder.getType());
                                chargingOrderAccountingStrategy.setElectrovalence(detailOrder.getElectrovalence());
                                chargingOrderAccountingStrategy.setServiceCharge(detailOrder.getServiceCharge());
                                chargingOrderAccountingStrategy.setCostServiceCharge(detailOrder.getCostServiceCharge());
                                chargingOrderAccountingStrategy.setChargingCapacity(subtract);
                                chargingOrderAccountingStrategy.setCreateTime(LocalDateTime.now());
                                if (list.size() == 0) {
                                    String time = sdf.format(collect.get(0).getCreate_time());
                                    chargingOrderAccountingStrategy.setStartTime(time);
                                } else {
                                    chargingOrderAccountingStrategy.setStartTime(detailOrder.getStartTime().split(" ")[1]);
                                }
                                chargingOrderAccountingStrategy.setEndTime(detailOrder.getEndTime().split(" ")[1]);
                                //已充电总度数
                                BigDecimal electrovalenc = detailOrder.getElectrovalence().multiply(subtract);
                                BigDecimal originalServicePrice = detailOrder.getServiceCharge().multiply(subtract);
                                BigDecimal serviceCharge = originalServicePrice;
                                BigDecimal vipDiscountAmount = BigDecimal.ZERO;
                                //计算优惠金额
                                if (!isWhitelistOrder(order) && null != order.getVipDiscount()) {
                                    //0.58折
                                    vipDiscountAmount = serviceCharge.multiply(new BigDecimal(1).subtract(order.getVipDiscount()));
                                    serviceCharge = serviceCharge.multiply(order.getVipDiscount());
                                }
                                chargingOrderAccountingStrategy.setPeriodElectricPrice(electrovalenc.setScale(4, RoundingMode.HALF_EVEN));
                                chargingOrderAccountingStrategy.setPeriodServicePrice(serviceCharge.setScale(4, RoundingMode.HALF_EVEN));
                                chargingOrderAccountingStrategy.setPeriodOriginalServicePrice(originalServicePrice.setScale(4, RoundingMode.HALF_EVEN));
                                chargingOrderAccountingStrategy.setVipDiscountAmount(vipDiscountAmount.setScale(4, RoundingMode.HALF_EVEN));
                                chargingOrderAccountingStrategy.setCreateTime(LocalDateTime.now());
                                list.add(chargingOrderAccountingStrategy);
                                //电费
                                periodElectricPrice_total = periodElectricPrice_total.add(electrovalenc);
                                //服务费(含折扣)
                                serviceCharge_total = serviceCharge_total.add(serviceCharge);
                                //服务费(不含折扣)
                                periodServicePrice_total = periodServicePrice_total.add(originalServicePrice);
                                //会员折扣优惠金额
                                vipDiscountAmount_total = vipDiscountAmount_total.add(vipDiscountAmount);
                                //原始总金额(不含折扣)
                                total = total.add(electrovalenc.add(originalServicePrice));
                            }
                        }
                    }
                    list.get(list.size() - 1).setEndTime(sdf.format(dataList.get(0).getCreate_time()));
                    chargingOrderAccountingStrategyService.saveBatch(list);
                    BigDecimal orderAmount = BigDecimal.valueOf(total.doubleValue());
                    //原金额
                    BigDecimal rechargeAmount = order.getRechargeAmount();
                    //支付金额
                    BigDecimal payAmount = periodElectricPrice_total.add(serviceCharge_total);
                    //退款金额=充值金额-实际支付金额
                    BigDecimal refundAmount = rechargeAmount.subtract(payAmount);
                    UploadRealTimeMonitoringData uploadRealTimeMonitoringData = uploadRealTimeMonitoringDataService.getLastDataById(order.getCode());
                    if (null != uploadRealTimeMonitoringData && null == order.getEndMode()) {
                        Integer soc = uploadRealTimeMonitoringData.getSoc();
                        if (soc >= 98) {
                            order.setEndMode(2);
                        } else if (null != order.getResidualAmount() && order.getResidualAmount().compareTo(new BigDecimal(1)) <= 0) {
                            order.setEndMode(3);
                        } else {
                            order.setEndMode(1);
                        }
                    }
                    order.setResidualAmount(rechargeAmount.subtract(total).setScale(2, RoundingMode.HALF_EVEN));
                    order.setStartTime(list.get(0).getCreateTime());
                    order.setEndTime(list.get(list.size() - 1).getCreateTime());
                    order.setStatus(5);
                    order.setOrderAmount(orderAmount.setScale(2, RoundingMode.HALF_EVEN));
                    order.setElectrovalence(periodElectricPrice_total.setScale(2, RoundingMode.HALF_EVEN));
                    order.setChargingCapacity(list.get(list.size() - 1).getChargingCapacity());
                    order.setElectricity(list.get(list.size() - 1).getChargingCapacity());
                    order.setVipDiscountAmount(vipDiscountAmount_total);
                    if (vipDiscountAmount_total.compareTo(BigDecimal.ZERO) == 0) {
                        order.setVipDiscount(BigDecimal.valueOf(1));
                    }
                    //计算优惠券
                    BigDecimal couponDiscount = BigDecimal.ZERO;
                    if (!isWhitelistOrder(order) && null != order.getAppCouponId()) {
                        //判断实际充电金额是否满足优惠券使用条件,如果不满足则不适用优惠券。
                        TAppCoupon appCoupon = appCouponClient.getAppCouponById(order.getAppCouponId()).getData();
                        String couponJson = appCoupon.getCouponJson();
                        TCoupon tCoupon = com.alibaba.fastjson2.JSON.parseObject(couponJson, TCoupon.class);
                        Integer preferentialMode = tCoupon.getPreferentialMode();
                        if (1 == preferentialMode) {
                            //满减
                            if (payAmount.compareTo(tCoupon.getMeetTheConditions()) >= 0) {
                                BigDecimal couponDiscountAmount = tCoupon.getDiscountAmount();
                                //如果优惠金额大于服务费金额,以服务费作为最大限制
                                if (serviceCharge_total.compareTo(couponDiscountAmount) < 0) {
                                    couponDiscount = serviceCharge_total;
                                    serviceCharge_total = BigDecimal.ZERO;
                                } else {
                                    couponDiscount = couponDiscountAmount;
                                }
                                appCoupon.setStatus(2);
                                appCouponClient.updateAppCoupon(appCoupon);
                            } else {
                                appCouponClient.refund(order.getAppCouponId().toString());
                                order.setAppCouponId(null);
                                order.setCouponDiscountAmount(BigDecimal.ZERO);
                            }
                        }
                        if (2 == preferentialMode) {
                            //抵扣
                            if (payAmount.compareTo(tCoupon.getMeetTheConditions()) >= 0) {
                                //折扣金额
                                BigDecimal divide = payAmount.multiply(new BigDecimal(10).subtract(tCoupon.getDiscount())).divide(new BigDecimal(10));
                                divide = divide.compareTo(tCoupon.getMaximumDiscountAmount()) > 0 ? tCoupon.getMaximumDiscountAmount() : divide;
                                //如果优惠金额大于服务费金额,以服务费作为最大限制
                                if (serviceCharge_total.compareTo(divide) < 0) {
                                    couponDiscount = serviceCharge_total;
                                    serviceCharge_total = BigDecimal.ZERO;
                                } else {
                                    couponDiscount = divide;
                                }
                                appCoupon.setStatus(2);
                                appCouponClient.updateAppCoupon(appCoupon);
                            } else {
                                order.setAppCouponId(null);
                                order.setCouponDiscountAmount(BigDecimal.ZERO);
                                appCouponClient.refund(order.getAppCouponId().toString());
                            }
                        }
                    }
                    BigDecimal[] whitelistRefundSplit = calculateWhitelistRefundSplit(order, periodElectricPrice_total, serviceCharge_total);
                    BigDecimal electricDiscount = whitelistRefundSplit[0];
                    BigDecimal serviceDiscount = whitelistRefundSplit[1];
                    BigDecimal whitelistDiscount = electricDiscount.add(serviceDiscount).setScale(4, RoundingMode.HALF_EVEN);
                    if (whitelistDiscount.compareTo(BigDecimal.ZERO) > 0) {
                        // 补偿任务需与实时结算使用同一拆分口径,避免财务导出金额不一致。
                        periodElectricPrice_total = periodElectricPrice_total.subtract(electricDiscount).max(BigDecimal.ZERO);
                        serviceCharge_total = serviceCharge_total.subtract(serviceDiscount).max(BigDecimal.ZERO);
                        refundAmount = refundAmount.add(whitelistDiscount);
                        payAmount = payAmount.subtract(whitelistDiscount).max(BigDecimal.ZERO);
                    }
                    //优惠券优惠金额
                    couponDiscount = couponDiscount.setScale(4, RoundingMode.HALF_EVEN);
                    //退款金额+优惠券
                    refundAmount = refundAmount.add(couponDiscount);
                    //实际支付金额-优惠券
                    payAmount = payAmount.subtract(couponDiscount);
                    if (serviceCharge_total.compareTo(BigDecimal.ZERO) > 0) {
                        serviceCharge_total = serviceCharge_total.subtract(couponDiscount);
                    }
                    order.setCouponDiscountAmount(couponDiscount.setScale(2, RoundingMode.HALF_EVEN));
                    order.setWhitelistDiscountAmount(whitelistDiscount.setScale(2, RoundingMode.HALF_EVEN));
                    order.setWhitelistElectricRefundAmount(electricDiscount.setScale(2, RoundingMode.HALF_EVEN));
                    order.setWhitelistServiceRefundAmount(serviceDiscount.setScale(2, RoundingMode.HALF_EVEN));
                    order.setElectrovalence(periodElectricPrice_total.setScale(2, RoundingMode.HALF_EVEN));
                    order.setServiceCharge(serviceCharge_total.setScale(2, RoundingMode.HALF_EVEN));
                    order.setPaymentAmount(payAmount.setScale(2, RoundingMode.HALF_EVEN));
                    order.setRefundAmount(refundAmount.setScale(2, RoundingMode.HALF_EVEN));
                    order.setRefundStatus(1);
                    UploadRealTimeMonitoringData asc = uploadRealTimeMonitoringDataService.getDataByOrderCode(order.getCode(), "asc");
                    UploadRealTimeMonitoringData desc = uploadRealTimeMonitoringDataService.getDataByOrderCode(order.getCode(), "desc");
                    if(null != asc){
                        order.setStartSoc(new BigDecimal(asc.getSoc()));
                    }
                    if(null != desc){
                        order.setEndSoc(new BigDecimal(desc.getSoc()));
                    }
                    chargingOrderService.updateById(order);
                    order = chargingOrderService.getById(order.getId());
                    Site site = siteClient.getSiteByIds(Arrays.asList(order.getSiteId())).getData().get(0);
                    //推送三方平台
                    if (2 == order.getOrderSource() && 1 == site.getIsOpenSynchronization()) {
                        TChargingOrder finalChargingOrder = order;
                        new Thread(new Runnable() {
                            @Override
                            public void run() {
                                tcecClient.notificationEquipChargeStatus(finalChargingOrder.getStartChargeSeq(), finalChargingOrder.getOperatorId());
                                tcecClient.notificationStopChargeResult(finalChargingOrder.getStartChargeSeq(), finalChargingOrder.getChargingGunId().toString(),
                                        finalChargingOrder.getOperatorId());
                                tcecClient.notificationChargeOrderInfo(finalChargingOrder.getStartChargeSeq(), finalChargingOrder.getOperatorId());
                            }
                        }).start();
                    }
                    //开始将优惠券优惠的金额添加到明细中
                    BigDecimal couponDiscountAmount = order.getCouponDiscountAmount();
                    if (null != couponDiscountAmount && couponDiscountAmount.compareTo(BigDecimal.ZERO) > 0) {
                        List<TChargingOrderAccountingStrategy> list1 = chargingOrderAccountingStrategyService.list(new LambdaQueryWrapper<TChargingOrderAccountingStrategy>().eq(TChargingOrderAccountingStrategy::getChargingOrderId, order.getId()));
                        BigDecimal reduce = list1.stream().map(TChargingOrderAccountingStrategy::getPeriodServicePrice).reduce(BigDecimal.ZERO, BigDecimal::add);
                        for (TChargingOrderAccountingStrategy chargingOrderAccountingStrategy : list1) {
                            BigDecimal periodServicePrice = chargingOrderAccountingStrategy.getPeriodServicePrice();
                            BigDecimal multiply = couponDiscountAmount.multiply(periodServicePrice.divide(reduce, new MathContext(4, RoundingMode.HALF_EVEN)));
                            periodServicePrice = periodServicePrice.subtract(multiply);
                            chargingOrderAccountingStrategy.setPeriodServicePrice(periodServicePrice.setScale(2, RoundingMode.HALF_EVEN));
                            chargingOrderAccountingStrategy.setCouponDiscountAmount(multiply.setScale(2, RoundingMode.HALF_EVEN));
                        }
                        chargingOrderAccountingStrategyService.updateBatchById(list1);
                    }
                    // 将枪状态重置为空闲
                    TChargingGun chargingGun = new TChargingGun();
                    chargingGun.setId(order.getChargingGunId());
                    chargingGun.setStatus(2);
                    chargingGun.setChargingPower(BigDecimal.ZERO);
                    chargingGunClient.updateChargingGunById(chargingGun);
                    chargingGun = chargingGunClient.getChargingGunById(order.getChargingGunId()).getData();
                    //推送状态给三方平台
                    if (2 == order.getOrderSource() && 1 == site.getIsOpenSynchronization()) {
                        tcecClient.pushChargingGunStatus(chargingGun.getFullNumber(), 2);
                    }
                    ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.SECONDS, new LinkedBlockingDeque<>());
                    TChargingOrder finalOrder = order;
                    threadPoolExecutor.execute(()->{
                        //推送成都监管
                        NotificationConnectorChargeStatusVo statusVo = new NotificationConnectorChargeStatusVo();
                        statusVo.setOrderCode(finalOrder.getCode());
                        statusVo.setChargingGunId(finalOrder.getChargingGunId());
                        chengDuJianGuanClient.notificationConnectorChargeStatus(statusVo);
                        chengDuJianGuanClient.notificationOrderInfo(statusVo);
                    });
                    //添加积分
                    if (1 == order.getOrderSource()) {
                        TIntegralRule integralRule = integralRuleClient.getSet().getData();
                        if (null != integralRule) {
                            TAppUser appUser = appUserClient.getUserById(order.getAppUserId()).getData();
                            Integer num1 = com.alibaba.fastjson2.JSON.parseObject(integralRule.getChargeCredit()).getInteger("num1");
                            Integer integral = order.getServiceCharge().intValue() * num1;
                            if (null != appUser.getVipId()) {
                                TVip vip = vipClient.getInfo1(appUser.getVipId()).getData();
                                Integer doubleIntegration = vip.getDoubleIntegration();
                                //双倍积分
                                if (1 == doubleIntegration) {
                                    integral *= 2;
                                }
                            }
                            if (integral > 0) {
                                TAppUserIntegralChange appUserIntegralChange = new TAppUserIntegralChange();
                                appUserIntegralChange.setAppUserId(appUser.getId());
                                appUserIntegralChange.setChangeType(2);
                                appUserIntegralChange.setHistoricalIntegral(appUser.getPoints());
                                appUser.setPoints(appUser.getPoints() + integral);
                                appUserIntegralChange.setCurrentIntegral(appUser.getPoints());
                                appUserIntegralChange.setCreateTime(LocalDateTime.now());
                                appUserIntegralChange.setOrderCode(order.getCode());
                                appUserIntegralChange.setExtension(order.getId().toString());
                                appUserClient.updateAppUser(appUser);
                                appUserIntegralChangeClient.addAppUserIntegralChange(appUserIntegralChange);
                            }
                        }
                        //计算用户标签
                        chargingOrderService.editUserTag(order);
                        //用户推荐奖励
                        chargingOrderService.referralReward(order);
                        //开始构建退款费用
                        refundAmount = refundAmount.setScale(2, RoundingMode.HALF_EVEN);
                        BigDecimal refundableThirdPayAmount = getRefundableThirdPayAmount(order);
                        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();
                        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(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);
                            //构建退款明细
                            TChargingOrderRefund chargingOrderRefund = new TChargingOrderRefund();
                            chargingOrderRefund.setChargingOrderId(order.getId());
                            SimpleDateFormat sdfaa = new SimpleDateFormat("yyyyMMddHHmmssSSS");
                            chargingOrderRefund.setRefundCode("CDF" + sdfaa.format(new Date()) + (Double.valueOf(Math.random() * 1000).intValue()));
                            chargingOrderRefund.setRefundAmount(refundAmount);
                            chargingOrderRefund.setRefundStatus(1);
                            chargingOrderRefund.setPayType(rechargePaymentType);
                            chargingOrderRefund.setCode(order.getCode());
                            chargingOrderRefund.setRefundTitle("充电完成退款");
                            chargingOrderRefund.setRefundContent("充电完成退款");
                            chargingOrderRefund.setRefundReason("充电完成退款");
                            chargingOrderRefund.setRefundRemark("实际充电消费金额:" + order.getPaymentAmount());
                            chargingOrderRefund.setRefundTotalAmount(refundAmount);
                            chargingOrderRefund.setPayAmount(rechargeAmount);
                            if (thirdRefundAmount.compareTo(BigDecimal.ZERO) == 0) {
                                chargingOrderRefund.setRefundStatus(2);
                                chargingOrderRefund.setRefundSerialNumber("BALANCE");
                                chargingOrderRefund.setRefundTime(LocalDateTime.now());
                                chargingOrderRefundService.save(chargingOrderRefund);
                                if (balanceRefundAmount.compareTo(BigDecimal.ZERO) > 0) {
                                    recordBalanceRefund(order, balanceRefundAmount, chargingOrderRefund.getRefundCode());
                                }
                                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());
                                model.setOut_refund_no(chargingOrderRefund.getRefundCode());
                                model.setReason("充电完成退款");
                                model.setNotify_url("/payment/wx/refund/notify");
                                WxPaymentRefundModel.RefundAmount amount = new WxPaymentRefundModel.RefundAmount();
                                amount.setRefund(thirdRefundAmount.multiply(new BigDecimal(100)).intValue());
                                amount.setTotal(getRefundableThirdPayAmount(order).multiply(new BigDecimal(100)).intValue());
                                amount.setCurrency("CNY");
                                model.setAmount(amount);
                                R<Map<String, Object>> result = wxPaymentClient.refundOrderR(model);
                                if (200 == result.getCode()) {
                                    chargingOrderRefundService.save(chargingOrderRefund);
                                    //???
                                    Map<String, Object> amount1 = (Map<String, Object>) result.getData().get("amount");
                                    Object refund_fee1 = amount1.get("refund_fee");
                                    BigDecimal refund_fee = new BigDecimal(null == refund_fee1 ? "0" : refund_fee1.toString()).divide(new BigDecimal(100));
                                    chargingOrderRefund.setRefundFee(refund_fee);
                                    chargingOrderRefundService.updateById(chargingOrderRefund);
                                }
                            }
                            else if (2 == rechargePaymentType) {
                                RefundReq dto = new RefundReq();
                                dto.setOutTradeNo(order.getCode());
                                dto.setOutRequestNo(chargingOrderRefund.getRefundCode());
                                dto.setRefundAmount(thirdRefundAmount.toString());
                                dto.setRefundReason("充电完成退款");
                                RefundResp resp = aliPaymentClient.refund(dto).getData();
                                if (null != resp) {
                                    chargingOrderRefundService.save(chargingOrderRefund);
                                    chargingOrderService.chargingOrderStartupFailureWxRefund(chargingOrderRefund.getRefundCode(), resp.getTradeNo(), "SUCCESS", null);
                                }
                            }
                            else if (3 == rechargePaymentType) {
                                RefundReq dto = new RefundReq();
                                dto.setOutTradeNo(order.getRechargeSerialNumber());
                                dto.setOutRequestNo(chargingOrderRefund.getRefundCode());
                                dto.setRefundAmount(thirdRefundAmount.toString());
                                dto.setRefundReason("充电完成退款");
                                RefundResp resp = h5AliPaymentClient.refund(dto).getData();
                                if (null != resp && "10000".equals(resp.getCode())) {
                                    chargingOrderRefundService.save(chargingOrderRefund);
                                    chargingOrderService.chargingOrderStartupFailureWxRefund(chargingOrderRefund.getRefundCode(), resp.getTradeNo(), "SUCCESS", null);
                                }
                            }
                        } else if (recordedRefundAmount.compareTo(BigDecimal.ZERO) > 0) {
                            order.setThirdRefundAmount(thirdRefundAmount);
                            order.setBalanceRefundAmount(balanceRefundAmount);
                            order.setRefundAmount(recordedRefundAmount);
                            order.setRefundStatus(2);
                            chargingOrderService.updateById(order);
                            TChargingOrderRefund chargingOrderRefund = new TChargingOrderRefund();
                            chargingOrderRefund.setChargingOrderId(order.getId());
                            SimpleDateFormat sdfaa = new SimpleDateFormat("yyyyMMddHHmmssSSS");
                            chargingOrderRefund.setRefundCode("CDF" + sdfaa.format(new Date()) + (Double.valueOf(Math.random() * 1000).intValue()));
                            chargingOrderRefund.setRefundAmount(recordedRefundAmount);
                            chargingOrderRefund.setBalanceRefundAmount(balanceRefundAmount);
                            chargingOrderRefund.setThirdRefundAmount(thirdRefundAmount);
                            chargingOrderRefund.setRefundStatus(2);
                            chargingOrderRefund.setRefundSerialNumber("WHITELIST");
                            chargingOrderRefund.setRefundTime(LocalDateTime.now());
                            chargingOrderRefund.setPayType(rechargePaymentType);
                            chargingOrderRefund.setCode(order.getCode());
                            chargingOrderRefund.setRefundTitle("充电完成退款");
                            chargingOrderRefund.setRefundContent("充电完成退款");
                            chargingOrderRefund.setRefundReason("充电完成退款");
                            chargingOrderRefund.setRefundRemark("白名单全部免费,记录预估退款金额");
                            chargingOrderRefund.setRefundTotalAmount(recordedRefundAmount);
                            chargingOrderRefund.setPayAmount(rechargeAmount);
                            chargingOrderRefundService.save(chargingOrderRefund);
                        }
                    }
                    //添加汇总统计数据
                    List<TChargingOrderAccountingStrategy> list4 = chargingOrderAccountingStrategyService.list(new QueryWrapper<TChargingOrderAccountingStrategy>().eq("charging_order_id", order.getId()));
                    BigDecimal electronic_reduce = list4.stream().map(TChargingOrderAccountingStrategy::getPeriodElectricPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
                    BigDecimal service_reduce = list4.stream().map(TChargingOrderAccountingStrategy::getPeriodServicePrice).reduce(BigDecimal.ZERO, BigDecimal::add);
                    BigDecimal chargingCapacity = list4.stream().map(TChargingOrderAccountingStrategy::getChargingCapacity).reduce(BigDecimal.ZERO, BigDecimal::add);
                    BigDecimal serviceMoney = BigDecimal.ZERO;
                    BigDecimal paymentMoney = BigDecimal.ZERO;
                    long time = 0;
                    if (!order.getOrderSource().equals(2)) {
                        serviceMoney = serviceMoney.add(service_reduce);
                        paymentMoney = paymentMoney.add(electronic_reduce).add(service_reduce);
                    } else {
                        serviceMoney = serviceMoney.add(service_reduce.multiply(new BigDecimal("0.8")));
                        paymentMoney = paymentMoney.add(electronic_reduce).add(service_reduce.multiply(new BigDecimal("0.8")));
                    }
                    if (order.getStartTime() != null && order.getEndTime() != null) {
                        time = ChronoUnit.SECONDS.between(order.getStartTime(), order.getEndTime());
                    }
                    TChargingOrderSummaryData summaryData = new TChargingOrderSummaryData();
                    summaryData.setChargingOrderId(order.getId());
                    summaryData.setChargingCapacity(chargingCapacity.setScale(6, RoundingMode.HALF_EVEN));
                    summaryData.setChargingDuration(time);
                    summaryData.setIncome(paymentMoney.setScale(2, BigDecimal.ROUND_HALF_EVEN));
                    summaryData.setElectricPrice(electronic_reduce.setScale(2, BigDecimal.ROUND_HALF_EVEN));
                    summaryData.setServicePrice(serviceMoney.setScale(2, BigDecimal.ROUND_HALF_EVEN));
                    chargingOrderSummaryDataService.save(summaryData);
                    //推送监管平台订单状态和订单详情
                    ChargingOrderVo chargingOrderVo = new ChargingOrderVo();
                    BeanUtils.copyProperties(order, chargingOrderVo);
                    chargingMessageClient.pushOrderInfo(chargingOrderVo);
                    chargingMessageClient.pushOrderStatus(chargingOrderVo);
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
    /**
     * 添加充电算账单汇总数据
     */
    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 {
            if (billingMonth == null) {
                throw new IllegalArgumentException("账单月份不能为空");
            }
                LocalDate firstDayOfBillingMonth = billingMonth.withDayOfMonth(2);
                String string = firstDayOfBillingMonth.toString();
                // 将-替换为空字符串
                string = string.replace("-", "");
                String targetMonth = billingMonth.format(DateTimeFormatter.ofPattern("yyyy-MM"));
                //统计数据的开始时间
                String startTime = targetMonth + "-01 00:00:00";
                //统计数据的结束时间
                int lastDay = billingMonth.with(TemporalAdjusters.lastDayOfMonth()).getDayOfMonth();
                String endTime = targetMonth + "-" + String.format("%02d", lastDay) + " 23:59:59";
                LocalDateTime createTime = LocalDateTime.now();
                //删除之前生成的汇总数据,在添加最新的汇总数据
                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 + "'"));
                //循环生成按照开始时间和结束时间分别统计的汇总数据
                for (int i = 1; i < 3; i++) {
                    TChargingSettlementBill chargingSettlementBill = new TChargingSettlementBill();
                    // 订单生成规则JSD+20231201(账单所属月份)+1131304205(随机10位数)+001(当月账单序号,每月重置)
                    Random random = new Random();
                    String randomDigits = random.ints(10, 0, 10) // 生成10个随机数字,范围在0-9
                            .mapToObj(String::valueOf)
                            .collect(Collectors.joining()); // 将其连接成一个字符串
                    chargingSettlementBill.setSiteId(0);
                    chargingSettlementBill.setStatisticalDateType(i);
                    chargingSettlementBill.setBillingCycle(firstDayOfBillingMonth);
                    chargingSettlementBill.setStatus(1);
                    chargingSettlementBill.setCode("JSD"+string+randomDigits);
                    //根据业务订单查询汇总数据
                    List<Map<String, Object>> mapList = chargingOrderService.getChargingSettlementBill(startTime, endTime, i);
                    Long chargingDuration = 0L;
                    Integer orderNumber = 0;
                    BigDecimal totalAmount = BigDecimal.ZERO;
                    BigDecimal platformFee = BigDecimal.ZERO;
                    BigDecimal tripartiteCommission = BigDecimal.ZERO;
                    BigDecimal fundsReceived = BigDecimal.ZERO;
                    BigDecimal totalElectricity = BigDecimal.ZERO;
                    BigDecimal totalElectricityCharge = BigDecimal.ZERO;
                    BigDecimal totalServiceFee = BigDecimal.ZERO;
                    BigDecimal couponDeduction = BigDecimal.ZERO;
                    List<TChargingSettlementBill> list = new ArrayList<>();
                    for (Map<String, Object> map : mapList) {
                        Long charging_duration = null == map.get("chargingDuration") ? 0L : Long.valueOf(map.get("chargingDuration").toString());
                        Integer order_number = null == map.get("orderNum") ? 0 : Integer.valueOf(map.get("orderNum").toString());
                        BigDecimal total_amount = null == map.get("totalAmount") ? BigDecimal.ZERO : new BigDecimal(map.get("totalAmount").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 funds_received = total_amount.subtract(platform_fee).subtract(tripartite_commission);
                        BigDecimal total_electricity = null == map.get("totalElectricity") ? BigDecimal.ZERO : new BigDecimal(map.get("totalElectricity").toString());
                        BigDecimal total_electricity_charge = null == map.get("totalElectricityCharge") ? BigDecimal.ZERO : new BigDecimal(map.get("totalElectricityCharge").toString());
                        BigDecimal total_service_fee = null == map.get("totalServiceFee") ? BigDecimal.ZERO : new BigDecimal(map.get("totalServiceFee").toString());
                        BigDecimal coupon_deduction = null == map.get("couponDeduction") ? BigDecimal.ZERO : new BigDecimal(map.get("couponDeduction").toString());
                        //构建每个站点的汇总数据
                        TChargingSettlementBill chargingSettlementBill1 = new TChargingSettlementBill();
                        String randomDigits1 = random.ints(10, 0, 10) // 生成10个随机数字,范围在0-9
                                .mapToObj(String::valueOf)
                                .collect(Collectors.joining()); // 将其连接成一个字符串
                        chargingSettlementBill1.setSiteId(Integer.valueOf(map.get("siteId").toString()));
                        chargingSettlementBill1.setStatisticalDateType(i);
                        chargingSettlementBill1.setBillingCycle(firstDayOfBillingMonth);
                        chargingSettlementBill1.setStatus(1);
                        chargingSettlementBill1.setCode("JSD"+string+randomDigits1);
                        chargingSettlementBill1.setChargingDuration(charging_duration);
                        chargingSettlementBill1.setOrderNumber(order_number);
                        chargingSettlementBill1.setTotalAmount(total_amount.setScale(2, RoundingMode.HALF_EVEN));
                        chargingSettlementBill1.setCouponDeduction(coupon_deduction.setScale(2, RoundingMode.HALF_EVEN));
                        chargingSettlementBill1.setPlatformFee(platform_fee.setScale(2, RoundingMode.HALF_EVEN));
                        chargingSettlementBill1.setTripartiteCommission(tripartite_commission.setScale(2, RoundingMode.HALF_EVEN));
                        chargingSettlementBill1.setFundsReceived(funds_received.setScale(2, RoundingMode.HALF_EVEN));
                        chargingSettlementBill1.setTotalElectricity(total_electricity.setScale(4, RoundingMode.HALF_EVEN));
                        chargingSettlementBill1.setTotalElectricityCharge(total_electricity_charge.setScale(2, RoundingMode.HALF_EVEN));
                        chargingSettlementBill1.setTotalServiceFee(total_service_fee.setScale(2, RoundingMode.HALF_EVEN));
                        chargingSettlementBill1.setCreateTime(createTime);
                        list.add(chargingSettlementBill1);
                        //计算全站汇总数据
                        chargingDuration = chargingDuration + charging_duration;
                        orderNumber = orderNumber + order_number;
                        totalAmount = totalAmount.add(total_amount);
                        platformFee = platformFee.add(platform_fee);
                        tripartiteCommission = tripartiteCommission.add(tripartite_commission);
                        fundsReceived = fundsReceived.add(funds_received);
                        totalElectricity = totalElectricity.add(total_electricity);
                        totalElectricityCharge = totalElectricityCharge.add(total_electricity_charge);
                        totalServiceFee = totalServiceFee.add(total_service_fee);
                        couponDeduction = couponDeduction.add(coupon_deduction);
                    }
                    chargingSettlementBill.setChargingDuration(chargingDuration);
                    chargingSettlementBill.setOrderNumber(orderNumber);
                    chargingSettlementBill.setTotalAmount(totalAmount.setScale(2, RoundingMode.HALF_EVEN));
                    chargingSettlementBill.setCouponDeduction(couponDeduction.setScale(2, RoundingMode.HALF_EVEN));
                    chargingSettlementBill.setPlatformFee(platformFee.setScale(2, RoundingMode.HALF_EVEN));
                    chargingSettlementBill.setTripartiteCommission(tripartiteCommission.setScale(2, RoundingMode.HALF_EVEN));
                    chargingSettlementBill.setFundsReceived(fundsReceived.setScale(2, RoundingMode.HALF_EVEN));
                    chargingSettlementBill.setTotalElectricity(totalElectricity.setScale(4, RoundingMode.HALF_EVEN));
                    chargingSettlementBill.setTotalElectricityCharge(totalElectricityCharge.setScale(2, RoundingMode.HALF_EVEN));
                    chargingSettlementBill.setTotalServiceFee(totalServiceFee.setScale(2, RoundingMode.HALF_EVEN));
                    chargingSettlementBill.setCreateTime(createTime);
                    chargingSettlementBillService.save(chargingSettlementBill);
                    chargingSettlementBillService.saveBatch(list);
                }
        } catch (Exception e) {
            log.error("生成{}充电结算账单失败", billingMonth, e);
            throw new RuntimeException("生成充电结算账单失败", e);
        }
    }
    /**
     * 添加账户结算账单数据
     */
    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 {
                if (billingMonth == null) {
                    throw new IllegalArgumentException("账单月份不能为空");
                }
                LocalDate firstDayOfBillingMonth = billingMonth.withDayOfMonth(2);
                String string = firstDayOfBillingMonth.toString();
                // 将-替换为空字符串
                string = string.replace("-", "");
                String targetMonth = billingMonth.format(DateTimeFormatter.ofPattern("yyyy-MM"));
                //统计数据的开始时间
                String startTime = targetMonth + "-01 00:00:00";
                //统计数据的结束时间
                int targetLastDay = billingMonth.with(TemporalAdjusters.lastDayOfMonth()).getDayOfMonth();
                String endTime = targetMonth + "-" + String.format("%02d", targetLastDay) + " 23:59:59";
                LocalDateTime createTime = LocalDateTime.now();
                //删除之前生成的汇总数据,在添加最新的汇总数据
                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 + "'"));
                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();
                    String randomDigits = random.ints(10, 0, 10) // 生成10个随机数字,范围在0-9
                            .mapToObj(String::valueOf)
                            .collect(Collectors.joining()); // 将其连接成一个字符串
                    accountSettlementStatement.setSiteId(0);
                    accountSettlementStatement.setAccountType(i);
                    accountSettlementStatement.setBillingCycle(firstDayOfBillingMonth);
                    accountSettlementStatement.setStatus(1);
                    accountSettlementStatement.setCode("JSD"+string+randomDigits);
                    //根据业务订单查询汇总数据
                    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 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(siteId);
                        accountSettlementStatement1.setAccountType(i);
                        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(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);
                        recordedAmount = recordedAmount.add(recorded_amount);
                        platformIncome = platformIncome.add(platform_income);
                        partnerIncome = partnerIncome.add(partner_income);
                    }
                    accountSettlementStatement.setRechargeAmount(rechargeAmount.setScale(2, RoundingMode.HALF_EVEN));
                    accountSettlementStatement.setRefundAmount(refundAmount.setScale(2, RoundingMode.HALF_EVEN));
                    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) {
            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;
    }
    /**
     * 推送三方引流平台充电数据
     */
    public void pushOrderDrainagePlatform(){
        String format = LocalDateTime.now().minusDays(1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        List<TChargingOrder> list = chargingOrderService.list(new LambdaQueryWrapper<TChargingOrder>().eq(TChargingOrder::getStatus, 5)
                .eq(TChargingOrder::getOrderSource, 2).eq(TChargingOrder::getDelFlag, 0)
                .isNotNull(TChargingOrder::getStartChargeSeq).isNotNull(TChargingOrder::getOperatorId)
                .last(" and DATE_FORMAT(end_time, '%Y-%m-%d') = '" + format + "'"));
        for (TChargingOrder tChargingOrder : list) {
            String code = tChargingOrder.getCode();
            chargingOrderService.pushOrderInfo(code);
        }
    }
}