puzhibing
8 小时以前 e1c8c9d51f1c6e42c9868743f16fa8e52bb419cd
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingOrderServiceImpl.java
@@ -56,6 +56,7 @@
import com.ruoyi.order.mapper.TChargingOrderMapper;
import com.ruoyi.order.mapper.TChargingOrderShareRecordMapper;
import com.ruoyi.order.mapper.TSettlementConfirmMapper;
import com.ruoyi.order.mapper.TVinChargingOrderMapper;
import com.ruoyi.order.service.TChargingOrderAccountingStrategyService;
import com.ruoyi.order.service.TChargingOrderRefundService;
import com.ruoyi.order.service.TChargingOrderService;
@@ -251,6 +252,9 @@
    @Resource
    private UploadRealTimeMonitoringDataService uploadRealTimeMonitoringDataService;
    @Resource
    private TVinChargingOrderMapper vinChargingOrderMapper;
    @Resource
    private TCECClient tcecClient;
@@ -804,10 +808,10 @@
     * 解析白名单企业账户充电上下文(白名单用户选择余额支付时调用):
     * 1) 校验归属公司存在且启用,未归属/停用直接拒绝;
     * 2) 校验企业充电授权(站点范围、可用时段/电价阶段)并计算授权截止时间,未配置授权按放行处理(对齐 VIN 口径);
     * 3) 下发额度 = min(用户输入充值金额, 账户可用额度, 企业设定的充值金额):
     * 3) 下发额度:
     *    - 账户可用额度:共享模式=公司可用余额,分配模式=白名单账户余额;
     *    - 企业设定充值金额=授权配置下发金额,未配置默认 200 元;
     *    - 用户输入金额为空或非正数时按 min(企业设定充值金额, 账户可用额度) 下发。
     *    - 共享模式=min(用户输入充值金额, 账户可用额度, 企业设定充值金额),企业设定充值金额=授权配置下发金额,未配置默认 200 元;
     *    - 分配模式=min(用户输入充值金额, 白名单账户余额),用户输入为空或非正数时直接下发白名单账户余额(不再受企业设定充值金额限制)。
     *
     * @param whitelist       白名单命中结果(含归属公司与账户余额快照)
     * @param userInputAmount 用户输入的充值金额
@@ -867,14 +871,19 @@
        if (usable.compareTo(BigDecimal.ZERO) <= 0) {
            return ChargeAccountSupport.ChargeContext.fail(3, "企业额度不足,请选择其他支付方式");
        }
        BigDecimal enterpriseLimit = authorization == null ? null : authorization.getDispatchAmount();
        if (enterpriseLimit == null || enterpriseLimit.compareTo(BigDecimal.ZERO) <= 0) {
            enterpriseLimit = ChargeAccountSupport.DEFAULT_DISPATCH_AMOUNT;
        }
        BigDecimal dispatch = money(userInputAmount);
        dispatch = dispatch.compareTo(BigDecimal.ZERO) <= 0
                ? enterpriseLimit.min(usable)
                : dispatch.min(enterpriseLimit).min(usable);
        if (accountMode == ChargeAccountSupport.ACCOUNT_MODE_ALLOCATED) {
            // 分配模式:直接下发白名单账户余额(用户输入正数时以用户输入为上限),不再受公司充电下发金额限制
            dispatch = dispatch.compareTo(BigDecimal.ZERO) <= 0 ? usable : dispatch.min(usable);
        } else {
            BigDecimal enterpriseLimit = authorization == null ? null : authorization.getDispatchAmount();
            if (enterpriseLimit == null || enterpriseLimit.compareTo(BigDecimal.ZERO) <= 0) {
                enterpriseLimit = ChargeAccountSupport.DEFAULT_DISPATCH_AMOUNT;
            }
            dispatch = dispatch.compareTo(BigDecimal.ZERO) <= 0
                    ? enterpriseLimit.min(usable)
                    : dispatch.min(enterpriseLimit).min(usable);
        }
        return ChargeAccountSupport.ChargeContext.ok(accountMode, dispatch.setScale(2, RoundingMode.HALF_UP), maxEndTime);
    }
@@ -2767,7 +2776,19 @@
                .orderByDesc(TChargingOrder::getCreateTime)
                .last(" limit 0, 1"));
        if (null == one || !one.getAppUserId().equals(userId)) {
            return null;
            // VIN 码充电订单兜底:VD 订单存于 t_vin_charging_order,且后付模式无支付动作,
            // 不按 rechargePaymentStatus 过滤;TVinChargingOrder 继承 TChargingOrder,后续组装原样复用
            TVinChargingOrder vinOrder = vinChargingOrderMapper.selectOne(new LambdaQueryWrapper<TVinChargingOrder>()
                    .eq(TVinChargingOrder::getAppUserId, userId)
                    .eq(TVinChargingOrder::getChargingGunId, id)
                    .in(TVinChargingOrder::getStatus, Arrays.asList(2, 3, 4))
                    .eq(TVinChargingOrder::getDelFlag, 0)
                    .orderByDesc(TVinChargingOrder::getCreateTime)
                    .last(" limit 0, 1"));
            if (null == vinOrder) {
                return null;
            }
            one = vinOrder;
        }
        ChargingDetails chargingDetails = new ChargingDetails();
        chargingDetails.setId(one.getId().toString());
@@ -2780,7 +2801,8 @@
        boolean reservationPending = ReservationOrderSupport.isPending(
                one.getStatus(), one.getReservationTime(), LocalDateTime.now());
        chargingDetails.setStatus(reservationPending ? 1 : one.getStatus());
        chargingDetails.setChargingCost(one.getResidualAmount());
        // 已使用费用:默认取订单已使用金额,存在实时监测数据时以设备上报已充金额(电费+服务费)为准
        chargingDetails.setChargingCost(money(one.getResidualAmount()));
        UploadRealTimeMonitoringData data = uploadRealTimeMonitoringDataService.getLastDataById(one.getCode());
        if (null != data) {
            chargingDetails.setChargeCurrent(data.getOutput_current());
@@ -2793,6 +2815,10 @@
            Integer h = Integer.valueOf(data.getCumulative_charging_time() / 60);
            Integer m = Integer.valueOf(data.getCumulative_charging_time() % 60);
            chargingDetails.setChargedTime(String.format("%02d", h) + ":" + String.format("%02d", m));
            // 设备上报已充金额非空时覆盖,上报缺失则沿用订单已使用金额
            if (null != data.getPaid_amount()) {
                chargingDetails.setChargingCost(money(data.getPaid_amount()));
            }
            if (null != one.getAppUserCarId()) {
                TAppUserCar appUserCar = appUserCarClient.getCarById(one.getAppUserCarId().toString()).getData();
                //   续航 = 续航里程 * soc
@@ -8058,6 +8084,14 @@
    public EndOfChargePageInfo getEndOfChargePageInfo(String id) {
        EndOfChargePageInfo info = new EndOfChargePageInfo();
        TChargingOrder chargingOrder = this.getById(id);
        if (chargingOrder == null) {
            // VIN 码充电订单兜底:VD 订单存于 t_vin_charging_order(继承 TChargingOrder,字段兼容;
            // 结算已写 paymentAmount/startTime/endTime,后续组装原样复用)
            chargingOrder = vinChargingOrderMapper.selectById(id);
        }
        if (chargingOrder == null) {
            throw new RuntimeException("充电订单不存在");
        }
        Long userId = tokenService.getLoginUserApplet().getUserId();
        if (!chargingOrder.getAppUserId().equals(userId)) {
            throw new RuntimeException("权限不足");