mirror of
https://codeup.aliyun.com/67c68d4e484ca2f0a13ac3c1/ydc/jsowell-charger-web.git
synced 2026-04-21 03:25:12 +08:00
优化结算订单逻辑
This commit is contained in:
@@ -149,6 +149,8 @@ public abstract class AbstractProgramLogic implements InitializingBean {
|
||||
*/
|
||||
public abstract void settleOrder(TransactionRecordsData data, OrderBasicInfo orderBasicInfo);
|
||||
|
||||
public abstract void settleOrderV2(TransactionRecordsData data, OrderBasicInfo orderBasicInfo);
|
||||
|
||||
/**
|
||||
* 电单车结算逻辑
|
||||
* @param message
|
||||
@@ -463,6 +465,198 @@ public abstract class AbstractProgramLogic implements InitializingBean {
|
||||
return orderDetail;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新订单主表和订单详情中的各种金额
|
||||
* 只交易记录中的耗电量, 其他金额都以平台计算为主
|
||||
* @param data 交易记录数据
|
||||
* @param orderBasicInfo 订单基础信息
|
||||
* @param orderDetail 订单详情
|
||||
*/
|
||||
public void updateOrderBasicInfoAndOrderDetail(TransactionRecordsData data, OrderBasicInfo orderBasicInfo, OrderDetail orderDetail) {
|
||||
// 订单编号
|
||||
String orderCode = orderBasicInfo.getOrderCode();
|
||||
// 订单支付金额
|
||||
BigDecimal payAmount = orderBasicInfo.getPayAmount();
|
||||
// data中的消费金额 精确到小数点后四位,包含电费、 服务费
|
||||
BigDecimal dataOrderAmount = new BigDecimal(data.getConsumptionAmount()).setScale(2, RoundingMode.HALF_UP);
|
||||
// data中的总用电量
|
||||
BigDecimal totalElectricity = new BigDecimal(StringUtils.isBlank(data.getTotalElectricity()) ? Constants.ZERO : data.getTotalElectricity());
|
||||
// 总电费金额
|
||||
BigDecimal totalElectricityAmount = BigDecimal.ZERO;
|
||||
// 总服务费金额
|
||||
BigDecimal totalServiceAmount = BigDecimal.ZERO;
|
||||
|
||||
// 尖时段用电量
|
||||
BigDecimal sharpUsedElectricity = StringUtils.isNotBlank(data.getSharpUsedElectricity()) ? new BigDecimal(data.getSharpUsedElectricity()) : BigDecimal.ZERO;
|
||||
if (sharpUsedElectricity.compareTo(BigDecimal.ZERO) > 0) {
|
||||
// 该时段电费单价
|
||||
BigDecimal electricityPrice = orderDetail.getSharpElectricityPrice();
|
||||
// 计算该时段电费 = 电费单价 x 用电量
|
||||
BigDecimal electricityAmount = electricityPrice.multiply(sharpUsedElectricity).setScale(2, RoundingMode.DOWN);
|
||||
// 该时段服务费单价
|
||||
BigDecimal servicePrice = orderDetail.getSharpServicePrice();
|
||||
// 计算该时段服务费 = 服务费单价 x 用电量
|
||||
BigDecimal serviceAmount = servicePrice.multiply(sharpUsedElectricity).setScale(2, RoundingMode.DOWN);
|
||||
// 汇总
|
||||
totalElectricityAmount = totalElectricityAmount.add(electricityAmount);
|
||||
totalServiceAmount = totalServiceAmount.add(serviceAmount);
|
||||
// 该时段单价 = 电费单价 + 服务费单价
|
||||
BigDecimal price = electricityPrice.add(servicePrice);
|
||||
// 该时段金额 = 该时段电费 + 该时段服务费
|
||||
BigDecimal amount = electricityAmount.add(serviceAmount);
|
||||
orderDetail.setSharpPrice(price);
|
||||
orderDetail.setSharpAmount(amount);
|
||||
logger.info("updateOrderBasicInfoAndOrderDetail:【{}】, 当前为尖时段, 时段单价:{}(电费单价:{}+服务费单价:{}), 耗电量:{}, 平台计算该时段消费金额:{}(电费:{}+服务费:{}), 桩传的单价:{}, 桩传的金额:{}",
|
||||
orderCode, price, electricityPrice, servicePrice, sharpUsedElectricity, amount, electricityAmount, serviceAmount, data.getSharpPrice(), data.getSharpAmount());
|
||||
}
|
||||
|
||||
// 峰时段用电量
|
||||
BigDecimal peakUsedElectricity = StringUtils.isNotBlank(data.getPeakUsedElectricity()) ? new BigDecimal(data.getPeakUsedElectricity()) : BigDecimal.ZERO;
|
||||
if (peakUsedElectricity.compareTo(BigDecimal.ZERO) > 0) {
|
||||
// 该时段电费单价
|
||||
BigDecimal electricityPrice = orderDetail.getPeakElectricityPrice();
|
||||
// 计算该时段电费 = 电费单价 x 用电量
|
||||
BigDecimal electricityAmount = electricityPrice.multiply(peakUsedElectricity).setScale(2, RoundingMode.DOWN);
|
||||
// 该时段服务费单价
|
||||
BigDecimal servicePrice = orderDetail.getPeakServicePrice();
|
||||
// 计算该时段服务费 = 服务费单价 x 用电量
|
||||
BigDecimal serviceAmount = servicePrice.multiply(peakUsedElectricity).setScale(2, RoundingMode.DOWN);
|
||||
// 汇总
|
||||
totalElectricityAmount = totalElectricityAmount.add(electricityAmount);
|
||||
totalServiceAmount = totalServiceAmount.add(serviceAmount);
|
||||
// 该时段单价 = 电费单价 + 服务费单价
|
||||
BigDecimal price = electricityPrice.add(servicePrice);
|
||||
// 该时段金额 = 该时段电费 + 该时段服务费
|
||||
BigDecimal amount = electricityAmount.add(serviceAmount);
|
||||
orderDetail.setPeakPrice(price);
|
||||
orderDetail.setPeakAmount(amount);
|
||||
logger.info("updateOrderBasicInfoAndOrderDetail:【{}】, 当前为峰时段, 时段单价:{}(电费单价:{}+服务费单价:{}), 耗电量:{}, 平台计算该时段消费金额:{}(电费:{}+服务费:{}), 桩传的单价:{}, 桩传的金额:{}",
|
||||
orderCode, price, electricityPrice, servicePrice, peakUsedElectricity, amount, electricityAmount, serviceAmount, data.getPeakPrice(), data.getPeakAmount());
|
||||
}
|
||||
|
||||
// 平时段用电量
|
||||
BigDecimal flatUsedElectricity = StringUtils.isNotBlank(data.getFlatUsedElectricity()) ? new BigDecimal(data.getFlatUsedElectricity()) : BigDecimal.ZERO;
|
||||
if (flatUsedElectricity.compareTo(BigDecimal.ZERO) > 0) {
|
||||
// 该时段电费单价
|
||||
BigDecimal electricityPrice = orderDetail.getFlatElectricityPrice();
|
||||
// 计算该时段电费 = 电费单价 x 用电量
|
||||
BigDecimal electricityAmount = electricityPrice.multiply(flatUsedElectricity).setScale(2, RoundingMode.DOWN);
|
||||
// 该时段服务费单价
|
||||
BigDecimal servicePrice = orderDetail.getFlatServicePrice();
|
||||
// 计算该时段服务费 = 服务费单价 x 用电量
|
||||
BigDecimal serviceAmount = servicePrice.multiply(flatUsedElectricity).setScale(2, RoundingMode.DOWN);
|
||||
// 汇总
|
||||
totalElectricityAmount = totalElectricityAmount.add(electricityAmount);
|
||||
totalServiceAmount = totalServiceAmount.add(serviceAmount);
|
||||
// 该时段单价 = 电费单价 + 服务费单价
|
||||
BigDecimal price = electricityPrice.add(servicePrice);
|
||||
// 该时段金额 = 该时段电费 + 该时段服务费
|
||||
BigDecimal amount = electricityAmount.add(serviceAmount);
|
||||
orderDetail.setFlatPrice(price);
|
||||
orderDetail.setFlatAmount(amount);
|
||||
logger.info("updateOrderBasicInfoAndOrderDetail:【{}】, 当前为平时段, 时段单价:{}(电费单价:{}+服务费单价:{}), 耗电量:{}, 平台计算该时段消费金额:{}(电费:{}+服务费:{}), 桩传的单价:{}, 桩传的金额:{}",
|
||||
orderCode, price, electricityPrice, servicePrice, flatUsedElectricity, amount, electricityAmount, serviceAmount, data.getFlatPrice(), data.getFlatAmount());
|
||||
}
|
||||
|
||||
// 谷时段用电量
|
||||
BigDecimal valleyUsedElectricity = StringUtils.isNotBlank(data.getValleyUsedElectricity()) ? new BigDecimal(data.getValleyUsedElectricity()) : BigDecimal.ZERO;
|
||||
if (valleyUsedElectricity.compareTo(BigDecimal.ZERO) > 0) {
|
||||
// 该时段电费单价
|
||||
BigDecimal electricityPrice = orderDetail.getValleyElectricityPrice();
|
||||
// 计算该时段电费 = 电费单价 x 用电量
|
||||
BigDecimal electricityAmount = electricityPrice.multiply(valleyUsedElectricity).setScale(2, RoundingMode.DOWN);
|
||||
// 该时段服务费单价
|
||||
BigDecimal servicePrice = orderDetail.getValleyServicePrice();
|
||||
// 计算该时段服务费 = 服务费单价 x 用电量
|
||||
BigDecimal serviceAmount = servicePrice.multiply(valleyUsedElectricity).setScale(2, RoundingMode.DOWN);
|
||||
// 汇总
|
||||
totalElectricityAmount = totalElectricityAmount.add(electricityAmount);
|
||||
totalServiceAmount = totalServiceAmount.add(serviceAmount);
|
||||
// 该时段单价 = 电费单价 + 服务费单价
|
||||
BigDecimal price = electricityPrice.add(servicePrice);
|
||||
// 该时段金额 = 该时段电费 + 该时段服务费
|
||||
BigDecimal amount = electricityAmount.add(serviceAmount);
|
||||
orderDetail.setValleyPrice(price);
|
||||
orderDetail.setValleyAmount(amount);
|
||||
logger.info("updateOrderBasicInfoAndOrderDetail:【{}】, 当前为谷时段, 时段单价:{}(电费单价:{}+服务费单价:{}), 耗电量:{}, 平台计算该时段消费金额:{}(电费:{}+服务费:{}), 桩传的单价:{}, 桩传的金额:{}",
|
||||
orderCode, price, electricityPrice, servicePrice, valleyUsedElectricity, amount, electricityAmount, serviceAmount, data.getValleyPrice(), data.getValleyAmount());
|
||||
}
|
||||
// 尖峰平谷用电量汇总
|
||||
BigDecimal sumUsedElectricity = sharpUsedElectricity.add(peakUsedElectricity).add(flatUsedElectricity).add(valleyUsedElectricity);
|
||||
// 平台计算的总消费金额 平台计算总电费金额 + 平台计算总服务费金额
|
||||
BigDecimal computeTotalAmount = totalElectricityAmount.add(totalServiceAmount);
|
||||
|
||||
// 如果算出来的 电费金额 + 服务费金额 != 总消费金额,则电费金额等于总消费金额 - 服务费金额
|
||||
if (computeTotalAmount.compareTo(dataOrderAmount) != 0) {
|
||||
// 2025年3月26日15点50分, 订单金额以平台计算为主,所以注释掉, 并打印日志说明
|
||||
// totalElectricityAmount = dataOrderAmount.subtract(totalServiceAmount);
|
||||
logger.info("updateOrderBasicInfoAndOrderDetail平台计算出电费金额:{}, 服务费金额:{}, 汇总:{}, 交易记录传来的金额:{}", totalElectricityAmount, totalServiceAmount, computeTotalAmount, dataOrderAmount);
|
||||
dataOrderAmount = computeTotalAmount;
|
||||
}
|
||||
|
||||
// 虚拟金额 指订单消费中不参与结算的部分
|
||||
BigDecimal virtualAmount = BigDecimal.ZERO;
|
||||
if (OrderPayModeEnum.PAYMENT_OF_WHITELIST.getValue().equals(orderBasicInfo.getPayMode())
|
||||
|| OrderPayModeEnum.PAYMENT_OF_PRINCIPAL_BALANCE.getValue().equals(orderBasicInfo.getPayMode())) {
|
||||
// 白名单支付所消费的金额,都属于虚拟金额,不参与结算对账
|
||||
virtualAmount = new BigDecimal(dataOrderAmount.toString());
|
||||
logger.info("updateOrderBasicInfoAndOrderDetail结算订单:【{}】, 虚拟金额为:{}, 白名单支付所消费的金额,都属于虚拟金额,不参与结算对账", orderCode, virtualAmount);
|
||||
}
|
||||
|
||||
// 有时候充电桩到达金额停止充电会多出一点金额,比如实际需要充50元的电,充电桩传来的消费金额为50.01元,在后台记录的时候需要舍去
|
||||
if (dataOrderAmount.compareTo(payAmount) > 0) {
|
||||
logger.info("updateOrderBasicInfoAndOrderDetail结算订单:【{}】充电桩传来的消费金额:【{}】大于付款金额:【{}】, 消费金额设置为付款金额相等数据", orderCode, dataOrderAmount, payAmount);
|
||||
dataOrderAmount = payAmount;
|
||||
}
|
||||
|
||||
// 退款金额 = 支付金额 - 订单消费金额 剩余需要退回的金额 residue
|
||||
BigDecimal refundAmount = payAmount.subtract(dataOrderAmount);
|
||||
|
||||
/*
|
||||
orderBasicInfo需要更新的字段
|
||||
*/
|
||||
orderBasicInfo.setOrderStatus(OrderStatusEnum.ORDER_COMPLETE.getValue());
|
||||
orderBasicInfo.setOrderAmount(dataOrderAmount); // 订单消费金额
|
||||
orderBasicInfo.setRefundAmount(refundAmount); // 订单退款金额
|
||||
orderBasicInfo.setVirtualAmount(virtualAmount); // 虚拟金额
|
||||
orderBasicInfo.setSettleAmount(dataOrderAmount.subtract(virtualAmount)); // 结算金额 = 消费金额 - 虚拟金额
|
||||
orderBasicInfo.setReason(data.getStopReasonMsg()); // 充电停止原因
|
||||
orderBasicInfo.setSettlementTime(DateUtils.getNowDate()); // 结算时间
|
||||
updateSOC(orderBasicInfo);
|
||||
|
||||
/*
|
||||
orderDetail需要更新的字段
|
||||
*/
|
||||
orderDetail.setSharpUsedElectricity(sharpUsedElectricity); // 尖时段用电量
|
||||
orderDetail.setPeakUsedElectricity(peakUsedElectricity); // 峰时段用电量
|
||||
orderDetail.setFlatUsedElectricity(flatUsedElectricity); // 平时段用电量
|
||||
orderDetail.setValleyUsedElectricity(valleyUsedElectricity); // 谷时段用电量
|
||||
orderDetail.setTotalElectricityAmount(totalElectricityAmount); // 电费总金额
|
||||
orderDetail.setTotalServiceAmount(totalServiceAmount); // 服务费总金额
|
||||
// sumUsedElectricity与totalElectricity对比, 取最大的值
|
||||
orderDetail.setTotalUsedElectricity(totalElectricity.max(sumUsedElectricity));
|
||||
orderDetail.setTotalOrderAmount(dataOrderAmount); // 订单总金额
|
||||
logger.info("end updateOrderBasicInfoAndOrderDetail:【{}】, 电费总金额:{}, 服务费总金额:{}, 总用电量:{}, 订单总金额:{}", orderCode, totalElectricityAmount, totalServiceAmount, orderDetail.getTotalUsedElectricity(), dataOrderAmount);
|
||||
}
|
||||
|
||||
private void updateSOC(OrderBasicInfo orderBasicInfo) {
|
||||
if (StringUtils.isBlank(orderBasicInfo.getStartSoc()) || StringUtils.isBlank(orderBasicInfo.getEndSoc())) {
|
||||
try {
|
||||
Map<String, String> socMap = YKCUtils.getSOCMap(orderBasicInfo.getTransactionCode());
|
||||
if (Objects.nonNull(socMap)) {
|
||||
if (StringUtils.isBlank(orderBasicInfo.getStartSoc())) {
|
||||
orderBasicInfo.setStartSoc(socMap.get("startSoc"));
|
||||
}
|
||||
if (StringUtils.isBlank(orderBasicInfo.getEndSoc())) {
|
||||
orderBasicInfo.setEndSoc(socMap.get("endSoc"));
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("获取订单充电开始结束SOC失败:{}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取更新数据后的orderDetail对象(给第三方平台结算订单用)
|
||||
|
||||
@@ -524,6 +524,75 @@ public class DelayMerchantProgramLogic extends AbstractProgramLogic {
|
||||
orderBasicInfo.getOrderCode(), orderBasicInfo.getTransactionCode(), JSON.toJSONString(dto));
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单结算/结算订单逻辑/订单结算逻辑
|
||||
*/
|
||||
@Override
|
||||
public void settleOrderV2(TransactionRecordsData data, OrderBasicInfo orderBasicInfo) {
|
||||
logger.info("【{}】-结算订单V2start data:{}, orderBasicInfo:{}", this.getClass().getSimpleName(), data.toString(), JSON.toJSONString(orderBasicInfo));
|
||||
// 判断订单状态
|
||||
if (StringUtils.equals(orderBasicInfo.getOrderStatus(), OrderStatusEnum.ORDER_COMPLETE.getValue())) {
|
||||
logger.info("结算订单V2:{}, 是订单完成状态", orderBasicInfo.getOrderCode());
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取更新数据后的orderBasicInfo对象
|
||||
// returnUpdateOrderBasicInfo(orderBasicInfo, data);
|
||||
|
||||
// 获取更新数据后的orderDetail对象/更新订单详情 查询订单详情 修改订单数据
|
||||
// OrderDetail orderDetail = returnUpdateOrderDetail(orderBasicInfo, data);
|
||||
|
||||
// 查询订单详情
|
||||
OrderDetail orderDetail = orderBasicInfoService.getOrderDetailByOrderCode(orderBasicInfo.getOrderCode());
|
||||
|
||||
// 计算订单各种金额
|
||||
updateOrderBasicInfoAndOrderDetail(data, orderBasicInfo, orderDetail);
|
||||
|
||||
// 计算订单折扣
|
||||
calculateOrderDiscountsV2(orderBasicInfo, orderDetail);
|
||||
|
||||
// 更新数据库
|
||||
OrderTransactionDTO dto = new OrderTransactionDTO();
|
||||
dto.setOrderBasicInfo(orderBasicInfo);
|
||||
dto.setOrderDetail(orderDetail);
|
||||
transactionService.doUpdateOrder(dto);
|
||||
|
||||
// 组装after参数
|
||||
AfterSettleOrderDTO afterSettleOrderDTO = AfterSettleOrderDTO.builder()
|
||||
.orderCode(orderBasicInfo.getOrderCode())
|
||||
.merchantId(orderBasicInfo.getMerchantId())
|
||||
.stationId(orderBasicInfo.getStationId())
|
||||
.orderPayAmount(orderBasicInfo.getPayAmount()) // 支付金额
|
||||
.orderConsumeAmount(orderBasicInfo.getOrderAmount()) // 消费金额
|
||||
.orderSettleAmount(orderBasicInfo.getSettleAmount()) // 结算金额
|
||||
.orderElectricityAmount(orderDetail.getTotalElectricityAmount()) // 电费金额
|
||||
.orderElectricityDiscountAmount(orderDetail.getDiscountElectricityAmount()) // 电费折扣金额
|
||||
.orderServiceAmount(orderDetail.getTotalServiceAmount()) // 服务费金额
|
||||
.orderServiceDiscountAmount(orderDetail.getDiscountServiceAmount()) // 服务费折扣金额
|
||||
.orderRefundAmount(orderBasicInfo.getRefundAmount()) // 退款金额
|
||||
.build();
|
||||
rabbitTemplate.convertAndSend(RabbitConstants.YKC_EXCHANGE_NAME, RabbitConstants.QUEUE_CHARGE_ORDER_DATA, afterSettleOrderDTO);
|
||||
|
||||
// 将卡/vin状态解锁
|
||||
if (!StringUtils.equals("0000000000000000", data.getLogicCard())) {
|
||||
cardStatusUnlocked(orderBasicInfo.getLogicCard());
|
||||
}
|
||||
|
||||
// 如果是vin启动,将启动锁定状态改为正常
|
||||
if (StringUtils.equals(data.getTransactionIdentifier(), "05")) {
|
||||
vinStatusUnlocked(data.getVinCode());
|
||||
}
|
||||
|
||||
// 发送停止充电订阅消息
|
||||
sendMsg(orderBasicInfo);
|
||||
|
||||
// 从redis中取出实时记录保存到表中
|
||||
realTimeMonitorDataRedis2DB(orderBasicInfo.getTransactionCode(), orderBasicInfo.getOrderCode());
|
||||
|
||||
logger.info("结算订单V2end! orderCode:{}, transactionCode:{}, OrderTransactionDTO:{}",
|
||||
orderBasicInfo.getOrderCode(), orderBasicInfo.getTransactionCode(), JSON.toJSONString(dto));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void settleOrderForEBike(EBikeMessageCmd03 message, OrderBasicInfo orderBasicInfo) {
|
||||
// 判断订单状态
|
||||
|
||||
Reference in New Issue
Block a user