Pu Zhibing
13 小时以前 9bc378e6bb9b4563a0dec222e1c2d5d3278632cb
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/util/task/TaskUtil.java
@@ -1,164 +1,763 @@
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.ruoyi.account.api.feignClient.AppCouponClient;
import com.ruoyi.account.api.feignClient.AppUserClient;
import com.ruoyi.account.api.feignClient.AppUserIntegralChangeClient;
import com.ruoyi.account.api.feignClient.AppUserVipDetailClient;
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.Site;
import com.ruoyi.order.api.model.TChargingBill;
import com.ruoyi.order.service.TChargingBillService;
import com.ruoyi.chargingPile.api.model.TChargingGun;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.integration.api.feignClient.ChargingMessageClient;
import com.ruoyi.integration.api.feignClient.TCECClient;
import com.ruoyi.integration.api.feignClient.UploadRealTimeMonitoringDataClient;
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.*;
import com.ruoyi.order.api.vo.AccountingStrategyDetailOrderVo;
import com.ruoyi.order.api.vo.TransactionRecordMessageVO;
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.feignClient.IntegralRuleClient;
import com.ruoyi.other.api.feignClient.VipClient;
import com.ruoyi.payment.api.feignClient.AliPaymentClient;
import com.ruoyi.payment.api.feignClient.H5AliPaymentClient;
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 lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.core.util.UuidUtil;
import org.apache.poi.util.StringUtil;
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 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.util.*;
import java.util.stream.Collectors;
/**
 * @author zhibing.pu
 * @date 2023/7/11 8:39
 */
@Slf4j
@Component
public class TaskUtil {
public class TaskUtil implements ApplicationListener<WebServerInitializedEvent> {
    @Resource
    private TChargingBillService chargingBillService;
    @Resource
    private SiteClient siteClient;
    @Resource
    private TChargingOrderService chargingOrderService;
    @Resource
    private TChargingOrderRefundService chargingOrderRefundService;
    @Resource
    private UploadRealTimeMonitoringDataService uploadRealTimeMonitoringDataService;
    @Resource
    private TransactionRecordService transactionRecordService;
    @Resource
    private ChargingMessageClient chargingMessageClient;
    private Integer port = null;
    @Resource
    private AccountingStrategyDetailOrderService accountingStrategyDetailOrderService;
    public static void main(String[] args) {
        LocalDate firstDayOfLastMonth = LocalDate.now().minusMonths(1).
                withDayOfMonth(2);
        String string = firstDayOfLastMonth.toString();
        // 将-替换为空字符串
        string = string.replace("-", "");
        System.err.println(string);
    @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 WxPaymentClient wxPaymentClient;
    @Resource
    private AliPaymentClient aliPaymentClient;
    @Resource
    private H5AliPaymentClient h5AliPaymentClient;
    @Resource
    private ITChargingOrderSummaryDataService chargingOrderSummaryDataService;
    //十分钟循环执行的定时任务
    @Scheduled(fixedRate = 1000 * 60 * 10)
    public void taskTenMinutes() {
        if(null != port && port == 5400){
            List<TChargingOrder> failedStartupOrder = chargingOrderService.findFailedStartupOrder();
            log.info("定时任务执行,查询到启动失败的订单数量:{}", failedStartupOrder.size());
            for (TChargingOrder order : failedStartupOrder) {
                log.info("定时任务执行,查询到启动失败的订单:{}", order.getCode());
                //查询是否有充电信息
                List<UploadRealTimeMonitoringData> dataByOrderCode = uploadRealTimeMonitoringDataService.getDataByOrderCode(order.getCode());
                log.info("充电实时数据:{}", dataByOrderCode.size());
                //没有充电数据,则执行退款
                if(null == dataByOrderCode || dataByOrderCode.isEmpty()){
                    log.info("定时任务执行,查询到启动失败的订单,执行退款:{}", order.getCode());
                    if(1 == order.getOrderSource()){
                        chargingOrderService.refund(order.getCode());
                        int num = 0;
                        while (true){
                            TChargingOrderRefund one = chargingOrderRefundService.getOne(new LambdaQueryWrapper<TChargingOrderRefund>().eq(TChargingOrderRefund::getChargingOrderId, order.getId()));
                            if(null != one && 2 == one.getRefundStatus()){
                                order.setStatus(-1);
                                chargingOrderService.updateById(order);
                                break;
                            }
                            try {
                                Thread.sleep(5000);
                            } catch (InterruptedException e) {
                                throw new RuntimeException(e);
                            }
                            num++;
                            if(num > 10){
                                break;
                            }
                        }
                    }else{
                        order.setStatus(-1);
                        chargingOrderService.updateById(order);
                    }
                }
            }
            //处理退款中的数据
            List<TChargingOrder> stoppedOrder = chargingOrderService.findStoppedOrder();
            log.info("定时任务执行,查询到停止中的订单数量:{}", stoppedOrder.size());
            for (TChargingOrder order : stoppedOrder) {
                log.info("定时任务执行,查询到停止中的订单:{}", order.getCode());
                TransactionRecord one = transactionRecordService.findOne(order.getCode());
                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())));
                    }
                    if(null == order.getEndTime()){
                        order.setEndTime(LocalDateTime.parse(one.getEnd_time(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SS").withZone(ZoneId.systemDefault())));
                    }
                    chargingOrderService.updateById(order);
                    TransactionRecordMessageVO vo = new TransactionRecordMessageVO();
                    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());
            for (TChargingOrder order : chargingOrder) {
                log.info("定时任务执行,查询到充电中的订单:{}", order.getCode());
                TransactionRecord one = transactionRecordService.findOne(order.getCode());
                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())));
                    }
                    if(null == order.getEndTime()){
                        order.setEndTime(LocalDateTime.parse(one.getEnd_time(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SS").withZone(ZoneId.systemDefault())));
                    }
                    chargingOrderService.updateById(order);
                    TransactionRecordMessageVO vo = new TransactionRecordMessageVO();
                    BeanUtils.copyProperties(one, vo);
                    R r = chargingOrderService.endChargeBillingCharge(vo);
                    log.info("定时任务执行,充电中的订单处理结果:{}", JSON.toJSONString(r));
                }
            }
            //处理还未退款,但是订单状态已结束的数据
            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);
            }
        }
    }
    // 每月2号凌晨12点执行的定时任务
//    @Scheduled(cron = "0 0 0 2 * ?")
    // 每天凌晨12点执行的定时任务
@Scheduled(cron = "0 0 12 1 * ?")
//@Scheduled(fixedRate = 60000)
    @Scheduled(cron = "0 0 0 2 * ?")
    public void taskMonth() {
        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
        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()); // 将其连接成一个字符串
                tChargingBill2.setCode("JSD"+string+randomDigits2+(i+1) );
                tChargingBill2.setType(2);
                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
                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()); // 将其连接成一个字符串
                tChargingBill3.setCode("JSD"+string+randomDigits3+(i+1) );
                tChargingBill3.setType(2);
                tChargingBill3.setSiteId(collect.get(i));
                tChargingBill3.setBillTime(LocalDateTime.now());
                tChargingBill3.setBillType(1);
                tChargingBill3.setStatus(1);
                tChargingBill3.setOrderState(2);
                tChargingBills1.add(tChargingBill3);
                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();
            }
            System.err.println("列表"+tChargingBills);
            if (!tChargingBills.isEmpty())chargingBillService.saveBatch(tChargingBills);
            if (!tChargingBills1.isEmpty())chargingBillService.saveBatch(tChargingBills1);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    // 每天晚上23:59:59执行的定时任务
    @Scheduled(cron = "0 0 23 1 * ?")
    // 每个月最后一天23点执行的定时任务
    @Scheduled(cron = "0 0 23 * * ?")
    public void taskLastDay() {
        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);
        if(null != port && port == 5400){
            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);
                }
                chargingBillService.updateBatchById(list);
            } catch (Exception e) {
                e.printStackTrace();
            }
            chargingBillService.updateBatchById(list);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    @Override
    public void onApplicationEvent(WebServerInitializedEvent event) {
        port = event.getWebServer().getPort();
        System.out.println("端口号:" + port);
    }
    public void endOrder(TChargingOrder order){
        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 (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 (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());
                    }
                }
            }
            //优惠券优惠金额
            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.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);
            chargingOrderService.updateById(order);
            order = chargingOrderService.getById(order.getId());
            //推送三方平台
            if (2 == order.getOrderSource()) {
                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()) {
                tcecClient.pushChargingGunStatus(chargingGun.getFullNumber(), 2);
            }
            //添加积分
            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);
                if (refundAmount.compareTo(BigDecimal.ZERO) > 0) {
                    Integer rechargePaymentType = order.getRechargePaymentType();
                    //构建退款明细
                    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.setRefundStatus(1);
                    chargingOrderRefund.setCode(order.getCode());
                    chargingOrderRefund.setRefundTitle("充电完成退款");
                    chargingOrderRefund.setRefundContent("充电完成退款");
                    chargingOrderRefund.setRefundReason("充电完成退款");
                    chargingOrderRefund.setRefundRemark("实际充电消费金额:" + order.getPaymentAmount());
                    chargingOrderRefund.setRefundTotalAmount(refundAmount);
                    chargingOrderRefund.setPayAmount(rechargeAmount);
                    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(refundAmount.multiply(new BigDecimal(100)).intValue());
                        amount.setTotal(rechargeAmount.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);
                        }
                    }
                    if (2 == rechargePaymentType) {
                        RefundReq dto = new RefundReq();
                        dto.setOutTradeNo(order.getCode());
                        dto.setOutRequestNo(chargingOrderRefund.getRefundCode());
                        dto.setRefundAmount(refundAmount.toString());
                        dto.setRefundReason("充电完成退款");
                        RefundResp resp = aliPaymentClient.refund(dto).getData();
                        if (null != resp) {
                            chargingOrderRefundService.save(chargingOrderRefund);
                            chargingOrderService.chargingOrderStartupFailureWxRefund(chargingOrderRefund.getRefundCode(), resp.getTradeNo(), "SUCCESS", null);
                        }
                    }
                    if (3 == rechargePaymentType) {
                        RefundReq dto = new RefundReq();
                        dto.setOutTradeNo(order.getRechargeSerialNumber());
                        dto.setOutRequestNo(chargingOrderRefund.getRefundCode());
                        dto.setRefundAmount(refundAmount.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);
                        }
                    }
                }
            }
            //添加汇总统计数据
            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);
            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);
        }
    }
}