|
|
@@ -47,6 +47,15 @@ import java.util.stream.Collectors;
|
|
|
@RequiredArgsConstructor
|
|
|
public class ParkingWalletFeeService {
|
|
|
|
|
|
+ private final KwtParkingWalletFeeRepository parkingWalletFeeRepository;
|
|
|
+ private final KwtParkingWalletFeeBalanceRepository parkingWalletFeeBalanceRepository;
|
|
|
+
|
|
|
+ private final KwtParkingChangeStrategyRepository parkingChangeStrategyRepository;
|
|
|
+ private final KwtParkingChangeStrategyUnitRepository parkingChangeStrategyUnitRepository;
|
|
|
+ private final KwtParkingStrategySwitchRepository parkingStrategySwitchRepository;
|
|
|
+
|
|
|
+ @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 6000)
|
|
|
+ RemoteSystemService remoteSystemService;
|
|
|
|
|
|
private static final BigDecimal ZERO_AMOUNT = BigDecimal.ZERO;
|
|
|
private static final int STRATEGY_OPEN = 1;
|
|
|
@@ -57,14 +66,279 @@ public class ParkingWalletFeeService {
|
|
|
/** 钱包明细交易类型:消费(订单完结按实际履约量正式扣减服务费) */
|
|
|
private static final int TRADE_TYPE_CONSUME = 6;
|
|
|
|
|
|
- private final KwtParkingWalletFeeRepository parkingWalletFeeRepository;
|
|
|
- private final KwtParkingWalletFeeBalanceRepository parkingWalletFeeBalanceRepository;
|
|
|
- private final KwtParkingChangeStrategyRepository parkingChangeStrategyRepository;
|
|
|
- private final KwtParkingChangeStrategyUnitRepository parkingChangeStrategyUnitRepository;
|
|
|
- private final KwtParkingStrategySwitchRepository parkingStrategySwitchRepository;
|
|
|
+ /**
|
|
|
+ * 查询汇总服务费
|
|
|
+ * @param param
|
|
|
+ */
|
|
|
+ public ParkingWalletFeeResp queryTotalServerFee(ParkingWalletFeeTotalQueryParam param) {
|
|
|
+ log.info("查询汇总服务费:{}", JSON.toJSONString(param));
|
|
|
+ if (param.getSupEntId() != null) {
|
|
|
+ param.setSupEntId(551429255406292993L);
|
|
|
+ }
|
|
|
|
|
|
- @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 6000)
|
|
|
- RemoteSystemService remoteSystemService;
|
|
|
+ //构建查询条件
|
|
|
+ LambdaQueryWrapper<KwtParkingWalletFee> wrapper = buildAndExecuteQuery(param);
|
|
|
+
|
|
|
+ // 初始化
|
|
|
+ ParkingWalletFeeResp resp = new ParkingWalletFeeResp();
|
|
|
+ resp.setServiceFeeBalance(BigDecimal.ZERO);
|
|
|
+ resp.setTradingAmount(BigDecimal.ZERO);
|
|
|
+
|
|
|
+ List<KwtParkingWalletFee> records = parkingWalletFeeRepository.list(wrapper);
|
|
|
+ if (CollectionUtils.isEmpty(records)) {
|
|
|
+ log.info("汇总服务费信息为空");
|
|
|
+ return resp;
|
|
|
+ }
|
|
|
+ // 查询采购商汇总服务费
|
|
|
+ if (param.getProEntId() != null) {
|
|
|
+ return getProWalletFee(records.get(0));
|
|
|
+ }
|
|
|
+ // 查询平台汇总服务费
|
|
|
+ if (param.getSupEntId() != null) {
|
|
|
+ return getSupWalletFee(records);
|
|
|
+ }
|
|
|
+ return resp;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构建查询条件并执行分页查询
|
|
|
+ */
|
|
|
+ private LambdaQueryWrapper<KwtParkingWalletFee> buildAndExecuteQuery(ParkingWalletFeeTotalQueryParam param) {
|
|
|
+ return Wrappers.<KwtParkingWalletFee>lambdaQuery()
|
|
|
+ .eq(param.getProEntId() != null, KwtParkingWalletFee::getProEntId, param.getProEntId())
|
|
|
+ .eq(param.getSupEntId() != null, KwtParkingWalletFee::getSupEntId, param.getSupEntId())
|
|
|
+ .orderByDesc(KwtParkingWalletFee::getUpdateTime);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取采购商汇总服务费
|
|
|
+ * @param fee
|
|
|
+ */
|
|
|
+ private ParkingWalletFeeResp getProWalletFee(KwtParkingWalletFee fee) {
|
|
|
+ log.info("开始汇总采购商服务费,param:{}", JSON.toJSONString(fee));
|
|
|
+
|
|
|
+ ParkingWalletFeeResp resp = new ParkingWalletFeeResp();
|
|
|
+ resp.setServiceFeeBalance(fee.getServiceFeeBalance() != null ? fee.getServiceFeeBalance() : BigDecimal.ZERO);
|
|
|
+ resp.setTradingAmount(fee.getTradingAmount() != null ? fee.getTradingAmount() : BigDecimal.ZERO);
|
|
|
+ resp.setProEntName(getEntName(fee.getProEntId()));
|
|
|
+ log.info("汇总采购商服务费结束,总余额:{}, 总履约中金额:{}", fee.getServiceFeeBalance(), fee.getTradingAmount());
|
|
|
+ return resp;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取平台汇总服务费
|
|
|
+ * @param feeList
|
|
|
+ */
|
|
|
+ private ParkingWalletFeeResp getSupWalletFee(List<KwtParkingWalletFee> feeList) {
|
|
|
+ log.info("开始汇总平台服务费, size:{}", CollectionUtils.isEmpty(feeList) ? 0 : feeList.size());
|
|
|
+ // 汇总余额
|
|
|
+ BigDecimal totalServiceFee = feeList.stream()
|
|
|
+ .map(fee -> fee.getServiceFeeBalance() != null ? fee.getServiceFeeBalance() : BigDecimal.ZERO)
|
|
|
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
+ // 汇总冻结金额
|
|
|
+ BigDecimal totalTradingAmount = feeList.stream()
|
|
|
+ .map(fee -> fee.getTradingAmount() != null ? fee.getTradingAmount() : BigDecimal.ZERO)
|
|
|
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
+ ParkingWalletFeeResp resp = new ParkingWalletFeeResp();
|
|
|
+ resp.setServiceFeeBalance(totalServiceFee);
|
|
|
+ resp.setTradingAmount(totalTradingAmount);
|
|
|
+ resp.setSupEntName(getEntName(feeList.get(0).getSupEntId()));
|
|
|
+ log.info("汇总平台服务费结束,总余额:{}, 总履约中金额:{}", totalServiceFee, totalTradingAmount);
|
|
|
+ return resp;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 分页查询服务费
|
|
|
+ * @param param
|
|
|
+ */
|
|
|
+ public PageDataResult<ParkingWalletFeeResp> pageQueryServerFee(ParkingWalletFeeQueryParam param) {
|
|
|
+ log.info("分页查询服务费:{}", JSON.toJSONString(param));
|
|
|
+ if (param.getSupEntId() != null) {
|
|
|
+ param.setSupEntId(551429255406292993L);
|
|
|
+ }
|
|
|
+
|
|
|
+ //构建查询条件
|
|
|
+ LambdaQueryWrapper<KwtParkingWalletFee> wrapper = buildAndExecuteQuery(param);
|
|
|
+
|
|
|
+ Page<KwtParkingWalletFee> pageByStatus = parkingWalletFeeRepository.page(new Page<>(param.getPageNum(), param.getPageSize()), wrapper);
|
|
|
+ List<KwtParkingWalletFee> records = pageByStatus.getRecords();
|
|
|
+ if (CollectionUtils.isEmpty(records)) {
|
|
|
+ log.info("服务费信息为空");
|
|
|
+ return PageDataResult.empty(param.getPageNum(), param.getPageSize());
|
|
|
+ }
|
|
|
+ List<ParkingWalletFeeResp> changeStrategyRespList = getWalletFeePageResult(records);
|
|
|
+ return PageDataResult.success(param.getPageNum(), param.getPageSize(), pageByStatus.getTotal(), changeStrategyRespList);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构建查询条件并执行分页查询
|
|
|
+ */
|
|
|
+ private LambdaQueryWrapper<KwtParkingWalletFee> buildAndExecuteQuery(ParkingWalletFeeQueryParam param) {
|
|
|
+ return Wrappers.<KwtParkingWalletFee>lambdaQuery()
|
|
|
+ .eq(param.getSupEntId() != null, KwtParkingWalletFee::getSupEntId, param.getSupEntId())
|
|
|
+ .eq(param.getProEntId() != null, KwtParkingWalletFee::getProEntId, param.getProEntId())
|
|
|
+ .orderByDesc(KwtParkingWalletFee::getUpdateTime);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取收费策略
|
|
|
+ * @param records
|
|
|
+ */
|
|
|
+ private List<ParkingWalletFeeResp> getWalletFeePageResult(List<KwtParkingWalletFee> records) {
|
|
|
+ log.info("组装服务费,param:{}", JSON.toJSONString(records));
|
|
|
+ if (CollectionUtils.isEmpty(records)) {
|
|
|
+ return Collections.emptyList();
|
|
|
+ }
|
|
|
+ List<ParkingWalletFeeResp> walletFeeList = records.stream()
|
|
|
+ .map(fee -> {
|
|
|
+ ParkingWalletFeeResp resp = new ParkingWalletFeeResp();
|
|
|
+ resp.setId(fee.getId());
|
|
|
+ resp.setProEntId(fee.getProEntId());
|
|
|
+ resp.setProEntName(getEntName(fee.getProEntId()));
|
|
|
+ resp.setSupEntId(fee.getSupEntId());
|
|
|
+ resp.setSupEntName(getEntName(fee.getSupEntId()));
|
|
|
+ resp.setServiceFeeBalance(fee.getServiceFeeBalance());
|
|
|
+ resp.setTradingAmount(fee.getTradingAmount());
|
|
|
+ resp.setUpdateTime(fee.getUpdateTime());
|
|
|
+ return resp;
|
|
|
+ }).collect(Collectors.toList());
|
|
|
+
|
|
|
+ log.info("组装服务费结束,size:{}", JSON.toJSONString(walletFeeList.size()));
|
|
|
+ return walletFeeList;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 保存服务费
|
|
|
+ * @param param
|
|
|
+ */
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void saveServerFee(ParkingWalletFeeSaveParam param) {
|
|
|
+ log.info("保存服务费,param:{}", JSON.toJSONString(param));
|
|
|
+ if (param.getSupEntId() != null) {
|
|
|
+ param.setSupEntId(551429255406292993L);
|
|
|
+ }
|
|
|
+
|
|
|
+ KwtParkingWalletFee walletFee = parkingWalletFeeRepository.getById(param.getId());
|
|
|
+ if (walletFee == null) {
|
|
|
+ throw new BusinessPlatfromException(ErrorCodeEnum.PARAM_ERROR, "服务费信息不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 预付
|
|
|
+ if (Objects.equals(param.getPaymentType(), 1)) {
|
|
|
+ walletFee.setServiceFeeBalance(walletFee.getServiceFeeBalance().add(param.getServiceFee()));
|
|
|
+ }else {
|
|
|
+ if (walletFee.getServiceFeeBalance().compareTo(param.getServiceFee()) < 0) {
|
|
|
+ throw new BusinessPlatfromException(ErrorCodeEnum.PARAM_ERROR, "扣款金额不能大于服务余额");
|
|
|
+ }
|
|
|
+ walletFee.setServiceFeeBalance(walletFee.getServiceFeeBalance().subtract(param.getServiceFee()));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 1. 先修改服务余额
|
|
|
+ parkingWalletFeeRepository.updateById(walletFee);
|
|
|
+
|
|
|
+ // 2.新增明细
|
|
|
+ KwtParkingWalletFeeBalance feeBalance = new KwtParkingWalletFeeBalance();
|
|
|
+ feeBalance.setSupEntId(param.getSupEntId());
|
|
|
+ feeBalance.setProEntId(param.getProEntId());
|
|
|
+ feeBalance.setTradeType(9);
|
|
|
+ feeBalance.setPaymentType(param.getPaymentType());
|
|
|
+ feeBalance.setTradeAmount(param.getServiceFee());
|
|
|
+ feeBalance.setServiceFeeBalance(walletFee.getServiceFeeBalance());
|
|
|
+ feeBalance.setTradingAmount(walletFee.getTradingAmount());
|
|
|
+ feeBalance.setVoucherUrl(param.getVoucherUrl());
|
|
|
+ feeBalance.setRemark(param.getRemark());
|
|
|
+ parkingWalletFeeBalanceRepository.save(feeBalance);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 分页查询服务费明细
|
|
|
+ * @param param
|
|
|
+ */
|
|
|
+ public PageDataResult<ParkingWalletFeeBalanceResp> pageQueryServerFeeDetails(ParkingWalletFeeBalanceQueryParam param) {
|
|
|
+ log.info("分页查询服务费明细:{}", JSON.toJSONString(param));
|
|
|
+ if (param.getSupEntId() != null) {
|
|
|
+ param.setSupEntId(551429255406292993L);
|
|
|
+ }
|
|
|
+ //构建查询条件
|
|
|
+ LambdaQueryWrapper<KwtParkingWalletFeeBalance> wrapper = buildAndExecuteQuery(param);
|
|
|
+
|
|
|
+ Page<KwtParkingWalletFeeBalance> pageByStatus = parkingWalletFeeBalanceRepository.page(new Page<>(param.getPageNum(), param.getPageSize()), wrapper);
|
|
|
+ List<KwtParkingWalletFeeBalance> records = pageByStatus.getRecords();
|
|
|
+ if (CollectionUtils.isEmpty(records)) {
|
|
|
+ log.info("分页查询服务费明细为空");
|
|
|
+ return PageDataResult.empty(param.getPageNum(), param.getPageSize());
|
|
|
+ }
|
|
|
+ List<ParkingWalletFeeBalanceResp> changeStrategyRespList = getWalletFeeBalancePageResult(records);
|
|
|
+ return PageDataResult.success(param.getPageNum(), param.getPageSize(), pageByStatus.getTotal(), changeStrategyRespList);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构建查询条件并执行分页查询
|
|
|
+ */
|
|
|
+ private LambdaQueryWrapper<KwtParkingWalletFeeBalance> buildAndExecuteQuery(ParkingWalletFeeBalanceQueryParam param) {
|
|
|
+ return Wrappers.<KwtParkingWalletFeeBalance>lambdaQuery()
|
|
|
+ .eq(param.getSupEntId() != null, KwtParkingWalletFeeBalance::getSupEntId, param.getSupEntId())
|
|
|
+ .eq(param.getProEntId() != null, KwtParkingWalletFeeBalance::getProEntId, param.getProEntId())
|
|
|
+ .eq(KwtParkingWalletFeeBalance::getOrderNo, param.getOrderNo())
|
|
|
+ .eq(KwtParkingWalletFeeBalance::getTradeType, param.getTradeType())
|
|
|
+ .ge(KwtParkingWalletFeeBalance::getTradeAmount, param.getMinFee())
|
|
|
+ .le(KwtParkingWalletFeeBalance::getTradeAmount, param.getMaxFee())
|
|
|
+ .ge(KwtParkingWalletFeeBalance::getCreateTime, param.getStartCreateTime())
|
|
|
+ .le(KwtParkingWalletFeeBalance::getCreateTime, param.getEndCreateTime())
|
|
|
+ .orderByDesc(KwtParkingWalletFeeBalance::getServiceFeeBalance);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取服务费明细
|
|
|
+ * @param records
|
|
|
+ */
|
|
|
+ private List<ParkingWalletFeeBalanceResp> getWalletFeeBalancePageResult(List<KwtParkingWalletFeeBalance> records) {
|
|
|
+ log.info("组装服务费明细,param:{}", JSON.toJSONString(records));
|
|
|
+ if (CollectionUtils.isEmpty(records)) {
|
|
|
+ return Collections.emptyList();
|
|
|
+ }
|
|
|
+ List<ParkingWalletFeeBalanceResp> walletFeeList = records.stream()
|
|
|
+ .map(feeBalance -> {
|
|
|
+ ParkingWalletFeeBalanceResp resp = new ParkingWalletFeeBalanceResp();
|
|
|
+ resp.setId(feeBalance.getId());
|
|
|
+ resp.setOrderNo(feeBalance.getOrderNo());
|
|
|
+ resp.setProEntId(feeBalance.getProEntId());
|
|
|
+ resp.setProEntName(getEntName(feeBalance.getProEntId()));
|
|
|
+ resp.setSupEntId(feeBalance.getSupEntId());
|
|
|
+ resp.setSupEntName(getEntName(feeBalance.getSupEntId()));
|
|
|
+ resp.setTradeType(feeBalance.getTradeType());
|
|
|
+ resp.setTradeTypeDesc(WalletTypEnum.getDescByCode(feeBalance.getTradeType()));
|
|
|
+ resp.setPaymentType(feeBalance.getPaymentType());
|
|
|
+ resp.setTradeAmount(Objects.equals(feeBalance.getPaymentType(), 1) ? feeBalance.getTradeAmount() : feeBalance.getTradeAmount().negate());
|
|
|
+ resp.setServiceFeeBalance(feeBalance.getServiceFeeBalance());
|
|
|
+ resp.setTradingAmount(feeBalance.getTradingAmount());
|
|
|
+ resp.setVoucherUrl(feeBalance.getVoucherUrl());
|
|
|
+ resp.setRemark(feeBalance.getRemark());
|
|
|
+ resp.setCreateTime(feeBalance.getCreateTime());
|
|
|
+ return resp;
|
|
|
+ }).collect(Collectors.toList());
|
|
|
+
|
|
|
+ log.info("组装服务费明细结束,size:{}", JSON.toJSONString(walletFeeList.size()));
|
|
|
+ return walletFeeList;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 通过企业id查询企业名称
|
|
|
+ * @param entId
|
|
|
+ */
|
|
|
+ private String getEntName(Long entId) {
|
|
|
+ // 查询企业名称
|
|
|
+ EntCacheResDto entCacheResDto = remoteSystemService.queryEntDetails(entId);
|
|
|
+ if (entCacheResDto == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ return entCacheResDto.getFirmName();
|
|
|
+ }
|
|
|
|
|
|
/**
|
|
|
* 查询服务费余额、本次预计服务费与最大可购买数量。
|
|
|
@@ -72,7 +346,7 @@ public class ParkingWalletFeeService {
|
|
|
* 业务规则:
|
|
|
* 1. 服务费余额取当前登录采购企业的可用服务费余额;
|
|
|
* 2. 收费策略总开关关闭时,不计算预计服务费,最大可购买数量返回 null,表示不做余额约束;
|
|
|
- * 3. 收费策略总开关开启时,按企业绑定的当前收费策略计算预计服务费;
|
|
|
+ * 3. 收费策略总开关开启时,按企业绑定的当前收费策略计算预计服务费;无企业策略时使用开关表 default_fee;
|
|
|
* 4. 策略 method 为 0.00 时,实际单价使用 kwt_parking_strategy_switch.default_fee;
|
|
|
* 5. 最大可购买数量 = 服务费余额 / 实际策略单价,向下取整,避免超出余额。
|
|
|
*
|
|
|
@@ -99,7 +373,7 @@ public class ParkingWalletFeeService {
|
|
|
// 收费策略总开关统一以 kwt_parking_strategy_switch.status 为准,策略表 status 不再作为计费开关。
|
|
|
boolean chargeStrategySwitchOpen = isChargeStrategySwitchOpen();
|
|
|
|
|
|
- // 查询当前企业绑定的最新收费策略;若 method 为 0.00,resolveStrategyUnitFee 会使用开关表 default_fee。
|
|
|
+ // 查询当前企业绑定的最新收费策略;无企业策略或 method 为 0.00 时,resolveStrategyUnitFee 会使用开关表 default_fee。
|
|
|
KwtParkingChargeStrategy currentStrategy = queryCurrentEnableStrategy(entId);
|
|
|
BigDecimal currentStrategyUnitFee = resolveStrategyUnitFee(currentStrategy);
|
|
|
log.info("服务费预估策略匹配完成,企业id:{}, 开关状态:{}, 策略id:{}, 策略原始单价:{}, 实际计费单价:{}",
|
|
|
@@ -116,8 +390,8 @@ public class ParkingWalletFeeService {
|
|
|
log.info("服务费预估金额计算完成,企业id:{}, 采购数量:{}, 实际计费单价:{}, 预计服务费:{}",
|
|
|
entId, param.getPurchaseQuantity(), currentStrategyUnitFee, estimatedServiceFee);
|
|
|
|
|
|
- // 开关开启且存在有效策略单价时,按服务费余额计算最大可购买数量;否则返回 null。
|
|
|
- BigDecimal maxPurchaseQuantity = calculateMaxPurchaseQuantity(currentStrategy, currentStrategyUnitFee, serviceFeeBalance);
|
|
|
+ // 开关开启且存在有效单价时,按服务费余额计算最大可购买数量;否则返回 null。
|
|
|
+ BigDecimal maxPurchaseQuantity = calculateMaxPurchaseQuantity(currentStrategyUnitFee, serviceFeeBalance);
|
|
|
log.info("服务费预估计算完成,企业id:{}, 采购数量:{}, 服务费余额:{}, 预计服务费:{}, 最大可购买数量:{}",
|
|
|
entId, param.getPurchaseQuantity(), serviceFeeBalance, estimatedServiceFee, maxPurchaseQuantity);
|
|
|
|
|
|
@@ -129,6 +403,7 @@ public class ParkingWalletFeeService {
|
|
|
return resp;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
/**
|
|
|
* 贸易订单下单应用收费策略并冻结服务费
|
|
|
* 规则:
|
|
|
@@ -200,6 +475,7 @@ public class ParkingWalletFeeService {
|
|
|
result.setApplyChargeStrategy(Global.YES);
|
|
|
result.setChargeStrategyId(currentStrategy.getId());
|
|
|
result.setChargeStrategyDesc(buildStrategyMethodDesc(currentStrategy));
|
|
|
+ result.setChargeStrategyAmount(unitFee);
|
|
|
result.setFreezeAmount(freezeAmount);
|
|
|
result.setServiceFeeBalance(walletFee.getServiceFeeBalance());
|
|
|
log.info("贸易订单应用收费策略完成,orderNo:{}, result:{}", param.getOrderNo(), result);
|
|
|
@@ -263,6 +539,7 @@ public class ParkingWalletFeeService {
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
/**
|
|
|
* 贸易订单完结结算服务费
|
|
|
* <p>
|
|
|
@@ -390,6 +667,7 @@ public class ParkingWalletFeeService {
|
|
|
String strategyDesc) {
|
|
|
}
|
|
|
|
|
|
+
|
|
|
/**
|
|
|
* 查询采购方服务费余额
|
|
|
*/
|
|
|
@@ -430,8 +708,8 @@ public class ParkingWalletFeeService {
|
|
|
/**
|
|
|
* 解析订单完结服务费扣减信息
|
|
|
* <p>
|
|
|
- * 扣减金额 = 运输净重量 × 采购方当前最优收费策略单价;
|
|
|
- * 最优策略:企业已绑定且开启的策略中,单价最低的一条(对采购方最优惠)。
|
|
|
+ * 扣减金额 = 运输净重量 × 收费策略单价;
|
|
|
+ * 单价优先取订单下单快照(chargeStrategyAmount),无快照时再取采购方当前最优策略;
|
|
|
* 若无法匹配策略,则回退为下单冻结金额。
|
|
|
*
|
|
|
* @param param 结算参数(actualQuantity 为运输净重量)
|
|
|
@@ -440,6 +718,17 @@ public class ParkingWalletFeeService {
|
|
|
*/
|
|
|
private SettleConsumeInfo resolveSettleConsumeInfo(ParkingWalletFeeFreezeParam param, BigDecimal freezeAmount) {
|
|
|
BigDecimal transportNetWeight = param.getActualQuantity() == null ? ZERO_AMOUNT : param.getActualQuantity();
|
|
|
+
|
|
|
+ // 优先使用订单下单时快照的收费策略单价,避免策略表变更后扣减金额变化
|
|
|
+ BigDecimal snapshotUnitFee = param.getChargeStrategyAmount();
|
|
|
+ if (snapshotUnitFee != null && snapshotUnitFee.compareTo(ZERO_AMOUNT) > 0) {
|
|
|
+ BigDecimal consumeAmount = transportNetWeight.multiply(snapshotUnitFee).setScale(2, RoundingMode.HALF_UP);
|
|
|
+ log.info("按订单快照单价计算扣减,orderNo:{}, transportNetWeight:{}, snapshotUnitFee:{}, consumeAmount:{}",
|
|
|
+ param.getOrderNo(), transportNetWeight, snapshotUnitFee, consumeAmount);
|
|
|
+ return new SettleConsumeInfo(consumeAmount, transportNetWeight, param.getChargeStrategyId(),
|
|
|
+ null, buildSnapshotStrategyDesc(snapshotUnitFee));
|
|
|
+ }
|
|
|
+
|
|
|
KwtParkingChargeStrategy strategy = queryOptimalEnableStrategy(param.getProEntId());
|
|
|
if (strategy == null && param.getChargeStrategyId() != null) {
|
|
|
strategy = parkingChangeStrategyRepository.getById(param.getChargeStrategyId());
|
|
|
@@ -531,7 +820,6 @@ public class ParkingWalletFeeService {
|
|
|
param.getOrderNo(), param.getProEntId(), param.getSupEntId(), TRADE_TYPE_UNFREEZE,
|
|
|
unfreezeAmount, walletFee.getServiceFeeBalance());
|
|
|
}
|
|
|
-
|
|
|
/**
|
|
|
* 写入订单完结解冻明细(trade_type=5)
|
|
|
* 仅释放履约中金额至可用余额,不代表最终扣减完成
|
|
|
@@ -562,6 +850,7 @@ public class ParkingWalletFeeService {
|
|
|
walletFee.getServiceFeeBalance(), walletFee.getTradingAmount());
|
|
|
}
|
|
|
|
|
|
+
|
|
|
/**
|
|
|
* 写入订单完结扣减明细(trade_type=6)
|
|
|
* 标志服务费正式消费完成,同时作为结算幂等依据
|
|
|
@@ -608,6 +897,13 @@ public class ParkingWalletFeeService {
|
|
|
return unitFee.stripTrailingZeros().toPlainString() + "元/月";
|
|
|
}
|
|
|
|
|
|
+ private String buildSnapshotStrategyDesc(BigDecimal snapshotUnitFee) {
|
|
|
+ if (snapshotUnitFee == null || snapshotUnitFee.compareTo(ZERO_AMOUNT) <= 0) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ return snapshotUnitFee.stripTrailingZeros().toPlainString() + "元";
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 写入服务费钱包日志(kwt_parking_wallet_fee_balance)
|
|
|
*/
|
|
|
@@ -657,23 +953,19 @@ public class ParkingWalletFeeService {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 计算服务费余额支持的最大可购买数量
|
|
|
- * 仅在收费策略开关开启且单价大于0时计算:服务费余额 / 策略单价(向下取整,保留4位小数)
|
|
|
+ * 计算服务费余额支持的最大可购买数量。
|
|
|
+ * 仅在收费策略总开关开启且实际单价大于 0 时计算:服务费余额 / 单价(向下取整)。
|
|
|
*
|
|
|
- * @param currentStrategy 当前收费策略
|
|
|
- * @param currentStrategyUnitFee 策略单价
|
|
|
- * @param serviceFeeBalance 服务费余额
|
|
|
- * @return 最大可购买数量;策略未开启时不做余额约束,返回null
|
|
|
+ * @param currentStrategyUnitFee 实际计费单价(含 default_fee 兜底)
|
|
|
+ * @param serviceFeeBalance 服务费余额
|
|
|
+ * @return 最大可购买数量;开关未开启或单价无效时返回 null
|
|
|
*/
|
|
|
- private BigDecimal calculateMaxPurchaseQuantity(KwtParkingChargeStrategy currentStrategy,
|
|
|
- BigDecimal currentStrategyUnitFee,
|
|
|
+ private BigDecimal calculateMaxPurchaseQuantity(BigDecimal currentStrategyUnitFee,
|
|
|
BigDecimal serviceFeeBalance) {
|
|
|
boolean strategySwitchOpen = isChargeStrategySwitchOpen();
|
|
|
- if (!strategySwitchOpen || currentStrategy == null
|
|
|
- || currentStrategyUnitFee.compareTo(ZERO_AMOUNT) <= 0) {
|
|
|
+ if (!strategySwitchOpen || currentStrategyUnitFee.compareTo(ZERO_AMOUNT) <= 0) {
|
|
|
log.info("最大可购买数量未计算,原因:{}",
|
|
|
- !strategySwitchOpen ? "收费策略开关未开启"
|
|
|
- : currentStrategy == null ? "未匹配到收费策略" : "策略单价<=0");
|
|
|
+ !strategySwitchOpen ? "收费策略开关未开启" : "实际计费单价<=0");
|
|
|
return null;
|
|
|
}
|
|
|
//向下取整
|
|
|
@@ -683,6 +975,7 @@ public class ParkingWalletFeeService {
|
|
|
return maxPurchaseQuantity.max(ZERO_AMOUNT);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
/**
|
|
|
* 判断收费策略总开关是否开启(以 kwt_parking_strategy_switch 表为准)
|
|
|
*/
|
|
|
@@ -703,10 +996,20 @@ public class ParkingWalletFeeService {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 解析策略实际计费单价:method 为 0.00 时使用开关表 default_fee
|
|
|
+ * 解析策略实际计费单价。
|
|
|
+ * <ul>
|
|
|
+ * <li>无企业策略且收费策略总开关开启:使用 {@code kwt_parking_strategy_switch.default_fee}</li>
|
|
|
+ * <li>有企业策略且 method 为 0.00:使用开关表 default_fee</li>
|
|
|
+ * <li>有企业策略且 method > 0:使用策略 method</li>
|
|
|
+ * </ul>
|
|
|
*/
|
|
|
private BigDecimal resolveStrategyUnitFee(KwtParkingChargeStrategy strategy) {
|
|
|
if (strategy == null) {
|
|
|
+ if (isChargeStrategySwitchOpen()) {
|
|
|
+ BigDecimal defaultFee = resolveDefaultFee();
|
|
|
+ log.info("未匹配到企业收费策略,收费策略开关已开启,使用默认单价:{}", defaultFee);
|
|
|
+ return defaultFee;
|
|
|
+ }
|
|
|
return ZERO_AMOUNT;
|
|
|
}
|
|
|
BigDecimal method = strategy.getMethod() == null ? ZERO_AMOUNT : strategy.getMethod();
|
|
|
@@ -811,242 +1114,5 @@ public class ParkingWalletFeeService {
|
|
|
return walletFee.getServiceFeeBalance();
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 查询汇总服务费
|
|
|
- * @param param
|
|
|
- */
|
|
|
- public ParkingWalletFeeResp queryTotalServerFee(ParkingWalletFeeTotalQueryParam param) {
|
|
|
- log.info("查询汇总服务费:{}", JSON.toJSONString(param));
|
|
|
- //构建查询条件
|
|
|
- LambdaQueryWrapper<KwtParkingWalletFee> wrapper = buildAndExecuteQuery(param);
|
|
|
-
|
|
|
- // 初始化
|
|
|
- ParkingWalletFeeResp resp = new ParkingWalletFeeResp();
|
|
|
- resp.setServiceFeeBalance(BigDecimal.ZERO);
|
|
|
- resp.setTradingAmount(BigDecimal.ZERO);
|
|
|
-
|
|
|
- List<KwtParkingWalletFee> records = parkingWalletFeeRepository.list(wrapper);
|
|
|
- if (CollectionUtils.isEmpty(records)) {
|
|
|
- log.info("汇总服务费信息为空");
|
|
|
- return resp;
|
|
|
- }
|
|
|
- // 查询采购商汇总服务费
|
|
|
- if (param.getProEntId() != null) {
|
|
|
- return getProWalletFee(records.get(0));
|
|
|
- }
|
|
|
- // 查询平台汇总服务费
|
|
|
- if (param.getSupEntId() != null) {
|
|
|
- return getSupWalletFee(records);
|
|
|
- }
|
|
|
- return resp;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取采购商汇总服务费
|
|
|
- * @param fee
|
|
|
- */
|
|
|
- private ParkingWalletFeeResp getProWalletFee(KwtParkingWalletFee fee) {
|
|
|
- log.info("开始汇总采购商服务费,param:{}", JSON.toJSONString(fee));
|
|
|
-
|
|
|
- ParkingWalletFeeResp resp = new ParkingWalletFeeResp();
|
|
|
- resp.setServiceFeeBalance(fee.getServiceFeeBalance() != null ? fee.getServiceFeeBalance() : BigDecimal.ZERO);
|
|
|
- resp.setTradingAmount(fee.getTradingAmount() != null ? fee.getTradingAmount() : BigDecimal.ZERO);
|
|
|
- log.info("汇总采购商服务费结束,总余额:{}, 总履约中金额:{}", fee.getServiceFeeBalance(), fee.getTradingAmount());
|
|
|
- return resp;
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取平台汇总服务费
|
|
|
- * @param feeList
|
|
|
- */
|
|
|
- private ParkingWalletFeeResp getSupWalletFee(List<KwtParkingWalletFee> feeList) {
|
|
|
- log.info("开始汇总平台服务费, size:{}", CollectionUtils.isEmpty(feeList) ? 0 : feeList.size());
|
|
|
- // 汇总余额
|
|
|
- BigDecimal totalServiceFee = feeList.stream()
|
|
|
- .map(fee -> fee.getServiceFeeBalance() != null ? fee.getServiceFeeBalance() : BigDecimal.ZERO)
|
|
|
- .reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
- // 汇总冻结金额
|
|
|
- BigDecimal totalTradingAmount = feeList.stream()
|
|
|
- .map(fee -> fee.getTradingAmount() != null ? fee.getTradingAmount() : BigDecimal.ZERO)
|
|
|
- .reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
- ParkingWalletFeeResp resp = new ParkingWalletFeeResp();
|
|
|
- resp.setServiceFeeBalance(totalServiceFee);
|
|
|
- resp.setTradingAmount(totalTradingAmount);
|
|
|
- log.info("汇总平台服务费结束,总余额:{}, 总履约中金额:{}", totalServiceFee, totalTradingAmount);
|
|
|
- return resp;
|
|
|
- }
|
|
|
- /**
|
|
|
- * 构建查询条件并执行分页查询
|
|
|
- */
|
|
|
- private LambdaQueryWrapper<KwtParkingWalletFee> buildAndExecuteQuery(ParkingWalletFeeTotalQueryParam param) {
|
|
|
- return Wrappers.<KwtParkingWalletFee>lambdaQuery()
|
|
|
- .eq(param.getProEntId() != null, KwtParkingWalletFee::getProEntId, param.getProEntId())
|
|
|
- .eq(param.getSupEntId() != null, KwtParkingWalletFee::getSupEntId, param.getSupEntId())
|
|
|
- .orderByDesc(KwtParkingWalletFee::getUpdateTime);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 分页查询服务费
|
|
|
- * @param param
|
|
|
- */
|
|
|
- public PageDataResult<ParkingWalletFeeResp> pageQueryServerFee(ParkingWalletFeeQueryParam param) {
|
|
|
- log.info("分页查询服务费:{}", JSON.toJSONString(param));
|
|
|
-
|
|
|
- //构建查询条件
|
|
|
- LambdaQueryWrapper<KwtParkingWalletFee> wrapper = buildAndExecuteQuery(param);
|
|
|
-
|
|
|
- Page<KwtParkingWalletFee> pageByStatus = parkingWalletFeeRepository.page(new Page<>(param.getPageNum(), param.getPageSize()), wrapper);
|
|
|
- List<KwtParkingWalletFee> records = pageByStatus.getRecords();
|
|
|
- if (CollectionUtils.isEmpty(records)) {
|
|
|
- log.info("服务费信息为空");
|
|
|
- return PageDataResult.empty(param.getPageNum(), param.getPageSize());
|
|
|
- }
|
|
|
- List<ParkingWalletFeeResp> changeStrategyRespList = getWalletFeePageResult(records);
|
|
|
- return PageDataResult.success(param.getPageNum(), param.getPageSize(), pageByStatus.getTotal(), changeStrategyRespList);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取收费策略
|
|
|
- * @param records
|
|
|
- */
|
|
|
- private List<ParkingWalletFeeResp> getWalletFeePageResult(List<KwtParkingWalletFee> records) {
|
|
|
- log.info("组装服务费,param:{}", JSON.toJSONString(records));
|
|
|
- if (CollectionUtils.isEmpty(records)) {
|
|
|
- return Collections.emptyList();
|
|
|
- }
|
|
|
- List<ParkingWalletFeeResp> walletFeeList = records.stream()
|
|
|
- .map(fee -> {
|
|
|
- ParkingWalletFeeResp resp = new ParkingWalletFeeResp();
|
|
|
- resp.setId(fee.getId());
|
|
|
- resp.setProEntId(fee.getProEntId());
|
|
|
- resp.setProEntName(null);
|
|
|
- resp.setSupEntId(fee.getSupEntId());
|
|
|
- resp.setSupEntName(null);
|
|
|
- resp.setServiceFeeBalance(fee.getServiceFeeBalance());
|
|
|
- resp.setTradingAmount(fee.getTradingAmount());
|
|
|
- resp.setUpdateTime(fee.getUpdateTime());
|
|
|
- return resp;
|
|
|
- }).collect(Collectors.toList());
|
|
|
-
|
|
|
- log.info("组装服务费结束,size:{}", JSON.toJSONString(walletFeeList.size()));
|
|
|
- return walletFeeList;
|
|
|
- }
|
|
|
- /**
|
|
|
- * 构建查询条件并执行分页查询
|
|
|
- */
|
|
|
- private LambdaQueryWrapper<KwtParkingWalletFee> buildAndExecuteQuery(ParkingWalletFeeQueryParam param) {
|
|
|
- return Wrappers.<KwtParkingWalletFee>lambdaQuery()
|
|
|
- .eq(param.getSupEntId() != null, KwtParkingWalletFee::getSupEntId, param.getSupEntId())
|
|
|
- .eq(param.getProEntId() != null, KwtParkingWalletFee::getProEntId, param.getProEntId())
|
|
|
- .orderByDesc(KwtParkingWalletFee::getUpdateTime);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 保存服务费
|
|
|
- * @param param
|
|
|
- */
|
|
|
- @Transactional(rollbackFor = Exception.class)
|
|
|
- public void saveServerFee(ParkingWalletFeeSaveParam param) {
|
|
|
- log.info("保存服务费,param:{}", JSON.toJSONString(param));
|
|
|
- KwtParkingWalletFee walletFee = parkingWalletFeeRepository.getById(param.getId());
|
|
|
- if (walletFee == null) {
|
|
|
- throw new BusinessPlatfromException(ErrorCodeEnum.DRIVER_NOT_FOUND, "服务费信息不存在");
|
|
|
- }
|
|
|
- // 1. 先修改服务余额
|
|
|
- walletFee.setServiceFeeBalance(walletFee.getServiceFeeBalance().add(param.getServiceFee()));
|
|
|
- parkingWalletFeeRepository.updateById(walletFee);
|
|
|
-
|
|
|
- // 2.新增明细
|
|
|
- KwtParkingWalletFeeBalance feeBalance = new KwtParkingWalletFeeBalance();
|
|
|
- feeBalance.setProEntId(param.getEntId());
|
|
|
- feeBalance.setTradeType(9);
|
|
|
- feeBalance.setTradeAmount(param.getServiceFee());
|
|
|
- feeBalance.setServiceFeeBalance(walletFee.getServiceFeeBalance());
|
|
|
- feeBalance.setTradingAmount(walletFee.getTradingAmount());
|
|
|
- feeBalance.setVoucherUrl(param.getVoucherUrl());
|
|
|
- feeBalance.setRemark(param.getRemark());
|
|
|
- parkingWalletFeeBalanceRepository.save(feeBalance);
|
|
|
- }
|
|
|
- /**
|
|
|
- * 分页查询服务费明细
|
|
|
- * @param param
|
|
|
- */
|
|
|
- public PageDataResult<ParkingWalletFeeBalanceResp> pageQueryServerFeeDetails(ParkingWalletFeeBalanceQueryParam param) {
|
|
|
- log.info("分页查询服务费明细:{}", JSON.toJSONString(param));
|
|
|
-
|
|
|
- //构建查询条件
|
|
|
- LambdaQueryWrapper<KwtParkingWalletFeeBalance> wrapper = buildAndExecuteQuery(param);
|
|
|
|
|
|
- Page<KwtParkingWalletFeeBalance> pageByStatus = parkingWalletFeeBalanceRepository.page(new Page<>(param.getPageNum(), param.getPageSize()), wrapper);
|
|
|
- List<KwtParkingWalletFeeBalance> records = pageByStatus.getRecords();
|
|
|
- if (CollectionUtils.isEmpty(records)) {
|
|
|
- log.info("分页查询服务费明细为空");
|
|
|
- return PageDataResult.empty(param.getPageNum(), param.getPageSize());
|
|
|
- }
|
|
|
- List<ParkingWalletFeeBalanceResp> changeStrategyRespList = getWalletFeeBalancePageResult(records);
|
|
|
- return PageDataResult.success(param.getPageNum(), param.getPageSize(), pageByStatus.getTotal(), changeStrategyRespList);
|
|
|
- }
|
|
|
- /**
|
|
|
- * 构建查询条件并执行分页查询
|
|
|
- */
|
|
|
- private LambdaQueryWrapper<KwtParkingWalletFeeBalance> buildAndExecuteQuery(ParkingWalletFeeBalanceQueryParam param) {
|
|
|
- return Wrappers.<KwtParkingWalletFeeBalance>lambdaQuery()
|
|
|
- .eq(param.getSupEntId() != null, KwtParkingWalletFeeBalance::getSupEntId, param.getSupEntId())
|
|
|
- .eq(param.getProEntId() != null, KwtParkingWalletFeeBalance::getProEntId, param.getProEntId())
|
|
|
- .eq(KwtParkingWalletFeeBalance::getOrderNo, param.getOrderNo())
|
|
|
- .eq(KwtParkingWalletFeeBalance::getTradeType, param.getTradeType())
|
|
|
- .ge(KwtParkingWalletFeeBalance::getTradeAmount, param.getMinFee())
|
|
|
- .le(KwtParkingWalletFeeBalance::getTradeAmount, param.getMaxFee())
|
|
|
- .ge(KwtParkingWalletFeeBalance::getCreateTime, param.getStartCreateTime())
|
|
|
- .le(KwtParkingWalletFeeBalance::getCreateTime, param.getEndCreateTime())
|
|
|
- .orderByDesc(KwtParkingWalletFeeBalance::getServiceFeeBalance);
|
|
|
- }
|
|
|
- /**
|
|
|
- * 获取服务费明细
|
|
|
- * @param records
|
|
|
- */
|
|
|
- private List<ParkingWalletFeeBalanceResp> getWalletFeeBalancePageResult(List<KwtParkingWalletFeeBalance> records) {
|
|
|
- log.info("组装服务费明细,param:{}", JSON.toJSONString(records));
|
|
|
- if (CollectionUtils.isEmpty(records)) {
|
|
|
- return Collections.emptyList();
|
|
|
- }
|
|
|
- List<ParkingWalletFeeBalanceResp> walletFeeList = records.stream()
|
|
|
- .map(feeBalance -> {
|
|
|
- ParkingWalletFeeBalanceResp resp = new ParkingWalletFeeBalanceResp();
|
|
|
- resp.setId(feeBalance.getId());
|
|
|
- resp.setOrderNo(feeBalance.getOrderNo());
|
|
|
- resp.setProEntId(feeBalance.getProEntId());
|
|
|
- resp.setProEntName(getEntName(feeBalance.getProEntId()));
|
|
|
- resp.setSupEntId(feeBalance.getSupEntId());
|
|
|
- resp.setSupEntName(getEntName(feeBalance.getSupEntId()));
|
|
|
- resp.setTradeType(feeBalance.getTradeType());
|
|
|
- resp.setTradeTypeDesc(WalletTypEnum.getDescByCode(feeBalance.getTradeType()));
|
|
|
- resp.setTradeAmount(feeBalance.getTradeAmount());
|
|
|
- resp.setServiceFeeBalance(feeBalance.getServiceFeeBalance());
|
|
|
- resp.setTradingAmount(feeBalance.getTradingAmount());
|
|
|
- resp.setVoucherUrl(feeBalance.getVoucherUrl());
|
|
|
- resp.setRemark(feeBalance.getRemark());
|
|
|
- resp.setCreateTime(feeBalance.getCreateTime());
|
|
|
- return resp;
|
|
|
- }).collect(Collectors.toList());
|
|
|
-
|
|
|
- log.info("组装服务费明细结束,size:{}", JSON.toJSONString(walletFeeList.size()));
|
|
|
- return walletFeeList;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- /**
|
|
|
- * 通过企业id查询企业名称
|
|
|
- * @param entId
|
|
|
- */
|
|
|
- private String getEntName(Long entId) {
|
|
|
- // 查询企业名称
|
|
|
- EntCacheResDto entCacheResDto = remoteSystemService.queryEntDetails(entId);
|
|
|
- if (entCacheResDto == null) {
|
|
|
- return null;
|
|
|
- }
|
|
|
- return entCacheResDto.getFirmName();
|
|
|
- }
|
|
|
}
|