From 9af2c277033957c095d1090c8e6f77e54b86172f Mon Sep 17 00:00:00 2001
From: shinnosuke <tantao@1hoper.com>
Date: 星期四, 02 七月 2026 16:58:59 +0800
Subject: [PATCH] 新增企业用户充电分析功能页(包含充电明细);新增系统用户管理中的重置操作密码功能;在角色管理中增加独立合作商角色;角色管理中的添加角色操作新增数据驾驶舱和视频监控入口(需在角色管理员有按钮权限控制)。

---
 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java | 1633 ++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 1,473 insertions(+), 160 deletions(-)

diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java
index 118a94b..85f821c 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java
@@ -9,6 +9,7 @@
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.account.api.feignClient.*;
 import com.ruoyi.account.api.model.*;
+import com.ruoyi.account.api.vo.AppUserWhitelistMatchVO;
 import com.ruoyi.account.api.vo.GetAppUserVipDetail;
 import com.ruoyi.account.api.vo.GetInviteUser;
 import com.ruoyi.chargingPile.api.dto.GetSiteListDTO;
@@ -18,6 +19,7 @@
 import com.ruoyi.common.core.domain.R;
 import com.ruoyi.common.core.dto.ChargingOrderGroup;
 import com.ruoyi.common.core.dto.ChargingPercentProvinceDto;
+import com.ruoyi.common.core.exception.ServiceException;
 import com.ruoyi.common.core.web.domain.AjaxResult;
 import com.ruoyi.common.core.web.domain.BasePojo;
 import com.ruoyi.common.core.web.page.PageInfo;
@@ -69,9 +71,7 @@
 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 com.ruoyi.payment.api.model.*;
 import com.ruoyi.payment.api.vo.*;
 import com.ruoyi.system.api.domain.SysUser;
 import com.ruoyi.system.api.feignClient.SysUserClient;
@@ -115,7 +115,10 @@
 public class TChargingOrderServiceImpl extends ServiceImpl<TChargingOrderMapper, TChargingOrder> implements TChargingOrderService {
 	
 	private Logger log = LoggerFactory.getLogger(TChargingOrderServiceImpl.class);
-	
+	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 ChargingGunClient chargingGunClient;
 	@Resource
@@ -149,7 +152,9 @@
 	
 	@Resource
 	private AppCouponClient appCouponClient;
-	
+	@Resource
+	private AppUserWhitelistClient appUserWhitelistClient;
+
 	@Resource
 	private AppUserVipDetailClient appUserVipDetailClient;
 	
@@ -205,7 +210,7 @@
 	private VipClient vipClient;
 	@Resource
 	private OtherClient otherClient;
-	
+
 	@Resource
 	private UserTagClient userTagClient;
 	
@@ -373,7 +378,7 @@
 			}
 			myChargingOrderInfo.setPower(power);
 		}
-		myChargingOrderInfo.setActionable(myChargingOrderInfo.getEndTime() + 604800000L < System.currentTimeMillis() ? 0 : 1);
+		myChargingOrderInfo.setActionable(myChargingOrderInfo.getEndTime()==null || myChargingOrderInfo.getEndTime() + 604800000L < System.currentTimeMillis() ? 0 : 1);
 		long count = orderAppealService.count(Wrappers.lambdaQuery(TOrderAppeal.class)
 				.eq(TOrderAppeal::getOrderId, id));
 		myChargingOrderInfo.setIsAppeal(count > 0 ? 0 : 1);
@@ -421,15 +426,53 @@
 	 * @param addChargingOrder
 	 * @return
 	 */
-	
+
+    /**
+     * 判断订单是否使用余额或余额组合支付
+     *
+     * @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 (Integer.valueOf(3).equals(order.getPayMethod())) {
+            return money(order.getRechargeAmount());
+        }
+        return thirdPayAmount;
+    }
+
+    /**
+     * 调整用户余额
+     *
+     * @param userId 用户ID
+     * @param delta 余额变动金额
+     */
     private void changeUserBalance(Long userId, BigDecimal delta) {
         if (userId == null || delta == null || delta.compareTo(BigDecimal.ZERO) == 0) {
             return;
@@ -441,12 +484,137 @@
         appUser.setBalance(money(appUser.getBalance()).add(delta).setScale(2, RoundingMode.HALF_UP));
         appUserClient.updateAppUser(appUser);
     }
+
+
+    /**
+     * 记录兑换码余额消费流水
+     *
+     * @param chargingOrder 充电订单
+     * @param consumeAmount 消费金额
+     */
+    private void recordBalanceConsume(TChargingOrder chargingOrder, BigDecimal consumeAmount) {
+        if (chargingOrder == null || chargingOrder.getAppUserId() == null || chargingOrder.getId() == null
+                || consumeAmount == null || consumeAmount.compareTo(BigDecimal.ZERO) <= 0) {
+            return;
+        }
+        ExchangeCodeConsumeDTO consumeDTO = new ExchangeCodeConsumeDTO();
+        consumeDTO.setUserId(chargingOrder.getAppUserId());
+        consumeDTO.setOrderId(chargingOrder.getId());
+        consumeDTO.setAmount(consumeAmount);
+        R<ExchangeCodeConsumeResultVO> result = otherClient.consumeExchangeCodeBalance(consumeDTO);
+        if (result == null || result.getCode() != 200) {
+            throw new RuntimeException("扣减兑换码余额失败");
+        }
+    }
+
+    /**
+     * 记录兑换码余额退款流水
+     *
+     * @param chargingOrder 充电订单
+     * @param refundAmount 退款金额
+     * @param refundNo 退款单号
+     */
+    private void recordBalanceRefund(TChargingOrder chargingOrder, BigDecimal refundAmount, String refundNo) {
+        if (chargingOrder == null || chargingOrder.getAppUserId() == null || chargingOrder.getId() == null
+                || refundAmount == null || refundAmount.compareTo(BigDecimal.ZERO) <= 0) {
+            return;
+        }
+        ExchangeCodeConsumeDTO refundDTO = new ExchangeCodeConsumeDTO();
+        refundDTO.setUserId(chargingOrder.getAppUserId());
+        refundDTO.setOrderId(chargingOrder.getId());
+        refundDTO.setAmount(refundAmount);
+        refundDTO.setRefundNo(refundNo);
+        R<ExchangeCodeConsumeResultVO> result = otherClient.refundExchangeCodeBalance(refundDTO);
+        if (result == null || result.getCode() != 200) {
+            throw new RuntimeException("退还兑换码余额失败");
+        }
+    }
+
+	/**
+	 * 完成人工退款结果落库,并同步余额退款流水
+	 *
+	 * @param chargingOrder 充电订单
+	 * @param refund 退款记录
+	 * @param refundAmount 退款总金额
+	 * @param balanceRefundAmount 余额退款金额
+	 * @param thirdRefundAmount 三方退款金额
+	 */
+	private void finishManualChargingRefund(TChargingOrder chargingOrder, TChargingOrderRefund refund,
+	                                            BigDecimal refundAmount, BigDecimal balanceRefundAmount, BigDecimal thirdRefundAmount) {
+        chargingOrder.setRefundStatus(2);
+        chargingOrder.setRefundAmount(money(chargingOrder.getRefundAmount()).add(refundAmount));
+        chargingOrder.setBalanceRefundAmount(money(chargingOrder.getBalanceRefundAmount()).add(balanceRefundAmount));
+        chargingOrder.setThirdRefundAmount(money(chargingOrder.getThirdRefundAmount()).add(thirdRefundAmount));
+        this.baseMapper.updateById(chargingOrder);
+        refund.setRefundStatus(2);
+        chargingOrderRefundService.save(refund);
+        if (balanceRefundAmount.compareTo(BigDecimal.ZERO) > 0) {
+            changeUserBalance(chargingOrder.getAppUserId(), balanceRefundAmount);
+            recordBalanceRefund(chargingOrder, balanceRefundAmount, refund.getRefundCode());
+        }
+    }
+
+    /**
+     * 判断订单是否为白名单订单
+     *
+     * @param chargingOrder 充电订单
+     * @return true=白名单订单
+     */
+    private boolean isWhitelistOrder(TChargingOrder chargingOrder) {
+        return chargingOrder != null && Integer.valueOf(1).equals(chargingOrder.getIsWhitelist());
+    }
+
+    /**
+     * 判断订单是否为白名单全部免费权益
+     *
+     * @param chargingOrder 充电订单
+     * @return true=全部免费白名单订单
+     */
+    private boolean isWhitelistAllFreeOrder(TChargingOrder chargingOrder) {
+        return isWhitelistOrder(chargingOrder)
+                && Integer.valueOf(WHITELIST_BENEFIT_ALL_FREE).equals(chargingOrder.getWhitelistBenefitType());
+    }
+
+    /**
+     * 按白名单权益拆分电费和服务费减免金额,财务统计需要分开展示两类退款金额
+     *
+     * @param chargingOrder 充电订单
+     * @param electrovalence 原始电费
+     * @param serviceCharge 原始服务费
+     * @return 数组下标0=电费减免,下标1=服务费减免
+     */
+    private BigDecimal[] calculateWhitelistRefundSplit(TChargingOrder chargingOrder, BigDecimal electrovalence, BigDecimal serviceCharge) {
+        BigDecimal electricDiscount = BigDecimal.ZERO;
+        BigDecimal serviceDiscount = BigDecimal.ZERO;
+        if (!isWhitelistOrder(chargingOrder)) {
+            return new BigDecimal[]{electricDiscount, serviceDiscount};
+        }
+        if (Integer.valueOf(WHITELIST_BENEFIT_ALL_FREE).equals(chargingOrder.getWhitelistBenefitType())) {
+            electricDiscount = electrovalence == null ? BigDecimal.ZERO : electrovalence;
+            serviceDiscount = serviceCharge == null ? BigDecimal.ZERO : serviceCharge;
+        } else if (Integer.valueOf(WHITELIST_BENEFIT_ELECTRIC_FREE).equals(chargingOrder.getWhitelistBenefitType())) {
+            electricDiscount = electrovalence == null ? BigDecimal.ZERO : electrovalence;
+        } else if (Integer.valueOf(WHITELIST_BENEFIT_SERVICE_FREE).equals(chargingOrder.getWhitelistBenefitType())) {
+            serviceDiscount = serviceCharge == null ? BigDecimal.ZERO : serviceCharge;
+        }
+        return new BigDecimal[]{electricDiscount, serviceDiscount};
+    }
+
 	@Override
 	public AjaxResult paymentChargingOrder(AddChargingOrder addChargingOrder) {
 		Long userId = tokenService.getLoginUserApplet().getUserId();
 		TAppUser appUser = appUserClient.getUserById(userId).getData();
 		Integer payMethod = addChargingOrder.getPayMethod() == null ? 3 : addChargingOrder.getPayMethod();
 		BigDecimal rechargeAmount = money(addChargingOrder.getPaymentAmount());
+		TChargingGun tChargingGun = chargingGunClient.getChargingGunById(addChargingOrder.getId()).getData();
+		TChargingPile chargingPile = chargingPileClient.getChargingPileById(tChargingGun.getChargingPileId()).getData();
+		AppUserWhitelistMatchVO whitelist = appUserWhitelistClient.matchWhitelist(userId, tChargingGun.getSiteId()).getData();
+		boolean whitelistMatched = whitelist != null && Boolean.TRUE.equals(whitelist.getMatched());
+		if (whitelistMatched) {
+			payMethod = 3;
+			addChargingOrder.setPayMethod(3);
+			addChargingOrder.setAppUserCouponId(null);
+		}
 		BigDecimal userBalance = money(appUser.getBalance());
 		BigDecimal balancePayAmount = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
 		BigDecimal thirdPayAmount = rechargeAmount;
@@ -461,6 +629,12 @@
 			}
 			balancePayAmount = payMethod == 1 ? rechargeAmount : userBalance.min(rechargeAmount).setScale(2, RoundingMode.HALF_UP);
 			thirdPayAmount = rechargeAmount.subtract(balancePayAmount).setScale(2, RoundingMode.HALF_UP);
+		}
+		if (whitelistMatched) {
+			balancePayAmount = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
+			thirdPayAmount = Integer.valueOf(WHITELIST_BENEFIT_ALL_FREE).equals(whitelist.getBenefitType())
+					? BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP)
+					: rechargeAmount;
 		}
 		//查询待支付状态的订单,没有支付则删除订单
 		List<TChargingOrder> list = this.list(new LambdaQueryWrapper<TChargingOrder>().eq(TChargingOrder::getAppUserId, userId)
@@ -572,8 +746,6 @@
 				chargingOrder.setPlateNum(userCar.getLicensePlate());
 			}
 		}
-		TChargingGun tChargingGun = chargingGunClient.getChargingGunById(addChargingOrder.getId()).getData();
-		TChargingPile chargingPile = chargingPileClient.getChargingPileById(tChargingGun.getChargingPileId()).getData();
 		chargingOrder.setSiteId(tChargingGun.getSiteId());
 		chargingOrder.setChargingPileId(tChargingGun.getChargingPileId());
 		chargingOrder.setChargingGunId(addChargingOrder.getId());
@@ -586,6 +758,12 @@
 		chargingOrder.setThirdRefundAmount(BigDecimal.ZERO);
 		chargingOrder.setRechargeAmount(rechargeAmount);
 		chargingOrder.setAppCouponId(addChargingOrder.getAppUserCouponId());
+		chargingOrder.setIsWhitelist(whitelistMatched ? 1 : 0);
+		chargingOrder.setWhitelistId(whitelistMatched ? whitelist.getWhitelistId() : null);
+		chargingOrder.setWhitelistBenefitType(whitelistMatched ? whitelist.getBenefitType() : null);
+		chargingOrder.setWhitelistDiscountAmount(BigDecimal.ZERO);
+		chargingOrder.setWhitelistElectricRefundAmount(BigDecimal.ZERO);
+		chargingOrder.setWhitelistServiceRefundAmount(BigDecimal.ZERO);
 		chargingOrder.setVipDiscountAmount(BigDecimal.ZERO);
 		chargingOrder.setOrderSource(1);
 		chargingOrder.setTitle("【充电桩充电】" + chargingPile.getNumber() + "号桩/" + tChargingGun.getCode() + "号枪");
@@ -598,25 +776,29 @@
 		}
 		TAccountingStrategy accountingStrategy = accountingStrategyClient.getAccountingStrategyById(accountingStrategyId).getData();
 		
-		//直营站点才可以享受会员折扣
-		if (!isBalancePayMode(payMethod) && null != appUser.getVipId() && 1 == site.getBusinessCategory()) {
+		//会员折扣支持直营网点和加盟商站点
+		if (!whitelistMatched && !isBalancePayMode(payMethod) && null != appUser.getVipId()) {
 			TVip vip = vipClient.getInfo1(appUser.getVipId()).getData();
-			BigDecimal discount = null;
-			if (1 == vip.getType()) {
-				//普通会员折扣使用积分策略上的折扣,且有最高优惠金额
-				discount = accountingStrategy.getDiscount();
-			} else {
-				//内部会员使用会员信息设置的折扣,没有最高优惠金额
-				discount = vip.getDiscount();
-			}
-			GetAppUserVipDetail getAppUserVipDetail = new GetAppUserVipDetail();
-			getAppUserVipDetail.setAppUserId(appUser.getId());
-			getAppUserVipDetail.setVipId(appUser.getVipId());
-			TAppUserVipDetail vipDetail = appUserVipDetailClient.getAppUserVipDetail(getAppUserVipDetail).getData();
-			if (null != vipDetail) {
-				Integer chargeNum = vipDetail.getChargeNum();
-				if (0 < chargeNum) {
-					chargingOrder.setVipDiscount(discount);
+			if (null != vip) {
+				BigDecimal discount = null;
+				if (Integer.valueOf(1).equals(vip.getType())) {
+					//普通会员折扣使用积分策略上的折扣,且有最高优惠金额
+					discount = accountingStrategy.getDiscount();
+				} else {
+					//内部会员使用会员信息设置的折扣,没有最高优惠金额
+					discount = vip.getDiscount();
+				}
+				if (null != discount) {
+					GetAppUserVipDetail getAppUserVipDetail = new GetAppUserVipDetail();
+					getAppUserVipDetail.setAppUserId(appUser.getId());
+					getAppUserVipDetail.setVipId(appUser.getVipId());
+					TAppUserVipDetail vipDetail = appUserVipDetailClient.getAppUserVipDetail(getAppUserVipDetail).getData();
+					if (null != vipDetail) {
+						Integer chargeNum = vipDetail.getChargeNum();
+						if (null != chargeNum && 0 < chargeNum) {
+							chargingOrder.setVipDiscount(discount);
+						}
+					}
 				}
 			}
 		}
@@ -641,9 +823,10 @@
 		
 		if (thirdPayAmount.compareTo(BigDecimal.ZERO) == 0 && balancePayAmount.compareTo(BigDecimal.ZERO) > 0) {
 			changeUserBalance(userId, balancePayAmount.negate());
+			recordBalanceConsume(chargingOrder, balancePayAmount);
 		}
 		if (thirdPayAmount.compareTo(BigDecimal.ZERO) == 0) {
-			return chargingOrderCallback(addChargingOrder.getPaymentType(), chargingOrder.getCode(), "BALANCE", null);
+			return chargingOrderCallback(addChargingOrder.getPaymentType(), chargingOrder.getCode(), whitelistMatched ? "WHITELIST" : "BALANCE", null);
 		}
 		//会员优惠折扣将其计入增加充电时长(增加总充电金额)
 		//如果充电总金额未使用完,则需要退回费用=(原金额/总金额)*(总金额-实际充电金额)
@@ -712,6 +895,7 @@
 				throw new RuntimeException("余额不足,支付回调处理失败");
 			}
 			changeUserBalance(chargingOrder.getAppUserId(), money(chargingOrder.getBalancePayAmount()).negate());
+			recordBalanceConsume(chargingOrder, money(chargingOrder.getBalancePayAmount()));
 		}
 		chargingOrder.setRechargePaymentStatus(2);
 		chargingOrder.setRechargeSerialNumber(transaction_id);
@@ -724,6 +908,7 @@
 		preChargeCheck.setInsulationTesting(false);
 		preChargeCheck.setSecureConnectionDetection(false);
 		preChargeCheck.setStartupSuccess(1);
+        preChargeCheck.setAddTime(LocalDateTime.now());
 		String key = "AQJC_" + chargingOrder.getChargingGunId();
 		redisService.setCacheObject(key, preChargeCheck, 24L, TimeUnit.HOURS);
 		
@@ -745,7 +930,7 @@
 		
 		TAppUser appUser = appUserClient.getUserById(chargingOrder.getAppUserId()).getData();
 		//判断会员是否还有充电优惠次数,计算会员优惠的折扣金额
-		if (null != appUser.getVipId()) {
+		if (!isWhitelistOrder(chargingOrder) && null != appUser.getVipId()) {
 			GetAppUserVipDetail getAppUserVipDetail = new GetAppUserVipDetail();
 			getAppUserVipDetail.setAppUserId(chargingOrder.getAppUserId());
 			getAppUserVipDetail.setVipId(appUser.getVipId());
@@ -1112,22 +1297,24 @@
                 TChargingOrder chargingOrder = this.getOne(new LambdaQueryWrapper<TChargingOrder>().eq(TChargingOrder::getCode, code));
                 if (chargingOrder.getOrderSource() == 1 && chargingOrder.getStatus() == 2
                         && (chargingOrder.getRefundStatus() == null || chargingOrder.getRefundStatus() != 2)) {
-                    Integer rechargePaymentType = chargingOrder.getRechargePaymentType();
-                    BigDecimal rechargeAmount = money(chargingOrder.getRechargeAmount());
-                    BigDecimal totalRefundAmount = isBalancePayMode(chargingOrder.getPayMethod())
-                            ? money(chargingOrder.getBalancePayAmount()).add(money(chargingOrder.getThirdPayAmount())).setScale(2, RoundingMode.HALF_UP)
-                            : rechargeAmount;
-                    BigDecimal thirdRefundAmount = totalRefundAmount.min(money(chargingOrder.getThirdPayAmount())).setScale(2, RoundingMode.HALF_UP);
-                    if (!isBalancePayMode(chargingOrder.getPayMethod())) {
-                        thirdRefundAmount = totalRefundAmount;
-                    }
-                    BigDecimal balanceRefundAmount = totalRefundAmount.subtract(thirdRefundAmount).min(money(chargingOrder.getBalancePayAmount())).setScale(2, RoundingMode.HALF_UP);
+	                    Integer rechargePaymentType = chargingOrder.getRechargePaymentType();
+	                    BigDecimal rechargeAmount = money(chargingOrder.getRechargeAmount());
+	                    BigDecimal totalRefundAmount = isBalancePayMode(chargingOrder.getPayMethod())
+	                            ? money(chargingOrder.getBalancePayAmount()).add(money(chargingOrder.getThirdPayAmount())).setScale(2, RoundingMode.HALF_UP)
+	                            : rechargeAmount;
+	                    // 白名单全部免费启动失败同样只记录预估金额,避免未支付订单进入实际退款流程。
+	                    BigDecimal recordedRefundAmount = isWhitelistAllFreeOrder(chargingOrder) ? rechargeAmount : totalRefundAmount;
+	                    BigDecimal channelRefundAmount = isWhitelistAllFreeOrder(chargingOrder) ? BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP) : totalRefundAmount;
+                    BigDecimal thirdRefundAmount = channelRefundAmount.min(getRefundableThirdPayAmount(chargingOrder)).setScale(2, RoundingMode.HALF_UP);
+	                    BigDecimal balanceRefundAmount = channelRefundAmount.subtract(thirdRefundAmount).min(money(chargingOrder.getBalancePayAmount())).setScale(2, RoundingMode.HALF_UP);
                     //构建退款明细
                     TChargingOrderRefund chargingOrderRefund = new TChargingOrderRefund();
                     chargingOrderRefund.setChargingOrderId(chargingOrder.getId());
                     SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
                     chargingOrderRefund.setRefundCode("CDF" + sdf.format(new Date()) + Double.valueOf(Math.random() * 1000).intValue());
-                    chargingOrderRefund.setRefundAmount(totalRefundAmount);
+                    chargingOrderRefund.setRefundAmount(recordedRefundAmount);
+                    chargingOrderRefund.setBalanceRefundAmount(balanceRefundAmount);
+                    chargingOrderRefund.setThirdRefundAmount(thirdRefundAmount);
                     chargingOrderRefund.setRefundStatus(1);
                     chargingOrderRefund.setPayType(rechargePaymentType);
                     chargingOrderRefund.setRefundStatus(1);
@@ -1135,27 +1322,27 @@
                     chargingOrderRefund.setRefundTitle("充电失败");
                     chargingOrderRefund.setRefundContent("充电失败");
                     chargingOrderRefund.setRefundReason("充电失败");
-                    chargingOrderRefund.setRefundRemark("全额退款");
-                    chargingOrderRefund.setRefundTotalAmount(totalRefundAmount);
+                    chargingOrderRefund.setRefundRemark(isWhitelistAllFreeOrder(chargingOrder) ? "白名单全部免费,启动失败记录预估退款金额" : "全额退款");
+                    chargingOrderRefund.setRefundTotalAmount(recordedRefundAmount);
                     chargingOrderRefund.setPayAmount(rechargeAmount);
                     chargingOrder.setBalanceRefundAmount(balanceRefundAmount);
                     chargingOrder.setThirdRefundAmount(thirdRefundAmount);
-                    chargingOrder.setRefundAmount(totalRefundAmount);
+                    chargingOrder.setRefundAmount(recordedRefundAmount);
                     chargingOrder.setRefundStatus(thirdRefundAmount.compareTo(BigDecimal.ZERO) > 0 ? 1 : 2);
                     if (thirdRefundAmount.compareTo(BigDecimal.ZERO) == 0) {
                         if (balanceRefundAmount.compareTo(BigDecimal.ZERO) > 0) {
                             changeUserBalance(chargingOrder.getAppUserId(), balanceRefundAmount);
+                            recordBalanceRefund(chargingOrder, balanceRefundAmount, chargingOrderRefund.getRefundCode());
                         }
                         chargingOrderRefund.setRefundStatus(2);
-                        chargingOrderRefund.setRefundSerialNumber("BALANCE");
+                        chargingOrderRefund.setRefundSerialNumber(isWhitelistAllFreeOrder(chargingOrder) ? "WHITELIST" : "BALANCE");
                         chargingOrderRefund.setRefundTime(LocalDateTime.now());
                         chargingOrderRefundService.save(chargingOrderRefund);
                         this.updateById(chargingOrder);
                         return;
                     }
                     this.updateById(chargingOrder);
-                    chargingOrderRefund.setRefundAmount(thirdRefundAmount);
-                    if (1 == rechargePaymentType) {
+                    if (thirdRefundAmount.compareTo(BigDecimal.ZERO) > 0 && 1 == rechargePaymentType) {
                         WxPaymentRefundModel model = new WxPaymentRefundModel();
                         model.setOut_trade_no(chargingOrder.getCode());
                         model.setOut_refund_no(chargingOrderRefund.getRefundCode());
@@ -1163,7 +1350,7 @@
                         model.setNotify_url("/payment/wx/refund/notify");
                         WxPaymentRefundModel.RefundAmount amount = new WxPaymentRefundModel.RefundAmount();
                         amount.setRefund(thirdRefundAmount.multiply(new BigDecimal(100)).intValue());
-                        amount.setTotal((isBalancePayMode(chargingOrder.getPayMethod()) ? money(chargingOrder.getThirdPayAmount()) : rechargeAmount).multiply(new BigDecimal(100)).intValue());
+                        amount.setTotal(getRefundableThirdPayAmount(chargingOrder).multiply(new BigDecimal(100)).intValue());
                         amount.setCurrency("CNY");
                         model.setAmount(amount);
                         R<Map<String, Object>> orderR = wxPaymentClient.refundOrderR(model);
@@ -1268,12 +1455,29 @@
 		if (chargingOrder.getOrderSource() == 1) {
 			BigDecimal rechargeAmount = chargingOrder.getRechargeAmount();
 			Integer rechargePaymentType = chargingOrder.getRechargePaymentType();
+			Integer payMethod = chargingOrder.getPayMethod();
 			//构建退款明细
 			TChargingOrderRefund chargingOrderRefund = new TChargingOrderRefund();
 			chargingOrderRefund.setChargingOrderId(chargingOrder.getId());
 			SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
 			chargingOrderRefund.setRefundCode("CDF" + sdf.format(new Date()) + Double.valueOf(Math.random() * 1000).intValue());
 			chargingOrderRefund.setRefundAmount(money);
+			BigDecimal thirdRefundAmount = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
+			BigDecimal balanceRefundAmount = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
+			if (Integer.valueOf(1).equals(payMethod)) {
+				balanceRefundAmount = money.min(money(chargingOrder.getBalancePayAmount())).setScale(2, RoundingMode.HALF_UP);
+			} else if (Integer.valueOf(2).equals(payMethod)) {
+				BigDecimal refundableThirdAmount = money(chargingOrder.getThirdPayAmount()).subtract(money(chargingOrder.getThirdRefundAmount()));
+				if (refundableThirdAmount.compareTo(BigDecimal.ZERO) < 0) {
+					refundableThirdAmount = BigDecimal.ZERO;
+				}
+				thirdRefundAmount = money.min(refundableThirdAmount).setScale(2, RoundingMode.HALF_UP);
+				balanceRefundAmount = money.subtract(thirdRefundAmount).min(money(chargingOrder.getBalancePayAmount())).setScale(2, RoundingMode.HALF_UP);
+			} else {
+				thirdRefundAmount = money;
+			}
+			chargingOrderRefund.setBalanceRefundAmount(balanceRefundAmount);
+			chargingOrderRefund.setThirdRefundAmount(thirdRefundAmount);
 			chargingOrderRefund.setRefundStatus(1);
 			chargingOrderRefund.setPayType(rechargePaymentType);
 			chargingOrderRefund.setRefundStatus(1);
@@ -1284,6 +1488,11 @@
 			chargingOrderRefund.setRefundRemark("充电完成退款,手动退款");
 			chargingOrderRefund.setRefundTotalAmount(money);
 			chargingOrderRefund.setPayAmount(money);
+			if (thirdRefundAmount.compareTo(BigDecimal.ZERO) == 0) {
+				chargingOrderRefund.setRefundSerialNumber("BALANCE");
+				finishManualChargingRefund(chargingOrder, chargingOrderRefund, money, balanceRefundAmount, thirdRefundAmount);
+				return;
+			}
 			if (1 == rechargePaymentType) {
 				WxPaymentRefundModel model = new WxPaymentRefundModel();
 				model.setOut_trade_no(chargingOrder.getCode());
@@ -1291,8 +1500,8 @@
 				model.setReason("充电完成退款");
 				model.setNotify_url("/payment/wx/refund/notify");
 				WxPaymentRefundModel.RefundAmount amount = new WxPaymentRefundModel.RefundAmount();
-				amount.setRefund(money.multiply(new BigDecimal(100)).intValue());
-				amount.setTotal(rechargeAmount.multiply(new BigDecimal(100)).intValue());
+				amount.setRefund(thirdRefundAmount.multiply(new BigDecimal(100)).intValue());
+				amount.setTotal(getRefundableThirdPayAmount(chargingOrder).multiply(new BigDecimal(100)).intValue());
 				amount.setCurrency("CNY");
 				model.setAmount(amount);
 				R<Map<String, Object>> orderR = wxPaymentClient.refundOrderR(model);
@@ -1309,8 +1518,8 @@
 			if (2 == rechargePaymentType) {
 				RefundReq dto = new RefundReq();
 				dto.setOutTradeNo(chargingOrder.getCode());
-				dto.setOutRequestNo(chargingOrderRefund.getCode());
-				dto.setRefundAmount(money.toString());
+				dto.setOutRequestNo(chargingOrderRefund.getRefundCode());
+				dto.setRefundAmount(thirdRefundAmount.toString());
 				dto.setRefundReason("充电完成退款");
 				RefundResp resp = aliPaymentClient.refund(dto).getData();
 				if (null != resp) {
@@ -1326,8 +1535,8 @@
 			if (3 == rechargePaymentType) {
 				RefundReq dto = new RefundReq();
 				dto.setOutTradeNo(chargingOrder.getRechargeSerialNumber());
-				dto.setOutRequestNo(chargingOrderRefund.getCode());
-				dto.setRefundAmount(money.toString());
+				dto.setOutRequestNo(chargingOrderRefund.getRefundCode());
+				dto.setRefundAmount(thirdRefundAmount.toString());
 				dto.setRefundReason("充电完成退款");
 				RefundResp resp = h5AliPaymentClient.refund(dto).getData();
 				if (null != resp && "10000".equals(resp.getCode())) {
@@ -1361,24 +1570,33 @@
             boolean tryLock = lock.tryLock(10, 10, TimeUnit.SECONDS);
             if(tryLock){
                 TChargingOrderRefund one = chargingOrderRefundService.getOne(new LambdaQueryWrapper<TChargingOrderRefund>().eq(TChargingOrderRefund::getRefundCode, out_refund_no));
-                if(null != one && one.getRefundStatus() == 1){
-                    one.setRefundSerialNumber(refund_id);
-                    one.setRefundStatus(2);
-                    one.setRefundTime(LocalDateTime.now());
-                    chargingOrderRefundService.updateById(one);
-
-                    TChargingOrder order = this.getById(one.getChargingOrderId());
-                    if (money(order.getBalanceRefundAmount()).compareTo(BigDecimal.ZERO) > 0) {
-                        changeUserBalance(order.getAppUserId(), money(order.getBalanceRefundAmount()));
-                    }
-                    TChargingOrder chargingOrder = new TChargingOrder();
-                    chargingOrder.setId(one.getChargingOrderId());
-                    chargingOrder.setAppUserId(order.getAppUserId());
-                    chargingOrder.setRefundStatus(2);
-                    chargingOrder.setRefundSerialNumber(refund_id);
-                    chargingOrder.setRefundTime(LocalDateTime.now());
-                    this.updateById(chargingOrder);
+                if (null == one || one.getRefundStatus() == null || one.getRefundStatus() != 1) {
+                    return AjaxResult.success();
                 }
+                if (!"SUCCESS".equals(tradeState)) {
+                    return AjaxResult.success();
+                }
+                TChargingOrder order = this.getById(one.getChargingOrderId());
+                if (order == null || (order.getRefundStatus() != null && order.getRefundStatus() == 2)) {
+                    return AjaxResult.success();
+                }
+
+                one.setRefundSerialNumber(refund_id);
+                one.setRefundStatus(2);
+                one.setRefundTime(LocalDateTime.now());
+                chargingOrderRefundService.updateById(one);
+
+                if (money(one.getBalanceRefundAmount()).compareTo(BigDecimal.ZERO) > 0) {
+                    changeUserBalance(order.getAppUserId(), money(one.getBalanceRefundAmount()));
+                    recordBalanceRefund(order, money(one.getBalanceRefundAmount()), one.getRefundCode());
+                }
+                TChargingOrder chargingOrder = new TChargingOrder();
+                chargingOrder.setId(one.getChargingOrderId());
+                chargingOrder.setAppUserId(order.getAppUserId());
+                chargingOrder.setRefundStatus(2);
+                chargingOrder.setRefundSerialNumber(refund_id);
+                chargingOrder.setRefundTime(LocalDateTime.now());
+                this.updateById(chargingOrder);
             }
         } catch (InterruptedException e) {
             throw new RuntimeException(e);
@@ -1696,39 +1914,11 @@
 		// 查询当前登陆人按钮权限
 		SysUser sysUser = sysUserClient.getSysUser(tokenService.getLoginUser().getUserid()).getData();
 		Integer roleType = sysUser.getRoleType();
-		//如果没传siteId,获取当前登陆人所有的siteIds
-		List<Integer> siteIds = new ArrayList<>();
-		if (dto.getSiteId() == null) {
-			if (userId != null) {
-				List<GetSiteListDTO> data = siteClient.getSiteListByUserId(userId).getData();
-				for (GetSiteListDTO datum : data) {
-					siteIds.add(datum.getId());
-				}
-			}
-		} else {
-			siteIds.add(dto.getSiteId());
-		}
-		if (siteIds.isEmpty()) {
-			siteIds.add(-1);
-		} else {
-			if (roleType == 2) {
-				List<Integer> integers = new ArrayList<>();
-				for (Integer siteId : siteIds) {
-					// 校验有没有这个站点的权限
-					List<Boolean> t1 = partnerClient.getChargingOrderMenu(sysUser.getObjectId(), siteId).getData();
-					
-					Boolean b = t1.get(1);
-					if (b) {
-						integers.add(siteId);
-					}
-				}
-				siteIds = integers;
-			}
-		}
-		if (siteIds.isEmpty()) siteIds.add(-1);
-		dto.setSiteIds(siteIds);
-		List<ChargingOrderVO> list = this.baseMapper.chargingOrder(pageInfo, dto, startTime1, startTime2, endTime1, endTime2);
-		List<TChargingOrderAccountingStrategy> list3 = chargingOrderAccountingStrategyService.list();
+			setChargingOrderAuthSiteIds(dto, sysUser, userId, roleType);
+			List<Integer> siteIds = dto.getSiteIds();
+			List<ChargingOrderVO> list = this.baseMapper.chargingOrder(pageInfo, dto, startTime1, startTime2, endTime1, endTime2);
+			fillChargingOrderBalanceIncome(list);
+			List<TChargingOrderAccountingStrategy> list3 = chargingOrderAccountingStrategyService.list();
 		for (ChargingOrderVO chargingOrderVO : list) {
 			if (roleType == 2) {
 				for (Integer siteId : siteIds) {
@@ -1792,25 +1982,235 @@
 				
 			}
 		}
+		fillEmptyChargingOrderSummary(tCharingOrderVO);
 		Map<String, Object> map = this.baseMapper.chargingOrderNolimit(dto, startTime1, startTime2, endTime1, endTime2);
 		if (null != map) {
-			tCharingOrderVO.setTotal(map.get("total") == null ? BigDecimal.ZERO : (BigDecimal) map.get("total"));
-			tCharingOrderVO.setTime(map.get("time") == null ? 0L : (Long) map.get("time"));
-			tCharingOrderVO.setIncome(map.get("income") == null ? BigDecimal.ZERO : ((BigDecimal) map.get("income")).setScale(2, RoundingMode.HALF_EVEN));
-			tCharingOrderVO.setElectronicMoney(map.get("electronicMoney") == null ? BigDecimal.ZERO : ((BigDecimal) map.get("electronicMoney")).setScale(2, RoundingMode.HALF_EVEN));
-			tCharingOrderVO.setServiceMoney(map.get("serviceMoney") == null ? BigDecimal.ZERO : ((BigDecimal) map.get("serviceMoney")).setScale(2, RoundingMode.HALF_EVEN));
-		} else {
-			tCharingOrderVO.setTotal(BigDecimal.ZERO);
-			tCharingOrderVO.setTime(0L);
-			tCharingOrderVO.setIncome(BigDecimal.ZERO);
-			tCharingOrderVO.setElectronicMoney(BigDecimal.ZERO);
-			tCharingOrderVO.setServiceMoney(BigDecimal.ZERO);
+			tCharingOrderVO.setTotal(getSummaryDecimal(map, "total"));
+			tCharingOrderVO.setTime(getSummaryLong(map, "time"));
+			tCharingOrderVO.setIncome(getSummaryDecimal(map, "income"));
+			tCharingOrderVO.setElectronicMoney(getSummaryDecimal(map, "electronicMoney"));
+			tCharingOrderVO.setServiceMoney(getSummaryDecimal(map, "serviceMoney"));
 		}
+		Map<String, Object> fundMap = this.baseMapper.chargingOrderFundSummary(dto, startTime1, startTime2, endTime1, endTime2);
+		if (null != fundMap) {
+			tCharingOrderVO.setPlatformIncomeTotal(getSummaryDecimal(fundMap, "platformIncomeTotal"));
+			tCharingOrderVO.setPartnerIncomeTotal(getSummaryDecimal(fundMap, "partnerIncomeTotal"));
+			tCharingOrderVO.setWechatIncome(getSummaryDecimal(fundMap, "wechatIncome"));
+			tCharingOrderVO.setAlipayIncome(getSummaryDecimal(fundMap, "alipayIncome"));
+			tCharingOrderVO.setWhitelistChargingIncome(getSummaryDecimal(fundMap, "whitelistChargingIncome"));
+			tCharingOrderVO.setWhitelistRefund(getSummaryDecimal(fundMap, "whitelistRefund"));
+		}
+		Map<String, Object> balanceMap = getExchangeCodeBalanceSummary(dto, startTime1, startTime2, endTime1, endTime2);
+		tCharingOrderVO.setBalanceIncome(getSummaryDecimal(balanceMap, "balanceIncome"));
+		tCharingOrderVO.setBalanceGiftIncome(getSummaryDecimal(balanceMap, "balanceGiftIncome"));
 		pageInfo.setRecords(list);
 		tCharingOrderVO.setList(pageInfo);
-		return tCharingOrderVO;
+			return tCharingOrderVO;
+		}
+
+		/**
+		 * 填充充电桩订单列表余额收入,余额收入按真实充值余额统计,赠送余额单独展示。
+		 */
+		private void fillChargingOrderBalanceIncome(List<ChargingOrderVO> list) {
+			if (list == null || list.isEmpty()) {
+				return;
+			}
+			List<Long> orderIds = list.stream().map(ChargingOrderVO::getId).filter(Objects::nonNull).collect(Collectors.toList());
+			if (orderIds.isEmpty()) {
+				return;
+			}
+			Map<Long, Map<String, Object>> incomeMap = new HashMap<>();
+			List<Map<String, Object>> rows = this.baseMapper.exchangeCodeBalanceIncomeByOrderIds(orderIds);
+			if (rows != null) {
+				for (Map<String, Object> row : rows) {
+					Long orderId = getSummaryLong(row, "orderId");
+					if (orderId != null) {
+						incomeMap.put(orderId, row);
+					}
+				}
+			}
+			for (ChargingOrderVO item : list) {
+				Map<String, Object> row = incomeMap.get(item.getId());
+				item.setBalanceIncome(getSummaryDecimal(row, "balanceIncome"));
+				item.setBalanceGiftIncome(getSummaryDecimal(row, "balanceGiftIncome"));
+			}
+		}
+
+		private void setChargingOrderAuthSiteIds(ChargingOrderQuery dto, SysUser sysUser, Long userId, Integer roleType) {
+		List<Integer> siteIds = new ArrayList<>();
+		if (dto.getSiteId() == null) {
+			if (userId != null) {
+				List<GetSiteListDTO> data = siteClient.getSiteListByUserId(userId).getData();
+				for (GetSiteListDTO datum : data) {
+					siteIds.add(datum.getId());
+				}
+			}
+		} else {
+			siteIds.add(dto.getSiteId());
+		}
+		if (siteIds.isEmpty()) {
+			siteIds.add(-1);
+		} else if (roleType == 2) {
+			List<Integer> integers = new ArrayList<>();
+			for (Integer siteId : siteIds) {
+				List<Boolean> t1 = partnerClient.getChargingOrderMenu(sysUser.getObjectId(), siteId).getData();
+				Boolean b = t1.get(1);
+				if (b) {
+					integers.add(siteId);
+				}
+			}
+			siteIds = integers;
+		}
+		if (siteIds.isEmpty()) {
+			siteIds.add(-1);
+		}
+		dto.setSiteIds(siteIds);
 	}
-	
+
+	/**
+	 * 查询充电桩订单余额收入明细,余额收入按真实充值余额统计,赠送收入单独展示。
+	 */
+	@Override
+	public List<ChargingOrderBalanceIncomeDetailVO> balanceIncomeDetail(ChargingOrderQuery dto) {
+		String startTime1 = null;
+		String startTime2 = null;
+		String endTime1 = null;
+		String endTime2 = null;
+		if (StringUtils.hasLength(dto.getStartTime())) {
+			String[] split = dto.getStartTime().split(" - ");
+			startTime1 = split[0];
+			startTime2 = split[1];
+		}
+		if (StringUtils.hasLength(dto.getEndTime())) {
+			String[] split = dto.getEndTime().split(" - ");
+			endTime1 = split[0];
+			endTime2 = split[1];
+		}
+		if (StringUtils.hasLength(dto.getPhone())) {
+			List<Long> data = appUserClient.getUserIdsByPhone(dto.getPhone()).getData();
+			if (data == null || data.isEmpty()) {
+				return new ArrayList<>();
+			}
+			dto.setUserIds(data);
+		}
+		Long userId = tokenService.getLoginUser().getUserid();
+		SysUser sysUser = sysUserClient.getSysUser(userId).getData();
+		setChargingOrderAuthSiteIds(dto, sysUser, userId, sysUser.getRoleType());
+		List<Long> orderIds = this.baseMapper.chargingOrderSummaryOrderIds(dto, startTime1, startTime2, endTime1, endTime2);
+		if (orderIds == null || orderIds.isEmpty()) {
+			return new ArrayList<>();
+		}
+		Map<Long, ChargingOrderBalanceIncomeDetailVO> detailMap = new LinkedHashMap<>();
+		int batchSize = 500;
+		for (int i = 0; i < orderIds.size(); i += batchSize) {
+			List<Long> batchIds = orderIds.subList(i, Math.min(i + batchSize, orderIds.size()));
+			List<ChargingOrderBalanceIncomeDetailVO> batchList = this.baseMapper.exchangeCodeBalanceIncomeDetail(batchIds);
+			if (batchList == null || batchList.isEmpty()) {
+				continue;
+			}
+			for (ChargingOrderBalanceIncomeDetailVO item : batchList) {
+				Long packageId = item.getPackageId() == null ? 0L : item.getPackageId();
+				ChargingOrderBalanceIncomeDetailVO detail = detailMap.get(packageId);
+				if (detail == null) {
+					detail = new ChargingOrderBalanceIncomeDetailVO();
+					detail.setPackageId(item.getPackageId());
+					detail.setPackageName(item.getPackageName());
+					detail.setBalanceIncome(BigDecimal.ZERO);
+					detail.setGiftIncome(BigDecimal.ZERO);
+					detailMap.put(packageId, detail);
+				}
+				detail.setBalanceIncome(detail.getBalanceIncome().add(item.getBalanceIncome() == null ? BigDecimal.ZERO : item.getBalanceIncome()));
+				detail.setGiftIncome(detail.getGiftIncome().add(item.getGiftIncome() == null ? BigDecimal.ZERO : item.getGiftIncome()));
+			}
+		}
+		List<ChargingOrderBalanceIncomeDetailVO> result = new ArrayList<>();
+		for (ChargingOrderBalanceIncomeDetailVO detail : detailMap.values()) {
+			BigDecimal balanceIncome = (detail.getBalanceIncome() == null ? BigDecimal.ZERO : detail.getBalanceIncome()).setScale(2, RoundingMode.HALF_EVEN);
+			BigDecimal giftIncome = (detail.getGiftIncome() == null ? BigDecimal.ZERO : detail.getGiftIncome()).setScale(2, RoundingMode.HALF_EVEN);
+			if (balanceIncome.compareTo(BigDecimal.ZERO) == 0 && giftIncome.compareTo(BigDecimal.ZERO) == 0) {
+				continue;
+			}
+			detail.setBalanceIncome(balanceIncome);
+			detail.setGiftIncome(giftIncome);
+			result.add(detail);
+		}
+		return result;
+	}
+
+	private void fillEmptyChargingOrderSummary(TCharingOrderVO tCharingOrderVO) {
+		tCharingOrderVO.setTotal(BigDecimal.ZERO);
+		tCharingOrderVO.setTime(0L);
+		tCharingOrderVO.setIncome(BigDecimal.ZERO);
+		tCharingOrderVO.setElectronicMoney(BigDecimal.ZERO);
+		tCharingOrderVO.setServiceMoney(BigDecimal.ZERO);
+		tCharingOrderVO.setPlatformIncomeTotal(BigDecimal.ZERO);
+		tCharingOrderVO.setPartnerIncomeTotal(BigDecimal.ZERO);
+		tCharingOrderVO.setWechatIncome(BigDecimal.ZERO);
+		tCharingOrderVO.setAlipayIncome(BigDecimal.ZERO);
+		tCharingOrderVO.setBalanceIncome(BigDecimal.ZERO);
+		tCharingOrderVO.setBalanceGiftIncome(BigDecimal.ZERO);
+		tCharingOrderVO.setWhitelistChargingIncome(BigDecimal.ZERO);
+		tCharingOrderVO.setWhitelistRefund(BigDecimal.ZERO);
+	}
+
+	/**
+	 * 汇总充电桩订单余额收入,兑换码使用记录的usedAmount包含赠送余额,SQL中需扣除giftUsedAmount。
+	 */
+	private Map<String, Object> getExchangeCodeBalanceSummary(ChargingOrderQuery dto, String startTime1, String startTime2, String endTime1, String endTime2) {
+		Map<String, Object> totalMap = new HashMap<>();
+		totalMap.put("balanceIncome", BigDecimal.ZERO);
+		totalMap.put("balanceGiftIncome", BigDecimal.ZERO);
+		List<Long> orderIds = this.baseMapper.chargingOrderSummaryOrderIds(dto, startTime1, startTime2, endTime1, endTime2);
+		if (orderIds == null || orderIds.isEmpty()) {
+			return totalMap;
+		}
+		BigDecimal balanceIncome = BigDecimal.ZERO;
+		BigDecimal balanceGiftIncome = BigDecimal.ZERO;
+		int batchSize = 500;
+		for (int i = 0; i < orderIds.size(); i += batchSize) {
+			List<Long> batchIds = orderIds.subList(i, Math.min(i + batchSize, orderIds.size()));
+			Map<String, Object> batchMap = this.baseMapper.exchangeCodeBalanceSummary(batchIds);
+			if (batchMap != null) {
+				balanceIncome = balanceIncome.add(getSummaryDecimal(batchMap, "balanceIncome"));
+				balanceGiftIncome = balanceGiftIncome.add(getSummaryDecimal(batchMap, "balanceGiftIncome"));
+			}
+		}
+		totalMap.put("balanceIncome", balanceIncome);
+		totalMap.put("balanceGiftIncome", balanceGiftIncome);
+		return totalMap;
+	}
+
+		private BigDecimal getSummaryDecimal(Map<String, Object> map, String key) {
+			if (map == null) {
+				return BigDecimal.ZERO;
+			}
+			Object value = map.get(key);
+		if (value == null) {
+			return BigDecimal.ZERO;
+		}
+		if (value instanceof BigDecimal) {
+			return ((BigDecimal) value).setScale(2, RoundingMode.HALF_EVEN);
+		}
+		if (value instanceof Number) {
+			return BigDecimal.valueOf(((Number) value).doubleValue()).setScale(2, RoundingMode.HALF_EVEN);
+		}
+		return new BigDecimal(value.toString()).setScale(2, RoundingMode.HALF_EVEN);
+	}
+
+		private Long getSummaryLong(Map<String, Object> map, String key) {
+			if (map == null) {
+				return 0L;
+			}
+			Object value = map.get(key);
+		if (value == null) {
+			return 0L;
+		}
+		if (value instanceof Number) {
+			return ((Number) value).longValue();
+		}
+		return Long.parseLong(value.toString());
+	}
+
 	@Override
 	public R<PageInfo<PayOrderDto>> payOrderQuery(PayOrderQueryDto payOrderQueryDto) {
 		PageInfo<PayOrderDto> pageInfo = new PageInfo<>(payOrderQueryDto.getPageCurr(), payOrderQueryDto.getPageSize());
@@ -1828,7 +2228,62 @@
 		pageInfo.setRecords(list);
 		return R.ok(pageInfo);
 	}
-	
+		@Override
+	public R<PageInfo<EnterpriseChargingAnalysisVO>> enterpriseChargingAnalysis(EnterpriseChargingAnalysisQuery query) {
+		PageInfo<EnterpriseChargingAnalysisVO> pageInfo = new PageInfo<>(query.getPageCurr(), query.getPageSize());
+		List<EnterpriseChargingAnalysisVO> list = this.baseMapper.enterpriseChargingAnalysis(pageInfo, query);
+		for (EnterpriseChargingAnalysisVO row : list) {
+			EnterpriseChargingAnalysisQuery rowQuery = buildEnterpriseRowQuery(query, row);
+			List<Map<String, Object>> topSites = this.baseMapper.enterpriseTopSites(rowQuery);
+			String topSiteNames = topSites.stream()
+					.map(item -> Objects.toString(item.get("siteName"), ""))
+					.filter(org.springframework.util.StringUtils::hasText)
+					.collect(Collectors.joining("、"));
+			row.setTopSiteNames(topSiteNames);
+			row.setAverageChargingInterval(calculateAverageChargingInterval(this.baseMapper.enterpriseChargingTimes(rowQuery)));
+		}
+		pageInfo.setRecords(list);
+		return R.ok(pageInfo);
+	}
+
+	@Override
+	public R<PageInfo<EnterpriseChargingDetailVO>> enterpriseChargingDetail(EnterpriseChargingAnalysisQuery query) {
+		PageInfo<EnterpriseChargingDetailVO> pageInfo = new PageInfo<>(query.getPageCurr(), query.getPageSize());
+		List<EnterpriseChargingDetailVO> list = this.baseMapper.enterpriseChargingDetail(pageInfo, query);
+		pageInfo.setRecords(list);
+		return R.ok(pageInfo);
+	}
+
+	@Override
+	public List<EnterpriseChargingDetailVO> enterpriseChargingDetailExport(EnterpriseChargingAnalysisQuery query) {
+		return this.baseMapper.enterpriseChargingDetailExport(query);
+	}
+
+	private EnterpriseChargingAnalysisQuery buildEnterpriseRowQuery(EnterpriseChargingAnalysisQuery source, EnterpriseChargingAnalysisVO row) {
+		EnterpriseChargingAnalysisQuery rowQuery = new EnterpriseChargingAnalysisQuery();
+		BeanUtils.copyProperties(source, rowQuery);
+		rowQuery.setCompanyName(null);
+		rowQuery.setExactCompanyName(row.getCompanyName());
+		rowQuery.setSocialCreditCode(row.getSocialCreditCode());
+		return rowQuery;
+	}
+
+	private BigDecimal calculateAverageChargingInterval(List<LocalDateTime> times) {
+		if (times == null || times.size() < 2) {
+			return BigDecimal.ZERO;
+		}
+		long totalMinutes = 0L;
+		for (int i = 1; i < times.size(); i++) {
+			long minutes = ChronoUnit.MINUTES.between(times.get(i - 1), times.get(i));
+			if (minutes > 0) {
+				totalMinutes += minutes;
+			}
+		}
+		return BigDecimal.valueOf(totalMinutes)
+				.divide(BigDecimal.valueOf(times.size() - 1L), 4, RoundingMode.HALF_UP)
+				.divide(BigDecimal.valueOf(60), 2, RoundingMode.HALF_UP);
+	}
+
 	@Override
 	public R<PageInfo<TChargingOrderRefund>> getRefundList(ChargingRefundDto chargingRefundDto) {
 		PageInfo<TChargingOrderRefund> pageInfo = new PageInfo<>(chargingRefundDto.getPageCurr(), chargingRefundDto.getPageSize());
@@ -1858,7 +2313,112 @@
 	public Map<String, Object> countAll(List<Integer> siteIds) {
 		return this.baseMapper.countAll(siteIds);
 	}
-	
+
+	/**
+	 * 统计近六月订单收入支付方式占比;服务层聚合避免复杂CASE SQL在当前数据库驱动中转换异常。
+	 */
+	@Override
+	public List<SixIncomeCircleDto> payTypeCircle(LocalDate sixBefore, List<Integer> siteIds) {
+		if (siteIds == null || siteIds.isEmpty()) {
+			return buildPayTypeCircleData(BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO);
+		}
+		List<TChargingOrder> orders = this.lambdaQuery()
+				.select(TChargingOrder::getRechargePaymentType, TChargingOrder::getPayMethod,
+						TChargingOrder::getThirdPayAmount, TChargingOrder::getThirdRefundAmount,
+						TChargingOrder::getBalancePayAmount, TChargingOrder::getBalanceRefundAmount,
+						TChargingOrder::getPaymentAmount, TChargingOrder::getRechargeAmount,
+						TChargingOrder::getRefundAmount)
+				.eq(TChargingOrder::getDelFlag, 0)
+				.eq(TChargingOrder::getRechargePaymentStatus, 2)
+				.eq(TChargingOrder::getStatus, 5)
+				.ge(sixBefore != null, TChargingOrder::getCreateTime, sixBefore == null ? null : sixBefore.atStartOfDay())
+				.in(TChargingOrder::getSiteId, siteIds)
+				.list();
+		BigDecimal wechatAmount = BigDecimal.ZERO;
+		BigDecimal alipayAmount = BigDecimal.ZERO;
+		BigDecimal balanceAmount = BigDecimal.ZERO;
+		for (TChargingOrder order : orders) {
+			BigDecimal thirdPayAmount = getThirdPayNetAmount(order);
+			BigDecimal balancePayAmount = getBalancePayNetAmount(order);
+			Integer rechargePaymentType = order.getRechargePaymentType();
+			if (Integer.valueOf(1).equals(rechargePaymentType)) {
+				wechatAmount = wechatAmount.add(thirdPayAmount);
+			}
+			if (Integer.valueOf(2).equals(rechargePaymentType) || Integer.valueOf(3).equals(rechargePaymentType)) {
+				alipayAmount = alipayAmount.add(thirdPayAmount);
+			}
+			Integer payMethod = order.getPayMethod();
+			if (Integer.valueOf(1).equals(payMethod) || Integer.valueOf(2).equals(payMethod)) {
+				balanceAmount = balanceAmount.add(balancePayAmount);
+			}
+		}
+		return buildPayTypeCircleData(wechatAmount, alipayAmount, balanceAmount);
+	}
+
+	/**
+	 * 构造固定三类支付方式数据,保证前端饼图在无订单时也有稳定结构。
+	 */
+	private List<SixIncomeCircleDto> buildPayTypeCircleData(BigDecimal wechatAmount, BigDecimal alipayAmount, BigDecimal balanceAmount) {
+		List<SixIncomeCircleDto> data = new ArrayList<>();
+		data.add(buildIncomeCircleDto("微信支付", wechatAmount));
+		data.add(buildIncomeCircleDto("支付宝支付", alipayAmount));
+		data.add(buildIncomeCircleDto("余额支付", balanceAmount));
+		return data;
+	}
+
+	/**
+	 * 构造单个饼图项并统一金额精度。
+	 */
+	private SixIncomeCircleDto buildIncomeCircleDto(String name, BigDecimal paymentAmount) {
+		SixIncomeCircleDto dto = new SixIncomeCircleDto();
+		dto.setName(name);
+		dto.setPaymentAmount(nullToZero(paymentAmount).setScale(2, RoundingMode.HALF_EVEN));
+		return dto;
+	}
+
+	/**
+	 * 计算第三方渠道实收:优先使用拆分字段,兼容旧订单回退到paymentAmount/rechargeAmount。
+	 */
+	private BigDecimal getThirdPayNetAmount(TChargingOrder order) {
+		BigDecimal payAmount = order.getThirdPayAmount();
+		if (payAmount == null && Integer.valueOf(3).equals(order.getPayMethod())) {
+			payAmount = firstNonNull(order.getPaymentAmount(), order.getRechargeAmount());
+		}
+		BigDecimal refundAmount = order.getThirdRefundAmount();
+		if (refundAmount == null && Integer.valueOf(3).equals(order.getPayMethod())) {
+			refundAmount = order.getRefundAmount();
+		}
+		return nonNegative(nullToZero(payAmount).subtract(nullToZero(refundAmount)));
+	}
+
+	/**
+	 * 计算余额渠道实收:组合支付优先使用拆分字段,兼容旧余额订单回退到paymentAmount。
+	 */
+	private BigDecimal getBalancePayNetAmount(TChargingOrder order) {
+		BigDecimal payAmount = order.getBalancePayAmount();
+		Integer payMethod = order.getPayMethod();
+		if (payAmount == null && (Integer.valueOf(1).equals(payMethod) || Integer.valueOf(2).equals(payMethod))) {
+			payAmount = order.getPaymentAmount();
+		}
+		BigDecimal refundAmount = order.getBalanceRefundAmount();
+		if (refundAmount == null && (Integer.valueOf(1).equals(payMethod) || Integer.valueOf(2).equals(payMethod))) {
+			refundAmount = order.getRefundAmount();
+		}
+		return nonNegative(nullToZero(payAmount).subtract(nullToZero(refundAmount)));
+	}
+
+	private BigDecimal firstNonNull(BigDecimal first, BigDecimal second) {
+		return first != null ? first : second;
+	}
+
+	private BigDecimal nullToZero(BigDecimal value) {
+		return value == null ? BigDecimal.ZERO : value;
+	}
+
+	private BigDecimal nonNegative(BigDecimal value) {
+		return value.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : value;
+	}
+
 	@Override
 	public List<Map<String, Object>> getSumByType(LocalDate start, LocalDate end, List<Integer> siteIds) {
 		LocalDateTime start1 = start.atStartOfDay();
@@ -2059,6 +2619,11 @@
 			if(null != map.get("licensePlate")){
 				chargingOrderListVO.setLicensePlate(map.get("licensePlate").toString());
 			}
+			chargingOrderListVO.setIsWhitelist(null == map.get("isWhitelist") ? 0 : Integer.valueOf(map.get("isWhitelist").toString()));
+			// 白名单退款金额由电费退款和服务费退款组成,列表展示总额,财务导出继续保留拆分字段。
+			chargingOrderListVO.setWhitelistElectricRefundAmount(getSummaryDecimal(map, "whitelistElectricRefundAmount"));
+			chargingOrderListVO.setWhitelistServiceRefundAmount(getSummaryDecimal(map, "whitelistServiceRefundAmount"));
+			chargingOrderListVO.setWhitelistRefundAmount(getSummaryDecimal(map, "whitelistRefundAmount"));
 			BigDecimal jian = null == map.get("jian") ? BigDecimal.ZERO : new BigDecimal(map.get("jian").toString());
 			BigDecimal feng = null == map.get("feng") ? BigDecimal.ZERO : new BigDecimal(map.get("feng").toString());
 			BigDecimal ping = null == map.get("ping") ? BigDecimal.ZERO : new BigDecimal(map.get("ping").toString());
@@ -2261,9 +2826,38 @@
 		}
 		dto.setSiteIds(siteIds);
 		List<ChargingOrderListVO> list1 = this.baseMapper.chargingList(dto, startTime1, startTime2, endTime1, endTime2);
+		fillChargingPeriodExportBalanceIncome(list1);
 		return list1;
 	}
-	
+
+	/**
+	 * 充电时段统计导出补充余额收入;兑换码usedAmount包含赠送金额,需沿用订单列表口径拆分。
+	 */
+	private void fillChargingPeriodExportBalanceIncome(List<ChargingOrderListVO> list) {
+		if (list == null || list.isEmpty()) {
+			return;
+		}
+		List<Long> orderIds = list.stream().map(ChargingOrderListVO::getId).filter(Objects::nonNull).collect(Collectors.toList());
+		if (orderIds.isEmpty()) {
+			return;
+		}
+		Map<Long, Map<String, Object>> incomeMap = new HashMap<>();
+		List<Map<String, Object>> rows = this.baseMapper.exchangeCodeBalanceIncomeByOrderIds(orderIds);
+		if (rows != null) {
+			for (Map<String, Object> row : rows) {
+				Long orderId = getSummaryLong(row, "orderId");
+				if (orderId != null) {
+					incomeMap.put(orderId, row);
+				}
+			}
+		}
+		for (ChargingOrderListVO item : list) {
+			Map<String, Object> row = incomeMap.get(item.getId());
+			item.setBalanceIncome(getSummaryDecimal(row, "balanceIncome"));
+			item.setBalanceGiftIncome(getSummaryDecimal(row, "balanceGiftIncome"));
+		}
+	}
+
 	
 	@Override
 	public ChargingOrderListInfoVO chargingInfo(String uid) {
@@ -2457,6 +3051,12 @@
 		RLock lock = redissonClient.getLock("endOrder:" + vo.getTransaction_serial_number());
 		try {
             boolean tryLock = lock.tryLock(60, 60, TimeUnit.SECONDS);
+            //添加redis缓存数据,过期时间,用于防止处理缓慢且硬件重复发送报文导致的重复退款
+            Boolean hasKey = redisService.hasKey("END_ORDER:" + vo.getTransaction_serial_number());
+            if(hasKey){
+                return R.fail("不能重复退款");
+            }
+            redisService.setCacheObject("END_ORDER:" + vo.getTransaction_serial_number(), System.currentTimeMillis() + "", 10L, TimeUnit.MINUTES);
             if(tryLock){
                 TChargingOrder chargingOrder = this.getOne(new LambdaQueryWrapper<TChargingOrder>().eq(TChargingOrder::getCode, vo.getTransaction_serial_number()));
                 if (null == chargingOrder) {
@@ -2703,7 +3303,7 @@
 
                 //计算优惠券
                 BigDecimal couponDiscount = BigDecimal.ZERO;
-                if (!isBalancePayMode(chargingOrder.getPayMethod()) && null != chargingOrder.getAppCouponId()) {
+                if (!isWhitelistOrder(chargingOrder) && !isBalancePayMode(chargingOrder.getPayMethod()) && null != chargingOrder.getAppCouponId()) {
                     //判断实际充电金额是否满足优惠券使用条件,如果不满足则不适用优惠券。
                     TAppCoupon appCoupon = appCouponClient.getAppCouponById(chargingOrder.getAppCouponId()).getData();
                     String couponJson = appCoupon.getCouponJson();
@@ -2751,6 +3351,17 @@
                         }
                     }
                 }
+                BigDecimal[] whitelistRefundSplit = calculateWhitelistRefundSplit(chargingOrder, 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);
                 //退款金额+优惠券
@@ -2761,11 +3372,34 @@
                     serviceCharge_total = serviceCharge_total.subtract(couponDiscount);
                 }
                 chargingOrder.setCouponDiscountAmount(couponDiscount.setScale(2, RoundingMode.HALF_EVEN));
+                chargingOrder.setWhitelistDiscountAmount(whitelistDiscount.setScale(2, RoundingMode.HALF_EVEN));
+                chargingOrder.setWhitelistElectricRefundAmount(electricDiscount.setScale(2, RoundingMode.HALF_EVEN));
+                chargingOrder.setWhitelistServiceRefundAmount(serviceDiscount.setScale(2, RoundingMode.HALF_EVEN));
+                chargingOrder.setElectrovalence(periodElectricPrice_total.setScale(2, RoundingMode.HALF_EVEN));
                 chargingOrder.setServiceCharge(serviceCharge_total.setScale(2, RoundingMode.HALF_EVEN));
                 refundAmount = refundAmount.max(BigDecimal.ZERO).setScale(2, RoundingMode.HALF_UP);
-                BigDecimal thirdRefundAmount = refundAmount.min(money(chargingOrder.getThirdPayAmount())).setScale(2, RoundingMode.HALF_UP);
-                BigDecimal balanceRefundAmount = refundAmount.subtract(thirdRefundAmount).min(money(chargingOrder.getBalancePayAmount())).setScale(2, RoundingMode.HALF_UP);
-                BigDecimal actualThirdPayAmount = money(chargingOrder.getThirdPayAmount()).subtract(thirdRefundAmount);
+                // 白名单全部免费无需实际渠道退款,但财务展示需要将预估预充金额记录到订单退款金额。
+                BigDecimal recordedRefundAmount = isWhitelistAllFreeOrder(chargingOrder)
+                        ? money(chargingOrder.getRechargeAmount())
+                        : refundAmount;
+                Integer payMethod = chargingOrder.getPayMethod();
+                BigDecimal thirdRefundAmount = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
+                BigDecimal balanceRefundAmount = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
+                BigDecimal refundableThirdPayAmount = getRefundableThirdPayAmount(chargingOrder);
+                BigDecimal refundableAmount = refundableThirdPayAmount.add(money(chargingOrder.getBalancePayAmount())).setScale(2, RoundingMode.HALF_UP);
+                // 全部免费订单启动时未拉起支付,渠道可退金额固定为0,避免误触发微信/支付宝/余额退款。
+                BigDecimal channelRefundAmount = isWhitelistAllFreeOrder(chargingOrder)
+                        ? BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP)
+                        : refundAmount.min(refundableAmount).setScale(2, RoundingMode.HALF_UP);
+                if (Integer.valueOf(1).equals(payMethod)) {
+                    balanceRefundAmount = channelRefundAmount.min(money(chargingOrder.getBalancePayAmount())).setScale(2, RoundingMode.HALF_UP);
+                } else if (Integer.valueOf(2).equals(payMethod)) {
+                    thirdRefundAmount = channelRefundAmount.min(refundableThirdPayAmount).setScale(2, RoundingMode.HALF_UP);
+                    balanceRefundAmount = channelRefundAmount.subtract(thirdRefundAmount).min(money(chargingOrder.getBalancePayAmount())).setScale(2, RoundingMode.HALF_UP);
+                } else {
+                    thirdRefundAmount = channelRefundAmount.min(refundableThirdPayAmount).setScale(2, RoundingMode.HALF_UP);
+                }
+                BigDecimal actualThirdPayAmount = refundableThirdPayAmount.subtract(thirdRefundAmount);
                 if (actualThirdPayAmount.compareTo(BigDecimal.ZERO) < 0) {
                     actualThirdPayAmount = BigDecimal.ZERO;
                 }
@@ -2773,20 +3407,13 @@
                 if (actualBalancePayAmount.compareTo(BigDecimal.ZERO) < 0) {
                     actualBalancePayAmount = BigDecimal.ZERO;
                 }
-                if (isBalancePayMode(chargingOrder.getPayMethod()) && chargingOrder.getAppUserId() != null
-                        && actualBalancePayAmount.compareTo(BigDecimal.ZERO) > 0) {
-                    ExchangeCodeConsumeDTO exchangeCodeConsumeDTO = new ExchangeCodeConsumeDTO();
-                    exchangeCodeConsumeDTO.setUserId(chargingOrder.getAppUserId());
-                    exchangeCodeConsumeDTO.setOrderId(chargingOrder.getId());
-                    exchangeCodeConsumeDTO.setAmount(actualBalancePayAmount);
-                    otherClient.consumeExchangeCodeBalance(exchangeCodeConsumeDTO);
-                }
-                refundAmount = thirdRefundAmount.add(balanceRefundAmount);
+                refundAmount = recordedRefundAmount;
                 chargingOrder.setBalanceRefundAmount(balanceRefundAmount.setScale(2, RoundingMode.HALF_UP));
                 chargingOrder.setThirdRefundAmount(thirdRefundAmount.setScale(2, RoundingMode.HALF_UP));
-                chargingOrder.setPaymentAmount(actualThirdPayAmount.setScale(2, RoundingMode.HALF_EVEN));
+                // paymentAmount用于小程序展示实际消费金额,需包含第三方实扣和余额实扣,不能只取第三方渠道金额。
+                chargingOrder.setPaymentAmount(actualThirdPayAmount.add(actualBalancePayAmount).setScale(2, RoundingMode.HALF_EVEN));
                 chargingOrder.setRefundAmount(refundAmount.setScale(2, RoundingMode.HALF_EVEN));
-                chargingOrder.setRefundStatus(1);
+                chargingOrder.setRefundStatus(channelRefundAmount.compareTo(BigDecimal.ZERO) > 0 ? 1 : 2);
                 UploadRealTimeMonitoringData asc = uploadRealTimeMonitoringDataService.getDataByOrderCode(chargingOrder.getCode(), "asc");
                 UploadRealTimeMonitoringData desc = uploadRealTimeMonitoringDataService.getDataByOrderCode(chargingOrder.getCode(), "desc");
                 if(null != asc){
@@ -2889,13 +3516,15 @@
                     //开始构建退款费用
                     refundAmount = refundAmount.setScale(2, RoundingMode.HALF_EVEN);
                     Integer rechargePaymentType = chargingOrder.getRechargePaymentType();
-                    if (refundAmount.compareTo(BigDecimal.ZERO) > 0) {
+                    if (channelRefundAmount.compareTo(BigDecimal.ZERO) > 0) {
                         //构建退款明细
                         TChargingOrderRefund chargingOrderRefund = new TChargingOrderRefund();
                         chargingOrderRefund.setChargingOrderId(chargingOrder.getId());
                         SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyMMddHHmmssSSS");
                         chargingOrderRefund.setRefundCode("CDF" + sdf1.format(new Date()) + (Double.valueOf(Math.random() * 1000).intValue()));
                         chargingOrderRefund.setRefundAmount(refundAmount);
+                        chargingOrderRefund.setBalanceRefundAmount(balanceRefundAmount);
+                        chargingOrderRefund.setThirdRefundAmount(thirdRefundAmount);
                         chargingOrderRefund.setPayType(rechargePaymentType);
                         chargingOrderRefund.setRefundStatus(1);
                         chargingOrderRefund.setCode(chargingOrder.getCode());
@@ -2905,7 +3534,20 @@
                         chargingOrderRefund.setRefundRemark("实际充电消费金额:" + chargingOrder.getPaymentAmount());
                         chargingOrderRefund.setRefundTotalAmount(refundAmount);
                         chargingOrderRefund.setPayAmount(rechargeAmount);
-                        if (1 == rechargePaymentType) {
+                        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) {
+                                changeUserBalance(chargingOrder.getAppUserId(), balanceRefundAmount);
+                                recordBalanceRefund(chargingOrder, balanceRefundAmount, chargingOrderRefund.getRefundCode());
+                            }
+
+                            chargingOrder.setRefundStatus(2);
+                            chargingOrder.setRefundTime(LocalDateTime.now());
+                            this.updateById(chargingOrder);
+                        } else if (1 == rechargePaymentType) {
                             WxPaymentRefundModel model = new WxPaymentRefundModel();
                             model.setOut_trade_no(chargingOrder.getCode());
                             model.setOut_refund_no(chargingOrderRefund.getRefundCode());
@@ -2913,7 +3555,7 @@
                             model.setNotify_url("/payment/wx/refund/notify");
                             WxPaymentRefundModel.RefundAmount amount = new WxPaymentRefundModel.RefundAmount();
                             amount.setRefund(thirdRefundAmount.multiply(new BigDecimal(100)).intValue());
-                            amount.setTotal(rechargeAmount.multiply(new BigDecimal(100)).intValue());
+                            amount.setTotal(getRefundableThirdPayAmount(chargingOrder).multiply(new BigDecimal(100)).intValue());
                             amount.setCurrency("CNY");
                             model.setAmount(amount);
                             R<Map<String, Object>> result = wxPaymentClient.refundOrderR(model);
@@ -2950,13 +3592,39 @@
                                 this.chargingOrderStartupFailureWxRefund(chargingOrderRefund.getRefundCode(), resp.getTradeNo(), "SUCCESS", null);
                             }
                         }
-                    }else{
+                    } else if (recordedRefundAmount.compareTo(BigDecimal.ZERO) > 0) {
+                        TChargingOrderRefund chargingOrderRefund = new TChargingOrderRefund();
+                        chargingOrderRefund.setChargingOrderId(chargingOrder.getId());
+                        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyMMddHHmmssSSS");
+                        chargingOrderRefund.setRefundCode("CDF" + sdf1.format(new Date()) + (Double.valueOf(Math.random() * 1000).intValue()));
+                        chargingOrderRefund.setRefundAmount(recordedRefundAmount);
+                        chargingOrderRefund.setBalanceRefundAmount(balanceRefundAmount);
+                        chargingOrderRefund.setThirdRefundAmount(thirdRefundAmount);
+                        chargingOrderRefund.setRefundStatus(2);
+                        chargingOrderRefund.setRefundSerialNumber(isWhitelistAllFreeOrder(chargingOrder) ? "WHITELIST" : "BALANCE");
+                        chargingOrderRefund.setPayType(rechargePaymentType);
+                        chargingOrderRefund.setCode(chargingOrder.getCode());
+                        chargingOrderRefund.setRefundTitle("充电完成退款");
+                        chargingOrderRefund.setRefundContent("充电完成退款");
+                        chargingOrderRefund.setRefundReason("充电完成退款");
+                        chargingOrderRefund.setRefundRemark(isWhitelistAllFreeOrder(chargingOrder) ? "白名单全部免费,记录预估退款金额" : "实际充电消费金额:" + chargingOrder.getPaymentAmount());
+                        chargingOrderRefund.setRefundTotalAmount(recordedRefundAmount);
+                        chargingOrderRefund.setPayAmount(rechargeAmount);
+                        chargingOrderRefund.setRefundTime(LocalDateTime.now());
+                        chargingOrderRefundService.save(chargingOrderRefund);
+
+                        chargingOrder.setRefundStatus(2);
+                        chargingOrder.setRefundTime(LocalDateTime.now());
+                        this.updateById(chargingOrder);
+                    } else {
                         //构建退款明细
                         TChargingOrderRefund chargingOrderRefund = new TChargingOrderRefund();
                         chargingOrderRefund.setChargingOrderId(chargingOrder.getId());
                         SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyMMddHHmmssSSS");
                         chargingOrderRefund.setRefundCode("CDF" + sdf1.format(new Date()) + (Double.valueOf(Math.random() * 1000).intValue()));
                         chargingOrderRefund.setRefundAmount(refundAmount);
+                        chargingOrderRefund.setBalanceRefundAmount(balanceRefundAmount);
+                        chargingOrderRefund.setThirdRefundAmount(thirdRefundAmount);
                         chargingOrderRefund.setRefundStatus(2);
                         chargingOrderRefund.setPayType(rechargePaymentType);
                         chargingOrderRefund.setCode(chargingOrder.getCode());
@@ -2968,6 +3636,10 @@
                         chargingOrderRefund.setPayAmount(rechargeAmount);
                         chargingOrderRefund.setRefundTime(LocalDateTime.now());
                         chargingOrderRefundService.save(chargingOrderRefund);
+                        if (balanceRefundAmount.compareTo(BigDecimal.ZERO) > 0) {
+                            changeUserBalance(chargingOrder.getAppUserId(), balanceRefundAmount);
+                            recordBalanceRefund(chargingOrder, balanceRefundAmount, chargingOrderRefund.getRefundCode());
+                        }
 
                         chargingOrder.setRefundStatus(2);
                         chargingOrder.setRefundTime(LocalDateTime.now());
@@ -3136,8 +3808,27 @@
 			chargingOrderRefund.setRefundRemark(payOrderQueryDto.getRemark());
 			chargingOrderRefund.setRefundTotalAmount(tChargingOrder.getRefundAmount().add(payOrderQueryDto.getRefundAmount()));
 			chargingOrderRefund.setPayAmount(tChargingOrder.getPaymentAmount());
-			
-			if (1 == tChargingOrder.getRechargePaymentType()) {
+			BigDecimal manualRefundAmount = money(payOrderQueryDto.getRefundAmount());
+			BigDecimal refundedThirdAmount = money(tChargingOrder.getThirdRefundAmount());
+			BigDecimal refundableThirdAmount = money(tChargingOrder.getThirdPayAmount()).subtract(refundedThirdAmount);
+			if (refundableThirdAmount.compareTo(BigDecimal.ZERO) < 0) {
+				refundableThirdAmount = BigDecimal.ZERO;
+			}
+			BigDecimal thirdRefundAmount = isBalancePayMode(tChargingOrder.getPayMethod())
+					? manualRefundAmount.min(refundableThirdAmount).setScale(2, RoundingMode.HALF_UP)
+					: manualRefundAmount;
+			BigDecimal balanceRefundAmount = manualRefundAmount.subtract(thirdRefundAmount).setScale(2, RoundingMode.HALF_UP);
+			if (balanceRefundAmount.compareTo(BigDecimal.ZERO) < 0) {
+				balanceRefundAmount = BigDecimal.ZERO;
+			}
+			chargingOrderRefund.setBalanceRefundAmount(balanceRefundAmount);
+			chargingOrderRefund.setThirdRefundAmount(thirdRefundAmount);
+
+			if (thirdRefundAmount.compareTo(BigDecimal.ZERO) == 0) {
+				chargingOrderRefund.setRefundSerialNumber("BALANCE");
+				finishManualChargingRefund(tChargingOrder, chargingOrderRefund, manualRefundAmount, balanceRefundAmount, thirdRefundAmount);
+			}
+			else if (1 == tChargingOrder.getRechargePaymentType()) {
 				WxPaymentRefundModel model = new WxPaymentRefundModel();
 				model.setOut_trade_no(tChargingOrder.getCode());
 				model.setOut_refund_no(chargingOrderRefund.getRefundCode());
@@ -3145,16 +3836,13 @@
 				model.setReason("取消订单");
 				model.setNotify_url("/payment/wx/refund/notify");
 				WxPaymentRefundModel.RefundAmount amount = new WxPaymentRefundModel.RefundAmount();
-				amount.setRefund(payOrderQueryDto.getRefundAmount().multiply(new BigDecimal(100)).intValue());
-				amount.setTotal(tChargingOrder.getRechargeAmount().multiply(new BigDecimal(100)).intValue());
+				amount.setRefund(thirdRefundAmount.multiply(new BigDecimal(100)).intValue());
+				amount.setTotal(getRefundableThirdPayAmount(tChargingOrder).multiply(new BigDecimal(100)).intValue());
 				amount.setCurrency("CNY");
 				model.setAmount(amount);
 				R<Map<String, Object>> orderR = wxPaymentClient.refundOrderR(model);
 				if (200 == orderR.getCode()) {
-					tChargingOrder.setRefundStatus(2);
-					tChargingOrder.setRefundAmount((tChargingOrder.getRefundAmount() == null ? BigDecimal.valueOf(0) : tChargingOrder.getRefundAmount()).add(payOrderQueryDto.getRefundAmount()));
-					this.baseMapper.updateById(tChargingOrder);
-					chargingOrderRefundService.save(chargingOrderRefund);
+					finishManualChargingRefund(tChargingOrder, chargingOrderRefund, manualRefundAmount, balanceRefundAmount, thirdRefundAmount);
 					//手续费
 					Map<String, Object> amount1 = (Map<String, Object>) orderR.getData().get("amount");
 					Object refund_fee1 = amount1.get("refund_fee");
@@ -3164,33 +3852,27 @@
 				}
 			}
 			
-			if (2 == tChargingOrder.getRechargePaymentType()) {
+			else if (2 == tChargingOrder.getRechargePaymentType()) {
 				RefundReq dto = new RefundReq();
 				dto.setOutTradeNo(tChargingOrder.getCode());
 				dto.setOutRequestNo(tChargingOrder.getCode());
-				dto.setRefundAmount(payOrderQueryDto.getRefundAmount().toString());
+				dto.setRefundAmount(thirdRefundAmount.toString());
 				dto.setRefundReason("取消订单");
 				RefundResp resp = aliPaymentClient.refund(dto).getData();
 				if (null != resp) {
-					chargingOrderRefund.setRefundStatus(2);
-					chargingOrderRefund.setRefundAmount((tChargingOrder.getRefundAmount() == null ? BigDecimal.valueOf(0) : tChargingOrder.getRefundAmount()).add(payOrderQueryDto.getRefundAmount()));
-					this.baseMapper.updateById(tChargingOrder);
-					chargingOrderRefundService.save(chargingOrderRefund);
+					finishManualChargingRefund(tChargingOrder, chargingOrderRefund, manualRefundAmount, balanceRefundAmount, thirdRefundAmount);
 					
 				}
 			}
-			if (3 == tChargingOrder.getRechargePaymentType()) {
+			else if (3 == tChargingOrder.getRechargePaymentType()) {
 				RefundReq dto = new RefundReq();
 				dto.setOutTradeNo(tChargingOrder.getRechargeSerialNumber());
 				dto.setOutRequestNo(tChargingOrder.getCode());
-				dto.setRefundAmount(payOrderQueryDto.getRefundAmount().toString());
+				dto.setRefundAmount(thirdRefundAmount.toString());
 				dto.setRefundReason("取消订单");
 				RefundResp resp = h5AliPaymentClient.refund(dto).getData();
 				if (null != resp && "10000".equals(resp.getCode())) {
-					chargingOrderRefund.setRefundStatus(2);
-					chargingOrderRefund.setRefundAmount((tChargingOrder.getRefundAmount() == null ? BigDecimal.valueOf(0) : tChargingOrder.getRefundAmount()).add(payOrderQueryDto.getRefundAmount()));
-					this.baseMapper.updateById(tChargingOrder);
-					chargingOrderRefundService.save(chargingOrderRefund);
+					finishManualChargingRefund(tChargingOrder, chargingOrderRefund, manualRefundAmount, balanceRefundAmount, thirdRefundAmount);
 					
 				}
 			}
@@ -3231,7 +3913,7 @@
 			shoppingOrderRefund.setRefundRemark(payOrderQueryDto.getRemark());
 			shoppingOrderRefund.setRefundTotalAmount(shoppingOrder.getRefundAmount().add(payOrderQueryDto.getRefundAmount()));
 			shoppingOrderRefund.setPayAmount(shoppingOrder.getPaymentAmount());
-			
+
 			if (1 == shoppingOrder.getPaymentType()) {
 				WxPaymentRefundModel model = new WxPaymentRefundModel();
 				model.setOut_trade_no(shoppingOrder.getCode());
@@ -4341,6 +5023,7 @@
 		preChargeCheck.setInsulationTesting(false);
 		preChargeCheck.setSecureConnectionDetection(false);
 		preChargeCheck.setStartupSuccess(1);
+        preChargeCheck.setAddTime(LocalDateTime.now());
 		String key = "AQJC_" + chargingOrder.getChargingGunId();
 		redisService.setCacheObject(key, preChargeCheck, 24L, TimeUnit.HOURS);
 		
@@ -4652,4 +5335,634 @@
 	public List<Map<String, Object>> getAccountSettlementStatement(String startTime, String endTime, Integer rechargePaymentType) {
 		return this.baseMapper.getAccountSettlementStatement(startTime, endTime, rechargePaymentType);
 	}
+
+
+    /**
+     * 手动处理退款数据
+     * @param refund_out_trade_no 退款商户单号
+     */
+    @Override
+    public void orderQueryRefund(Long orderId, String refund_out_trade_no) {
+        TChargingOrder chargingOrder = this.getById(orderId);
+        BigDecimal rechargeAmount = chargingOrder.getRechargeAmount();
+        List<TChargingOrderRefund> orderRefunds = chargingOrderRefundService.list(new QueryWrapper<TChargingOrderRefund>().eq("charging_order_id", orderId));
+        List<String> collect = orderRefunds.stream().map(TChargingOrderRefund::getRefundCode).collect(Collectors.toList());
+        if(!collect.contains(refund_out_trade_no)){
+            if(1 == chargingOrder.getRechargePaymentType()){
+                Map<String, Object> data = wxPaymentClient.queryRefund(refund_out_trade_no).getData();
+                if(null == data){
+                    throw new ServiceException("退款查询失败");
+                }
+                log.info("退款查询结果:{}", JSON.toJSONString(data));
+                Map<String, Object> amount = (Map<String, Object>)data.get("amount");
+                TChargingOrderRefund chargingOrderRefund = new TChargingOrderRefund();
+                chargingOrderRefund.setChargingOrderId(chargingOrder.getId());
+                chargingOrderRefund.setRefundCode(refund_out_trade_no);
+                chargingOrderRefund.setRefundAmount(new BigDecimal(amount.get("refund").toString()).divide(new BigDecimal(100)));
+                chargingOrderRefund.setRefundStatus(2);
+                chargingOrderRefund.setPayType(1);
+                chargingOrderRefund.setRefundSerialNumber(data.get("refund_id").toString());
+                String success_time = data.get("success_time").toString();
+                success_time = success_time.replace("T", " ");
+                success_time = success_time.substring(0, success_time.lastIndexOf("+"));
+                chargingOrderRefund.setRefundTime(LocalDateTime.parse(success_time, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
+                chargingOrderRefund.setCode(chargingOrder.getCode());
+                chargingOrderRefund.setRefundTitle(rechargeAmount.compareTo(chargingOrderRefund.getRefundAmount()) == 0 ? "充电失败" : "充电完成退款");
+                chargingOrderRefund.setRefundContent(rechargeAmount.compareTo(chargingOrderRefund.getRefundAmount()) == 0 ? "充电失败" : "充电完成退款");
+                chargingOrderRefund.setRefundReason(rechargeAmount.compareTo(chargingOrderRefund.getRefundAmount()) == 0 ? "充电失败" : "充电完成退款");
+                chargingOrderRefund.setRefundRemark(rechargeAmount.compareTo(chargingOrderRefund.getRefundAmount()) == 0 ? "充电失败" : "充电完成退款");
+                chargingOrderRefund.setRefundTotalAmount(new BigDecimal(amount.get("refund").toString()).divide(new BigDecimal(100)));
+                chargingOrderRefund.setPayAmount(rechargeAmount);
+                chargingOrderRefund.setCreateTime(chargingOrderRefund.getRefundTime());
+                chargingOrderRefundService.save(chargingOrderRefund);
+                if(rechargeAmount.compareTo(chargingOrderRefund.getRefundAmount()) == 0){
+                    chargingOrder.setStatus(-1);
+                }else{
+                    chargingOrder.setStatus(5);
+                }
+                this.updateById(chargingOrder);
+            }
+            if(2 == chargingOrder.getRechargePaymentType()){
+                QueryRefundReq dto = new QueryRefundReq();
+                dto.setOutTradeNo(refund_out_trade_no);
+                QueryRefundResp data = aliPaymentClient.queryRefund(dto).getData();
+                if(null == data){
+                    throw new ServiceException("退款查询失败");
+                }
+                TChargingOrderRefund chargingOrderRefund = new TChargingOrderRefund();
+                chargingOrderRefund.setChargingOrderId(chargingOrder.getId());
+                chargingOrderRefund.setRefundCode(refund_out_trade_no);
+                chargingOrderRefund.setRefundAmount(new BigDecimal(data.getRefundAmount()));
+                chargingOrderRefund.setRefundStatus(2);
+                chargingOrderRefund.setPayType(1);
+                chargingOrderRefund.setRefundSerialNumber(data.getOutRequestNo());
+                chargingOrderRefund.setRefundTime(LocalDateTime.parse(data.getRefundTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
+                chargingOrderRefund.setCode(chargingOrder.getCode());
+                chargingOrderRefund.setRefundTitle(rechargeAmount.compareTo(chargingOrderRefund.getRefundAmount()) == 0 ? "充电失败" : "充电完成退款");
+                chargingOrderRefund.setRefundContent(rechargeAmount.compareTo(chargingOrderRefund.getRefundAmount()) == 0 ? "充电失败" : "充电完成退款");
+                chargingOrderRefund.setRefundReason(rechargeAmount.compareTo(chargingOrderRefund.getRefundAmount()) == 0 ? "充电失败" : "充电完成退款");
+                chargingOrderRefund.setRefundRemark(rechargeAmount.compareTo(chargingOrderRefund.getRefundAmount()) == 0 ? "充电失败" : "充电完成退款");
+                chargingOrderRefund.setRefundTotalAmount(new BigDecimal(data.getRefundAmount()));
+                chargingOrderRefund.setPayAmount(rechargeAmount);
+                chargingOrderRefund.setCreateTime(chargingOrderRefund.getRefundTime());
+                chargingOrderRefundService.save(chargingOrderRefund);
+
+                if(rechargeAmount.compareTo(chargingOrderRefund.getRefundAmount()) == 0){
+                    chargingOrder.setStatus(-1);
+                }else{
+                    chargingOrder.setStatus(5);
+                }
+                this.updateById(chargingOrder);
+            }
+        }
+    }
+
+
+    /**
+     * 手动添加完善订单费用明细
+     * @param orderId
+     */
+    @Override
+    public void addOrderExpenseBreakdown(Long orderId) {
+        try {
+            TChargingOrder chargingOrder = this.getById(orderId);
+            TransactionRecord one = transactionRecordService.findOne(chargingOrder.getCode());
+            if(null != one){
+                TransactionRecordMessageVO vo = new TransactionRecordMessageVO();
+                BeanUtils.copyProperties(one, vo);
+                //如果使用优惠券需要判断优惠券是否满足使用条件
+                //退款金额=优惠券金额+剩余充电金额
+                BigDecimal periodElectricPrice_total = BigDecimal.ZERO;
+                BigDecimal periodServicePrice_total = BigDecimal.ZERO;
+                BigDecimal vipDiscountAmount_total = BigDecimal.ZERO;
+                BigDecimal serviceCharge_total = BigDecimal.ZERO;
+                BigDecimal total = BigDecimal.ZERO;
+
+                //获取订单的计费策略
+                List<AccountingStrategyDetailOrder> accountingStrategyDetailOrderList = accountingStrategyDetailOrderClient.getAllAccountingStrategyDetailOrder(chargingOrder.getId()).getData();
+                if (accountingStrategyDetailOrderList.isEmpty()) {
+                    throw new ServiceException("计费策略为空,无法计算费用");
+                }
+                accountingStrategyDetailOrderList.get(accountingStrategyDetailOrderList.size() - 1).setEndTime("23:59");
+                //开始处理计费明细数据和优惠数据
+                chargingOrderAccountingStrategyService.remove(new LambdaQueryWrapper<TChargingOrderAccountingStrategy>().eq(TChargingOrderAccountingStrategy::getChargingOrderId, chargingOrder.getId()));
+                SimpleDateFormat sdfs = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+                List<AccountingStrategyDetailOrderVo> lists = new ArrayList<>();
+                List<UploadRealTimeMonitoringData> dataList = uploadRealTimeMonitoringDataService.getDataByOrderCode(chargingOrder.getCode());
+                if(!dataList.isEmpty()){
+                    vo.setStart_time(sdfs.format(dataList.get(dataList.size() - 1).getCreate_time()) + ".00");
+                    vo.setEnd_time(sdfs.format(dataList.get(0).getCreate_time()) + ".00");
+                }
+
+                //跨天
+                if (!vo.getStart_time().split(" ")[0].equals(vo.getEnd_time().split(" ")[0])) {
+                    //当天的
+                    //开始通过计费策略遍历解析每个时段的费用明细
+                    String start_time = vo.getStart_time();
+                    String end_time = vo.getEnd_time();
+                    long start = sdfs.parse(start_time).getTime();
+                    long end = sdfs.parse(end_time).getTime();
+                    Class<? extends TransactionRecordMessageVO> clazz = vo.getClass();
+                    /**
+                     * "start_time": "2025-01-03 23:06:43.00",
+                     * 	"end_time": "2025-01-04 00:39:39.00",
+                     */
+                    for (int i = accountingStrategyDetailOrderList.size(); i > 0; i--) {
+                        AccountingStrategyDetailOrder strategyDetail = accountingStrategyDetailOrderList.get(i - 1);
+                        long time = sdfs.parse(start_time.split(" ")[0] + " " + strategyDetail.getEndTime() + ":00").getTime();
+                        if (time < start) {
+                            break;
+                        }
+                        //阶段(1=尖阶段,2=峰阶段,3=平阶段,4=谷阶段)
+                        Object invoke = null;
+                        switch (strategyDetail.getType()) {
+                            case 1:
+                                //充电度数
+                                invoke = clazz.getMethod("getSpike_charge" + (i)).invoke(vo);
+                                break;
+                            case 2:
+                                //充电度数
+                                invoke = clazz.getMethod("getPeak_charge" + (i)).invoke(vo);
+                                break;
+                            case 3:
+                                //充电度数
+                                invoke = clazz.getMethod("getFlat_charge" + (i)).invoke(vo);
+                                break;
+                            case 4:
+                                //充电度数
+                                invoke = clazz.getMethod("getValley_charge" + (i)).invoke(vo);
+                                break;
+                        }
+                        if (null == invoke || Double.valueOf(invoke.toString()) == 0) {
+                            continue;
+                        }
+                        BigDecimal sharp_peak_charge = new BigDecimal(invoke.toString());
+                        AccountingStrategyDetailOrderVo vo1 = new AccountingStrategyDetailOrderVo();
+                        BeanUtils.copyProperties(strategyDetail, vo1);
+                        vo1.setChargingCapacity(sharp_peak_charge);
+                        lists.add(0, vo1);
+                    }
+
+                    //第二天的
+                    //开始通过计费策略遍历解析每个时段的费用明细
+                    for (int i = 0; i < accountingStrategyDetailOrderList.size(); i++) {
+                        AccountingStrategyDetailOrder strategyDetail = accountingStrategyDetailOrderList.get(i);
+                        long time = sdfs.parse(end_time.split(" ")[0] + " " + strategyDetail.getStartTime() + ":00").getTime();
+                        if (time > end) {
+                            break;
+                        }
+                        //阶段(1=尖阶段,2=峰阶段,3=平阶段,4=谷阶段)
+                        Object invoke = null;
+                        switch (strategyDetail.getType()) {
+                            case 1:
+                                //充电度数
+                                invoke = clazz.getMethod("getSpike_charge" + (i + 1)).invoke(vo);
+                                break;
+                            case 2:
+                                //充电度数
+                                invoke = clazz.getMethod("getPeak_charge" + (i + 1)).invoke(vo);
+                                break;
+                            case 3:
+                                //充电度数
+                                invoke = clazz.getMethod("getFlat_charge" + (i + 1)).invoke(vo);
+                                break;
+                            case 4:
+                                //充电度数
+                                invoke = clazz.getMethod("getValley_charge" + (i + 1)).invoke(vo);
+                                break;
+                        }
+                        if (null == invoke || Double.valueOf(invoke.toString()) == 0) {
+                            continue;
+                        }
+                        BigDecimal sharp_peak_charge = new BigDecimal(invoke.toString());
+                        AccountingStrategyDetailOrderVo vo1 = new AccountingStrategyDetailOrderVo();
+                        BeanUtils.copyProperties(strategyDetail, vo1);
+                        vo1.setChargingCapacity(sharp_peak_charge);
+                        lists.add(vo1);
+                    }
+                } else {
+                    for (int i = 0; i < accountingStrategyDetailOrderList.size(); i++) {
+                        Class<? extends TransactionRecordMessageVO> clazz = vo.getClass();
+                        AccountingStrategyDetailOrder strategyDetail = accountingStrategyDetailOrderList.get(i);
+                        //阶段(1=尖阶段,2=峰阶段,3=平阶段,4=谷阶段)
+                        Object invoke = null;
+                        switch (strategyDetail.getType()) {
+                            case 1:
+                                //充电度数
+                                invoke = clazz.getMethod("getSpike_charge" + (i + 1)).invoke(vo);
+                                break;
+                            case 2:
+                                //充电度数
+                                invoke = clazz.getMethod("getPeak_charge" + (i + 1)).invoke(vo);
+                                break;
+                            case 3:
+                                //充电度数
+                                invoke = clazz.getMethod("getFlat_charge" + (i + 1)).invoke(vo);
+                                break;
+                            case 4:
+                                //充电度数
+                                invoke = clazz.getMethod("getValley_charge" + (i + 1)).invoke(vo);
+                                break;
+                        }
+                        if (null == invoke || Double.valueOf(invoke.toString()) == 0) {
+                            continue;
+                        }
+                        BigDecimal sharp_peak_charge = new BigDecimal(invoke.toString());
+                        AccountingStrategyDetailOrderVo vo1 = new AccountingStrategyDetailOrderVo();
+                        BeanUtils.copyProperties(strategyDetail, vo1);
+                        vo1.setChargingCapacity(sharp_peak_charge);
+                        lists.add(vo1);
+                    }
+                }
+
+                //开始处理明细
+                for (int i = 0; i < lists.size(); i++) {
+                    AccountingStrategyDetailOrderVo strategyDetail = lists.get(i);
+                    BigDecimal sharp_peak_charge = strategyDetail.getChargingCapacity();
+                    TChargingOrderAccountingStrategy chargingOrderAccountingStrategy = new TChargingOrderAccountingStrategy();
+                    chargingOrderAccountingStrategy.setChargingOrderId(chargingOrder.getId());
+                    chargingOrderAccountingStrategy.setAccountingStrategyDetailId(strategyDetail.getId());
+                    chargingOrderAccountingStrategy.setType(strategyDetail.getType());
+                    chargingOrderAccountingStrategy.setElectrovalence(strategyDetail.getElectrovalence());
+                    chargingOrderAccountingStrategy.setServiceCharge(strategyDetail.getServiceCharge());
+                    chargingOrderAccountingStrategy.setCostServiceCharge(strategyDetail.getCostServiceCharge());
+                    if (i == 0) {
+                        String time = vo.getStart_time().split(" ")[1];
+                        chargingOrderAccountingStrategy.setStartTime(time.substring(0, time.lastIndexOf(":")));
+                    } else {
+                        chargingOrderAccountingStrategy.setStartTime(strategyDetail.getStartTime());
+                    }
+                    if (i == lists.size() - 1) {
+                        String time = vo.getEnd_time().split(" ")[1];
+                        chargingOrderAccountingStrategy.setEndTime(time.substring(0, time.lastIndexOf(":")));
+                    } else {
+                        chargingOrderAccountingStrategy.setEndTime(strategyDetail.getEndTime());
+                    }
+
+                    //已充电总度数
+                    BigDecimal electrovalenc = strategyDetail.getElectrovalence().multiply(sharp_peak_charge);
+                    BigDecimal originalServicePrice = strategyDetail.getServiceCharge().multiply(sharp_peak_charge);
+                    BigDecimal serviceCharge = originalServicePrice;
+                    BigDecimal vipDiscountAmount = BigDecimal.ZERO;
+                    //计算优惠金额
+                    if (null != chargingOrder.getVipDiscount()) {
+                        //0.58折
+                        vipDiscountAmount = serviceCharge.multiply(new BigDecimal(1).subtract(chargingOrder.getVipDiscount()));
+                        serviceCharge = serviceCharge.multiply(chargingOrder.getVipDiscount());
+                    }
+                    chargingOrderAccountingStrategy.setChargingCapacity(sharp_peak_charge);
+                    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());
+                    chargingOrderAccountingStrategyService.save(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));
+                }
+
+                BigDecimal orderAmount = BigDecimal.valueOf(total.doubleValue());
+                //原金额
+                BigDecimal rechargeAmount = chargingOrder.getRechargeAmount();
+                //支付金额
+                BigDecimal payAmount = periodElectricPrice_total.add(serviceCharge_total);
+                //退款金额=充值金额-实际支付金额
+                BigDecimal refundAmount = rechargeAmount.subtract(payAmount);
+
+                UploadRealTimeMonitoringData uploadRealTimeMonitoringData = uploadRealTimeMonitoringDataService.getLastDataById(chargingOrder.getCode());
+                if (null != uploadRealTimeMonitoringData && null == chargingOrder.getEndMode()) {
+                    Integer soc = uploadRealTimeMonitoringData.getSoc();
+                    if (soc >= 98) {
+                        chargingOrder.setEndMode(2);
+                    } else if (null != chargingOrder.getResidualAmount() && chargingOrder.getResidualAmount().compareTo(new BigDecimal(1)) <= 0) {
+                        chargingOrder.setEndMode(3);
+                    } else {
+                        chargingOrder.setEndMode(1);
+                    }
+                }
+                chargingOrder.setResidualAmount(rechargeAmount.subtract(total).setScale(2, RoundingMode.HALF_EVEN));
+
+                chargingOrder.setStartTime(LocalDateTime.parse(vo.getStart_time(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SS")));
+                chargingOrder.setEndTime(LocalDateTime.parse(vo.getEnd_time(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SS")));
+                chargingOrder.setStatus(5);
+                chargingOrder.setOrderAmount(orderAmount.setScale(2, RoundingMode.HALF_EVEN));
+                chargingOrder.setElectrovalence(periodElectricPrice_total.setScale(2, RoundingMode.HALF_EVEN));
+                chargingOrder.setChargingCapacity(vo.getTotal_electricity());
+                chargingOrder.setElectricity(vo.getTotal_electricity());
+                chargingOrder.setVipDiscountAmount(vipDiscountAmount_total);
+                if (vipDiscountAmount_total.compareTo(BigDecimal.ZERO) == 0) {
+                    chargingOrder.setVipDiscount(BigDecimal.valueOf(1));
+                }
+
+                //计算优惠券
+                BigDecimal couponDiscount = BigDecimal.ZERO;
+                if (null != chargingOrder.getAppCouponId()) {
+                    //判断实际充电金额是否满足优惠券使用条件,如果不满足则不适用优惠券。
+                    TAppCoupon appCoupon = appCouponClient.getAppCouponById(chargingOrder.getAppCouponId()).getData();
+                    String couponJson = appCoupon.getCouponJson();
+                    TCoupon tCoupon = 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(chargingOrder.getAppCouponId().toString());
+                            chargingOrder.setAppCouponId(null);
+                            chargingOrder.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 {
+                            chargingOrder.setAppCouponId(null);
+                            chargingOrder.setCouponDiscountAmount(BigDecimal.ZERO);
+                            appCouponClient.refund(chargingOrder.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);
+                }
+                chargingOrder.setCouponDiscountAmount(couponDiscount.setScale(2, RoundingMode.HALF_EVEN));
+                chargingOrder.setServiceCharge(serviceCharge_total.setScale(2, RoundingMode.HALF_EVEN));
+                chargingOrder.setPaymentAmount(payAmount.setScale(2, RoundingMode.HALF_EVEN));
+                chargingOrder.setRefundAmount(refundAmount.setScale(2, RoundingMode.HALF_EVEN));
+                chargingOrder.setRefundStatus(1);
+                UploadRealTimeMonitoringData asc = uploadRealTimeMonitoringDataService.getDataByOrderCode(chargingOrder.getCode(), "asc");
+                UploadRealTimeMonitoringData desc = uploadRealTimeMonitoringDataService.getDataByOrderCode(chargingOrder.getCode(), "desc");
+                if(null != asc){
+                    chargingOrder.setStartSoc(new BigDecimal(asc.getSoc()));
+                }
+                if(null != desc){
+                    chargingOrder.setEndSoc(new BigDecimal(desc.getSoc()));
+                }
+                this.updateById(chargingOrder);
+            }else{
+                List<UploadRealTimeMonitoringData> dataList = uploadRealTimeMonitoringDataService.getDataByOrderCode(chargingOrder.getCode());
+                if(!dataList.isEmpty()) {
+                    //获取当前订单的计费规则,然后分段计算总的度数和充电金额
+                    List<AccountingStrategyDetailOrder> detailOrders = accountingStrategyDetailOrderService.list(new LambdaQueryWrapper<AccountingStrategyDetailOrder>()
+                            .eq(AccountingStrategyDetailOrder::getChargingOrderId, chargingOrder.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(chargingOrder.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 != chargingOrder.getVipDiscount()) {
+                                    //0.58折
+                                    vipDiscountAmount = serviceCharge.multiply(new BigDecimal(1).subtract(chargingOrder.getVipDiscount()));
+                                    serviceCharge = serviceCharge.multiply(chargingOrder.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 = chargingOrder.getRechargeAmount();
+                    //支付金额
+                    BigDecimal payAmount = periodElectricPrice_total.add(serviceCharge_total);
+                    //退款金额=充值金额-实际支付金额
+                    BigDecimal refundAmount = rechargeAmount.subtract(payAmount);
+
+                    UploadRealTimeMonitoringData uploadRealTimeMonitoringData = uploadRealTimeMonitoringDataService.getLastDataById(chargingOrder.getCode());
+                    if (null != uploadRealTimeMonitoringData && null == chargingOrder.getEndMode()) {
+                        Integer soc = uploadRealTimeMonitoringData.getSoc();
+                        if (soc >= 98) {
+                            chargingOrder.setEndMode(2);
+                        } else if (null != chargingOrder.getResidualAmount() && chargingOrder.getResidualAmount().compareTo(new BigDecimal(1)) <= 0) {
+                            chargingOrder.setEndMode(3);
+                        } else {
+                            chargingOrder.setEndMode(1);
+                        }
+                    }
+
+                    chargingOrder.setResidualAmount(rechargeAmount.subtract(total).setScale(2, RoundingMode.HALF_EVEN));
+                    chargingOrder.setStartTime(list.get(0).getCreateTime());
+                    chargingOrder.setEndTime(list.get(list.size() - 1).getCreateTime());
+                    chargingOrder.setStatus(5);
+                    chargingOrder.setOrderAmount(orderAmount.setScale(2, RoundingMode.HALF_EVEN));
+                    chargingOrder.setElectrovalence(periodElectricPrice_total.setScale(2, RoundingMode.HALF_EVEN));
+                    chargingOrder.setChargingCapacity(list.get(list.size() - 1).getChargingCapacity());
+                    chargingOrder.setElectricity(list.get(list.size() - 1).getChargingCapacity());
+                    chargingOrder.setVipDiscountAmount(vipDiscountAmount_total);
+                    if (vipDiscountAmount_total.compareTo(BigDecimal.ZERO) == 0) {
+                        chargingOrder.setVipDiscount(BigDecimal.valueOf(1));
+                    }
+
+                    //计算优惠券
+                    BigDecimal couponDiscount = BigDecimal.ZERO;
+                    if (null != chargingOrder.getAppCouponId()) {
+                        //判断实际充电金额是否满足优惠券使用条件,如果不满足则不适用优惠券。
+                        TAppCoupon appCoupon = appCouponClient.getAppCouponById(chargingOrder.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(chargingOrder.getAppCouponId().toString());
+                                chargingOrder.setAppCouponId(null);
+                                chargingOrder.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 {
+                                chargingOrder.setAppCouponId(null);
+                                chargingOrder.setCouponDiscountAmount(BigDecimal.ZERO);
+                                appCouponClient.refund(chargingOrder.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);
+                    }
+                    chargingOrder.setCouponDiscountAmount(couponDiscount.setScale(2, RoundingMode.HALF_EVEN));
+                    chargingOrder.setServiceCharge(serviceCharge_total.setScale(2, RoundingMode.HALF_EVEN));
+                    chargingOrder.setPaymentAmount(payAmount.setScale(2, RoundingMode.HALF_EVEN));
+                    chargingOrder.setRefundAmount(refundAmount.setScale(2, RoundingMode.HALF_EVEN));
+                    chargingOrder.setRefundStatus(1);
+                    UploadRealTimeMonitoringData asc = uploadRealTimeMonitoringDataService.getDataByOrderCode(chargingOrder.getCode(), "asc");
+                    UploadRealTimeMonitoringData desc = uploadRealTimeMonitoringDataService.getDataByOrderCode(chargingOrder.getCode(), "desc");
+                    if (null != asc) {
+                        chargingOrder.setStartSoc(new BigDecimal(asc.getSoc()));
+                    }
+                    if (null != desc) {
+                        chargingOrder.setEndSoc(new BigDecimal(desc.getSoc()));
+                    }
+                    chargingOrderService.updateById(chargingOrder);
+                }
+            }
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+    }
 }

--
Gitblit v1.7.1