puzhibing
10 小时以前 8ea02ca30907216aece38fda1ba918e5a5246abe
ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TCardChargingOrderServiceImpl.java
@@ -316,8 +316,9 @@
        result.put("endMode", order.getEndMode());
        result.put("phone", order.getPhone());
        result.put("licensePlate", order.getPlateNum());
        result.put("startSoc", "-");
        result.put("endSoc", "-");
        // SOC 展示口径:优先展示结算回填的开始/结束 SOC;历史订单未采集时保持占位符
        result.put("startSoc", order.getStartSoc() == null ? "-" : order.getStartSoc().toPlainString());
        result.put("endSoc", order.getEndSoc() == null ? "-" : order.getEndSoc().toPlainString());
        if (order.getStartTime() != null && order.getEndTime() != null) {
            result.put("chargingSecond", ChronoUnit.SECONDS.between(order.getStartTime(), order.getEndTime()));
        }
@@ -1418,6 +1419,9 @@
        final BigDecimal svcTotal = serviceChargeTotal;
        final BigDecimal discountElecTotal = discountElectricTotal;
        final BigDecimal discountSvcTotal = discountServiceTotal;
        // SOC 回填(与 VIN 结算同口径):取订单最早/最新实时监控上报,读取失败不阻断结算
        final BigDecimal startSoc = getMonitoringSocQuietly(code, "asc");
        final BigDecimal endSoc = getMonitoringSocQuietly(code, "desc");
        // 剩余金额口径:可用金额基数(建单写入的 charge_amount) - 本单金额;
        // 改造前创建的老订单无基数时以本单金额兜底(剩余金额记 0),并顺带补齐 charge_amount
        final BigDecimal chargeBase = order.getChargeAmount() != null ? order.getChargeAmount() : orderAmount;
@@ -1455,6 +1459,13 @@
            update.setStatus(ORDER_STATUS_FINISHED);
            if (order.getEndMode() == null) {
                update.setEndMode(1);
            }
            // SOC 回填:监控数据缺失/查询异常时不覆盖既有值,与 VIN 结算行为一致
            if (startSoc != null) {
                update.setStartSoc(startSoc);
            }
            if (endSoc != null) {
                update.setEndSoc(endSoc);
            }
            if (preferentialBackfill) {
                // 历史订单(快照为空)实时查询结果回填订单快照列,保证后续补偿重算口径一致
@@ -1498,6 +1509,24 @@
    }
    /**
     * 容错读取订单最早/最新监控记录的 SOC(与 VIN 结算同口径):
     * Mongo 数据缺失、SOC 未上报或查询异常返回 null,不阻断主结算流程。
     */
    private BigDecimal getMonitoringSocQuietly(String code, String sort) {
        if (uploadRealTimeMonitoringDataService == null) {
            return null;
        }
        try {
            UploadRealTimeMonitoringData monitoringData = uploadRealTimeMonitoringDataService.getDataByOrderCode(code, sort);
            return monitoringData == null || monitoringData.getSoc() == null
                    ? null : BigDecimal.valueOf(monitoringData.getSoc().longValue());
        } catch (Exception ex) {
            log.error("[SD结算] 查询监控SOC失败 code={} sort={}", code, sort, ex);
            return null;
        }
    }
    /**
     * 结算刷卡账户资金(实扣冻结口径,与 VIN 链路同构):
     * 1) 分配模式:解锁卡片锁定额并按实际消费扣减(允许扣成负数),差额退回卡账户;
     * 2) 共享模式:解锁企业账户锁定额并按实际消费扣减,差额退回企业账户;