package com.ruoyi.order.service.impl;
|
|
import com.ruoyi.order.api.model.AccountingStrategyDetailOrder;
|
import com.ruoyi.order.api.model.TChargingOrder;
|
import com.ruoyi.order.api.vo.TransactionRecordMessageVO;
|
|
import java.lang.reflect.Method;
|
import java.math.BigDecimal;
|
import java.math.RoundingMode;
|
import java.time.LocalDateTime;
|
import java.time.LocalTime;
|
import java.time.format.DateTimeFormatter;
|
import java.util.List;
|
|
final class ChargingSimulationSupport {
|
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SS");
|
|
private ChargingSimulationSupport() {
|
}
|
|
static BigDecimal availableAmount(TChargingOrder order) {
|
if (order == null) {
|
return BigDecimal.ZERO.setScale(2);
|
}
|
BigDecimal chargeAmount = money(order.getChargeAmount());
|
return chargeAmount.compareTo(BigDecimal.ZERO) > 0 ? chargeAmount : money(order.getRechargeAmount());
|
}
|
|
static String paymentMode(TChargingOrder order) {
|
if (order == null) {
|
return "未知";
|
}
|
if (Integer.valueOf(1).equals(order.getIsWhitelist())
|
&& Integer.valueOf(1).equals(order.getWhitelistBenefitType())) {
|
return "免支付";
|
}
|
BigDecimal balanceAmount = money(order.getBalancePayAmount());
|
BigDecimal thirdAmount = thirdPayAmount(order);
|
if (balanceAmount.compareTo(BigDecimal.ZERO) == 0 && thirdAmount.compareTo(BigDecimal.ZERO) == 0) {
|
return "免支付";
|
}
|
String thirdChannel = thirdChannel(order);
|
if (balanceAmount.compareTo(BigDecimal.ZERO) > 0 && thirdAmount.compareTo(BigDecimal.ZERO) == 0) {
|
return "余额支付";
|
}
|
if (balanceAmount.compareTo(BigDecimal.ZERO) > 0 && thirdAmount.compareTo(BigDecimal.ZERO) > 0) {
|
return "余额+" + thirdChannel;
|
}
|
return thirdChannel;
|
}
|
|
static BigDecimal thirdPayAmount(TChargingOrder order) {
|
if (order == null) {
|
return BigDecimal.ZERO.setScale(2);
|
}
|
BigDecimal thirdAmount = money(order.getThirdPayAmount());
|
if (thirdAmount.compareTo(BigDecimal.ZERO) > 0) {
|
return thirdAmount;
|
}
|
if (Integer.valueOf(1).equals(order.getPayMethod())
|
&& !"ICBC".equalsIgnoreCase(order.getSourceName())) {
|
return thirdAmount;
|
}
|
return money(order.getRechargeAmount())
|
.subtract(money(order.getBalancePayAmount()))
|
.max(BigDecimal.ZERO)
|
.setScale(2, RoundingMode.HALF_UP);
|
}
|
|
private static String thirdChannel(TChargingOrder order) {
|
if ("ICBC".equalsIgnoreCase(order.getSourceName())) {
|
return "工行支付";
|
}
|
if (Integer.valueOf(2).equals(order.getRechargePaymentType())) {
|
return "支付宝支付";
|
}
|
if (Integer.valueOf(3).equals(order.getRechargePaymentType())) {
|
return "支付宝H5支付";
|
}
|
return "微信支付";
|
}
|
|
private static BigDecimal money(BigDecimal amount) {
|
return amount == null ? BigDecimal.ZERO.setScale(2) : amount.setScale(2, RoundingMode.HALF_UP);
|
}
|
|
static PreparedSimulation prepare(String orderCode,
|
List<AccountingStrategyDetailOrder> tariffs,
|
BigDecimal electricityFee,
|
BigDecimal serviceFee,
|
LocalDateTime endTime) {
|
validate(orderCode, tariffs, electricityFee, serviceFee);
|
if (tariffs.size() > 12) {
|
throw new IllegalArgumentException("模拟计费最多支持12个计费时段");
|
}
|
int index = findTariffIndex(tariffs, endTime.toLocalTime());
|
AccountingStrategyDetailOrder tariff = tariffs.get(index);
|
tariff.setElectrovalence(electricityFee);
|
tariff.setServiceCharge(serviceFee);
|
tariff.setCostServiceCharge(serviceFee);
|
|
TransactionRecordMessageVO record = new TransactionRecordMessageVO();
|
record.setTransaction_serial_number(orderCode);
|
record.setStart_time(endTime.minusSeconds(1).format(DATE_TIME_FORMATTER));
|
record.setEnd_time(endTime.format(DATE_TIME_FORMATTER));
|
record.setTrade_date(endTime.format(DATE_TIME_FORMATTER));
|
record.setTotal_electricity(BigDecimal.ONE);
|
record.setLoss_total_electricity(BigDecimal.ONE);
|
record.setPayment_amount(electricityFee.add(serviceFee));
|
record.setMethod(1);
|
record.setStop_reason(1);
|
setPeriodCharge(record, tariff.getType(), index + 1);
|
return new PreparedSimulation(tariff, record);
|
}
|
|
private static void validate(String orderCode,
|
List<AccountingStrategyDetailOrder> tariffs,
|
BigDecimal electricityFee,
|
BigDecimal serviceFee) {
|
if (orderCode == null || orderCode.trim().isEmpty()) {
|
throw new IllegalArgumentException("模拟订单号不能为空");
|
}
|
if (tariffs == null || tariffs.isEmpty()) {
|
throw new IllegalArgumentException("订单计费策略为空");
|
}
|
if (electricityFee == null || electricityFee.compareTo(BigDecimal.ZERO) < 0) {
|
throw new IllegalArgumentException("电费不能小于0");
|
}
|
if (serviceFee == null || serviceFee.compareTo(BigDecimal.ZERO) < 0) {
|
throw new IllegalArgumentException("服务费不能小于0");
|
}
|
if (electricityFee.add(serviceFee).compareTo(BigDecimal.ZERO) <= 0) {
|
throw new IllegalArgumentException("模拟消费金额必须大于0");
|
}
|
}
|
|
private static int findTariffIndex(List<AccountingStrategyDetailOrder> tariffs, LocalTime time) {
|
for (int i = 0; i < tariffs.size(); i++) {
|
AccountingStrategyDetailOrder tariff = tariffs.get(i);
|
LocalTime start = parseTime(tariff.getStartTime(), false);
|
LocalTime end = parseTime(tariff.getEndTime(), true);
|
if (!time.isBefore(start) && !time.isAfter(end)) {
|
return i;
|
}
|
}
|
throw new IllegalArgumentException("当前时间未匹配到订单计费时段");
|
}
|
|
private static LocalTime parseTime(String value, boolean end) {
|
if ("24:00".equals(value)) {
|
return LocalTime.MAX;
|
}
|
LocalTime time = LocalTime.parse(value, DateTimeFormatter.ofPattern("HH:mm"));
|
return end ? time.withSecond(59).withNano(999999999) : time;
|
}
|
|
private static void setPeriodCharge(TransactionRecordMessageVO record, Integer type, int index) {
|
String prefix;
|
if (Integer.valueOf(1).equals(type)) {
|
prefix = "Spike";
|
} else if (Integer.valueOf(2).equals(type)) {
|
prefix = "Peak";
|
} else if (Integer.valueOf(3).equals(type)) {
|
prefix = "Flat";
|
} else if (Integer.valueOf(4).equals(type)) {
|
prefix = "Valley";
|
} else {
|
throw new IllegalArgumentException("不支持的计费时段类型:" + type);
|
}
|
try {
|
Method setter = TransactionRecordMessageVO.class.getMethod("set" + prefix + "_charge" + index, BigDecimal.class);
|
setter.invoke(record, BigDecimal.ONE);
|
} catch (Exception e) {
|
throw new IllegalStateException("构造模拟计费时段失败", e);
|
}
|
}
|
|
static final class PreparedSimulation {
|
private final AccountingStrategyDetailOrder tariff;
|
private final TransactionRecordMessageVO record;
|
|
PreparedSimulation(AccountingStrategyDetailOrder tariff, TransactionRecordMessageVO record) {
|
this.tariff = tariff;
|
this.record = record;
|
}
|
|
AccountingStrategyDetailOrder getTariff() {
|
return tariff;
|
}
|
|
TransactionRecordMessageVO getRecord() {
|
return record;
|
}
|
}
|
}
|