|
@@ -881,110 +881,115 @@ public class AppletHomeServiceImpl implements AppletHomeService {
|
|
|
.last("LIMIT 1")
|
|
.last("LIMIT 1")
|
|
|
);
|
|
);
|
|
|
|
|
|
|
|
- // 7. 跨时段计算可用充电金额
|
|
|
|
|
- // 公式:可用余额 = 当前用户余额 - 安全价 - [(度数 × 运营费) + (度数 × 增值费用)]
|
|
|
|
|
- // 其中:度数 = (余额 - 安全价) / (电费 + 服务费)
|
|
|
|
|
-
|
|
|
|
|
- BigDecimal remainingBalance = balanceAfterSafety; // 剩余可用余额(用于计算度数)
|
|
|
|
|
- BigDecimal totalOpFeeCost = BigDecimal.ZERO; // 总运营费
|
|
|
|
|
- BigDecimal totalValueAddedCost = BigDecimal.ZERO; // 总增值费用
|
|
|
|
|
-
|
|
|
|
|
- // 遍历每个时段,计算在该时段能充多少度电及对应的费用
|
|
|
|
|
- for (ThirdPartyPolicyInfo policyInfo : policyInfoList) {
|
|
|
|
|
- // 获取电费、服务费
|
|
|
|
|
- BigDecimal elecPrice = policyInfo.getElecPrice() != null ? policyInfo.getElecPrice() : BigDecimal.ZERO;
|
|
|
|
|
- BigDecimal servicePrice = policyInfo.getServicePrice() != null ? policyInfo.getServicePrice() : BigDecimal.ZERO;
|
|
|
|
|
- BigDecimal basePrice = elecPrice.add(servicePrice); // 基础价格 = 电费 + 服务费
|
|
|
|
|
-
|
|
|
|
|
- if (basePrice.compareTo(BigDecimal.ZERO) == 0) {
|
|
|
|
|
- continue; // 跳过基础价格为0的时段
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 查询该时段的运营费
|
|
|
|
|
- PolicyFee policyFee;
|
|
|
|
|
- if (userFirm != null) {
|
|
|
|
|
- policyFee = policyFeeMapper.selectOne(
|
|
|
|
|
- new LambdaQueryWrapper<PolicyFee>()
|
|
|
|
|
- .eq(PolicyFee::getStationInfoId, stationInfo.getId())
|
|
|
|
|
- .eq(PolicyFee::getPeriodFlag, policyInfo.getPeriodFlag())
|
|
|
|
|
- .eq(PolicyFee::getSalesType, 1)
|
|
|
|
|
- .eq(PolicyFee::getFirmId, userFirm.getFirmId())
|
|
|
|
|
- .eq(PolicyFee::getIsDeleted, 0)
|
|
|
|
|
- .last("LIMIT 1")
|
|
|
|
|
- );
|
|
|
|
|
- } else {
|
|
|
|
|
- policyFee = policyFeeMapper.selectOne(
|
|
|
|
|
- new LambdaQueryWrapper<PolicyFee>()
|
|
|
|
|
- .eq(PolicyFee::getStationInfoId, stationInfo.getId())
|
|
|
|
|
- .eq(PolicyFee::getPeriodFlag, policyInfo.getPeriodFlag())
|
|
|
|
|
- .eq(PolicyFee::getSalesType, 0)
|
|
|
|
|
- .eq(PolicyFee::getIsDeleted, 0)
|
|
|
|
|
- .last("LIMIT 1")
|
|
|
|
|
- );
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- BigDecimal opFee = (policyFee != null && policyFee.getOpFee() != null)
|
|
|
|
|
- ? policyFee.getOpFee()
|
|
|
|
|
- : getDefaultOpFee();
|
|
|
|
|
-
|
|
|
|
|
- // 查询增值费用
|
|
|
|
|
- BigDecimal valueAddedFee = BigDecimal.ZERO;
|
|
|
|
|
- if (policyInfo.getPeriodFlag() != null) {
|
|
|
|
|
- String periodLabel = "";
|
|
|
|
|
- switch (policyInfo.getPeriodFlag()) {
|
|
|
|
|
- case 1: periodLabel = "尖"; break;
|
|
|
|
|
- case 2: periodLabel = "峰"; break;
|
|
|
|
|
- case 3: periodLabel = "平"; break;
|
|
|
|
|
- case 4: periodLabel = "谷"; break;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (!periodLabel.isEmpty()) {
|
|
|
|
|
- DictItem valueAddedItem = dictItemMapper.selectOne(
|
|
|
|
|
- new LambdaQueryWrapper<DictItem>()
|
|
|
|
|
- .eq(DictItem::getDictCode, "time_period_flag")
|
|
|
|
|
- .eq(DictItem::getLabel, periodLabel)
|
|
|
|
|
- .eq(DictItem::getStatus, 1)
|
|
|
|
|
- .last("LIMIT 1")
|
|
|
|
|
- );
|
|
|
|
|
- if (valueAddedItem != null && valueAddedItem.getValue() != null) {
|
|
|
|
|
- valueAddedFee = new BigDecimal(valueAddedItem.getValue());
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 计算在当前时段能充多少度电(使用剩余余额)
|
|
|
|
|
- // 度数 = 剩余余额 / (电费 + 服务费)
|
|
|
|
|
- BigDecimal kwh = remainingBalance.divide(basePrice, 4, RoundingMode.HALF_UP);
|
|
|
|
|
-
|
|
|
|
|
- // 如果剩余余额不足以充电,结束计算
|
|
|
|
|
- if (kwh.compareTo(BigDecimal.ZERO) <= 0) {
|
|
|
|
|
|
|
+ // 7. 计算可用充电金额
|
|
|
|
|
+ // 正确公式:可用余额 = (用户余额 - 安全价) × 基础费率占比
|
|
|
|
|
+ // 其中:基础费率占比 = (电费 + 服务费) / (电费 + 服务费 + 运营费 + 增值费)
|
|
|
|
|
+ // 这样计算确保度数计算时已包含所有费用,避免重复扣费
|
|
|
|
|
+
|
|
|
|
|
+ // 获取当前时段的价格信息(用于计算费率占比)
|
|
|
|
|
+ String currentTimeStr = LocalTime.now().format(TIME_FORMATTER);
|
|
|
|
|
+ ThirdPartyPolicyInfo currentPolicyInfo = null;
|
|
|
|
|
+ for (int i = 0; i < policyInfoList.size(); i++) {
|
|
|
|
|
+ ThirdPartyPolicyInfo policyInfo = policyInfoList.get(i);
|
|
|
|
|
+ String startTime = policyInfo.getStartTime();
|
|
|
|
|
+ // 下一个时段的开始时间作为当前时段的结束时间
|
|
|
|
|
+ String endTime = (i + 1 < policyInfoList.size())
|
|
|
|
|
+ ? policyInfoList.get(i + 1).getStartTime()
|
|
|
|
|
+ : "240000";
|
|
|
|
|
+
|
|
|
|
|
+ // 判断当前时间是否在该时段内
|
|
|
|
|
+ if (currentTimeStr.compareTo(startTime) >= 0 && currentTimeStr.compareTo(endTime) < 0) {
|
|
|
|
|
+ currentPolicyInfo = policyInfo;
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
|
|
+ }
|
|
|
|
|
+ // 如果没找到当前时段,使用第一个时段
|
|
|
|
|
+ if (currentPolicyInfo == null && !policyInfoList.isEmpty()) {
|
|
|
|
|
+ currentPolicyInfo = policyInfoList.get(0);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (currentPolicyInfo == null) {
|
|
|
|
|
+ log.warn("无法确定当前时段价格 - connectorId: {}", connectorCode);
|
|
|
|
|
+ return BigDecimal.ZERO;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- // 计算该时段的运营费和增值费用
|
|
|
|
|
- BigDecimal periodOpFeeCost = kwh.multiply(opFee);
|
|
|
|
|
- BigDecimal periodValueAddedCost = kwh.multiply(valueAddedFee);
|
|
|
|
|
|
|
+ // 获取电费、服务费
|
|
|
|
|
+ BigDecimal elecPrice = currentPolicyInfo.getElecPrice() != null ? currentPolicyInfo.getElecPrice() : BigDecimal.ZERO;
|
|
|
|
|
+ BigDecimal servicePrice = currentPolicyInfo.getServicePrice() != null ? currentPolicyInfo.getServicePrice() : BigDecimal.ZERO;
|
|
|
|
|
+ BigDecimal basePrice = elecPrice.add(servicePrice); // 基础价格 = 电费 + 服务费
|
|
|
|
|
|
|
|
- totalOpFeeCost = totalOpFeeCost.add(periodOpFeeCost);
|
|
|
|
|
- totalValueAddedCost = totalValueAddedCost.add(periodValueAddedCost);
|
|
|
|
|
|
|
+ if (basePrice.compareTo(BigDecimal.ZERO) == 0) {
|
|
|
|
|
+ log.warn("基础价格为0 - connectorId: {}", connectorCode);
|
|
|
|
|
+ return BigDecimal.ZERO;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- // 更新剩余余额(减去当前时段的所有费用)
|
|
|
|
|
- // 当前时段总费用 = (电费 + 服务费) * 度数 + 运营费 + 增值费用
|
|
|
|
|
- BigDecimal periodBaseCost = kwh.multiply(basePrice);
|
|
|
|
|
- BigDecimal periodTotalCost = periodBaseCost.add(periodOpFeeCost).add(periodValueAddedCost);
|
|
|
|
|
- remainingBalance = remainingBalance.subtract(periodTotalCost);
|
|
|
|
|
|
|
+ // 查询该时段的运营费
|
|
|
|
|
+ PolicyFee policyFee;
|
|
|
|
|
+ if (userFirm != null) {
|
|
|
|
|
+ policyFee = policyFeeMapper.selectOne(
|
|
|
|
|
+ new LambdaQueryWrapper<PolicyFee>()
|
|
|
|
|
+ .eq(PolicyFee::getStationInfoId, stationInfo.getId())
|
|
|
|
|
+ .eq(PolicyFee::getPeriodFlag, currentPolicyInfo.getPeriodFlag())
|
|
|
|
|
+ .eq(PolicyFee::getSalesType, 1)
|
|
|
|
|
+ .eq(PolicyFee::getFirmId, userFirm.getFirmId())
|
|
|
|
|
+ .eq(PolicyFee::getIsDeleted, 0)
|
|
|
|
|
+ .last("LIMIT 1")
|
|
|
|
|
+ );
|
|
|
|
|
+ } else {
|
|
|
|
|
+ policyFee = policyFeeMapper.selectOne(
|
|
|
|
|
+ new LambdaQueryWrapper<PolicyFee>()
|
|
|
|
|
+ .eq(PolicyFee::getStationInfoId, stationInfo.getId())
|
|
|
|
|
+ .eq(PolicyFee::getPeriodFlag, currentPolicyInfo.getPeriodFlag())
|
|
|
|
|
+ .eq(PolicyFee::getSalesType, 0)
|
|
|
|
|
+ .eq(PolicyFee::getIsDeleted, 0)
|
|
|
|
|
+ .last("LIMIT 1")
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- log.debug("时段计算 - startTime: {}, 电费: {}, 服务费: {}, 运营费: {}, 增值费: {}, 度数: {}, 该时段费用: {}, 剩余余额: {}",
|
|
|
|
|
- policyInfo.getStartTime(), elecPrice, servicePrice, opFee, valueAddedFee, kwh, periodTotalCost, remainingBalance);
|
|
|
|
|
|
|
+ BigDecimal opFee = (policyFee != null && policyFee.getOpFee() != null)
|
|
|
|
|
+ ? policyFee.getOpFee()
|
|
|
|
|
+ : getDefaultOpFee();
|
|
|
|
|
+
|
|
|
|
|
+ // 查询增值费用
|
|
|
|
|
+ BigDecimal valueAddedFee = BigDecimal.ZERO;
|
|
|
|
|
+ if (currentPolicyInfo.getPeriodFlag() != null) {
|
|
|
|
|
+ String periodLabel = "";
|
|
|
|
|
+ switch (currentPolicyInfo.getPeriodFlag()) {
|
|
|
|
|
+ case 1: periodLabel = "尖"; break;
|
|
|
|
|
+ case 2: periodLabel = "峰"; break;
|
|
|
|
|
+ case 3: periodLabel = "平"; break;
|
|
|
|
|
+ case 4: periodLabel = "谷"; break;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- // 如果剩余余额小于等于0,结束计算
|
|
|
|
|
- if (remainingBalance.compareTo(BigDecimal.ZERO) <= 0) {
|
|
|
|
|
- break;
|
|
|
|
|
|
|
+ if (!periodLabel.isEmpty()) {
|
|
|
|
|
+ DictItem valueAddedItem = dictItemMapper.selectOne(
|
|
|
|
|
+ new LambdaQueryWrapper<DictItem>()
|
|
|
|
|
+ .eq(DictItem::getDictCode, "time_period_flag")
|
|
|
|
|
+ .eq(DictItem::getLabel, periodLabel)
|
|
|
|
|
+ .eq(DictItem::getStatus, 1)
|
|
|
|
|
+ .last("LIMIT 1")
|
|
|
|
|
+ );
|
|
|
|
|
+ if (valueAddedItem != null && valueAddedItem.getValue() != null) {
|
|
|
|
|
+ valueAddedFee = new BigDecimal(valueAddedItem.getValue());
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 8. 计算最终可用余额
|
|
|
|
|
- BigDecimal availableAmount = userBalance.subtract(safetyFee).subtract(totalOpFeeCost).subtract(totalValueAddedCost);
|
|
|
|
|
|
|
+ // 计算总单价(每度电的总费用)
|
|
|
|
|
+ BigDecimal totalUnitPrice = basePrice.add(opFee).add(valueAddedFee);
|
|
|
|
|
+
|
|
|
|
|
+ // 计算可充电度数 = (余额 - 安全价) / 总单价
|
|
|
|
|
+ BigDecimal kwh = balanceAfterSafety.divide(totalUnitPrice, 4, RoundingMode.HALF_UP);
|
|
|
|
|
+
|
|
|
|
|
+ // 计算可用于基础费用(电费+服务费)的金额 = 度数 × 基础价格
|
|
|
|
|
+ // 这就是实际可用于充电的金额(不含运营费和增值费)
|
|
|
|
|
+ BigDecimal availableAmount = kwh.multiply(basePrice);
|
|
|
|
|
+
|
|
|
|
|
+ // 计算运营费和增值费用(用于日志记录)
|
|
|
|
|
+ BigDecimal totalOpFeeCost = kwh.multiply(opFee);
|
|
|
|
|
+ BigDecimal totalValueAddedCost = kwh.multiply(valueAddedFee);
|
|
|
|
|
+
|
|
|
|
|
+ log.debug("时段计算 - 电费: {}, 服务费: {}, 运营费: {}, 增值费: {}, 总单价: {}, 可充度数: {}, 基础费用: {}",
|
|
|
|
|
+ elecPrice, servicePrice, opFee, valueAddedFee, totalUnitPrice, kwh, availableAmount);
|
|
|
|
|
|
|
|
// 确保不为负数
|
|
// 确保不为负数
|
|
|
if (availableAmount.compareTo(BigDecimal.ZERO) < 0) {
|
|
if (availableAmount.compareTo(BigDecimal.ZERO) < 0) {
|