From a70433b2ee5bb37823ab73422a01251343cb5f58 Mon Sep 17 00:00:00 2001
From: puzhibing <393733352@qq.com>
Date: 星期二, 29 九月 2026 17:55:50 +0800
Subject: [PATCH] 修改订单业务流程和其他功能修改

---
 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/util/task/TaskUtil.java |  117 +++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 106 insertions(+), 11 deletions(-)

diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/util/task/TaskUtil.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/util/task/TaskUtil.java
index 40fd2aa..22b88b7 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/util/task/TaskUtil.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/util/task/TaskUtil.java
@@ -11,10 +11,12 @@
 import com.ruoyi.account.api.model.TAppCoupon;
 import com.ruoyi.account.api.model.TAppUser;
 import com.ruoyi.account.api.model.TAppUserIntegralChange;
+import com.ruoyi.chargingPile.api.dto.TBillingTemplateDTO;
 import com.ruoyi.chargingPile.api.feignClient.ChargingGunClient;
 import com.ruoyi.chargingPile.api.feignClient.SiteClient;
 import com.ruoyi.chargingPile.api.model.Partner;
 import com.ruoyi.chargingPile.api.model.Site;
+import com.ruoyi.chargingPile.api.model.TBillingTemplateDetail;
 import com.ruoyi.chargingPile.api.model.TChargingGun;
 import com.ruoyi.common.core.domain.R;
 import com.ruoyi.common.core.utils.StringUtils;
@@ -29,11 +31,13 @@
 import com.ruoyi.order.api.vo.TransactionRecordMessageVO;
 import com.ruoyi.order.service.*;
 import com.ruoyi.order.service.impl.ChargingCouponSupport;
+import com.ruoyi.order.support.ChargeAccountSupport;
 import com.ruoyi.order.util.mongodb.service.TransactionRecordService;
 import com.ruoyi.order.util.mongodb.service.UploadRealTimeMonitoringDataService;
 import com.ruoyi.other.api.domain.TCoupon;
 import com.ruoyi.other.api.domain.TIntegralRule;
 import com.ruoyi.other.api.domain.TVip;
+import com.ruoyi.other.api.dto.CompanyPreferentialDTO;
 import com.ruoyi.other.api.dto.ExchangeCodeConsumeDTO;
 import com.ruoyi.other.api.feignClient.IntegralRuleClient;
 import com.ruoyi.other.api.feignClient.OtherClient;
@@ -164,6 +168,9 @@
 
     @Resource
     private RedissonClient redissonClient;
+
+    @Resource
+    private ChargeAccountSupport chargeAccountSupport;
 
 
 
@@ -303,6 +310,21 @@
         if (isScheduledTaskPort(port)) {
             compensateCardOrders();
             compensateVinOrders();
+        }
+    }
+
+    /**
+     * VIN 结算失败重试(1分钟一轮,结算失败主触发):处理账户结算失败回退的状态4订单,
+     * 与10分钟补偿任务(DB兜底扫描)互补;重试幂等由账户侧消费流水保证,不会重复扣款。
+     */
+    @Scheduled(fixedRate = 1000 * 60, initialDelay = 1000 * 30)
+    public void vinSettleRetryTask() {
+        if (isScheduledTaskPort(port)) {
+            try {
+                vinChargingOrderService.retryPendingVinSettle();
+            } catch (Exception e) {
+                log.error("[VD结算重试] 定时任务异常", e);
+            }
         }
     }
 
@@ -668,6 +690,16 @@
                         }
                     }
 
+                    //企业账户流程:白名单企业账户订单按企业优惠结算(方式2=服务费比例优惠,方式3=按计费模板同阶段单价)
+                    boolean enterpriseSettlement = chargingOrderService.isWhitelistEnterpriseOrder(order);
+                    CompanyPreferentialDTO enterprisePreferential = enterpriseSettlement
+                            ? chargeAccountSupport.loadCompanyPreferential(order.getCompanyId()) : null;
+                    Integer enterprisePreferentialType = null == enterprisePreferential ? null : enterprisePreferential.getPreferentialType();
+                    TBillingTemplateDTO enterpriseTemplate = enterpriseSettlement
+                            ? chargeAccountSupport.loadBillingTemplate(enterprisePreferential) : null;
+                    BigDecimal enterpriseElectricDiscount = BigDecimal.ZERO;
+                    BigDecimal enterpriseServiceDiscount = BigDecimal.ZERO;
+
                     SimpleDateFormat sdf1 = new SimpleDateFormat("yyyyMMddHHmm");
                     List<TChargingOrderAccountingStrategy> list = new ArrayList<>();
                     for (AccountingStrategyDetailOrder detailOrder : detailOrders) {
@@ -708,15 +740,46 @@
                                 chargingOrderAccountingStrategy.setEndTime(detailOrder.getEndTime().split(" ")[1]);
 
                                 //已充电总度数
-                                BigDecimal electrovalenc = detailOrder.getElectrovalence().multiply(subtract);
+                                BigDecimal finalElectricPrice = detailOrder.getElectrovalence();
+                                BigDecimal finalServicePrice = detailOrder.getServiceCharge();
+                                //企业账户流程:按企业优惠计算最终用电单价
+                                if (enterpriseSettlement) {
+                                    if (Integer.valueOf(ChargeAccountSupport.PREFERENTIAL_TYPE_RATE).equals(enterprisePreferentialType)) {
+                                        //方式2:服务费按比例优惠
+                                        finalServicePrice = ChargeAccountSupport.applyServiceDiscountRate(finalServicePrice, enterprisePreferential.getServiceDiscountRate());
+                                    } else if (Integer.valueOf(ChargeAccountSupport.PREFERENTIAL_TYPE_TEMPLATE).equals(enterprisePreferentialType)) {
+                                        //方式3:按计费模板同电价阶段单价
+                                        TBillingTemplateDetail templateDetail = ChargeAccountSupport.findTemplateDetail(enterpriseTemplate, detailOrder.getType());
+                                        if (null == templateDetail) {
+                                            log.error("[CD补偿结算] 计费模板缺少对应电价阶段,该阶段按原价结算 code={} type={}", order.getCode(), detailOrder.getType());
+                                        } else {
+                                            if (null != templateDetail.getElectrovalence()) {
+                                                finalElectricPrice = templateDetail.getElectrovalence();
+                                            }
+                                            if (null != templateDetail.getServiceCharge()) {
+                                                finalServicePrice = templateDetail.getServiceCharge();
+                                            }
+                                        }
+                                    }
+                                }
+                                BigDecimal electrovalenc = finalElectricPrice.multiply(subtract);
                                 BigDecimal originalServicePrice = detailOrder.getServiceCharge().multiply(subtract);
-                                BigDecimal serviceCharge = originalServicePrice;
+                                BigDecimal serviceCharge = finalServicePrice.multiply(subtract);
                                 BigDecimal vipDiscountAmount = BigDecimal.ZERO;
-                                //计算优惠金额;余额支付(含组合支付)不参与会员折扣
-                                if (!isWhitelistOrder(order) && !isBalancePayMode(order.getPayMethod()) && null != order.getVipDiscount()) {
+                                //计算优惠金额;企业账户流程按企业优惠结算,其余订单中余额支付(含组合支付)不参与会员折扣
+                                if (enterpriseSettlement) {
+                                    //企业优惠金额(原价-优惠价),用于订单优惠统计与 whitelist_* 快照
+                                    enterpriseElectricDiscount = enterpriseElectricDiscount.add(detailOrder.getElectrovalence().multiply(subtract).subtract(electrovalenc));
+                                    enterpriseServiceDiscount = enterpriseServiceDiscount.add(originalServicePrice.subtract(serviceCharge));
+                                } else if (!isWhitelistOrder(order) && !isBalancePayMode(order.getPayMethod()) && null != order.getVipDiscount()) {
                                     //0.58折
                                     vipDiscountAmount = serviceCharge.multiply(new BigDecimal(1).subtract(order.getVipDiscount()));
                                     serviceCharge = serviceCharge.multiply(order.getVipDiscount());
+                                }
+                                //企业账户流程:明细单价记录优惠后单价,金额与单价口径一致
+                                if (enterpriseSettlement) {
+                                    chargingOrderAccountingStrategy.setElectrovalence(finalElectricPrice);
+                                    chargingOrderAccountingStrategy.setServiceCharge(finalServicePrice);
                                 }
                                 chargingOrderAccountingStrategy.setPeriodElectricPrice(electrovalenc.setScale(4, RoundingMode.HALF_EVEN));
                                 chargingOrderAccountingStrategy.setPeriodServicePrice(serviceCharge.setScale(4, RoundingMode.HALF_EVEN));
@@ -828,7 +891,12 @@
                     BigDecimal electricDiscount = whitelistRefundSplit[0];
                     BigDecimal serviceDiscount = whitelistRefundSplit[1];
                     BigDecimal whitelistDiscount = electricDiscount.add(serviceDiscount).setScale(4, RoundingMode.HALF_EVEN);
-                    if (whitelistDiscount.compareTo(BigDecimal.ZERO) > 0) {
+                    if (enterpriseSettlement) {
+                        // 企业账户流程:企业优惠已在明细阶段计入金额,这里只做统计快照(金额口径与实时结算一致)
+                        electricDiscount = enterpriseElectricDiscount.max(BigDecimal.ZERO).setScale(4, RoundingMode.HALF_EVEN);
+                        serviceDiscount = enterpriseServiceDiscount.max(BigDecimal.ZERO).setScale(4, RoundingMode.HALF_EVEN);
+                        whitelistDiscount = electricDiscount.add(serviceDiscount);
+                    } else if (whitelistDiscount.compareTo(BigDecimal.ZERO) > 0) {
                         // 补偿任务需与实时结算使用同一拆分口径,避免财务导出金额不一致。
                         periodElectricPrice_total = periodElectricPrice_total.subtract(electricDiscount).max(BigDecimal.ZERO);
                         serviceCharge_total = serviceCharge_total.subtract(serviceDiscount).max(BigDecimal.ZERO);
@@ -845,14 +913,32 @@
                         serviceCharge_total = serviceCharge_total.subtract(couponDiscount);
                     }
                     order.setCouponDiscountAmount(couponDiscount.setScale(2, RoundingMode.HALF_EVEN));
-                    order.setWhitelistDiscountAmount(whitelistDiscount.setScale(2, RoundingMode.HALF_EVEN));
-                    order.setWhitelistElectricRefundAmount(electricDiscount.setScale(2, RoundingMode.HALF_EVEN));
-                    order.setWhitelistServiceRefundAmount(serviceDiscount.setScale(2, RoundingMode.HALF_EVEN));
+                    //企业账户流程:企业优惠金额与 whitelist_* 三列快照双写(订单优惠统计沿用 whitelist_* 口径)
+                    if (enterpriseSettlement) {
+                        order.setDiscountElectrovalence(electricDiscount.setScale(2, RoundingMode.HALF_EVEN));
+                        order.setDiscountServiceCharge(serviceDiscount.setScale(2, RoundingMode.HALF_EVEN));
+                        order.setWhitelistElectricRefundAmount(electricDiscount.setScale(2, RoundingMode.HALF_EVEN));
+                        order.setWhitelistServiceRefundAmount(serviceDiscount.setScale(2, RoundingMode.HALF_EVEN));
+                        order.setWhitelistDiscountAmount(whitelistDiscount.setScale(2, RoundingMode.HALF_EVEN));
+                    } else {
+                        order.setWhitelistDiscountAmount(whitelistDiscount.setScale(2, RoundingMode.HALF_EVEN));
+                        order.setWhitelistElectricRefundAmount(electricDiscount.setScale(2, RoundingMode.HALF_EVEN));
+                        order.setWhitelistServiceRefundAmount(serviceDiscount.setScale(2, RoundingMode.HALF_EVEN));
+                    }
                     order.setElectrovalence(periodElectricPrice_total.setScale(2, RoundingMode.HALF_EVEN));
                     order.setServiceCharge(serviceCharge_total.setScale(2, RoundingMode.HALF_EVEN));
-                    order.setPaymentAmount(payAmount.setScale(2, RoundingMode.HALF_EVEN));
-                    order.setRefundAmount(refundAmount.setScale(2, RoundingMode.HALF_EVEN));
-                    order.setRefundStatus(1);
+                    if (enterpriseSettlement) {
+                        // 企业账户流程:资金来自企业账户额度(差额结算时退回企业账户),订单无用户侧退款,实付金额=实际消费金额
+                        order.setBalancePayAmount(payAmount.setScale(2, RoundingMode.HALF_EVEN));
+                        order.setPaymentAmount(payAmount.setScale(2, RoundingMode.HALF_EVEN));
+                        order.setRefundAmount(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_EVEN));
+                        order.setRefundStatus(2);
+                        refundAmount = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_EVEN);
+                    } else {
+                        order.setPaymentAmount(payAmount.setScale(2, RoundingMode.HALF_EVEN));
+                        order.setRefundAmount(refundAmount.setScale(2, RoundingMode.HALF_EVEN));
+                        order.setRefundStatus(1);
+                    }
                     UploadRealTimeMonitoringData asc = uploadRealTimeMonitoringDataService.getDataByOrderCode(order.getCode(), "asc");
                     UploadRealTimeMonitoringData desc = uploadRealTimeMonitoringDataService.getDataByOrderCode(order.getCode(), "desc");
                     if(null != asc){
@@ -863,6 +949,15 @@
                     }
                     chargingOrderService.updateById(order);
 
+                    //企业账户流程:结算企业额度(按实际消费扣减锁定额度、差额退回企业账户)并写消费流水
+                    if (enterpriseSettlement && !chargingOrderService.settleWhitelistEnterpriseAccount(order, payAmount)) {
+                        // 结算失败回退为停止中,交由补偿任务下一轮重新结算,避免企业额度长期冻结
+                        order.setStatus(4);
+                        chargingOrderService.updateById(order);
+                        log.error("[CD补偿结算] 企业账户额度结算失败,订单回退停止中等待重试 code={}", order.getCode());
+                        return;
+                    }
+
                     order = chargingOrderService.getById(order.getId());
                     Site site = siteClient.getSiteByIds(Arrays.asList(order.getSiteId())).getData().get(0);
                     //推送三方平台

--
Gitblit v1.7.1