From 202bda62a92e2885a230f48e85bdb212a1bcc04f Mon Sep 17 00:00:00 2001 From: "autumn.g@foxmail.com" Date: Thu, 25 May 2023 14:31:50 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=88=B7=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../impl/OrderBasicInfoServiceImpl.java | 3188 +++++++++-------- 1 file changed, 1598 insertions(+), 1590 deletions(-) diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java index dc2128f45..a1e351370 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/service/impl/OrderBasicInfoServiceImpl.java @@ -67,1636 +67,1644 @@ import java.util.stream.Collectors; @Service public class OrderBasicInfoServiceImpl implements IOrderBasicInfoService { - private Logger logger = LoggerFactory.getLogger(this.getClass()); + private Logger logger = LoggerFactory.getLogger(this.getClass()); - @Autowired - private OrderBasicInfoMapper orderBasicInfoMapper; + @Autowired + private OrderBasicInfoMapper orderBasicInfoMapper; - @Autowired - private TransactionService transactionService; + @Autowired + private TransactionService transactionService; - @Autowired - private RedisCache redisCache; + @Autowired + private RedisCache redisCache; - @Autowired - private IOrderPayRecordService orderPayRecordService; + @Autowired + private IOrderPayRecordService orderPayRecordService; - @Autowired - private IMemberBasicInfoService memberBasicInfoService; + @Autowired + private IMemberBasicInfoService memberBasicInfoService; - @Autowired - private WxpayCallbackRecordService wxpayCallbackRecordService; + @Autowired + private WxpayCallbackRecordService wxpayCallbackRecordService; - @Autowired - private WechatPayService wechatPayService; + @Autowired + private WechatPayService wechatPayService; - @Autowired - private IOrderAbnormalRecordService orderAbnormalRecordService; + @Autowired + private IOrderAbnormalRecordService orderAbnormalRecordService; - @Autowired - private TransactionService pileTransactionService; + @Autowired + private TransactionService pileTransactionService; - @Autowired - private WxAppletRemoteService wxAppletRemoteService; + @Autowired + private WxAppletRemoteService wxAppletRemoteService; - @Autowired - private IPileBasicInfoService pileBasicInfoService; + @Autowired + private IPileBasicInfoService pileBasicInfoService; - @Autowired - private IPileConnectorInfoService pileConnectorInfoService; + @Autowired + private IPileConnectorInfoService pileConnectorInfoService; - @Autowired - private WxpayRefundCallbackService wxpayRefundCallbackService; + @Autowired + private WxpayRefundCallbackService wxpayRefundCallbackService; - @Autowired - private IPileBillingTemplateService pileBillingTemplateService; + @Autowired + private IPileBillingTemplateService pileBillingTemplateService; - @Autowired - private IPileAuthCardService pileAuthCardService; + @Autowired + private IPileAuthCardService pileAuthCardService; - @Autowired - private OrderMonitorDataService orderMonitorDataService; + @Autowired + private OrderMonitorDataService orderMonitorDataService; - @Autowired - private IPileStationInfoService pileStationInfoService; + @Autowired + private IPileStationInfoService pileStationInfoService; - @Autowired - private IPileMerchantInfoService pileMerchantInfoService; + @Autowired + private IPileMerchantInfoService pileMerchantInfoService; - /** - * 条件查询订单基本信息 - * - * @param info - * @return - */ - @Override - public OrderBasicInfo getOrderBasicInfo(OrderBasicInfo info) { - return orderBasicInfoMapper.getOrderBasicInfo(info); - } + /** + * 条件查询订单基本信息 + * + * @param info + * @return + */ + @Override + public OrderBasicInfo getOrderBasicInfo(OrderBasicInfo info) { + return orderBasicInfoMapper.getOrderBasicInfo(info); + } - /** - * 查询订单列表 - * - * @param dto 订单 - * @return 订单 - */ - @Override - // @DataScope(deptAlias = "t3") - public List selectOrderBasicInfoList(QueryOrderDTO dto) { - // 权限过滤 - AuthorizedDeptVO authorizedMap = SecurityUtils.getAuthorizedMap(); - if (authorizedMap == null) { - // 为空表示没有权限,返回空数组 - return Lists.newArrayList(); - } - dto.setStationDeptIds(authorizedMap.getStationDeptIds()); - dto.setMerchantDeptIds(authorizedMap.getMerchantDeptIds()); + /** + * 查询订单列表 + * + * @param dto 订单 + * @return 订单 + */ + @Override + // @DataScope(deptAlias = "t3") + public List selectOrderBasicInfoList(QueryOrderDTO dto) { + // 权限过滤 + AuthorizedDeptVO authorizedMap = SecurityUtils.getAuthorizedMap(); + if (authorizedMap == null) { + // 为空表示没有权限,返回空数组 + return Lists.newArrayList(); + } + dto.setStationDeptIds(authorizedMap.getStationDeptIds()); + dto.setMerchantDeptIds(authorizedMap.getMerchantDeptIds()); - List orderListVOS = orderBasicInfoMapper.selectOrderBasicInfoList(dto); - if (CollectionUtils.isNotEmpty(orderListVOS)) { - for (OrderListVO orderListVO : orderListVOS) { - // 如果是微信支付,通过订单号查询微信支付单号 - if (StringUtils.equals(OrderPayModeEnum.PAYMENT_OF_WECHATPAY.getValue(), orderListVO.getPayMode())) { - WxpayCallbackRecord wxpayCallbackRecord = wxpayCallbackRecordService.selectByOrderCode(orderListVO.getOrderCode()); - orderListVO.setOutTradeNo(wxpayCallbackRecord.getOutTradeNo()); - } - orderListVO.setPileConnectorCode(orderListVO.getPileSn() + orderListVO.getConnectorCode()); - orderListVO.setOrderStatusDescribe(transformOrderStatusDescribe(orderListVO.getOrderStatus(), orderListVO.getPayStatus())); - } - } - return orderListVOS; - } + List orderListVOS = orderBasicInfoMapper.selectOrderBasicInfoList(dto); + if (CollectionUtils.isNotEmpty(orderListVOS)) { + for (OrderListVO orderListVO : orderListVOS) { + // 如果是微信支付,通过订单号查询微信支付单号 + if (StringUtils.equals(OrderPayModeEnum.PAYMENT_OF_WECHATPAY.getValue(), orderListVO.getPayMode())) { + WxpayCallbackRecord wxpayCallbackRecord = wxpayCallbackRecordService.selectByOrderCode(orderListVO.getOrderCode()); + orderListVO.setOutTradeNo(wxpayCallbackRecord.getOutTradeNo()); + } + orderListVO.setPileConnectorCode(orderListVO.getPileSn() + orderListVO.getConnectorCode()); + orderListVO.setOrderStatusDescribe(transformOrderStatusDescribe(orderListVO.getOrderStatus(), orderListVO.getPayStatus())); + } + } + return orderListVOS; + } - private void tempUpdateVirtualAmount(List orderListVOS) { - for (OrderListVO orderListVO : orderListVOS) { - if (orderListVO.getVirtualAmount() != null) { - continue; - } - // 订单总消费金额 - BigDecimal orderAmount = new BigDecimal(orderListVO.getOrderAmount()); + private void tempUpdateVirtualAmount(List orderListVOS) { + for (OrderListVO orderListVO : orderListVOS) { + if (orderListVO.getVirtualAmount() != null) { + // continue; + } + // 订单总消费金额 + BigDecimal orderAmount = new BigDecimal(orderListVO.getOrderAmount()); - // 使用虚拟金额消费 金额 - BigDecimal virtualAmount = BigDecimal.ZERO; - // 结算金额 - BigDecimal settleAmount = BigDecimal.ZERO; + // 使用虚拟金额消费 金额 + BigDecimal virtualAmount = BigDecimal.ZERO; + // 结算金额 + BigDecimal settleAmount = BigDecimal.ZERO; - if (StringUtils.equals(orderListVO.getPayMode(), OrderPayModeEnum.PAYMENT_OF_BALANCE.getValue())) { - /* - 余额支付 查询支付记录,如全部用本金支付,则虚拟金额为0,结算金额为订单消费金额, - 如果使用了赠送金额,虚拟金额为赠送金额支付部分,结算金额=订单消费金额-虚拟金额消费部分 - */ - // 查询支付记录 - List orderPayRecordList = orderPayRecordService.getOrderPayRecordList(orderListVO.getOrderCode()); - for (OrderPayRecord orderPayRecord : orderPayRecordList) { - if (StringUtils.equals(orderPayRecord.getPayMode(), OrderPayRecordEnum.GIFT_BALANCE_PAYMENT.getValue())) { - BigDecimal bigDecimal = orderPayRecord.getRefundAmount() == null ? BigDecimal.ZERO : orderPayRecord.getRefundAmount(); - virtualAmount = orderPayRecord.getPayAmount().subtract(bigDecimal); - settleAmount = orderAmount.subtract(virtualAmount); - } else { - settleAmount = orderAmount; - } - } - } else { - /* - 微信支付 虚拟金额为0 结算金额等于订单消费金额 - */ - settleAmount = orderAmount; - } + if (orderAmount.compareTo(BigDecimal.ZERO) > 0) { + if (StringUtils.equals(orderListVO.getPayMode(), OrderPayModeEnum.PAYMENT_OF_BALANCE.getValue())) { + /* + 余额支付 查询支付记录,如全部用本金支付,则虚拟金额为0,结算金额为订单消费金额, + 如果使用了赠送金额,虚拟金额为赠送金额支付部分,结算金额=订单消费金额-虚拟金额消费部分 + */ + // 查询支付记录 + List orderPayRecordList = orderPayRecordService.getOrderPayRecordList(orderListVO.getOrderCode()); + for (OrderPayRecord orderPayRecord : orderPayRecordList) { + if (StringUtils.equals(orderPayRecord.getPayMode(), OrderPayRecordEnum.GIFT_BALANCE_PAYMENT.getValue())) { + if (orderPayRecord.getRefundAmount() == null) { + // 需要退款的金额 = 支付金额 - 订单金额 + BigDecimal refundAmount = orderPayRecord.getPayAmount().subtract(orderAmount); + // 赠送金额消费部分 = 支付金额 - 需要退款金额 + virtualAmount = orderPayRecord.getPayAmount().subtract(refundAmount); + } + // 结算金额 = 订单金额 - 赠送金额消费部分 + settleAmount = orderAmount.subtract(virtualAmount); + } else { + settleAmount = orderAmount; + } + } + } else { + /* + 微信支付 虚拟金额为0 结算金额等于订单消费金额 + */ + settleAmount = orderAmount; + } + } - OrderBasicInfo build = OrderBasicInfo.builder() - .id(Long.parseLong(orderListVO.getId())) - .orderCode(orderListVO.getOrderCode()) - .virtualAmount(virtualAmount) - .settleAmount(settleAmount) - .build(); - updateOrderBasicInfo(build); - } - } + OrderBasicInfo build = OrderBasicInfo.builder() + .id(Long.parseLong(orderListVO.getId())) + .orderCode(orderListVO.getOrderCode()) + .virtualAmount(virtualAmount) + .settleAmount(settleAmount) + .build(); + updateOrderBasicInfo(build); + } + } - /** - * 通过订单状态和支付状态 转换订单状态描述 - * - * @param orderStatus - * @param payStatus - * @return - */ - @Override - public String transformOrderStatusDescribe(String orderStatus, String payStatus) { - // 订单状态描述 - // String orderStatus = orderListVO.getOrderStatus(); // 订单状态 - // String payStatus = orderListVO.getPayStatus(); // 支付状态 - String orderStatusDescribe; - if (StringUtils.equals(orderStatus, OrderStatusEnum.NOT_START.getValue())) { - // 未启动还有两种情况 待支付 / 支付成功 - if (StringUtils.equals(payStatus, OrderPayStatusEnum.paid.getValue())) { - // 支付成功,未启动 - orderStatusDescribe = OrderPayStatusEnum.paid.getLabel() + ", " + OrderStatusEnum.getOrderStatus(orderStatus); - } else { - // 待支付 - orderStatusDescribe = OrderPayStatusEnum.unpaid.getLabel(); - } - } else { - orderStatusDescribe = OrderStatusEnum.getOrderStatus(orderStatus); - } - return orderStatusDescribe; - } + /** + * 通过订单状态和支付状态 转换订单状态描述 + * + * @param orderStatus + * @param payStatus + * @return + */ + @Override + public String transformOrderStatusDescribe(String orderStatus, String payStatus) { + // 订单状态描述 + // String orderStatus = orderListVO.getOrderStatus(); // 订单状态 + // String payStatus = orderListVO.getPayStatus(); // 支付状态 + String orderStatusDescribe; + if (StringUtils.equals(orderStatus, OrderStatusEnum.NOT_START.getValue())) { + // 未启动还有两种情况 待支付 / 支付成功 + if (StringUtils.equals(payStatus, OrderPayStatusEnum.paid.getValue())) { + // 支付成功,未启动 + orderStatusDescribe = OrderPayStatusEnum.paid.getLabel() + ", " + OrderStatusEnum.getOrderStatus(orderStatus); + } else { + // 待支付 + orderStatusDescribe = OrderPayStatusEnum.unpaid.getLabel(); + } + } else { + orderStatusDescribe = OrderStatusEnum.getOrderStatus(orderStatus); + } + return orderStatusDescribe; + } - /** - * 查询时间段内订单总金额和总用电量 - * - * @param dto - * @return - */ - @Override - // @DataScope(deptAlias = "t3") - public OrderTotalDataVO getOrderTotalData(QueryOrderDTO dto) { - OrderTotalDataVO vo = new OrderTotalDataVO(); - dto.setOrderStatus(OrderStatusEnum.ORDER_COMPLETE.getValue()); - List list = selectOrderBasicInfoList(dto); - BigDecimal sumOrderAmount = BigDecimal.ZERO; - BigDecimal sumUsedElectricity = BigDecimal.ZERO; - vo.setDateDescription(dto.getStartTime() + " - " + dto.getEndTime()); - if (CollectionUtils.isNotEmpty(list)) { - for (OrderListVO orderListVO : list) { - BigDecimal orderAmount = StringUtils.isBlank(orderListVO.getOrderAmount()) - ? BigDecimal.ZERO - : new BigDecimal(orderListVO.getOrderAmount()); - sumOrderAmount = sumOrderAmount.add(orderAmount); + /** + * 查询时间段内订单总金额和总用电量 + * + * @param dto + * @return + */ + @Override + // @DataScope(deptAlias = "t3") + public OrderTotalDataVO getOrderTotalData(QueryOrderDTO dto) { + OrderTotalDataVO vo = new OrderTotalDataVO(); + dto.setOrderStatus(OrderStatusEnum.ORDER_COMPLETE.getValue()); + List list = selectOrderBasicInfoList(dto); + BigDecimal sumOrderAmount = BigDecimal.ZERO; + BigDecimal sumUsedElectricity = BigDecimal.ZERO; + vo.setDateDescription(dto.getStartTime() + " - " + dto.getEndTime()); + if (CollectionUtils.isNotEmpty(list)) { + for (OrderListVO orderListVO : list) { + BigDecimal orderAmount = StringUtils.isBlank(orderListVO.getOrderAmount()) + ? BigDecimal.ZERO + : new BigDecimal(orderListVO.getOrderAmount()); + sumOrderAmount = sumOrderAmount.add(orderAmount); - BigDecimal chargingDegree = StringUtils.isBlank(orderListVO.getChargingDegree()) - ? BigDecimal.ZERO - : new BigDecimal(orderListVO.getChargingDegree()); - sumUsedElectricity = sumUsedElectricity.add(chargingDegree); - } - } - vo.setSumOrderAmount(sumOrderAmount); - vo.setSumUsedElectricity(sumUsedElectricity); - return vo; - } + BigDecimal chargingDegree = StringUtils.isBlank(orderListVO.getChargingDegree()) + ? BigDecimal.ZERO + : new BigDecimal(orderListVO.getChargingDegree()); + sumUsedElectricity = sumUsedElectricity.add(chargingDegree); + } + } + vo.setSumOrderAmount(sumOrderAmount); + vo.setSumUsedElectricity(sumUsedElectricity); + return vo; + } - /** - * 通过订单号查询订单信息(小程序发送消息用) - * - * @param orderCode - * @return - */ - @Override - public SendMessageVO selectOrderInfoByOrderCode(String orderCode) { - return orderBasicInfoMapper.selectOrderInfoByOrderCode(orderCode); - } + /** + * 通过订单号查询订单信息(小程序发送消息用) + * + * @param orderCode + * @return + */ + @Override + public SendMessageVO selectOrderInfoByOrderCode(String orderCode) { + return orderBasicInfoMapper.selectOrderInfoByOrderCode(orderCode); + } - /** - * 充电桩启动失败 - * - * @param transactionCode 交易流水号 - * @param failedReasonMsg 失败原因 - */ - @Override - public void chargingPileFailedToStart(String transactionCode, String failedReasonMsg) { - logger.info("启动失败退款 transactionCode:{}, 失败原因:{}", transactionCode, failedReasonMsg); - // OrderBasicInfo orderInfo = getOrderInfoByOrderCode(orderCode); - OrderBasicInfo orderInfo = getOrderInfoByTransactionCode(transactionCode); - if (orderInfo == null) { - return; - } - // 启动失败原因 - orderInfo.setReason(failedReasonMsg); - // 订单退款(结算订单) - TransactionRecordsData data = TransactionRecordsData.builder() - .transactionCode(orderInfo.getTransactionCode()) - .consumptionAmount(String.valueOf(orderInfo.getOrderAmount())) - .stopReasonMsg(failedReasonMsg) - .totalElectricity(Constants.ZERO) - .sharpUsedElectricity(Constants.ZERO) - .peakUsedElectricity(Constants.ZERO) - .flatUsedElectricity(Constants.ZERO) - .valleyUsedElectricity(Constants.ZERO) - .build(); - settleOrder(data, orderInfo); - } + /** + * 充电桩启动失败 + * + * @param transactionCode 交易流水号 + * @param failedReasonMsg 失败原因 + */ + @Override + public void chargingPileFailedToStart(String transactionCode, String failedReasonMsg) { + logger.info("启动失败退款 transactionCode:{}, 失败原因:{}", transactionCode, failedReasonMsg); + // OrderBasicInfo orderInfo = getOrderInfoByOrderCode(orderCode); + OrderBasicInfo orderInfo = getOrderInfoByTransactionCode(transactionCode); + if (orderInfo == null) { + return; + } + // 启动失败原因 + orderInfo.setReason(failedReasonMsg); + // 订单退款(结算订单) + TransactionRecordsData data = TransactionRecordsData.builder() + .transactionCode(orderInfo.getTransactionCode()) + .consumptionAmount(String.valueOf(orderInfo.getOrderAmount())) + .stopReasonMsg(failedReasonMsg) + .totalElectricity(Constants.ZERO) + .sharpUsedElectricity(Constants.ZERO) + .peakUsedElectricity(Constants.ZERO) + .flatUsedElectricity(Constants.ZERO) + .valleyUsedElectricity(Constants.ZERO) + .build(); + settleOrder(data, orderInfo); + } - /** - * 充电桩启动成功 - * - * @param transactionCode - */ - @Override - public void chargingPileStartedSuccessfully(String transactionCode) { - // OrderBasicInfo orderInfo = getOrderInfoByOrderCode(orderCode); - OrderBasicInfo orderInfo = getOrderInfoByTransactionCode(transactionCode); - if (orderInfo == null) { - return; - } - // 启动成功,订单状态改为充电中 - orderInfo.setOrderStatus(OrderStatusEnum.IN_THE_CHARGING.getValue()); - if (orderInfo.getChargeStartTime() == null) { - orderInfo.setChargeStartTime(new Date()); - } - updateOrderBasicInfo(orderInfo); - } + /** + * 充电桩启动成功 + * + * @param transactionCode + */ + @Override + public void chargingPileStartedSuccessfully(String transactionCode) { + // OrderBasicInfo orderInfo = getOrderInfoByOrderCode(orderCode); + OrderBasicInfo orderInfo = getOrderInfoByTransactionCode(transactionCode); + if (orderInfo == null) { + return; + } + // 启动成功,订单状态改为充电中 + orderInfo.setOrderStatus(OrderStatusEnum.IN_THE_CHARGING.getValue()); + if (orderInfo.getChargeStartTime() == null) { + orderInfo.setChargeStartTime(new Date()); + } + updateOrderBasicInfo(orderInfo); + } - @Override - public void closeStartFailedOrder(String startTime, String endTime) { - List orderList = orderBasicInfoMapper.selectOrderListByTimeRangeAndStatus(startTime, endTime, OrderStatusEnum.NOT_START.getValue(), OrderPayStatusEnum.paid.getValue()); - List orderCodeList = orderList.stream().map(OrderBasicInfo::getOrderCode).collect(Collectors.toList()); - logger.info("{}-{}期间,共{}条,支付成功未启动订单,订单号:{}", startTime, endTime, orderList.size(), orderCodeList); - if (CollectionUtils.isEmpty(orderList)) { - return; - } - long currentTimeMillis = System.currentTimeMillis(); - // 判断支付成功时间距当前时间是否大于15分钟 - for (OrderBasicInfo orderBasicInfo : orderList) { - // 立即启动的订单使用支付时间判断,预约充电的订单使用预约时间判断 - long time; - String startType = orderBasicInfo.getStartType(); - if (StringUtils.equals(StartTypeEnum.NOW.getValue(), startType)) { - Date payTime = orderBasicInfo.getPayTime(); - time = payTime == null ? 0L : payTime.getTime(); - } else { - Date appointmentTime = orderBasicInfo.getAppointmentTime(); - time = appointmentTime == null ? 0L : appointmentTime.getTime(); - } + @Override + public void closeStartFailedOrder(String startTime, String endTime) { + List orderList = orderBasicInfoMapper.selectOrderListByTimeRangeAndStatus(startTime, endTime, OrderStatusEnum.NOT_START.getValue(), OrderPayStatusEnum.paid.getValue()); + List orderCodeList = orderList.stream().map(OrderBasicInfo::getOrderCode).collect(Collectors.toList()); + logger.info("{}-{}期间,共{}条,支付成功未启动订单,订单号:{}", startTime, endTime, orderList.size(), orderCodeList); + if (CollectionUtils.isEmpty(orderList)) { + return; + } + long currentTimeMillis = System.currentTimeMillis(); + // 判断支付成功时间距当前时间是否大于15分钟 + for (OrderBasicInfo orderBasicInfo : orderList) { + // 立即启动的订单使用支付时间判断,预约充电的订单使用预约时间判断 + long time; + String startType = orderBasicInfo.getStartType(); + if (StringUtils.equals(StartTypeEnum.NOW.getValue(), startType)) { + Date payTime = orderBasicInfo.getPayTime(); + time = payTime == null ? 0L : payTime.getTime(); + } else { + Date appointmentTime = orderBasicInfo.getAppointmentTime(); + time = appointmentTime == null ? 0L : appointmentTime.getTime(); + } - if (currentTimeMillis - time < 1000 * 60 * 15) { - continue; - } - // 已经支付超过15分钟 判断充电桩的状态 - String pileConnectorCode = orderBasicInfo.getPileSn() + orderBasicInfo.getConnectorCode(); - PileConnectorInfoVO connector = pileConnectorInfoService.getPileConnectorInfoByConnectorCode(pileConnectorCode); - // 充电桩不在线,则不做处理。请联系管理员操作 - if (PileConnectorDataBaseStatusEnum.OFF_NETWORK.getValue().equals(String.valueOf(connector.getStatus()))) { - logger.info("订单号:{}已经支付超过15分钟,充电桩:{}未启动,但是该桩为离线状态,请联系管理员处理", orderBasicInfo.getOrderCode(), pileConnectorCode); - continue; - } - // 获取订单的实时检测数据,有实时数据说明充电了,没有实时数据说明桩确实没有充电 - List chargingRealTimeData = getChargingRealTimeData(orderBasicInfo.getTransactionCode()); - if (CollectionUtils.isEmpty(chargingRealTimeData)) { - // 充电桩在线,并且没有0x13实时数据,则执行结算退款操作 - chargingPileFailedToStart(orderBasicInfo.getTransactionCode(), "充电桩启动失败,执行退款处理"); - } - } - } + if (currentTimeMillis - time < 1000 * 60 * 15) { + continue; + } + // 已经支付超过15分钟 判断充电桩的状态 + String pileConnectorCode = orderBasicInfo.getPileSn() + orderBasicInfo.getConnectorCode(); + PileConnectorInfoVO connector = pileConnectorInfoService.getPileConnectorInfoByConnectorCode(pileConnectorCode); + // 充电桩不在线,则不做处理。请联系管理员操作 + if (PileConnectorDataBaseStatusEnum.OFF_NETWORK.getValue().equals(String.valueOf(connector.getStatus()))) { + logger.info("订单号:{}已经支付超过15分钟,充电桩:{}未启动,但是该桩为离线状态,请联系管理员处理", orderBasicInfo.getOrderCode(), pileConnectorCode); + continue; + } + // 获取订单的实时检测数据,有实时数据说明充电了,没有实时数据说明桩确实没有充电 + List chargingRealTimeData = getChargingRealTimeData(orderBasicInfo.getTransactionCode()); + if (CollectionUtils.isEmpty(chargingRealTimeData)) { + // 充电桩在线,并且没有0x13实时数据,则执行结算退款操作 + chargingPileFailedToStart(orderBasicInfo.getTransactionCode(), "充电桩启动失败,执行退款处理"); + } + } + } - /** - * 查询充电中的订单,没有数据权限校验,后管不要用 - * - * @param pileSn - * @return - */ - @Override - public List selectChargingOrder(String pileSn) { - QueryOrderDTO dto = QueryOrderDTO.builder() - .pileSn(pileSn) - .orderStatus(OrderStatusEnum.IN_THE_CHARGING.getValue()) - .build(); - return orderBasicInfoMapper.selectOrderBasicInfoList(dto); - } + /** + * 查询充电中的订单,没有数据权限校验,后管不要用 + * + * @param pileSn + * @return + */ + @Override + public List selectChargingOrder(String pileSn) { + QueryOrderDTO dto = QueryOrderDTO.builder() + .pileSn(pileSn) + .orderStatus(OrderStatusEnum.IN_THE_CHARGING.getValue()) + .build(); + return orderBasicInfoMapper.selectOrderBasicInfoList(dto); + } - /** - * 修改订单 - * - * @param orderBasicInfo 订单 - * @return 结果 - */ - @Transactional - @Override - public int updateOrderBasicInfo(OrderBasicInfo orderBasicInfo) { - // 清缓存 - this.cleanCacheByOrderCode(orderBasicInfo.getOrderCode(), orderBasicInfo.getTransactionCode()); - int i = orderBasicInfoMapper.updateOrderBasicInfo(orderBasicInfo); - CompletableFuture.runAsync(() -> this.cleanCacheByOrderCode(orderBasicInfo.getOrderCode(), orderBasicInfo.getTransactionCode())); - return i; - } + /** + * 修改订单 + * + * @param orderBasicInfo 订单 + * @return 结果 + */ + @Transactional + @Override + public int updateOrderBasicInfo(OrderBasicInfo orderBasicInfo) { + // 清缓存 + this.cleanCacheByOrderCode(orderBasicInfo.getOrderCode(), orderBasicInfo.getTransactionCode()); + int i = orderBasicInfoMapper.updateOrderBasicInfo(orderBasicInfo); + CompletableFuture.runAsync(() -> this.cleanCacheByOrderCode(orderBasicInfo.getOrderCode(), orderBasicInfo.getTransactionCode())); + return i; + } - /** - * 修改订单详情 - * @param orderDetail - * @return - */ + /** + * 修改订单详情 + * + * @param orderDetail + * @return + */ @Override public int updateOrderDetail(OrderDetail orderDetail) { return orderBasicInfoMapper.updateOrderDetail(orderDetail); } @Override - public void cleanCacheByOrderCode(String orderCode, String transactionCode) { - logger.debug("清除订单缓存 orderCode:{}, transactionCode:{}", orderCode, transactionCode); - List keys = Lists.newArrayList(); - if (StringUtils.isNotBlank(orderCode)) { - keys.add(CacheConstants.GET_ORDER_INFO_BY_ORDER_CODE + orderCode); - } - if (StringUtils.isNotBlank(transactionCode)) { - keys.add(CacheConstants.GET_ORDER_INFO_BY_TRANSACTION_CODE + transactionCode); - } - if (CollectionUtils.isNotEmpty(keys)) { - redisCache.deleteObject(keys); - } - } - - /** - * 批量删除订单 - * - * @param ids 需要删除的订单主键 - * @return 结果 - */ - @Transactional - @Override - public int deleteOrderBasicInfoByIds(Long[] ids) { - orderBasicInfoMapper.deleteOrderDetailByOrderCodes(ids); - return orderBasicInfoMapper.deleteOrderBasicInfoByIds(ids); - } - - /** - * 通过订单号查询订单信息 - * - * @param orderCode 订单号 - * @return - */ - @Override - public OrderBasicInfo getOrderInfoByOrderCode(String orderCode) { - // 如果orderCode是00000000000000000000000000000000,直接返回null - if (StringUtils.equals(Constants.ILLEGAL_TRANSACTION_CODE, orderCode)) { - return null; - } - String redisKey = CacheConstants.GET_ORDER_INFO_BY_ORDER_CODE + orderCode; - OrderBasicInfo orderBasicInfo = redisCache.getCacheObject(redisKey); - if (orderBasicInfo == null) { - // 查数据库 - orderBasicInfo = orderBasicInfoMapper.getOrderInfoByOrderCode(orderCode); - // 放缓存 - if (orderBasicInfo != null) { - redisCache.setCacheObject(redisKey, orderBasicInfo, 5, TimeUnit.MINUTES); - } - } - logger.info("通过订单号:{}, 查询订单信息:{}", orderCode, JSON.toJSONString(orderBasicInfo)); - return orderBasicInfo; - } - - @Override - public OrderBasicInfo getOrderInfoByTransactionCode(String transactionCode) { - if (StringUtils.equals(Constants.ILLEGAL_TRANSACTION_CODE, transactionCode)) { - return null; - } - String redisKey = CacheConstants.GET_ORDER_INFO_BY_TRANSACTION_CODE + transactionCode; - OrderBasicInfo orderBasicInfo = redisCache.getCacheObject(redisKey); - if (orderBasicInfo == null) { - // 查数据库 - orderBasicInfo = orderBasicInfoMapper.getOrderInfoByTransactionCode(transactionCode); - // 放缓存 - if (orderBasicInfo != null) { - redisCache.setCacheObject(redisKey, orderBasicInfo, 5, TimeUnit.MINUTES); - } - } - logger.info("通过交易流水号:{}, 查询订单信息:{}", transactionCode, JSON.toJSONString(orderBasicInfo)); - return orderBasicInfo; - } - - /** - * 根据充电桩编号和枪口号查询正在充电中的订单 - * - * @param pileSn 桩编号 - * @param connectorCode 枪口号 - * @return - */ - @Override - public OrderBasicInfo queryChargingByPileSnAndConnectorCode(String pileSn, String connectorCode) { - return orderBasicInfoMapper.queryOrderBasicInfo(pileSn, connectorCode, OrderStatusEnum.IN_THE_CHARGING.getValue()); - } - - /** - * 根据枪口编号查询正在充电中的订单 - * - * @param pileConnectorCode - * @return - */ - @Override - public OrderBasicInfo queryChargingByPileConnectorCode(String pileConnectorCode) { - if (StringUtils.isBlank(pileConnectorCode)) { - return null; - } - String pileSn = pileConnectorCode.substring(0, pileConnectorCode.length() - 2); - String connectorCode = pileConnectorCode.substring(pileConnectorCode.length() - 2); - return queryChargingByPileSnAndConnectorCode(pileSn, connectorCode); - } - - /** - * 结算订单逻辑 - * - * @param data 交易记录数据 - * @param orderBasicInfo 订单主表信息,由调用方传过来 - */ - @Override - public void settleOrder(TransactionRecordsData data, OrderBasicInfo orderBasicInfo) { - logger.info("结算订单start data:{}, orderBasicInfo:{}", data.toString(), orderBasicInfo.toString()); - String orderCode = orderBasicInfo.getOrderCode(); - - // 判断订单状态 - if (StringUtils.equals(orderBasicInfo.getOrderStatus(), OrderStatusEnum.ORDER_COMPLETE.getValue())) { - logger.info("结算订单:{}, 是订单完成状态", orderCode); - return; - } - // 消费金额就是订单总金额 - BigDecimal orderAmount = new BigDecimal(data.getConsumptionAmount()); - - // 付款金额 - 实际消费金额,如果有剩余,需要走退款操作 当使用余额支付时payAmount = principalPay + giftPay - BigDecimal payAmount = orderBasicInfo.getPayAmount(); - - // 有时候充电桩到达金额停止充电会多出一点金额,比如实际需要充50元的电,充电桩传来的消费金额为50.01元,在后台记录的时候需要舍去 - if (orderAmount.compareTo(payAmount) > 0) { - logger.info("结算订单:【{}】充电桩传来的消费金额:【{}】大于付款金额:【{}】, 消费金额设置为付款金额相等数据", orderBasicInfo.getOrderCode(), orderAmount, payAmount); - orderAmount = payAmount; - } - - // 虚拟金额 指订单消费中使用赠送金额支付的部分 - BigDecimal virtualAmount = BigDecimal.ZERO; - - // 剩余需要退回的金额 residue - BigDecimal residue = payAmount.subtract(orderAmount); - if (residue.compareTo(BigDecimal.ZERO) > 0) { - // 查支付记录 - List payRecordList = orderPayRecordService.getOrderPayRecordList(orderBasicInfo.getOrderCode()); - // 更新订单支付记录 - List updatePayRecordList = Lists.newArrayList(); - // 根据支付方式不同,走不同渠道退款 - String payMode = orderBasicInfo.getPayMode(); - if (StringUtils.equals(payMode, OrderPayModeEnum.PAYMENT_OF_BALANCE.getValue())) { // 余额支付 - Map payRecordMap = payRecordList.stream() - .collect(Collectors.toMap(OrderPayRecord::getPayMode, Function.identity(), (k1, k2) -> k1)); - // 取出本金支付金额,赠送支付金额 - BigDecimal principalPay = null; - BigDecimal giftPay = null; - - OrderPayRecord principalPayRecord = payRecordMap.get("1"); - if (principalPayRecord != null) { - principalPay = principalPayRecord.getPayAmount(); - } - - OrderPayRecord giftPayRecord = payRecordMap.get("2"); - if (giftPayRecord != null) { - giftPay = giftPayRecord.getPayAmount(); - } - - Map returnAmountMap = calculateReturnAmount(principalPay, giftPay, orderAmount); - logger.info("结算订单:{}, 剩余金额退回余额, 订单消费金额:{}, 本金支付金额:{}, 赠送支付金额:{}, 退回金额map:{}", - orderCode, orderAmount, principalPay, giftPay, JSONObject.toJSONString(returnAmountMap)); - // 更新会员钱包 - BigDecimal returnPrincipal = returnAmountMap.get("returnPrincipal"); - if (returnPrincipal != null && principalPayRecord != null) { - principalPayRecord.setRefundAmount(returnPrincipal); - updatePayRecordList.add(principalPayRecord); - } - BigDecimal returnGift = returnAmountMap.get("returnGift"); - if (returnGift != null && giftPayRecord != null) { - giftPayRecord.setRefundAmount(returnGift); - updatePayRecordList.add(giftPayRecord); - // 支付的赠送金额-退回的赠送金额 = 实际使用赠送金额消费的部分 - virtualAmount = giftPay.subtract(returnGift); - } - UpdateMemberBalanceDTO updateMemberBalanceDTO = UpdateMemberBalanceDTO.builder() - .memberId(orderBasicInfo.getMemberId()) - .type(MemberWalletEnum.TYPE_IN.getValue()) // 进账 - .subType(MemberWalletEnum.SUBTYPE_ORDER_SETTLEMENT_REFUND.getValue()) // 订单结算退款 - .updatePrincipalBalance(returnPrincipal) - .updateGiftBalance(returnGift) - .relatedOrderCode(orderBasicInfo.getOrderCode()) - .build(); - memberBasicInfoService.updateMemberBalance(updateMemberBalanceDTO); - } else if (StringUtils.equals(payMode, OrderPayModeEnum.PAYMENT_OF_WECHATPAY.getValue())) { // 微信支付 - // 微信退款逻辑 - WeChatRefundDTO weChatRefundDTO = new WeChatRefundDTO(); - weChatRefundDTO.setOrderCode(orderBasicInfo.getOrderCode()); - weChatRefundDTO.setRefundType("1"); - weChatRefundDTO.setRefundAmount(residue); - this.weChatRefund(weChatRefundDTO); - // 订单支付记录 - OrderPayRecord orderPayRecord = payRecordList.get(0); - orderPayRecord.setRefundAmount(residue); - updatePayRecordList.add(orderPayRecord); - } else if (StringUtils.equals(payMode, OrderPayModeEnum.PAYMENT_OF_ALIPAY.getValue())) { // 支付宝支付 - // 支付宝退款逻辑 - } else { - // 白名单支付 - logger.info("订单:{}使用白名单支付,不进行退款处理", orderBasicInfo.getOrderCode()); - } - - // 更新order_pay_record - if (CollectionUtils.isNotEmpty(updatePayRecordList)) { - for (OrderPayRecord orderPayRecord : updatePayRecordList) { - orderPayRecordService.updateByPrimaryKeySelective(orderPayRecord); - } - } - } - - // 修改订单数据 - // 查询订单详情 - OrderDetail orderDetail = getOrderDetailByOrderCode(orderBasicInfo.getOrderCode()); - - // 把交易记录中的用电量,金额等信息 更新到orderBasicInfo和orderDetail - orderBasicInfo.setOrderAmount(orderAmount); // 订单总金额 - orderBasicInfo.setVirtualAmount(virtualAmount); // 虚拟金额 - orderBasicInfo.setSettleAmount(orderAmount.subtract(virtualAmount)); // 结算金额 - orderBasicInfo.setOrderStatus(OrderStatusEnum.ORDER_COMPLETE.getValue()); - orderBasicInfo.setReason(data.getStopReasonMsg()); // 充电停止原因 - orderBasicInfo.setSettlementTime(DateUtils.getNowDate()); // 结算时间 - orderBasicInfo.setRefundAmount(residue); // 结算退款金额 - - // 更新订单详情 - try { - // 总电费金额 - BigDecimal totalElectricityAmount = BigDecimal.ZERO; - - // 尖时段用电量 - String sharpUsedElectricity = data.getSharpUsedElectricity(); - if (sharpUsedElectricity != null) { - orderDetail.setSharpUsedElectricity(new BigDecimal(sharpUsedElectricity)); - if (data.getSharpPrice() != null) { - orderDetail.setSharpPrice(new BigDecimal(data.getSharpPrice())); - } - if (data.getSharpAmount() != null) { - orderDetail.setSharpAmount(new BigDecimal(data.getSharpAmount())); - } - // 计算该时段电费 - BigDecimal multiply = orderDetail.getSharpElectricityPrice().multiply(new BigDecimal(sharpUsedElectricity)).setScale(2, BigDecimal.ROUND_DOWN); - totalElectricityAmount = totalElectricityAmount.add(multiply); - } - - // 峰时段用电量 - String peakUsedElectricity = data.getPeakUsedElectricity(); - if (peakUsedElectricity != null) { - orderDetail.setPeakUsedElectricity(new BigDecimal(peakUsedElectricity)); - if (data.getPeakPrice() != null) { - orderDetail.setPeakPrice(new BigDecimal(data.getPeakPrice())); - } - if (data.getPeakAmount() != null) { - orderDetail.setPeakAmount(new BigDecimal(data.getPeakAmount())); - } - // 计算该时段电费 - BigDecimal multiply = orderDetail.getPeakElectricityPrice().multiply(new BigDecimal(peakUsedElectricity)).setScale(2, BigDecimal.ROUND_DOWN); - totalElectricityAmount = totalElectricityAmount.add(multiply); - } - - // 平时段用电量 - String flatUsedElectricity = data.getFlatUsedElectricity(); - if (flatUsedElectricity != null) { - orderDetail.setFlatUsedElectricity(new BigDecimal(flatUsedElectricity)); - if (data.getFlatPrice() != null) { - orderDetail.setFlatPrice(new BigDecimal(data.getFlatPrice())); - } - if (data.getFlatAmount() != null) { - orderDetail.setFlatAmount(new BigDecimal(data.getFlatAmount())); - } - // 计算该时段电费 - BigDecimal multiply = orderDetail.getFlatElectricityPrice().multiply(new BigDecimal(flatUsedElectricity)).setScale(2, BigDecimal.ROUND_DOWN); - totalElectricityAmount = totalElectricityAmount.add(multiply); - } - - // 谷时段用电量 - String valleyUsedElectricity = data.getValleyUsedElectricity(); - if (valleyUsedElectricity != null) { - orderDetail.setValleyUsedElectricity(new BigDecimal(valleyUsedElectricity)); - if (data.getValleyPrice() != null) { - orderDetail.setValleyPrice(new BigDecimal(data.getValleyPrice())); - } - if (data.getValleyAmount() != null) { - orderDetail.setValleyAmount(new BigDecimal(data.getValleyAmount())); - } - // 计算该时段电费 - BigDecimal multiply = orderDetail.getValleyElectricityPrice().multiply(new BigDecimal(valleyUsedElectricity)).setScale(2, BigDecimal.ROUND_DOWN); - totalElectricityAmount = totalElectricityAmount.add(multiply); - } - - orderDetail.setTotalElectricityAmount(totalElectricityAmount); - orderDetail.setTotalServiceAmount(orderAmount.subtract(totalElectricityAmount)); - orderDetail.setTotalUsedElectricity(new BigDecimal(data.getTotalElectricity())); // 总用电量 - orderDetail.setTotalOrderAmount(orderAmount); // 订单总金额 - } catch (Exception e) { - logger.error("设置订单详情参数发生异常", e); - } - - OrderTransactionDTO dto = new OrderTransactionDTO(); - dto.setOrderBasicInfo(orderBasicInfo); - dto.setOrderDetail(orderDetail); - transactionService.doUpdateOrder(dto); - logger.info("结算订单 end OrderTransactionDTO:{}", JSONObject.toJSONString(dto)); - - try { - // uniApp 发送停止充电订阅消息 - WechatSendMsgDTO wechatSendMsgDTO = new WechatSendMsgDTO(); - wechatSendMsgDTO.setOrderCode(orderBasicInfo.getOrderCode()); - Map resultMap = wxAppletRemoteService.stopChargingSendMsg(wechatSendMsgDTO); - logger.info("小程序发送充电停止推送消息 result:{}", JSON.toJSONString(resultMap)); - } catch (Exception e) { - logger.error("小程序发送充电停止推送消息 error", e); - } - - try { - realTimeMonitorDataRedis2DB(orderBasicInfo.getTransactionCode(), orderBasicInfo.getOrderCode()); - } catch (Exception e) { - logger.error("redis中取出实时记录保存到表 发生异常", e); - } - - // TODO 推送停止充电结果 notification_stop_charge_result - - - } - - /** - * 从redis中取出实时记录保存到表中j - * 当订单完成的时候调用 - */ - @Override - public void realTimeMonitorDataRedis2DB(String transactionCode, String orderCode) { - if (StringUtils.isBlank(transactionCode) || StringUtils.isBlank(orderCode)) { - return; - } - // 校验有没有保存过 - OrderMonitorData orderMonitorData = orderMonitorDataService.selectByOrderCode(orderCode); - if (orderMonitorData != null) { - return; - } - List chargingRealTimeData = getChargingRealTimeData(transactionCode); - if (CollectionUtils.isEmpty(chargingRealTimeData)) { - return; - } - List list = Lists.newArrayList(); - for (RealTimeMonitorData data : chargingRealTimeData) { - RealTimeMonitorData build = RealTimeMonitorData.builder() - .outputCurrent(data.getOutputCurrent()) - .outputCurrent(data.getOutputCurrent()) // 电流 - .outputVoltage(data.getOutputVoltage()) // 电压 - .outputPower(data.getOutputPower()) // 功率 - .SOC(data.getSOC()) // soc - .dateTime(data.getDateTime()) // 时间 - .batteryMaxTemperature(data.getBatteryMaxTemperature()) - .chargingAmount(data.getChargingAmount()) - .chargingDegree(data.getChargingDegree()) - .sumChargingTime(data.getSumChargingTime()) - .timeRemaining(data.getTimeRemaining()) - .gunLineTemperature(data.getGunLineTemperature()) - .build(); - list.add(build); - } - - OrderMonitorData record = new OrderMonitorData(); - record.setOrderCode(orderCode); - record.setTransactionCode(transactionCode); - record.setMonitorData(JSONObject.toJSONString(list)); - int insert = orderMonitorDataService.insertSelective(record); - if (insert > 0) { - // 删除redis中缓存 - String pileConnectorCode = transactionCode.substring(0, 16); - String redisKey = CacheConstants.PILE_REAL_TIME_MONITOR_DATA + pileConnectorCode + "_" + transactionCode; - redisCache.deleteObject(redisKey); - } - - } - - @Override - public void updateElecAmount() { - // 查询 elecAmount为空的订单数据 - int pageNum = 1; - int pageSize = 500; - - int total = 0; - int batch = 1; - while (true) { - // 分页处理 - PageHelper.startPage(pageNum, pageSize); - List list = orderBasicInfoMapper.queryElecAmountNullList(); - PageInfo pageInfo = new PageInfo<>(list); - if (CollectionUtils.isEmpty(pageInfo.getList())) { - break; - } - - // 计算电量总金额 - List orderDetailList = calculateData(pageInfo.getList()); - - // 更新数据库 - int i = orderBasicInfoMapper.batchUpdateOrderDetail(orderDetailList); - total += i; - logger.info("updateElecAmount==第{}批次更新完成", batch); - batch += 1; - } - logger.info("updateElecAmount==共更新{}条数据", total); - } - - // 计算数据 - private List calculateData(List list) { - for (OrderDetail orderDetail : list) { - try { - // 总电费金额 - BigDecimal totalElectricityAmount = BigDecimal.ZERO; - - // 尖时段用电量 - BigDecimal sharpUsedElectricity = orderDetail.getSharpUsedElectricity(); - if (sharpUsedElectricity != null) { - // 计算该时段电费 - BigDecimal multiply = orderDetail.getSharpElectricityPrice().multiply(sharpUsedElectricity).setScale(2, BigDecimal.ROUND_DOWN); - totalElectricityAmount = totalElectricityAmount.add(multiply); - } - - // 峰时段用电量 - BigDecimal peakUsedElectricity = orderDetail.getPeakUsedElectricity(); - if (peakUsedElectricity != null) { - // 计算该时段电费 - BigDecimal multiply = orderDetail.getPeakElectricityPrice().multiply(peakUsedElectricity).setScale(2, BigDecimal.ROUND_DOWN); - totalElectricityAmount = totalElectricityAmount.add(multiply); - } - - // 平时段用电量 - BigDecimal flatUsedElectricity = orderDetail.getFlatUsedElectricity(); - if (flatUsedElectricity != null) { - // 计算该时段电费 - BigDecimal multiply = orderDetail.getFlatElectricityPrice().multiply(flatUsedElectricity).setScale(2, BigDecimal.ROUND_DOWN); - totalElectricityAmount = totalElectricityAmount.add(multiply); - } - - // 谷时段用电量 - BigDecimal valleyUsedElectricity = orderDetail.getValleyUsedElectricity(); - if (valleyUsedElectricity != null) { - // 计算该时段电费 - BigDecimal multiply = orderDetail.getValleyElectricityPrice().multiply(valleyUsedElectricity).setScale(2, BigDecimal.ROUND_DOWN); - totalElectricityAmount = totalElectricityAmount.add(multiply); - } - - orderDetail.setTotalElectricityAmount(totalElectricityAmount); - orderDetail.setTotalServiceAmount(orderDetail.getTotalOrderAmount().subtract(totalElectricityAmount)); - } catch (Exception e) { - logger.info("发生异常", e); - } - } - return list; - } - - /** - * 余额支付 计算需要退回的金额 - * - * @param principalPay - * @param giftPay - * @param orderAmount - * @return - */ - private Map calculateReturnAmount(BigDecimal principalPay, BigDecimal giftPay, BigDecimal orderAmount) { - Map resultMap = Maps.newHashMap(); - - // 消费金额优先使用本金 - BigDecimal returnPrincipal = null; // 退回本金金额 - BigDecimal returnGift = null; // 退回赠送金额 - - // 余额支付 有3种情况 - if (principalPay != null && giftPay == null) { - // 只有本金支付 - BigDecimal subtract = principalPay.subtract(orderAmount); - if (subtract.compareTo(BigDecimal.ZERO) > 0) { - returnPrincipal = subtract; - } - } - if (principalPay == null && giftPay != null) { - // 只有赠送金额支付 - BigDecimal subtract = giftPay.subtract(orderAmount); - if (subtract.compareTo(BigDecimal.ZERO) > 0) { - returnGift = subtract; - } - } - if (principalPay != null && giftPay != null) { - // 本金+赠送支付 - BigDecimal subtract = principalPay.subtract(orderAmount); - if (subtract.compareTo(BigDecimal.ZERO) > 0) { - // 本金减掉订单金额后还有剩余,那就把剩余的退回,赠送原封不动退回 - returnPrincipal = subtract; - returnGift = giftPay; - } else if (subtract.compareTo(BigDecimal.ZERO) == 0) { - // 本金刚好够,那赠送金额支付的原封不动退回 - returnGift = giftPay; - } else { - returnGift = giftPay.subtract(subtract.negate()); - } - } - - resultMap.put("returnPrincipal", returnPrincipal); - resultMap.put("returnGift", returnGift); - return resultMap; - } - - /** - * 结算订单退款和用户余额退款调这个方法 - * - * @param dto - */ - @Override - public void weChatRefund(WeChatRefundDTO dto) { - // 退款有两种情况 1-订单结算退款 2-用户余额退款 - String refundType = dto.getRefundType(); - if (StringUtils.equals(refundType, "1")) { - WechatPayRefundResponse response = refundForOrder(dto); - logger.info("订单结算退款 result:{}", JSONObject.toJSONString(response)); - } else if (StringUtils.equals(refundType, "2")) { - WechatPayRefundResponse response = refundForBalance(dto); - logger.info("用户余额退款 result:{}", JSONObject.toJSONString(response)); - } else { - logger.warn("没有找到退款处理逻辑"); - } - } - - @Override - public void saveAbnormalOrder(TransactionRecordsData data) { - OrderAbnormalRecord record = new OrderAbnormalRecord(); - BeanUtils.copyBeanProp(record, data); - orderAbnormalRecordService.insertOrderAbnormalRecord(record); - - // 保存到订单主表 - // 订单基本信息 - PileInfoVO pileInfoVO = pileBasicInfoService.selectPileInfoBySn(data.getPileSn()); - if (pileInfoVO == null) { - return; - } - String orderCode = IdUtils.getOrderCode(); - OrderBasicInfo orderBasicInfo = OrderBasicInfo.builder().build(); - // 订单编号 - orderBasicInfo.setOrderCode(orderCode); - // 交易流水号 - orderBasicInfo.setTransactionCode(data.getTransactionCode()); - // 站点id - orderBasicInfo.setStationId(pileInfoVO.getStationId()); - // 充电桩编号 - orderBasicInfo.setPileSn(data.getPileSn()); - // 枪口号 - orderBasicInfo.setConnectorCode(data.getConnectorCode()); - // 枪口编号 - orderBasicInfo.setPileConnectorCode(pileInfoVO.getPileSn() + data.getConnectorCode()); - // 启动方式 - String transactionIdentifier = data.getTransactionIdentifier(); - String startMode = null; - // if (StringUtils.equals(transactionIdentifier, "01")) { - // startMode = StartModeEnum.APP.getValue(); - // } else if (StringUtils.equals(transactionIdentifier, "02")) { - // // 卡启动 - // startMode = StartModeEnum.CARD.getValue(); - // } - // 卡号 - if (StringUtils.isNotBlank(data.getLogicCard())) { - startMode = StartModeEnum.OFFLINE_CARD.getValue(); - orderBasicInfo.setLogicCard(data.getLogicCard()); - // 订单状态 (2023.4.6 要求改成“订单完成”) - orderBasicInfo.setOrderStatus(OrderStatusEnum.ORDER_COMPLETE.getValue()); - } else { - // 订单状态 可疑 - orderBasicInfo.setOrderStatus(OrderStatusEnum.SUSPICIOUS.getValue()); - } - orderBasicInfo.setStartMode(startMode); - // 支付方式 - orderBasicInfo.setPayMode(null); - // 支付金额 - orderBasicInfo.setPayAmount(null); - // 支付状态 - orderBasicInfo.setPayStatus(null); - // 支付时间 - orderBasicInfo.setPayTime(null); - // 订单金额 - orderBasicInfo.setOrderAmount(new BigDecimal(data.getConsumptionAmount())); - // 充电开始时间 - orderBasicInfo.setChargeStartTime(DateUtils.parseDate(data.getStartTime())); - // 充电结束时间 - orderBasicInfo.setChargeEndTime(DateUtils.parseDate(data.getEndTime())); - // 停止原因 - orderBasicInfo.setReason(data.getStopReasonMsg()); - // 结算时间 - orderBasicInfo.setSettlementTime(DateUtils.getNowDate()); - // 创建人 - orderBasicInfo.setCreateBy(data.getLogicCard()); - - - // 订单详情 - OrderDetail orderDetail = OrderDetail.builder().build(); - // 订单编号 - orderDetail.setOrderCode(orderCode); - // 订单总金额 - orderDetail.setTotalOrderAmount(new BigDecimal(data.getConsumptionAmount())); - // 总用电量 - orderDetail.setTotalUsedElectricity(new BigDecimal(data.getTotalElectricity())); - // 总服务费金额 - // orderDetail.setTotalServiceAmount(); - // 总电费金额 - // orderDetail.setTotalElectricityAmount(); - - // 尖时段金额 - orderDetail.setSharpAmount(new BigDecimal(data.getSharpAmount())); - // 尖时段单价 - orderDetail.setSharpPrice(new BigDecimal(data.getSharpPrice())); - // 尖时段服务费单价 - // orderDetail.setSharpServicePrice(); - // 尖时段电费单价 - // orderDetail.setSharpElectricityPrice(); - // 尖时段用电量 - orderDetail.setSharpUsedElectricity(new BigDecimal(data.getSharpUsedElectricity())); - - // 峰时段金额 - orderDetail.setPeakAmount(new BigDecimal(data.getPeakAmount())); - // 峰时段单价 - orderDetail.setPeakPrice(new BigDecimal(data.getPeakPrice())); - // 峰时段服务费单价 - // orderDetail.setPeakServicePrice(); - // 峰时段电费单价 - // orderDetail.setPeakElectricityPrice(); - // 峰时段用电量 - orderDetail.setPeakUsedElectricity(new BigDecimal(data.getPeakUsedElectricity())); - - // 平时段金额 - orderDetail.setFlatAmount(new BigDecimal(data.getFlatAmount())); - // 平时段单价 - orderDetail.setFlatPrice(new BigDecimal(data.getFlatPrice())); - // 平时段服务费单价 - // orderDetail.setFlatServicePrice(); - // 平时段电费单价 - // orderDetail.setFlatElectricityPrice(); - // 平时段用电量 - orderDetail.setFlatUsedElectricity(new BigDecimal(data.getFlatUsedElectricity())); - - - // 谷时段金额 - orderDetail.setValleyAmount(new BigDecimal(data.getValleyAmount())); - // 谷时段单价 - orderDetail.setValleyPrice(new BigDecimal(data.getValleyPrice())); - // 谷时段服务费单价 - // orderDetail.setValleyServicePrice(); - // 谷时段电费单价 - // orderDetail.setValleyElectricityPrice(); - // 谷时段用电量 - orderDetail.setValleyUsedElectricity(new BigDecimal(data.getValleyUsedElectricity())); - - if (data.getCreateTime() != null) { - orderBasicInfo.setCreateTime(data.getCreateTime()); - orderDetail.setCreateTime(data.getCreateTime()); - } - - OrderTransactionDTO createOrderTransactionDTO = OrderTransactionDTO.builder() - .orderBasicInfo(orderBasicInfo) - .orderDetail(orderDetail) - .build(); - pileTransactionService.doCreateOrder(createOrderTransactionDTO); - } - - /** - * 根据订单编号获取充电实时数据 时间倒序 - * 订单只有在充电中,才会把实时数据保存到redis - * - * @param transactionCode 订单编号 - * @return - */ - @Override - public List getChargingRealTimeData(String transactionCode) { - List resultList = Lists.newArrayList(); - if (StringUtils.isBlank(transactionCode)) { - return resultList; - } - // logger.info("transactionCode:{}", transactionCode); - String pileConnectorCode = transactionCode.substring(0, 16); - String redisKey = CacheConstants.PILE_REAL_TIME_MONITOR_DATA + pileConnectorCode + "_" + transactionCode; - // 拿到所有数据 - Map map = redisCache.hmget(redisKey); - if (map != null && !map.isEmpty()) { - List keyList = map.keySet().stream() - .map(x -> (String) x) - .sorted(Comparator.reverseOrder()) // 对keyList排序 时间倒序 - .collect(Collectors.toList()); - for (String s : keyList) { - Object o = map.get(s); - RealTimeMonitorData data = JSONObject.parseObject((String) o, RealTimeMonitorData.class); - resultList.add(data); - } - } else { - logger.debug("redis中没有实时数据了,去数据库查"); - // redis中为空,去查库 - OrderMonitorData orderMonitorData = orderMonitorDataService.selectByTransactionCode(transactionCode); - if (orderMonitorData != null) { - String monitorData = orderMonitorData.getMonitorData(); - List dataList = JSON.parseArray(monitorData, RealTimeMonitorData.class); - resultList.addAll(dataList); - } - } - return resultList; - } - - /** - * 首页订单数据展示 - * - * @param dto 首页信息查询dto - * @return - */ - @Override - public List getIndexOrderInfo(IndexQueryDTO dto) { - AuthorizedDeptVO authorizedMap = SecurityUtils.getAuthorizedMap(); - if (authorizedMap == null) { - return Lists.newArrayList(); - } - List stationIdList = Lists.newArrayList(); - List stationDeptIds = authorizedMap.getStationDeptIds(); - if (CollectionUtils.isNotEmpty(stationDeptIds)) { - // 根据部门id查询站点id - List list = pileStationInfoService.queryByStationDeptIds(stationDeptIds); - if (CollectionUtils.isNotEmpty(list)) { - stationIdList.addAll(list); - } - } - List merchantDeptIds = authorizedMap.getMerchantDeptIds(); - if (CollectionUtils.isNotEmpty(merchantDeptIds)) { - // 根据运营商部门id查询下面所有站点id - List list = pileMerchantInfoService.queryByMerchantDeptIds(merchantDeptIds); - if (CollectionUtils.isNotEmpty(list)) { - stationIdList.addAll(list); - } - } - dto.setStationIdList(stationIdList); - return orderBasicInfoMapper.getIndexOrderInfo(dto); - } - - /** - * 获取超过15分钟的待支付状态订单 - * - * @return - */ - @Override - public List getUnpaidOrderListOver15Min() { - Date now = DateUtils.addMinute(new Date(), -15); - String nowString = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, now); - return orderBasicInfoMapper.getUnpaidOrderListOver15Min(nowString); - } - - /** - * 根据orderId批量修改订单状态 - * - * @param orderIds - * @param orderStatus - */ - @Override - public void updateOrderStatusById(List orderIds, String orderStatus) { - orderBasicInfoMapper.updateOrderStatusById(orderIds, orderStatus); - } - - @Override - public int close15MinutesOfUnpaidOrders() { - List orderList = getUnpaidOrderListOver15Min(); - if (CollectionUtils.isNotEmpty(orderList)) { - List orderIdList = orderList.stream() - .map(x -> String.valueOf(x.getId())) - .collect(Collectors.toList()); - // 修改订单状态 - updateOrderStatusById(orderIdList, OrderStatusEnum.ORDER_CLOSE_TIMEOUT.getValue()); - - for (OrderBasicInfo orderBasicInfo : orderList) { - this.cleanCacheByOrderCode(orderBasicInfo.getOrderCode(), orderBasicInfo.getTransactionCode()); - } - } - return orderList.size(); - } - - /** - * 订单退款处理逻辑 - */ - private WechatPayRefundResponse refundForOrder(WeChatRefundDTO dto) { - // 查出来原来的支付信息 - WxpayCallbackRecord record = wxpayCallbackRecordService.selectByOrderCode(dto.getOrderCode()); - if (Objects.isNull(record)) { - logger.error("orderCode:{}, 订单退款处理逻辑, 查询订单微信支付记录为空!", dto.getOrderCode()); - throw new BusinessException(ReturnCodeEnum.CODE_REFUND_ORDER_CALLBACK_RECORD_ERROR); - } - - // 判断支付金额和退款金额 - int refundAmountInt = dto.getRefundAmount().multiply(new BigDecimal("100")).intValue(); - int payerTotalInt = Integer.parseInt(record.getPayerTotal()); - if (refundAmountInt > payerTotalInt) { - logger.error("订单号:{}, 退款金额:{}(分),大于可退金额{}(分), 抛出异常", dto.getOrderCode(), refundAmountInt, payerTotalInt); - throw new BusinessException(ReturnCodeEnum.CODE_REFUND_ORDER_AMOUNT_ERROR); - } - - // 调微信退款接口 - WechatPayRefundRequest request = new WechatPayRefundRequest(); - request.setTransaction_id(record.getTransactionId()); // 微信支付单号 - request.setOut_trade_no(record.getOutTradeNo()); // 商户订单号 - // 生成退款单号 - request.setOut_refund_no(SnowflakeIdWorker.getSnowflakeId()); // 商户退款单号 - request.setNotify_url(WeChatPayParameter.refundNotifyUrl); // 回调接口 - WechatPayRefundRequest.Amount amount = new WechatPayRefundRequest.Amount(); - amount.setRefund(refundAmountInt); // 退款金额 - amount.setTotal(payerTotalInt); // 原订单金额 - request.setAmount(amount); - request.setReason("订单结算退款"); - request.setFunds_account("AVAILABLE"); - try { - return wechatPayService.ApplyForWechatPayRefundV3(request); - } catch (JsonProcessingException e) { - logger.error("调微信退款API发生异常", e); - } - return null; - } - - /** - * 余额退款处理逻辑 - * - * @param dto - */ - private WechatPayRefundResponse refundForBalance(WeChatRefundDTO dto) { - // 查会员余额 - MemberVO memberVO = memberBasicInfoService.queryMemberInfoByMemberId(dto.getMemberId()); - if (memberVO == null) { - throw new BusinessException(ReturnCodeEnum.CODE_SELECT_MEMBER_NULL_ERROR); - } - // 校验退款金额 - BigDecimal principalBalance = memberVO.getPrincipalBalance(); - BigDecimal refundAmount = dto.getRefundAmount(); - if (refundAmount.compareTo(principalBalance) > 0) { - throw new BusinessException(ReturnCodeEnum.CODE_REFUND_MEMBER_BALANCE_ERROR); - } - // 退款金额 元转分 123 - int refundTotalCents = refundAmount.multiply(new BigDecimal(100)).intValue(); - - // 查询用户充值余额订单 过滤掉已经退款的充值订单 refundableOrder - List recordList = queryRefundableOrder(dto.getMemberId()); - - // 也许需要多笔支付订单才够退款 - List requestList = Lists.newArrayList(); - WechatPayRefundRequest request; - for (RefundableWxPayOrderData record : recordList) { - int refundableTotal = record.getRefundableAmount().intValue(); // 该笔支付订单的可退金额,单位分 - int payerTotal = record.getPayerAmount().intValue(); // 该笔支付订单的支付金额,单位分 - // 用户申请退款金额-可退金额 - refundTotalCents = refundTotalCents - refundableTotal; // 123 - 100 - request = new WechatPayRefundRequest(); - request.setTransaction_id(record.getTransactionId()); // 微信支付单号 - request.setOut_trade_no(record.getOutTradeNo()); // 商户订单号 - request.setOut_refund_no(SnowflakeIdWorker.getSnowflakeId()); // 商户退款单号 - request.setNotify_url(WeChatPayParameter.refundNotifyUrl); // 回调接口 - request.setReason("用户余额退款"); - request.setFunds_account("AVAILABLE"); - if (refundTotalCents > 0) { - // 如果大于0说明,这笔单退完也不够 - WechatPayRefundRequest.Amount amount = new WechatPayRefundRequest.Amount(); - amount.setRefund(refundableTotal); // 退款金额 - amount.setTotal(payerTotal); // 原订单金额 - request.setAmount(amount); - requestList.add(request); - } else { - // 如果小于0,这笔单退一部分 - // 生成退款单号 - WechatPayRefundRequest.Amount amount = new WechatPayRefundRequest.Amount(); - // 部分退 - int i = refundableTotal + refundTotalCents; - amount.setRefund(i); // 退款金额 - amount.setTotal(payerTotal); // 原订单金额 - request.setAmount(amount); - requestList.add(request); - break; - } - } - // 调微信退款api - if (CollectionUtils.isNotEmpty(requestList)) { - for (WechatPayRefundRequest refundRequest : requestList) { - try { - return wechatPayService.ApplyForWechatPayRefundV3(refundRequest); - // logger.info("调微信退款API退款====={}", JSONObject.toJSONString(refundRequest)); - } catch (Exception e) { - logger.error("调微信退款API发生异常", e); - } - } - } - return null; - } - - private List queryRefundableOrder(String memberId) { - List resultList = Lists.newArrayList(); - // 查询最近一年余额充值订单 - List recordList = wxpayCallbackRecordService.queryBalanceRechargeRecordOfTheLatestYear(memberId); - if (CollectionUtils.isEmpty(recordList)) { - return resultList; - } - // 拿到微信商户单号list - List outTradeNoList = recordList.stream() - .map(WxpayCallbackRecord::getOutTradeNo) - .collect(Collectors.toList()); - List wxpayRefundCallbacks = wxpayRefundCallbackService.selectWxpayRefundCallbackList(outTradeNoList); - if (CollectionUtils.isEmpty(wxpayRefundCallbacks)) { - // 退款记录为空,表示没有一笔退款 - for (WxpayCallbackRecord wxpayCallbackRecord : recordList) { - resultList.add( - RefundableWxPayOrderData.builder() - .outTradeNo(wxpayCallbackRecord.getOutTradeNo()) - .transactionId(wxpayCallbackRecord.getTransactionId()) - .payerAmount(new BigDecimal(wxpayCallbackRecord.getPayerTotal())) - .refundableAmount(new BigDecimal(wxpayCallbackRecord.getPayerTotal())) - .build() - ); - } - return resultList; - } - - // 退款记录转map key:outTradeNo value:退款记录 - Map> refundMap = wxpayRefundCallbacks.stream() - .collect(Collectors.groupingBy(WxpayRefundCallback::getOutTradeNo)); - for (WxpayCallbackRecord wxpayCallbackRecord : recordList) { - List refundCallbackList = refundMap.get(wxpayCallbackRecord.getOutTradeNo()); - if (CollectionUtils.isEmpty(refundCallbackList)) { - // 这笔单没有申请过退款 - resultList.add( - RefundableWxPayOrderData.builder() - .outTradeNo(wxpayCallbackRecord.getOutTradeNo()) - .transactionId(wxpayCallbackRecord.getTransactionId()) - .payerAmount(new BigDecimal(wxpayCallbackRecord.getPayerTotal())) - .refundableAmount(new BigDecimal(wxpayCallbackRecord.getPayerTotal())) - .build() - ); - continue; - } - // 支付订单产生过退款 - BigDecimal refundTotal = refundCallbackList.stream() - .map(x -> new BigDecimal(x.getAmountRefund())) - .reduce(BigDecimal::add) - .get(); - - // 可退金额 - BigDecimal subtract = new BigDecimal(wxpayCallbackRecord.getPayerTotal()).subtract(refundTotal); - if (subtract.compareTo(BigDecimal.ZERO) > 0) { - resultList.add( - RefundableWxPayOrderData.builder() - .outTradeNo(wxpayCallbackRecord.getOutTradeNo()) - .transactionId(wxpayCallbackRecord.getTransactionId()) - .payerAmount(new BigDecimal(wxpayCallbackRecord.getPayerTotal())) - .refundableAmount(subtract) - .build() - ); - } - } - return resultList; - } - - /** - * 通过订单号查询订单详情 - * - * @param orderCode 订单号 - * @return 订单详情 - */ - @Override - public OrderDetail getOrderDetailByOrderCode(String orderCode) { - return orderBasicInfoMapper.getOrderDetailByOrderCode(orderCode); - } - - @Override - public List getOrderDetailList(List orderCodes) { - return orderBasicInfoMapper.getOrderDetailList(orderCodes); - } - - /** - * 通过会员Id和订单状态查询订单信息 - * - * @param memberId 会员id - * @param orderStatusList 订单状态集合 - * @return - */ - @Override - public List getListByMemberIdAndOrderStatus(String memberId, List orderStatusList) { - return getListByMemberIdAndOrderStatus(memberId, orderStatusList, null, null); - } - - @Override - public List getListByMemberIdAndOrderStatus(String memberId, List orderStatusList, LocalDateTime dateTime) { - return getListByMemberIdAndOrderStatus(memberId, orderStatusList, dateTime, null); - } - - @Override - public List getListByMemberIdAndOrderStatus(String memberId, List orderStatusList, LocalDateTime dateTime, String stationId) { - return orderBasicInfoMapper.getListByMemberIdAndOrderStatus(memberId, orderStatusList, dateTime, stationId); - } - - @Override - public List getListByOrderCodes(List orderCodes) { - return orderBasicInfoMapper.getListByOrderCodes(orderCodes); - } - - /** - * 个人桩查询充电数据 - * - * @param dto - * @return - */ - @Override - public List getAccumulativeInfo(QueryPersonPileDTO dto) { - return orderBasicInfoMapper.getAccumulativeInfo(dto); - } - - /** - * 修改订单状态为异常(桩离线时调用) - * - * @param pileSn - */ - @Override - public void updateOrderStatusAsAbnormal(String pileSn) { - // 先从redis判断是否有订单再进行查询 - if (Objects.isNull(redisCache.getCacheObject(CacheConstants.PILE_IS_CHARGING + pileSn))) { - return; - } - // 将此桩正在进行充电的订单状态改为 异常 - List orderListVOS = selectChargingOrder(pileSn); - if (CollectionUtils.isEmpty(orderListVOS)) { - return; - } - for (OrderListVO orderListVO : orderListVOS) { - if (StringUtils.equals(orderListVO.getOrderStatus(), OrderStatusEnum.IN_THE_CHARGING.getValue())) { - // 修改数据库订单状态 - OrderBasicInfo info = OrderBasicInfo.builder() - .id(Long.parseLong(orderListVO.getId())) - .orderStatus(OrderStatusEnum.ABNORMAL.getValue()) - .build(); - updateOrderBasicInfo(info); - logger.info("充电桩:{}退出, 修改充电桩正在充电的订单状态为异常, orderCode: {}", pileSn, orderListVO.getOrderCode()); - } - } - } - - @Override - public List getAppointmentOrder(LocalDateTime dateTime) { - return orderBasicInfoMapper.getAppointmentOrder(dateTime); - } - - /** - * 生成订单 返回交易流水号 - * - * @param dto - * @return - */ - @Override - public Map generateOrderByCard(GenerateOrderDTO dto) { - String pileSn = dto.getPileSn(); - String connectorCode = dto.getConnectorCode(); - PileAuthCard pileAuthCardInfo = dto.getPileAuthCardInfo(); - // 通过memberId获取账户余额 - MemberVO memberVO = memberBasicInfoService.queryMemberInfoByMemberId(pileAuthCardInfo.getMemberId()); - if (memberVO == null) { - throw new BusinessException(ReturnCodeEnum.CODE_GET_MEMBER_ACCOUNT_AMOUNT_ERROR); - } - BigDecimal totalAccountAmount = memberVO.getTotalAccountAmount(); - if (totalAccountAmount.compareTo(BigDecimal.ZERO) <= 0) { - throw new BusinessException(ReturnCodeEnum.CODE_BALANCE_IS_INSUFFICIENT); - } - - String transactionCode = IdUtils.generateTransactionCode(pileSn, connectorCode); - // 通过桩号查询所属站点 - PileBasicInfo pileBasicInfo = pileBasicInfoService.selectPileBasicInfoBySN(pileSn); - Long stationId = pileBasicInfo.getStationId(); - // 自动余额全部支付订单 个人桩站点不计费 - - - // 将此订单信息存入订单表 - String orderCode = IdUtils.getOrderCode(); - // 订单基本信息 - OrderBasicInfo orderBasicInfo = OrderBasicInfo.builder() - .orderCode(orderCode) - .transactionCode(transactionCode) - .orderStatus(OrderStatusEnum.NOT_START.getValue()) - .memberId(memberVO.getMemberId()) - .stationId(String.valueOf(stationId)) - .pileSn(pileSn) - .connectorCode(connectorCode) - .pileConnectorCode(pileSn + connectorCode) - .logicCard(pileAuthCardInfo.getLogicCard()) - .startMode(StartModeEnum.AUTH_CARD.getValue()) - .payStatus(Constants.ONE) - .payAmount(totalAccountAmount) - .payTime(new Date()) - .payMode(OrderPayModeEnum.PAYMENT_OF_BALANCE.getValue()) - .orderAmount(BigDecimal.ZERO) - .build(); - // 根据桩编码查询当前计费模板 - BillingTemplateVO billingTemplateVO = pileBillingTemplateService.selectBillingTemplateDetailByPileSn(pileSn); - // 订单详情 - OrderDetail orderDetail = OrderDetail.builder() - .orderCode(orderCode) - .sharpElectricityPrice(billingTemplateVO.getSharpElectricityPrice()) - .sharpServicePrice(billingTemplateVO.getSharpServicePrice()) - .peakElectricityPrice(billingTemplateVO.getPeakElectricityPrice()) - .peakServicePrice(billingTemplateVO.getPeakServicePrice()) - .flatElectricityPrice(billingTemplateVO.getFlatElectricityPrice()) - .flatServicePrice(billingTemplateVO.getFlatServicePrice()) - .valleyElectricityPrice(billingTemplateVO.getValleyElectricityPrice()) - .valleyServicePrice(billingTemplateVO.getValleyServicePrice()) - .build(); - - OrderTransactionDTO createOrderTransactionDTO = OrderTransactionDTO.builder() - .orderBasicInfo(orderBasicInfo) - .orderDetail(orderDetail) - .build(); - pileTransactionService.doCreateOrder(createOrderTransactionDTO); - - // 将卡状态改为启动锁定 - PileAuthCard pileAuthCard = PileAuthCard.builder() - .id(pileAuthCardInfo.getId()) - .logicCard(pileAuthCardInfo.getLogicCard()) - .status("2") - .build(); - pileAuthCardService.updatePileAuthCard(pileAuthCard); - - // 组装结果集 - Map resultMap = Maps.newHashMap(); - resultMap.put("orderCode", orderBasicInfo.getOrderCode()); - resultMap.put("transactionCode", orderBasicInfo.getTransactionCode()); - resultMap.put("accountBalance", totalAccountAmount); - return resultMap; - } - - /** - * 联联平台 获取累计数据用 - * - * @param dto - * @return - */ - @Override - public List getAccumulativeInfoForLianLian(QueryStationInfoDTO dto) { - return orderBasicInfoMapper.getAccumulativeInfoForLianLian(dto); - } - - /** - * 联联平台生成订单 - * - * @param dto - * @return - */ - @Override - public Map generateOrderForLianLian(QueryStartChargeDTO dto) { - // 联联平台生成订单 - String orderCode = dto.getStartChargeSeq(); - String pileConnectorCode = dto.getConnectorID(); - String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); - String connectorCode = StringUtils.substring(pileConnectorCode, 14, 16); - - - String transactionCode = IdUtils.generateTransactionCode(pileSn, connectorCode); - - // 通过桩号查询所属站点 - PileBasicInfo pileBasicInfo = pileBasicInfoService.selectPileBasicInfoBySN(pileSn); - Long stationId = pileBasicInfo.getStationId(); - - - // 将此订单信息存入订单表 - // 订单基本信息 - OrderBasicInfo orderBasicInfo = OrderBasicInfo.builder() - .orderCode(orderCode) - .transactionCode(transactionCode) - .orderStatus(OrderStatusEnum.NOT_START.getValue()) - // .memberId(memberVO.getMemberId()) // 会员memberId - .stationId(String.valueOf(stationId)) - .pileSn(pileSn) - .connectorCode(connectorCode) - .pileConnectorCode(pileConnectorCode) - // .logicCard(pileAuthCardInfo.getLogicCard()) // 卡号 - .startMode(StartModeEnum.LIAN_LIAN.getValue()) - .payStatus(Constants.ONE) - // .payAmount(totalAccountAmount) // 支付金额 - .payTime(new Date()) - // .payMode(PayModeEnum.PAYMENT_OF_BALANCE.getValue()) // 支付方式 - .orderAmount(BigDecimal.ZERO) - .build(); - // 根据桩编码查询当前计费模板 - BillingTemplateVO billingTemplateVO = pileBillingTemplateService.selectBillingTemplateDetailByPileSn(pileSn); - // 订单详情 - OrderDetail orderDetail = OrderDetail.builder() - .orderCode(orderCode) - .sharpElectricityPrice(billingTemplateVO.getSharpElectricityPrice()) - .sharpServicePrice(billingTemplateVO.getSharpServicePrice()) - .peakElectricityPrice(billingTemplateVO.getPeakElectricityPrice()) - .peakServicePrice(billingTemplateVO.getPeakServicePrice()) - .flatElectricityPrice(billingTemplateVO.getFlatElectricityPrice()) - .flatServicePrice(billingTemplateVO.getFlatServicePrice()) - .valleyElectricityPrice(billingTemplateVO.getValleyElectricityPrice()) - .valleyServicePrice(billingTemplateVO.getValleyServicePrice()) - .build(); - - OrderTransactionDTO createOrderTransactionDTO = OrderTransactionDTO.builder() - .orderBasicInfo(orderBasicInfo) - .orderDetail(orderDetail) - .build(); - pileTransactionService.doCreateOrder(createOrderTransactionDTO); - - // 组装结果集 - Map resultMap = Maps.newHashMap(); - resultMap.put("orderCode", orderBasicInfo.getOrderCode()); - resultMap.put("transactionCode", orderBasicInfo.getTransactionCode()); - resultMap.put("orderBasicInfo", orderBasicInfo); - resultMap.put("orderDetail", orderDetail); - // resultMap.put("accountBalance", totalAccountAmount); - - return resultMap; - } - - @Override - public List queryOrderAmountDetail(List orderCodes) { - List orderDetailList = getOrderDetailList(orderCodes); - if (CollectionUtils.isEmpty(orderDetailList)) { - return Lists.newArrayList(); - } - List resultList = Lists.newArrayList(); - OrderAmountDetailVO vo = null; - for (OrderDetail orderDetail : orderDetailList) { - vo = new OrderAmountDetailVO(); - BeanUtils.copyBeanProp(vo, orderDetail); - resultList.add(vo); - } - return resultList; - } - - /** - * 订单详情 转换为各个时段的详情 - */ - @Override - public List transformPeriodAmountByOrderDetail(OrderDetail orderDetail) { - // 尖时段 - OrderPeriodAmountVO sharp = new OrderPeriodAmountVO(); - sharp.setPeriodType(BillingTimeEnum.SHARP.getLabel()); - sharp.setElectricityPrice(orderDetail.getSharpElectricityPrice()); - sharp.setServicePrice(orderDetail.getSharpServicePrice()); - BigDecimal sharpUsedElectricity = orderDetail.getSharpUsedElectricity() == null ? BigDecimal.ZERO : orderDetail.getSharpUsedElectricity(); - sharp.setUsedElectricity(sharpUsedElectricity); - sharp.setElectricityAmount(sharp.getElectricityPrice().multiply(sharp.getUsedElectricity()).setScale(2, BigDecimal.ROUND_DOWN)); - sharp.setServiceAmount(sharp.getServicePrice().multiply(sharp.getUsedElectricity()).setScale(2, BigDecimal.ROUND_DOWN)); - - // 峰时段 - OrderPeriodAmountVO peak = new OrderPeriodAmountVO(); - peak.setPeriodType(BillingTimeEnum.PEAK.getLabel()); - peak.setElectricityPrice(orderDetail.getPeakElectricityPrice()); - peak.setServicePrice(orderDetail.getPeakServicePrice()); - BigDecimal peakUsedElectricity = orderDetail.getPeakUsedElectricity() == null ? BigDecimal.ZERO : orderDetail.getPeakUsedElectricity(); - peak.setUsedElectricity(peakUsedElectricity); - peak.setElectricityAmount(peak.getElectricityPrice().multiply(peak.getUsedElectricity()).setScale(2, BigDecimal.ROUND_DOWN)); - peak.setServiceAmount(peak.getServicePrice().multiply(peak.getUsedElectricity()).setScale(2, BigDecimal.ROUND_DOWN)); - - // 平时段 - OrderPeriodAmountVO flat = new OrderPeriodAmountVO(); - flat.setPeriodType(BillingTimeEnum.FLAT.getLabel()); - flat.setElectricityPrice(orderDetail.getFlatElectricityPrice()); - flat.setServicePrice(orderDetail.getFlatServicePrice()); - BigDecimal flatUsedElectricity = orderDetail.getFlatUsedElectricity() == null ? BigDecimal.ZERO : orderDetail.getFlatUsedElectricity(); - flat.setUsedElectricity(flatUsedElectricity); - flat.setElectricityAmount(flat.getElectricityPrice().multiply(flat.getUsedElectricity()).setScale(2, BigDecimal.ROUND_DOWN)); - flat.setServiceAmount(flat.getServicePrice().multiply(flat.getUsedElectricity()).setScale(2, BigDecimal.ROUND_DOWN)); - - // 谷时段 - OrderPeriodAmountVO valley = new OrderPeriodAmountVO(); - valley.setPeriodType(BillingTimeEnum.VALLEY.getLabel()); - valley.setElectricityPrice(orderDetail.getValleyElectricityPrice()); - valley.setServicePrice(orderDetail.getValleyServicePrice()); - BigDecimal valleyUsedElectricity = orderDetail.getValleyUsedElectricity() == null ? BigDecimal.ZERO : orderDetail.getValleyUsedElectricity(); - valley.setUsedElectricity(valleyUsedElectricity); - valley.setElectricityAmount(valley.getElectricityPrice().multiply(valley.getUsedElectricity()).setScale(2, BigDecimal.ROUND_DOWN)); - valley.setServiceAmount(valley.getServicePrice().multiply(valley.getUsedElectricity()).setScale(2, BigDecimal.ROUND_DOWN)); - - return Lists.newArrayList(sharp, peak, flat, valley); - } - - @Override - public String tempUpdateVirtualAmount(QueryOrderDTO dto) { - dto.setOrderStatus(OrderStatusEnum.ORDER_COMPLETE.getValue()); - List orderListVOS = orderBasicInfoMapper.selectOrderBasicInfoList(dto); - if (CollectionUtils.isEmpty(orderListVOS)) { - return "没有订单需要修改"; - } - tempUpdateVirtualAmount(orderListVOS); - return "共修改" + orderListVOS.size() + "条订单数据"; - } + public void cleanCacheByOrderCode(String orderCode, String transactionCode) { + logger.debug("清除订单缓存 orderCode:{}, transactionCode:{}", orderCode, transactionCode); + List keys = Lists.newArrayList(); + if (StringUtils.isNotBlank(orderCode)) { + keys.add(CacheConstants.GET_ORDER_INFO_BY_ORDER_CODE + orderCode); + } + if (StringUtils.isNotBlank(transactionCode)) { + keys.add(CacheConstants.GET_ORDER_INFO_BY_TRANSACTION_CODE + transactionCode); + } + if (CollectionUtils.isNotEmpty(keys)) { + redisCache.deleteObject(keys); + } + } + + /** + * 批量删除订单 + * + * @param ids 需要删除的订单主键 + * @return 结果 + */ + @Transactional + @Override + public int deleteOrderBasicInfoByIds(Long[] ids) { + orderBasicInfoMapper.deleteOrderDetailByOrderCodes(ids); + return orderBasicInfoMapper.deleteOrderBasicInfoByIds(ids); + } + + /** + * 通过订单号查询订单信息 + * + * @param orderCode 订单号 + * @return + */ + @Override + public OrderBasicInfo getOrderInfoByOrderCode(String orderCode) { + // 如果orderCode是00000000000000000000000000000000,直接返回null + if (StringUtils.equals(Constants.ILLEGAL_TRANSACTION_CODE, orderCode)) { + return null; + } + String redisKey = CacheConstants.GET_ORDER_INFO_BY_ORDER_CODE + orderCode; + OrderBasicInfo orderBasicInfo = redisCache.getCacheObject(redisKey); + if (orderBasicInfo == null) { + // 查数据库 + orderBasicInfo = orderBasicInfoMapper.getOrderInfoByOrderCode(orderCode); + // 放缓存 + if (orderBasicInfo != null) { + redisCache.setCacheObject(redisKey, orderBasicInfo, 5, TimeUnit.MINUTES); + } + } + logger.info("通过订单号:{}, 查询订单信息:{}", orderCode, JSON.toJSONString(orderBasicInfo)); + return orderBasicInfo; + } + + @Override + public OrderBasicInfo getOrderInfoByTransactionCode(String transactionCode) { + if (StringUtils.equals(Constants.ILLEGAL_TRANSACTION_CODE, transactionCode)) { + return null; + } + String redisKey = CacheConstants.GET_ORDER_INFO_BY_TRANSACTION_CODE + transactionCode; + OrderBasicInfo orderBasicInfo = redisCache.getCacheObject(redisKey); + if (orderBasicInfo == null) { + // 查数据库 + orderBasicInfo = orderBasicInfoMapper.getOrderInfoByTransactionCode(transactionCode); + // 放缓存 + if (orderBasicInfo != null) { + redisCache.setCacheObject(redisKey, orderBasicInfo, 5, TimeUnit.MINUTES); + } + } + logger.info("通过交易流水号:{}, 查询订单信息:{}", transactionCode, JSON.toJSONString(orderBasicInfo)); + return orderBasicInfo; + } + + /** + * 根据充电桩编号和枪口号查询正在充电中的订单 + * + * @param pileSn 桩编号 + * @param connectorCode 枪口号 + * @return + */ + @Override + public OrderBasicInfo queryChargingByPileSnAndConnectorCode(String pileSn, String connectorCode) { + return orderBasicInfoMapper.queryOrderBasicInfo(pileSn, connectorCode, OrderStatusEnum.IN_THE_CHARGING.getValue()); + } + + /** + * 根据枪口编号查询正在充电中的订单 + * + * @param pileConnectorCode + * @return + */ + @Override + public OrderBasicInfo queryChargingByPileConnectorCode(String pileConnectorCode) { + if (StringUtils.isBlank(pileConnectorCode)) { + return null; + } + String pileSn = pileConnectorCode.substring(0, pileConnectorCode.length() - 2); + String connectorCode = pileConnectorCode.substring(pileConnectorCode.length() - 2); + return queryChargingByPileSnAndConnectorCode(pileSn, connectorCode); + } + + /** + * 结算订单逻辑 + * + * @param data 交易记录数据 + * @param orderBasicInfo 订单主表信息,由调用方传过来 + */ + @Override + public void settleOrder(TransactionRecordsData data, OrderBasicInfo orderBasicInfo) { + logger.info("结算订单start data:{}, orderBasicInfo:{}", data.toString(), orderBasicInfo.toString()); + String orderCode = orderBasicInfo.getOrderCode(); + + // 判断订单状态 + if (StringUtils.equals(orderBasicInfo.getOrderStatus(), OrderStatusEnum.ORDER_COMPLETE.getValue())) { + logger.info("结算订单:{}, 是订单完成状态", orderCode); + return; + } + // 消费金额就是订单总金额 + BigDecimal orderAmount = new BigDecimal(data.getConsumptionAmount()); + + // 付款金额 - 实际消费金额,如果有剩余,需要走退款操作 当使用余额支付时payAmount = principalPay + giftPay + BigDecimal payAmount = orderBasicInfo.getPayAmount(); + + // 有时候充电桩到达金额停止充电会多出一点金额,比如实际需要充50元的电,充电桩传来的消费金额为50.01元,在后台记录的时候需要舍去 + if (orderAmount.compareTo(payAmount) > 0) { + logger.info("结算订单:【{}】充电桩传来的消费金额:【{}】大于付款金额:【{}】, 消费金额设置为付款金额相等数据", orderBasicInfo.getOrderCode(), orderAmount, payAmount); + orderAmount = payAmount; + } + + // 虚拟金额 指订单消费中使用赠送金额支付的部分 + BigDecimal virtualAmount = BigDecimal.ZERO; + + // 剩余需要退回的金额 residue + BigDecimal residue = payAmount.subtract(orderAmount); + if (residue.compareTo(BigDecimal.ZERO) > 0) { + // 查支付记录 + List payRecordList = orderPayRecordService.getOrderPayRecordList(orderBasicInfo.getOrderCode()); + // 更新订单支付记录 + List updatePayRecordList = Lists.newArrayList(); + // 根据支付方式不同,走不同渠道退款 + String payMode = orderBasicInfo.getPayMode(); + if (StringUtils.equals(payMode, OrderPayModeEnum.PAYMENT_OF_BALANCE.getValue())) { // 余额支付 + Map payRecordMap = payRecordList.stream() + .collect(Collectors.toMap(OrderPayRecord::getPayMode, Function.identity(), (k1, k2) -> k1)); + // 取出本金支付金额,赠送支付金额 + BigDecimal principalPay = null; + BigDecimal giftPay = null; + + OrderPayRecord principalPayRecord = payRecordMap.get("1"); + if (principalPayRecord != null) { + principalPay = principalPayRecord.getPayAmount(); + } + + OrderPayRecord giftPayRecord = payRecordMap.get("2"); + if (giftPayRecord != null) { + giftPay = giftPayRecord.getPayAmount(); + } + + Map returnAmountMap = calculateReturnAmount(principalPay, giftPay, orderAmount); + logger.info("结算订单:{}, 剩余金额退回余额, 订单消费金额:{}, 本金支付金额:{}, 赠送支付金额:{}, 退回金额map:{}", + orderCode, orderAmount, principalPay, giftPay, JSONObject.toJSONString(returnAmountMap)); + // 更新会员钱包 + BigDecimal returnPrincipal = returnAmountMap.get("returnPrincipal"); + if (returnPrincipal != null && principalPayRecord != null) { + principalPayRecord.setRefundAmount(returnPrincipal); + updatePayRecordList.add(principalPayRecord); + } + BigDecimal returnGift = returnAmountMap.get("returnGift"); + if (returnGift != null && giftPayRecord != null) { + giftPayRecord.setRefundAmount(returnGift); + updatePayRecordList.add(giftPayRecord); + // 支付的赠送金额-退回的赠送金额 = 实际使用赠送金额消费的部分 + virtualAmount = giftPay.subtract(returnGift); + } + UpdateMemberBalanceDTO updateMemberBalanceDTO = UpdateMemberBalanceDTO.builder() + .memberId(orderBasicInfo.getMemberId()) + .type(MemberWalletEnum.TYPE_IN.getValue()) // 进账 + .subType(MemberWalletEnum.SUBTYPE_ORDER_SETTLEMENT_REFUND.getValue()) // 订单结算退款 + .updatePrincipalBalance(returnPrincipal) + .updateGiftBalance(returnGift) + .relatedOrderCode(orderBasicInfo.getOrderCode()) + .build(); + memberBasicInfoService.updateMemberBalance(updateMemberBalanceDTO); + } else if (StringUtils.equals(payMode, OrderPayModeEnum.PAYMENT_OF_WECHATPAY.getValue())) { // 微信支付 + // 微信退款逻辑 + WeChatRefundDTO weChatRefundDTO = new WeChatRefundDTO(); + weChatRefundDTO.setOrderCode(orderBasicInfo.getOrderCode()); + weChatRefundDTO.setRefundType("1"); + weChatRefundDTO.setRefundAmount(residue); + this.weChatRefund(weChatRefundDTO); + // 订单支付记录 + OrderPayRecord orderPayRecord = payRecordList.get(0); + orderPayRecord.setRefundAmount(residue); + updatePayRecordList.add(orderPayRecord); + } else if (StringUtils.equals(payMode, OrderPayModeEnum.PAYMENT_OF_ALIPAY.getValue())) { // 支付宝支付 + // 支付宝退款逻辑 + } else { + // 白名单支付 + logger.info("订单:{}使用白名单支付,不进行退款处理", orderBasicInfo.getOrderCode()); + } + + // 更新order_pay_record + if (CollectionUtils.isNotEmpty(updatePayRecordList)) { + for (OrderPayRecord orderPayRecord : updatePayRecordList) { + orderPayRecordService.updateByPrimaryKeySelective(orderPayRecord); + } + } + } + + // 修改订单数据 + // 查询订单详情 + OrderDetail orderDetail = getOrderDetailByOrderCode(orderBasicInfo.getOrderCode()); + + // 把交易记录中的用电量,金额等信息 更新到orderBasicInfo和orderDetail + orderBasicInfo.setOrderAmount(orderAmount); // 订单总金额 + orderBasicInfo.setVirtualAmount(virtualAmount); // 虚拟金额 + orderBasicInfo.setSettleAmount(orderAmount.subtract(virtualAmount)); // 结算金额 + orderBasicInfo.setOrderStatus(OrderStatusEnum.ORDER_COMPLETE.getValue()); + orderBasicInfo.setReason(data.getStopReasonMsg()); // 充电停止原因 + orderBasicInfo.setSettlementTime(DateUtils.getNowDate()); // 结算时间 + orderBasicInfo.setRefundAmount(residue); // 结算退款金额 + + // 更新订单详情 + try { + // 总电费金额 + BigDecimal totalElectricityAmount = BigDecimal.ZERO; + + // 尖时段用电量 + String sharpUsedElectricity = data.getSharpUsedElectricity(); + if (sharpUsedElectricity != null) { + orderDetail.setSharpUsedElectricity(new BigDecimal(sharpUsedElectricity)); + if (data.getSharpPrice() != null) { + orderDetail.setSharpPrice(new BigDecimal(data.getSharpPrice())); + } + if (data.getSharpAmount() != null) { + orderDetail.setSharpAmount(new BigDecimal(data.getSharpAmount())); + } + // 计算该时段电费 + BigDecimal multiply = orderDetail.getSharpElectricityPrice().multiply(new BigDecimal(sharpUsedElectricity)).setScale(2, BigDecimal.ROUND_DOWN); + totalElectricityAmount = totalElectricityAmount.add(multiply); + } + + // 峰时段用电量 + String peakUsedElectricity = data.getPeakUsedElectricity(); + if (peakUsedElectricity != null) { + orderDetail.setPeakUsedElectricity(new BigDecimal(peakUsedElectricity)); + if (data.getPeakPrice() != null) { + orderDetail.setPeakPrice(new BigDecimal(data.getPeakPrice())); + } + if (data.getPeakAmount() != null) { + orderDetail.setPeakAmount(new BigDecimal(data.getPeakAmount())); + } + // 计算该时段电费 + BigDecimal multiply = orderDetail.getPeakElectricityPrice().multiply(new BigDecimal(peakUsedElectricity)).setScale(2, BigDecimal.ROUND_DOWN); + totalElectricityAmount = totalElectricityAmount.add(multiply); + } + + // 平时段用电量 + String flatUsedElectricity = data.getFlatUsedElectricity(); + if (flatUsedElectricity != null) { + orderDetail.setFlatUsedElectricity(new BigDecimal(flatUsedElectricity)); + if (data.getFlatPrice() != null) { + orderDetail.setFlatPrice(new BigDecimal(data.getFlatPrice())); + } + if (data.getFlatAmount() != null) { + orderDetail.setFlatAmount(new BigDecimal(data.getFlatAmount())); + } + // 计算该时段电费 + BigDecimal multiply = orderDetail.getFlatElectricityPrice().multiply(new BigDecimal(flatUsedElectricity)).setScale(2, BigDecimal.ROUND_DOWN); + totalElectricityAmount = totalElectricityAmount.add(multiply); + } + + // 谷时段用电量 + String valleyUsedElectricity = data.getValleyUsedElectricity(); + if (valleyUsedElectricity != null) { + orderDetail.setValleyUsedElectricity(new BigDecimal(valleyUsedElectricity)); + if (data.getValleyPrice() != null) { + orderDetail.setValleyPrice(new BigDecimal(data.getValleyPrice())); + } + if (data.getValleyAmount() != null) { + orderDetail.setValleyAmount(new BigDecimal(data.getValleyAmount())); + } + // 计算该时段电费 + BigDecimal multiply = orderDetail.getValleyElectricityPrice().multiply(new BigDecimal(valleyUsedElectricity)).setScale(2, BigDecimal.ROUND_DOWN); + totalElectricityAmount = totalElectricityAmount.add(multiply); + } + + orderDetail.setTotalElectricityAmount(totalElectricityAmount); + orderDetail.setTotalServiceAmount(orderAmount.subtract(totalElectricityAmount)); + orderDetail.setTotalUsedElectricity(new BigDecimal(data.getTotalElectricity())); // 总用电量 + orderDetail.setTotalOrderAmount(orderAmount); // 订单总金额 + } catch (Exception e) { + logger.error("设置订单详情参数发生异常", e); + } + + OrderTransactionDTO dto = new OrderTransactionDTO(); + dto.setOrderBasicInfo(orderBasicInfo); + dto.setOrderDetail(orderDetail); + transactionService.doUpdateOrder(dto); + logger.info("结算订单 end OrderTransactionDTO:{}", JSONObject.toJSONString(dto)); + + try { + // uniApp 发送停止充电订阅消息 + WechatSendMsgDTO wechatSendMsgDTO = new WechatSendMsgDTO(); + wechatSendMsgDTO.setOrderCode(orderBasicInfo.getOrderCode()); + Map resultMap = wxAppletRemoteService.stopChargingSendMsg(wechatSendMsgDTO); + logger.info("小程序发送充电停止推送消息 result:{}", JSON.toJSONString(resultMap)); + } catch (Exception e) { + logger.error("小程序发送充电停止推送消息 error", e); + } + + try { + realTimeMonitorDataRedis2DB(orderBasicInfo.getTransactionCode(), orderBasicInfo.getOrderCode()); + } catch (Exception e) { + logger.error("redis中取出实时记录保存到表 发生异常", e); + } + + // TODO 推送停止充电结果 notification_stop_charge_result + + + } + + /** + * 从redis中取出实时记录保存到表中j + * 当订单完成的时候调用 + */ + @Override + public void realTimeMonitorDataRedis2DB(String transactionCode, String orderCode) { + if (StringUtils.isBlank(transactionCode) || StringUtils.isBlank(orderCode)) { + return; + } + // 校验有没有保存过 + OrderMonitorData orderMonitorData = orderMonitorDataService.selectByOrderCode(orderCode); + if (orderMonitorData != null) { + return; + } + List chargingRealTimeData = getChargingRealTimeData(transactionCode); + if (CollectionUtils.isEmpty(chargingRealTimeData)) { + return; + } + List list = Lists.newArrayList(); + for (RealTimeMonitorData data : chargingRealTimeData) { + RealTimeMonitorData build = RealTimeMonitorData.builder() + .outputCurrent(data.getOutputCurrent()) + .outputCurrent(data.getOutputCurrent()) // 电流 + .outputVoltage(data.getOutputVoltage()) // 电压 + .outputPower(data.getOutputPower()) // 功率 + .SOC(data.getSOC()) // soc + .dateTime(data.getDateTime()) // 时间 + .batteryMaxTemperature(data.getBatteryMaxTemperature()) + .chargingAmount(data.getChargingAmount()) + .chargingDegree(data.getChargingDegree()) + .sumChargingTime(data.getSumChargingTime()) + .timeRemaining(data.getTimeRemaining()) + .gunLineTemperature(data.getGunLineTemperature()) + .build(); + list.add(build); + } + + OrderMonitorData record = new OrderMonitorData(); + record.setOrderCode(orderCode); + record.setTransactionCode(transactionCode); + record.setMonitorData(JSONObject.toJSONString(list)); + int insert = orderMonitorDataService.insertSelective(record); + if (insert > 0) { + // 删除redis中缓存 + String pileConnectorCode = transactionCode.substring(0, 16); + String redisKey = CacheConstants.PILE_REAL_TIME_MONITOR_DATA + pileConnectorCode + "_" + transactionCode; + redisCache.deleteObject(redisKey); + } + + } + + @Override + public void updateElecAmount() { + // 查询 elecAmount为空的订单数据 + int pageNum = 1; + int pageSize = 500; + + int total = 0; + int batch = 1; + while (true) { + // 分页处理 + PageHelper.startPage(pageNum, pageSize); + List list = orderBasicInfoMapper.queryElecAmountNullList(); + PageInfo pageInfo = new PageInfo<>(list); + if (CollectionUtils.isEmpty(pageInfo.getList())) { + break; + } + + // 计算电量总金额 + List orderDetailList = calculateData(pageInfo.getList()); + + // 更新数据库 + int i = orderBasicInfoMapper.batchUpdateOrderDetail(orderDetailList); + total += i; + logger.info("updateElecAmount==第{}批次更新完成", batch); + batch += 1; + } + logger.info("updateElecAmount==共更新{}条数据", total); + } + + // 计算数据 + private List calculateData(List list) { + for (OrderDetail orderDetail : list) { + try { + // 总电费金额 + BigDecimal totalElectricityAmount = BigDecimal.ZERO; + + // 尖时段用电量 + BigDecimal sharpUsedElectricity = orderDetail.getSharpUsedElectricity(); + if (sharpUsedElectricity != null) { + // 计算该时段电费 + BigDecimal multiply = orderDetail.getSharpElectricityPrice().multiply(sharpUsedElectricity).setScale(2, BigDecimal.ROUND_DOWN); + totalElectricityAmount = totalElectricityAmount.add(multiply); + } + + // 峰时段用电量 + BigDecimal peakUsedElectricity = orderDetail.getPeakUsedElectricity(); + if (peakUsedElectricity != null) { + // 计算该时段电费 + BigDecimal multiply = orderDetail.getPeakElectricityPrice().multiply(peakUsedElectricity).setScale(2, BigDecimal.ROUND_DOWN); + totalElectricityAmount = totalElectricityAmount.add(multiply); + } + + // 平时段用电量 + BigDecimal flatUsedElectricity = orderDetail.getFlatUsedElectricity(); + if (flatUsedElectricity != null) { + // 计算该时段电费 + BigDecimal multiply = orderDetail.getFlatElectricityPrice().multiply(flatUsedElectricity).setScale(2, BigDecimal.ROUND_DOWN); + totalElectricityAmount = totalElectricityAmount.add(multiply); + } + + // 谷时段用电量 + BigDecimal valleyUsedElectricity = orderDetail.getValleyUsedElectricity(); + if (valleyUsedElectricity != null) { + // 计算该时段电费 + BigDecimal multiply = orderDetail.getValleyElectricityPrice().multiply(valleyUsedElectricity).setScale(2, BigDecimal.ROUND_DOWN); + totalElectricityAmount = totalElectricityAmount.add(multiply); + } + + orderDetail.setTotalElectricityAmount(totalElectricityAmount); + orderDetail.setTotalServiceAmount(orderDetail.getTotalOrderAmount().subtract(totalElectricityAmount)); + } catch (Exception e) { + logger.info("发生异常", e); + } + } + return list; + } + + /** + * 余额支付 计算需要退回的金额 + * + * @param principalPay + * @param giftPay + * @param orderAmount + * @return + */ + private Map calculateReturnAmount(BigDecimal principalPay, BigDecimal giftPay, BigDecimal orderAmount) { + Map resultMap = Maps.newHashMap(); + + // 消费金额优先使用本金 + BigDecimal returnPrincipal = null; // 退回本金金额 + BigDecimal returnGift = null; // 退回赠送金额 + + // 余额支付 有3种情况 + if (principalPay != null && giftPay == null) { + // 只有本金支付 + BigDecimal subtract = principalPay.subtract(orderAmount); + if (subtract.compareTo(BigDecimal.ZERO) > 0) { + returnPrincipal = subtract; + } + } + if (principalPay == null && giftPay != null) { + // 只有赠送金额支付 + BigDecimal subtract = giftPay.subtract(orderAmount); + if (subtract.compareTo(BigDecimal.ZERO) > 0) { + returnGift = subtract; + } + } + if (principalPay != null && giftPay != null) { + // 本金+赠送支付 + BigDecimal subtract = principalPay.subtract(orderAmount); + if (subtract.compareTo(BigDecimal.ZERO) > 0) { + // 本金减掉订单金额后还有剩余,那就把剩余的退回,赠送原封不动退回 + returnPrincipal = subtract; + returnGift = giftPay; + } else if (subtract.compareTo(BigDecimal.ZERO) == 0) { + // 本金刚好够,那赠送金额支付的原封不动退回 + returnGift = giftPay; + } else { + returnGift = giftPay.subtract(subtract.negate()); + } + } + + resultMap.put("returnPrincipal", returnPrincipal); + resultMap.put("returnGift", returnGift); + return resultMap; + } + + /** + * 结算订单退款和用户余额退款调这个方法 + * + * @param dto + */ + @Override + public void weChatRefund(WeChatRefundDTO dto) { + // 退款有两种情况 1-订单结算退款 2-用户余额退款 + String refundType = dto.getRefundType(); + if (StringUtils.equals(refundType, "1")) { + WechatPayRefundResponse response = refundForOrder(dto); + logger.info("订单结算退款 result:{}", JSONObject.toJSONString(response)); + } else if (StringUtils.equals(refundType, "2")) { + WechatPayRefundResponse response = refundForBalance(dto); + logger.info("用户余额退款 result:{}", JSONObject.toJSONString(response)); + } else { + logger.warn("没有找到退款处理逻辑"); + } + } + + @Override + public void saveAbnormalOrder(TransactionRecordsData data) { + OrderAbnormalRecord record = new OrderAbnormalRecord(); + BeanUtils.copyBeanProp(record, data); + orderAbnormalRecordService.insertOrderAbnormalRecord(record); + + // 保存到订单主表 + // 订单基本信息 + PileInfoVO pileInfoVO = pileBasicInfoService.selectPileInfoBySn(data.getPileSn()); + if (pileInfoVO == null) { + return; + } + String orderCode = IdUtils.getOrderCode(); + OrderBasicInfo orderBasicInfo = OrderBasicInfo.builder().build(); + // 订单编号 + orderBasicInfo.setOrderCode(orderCode); + // 交易流水号 + orderBasicInfo.setTransactionCode(data.getTransactionCode()); + // 站点id + orderBasicInfo.setStationId(pileInfoVO.getStationId()); + // 充电桩编号 + orderBasicInfo.setPileSn(data.getPileSn()); + // 枪口号 + orderBasicInfo.setConnectorCode(data.getConnectorCode()); + // 枪口编号 + orderBasicInfo.setPileConnectorCode(pileInfoVO.getPileSn() + data.getConnectorCode()); + // 启动方式 + String transactionIdentifier = data.getTransactionIdentifier(); + String startMode = null; + // if (StringUtils.equals(transactionIdentifier, "01")) { + // startMode = StartModeEnum.APP.getValue(); + // } else if (StringUtils.equals(transactionIdentifier, "02")) { + // // 卡启动 + // startMode = StartModeEnum.CARD.getValue(); + // } + // 卡号 + if (StringUtils.isNotBlank(data.getLogicCard())) { + startMode = StartModeEnum.OFFLINE_CARD.getValue(); + orderBasicInfo.setLogicCard(data.getLogicCard()); + // 订单状态 (2023.4.6 要求改成“订单完成”) + orderBasicInfo.setOrderStatus(OrderStatusEnum.ORDER_COMPLETE.getValue()); + } else { + // 订单状态 可疑 + orderBasicInfo.setOrderStatus(OrderStatusEnum.SUSPICIOUS.getValue()); + } + orderBasicInfo.setStartMode(startMode); + // 支付方式 + orderBasicInfo.setPayMode(null); + // 支付金额 + orderBasicInfo.setPayAmount(null); + // 支付状态 + orderBasicInfo.setPayStatus(null); + // 支付时间 + orderBasicInfo.setPayTime(null); + // 订单金额 + orderBasicInfo.setOrderAmount(new BigDecimal(data.getConsumptionAmount())); + // 充电开始时间 + orderBasicInfo.setChargeStartTime(DateUtils.parseDate(data.getStartTime())); + // 充电结束时间 + orderBasicInfo.setChargeEndTime(DateUtils.parseDate(data.getEndTime())); + // 停止原因 + orderBasicInfo.setReason(data.getStopReasonMsg()); + // 结算时间 + orderBasicInfo.setSettlementTime(DateUtils.getNowDate()); + // 创建人 + orderBasicInfo.setCreateBy(data.getLogicCard()); + + + // 订单详情 + OrderDetail orderDetail = OrderDetail.builder().build(); + // 订单编号 + orderDetail.setOrderCode(orderCode); + // 订单总金额 + orderDetail.setTotalOrderAmount(new BigDecimal(data.getConsumptionAmount())); + // 总用电量 + orderDetail.setTotalUsedElectricity(new BigDecimal(data.getTotalElectricity())); + // 总服务费金额 + // orderDetail.setTotalServiceAmount(); + // 总电费金额 + // orderDetail.setTotalElectricityAmount(); + + // 尖时段金额 + orderDetail.setSharpAmount(new BigDecimal(data.getSharpAmount())); + // 尖时段单价 + orderDetail.setSharpPrice(new BigDecimal(data.getSharpPrice())); + // 尖时段服务费单价 + // orderDetail.setSharpServicePrice(); + // 尖时段电费单价 + // orderDetail.setSharpElectricityPrice(); + // 尖时段用电量 + orderDetail.setSharpUsedElectricity(new BigDecimal(data.getSharpUsedElectricity())); + + // 峰时段金额 + orderDetail.setPeakAmount(new BigDecimal(data.getPeakAmount())); + // 峰时段单价 + orderDetail.setPeakPrice(new BigDecimal(data.getPeakPrice())); + // 峰时段服务费单价 + // orderDetail.setPeakServicePrice(); + // 峰时段电费单价 + // orderDetail.setPeakElectricityPrice(); + // 峰时段用电量 + orderDetail.setPeakUsedElectricity(new BigDecimal(data.getPeakUsedElectricity())); + + // 平时段金额 + orderDetail.setFlatAmount(new BigDecimal(data.getFlatAmount())); + // 平时段单价 + orderDetail.setFlatPrice(new BigDecimal(data.getFlatPrice())); + // 平时段服务费单价 + // orderDetail.setFlatServicePrice(); + // 平时段电费单价 + // orderDetail.setFlatElectricityPrice(); + // 平时段用电量 + orderDetail.setFlatUsedElectricity(new BigDecimal(data.getFlatUsedElectricity())); + + + // 谷时段金额 + orderDetail.setValleyAmount(new BigDecimal(data.getValleyAmount())); + // 谷时段单价 + orderDetail.setValleyPrice(new BigDecimal(data.getValleyPrice())); + // 谷时段服务费单价 + // orderDetail.setValleyServicePrice(); + // 谷时段电费单价 + // orderDetail.setValleyElectricityPrice(); + // 谷时段用电量 + orderDetail.setValleyUsedElectricity(new BigDecimal(data.getValleyUsedElectricity())); + + if (data.getCreateTime() != null) { + orderBasicInfo.setCreateTime(data.getCreateTime()); + orderDetail.setCreateTime(data.getCreateTime()); + } + + OrderTransactionDTO createOrderTransactionDTO = OrderTransactionDTO.builder() + .orderBasicInfo(orderBasicInfo) + .orderDetail(orderDetail) + .build(); + pileTransactionService.doCreateOrder(createOrderTransactionDTO); + } + + /** + * 根据订单编号获取充电实时数据 时间倒序 + * 订单只有在充电中,才会把实时数据保存到redis + * + * @param transactionCode 订单编号 + * @return + */ + @Override + public List getChargingRealTimeData(String transactionCode) { + List resultList = Lists.newArrayList(); + if (StringUtils.isBlank(transactionCode)) { + return resultList; + } + // logger.info("transactionCode:{}", transactionCode); + String pileConnectorCode = transactionCode.substring(0, 16); + String redisKey = CacheConstants.PILE_REAL_TIME_MONITOR_DATA + pileConnectorCode + "_" + transactionCode; + // 拿到所有数据 + Map map = redisCache.hmget(redisKey); + if (map != null && !map.isEmpty()) { + List keyList = map.keySet().stream() + .map(x -> (String) x) + .sorted(Comparator.reverseOrder()) // 对keyList排序 时间倒序 + .collect(Collectors.toList()); + for (String s : keyList) { + Object o = map.get(s); + RealTimeMonitorData data = JSONObject.parseObject((String) o, RealTimeMonitorData.class); + resultList.add(data); + } + } else { + logger.debug("redis中没有实时数据了,去数据库查"); + // redis中为空,去查库 + OrderMonitorData orderMonitorData = orderMonitorDataService.selectByTransactionCode(transactionCode); + if (orderMonitorData != null) { + String monitorData = orderMonitorData.getMonitorData(); + List dataList = JSON.parseArray(monitorData, RealTimeMonitorData.class); + resultList.addAll(dataList); + } + } + return resultList; + } + + /** + * 首页订单数据展示 + * + * @param dto 首页信息查询dto + * @return + */ + @Override + public List getIndexOrderInfo(IndexQueryDTO dto) { + AuthorizedDeptVO authorizedMap = SecurityUtils.getAuthorizedMap(); + if (authorizedMap == null) { + return Lists.newArrayList(); + } + List stationIdList = Lists.newArrayList(); + List stationDeptIds = authorizedMap.getStationDeptIds(); + if (CollectionUtils.isNotEmpty(stationDeptIds)) { + // 根据部门id查询站点id + List list = pileStationInfoService.queryByStationDeptIds(stationDeptIds); + if (CollectionUtils.isNotEmpty(list)) { + stationIdList.addAll(list); + } + } + List merchantDeptIds = authorizedMap.getMerchantDeptIds(); + if (CollectionUtils.isNotEmpty(merchantDeptIds)) { + // 根据运营商部门id查询下面所有站点id + List list = pileMerchantInfoService.queryByMerchantDeptIds(merchantDeptIds); + if (CollectionUtils.isNotEmpty(list)) { + stationIdList.addAll(list); + } + } + dto.setStationIdList(stationIdList); + return orderBasicInfoMapper.getIndexOrderInfo(dto); + } + + /** + * 获取超过15分钟的待支付状态订单 + * + * @return + */ + @Override + public List getUnpaidOrderListOver15Min() { + Date now = DateUtils.addMinute(new Date(), -15); + String nowString = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, now); + return orderBasicInfoMapper.getUnpaidOrderListOver15Min(nowString); + } + + /** + * 根据orderId批量修改订单状态 + * + * @param orderIds + * @param orderStatus + */ + @Override + public void updateOrderStatusById(List orderIds, String orderStatus) { + orderBasicInfoMapper.updateOrderStatusById(orderIds, orderStatus); + } + + @Override + public int close15MinutesOfUnpaidOrders() { + List orderList = getUnpaidOrderListOver15Min(); + if (CollectionUtils.isNotEmpty(orderList)) { + List orderIdList = orderList.stream() + .map(x -> String.valueOf(x.getId())) + .collect(Collectors.toList()); + // 修改订单状态 + updateOrderStatusById(orderIdList, OrderStatusEnum.ORDER_CLOSE_TIMEOUT.getValue()); + + for (OrderBasicInfo orderBasicInfo : orderList) { + this.cleanCacheByOrderCode(orderBasicInfo.getOrderCode(), orderBasicInfo.getTransactionCode()); + } + } + return orderList.size(); + } + + /** + * 订单退款处理逻辑 + */ + private WechatPayRefundResponse refundForOrder(WeChatRefundDTO dto) { + // 查出来原来的支付信息 + WxpayCallbackRecord record = wxpayCallbackRecordService.selectByOrderCode(dto.getOrderCode()); + if (Objects.isNull(record)) { + logger.error("orderCode:{}, 订单退款处理逻辑, 查询订单微信支付记录为空!", dto.getOrderCode()); + throw new BusinessException(ReturnCodeEnum.CODE_REFUND_ORDER_CALLBACK_RECORD_ERROR); + } + + // 判断支付金额和退款金额 + int refundAmountInt = dto.getRefundAmount().multiply(new BigDecimal("100")).intValue(); + int payerTotalInt = Integer.parseInt(record.getPayerTotal()); + if (refundAmountInt > payerTotalInt) { + logger.error("订单号:{}, 退款金额:{}(分),大于可退金额{}(分), 抛出异常", dto.getOrderCode(), refundAmountInt, payerTotalInt); + throw new BusinessException(ReturnCodeEnum.CODE_REFUND_ORDER_AMOUNT_ERROR); + } + + // 调微信退款接口 + WechatPayRefundRequest request = new WechatPayRefundRequest(); + request.setTransaction_id(record.getTransactionId()); // 微信支付单号 + request.setOut_trade_no(record.getOutTradeNo()); // 商户订单号 + // 生成退款单号 + request.setOut_refund_no(SnowflakeIdWorker.getSnowflakeId()); // 商户退款单号 + request.setNotify_url(WeChatPayParameter.refundNotifyUrl); // 回调接口 + WechatPayRefundRequest.Amount amount = new WechatPayRefundRequest.Amount(); + amount.setRefund(refundAmountInt); // 退款金额 + amount.setTotal(payerTotalInt); // 原订单金额 + request.setAmount(amount); + request.setReason("订单结算退款"); + request.setFunds_account("AVAILABLE"); + try { + return wechatPayService.ApplyForWechatPayRefundV3(request); + } catch (JsonProcessingException e) { + logger.error("调微信退款API发生异常", e); + } + return null; + } + + /** + * 余额退款处理逻辑 + * + * @param dto + */ + private WechatPayRefundResponse refundForBalance(WeChatRefundDTO dto) { + // 查会员余额 + MemberVO memberVO = memberBasicInfoService.queryMemberInfoByMemberId(dto.getMemberId()); + if (memberVO == null) { + throw new BusinessException(ReturnCodeEnum.CODE_SELECT_MEMBER_NULL_ERROR); + } + // 校验退款金额 + BigDecimal principalBalance = memberVO.getPrincipalBalance(); + BigDecimal refundAmount = dto.getRefundAmount(); + if (refundAmount.compareTo(principalBalance) > 0) { + throw new BusinessException(ReturnCodeEnum.CODE_REFUND_MEMBER_BALANCE_ERROR); + } + // 退款金额 元转分 123 + int refundTotalCents = refundAmount.multiply(new BigDecimal(100)).intValue(); + + // 查询用户充值余额订单 过滤掉已经退款的充值订单 refundableOrder + List recordList = queryRefundableOrder(dto.getMemberId()); + + // 也许需要多笔支付订单才够退款 + List requestList = Lists.newArrayList(); + WechatPayRefundRequest request; + for (RefundableWxPayOrderData record : recordList) { + int refundableTotal = record.getRefundableAmount().intValue(); // 该笔支付订单的可退金额,单位分 + int payerTotal = record.getPayerAmount().intValue(); // 该笔支付订单的支付金额,单位分 + // 用户申请退款金额-可退金额 + refundTotalCents = refundTotalCents - refundableTotal; // 123 - 100 + request = new WechatPayRefundRequest(); + request.setTransaction_id(record.getTransactionId()); // 微信支付单号 + request.setOut_trade_no(record.getOutTradeNo()); // 商户订单号 + request.setOut_refund_no(SnowflakeIdWorker.getSnowflakeId()); // 商户退款单号 + request.setNotify_url(WeChatPayParameter.refundNotifyUrl); // 回调接口 + request.setReason("用户余额退款"); + request.setFunds_account("AVAILABLE"); + if (refundTotalCents > 0) { + // 如果大于0说明,这笔单退完也不够 + WechatPayRefundRequest.Amount amount = new WechatPayRefundRequest.Amount(); + amount.setRefund(refundableTotal); // 退款金额 + amount.setTotal(payerTotal); // 原订单金额 + request.setAmount(amount); + requestList.add(request); + } else { + // 如果小于0,这笔单退一部分 + // 生成退款单号 + WechatPayRefundRequest.Amount amount = new WechatPayRefundRequest.Amount(); + // 部分退 + int i = refundableTotal + refundTotalCents; + amount.setRefund(i); // 退款金额 + amount.setTotal(payerTotal); // 原订单金额 + request.setAmount(amount); + requestList.add(request); + break; + } + } + // 调微信退款api + if (CollectionUtils.isNotEmpty(requestList)) { + for (WechatPayRefundRequest refundRequest : requestList) { + try { + return wechatPayService.ApplyForWechatPayRefundV3(refundRequest); + // logger.info("调微信退款API退款====={}", JSONObject.toJSONString(refundRequest)); + } catch (Exception e) { + logger.error("调微信退款API发生异常", e); + } + } + } + return null; + } + + private List queryRefundableOrder(String memberId) { + List resultList = Lists.newArrayList(); + // 查询最近一年余额充值订单 + List recordList = wxpayCallbackRecordService.queryBalanceRechargeRecordOfTheLatestYear(memberId); + if (CollectionUtils.isEmpty(recordList)) { + return resultList; + } + // 拿到微信商户单号list + List outTradeNoList = recordList.stream() + .map(WxpayCallbackRecord::getOutTradeNo) + .collect(Collectors.toList()); + List wxpayRefundCallbacks = wxpayRefundCallbackService.selectWxpayRefundCallbackList(outTradeNoList); + if (CollectionUtils.isEmpty(wxpayRefundCallbacks)) { + // 退款记录为空,表示没有一笔退款 + for (WxpayCallbackRecord wxpayCallbackRecord : recordList) { + resultList.add( + RefundableWxPayOrderData.builder() + .outTradeNo(wxpayCallbackRecord.getOutTradeNo()) + .transactionId(wxpayCallbackRecord.getTransactionId()) + .payerAmount(new BigDecimal(wxpayCallbackRecord.getPayerTotal())) + .refundableAmount(new BigDecimal(wxpayCallbackRecord.getPayerTotal())) + .build() + ); + } + return resultList; + } + + // 退款记录转map key:outTradeNo value:退款记录 + Map> refundMap = wxpayRefundCallbacks.stream() + .collect(Collectors.groupingBy(WxpayRefundCallback::getOutTradeNo)); + for (WxpayCallbackRecord wxpayCallbackRecord : recordList) { + List refundCallbackList = refundMap.get(wxpayCallbackRecord.getOutTradeNo()); + if (CollectionUtils.isEmpty(refundCallbackList)) { + // 这笔单没有申请过退款 + resultList.add( + RefundableWxPayOrderData.builder() + .outTradeNo(wxpayCallbackRecord.getOutTradeNo()) + .transactionId(wxpayCallbackRecord.getTransactionId()) + .payerAmount(new BigDecimal(wxpayCallbackRecord.getPayerTotal())) + .refundableAmount(new BigDecimal(wxpayCallbackRecord.getPayerTotal())) + .build() + ); + continue; + } + // 支付订单产生过退款 + BigDecimal refundTotal = refundCallbackList.stream() + .map(x -> new BigDecimal(x.getAmountRefund())) + .reduce(BigDecimal::add) + .get(); + + // 可退金额 + BigDecimal subtract = new BigDecimal(wxpayCallbackRecord.getPayerTotal()).subtract(refundTotal); + if (subtract.compareTo(BigDecimal.ZERO) > 0) { + resultList.add( + RefundableWxPayOrderData.builder() + .outTradeNo(wxpayCallbackRecord.getOutTradeNo()) + .transactionId(wxpayCallbackRecord.getTransactionId()) + .payerAmount(new BigDecimal(wxpayCallbackRecord.getPayerTotal())) + .refundableAmount(subtract) + .build() + ); + } + } + return resultList; + } + + /** + * 通过订单号查询订单详情 + * + * @param orderCode 订单号 + * @return 订单详情 + */ + @Override + public OrderDetail getOrderDetailByOrderCode(String orderCode) { + return orderBasicInfoMapper.getOrderDetailByOrderCode(orderCode); + } + + @Override + public List getOrderDetailList(List orderCodes) { + return orderBasicInfoMapper.getOrderDetailList(orderCodes); + } + + /** + * 通过会员Id和订单状态查询订单信息 + * + * @param memberId 会员id + * @param orderStatusList 订单状态集合 + * @return + */ + @Override + public List getListByMemberIdAndOrderStatus(String memberId, List orderStatusList) { + return getListByMemberIdAndOrderStatus(memberId, orderStatusList, null, null); + } + + @Override + public List getListByMemberIdAndOrderStatus(String memberId, List orderStatusList, LocalDateTime dateTime) { + return getListByMemberIdAndOrderStatus(memberId, orderStatusList, dateTime, null); + } + + @Override + public List getListByMemberIdAndOrderStatus(String memberId, List orderStatusList, LocalDateTime dateTime, String stationId) { + return orderBasicInfoMapper.getListByMemberIdAndOrderStatus(memberId, orderStatusList, dateTime, stationId); + } + + @Override + public List getListByOrderCodes(List orderCodes) { + return orderBasicInfoMapper.getListByOrderCodes(orderCodes); + } + + /** + * 个人桩查询充电数据 + * + * @param dto + * @return + */ + @Override + public List getAccumulativeInfo(QueryPersonPileDTO dto) { + return orderBasicInfoMapper.getAccumulativeInfo(dto); + } + + /** + * 修改订单状态为异常(桩离线时调用) + * + * @param pileSn + */ + @Override + public void updateOrderStatusAsAbnormal(String pileSn) { + // 先从redis判断是否有订单再进行查询 + if (Objects.isNull(redisCache.getCacheObject(CacheConstants.PILE_IS_CHARGING + pileSn))) { + return; + } + // 将此桩正在进行充电的订单状态改为 异常 + List orderListVOS = selectChargingOrder(pileSn); + if (CollectionUtils.isEmpty(orderListVOS)) { + return; + } + for (OrderListVO orderListVO : orderListVOS) { + if (StringUtils.equals(orderListVO.getOrderStatus(), OrderStatusEnum.IN_THE_CHARGING.getValue())) { + // 修改数据库订单状态 + OrderBasicInfo info = OrderBasicInfo.builder() + .id(Long.parseLong(orderListVO.getId())) + .orderStatus(OrderStatusEnum.ABNORMAL.getValue()) + .build(); + updateOrderBasicInfo(info); + logger.info("充电桩:{}退出, 修改充电桩正在充电的订单状态为异常, orderCode: {}", pileSn, orderListVO.getOrderCode()); + } + } + } + + @Override + public List getAppointmentOrder(LocalDateTime dateTime) { + return orderBasicInfoMapper.getAppointmentOrder(dateTime); + } + + /** + * 生成订单 返回交易流水号 + * + * @param dto + * @return + */ + @Override + public Map generateOrderByCard(GenerateOrderDTO dto) { + String pileSn = dto.getPileSn(); + String connectorCode = dto.getConnectorCode(); + PileAuthCard pileAuthCardInfo = dto.getPileAuthCardInfo(); + // 通过memberId获取账户余额 + MemberVO memberVO = memberBasicInfoService.queryMemberInfoByMemberId(pileAuthCardInfo.getMemberId()); + if (memberVO == null) { + throw new BusinessException(ReturnCodeEnum.CODE_GET_MEMBER_ACCOUNT_AMOUNT_ERROR); + } + BigDecimal totalAccountAmount = memberVO.getTotalAccountAmount(); + if (totalAccountAmount.compareTo(BigDecimal.ZERO) <= 0) { + throw new BusinessException(ReturnCodeEnum.CODE_BALANCE_IS_INSUFFICIENT); + } + + String transactionCode = IdUtils.generateTransactionCode(pileSn, connectorCode); + // 通过桩号查询所属站点 + PileBasicInfo pileBasicInfo = pileBasicInfoService.selectPileBasicInfoBySN(pileSn); + Long stationId = pileBasicInfo.getStationId(); + // 自动余额全部支付订单 个人桩站点不计费 + + + // 将此订单信息存入订单表 + String orderCode = IdUtils.getOrderCode(); + // 订单基本信息 + OrderBasicInfo orderBasicInfo = OrderBasicInfo.builder() + .orderCode(orderCode) + .transactionCode(transactionCode) + .orderStatus(OrderStatusEnum.NOT_START.getValue()) + .memberId(memberVO.getMemberId()) + .stationId(String.valueOf(stationId)) + .pileSn(pileSn) + .connectorCode(connectorCode) + .pileConnectorCode(pileSn + connectorCode) + .logicCard(pileAuthCardInfo.getLogicCard()) + .startMode(StartModeEnum.AUTH_CARD.getValue()) + .payStatus(Constants.ONE) + .payAmount(totalAccountAmount) + .payTime(new Date()) + .payMode(OrderPayModeEnum.PAYMENT_OF_BALANCE.getValue()) + .orderAmount(BigDecimal.ZERO) + .build(); + // 根据桩编码查询当前计费模板 + BillingTemplateVO billingTemplateVO = pileBillingTemplateService.selectBillingTemplateDetailByPileSn(pileSn); + // 订单详情 + OrderDetail orderDetail = OrderDetail.builder() + .orderCode(orderCode) + .sharpElectricityPrice(billingTemplateVO.getSharpElectricityPrice()) + .sharpServicePrice(billingTemplateVO.getSharpServicePrice()) + .peakElectricityPrice(billingTemplateVO.getPeakElectricityPrice()) + .peakServicePrice(billingTemplateVO.getPeakServicePrice()) + .flatElectricityPrice(billingTemplateVO.getFlatElectricityPrice()) + .flatServicePrice(billingTemplateVO.getFlatServicePrice()) + .valleyElectricityPrice(billingTemplateVO.getValleyElectricityPrice()) + .valleyServicePrice(billingTemplateVO.getValleyServicePrice()) + .build(); + + OrderTransactionDTO createOrderTransactionDTO = OrderTransactionDTO.builder() + .orderBasicInfo(orderBasicInfo) + .orderDetail(orderDetail) + .build(); + pileTransactionService.doCreateOrder(createOrderTransactionDTO); + + // 将卡状态改为启动锁定 + PileAuthCard pileAuthCard = PileAuthCard.builder() + .id(pileAuthCardInfo.getId()) + .logicCard(pileAuthCardInfo.getLogicCard()) + .status("2") + .build(); + pileAuthCardService.updatePileAuthCard(pileAuthCard); + + // 组装结果集 + Map resultMap = Maps.newHashMap(); + resultMap.put("orderCode", orderBasicInfo.getOrderCode()); + resultMap.put("transactionCode", orderBasicInfo.getTransactionCode()); + resultMap.put("accountBalance", totalAccountAmount); + return resultMap; + } + + /** + * 联联平台 获取累计数据用 + * + * @param dto + * @return + */ + @Override + public List getAccumulativeInfoForLianLian(QueryStationInfoDTO dto) { + return orderBasicInfoMapper.getAccumulativeInfoForLianLian(dto); + } + + /** + * 联联平台生成订单 + * + * @param dto + * @return + */ + @Override + public Map generateOrderForLianLian(QueryStartChargeDTO dto) { + // 联联平台生成订单 + String orderCode = dto.getStartChargeSeq(); + String pileConnectorCode = dto.getConnectorID(); + String pileSn = StringUtils.substring(pileConnectorCode, 0, 14); + String connectorCode = StringUtils.substring(pileConnectorCode, 14, 16); + + + String transactionCode = IdUtils.generateTransactionCode(pileSn, connectorCode); + + // 通过桩号查询所属站点 + PileBasicInfo pileBasicInfo = pileBasicInfoService.selectPileBasicInfoBySN(pileSn); + Long stationId = pileBasicInfo.getStationId(); + + + // 将此订单信息存入订单表 + // 订单基本信息 + OrderBasicInfo orderBasicInfo = OrderBasicInfo.builder() + .orderCode(orderCode) + .transactionCode(transactionCode) + .orderStatus(OrderStatusEnum.NOT_START.getValue()) + // .memberId(memberVO.getMemberId()) // 会员memberId + .stationId(String.valueOf(stationId)) + .pileSn(pileSn) + .connectorCode(connectorCode) + .pileConnectorCode(pileConnectorCode) + // .logicCard(pileAuthCardInfo.getLogicCard()) // 卡号 + .startMode(StartModeEnum.LIAN_LIAN.getValue()) + .payStatus(Constants.ONE) + // .payAmount(totalAccountAmount) // 支付金额 + .payTime(new Date()) + // .payMode(PayModeEnum.PAYMENT_OF_BALANCE.getValue()) // 支付方式 + .orderAmount(BigDecimal.ZERO) + .build(); + // 根据桩编码查询当前计费模板 + BillingTemplateVO billingTemplateVO = pileBillingTemplateService.selectBillingTemplateDetailByPileSn(pileSn); + // 订单详情 + OrderDetail orderDetail = OrderDetail.builder() + .orderCode(orderCode) + .sharpElectricityPrice(billingTemplateVO.getSharpElectricityPrice()) + .sharpServicePrice(billingTemplateVO.getSharpServicePrice()) + .peakElectricityPrice(billingTemplateVO.getPeakElectricityPrice()) + .peakServicePrice(billingTemplateVO.getPeakServicePrice()) + .flatElectricityPrice(billingTemplateVO.getFlatElectricityPrice()) + .flatServicePrice(billingTemplateVO.getFlatServicePrice()) + .valleyElectricityPrice(billingTemplateVO.getValleyElectricityPrice()) + .valleyServicePrice(billingTemplateVO.getValleyServicePrice()) + .build(); + + OrderTransactionDTO createOrderTransactionDTO = OrderTransactionDTO.builder() + .orderBasicInfo(orderBasicInfo) + .orderDetail(orderDetail) + .build(); + pileTransactionService.doCreateOrder(createOrderTransactionDTO); + + // 组装结果集 + Map resultMap = Maps.newHashMap(); + resultMap.put("orderCode", orderBasicInfo.getOrderCode()); + resultMap.put("transactionCode", orderBasicInfo.getTransactionCode()); + resultMap.put("orderBasicInfo", orderBasicInfo); + resultMap.put("orderDetail", orderDetail); + // resultMap.put("accountBalance", totalAccountAmount); + + return resultMap; + } + + @Override + public List queryOrderAmountDetail(List orderCodes) { + List orderDetailList = getOrderDetailList(orderCodes); + if (CollectionUtils.isEmpty(orderDetailList)) { + return Lists.newArrayList(); + } + List resultList = Lists.newArrayList(); + OrderAmountDetailVO vo = null; + for (OrderDetail orderDetail : orderDetailList) { + vo = new OrderAmountDetailVO(); + BeanUtils.copyBeanProp(vo, orderDetail); + resultList.add(vo); + } + return resultList; + } + + /** + * 订单详情 转换为各个时段的详情 + */ + @Override + public List transformPeriodAmountByOrderDetail(OrderDetail orderDetail) { + // 尖时段 + OrderPeriodAmountVO sharp = new OrderPeriodAmountVO(); + sharp.setPeriodType(BillingTimeEnum.SHARP.getLabel()); + sharp.setElectricityPrice(orderDetail.getSharpElectricityPrice()); + sharp.setServicePrice(orderDetail.getSharpServicePrice()); + BigDecimal sharpUsedElectricity = orderDetail.getSharpUsedElectricity() == null ? BigDecimal.ZERO : orderDetail.getSharpUsedElectricity(); + sharp.setUsedElectricity(sharpUsedElectricity); + sharp.setElectricityAmount(sharp.getElectricityPrice().multiply(sharp.getUsedElectricity()).setScale(2, BigDecimal.ROUND_DOWN)); + sharp.setServiceAmount(sharp.getServicePrice().multiply(sharp.getUsedElectricity()).setScale(2, BigDecimal.ROUND_DOWN)); + + // 峰时段 + OrderPeriodAmountVO peak = new OrderPeriodAmountVO(); + peak.setPeriodType(BillingTimeEnum.PEAK.getLabel()); + peak.setElectricityPrice(orderDetail.getPeakElectricityPrice()); + peak.setServicePrice(orderDetail.getPeakServicePrice()); + BigDecimal peakUsedElectricity = orderDetail.getPeakUsedElectricity() == null ? BigDecimal.ZERO : orderDetail.getPeakUsedElectricity(); + peak.setUsedElectricity(peakUsedElectricity); + peak.setElectricityAmount(peak.getElectricityPrice().multiply(peak.getUsedElectricity()).setScale(2, BigDecimal.ROUND_DOWN)); + peak.setServiceAmount(peak.getServicePrice().multiply(peak.getUsedElectricity()).setScale(2, BigDecimal.ROUND_DOWN)); + + // 平时段 + OrderPeriodAmountVO flat = new OrderPeriodAmountVO(); + flat.setPeriodType(BillingTimeEnum.FLAT.getLabel()); + flat.setElectricityPrice(orderDetail.getFlatElectricityPrice()); + flat.setServicePrice(orderDetail.getFlatServicePrice()); + BigDecimal flatUsedElectricity = orderDetail.getFlatUsedElectricity() == null ? BigDecimal.ZERO : orderDetail.getFlatUsedElectricity(); + flat.setUsedElectricity(flatUsedElectricity); + flat.setElectricityAmount(flat.getElectricityPrice().multiply(flat.getUsedElectricity()).setScale(2, BigDecimal.ROUND_DOWN)); + flat.setServiceAmount(flat.getServicePrice().multiply(flat.getUsedElectricity()).setScale(2, BigDecimal.ROUND_DOWN)); + + // 谷时段 + OrderPeriodAmountVO valley = new OrderPeriodAmountVO(); + valley.setPeriodType(BillingTimeEnum.VALLEY.getLabel()); + valley.setElectricityPrice(orderDetail.getValleyElectricityPrice()); + valley.setServicePrice(orderDetail.getValleyServicePrice()); + BigDecimal valleyUsedElectricity = orderDetail.getValleyUsedElectricity() == null ? BigDecimal.ZERO : orderDetail.getValleyUsedElectricity(); + valley.setUsedElectricity(valleyUsedElectricity); + valley.setElectricityAmount(valley.getElectricityPrice().multiply(valley.getUsedElectricity()).setScale(2, BigDecimal.ROUND_DOWN)); + valley.setServiceAmount(valley.getServicePrice().multiply(valley.getUsedElectricity()).setScale(2, BigDecimal.ROUND_DOWN)); + + return Lists.newArrayList(sharp, peak, flat, valley); + } + + @Override + public String tempUpdateVirtualAmount(QueryOrderDTO dto) { + dto.setOrderStatus(OrderStatusEnum.ORDER_COMPLETE.getValue()); + List orderListVOS = orderBasicInfoMapper.selectOrderBasicInfoList(dto); + if (CollectionUtils.isEmpty(orderListVOS)) { + return "没有订单需要修改"; + } + tempUpdateVirtualAmount(orderListVOS); + return "共修改" + orderListVOS.size() + "条订单数据"; + } }