| | |
| | | package com.ruoyi.order.service.impl; |
| | | |
| | | import com.alibaba.fastjson2.JSON; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.account.api.feignClient.AppCouponClient; |
| | | import com.ruoyi.account.api.feignClient.AppUserCarClient; |
| | | import com.ruoyi.account.api.feignClient.AppUserClient; |
| | | import com.ruoyi.account.api.feignClient.AppUserVipDetailClient; |
| | | import com.ruoyi.account.api.model.TAppCoupon; |
| | | import com.ruoyi.account.api.model.TAppUser; |
| | | import com.ruoyi.account.api.model.TAppUserCar; |
| | | import com.ruoyi.account.api.model.TAppUserVipDetail; |
| | |
| | | import com.ruoyi.common.core.web.page.PageInfo; |
| | | import com.ruoyi.common.redis.service.RedisService; |
| | | import com.ruoyi.common.security.service.TokenService; |
| | | import com.ruoyi.integration.api.feignClient.ChargingHandshakeClient; |
| | | import com.ruoyi.integration.api.feignClient.PlatformStartChargingReplyClient; |
| | | import com.ruoyi.integration.api.feignClient.SendMessageClient; |
| | | import com.ruoyi.integration.api.feignClient.UploadRealTimeMonitoringDataClient; |
| | | import com.ruoyi.integration.api.model.ChargingHandshake; |
| | | import com.ruoyi.integration.api.model.PlatformStartCharging; |
| | | import com.ruoyi.integration.api.model.PlatformStartChargingReply; |
| | | import com.ruoyi.integration.api.model.UploadRealTimeMonitoringData; |
| | | import com.ruoyi.integration.api.feignClient.*; |
| | | import com.ruoyi.integration.api.model.*; |
| | | import com.ruoyi.integration.api.vo.GetPlatformStopChargingReply; |
| | | import com.ruoyi.order.api.feignClient.ChargingOrderAccountingStrategyClient; |
| | | import com.ruoyi.order.api.model.*; |
| | | import com.ruoyi.order.api.query.ChargingOrderQuery; |
| | | import com.ruoyi.order.api.query.UploadRealTimeMonitoringDataQuery; |
| | |
| | | import com.ruoyi.payment.api.vo.*; |
| | | import io.seata.spring.annotation.GlobalTransactional; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.util.StringUtils; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.math.BigDecimal; |
| | | import java.math.MathContext; |
| | | import java.math.RoundingMode; |
| | | import java.text.SimpleDateFormat; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | |
| | | private AliPaymentClient aliPaymentClient; |
| | | |
| | | |
| | | |
| | | @Resource |
| | | private AppCouponClient appCouponClient; |
| | | |
| | | @Resource |
| | | private AppUserVipDetailClient appUserVipDetailClient; |
| | |
| | | |
| | | @Resource |
| | | private TChargingOrderRefundService chargingOrderRefundService; |
| | | |
| | | @Resource |
| | | private PlatformStopChargingReplyClient platformStopChargingReplyClient; |
| | | |
| | | //计数器 |
| | | private Map<String, Integer> counter_map = new HashMap<>(); |
| | |
| | | chargingOrder.setRechargePaymentStatus(2); |
| | | chargingOrder.setRechargeSerialNumber(transaction_id); |
| | | chargingOrder.setStatus(2); |
| | | this.updateById(chargingOrder); |
| | | |
| | | //添加安全检测数据到缓存中,每步安全检测完成后需要更新缓存数据 |
| | | PreChargeCheck preChargeCheck = new PreChargeCheck(); |
| | |
| | | } |
| | | } |
| | | electrovalence = electrovalence.add(discount); |
| | | chargingOrder.setChargeAmount(electrovalence); |
| | | this.updateById(chargingOrder); |
| | | |
| | | |
| | | TChargingPile chargingPile = chargingPileClient.getChargingPileById(chargingGun.getChargingPileId()).getData(); |
| | |
| | | chargingOrder.setEndMode(1); |
| | | this.updateById(chargingOrder); |
| | | //调用硬件停止充电,停止成功后开始计算费用退款 |
| | | // todo 待完善 |
| | | TChargingPile chargingPile = chargingPileClient.getChargingPileById(chargingOrder.getChargingPileId()).getData(); |
| | | TChargingGun chargingGun = chargingGunClient.getChargingGunById(chargingOrder.getChargingGunId()).getData(); |
| | | PlatformStopCharging platformStopCharging = new PlatformStopCharging(); |
| | | platformStopCharging.setCharging_pile_code(chargingPile.getCode()); |
| | | platformStopCharging.setCharging_gun_code(chargingGun.getCode()); |
| | | sendMessageClient.platformStopCharging(platformStopCharging); |
| | | //开始查询停机应答,成功后开始计费费用 |
| | | for (int i = 0; i < 60; i++) { |
| | | GetPlatformStopChargingReply query = new GetPlatformStopChargingReply(); |
| | | query.setCharging_gun_code(chargingGun.getCode()); |
| | | query.setCharging_pile_code(chargingPile.getCode()); |
| | | PlatformStopChargingReply reply = platformStopChargingReplyClient.getPlatformStopChargingReply(query).getData(); |
| | | if(null == reply){ |
| | | try { |
| | | Thread.sleep(1000); |
| | | } catch (InterruptedException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | continue; |
| | | } |
| | | |
| | | if(0 == reply.getStop_result()){ |
| | | String failure_cause = ""; |
| | | switch (reply.getFailure_cause()){ |
| | | case 0: |
| | | failure_cause = "无"; |
| | | break; |
| | | case 1: |
| | | failure_cause = "设备编号不匹配"; |
| | | break; |
| | | case 2: |
| | | failure_cause = "枪未处于充电状态"; |
| | | break; |
| | | case 3: |
| | | failure_cause = "其他"; |
| | | break; |
| | | } |
| | | throw new RuntimeException(failure_cause); |
| | | } |
| | | |
| | | //计算费用,处理退款 |
| | | endCharge(chargingOrder); |
| | | break; |
| | | } |
| | | return AjaxResult.success(); |
| | | } |
| | | |
| | | |
| | | |
| | | public void endCharge(){ |
| | | |
| | | |
| | | |
| | | /** |
| | | * 手动结束后的费用计算和退款逻辑 |
| | | */ |
| | | @GlobalTransactional(rollbackFor = Exception.class) |
| | | public void endCharge(TChargingOrder chargingOrder){ |
| | | //如果使用优惠券需要判断优惠券是否满足使用条件 |
| | | //根据实际的充电金额计算退款金额 退回费用=(原金额/总金额)*(总金额-实际充电金额) |
| | | //退款金额=优惠券金额+剩余充电金额 |
| | | List<TChargingOrderAccountingStrategy> list = chargingOrderAccountingStrategyService.list(new LambdaQueryWrapper<TChargingOrderAccountingStrategy>().eq(TChargingOrderAccountingStrategy::getChargingOrderId, chargingOrder.getId())); |
| | | BigDecimal total = BigDecimal.ZERO; |
| | | for (TChargingOrderAccountingStrategy chargingOrderAccountingStrategy : list) { |
| | | BigDecimal periodElectricPrice = chargingOrderAccountingStrategy.getPeriodElectricPrice(); |
| | | BigDecimal periodServicePrice = chargingOrderAccountingStrategy.getPeriodOriginalServicePrice(); |
| | | total = total.add(periodElectricPrice).add(periodServicePrice); |
| | | } |
| | | BigDecimal rechargeAmount = chargingOrder.getRechargeAmount(); |
| | | BigDecimal vipDiscountAmount = chargingOrder.getVipDiscountAmount(); |
| | | BigDecimal decimal = rechargeAmount.add(vipDiscountAmount); |
| | | //退款金额(已经计算了折扣优惠部分) |
| | | BigDecimal refundAmount = rechargeAmount.divide(decimal, new MathContext(4, RoundingMode.HALF_EVEN)).multiply(decimal.subtract(total)); |
| | | BigDecimal payAmount = BigDecimal.valueOf(total.doubleValue()); |
| | | BigDecimal orderAmount = BigDecimal.valueOf(total.doubleValue()); |
| | | if(null != chargingOrder.getVipDiscount()){ |
| | | orderAmount = orderAmount.divide(chargingOrder.getVipDiscount().divide(new BigDecimal(10))); |
| | | chargingOrder.setOrderAmount(total); |
| | | } |
| | | |
| | | if(null != chargingOrder.getAppCouponId()){ |
| | | //判断实际充电金额是否满足优惠券使用条件,如果不满足则不适用优惠券。 |
| | | TAppCoupon appCoupon = appCouponClient.getAppCouponById(chargingOrder.getAppCouponId()).getData(); |
| | | String couponJson = appCoupon.getCouponJson(); |
| | | TCoupon tCoupon = JSON.parseObject(couponJson, TCoupon.class); |
| | | Integer preferentialMode = tCoupon.getPreferentialMode(); |
| | | if(1 == preferentialMode){ |
| | | //满减 |
| | | if(total.compareTo(tCoupon.getMeetTheConditions()) >= 0){ |
| | | refundAmount = refundAmount.add(tCoupon.getDiscountAmount()); |
| | | chargingOrder.setCouponDiscountAmount(tCoupon.getDiscountAmount()); |
| | | payAmount = payAmount.subtract(tCoupon.getDiscountAmount()); |
| | | }else{ |
| | | chargingOrder.setAppCouponId(null); |
| | | chargingOrder.setCouponDiscountAmount(BigDecimal.ZERO); |
| | | appCouponClient.refund(chargingOrder.getAppCouponId().toString()); |
| | | } |
| | | } |
| | | if(2 == preferentialMode){ |
| | | //抵扣 |
| | | if(total.compareTo(tCoupon.getMeetTheConditions()) >= 0){ |
| | | //折扣金额 |
| | | BigDecimal divide = total.multiply(new BigDecimal(10).subtract(tCoupon.getDiscount())).divide(new BigDecimal(10)); |
| | | divide = divide.compareTo(tCoupon.getMaximumDiscountAmount()) > 0 ? tCoupon.getMaximumDiscountAmount() : divide; |
| | | refundAmount = refundAmount.add(divide); |
| | | chargingOrder.setCouponDiscountAmount(divide); |
| | | payAmount = payAmount.subtract(divide); |
| | | }else{ |
| | | chargingOrder.setAppCouponId(null); |
| | | chargingOrder.setCouponDiscountAmount(BigDecimal.ZERO); |
| | | appCouponClient.refund(chargingOrder.getAppCouponId().toString()); |
| | | } |
| | | } |
| | | } |
| | | |
| | | if(null != chargingOrder.getVipDiscount()){ |
| | | BigDecimal subtract = orderAmount.subtract(total); |
| | | chargingOrder.setVipDiscountAmount(subtract); |
| | | payAmount = payAmount.subtract(subtract); |
| | | } |
| | | chargingOrder.setPaymentAmount(payAmount); |
| | | this.updateById(chargingOrder); |
| | | |
| | | //开始构建退款费用 |
| | | if(refundAmount.compareTo(BigDecimal.ZERO) > 0){ |
| | | Integer rechargePaymentType = chargingOrder.getRechargePaymentType(); |
| | | //构建退款明细 |
| | | TChargingOrderRefund chargingOrderRefund = new TChargingOrderRefund(); |
| | | chargingOrderRefund.setChargingOrderId(chargingOrder.getId()); |
| | | SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS"); |
| | | chargingOrderRefund.setRefundCode("CDF" + sdf.format(new Date()) + (Math.random() * 1000)); |
| | | chargingOrderRefund.setRefundAmount(refundAmount); |
| | | chargingOrderRefund.setRefundStatus(1); |
| | | chargingOrderRefund.setPayType(rechargePaymentType); |
| | | chargingOrderRefund.setRefundStatus(1); |
| | | chargingOrderRefund.setCode(chargingOrder.getCode()); |
| | | chargingOrderRefund.setRefundTitle("充电完成退款"); |
| | | chargingOrderRefund.setRefundContent("充电完成退款"); |
| | | chargingOrderRefund.setRefundReason("充电完成退款"); |
| | | chargingOrderRefund.setRefundRemark("充电完成退款"); |
| | | chargingOrderRefund.setRefundTotalAmount(refundAmount); |
| | | chargingOrderRefund.setPayAmount(rechargeAmount); |
| | | if(1 == rechargePaymentType){ |
| | | WxPaymentRefundModel model = new WxPaymentRefundModel(); |
| | | model.setOut_trade_no(chargingOrder.getCode()); |
| | | model.setOut_refund_no(chargingOrderRefund.getRefundCode()); |
| | | model.setReason("充电完成退款"); |
| | | model.setNotify_url("http://127.0.0.1:9000/order/t-charging-order/chargingOrderStartupFailureWxRefund"); |
| | | WxPaymentRefundModel.RefundAmount amount = new WxPaymentRefundModel.RefundAmount(); |
| | | amount.setRefund(refundAmount.multiply(new BigDecimal(100)).intValue()); |
| | | amount.setTotal(rechargeAmount.multiply(new BigDecimal(100)).intValue()); |
| | | amount.setCurrency("CNY"); |
| | | model.setAmount(amount); |
| | | R<String> orderR = wxPaymentClient.refundOrderR(model); |
| | | if(200 == orderR.getCode()){ |
| | | chargingOrderRefundService.save(chargingOrderRefund); |
| | | } |
| | | } |
| | | if(2 == rechargePaymentType){ |
| | | RefundReq dto = new RefundReq(); |
| | | dto.setOutTradeNo(chargingOrder.getCode()); |
| | | dto.setOutRequestNo(chargingOrderRefund.getCode()); |
| | | dto.setRefundAmount(rechargeAmount.toString()); |
| | | dto.setRefundReason("充电完成退款"); |
| | | RefundResp resp = aliPaymentClient.refund(dto).getData(); |
| | | if(null != resp){ |
| | | SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-DDTHH:mm:ss+TIMEZONE"); |
| | | AjaxResult success = chargingOrderStartupFailureWxRefund(resp.getOutTradeNo(), resp.getTradeNo(), "SUCCESS", sdf1.format(new Date())); |
| | | if(success.isSuccess()){ |
| | | chargingOrderRefundService.save(chargingOrderRefund); |
| | | } |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | } |
| | | |
| | | |
| | |
| | | */ |
| | | @Override |
| | | public void chargeMonitoring(UploadRealTimeMonitoringDataQuery query) { |
| | | // todo 需完善 |
| | | if(com.ruoyi.common.core.utils.StringUtils.isNotEmpty(query.getCharging_gun_code())){ |
| | | //获取当前的计费策略 |
| | | TChargingOrder chargingOrder = this.getOne(new LambdaQueryWrapper<TChargingOrder>().eq(TChargingOrder::getCode, query.getCharging_gun_code())); |
| | | TChargingGun chargingGun = chargingGunClient.getChargingGunById(chargingOrder.getChargingGunId()).getData(); |
| | | TAccountingStrategyDetail strategyDetail = accountingStrategyDetailClient.getNowData(chargingGun.getAccountingStrategyId()).getData(); |
| | | TChargingOrderAccountingStrategy chargingOrderAccountingStrategy = chargingOrderAccountingStrategyService.getOne(new LambdaQueryWrapper<TChargingOrderAccountingStrategy>() |
| | | .eq(TChargingOrderAccountingStrategy::getChargingOrderId, chargingOrder.getId()).orderByDesc(TChargingOrderAccountingStrategy::getCreateTime).last(" limit 0, 1")); |
| | | SimpleDateFormat sdf = new SimpleDateFormat("HH:mm"); |
| | | if(null == chargingOrderAccountingStrategy){ |
| | | chargingOrderAccountingStrategy = new TChargingOrderAccountingStrategy(); |
| | | chargingOrderAccountingStrategy.setChargingOrderId(chargingOrder.getId()); |
| | | chargingOrderAccountingStrategy.setAccountingStrategyDetailId(strategyDetail.getId()); |
| | | chargingOrderAccountingStrategy.setType(strategyDetail.getType()); |
| | | chargingOrderAccountingStrategy.setStartTime(sdf.format(chargingOrder.getStartTime())); |
| | | chargingOrderAccountingStrategy.setEndTime(sdf.format(new Date())); |
| | | chargingOrderAccountingStrategy.setElectrovalence(strategyDetail.getElectrovalence()); |
| | | chargingOrderAccountingStrategy.setServiceCharge(strategyDetail.getServiceCharge()); |
| | | chargingOrderAccountingStrategy.setCostServiceCharge(strategyDetail.getCostServiceCharge()); |
| | | BigDecimal charging_degree = query.getCharging_degree(); |
| | | BigDecimal electrovalenc = strategyDetail.getElectrovalence().multiply(charging_degree); |
| | | BigDecimal originalServicePrice = strategyDetail.getServiceCharge().multiply(charging_degree); |
| | | BigDecimal serviceCharge = originalServicePrice; |
| | | //计算优惠金额 |
| | | if(null != chargingOrder.getVipDiscount()){ |
| | | serviceCharge = serviceCharge.multiply(chargingOrder.getVipDiscount().divide(new BigDecimal(10))); |
| | | } |
| | | chargingOrderAccountingStrategy.setChargingCapacity(charging_degree); |
| | | chargingOrderAccountingStrategy.setPeriodElectricPrice(electrovalenc); |
| | | chargingOrderAccountingStrategy.setPeriodServicePrice(serviceCharge); |
| | | chargingOrderAccountingStrategy.setPeriodOriginalServicePrice(originalServicePrice); |
| | | chargingOrderAccountingStrategy.setCreateTime(LocalDateTime.now()); |
| | | chargingOrderAccountingStrategyService.save(chargingOrderAccountingStrategy); |
| | | }else{ |
| | | if(chargingOrderAccountingStrategy.getAccountingStrategyDetailId().equals(strategyDetail.getId())){ |
| | | BigDecimal periodServicePrice = chargingOrderAccountingStrategy.getPeriodServicePrice(); |
| | | BigDecimal periodElectricPrice = chargingOrderAccountingStrategy.getPeriodElectricPrice(); |
| | | BigDecimal periodOriginalServicePrice = chargingOrderAccountingStrategy.getPeriodOriginalServicePrice(); |
| | | BigDecimal charging_degree = query.getCharging_degree(); |
| | | BigDecimal electrovalenc = strategyDetail.getElectrovalence().multiply(charging_degree); |
| | | BigDecimal originalServicePrice = strategyDetail.getServiceCharge().multiply(charging_degree); |
| | | BigDecimal serviceCharge = originalServicePrice; |
| | | //计算优惠金额 |
| | | if(null != chargingOrder.getVipDiscount()){ |
| | | serviceCharge = serviceCharge.multiply(chargingOrder.getVipDiscount().divide(new BigDecimal(10))); |
| | | } |
| | | periodServicePrice = periodServicePrice.add(serviceCharge); |
| | | periodOriginalServicePrice = periodOriginalServicePrice.add(originalServicePrice); |
| | | periodElectricPrice = periodElectricPrice.add(electrovalenc); |
| | | chargingOrderAccountingStrategy.setPeriodServicePrice(periodServicePrice); |
| | | chargingOrderAccountingStrategy.setPeriodOriginalServicePrice(periodOriginalServicePrice); |
| | | chargingOrderAccountingStrategy.setPeriodElectricPrice(periodElectricPrice); |
| | | chargingOrderAccountingStrategy.setEndTime(sdf.format(new Date())); |
| | | chargingOrderAccountingStrategyService.updateById(chargingOrderAccountingStrategy); |
| | | }else{ |
| | | TChargingOrderAccountingStrategy chargingOrderAccountingStrategy1 = new TChargingOrderAccountingStrategy(); |
| | | chargingOrderAccountingStrategy1.setChargingOrderId(chargingOrder.getId()); |
| | | chargingOrderAccountingStrategy1.setAccountingStrategyDetailId(strategyDetail.getId()); |
| | | chargingOrderAccountingStrategy1.setType(strategyDetail.getType()); |
| | | chargingOrderAccountingStrategy1.setStartTime(sdf.format(chargingOrderAccountingStrategy.getEndTime())); |
| | | chargingOrderAccountingStrategy1.setEndTime(sdf.format(new Date())); |
| | | chargingOrderAccountingStrategy1.setElectrovalence(strategyDetail.getElectrovalence()); |
| | | chargingOrderAccountingStrategy1.setServiceCharge(strategyDetail.getServiceCharge()); |
| | | chargingOrderAccountingStrategy1.setCostServiceCharge(strategyDetail.getCostServiceCharge()); |
| | | BigDecimal charging_degree = query.getCharging_degree(); |
| | | BigDecimal electrovalenc = strategyDetail.getElectrovalence().multiply(charging_degree); |
| | | BigDecimal originalServicePrice = strategyDetail.getServiceCharge().multiply(charging_degree); |
| | | BigDecimal serviceCharge = originalServicePrice; |
| | | //计算优惠金额 |
| | | if(null != chargingOrder.getVipDiscount()){ |
| | | serviceCharge = serviceCharge.multiply(chargingOrder.getVipDiscount().divide(new BigDecimal(10))); |
| | | } |
| | | chargingOrderAccountingStrategy1.setChargingCapacity(charging_degree); |
| | | chargingOrderAccountingStrategy1.setPeriodElectricPrice(electrovalenc); |
| | | chargingOrderAccountingStrategy1.setPeriodOriginalServicePrice(originalServicePrice); |
| | | chargingOrderAccountingStrategy1.setPeriodServicePrice(serviceCharge); |
| | | chargingOrderAccountingStrategy1.setCreateTime(LocalDateTime.now()); |
| | | chargingOrderAccountingStrategyService.save(chargingOrderAccountingStrategy1); |
| | | } |
| | | } |
| | | |
| | | List<TChargingOrderAccountingStrategy> list = chargingOrderAccountingStrategyService.list(new LambdaQueryWrapper<TChargingOrderAccountingStrategy>() |
| | | .eq(TChargingOrderAccountingStrategy::getChargingOrderId, chargingOrder.getId())); |
| | | BigDecimal t = BigDecimal.ZERO; |
| | | for (TChargingOrderAccountingStrategy coas : list) { |
| | | t = t.add(coas.getPeriodServicePrice()).add(coas.getPeriodElectricPrice()); |
| | | } |
| | | BigDecimal residualAmount = chargingOrder.getRechargeAmount().subtract(t).setScale(2, RoundingMode.HALF_EVEN); |
| | | chargingOrder.setResidualAmount(residualAmount); |
| | | BigDecimal divide = query.getOutput_current().multiply(query.getOutput_voltage()).divide(new BigDecimal(1000)); |
| | | chargingOrder.setChargingPower(divide); |
| | | this.updateById(chargingOrder); |
| | | } |
| | | } |
| | | } |