| | |
| | | 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; |
| | |
| | | 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; |
| | |
| | | |
| | | @Resource |
| | | private RedissonClient redissonClient; |
| | | |
| | | @Resource |
| | | private ChargeAccountSupport chargeAccountSupport; |
| | | |
| | | |
| | | |
| | |
| | | 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); |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | //企业账户流程:白名单企业账户订单按企业优惠结算(方式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) { |
| | |
| | | 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)); |
| | |
| | | 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); |
| | |
| | | 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){ |
| | |
| | | } |
| | | 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); |
| | | //推送三方平台 |