计费规则:默认计算
This commit is contained in:
parent
55684426b1
commit
8f44c10610
@ -69,4 +69,13 @@ public class EbikeOrderDetails implements Serializable {
|
|||||||
@Column(onInsertValue = "now()")
|
@Column(onInsertValue = "now()")
|
||||||
private LocalDateTime createdAt;
|
private LocalDateTime createdAt;
|
||||||
|
|
||||||
|
public EbikeOrderDetails(Long orderId, Integer itemType, String itemName, BigDecimal itemAmount, String calculationRule, String couponId, LocalDateTime createdAt) {
|
||||||
|
this.orderId = orderId;
|
||||||
|
this.itemType = itemType;
|
||||||
|
this.itemName = itemName;
|
||||||
|
this.itemAmount = itemAmount;
|
||||||
|
this.calculationRule = calculationRule;
|
||||||
|
this.couponId = couponId;
|
||||||
|
this.createdAt = createdAt;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -162,6 +162,7 @@ public class UserOrdersServiceImpl extends ServiceImpl<UserOrdersMapper, EbikeUs
|
|||||||
FeignEbikeRegionDto regionDto = regionResult.getData();
|
FeignEbikeRegionDto regionDto = regionResult.getData();
|
||||||
|
|
||||||
ResFeignEbikeSysRcostsetDto feignEbikeSysRcostsetDto = operateJsonResult.getData();
|
ResFeignEbikeSysRcostsetDto feignEbikeSysRcostsetDto = operateJsonResult.getData();
|
||||||
|
//费用计算
|
||||||
costCalculation(feignEbikeSysRcostsetDto, resGpsDto, regionDto, userOrders);
|
costCalculation(feignEbikeSysRcostsetDto, resGpsDto, regionDto, userOrders);
|
||||||
userOrdersMapper.update(userOrders);
|
userOrdersMapper.update(userOrders);
|
||||||
//关锁,并且等待结果
|
//关锁,并且等待结果
|
||||||
@ -346,7 +347,8 @@ public class UserOrdersServiceImpl extends ServiceImpl<UserOrdersMapper, EbikeUs
|
|||||||
boolean pointInParking = redisUtil.isPointInParking(resGpsDto.getLongitude(), resGpsDto.getLatitude(), regionDto.getOrgId());
|
boolean pointInParking = redisUtil.isPointInParking(resGpsDto.getLongitude(), resGpsDto.getLatitude(), regionDto.getOrgId());
|
||||||
long minutes = TimeUtils.betweenMinutes(userOrders.getStartTime(), userOrders.getEndTime());
|
long minutes = TimeUtils.betweenMinutes(userOrders.getStartTime(), userOrders.getEndTime());
|
||||||
//是否取消订单
|
//是否取消订单
|
||||||
if (pointInOperation && pointInParking && minutes < feignEbikeSysRcostsetDto.getFreeDuration()) {
|
Integer freeDuration = feignEbikeSysRcostsetDto.getFreeDuration();
|
||||||
|
if (pointInOperation && pointInParking && minutes < freeDuration) {
|
||||||
userOrders.setStatus(OrderStatus.CANCELLED);
|
userOrders.setStatus(OrderStatus.CANCELLED);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -374,7 +376,7 @@ public class UserOrdersServiceImpl extends ServiceImpl<UserOrdersMapper, EbikeUs
|
|||||||
list.add(orderDetails);
|
list.add(orderDetails);
|
||||||
totalAmount = totalAmount.add(operationAreaSchedulingFee);
|
totalAmount = totalAmount.add(operationAreaSchedulingFee);
|
||||||
}
|
}
|
||||||
//时长费用计算
|
//时长费用计算(已知超出免费时长
|
||||||
Character timeDivisionCharging = feignEbikeSysRcostsetDto.getTimeDivisionCharging();
|
Character timeDivisionCharging = feignEbikeSysRcostsetDto.getTimeDivisionCharging();
|
||||||
BigDecimal decimal = switch (timeDivisionCharging) {
|
BigDecimal decimal = switch (timeDivisionCharging) {
|
||||||
case TIME_SLOT -> timeSlotCostCalculation(list, userOrders, feignEbikeSysRcostsetDto);
|
case TIME_SLOT -> timeSlotCostCalculation(list, userOrders, feignEbikeSysRcostsetDto);
|
||||||
@ -384,7 +386,7 @@ public class UserOrdersServiceImpl extends ServiceImpl<UserOrdersMapper, EbikeUs
|
|||||||
totalAmount = totalAmount.add(decimal);
|
totalAmount = totalAmount.add(decimal);
|
||||||
BigDecimal cappedAmount = feignEbikeSysRcostsetDto.getCappedAmount();
|
BigDecimal cappedAmount = feignEbikeSysRcostsetDto.getCappedAmount();
|
||||||
int result = cappedAmount.compareTo(totalAmount);
|
int result = cappedAmount.compareTo(totalAmount);
|
||||||
if (result == 1){
|
if (result > 0){
|
||||||
totalAmount = cappedAmount;
|
totalAmount = cappedAmount;
|
||||||
}
|
}
|
||||||
userOrders.setStatus(OrderStatus.PENDING_PAYMENT);
|
userOrders.setStatus(OrderStatus.PENDING_PAYMENT);
|
||||||
@ -401,7 +403,7 @@ public class UserOrdersServiceImpl extends ServiceImpl<UserOrdersMapper, EbikeUs
|
|||||||
* @return 计费后总金额
|
* @return 计费后总金额
|
||||||
*/
|
*/
|
||||||
BigDecimal timeSlotCostCalculation(List<EbikeOrderDetails> list, EbikeUserOrders userOrders, ResFeignEbikeSysRcostsetDto feignEbikeSysRcostsetDto) {
|
BigDecimal timeSlotCostCalculation(List<EbikeOrderDetails> list, EbikeUserOrders userOrders, ResFeignEbikeSysRcostsetDto feignEbikeSysRcostsetDto) {
|
||||||
BigDecimal decimal = new BigDecimal(0);
|
BigDecimal decimal = BigDecimal.ZERO;
|
||||||
//TODO:计算起步费用后时间后移
|
//TODO:计算起步费用后时间后移
|
||||||
List<TimeSegment> timeSegments = TimeUtils.splitByDays(userOrders.getStartTime(), userOrders.getEndTime());
|
List<TimeSegment> timeSegments = TimeUtils.splitByDays(userOrders.getStartTime(), userOrders.getEndTime());
|
||||||
//TODO:时间划分不同自然时间段,每一段才判断在高峰时间段内有多长时间收费多少,非高峰期多长时间收费多少
|
//TODO:时间划分不同自然时间段,每一段才判断在高峰时间段内有多长时间收费多少,非高峰期多长时间收费多少
|
||||||
@ -477,7 +479,7 @@ public class UserOrdersServiceImpl extends ServiceImpl<UserOrdersMapper, EbikeUs
|
|||||||
* @return 计费后总金额
|
* @return 计费后总金额
|
||||||
*/
|
*/
|
||||||
BigDecimal weekCostCalculation(List<EbikeOrderDetails> list, EbikeUserOrders userOrders, ResFeignEbikeSysRcostsetDto feignEbikeSysRcostsetDto) {
|
BigDecimal weekCostCalculation(List<EbikeOrderDetails> list, EbikeUserOrders userOrders, ResFeignEbikeSysRcostsetDto feignEbikeSysRcostsetDto) {
|
||||||
BigDecimal decimal = new BigDecimal(0);
|
BigDecimal decimal = BigDecimal.ZERO;
|
||||||
LocalDateTime startTime = userOrders.getStartTime();
|
LocalDateTime startTime = userOrders.getStartTime();
|
||||||
LocalDateTime endTime = userOrders.getEndTime();
|
LocalDateTime endTime = userOrders.getEndTime();
|
||||||
Long orderId = userOrders.getOrderId();
|
Long orderId = userOrders.getOrderId();
|
||||||
@ -487,113 +489,12 @@ public class UserOrdersServiceImpl extends ServiceImpl<UserOrdersMapper, EbikeUs
|
|||||||
for (int i = 0; i < timeSegments.size(); i++) {
|
for (int i = 0; i < timeSegments.size(); i++) {
|
||||||
TimeSegment timeSegment = timeSegments.get(i);
|
TimeSegment timeSegment = timeSegments.get(i);
|
||||||
boolean checked = checkWeek(timeSegment, feignEbikeSysRcostsetDto);
|
boolean checked = checkWeek(timeSegment, feignEbikeSysRcostsetDto);
|
||||||
BigDecimal dailiedFee = dailyFee(timeSegment, feignEbikeSysRcostsetDto, i < 1, checked, list, orderId);
|
BigDecimal dailiedFee = BigDecimal.ZERO;
|
||||||
decimal = decimal.add(dailiedFee);
|
decimal = decimal.add(dailiedFee);
|
||||||
}
|
}
|
||||||
return decimal;
|
return decimal;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据自然时间段计算高峰出行日费用
|
|
||||||
*
|
|
||||||
* @param timeSegment 时间段
|
|
||||||
* @param feignEbikeSysRcostsetDto 计算规则
|
|
||||||
* @return 金额
|
|
||||||
*/
|
|
||||||
BigDecimal dailyFee(TimeSegment timeSegment, ResFeignEbikeSysRcostsetDto feignEbikeSysRcostsetDto, boolean isStart, boolean isWeek, List<EbikeOrderDetails> list, long orderId) {
|
|
||||||
BigDecimal decimal = new BigDecimal(0);
|
|
||||||
List<ResFeignEbikeSysRcostsetWeekDto> weekDtos = feignEbikeSysRcostsetDto.getEbikeSysRcostsetWeekDtos();
|
|
||||||
LocalDateTime startTime = timeSegment.getStart();
|
|
||||||
String weekNumber = TimeUtils.getDayOfWeekNumber(startTime);
|
|
||||||
LocalDateTime endTime = timeSegment.getEnd();
|
|
||||||
long minutes = TimeUtils.betweenMinutes(startTime, endTime);
|
|
||||||
BigDecimal minutesNew = BigDecimal.valueOf(minutes);
|
|
||||||
if (isWeek) {
|
|
||||||
//高峰日出现计算
|
|
||||||
for (ResFeignEbikeSysRcostsetWeekDto weekCostCalculation : weekDtos) {
|
|
||||||
//根据符合要求的规则计算费用
|
|
||||||
if (weekCostCalculation.getWeek().contains(weekNumber)) {
|
|
||||||
if (isStart) {
|
|
||||||
EbikeOrderDetails orderDetails = new EbikeOrderDetails();
|
|
||||||
orderDetails.setOrderId(orderId);
|
|
||||||
orderDetails.setItemAmount(weekCostCalculation.getStartupCost());
|
|
||||||
orderDetails.setItemType(OrderDetailsType.TRAVEL_EXPENSES_ON_PEAK_DAYS);
|
|
||||||
orderDetails.setItemName("高峰日出行费用-起步费用");
|
|
||||||
orderDetails.setCalculationRule(JSONObject.toJSONString(feignEbikeSysRcostsetDto));
|
|
||||||
list.add(orderDetails);
|
|
||||||
Integer startupDuration = weekCostCalculation.getStartupDuration();
|
|
||||||
if (minutes > startupDuration) {
|
|
||||||
|
|
||||||
BigDecimal startupDurationNew = BigDecimal.valueOf(startupDuration);
|
|
||||||
//超出时长(总时长减去起步时长
|
|
||||||
minutesNew = minutesNew.subtract(startupDurationNew);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//时长计费
|
|
||||||
BigDecimal durationCost = weekCostCalculation.getDurationCost();
|
|
||||||
//时长多久计费一次
|
|
||||||
Integer duration = weekCostCalculation.getDuration();
|
|
||||||
//总计费几次(向上取整
|
|
||||||
int ceil = NumberUtils.divideAndCeil(duration, minutesNew.intValue());
|
|
||||||
BigDecimal ceilCost = BigDecimal.valueOf(ceil);
|
|
||||||
//最终值
|
|
||||||
BigDecimal multiply = durationCost.multiply(ceilCost);
|
|
||||||
|
|
||||||
EbikeOrderDetails durationCostOrderDetails = new EbikeOrderDetails();
|
|
||||||
durationCostOrderDetails.setOrderId(orderId);
|
|
||||||
durationCostOrderDetails.setItemAmount(multiply);
|
|
||||||
durationCostOrderDetails.setItemType(OrderDetailsType.TRAVEL_EXPENSES_ON_PEAK_DAYS);
|
|
||||||
durationCostOrderDetails.setItemName("高峰日出行费用-时长计费");
|
|
||||||
durationCostOrderDetails.setCalculationRule(JSONObject.toJSONString(feignEbikeSysRcostsetDto));
|
|
||||||
list.add(durationCostOrderDetails);
|
|
||||||
decimal = decimal.add(multiply);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
//非高峰出行日计费
|
|
||||||
if (isStart) {
|
|
||||||
//起始计费
|
|
||||||
Integer startupDuration = feignEbikeSysRcostsetDto.getStartupDuration();
|
|
||||||
BigDecimal startupCost = feignEbikeSysRcostsetDto.getStartupCost();
|
|
||||||
EbikeOrderDetails orderDetails = new EbikeOrderDetails();
|
|
||||||
orderDetails.setOrderId(orderId);
|
|
||||||
orderDetails.setItemAmount(startupCost);
|
|
||||||
orderDetails.setItemType(OrderDetailsType.STARTING_FEE);
|
|
||||||
orderDetails.setItemName("起步费用");
|
|
||||||
orderDetails.setCalculationRule(JSONObject.toJSONString(feignEbikeSysRcostsetDto));
|
|
||||||
list.add(orderDetails);
|
|
||||||
decimal = decimal.add(startupCost);
|
|
||||||
//超出起步时长计费
|
|
||||||
if (minutes > startupDuration) {
|
|
||||||
BigDecimal startupDurationNew = BigDecimal.valueOf(startupDuration);
|
|
||||||
//超出时长
|
|
||||||
minutesNew = minutesNew.subtract(startupDurationNew);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//时长计费
|
|
||||||
BigDecimal durationCost = feignEbikeSysRcostsetDto.getDurationCost();
|
|
||||||
//时长多久计费一次
|
|
||||||
Integer duration = feignEbikeSysRcostsetDto.getDuration();
|
|
||||||
//总计费几次(向上取整
|
|
||||||
int ceil = NumberUtils.divideAndCeil(duration, minutesNew.intValue());
|
|
||||||
BigDecimal ceilCost = BigDecimal.valueOf(ceil);
|
|
||||||
//最终值
|
|
||||||
BigDecimal multiply = durationCost.multiply(ceilCost);
|
|
||||||
|
|
||||||
EbikeOrderDetails durationCostOrderDetails = new EbikeOrderDetails();
|
|
||||||
durationCostOrderDetails.setOrderId(orderId);
|
|
||||||
durationCostOrderDetails.setItemAmount(multiply);
|
|
||||||
durationCostOrderDetails.setItemType(OrderDetailsType.CYCLING_DURATION_FEE);
|
|
||||||
durationCostOrderDetails.setItemName("时长计费");
|
|
||||||
durationCostOrderDetails.setCalculationRule(JSONObject.toJSONString(feignEbikeSysRcostsetDto));
|
|
||||||
list.add(durationCostOrderDetails);
|
|
||||||
decimal = decimal.add(multiply);
|
|
||||||
}
|
|
||||||
return decimal;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查是否高峰期
|
* 检查是否高峰期
|
||||||
@ -622,10 +523,31 @@ public class UserOrdersServiceImpl extends ServiceImpl<UserOrdersMapper, EbikeUs
|
|||||||
* @return 计费后总金额
|
* @return 计费后总金额
|
||||||
*/
|
*/
|
||||||
BigDecimal defaultCostCalculation(List<EbikeOrderDetails> list, EbikeUserOrders userOrders, ResFeignEbikeSysRcostsetDto feignEbikeSysRcostsetDto, long orderId) {
|
BigDecimal defaultCostCalculation(List<EbikeOrderDetails> list, EbikeUserOrders userOrders, ResFeignEbikeSysRcostsetDto feignEbikeSysRcostsetDto, long orderId) {
|
||||||
|
BigDecimal decimal = BigDecimal.ZERO;
|
||||||
LocalDateTime startTime = userOrders.getStartTime();
|
LocalDateTime startTime = userOrders.getStartTime();
|
||||||
LocalDateTime endTime = userOrders.getEndTime();
|
LocalDateTime endTime = userOrders.getEndTime();
|
||||||
//TODO:计算起步费用后时间后移
|
long minutes = TimeUtils.betweenMinutes(startTime, endTime);
|
||||||
TimeSegment timeSegment = new TimeSegment(startTime, endTime);
|
BigDecimal startupCost = feignEbikeSysRcostsetDto.getStartupCost();
|
||||||
return dailyFee(timeSegment, feignEbikeSysRcostsetDto, true, false, list, orderId);
|
EbikeOrderDetails startupDetails = new EbikeOrderDetails(orderId,OrderDetailsType.STARTING_FEE,"默认起步费用",startupCost,JSONObject.toJSONString(feignEbikeSysRcostsetDto),null,LocalDateTime.now());
|
||||||
|
list.add(startupDetails);
|
||||||
|
decimal = decimal.add(startupCost);
|
||||||
|
Integer startupDuration = feignEbikeSysRcostsetDto.getStartupDuration();
|
||||||
|
//判断是否超出起步时长
|
||||||
|
if (minutes>startupDuration) {
|
||||||
|
startTime = startTime.plusMinutes(startupDuration);
|
||||||
|
long newMinutes = TimeUtils.betweenMinutes(startTime, endTime);
|
||||||
|
Integer duration = feignEbikeSysRcostsetDto.getDuration();
|
||||||
|
//时长费用
|
||||||
|
BigDecimal durationCost = feignEbikeSysRcostsetDto.getDurationCost();
|
||||||
|
int newMinutesInt = NumberUtils.longConvertInt(newMinutes);
|
||||||
|
int ceil = NumberUtils.divideAndCeil(newMinutesInt, duration);
|
||||||
|
BigDecimal bigDecimalCeil = BigDecimal.valueOf(ceil);
|
||||||
|
//总时长费用
|
||||||
|
BigDecimal multiply = bigDecimalCeil.multiply(durationCost);
|
||||||
|
EbikeOrderDetails timeDetails = new EbikeOrderDetails(orderId,OrderDetailsType.CYCLING_DURATION_FEE,"默认时长费用",multiply,JSONObject.toJSONString(feignEbikeSysRcostsetDto),null,LocalDateTime.now());
|
||||||
|
list.add(timeDetails);
|
||||||
|
decimal = decimal.add(multiply);
|
||||||
|
}
|
||||||
|
return decimal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,6 +23,18 @@ public final class NumberUtils {
|
|||||||
return (int) Math.ceil((double) dividend / divisor);
|
return (int) Math.ceil((double) dividend / divisor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 安全的将long转换为int
|
||||||
|
* @param value long值
|
||||||
|
* @return int值
|
||||||
|
*/
|
||||||
|
public static int longConvertInt(long value) {
|
||||||
|
if (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) {
|
||||||
|
throw new ArithmeticException("大小超出安全值");
|
||||||
|
}
|
||||||
|
return (int) value;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 安全转换字符串为整数
|
* 安全转换字符串为整数
|
||||||
* @param str 要转换的字符串
|
* @param str 要转换的字符串
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user