| | |
| | | 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; |
| | |
| | | |
| | | @Resource |
| | | private UploadRealTimeMonitoringDataService uploadRealTimeMonitoringDataService; |
| | | |
| | | @Resource |
| | | private TVinChargingOrderMapper vinChargingOrderMapper; |
| | | |
| | | @Resource |
| | | private TCECClient tcecClient; |
| | |
| | | * 解析白名单企业账户充电上下文(白名单用户选择余额支付时调用): |
| | | * 1) 校验归属公司存在且启用,未归属/停用直接拒绝; |
| | | * 2) 校验企业充电授权(站点范围、可用时段/电价阶段)并计算授权截止时间,未配置授权按放行处理(对齐 VIN 口径); |
| | | * 3) 下发额度 = min(用户输入充值金额, 账户可用额度, 企业设定的充值金额): |
| | | * 3) 下发额度: |
| | | * - 账户可用额度:共享模式=公司可用余额,分配模式=白名单账户余额; |
| | | * - 企业设定充值金额=授权配置下发金额,未配置默认 200 元; |
| | | * - 用户输入金额为空或非正数时按 min(企业设定充值金额, 账户可用额度) 下发。 |
| | | * - 共享模式=min(用户输入充值金额, 账户可用额度, 企业设定充值金额),企业设定充值金额=授权配置下发金额,未配置默认 200 元; |
| | | * - 分配模式=min(用户输入充值金额, 白名单账户余额),用户输入为空或非正数时直接下发白名单账户余额(不再受企业设定充值金额限制)。 |
| | | * |
| | | * @param whitelist 白名单命中结果(含归属公司与账户余额快照) |
| | | * @param userInputAmount 用户输入的充值金额 |
| | |
| | | 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); |
| | | } |
| | | |
| | |
| | | .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()); |
| | |
| | | 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()); |
| | |
| | | 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 |
| | |
| | | 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("权限不足"); |