订单费用明细
This commit is contained in:
parent
fab86d8bab
commit
9986bc195b
@ -4,15 +4,51 @@ import cn.dev33.satoken.stp.StpUtil;
|
|||||||
import com.cdzy.common.ex.EbikeException;
|
import com.cdzy.common.ex.EbikeException;
|
||||||
import com.cdzy.common.model.dto.ResGPSDto;
|
import com.cdzy.common.model.dto.ResGPSDto;
|
||||||
import com.cdzy.common.model.request.PageParam;
|
import com.cdzy.common.model.request.PageParam;
|
||||||
import com.cdzy.operations.enums.*;
|
import com.cdzy.operations.enums.BatteryStatus;
|
||||||
import com.cdzy.operations.mapper.*;
|
import com.cdzy.operations.enums.BikeOrderType;
|
||||||
|
import com.cdzy.operations.enums.BikeQrStatus;
|
||||||
|
import com.cdzy.operations.enums.BikeStatus;
|
||||||
|
import com.cdzy.operations.enums.BikeUsageStatus;
|
||||||
|
import com.cdzy.operations.enums.OrderDispatchState;
|
||||||
|
import com.cdzy.operations.enums.OrderHandleState;
|
||||||
|
import com.cdzy.operations.enums.RegionStatus;
|
||||||
|
import com.cdzy.operations.enums.SpecialBillingConfigurationType;
|
||||||
|
import com.cdzy.operations.mapper.EbiekSpecialDayMapper;
|
||||||
|
import com.cdzy.operations.mapper.EbiekSpecialTimeMapper;
|
||||||
|
import com.cdzy.operations.mapper.EbikeBatteryInfoMapper;
|
||||||
|
import com.cdzy.operations.mapper.EbikeBikeInfoMapper;
|
||||||
|
import com.cdzy.operations.mapper.EbikeBikeOrderMapper;
|
||||||
|
import com.cdzy.operations.mapper.EbikeBikeQrMapper;
|
||||||
|
import com.cdzy.operations.mapper.EbikeDefaultBillingConfigurationMapper;
|
||||||
|
import com.cdzy.operations.mapper.EbikeRegionMapper;
|
||||||
|
import com.cdzy.operations.mapper.EbikeSiteMapper;
|
||||||
|
import com.cdzy.operations.mapper.EbikeSpecialBillingConfigurationMapper;
|
||||||
import com.cdzy.operations.model.dto.EbikeBikeInfoDto;
|
import com.cdzy.operations.model.dto.EbikeBikeInfoDto;
|
||||||
import com.cdzy.operations.model.dto.EbikeDto;
|
import com.cdzy.operations.model.dto.EbikeDto;
|
||||||
import com.cdzy.operations.model.dto.EbikeUserBikeInfo;
|
import com.cdzy.operations.model.dto.EbikeUserBikeInfo;
|
||||||
import com.cdzy.operations.model.dto.EbikeUserLockDto;
|
import com.cdzy.operations.model.dto.EbikeUserLockDto;
|
||||||
import com.cdzy.operations.model.entity.*;
|
import com.cdzy.operations.model.entity.EbikeBatteryInfo;
|
||||||
import com.cdzy.operations.model.vo.*;
|
import com.cdzy.operations.model.entity.EbikeBikeInfo;
|
||||||
import com.cdzy.operations.service.*;
|
import com.cdzy.operations.model.entity.EbikeBikeOrder;
|
||||||
|
import com.cdzy.operations.model.entity.EbikeBikeQr;
|
||||||
|
import com.cdzy.operations.model.entity.EbikeDefaultBillingConfiguration;
|
||||||
|
import com.cdzy.operations.model.entity.EbikeDispatchConfiguration;
|
||||||
|
import com.cdzy.operations.model.entity.EbikeEcuInfo;
|
||||||
|
import com.cdzy.operations.model.entity.EbikeInventoryRecord;
|
||||||
|
import com.cdzy.operations.model.entity.EbikeRegion;
|
||||||
|
import com.cdzy.operations.model.entity.EbikeSpecialBillingConfiguration;
|
||||||
|
import com.cdzy.operations.model.entity.EbikeSpecialDay;
|
||||||
|
import com.cdzy.operations.model.entity.EbikeSpecialTime;
|
||||||
|
import com.cdzy.operations.model.vo.EbikeBatchLaunchVo;
|
||||||
|
import com.cdzy.operations.model.vo.EbikeBatchUnLaunchVo;
|
||||||
|
import com.cdzy.operations.model.vo.EbikeBikeBindVo;
|
||||||
|
import com.cdzy.operations.model.vo.EbikeBikeRadiusVo;
|
||||||
|
import com.cdzy.operations.model.vo.EbikeInventoryVo;
|
||||||
|
import com.cdzy.operations.service.EbikeBikeInfoService;
|
||||||
|
import com.cdzy.operations.service.EbikeDispatchConfigurationService;
|
||||||
|
import com.cdzy.operations.service.EbikeEcuInfoService;
|
||||||
|
import com.cdzy.operations.service.EbikeInventoryRecordService;
|
||||||
|
import com.cdzy.operations.service.EbikeInventoryService;
|
||||||
import com.cdzy.operations.utils.RedisUtil;
|
import com.cdzy.operations.utils.RedisUtil;
|
||||||
import com.ebike.feign.model.vo.EbikeLockVo;
|
import com.ebike.feign.model.vo.EbikeLockVo;
|
||||||
import com.mybatisflex.core.paginate.Page;
|
import com.mybatisflex.core.paginate.Page;
|
||||||
@ -365,6 +401,8 @@ public class EbikeBikeInfoServiceImpl extends ServiceImpl<EbikeBikeInfoMapper, E
|
|||||||
bikeOrder.setHandleState(OrderHandleState.VOIDED);
|
bikeOrder.setHandleState(OrderHandleState.VOIDED);
|
||||||
orderMapper.update(bikeOrder);
|
orderMapper.update(bikeOrder);
|
||||||
}
|
}
|
||||||
|
// 删除redis中的 车辆多长时间无单生成调度工单
|
||||||
|
redisUtil.deleteNoDocument(bikeCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@ -488,7 +488,7 @@ public class RedisUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数据库2专用:存储 辆多长时间无单生成调度工单 并设置过期时间
|
* 数据库2专用:删除 车辆多长时间无单生成调度工单
|
||||||
*/
|
*/
|
||||||
public void deleteNoDocument(String bikeCode) {
|
public void deleteNoDocument(String bikeCode) {
|
||||||
delete(Database.DB2, BIKE_NO_DOCUMENT_PREFIX + bikeCode);
|
delete(Database.DB2, BIKE_NO_DOCUMENT_PREFIX + bikeCode);
|
||||||
|
|||||||
@ -19,9 +19,6 @@ import java.time.LocalDateTime;
|
|||||||
@Data
|
@Data
|
||||||
public class EbikeOrderDetailVo {
|
public class EbikeOrderDetailVo {
|
||||||
|
|
||||||
/**
|
|
||||||
* 订单表主键ID
|
|
||||||
*/
|
|
||||||
private Long orderId;
|
private Long orderId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -177,4 +174,24 @@ public class EbikeOrderDetailVo {
|
|||||||
* 是否免费订单 true-免费 false-收费
|
* 是否免费订单 true-免费 false-收费
|
||||||
*/
|
*/
|
||||||
private Boolean isFreeOrder;
|
private Boolean isFreeOrder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户花费时长费用
|
||||||
|
*/
|
||||||
|
private BigDecimal userDurationFee;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户花费起步费用
|
||||||
|
*/
|
||||||
|
private BigDecimal userBaseFee;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户花费调度费用
|
||||||
|
*/
|
||||||
|
private BigDecimal userDispatchFee;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户头盔费用
|
||||||
|
*/
|
||||||
|
private BigDecimal userHelmetFee;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -310,28 +310,13 @@ public class EbikeOrderServiceImpl extends ServiceImpl<EbikeOrderMapper, EbikeOr
|
|||||||
public EbikeOrderDetailVo getInfo(Long orderId) {
|
public EbikeOrderDetailVo getInfo(Long orderId) {
|
||||||
QueryWrapper queryWrapper = QueryWrapper.create()
|
QueryWrapper queryWrapper = QueryWrapper.create()
|
||||||
.select(
|
.select(
|
||||||
EBIKE_ORDER.ORDER_ID,
|
EBIKE_ORDER.ALL_COLUMNS
|
||||||
EBIKE_ORDER.USER_ID,
|
|
||||||
EBIKE_ORDER.OPERATOR_ID,
|
|
||||||
EBIKE_ORDER.BIKE_CODE,
|
|
||||||
EBIKE_ORDER.ORDER_TYPE,
|
|
||||||
EBIKE_ORDER.ORDER_STATUS,
|
|
||||||
EBIKE_ORDER.TOTAL_AMOUNT,
|
|
||||||
EBIKE_ORDER.ACTUAL_AMOUNT,
|
|
||||||
EBIKE_ORDER.START_TIME,
|
|
||||||
EBIKE_ORDER.END_TIME,
|
|
||||||
EBIKE_ORDER.PAYMENT_TIME,
|
|
||||||
EBIKE_ORDER.PAYMENT_METHOD,
|
|
||||||
EBIKE_ORDER.BASE_DURATION_MINUTES,
|
|
||||||
EBIKE_ORDER.FREE_DURATION_MINUTES,
|
|
||||||
EBIKE_ORDER.CHARGE_DURATION_MINUTES,
|
|
||||||
EBIKE_ORDER.MAX_FEE_AMOUNT,
|
|
||||||
EBIKE_ORDER.START_LOCATION,
|
|
||||||
EBIKE_ORDER.END_LOCATION,
|
|
||||||
EBIKE_ORDER.IS_FREE_ORDER
|
|
||||||
)
|
)
|
||||||
.where(EBIKE_ORDER.ORDER_ID.eq(orderId));
|
.where(EBIKE_ORDER.ORDER_ID.eq(orderId));
|
||||||
EbikeOrderDetailVo ebikeOrderDetailVo = this.mapper.selectOneByQueryAs(queryWrapper, EbikeOrderDetailVo.class);
|
EbikeOrderDetailVo ebikeOrderDetailVo = this.mapper.selectOneByQueryAs(queryWrapper, EbikeOrderDetailVo.class);
|
||||||
|
if (Objects.isNull(ebikeOrderDetailVo)) {
|
||||||
|
throw new EbikeException("订单不存在");
|
||||||
|
}
|
||||||
//获取费用详情
|
//获取费用详情
|
||||||
List<EbikePaymentCostDetailVo> details = ebikeOrderDetailService.getOrderDetailsByOrderId(orderId);
|
List<EbikePaymentCostDetailVo> details = ebikeOrderDetailService.getOrderDetailsByOrderId(orderId);
|
||||||
if (Objects.nonNull(details)) {
|
if (Objects.nonNull(details)) {
|
||||||
@ -340,27 +325,27 @@ public class EbikeOrderServiceImpl extends ServiceImpl<EbikeOrderMapper, EbikeOr
|
|||||||
switch (payDetailVo.getDetailType()) {
|
switch (payDetailVo.getDetailType()) {
|
||||||
case 1 -> {
|
case 1 -> {
|
||||||
BigDecimal current = payDetailVo.getDetailAmount();
|
BigDecimal current = payDetailVo.getDetailAmount();
|
||||||
ebikeOrderDetailVo.setDurationFee((current != null ? current : BigDecimal.ZERO));
|
ebikeOrderDetailVo.setUserDurationFee((current != null ? current : BigDecimal.ZERO));
|
||||||
}
|
}
|
||||||
case 2 -> {
|
case 2 -> {
|
||||||
BigDecimal current = payDetailVo.getDetailAmount();
|
BigDecimal current = payDetailVo.getDetailAmount();
|
||||||
ebikeOrderDetailVo.setBaseFee((current != null ? current : BigDecimal.ZERO));
|
ebikeOrderDetailVo.setUserBaseFee((current != null ? current : BigDecimal.ZERO));
|
||||||
}
|
}
|
||||||
case 3 -> {
|
case 3 -> {
|
||||||
BigDecimal current = payDetailVo.getDetailAmount();
|
BigDecimal current = payDetailVo.getDetailAmount();
|
||||||
ebikeOrderDetailVo.setOutOfServiceAreaFee((current != null ? current : BigDecimal.ZERO));
|
ebikeOrderDetailVo.setUserDispatchFee((current != null ? current : BigDecimal.ZERO));
|
||||||
}
|
}
|
||||||
case 4 -> {
|
case 4 -> {
|
||||||
BigDecimal current = payDetailVo.getDetailAmount();
|
BigDecimal current = payDetailVo.getDetailAmount();
|
||||||
ebikeOrderDetailVo.setOutOfParkingAreaFee((current != null ? current : BigDecimal.ZERO));
|
ebikeOrderDetailVo.setUserDispatchFee((current != null ? current : BigDecimal.ZERO));
|
||||||
}
|
}
|
||||||
case 5 -> {
|
case 5 -> {
|
||||||
BigDecimal current = payDetailVo.getDetailAmount();
|
BigDecimal current = payDetailVo.getDetailAmount();
|
||||||
ebikeOrderDetailVo.setNoParkingZoneFee((current != null ? current : BigDecimal.ZERO));
|
ebikeOrderDetailVo.setUserDispatchFee((current != null ? current : BigDecimal.ZERO));
|
||||||
}
|
}
|
||||||
case 6 -> {
|
case 6 -> {
|
||||||
BigDecimal current = payDetailVo.getDetailAmount();
|
BigDecimal current = payDetailVo.getDetailAmount();
|
||||||
ebikeOrderDetailVo.setHelmetManagementFee((current != null ? current : BigDecimal.ZERO));
|
ebikeOrderDetailVo.setUserHelmetFee((current != null ? current : BigDecimal.ZERO));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -459,61 +444,68 @@ public class EbikeOrderServiceImpl extends ServiceImpl<EbikeOrderMapper, EbikeOr
|
|||||||
* @return 订单费用
|
* @return 订单费用
|
||||||
*/
|
*/
|
||||||
private EbikeCostDetailDto costCalculation(LocalDateTime endTime,
|
private EbikeCostDetailDto costCalculation(LocalDateTime endTime,
|
||||||
EbikeOrder order, FeignEbikeUserLockDto data) {
|
EbikeOrder order,
|
||||||
// 基础费用计算
|
FeignEbikeUserLockDto data) {
|
||||||
|
EbikeCostDetailDto dto = new EbikeCostDetailDto();
|
||||||
|
|
||||||
|
// 1. 基础参数
|
||||||
BigDecimal baseFee = Objects.requireNonNullElse(order.getBaseFee(), BigDecimal.ZERO);
|
BigDecimal baseFee = Objects.requireNonNullElse(order.getBaseFee(), BigDecimal.ZERO);
|
||||||
BigDecimal durationFee = Objects.requireNonNullElse(order.getDurationFee(), BigDecimal.ZERO);
|
BigDecimal durationFee = Objects.requireNonNullElse(order.getDurationFee(), BigDecimal.ZERO);
|
||||||
Integer freeDurationMinutes = order.getFreeDurationMinutes();
|
Integer freeDurationMinutes = Objects.requireNonNullElse(order.getFreeDurationMinutes(), 0);
|
||||||
Integer chargeDurationMinutes = order.getChargeDurationMinutes();
|
Integer baseDurationMinutes = Objects.requireNonNullElse(order.getBaseDurationMinutes(), 0);
|
||||||
// 获取总骑行时长(秒)
|
int chargeDurationMinutes = Objects.requireNonNullElse(order.getChargeDurationMinutes(), 1);
|
||||||
|
|
||||||
|
// 2. 计算总骑行时长(秒)
|
||||||
long totalRideSeconds = Duration.between(order.getStartTime(), endTime).toSeconds();
|
long totalRideSeconds = Duration.between(order.getStartTime(), endTime).toSeconds();
|
||||||
// 免费时间(秒)
|
// 向上取整为分钟
|
||||||
long freeDurationSeconds = freeDurationMinutes * GlobalConstants.LONG_SIXTY;
|
long totalRideMinutes = (totalRideSeconds + 59) / 60;
|
||||||
// 如果骑行时长小于等于免费时长,不收费
|
|
||||||
BigDecimal baseCost;
|
// 3. 免费阶段:总时长 <= 免费时长
|
||||||
EbikeCostDetailDto ebikeCostDetailDto = new EbikeCostDetailDto();
|
if (totalRideMinutes <= freeDurationMinutes) {
|
||||||
// 起步费用
|
dto.setTotalCost(BigDecimal.ZERO);
|
||||||
ebikeCostDetailDto.setBaseFee(baseFee);
|
return dto;
|
||||||
if (totalRideSeconds <= freeDurationSeconds) {
|
|
||||||
ebikeCostDetailDto.setTotalCost(BigDecimal.ZERO);
|
|
||||||
return ebikeCostDetailDto;
|
|
||||||
} else {
|
|
||||||
long totalRoundedMinutes = (totalRideSeconds + GlobalConstants.NUMBER_FIFTY_NINE) / GlobalConstants.NUMBER_SIXTY;
|
|
||||||
// 可计费分钟数 = 向上取整后的总分钟 - 免费分钟
|
|
||||||
long chargeableMinutes = totalRoundedMinutes - freeDurationMinutes;
|
|
||||||
long chargeUnits = (chargeableMinutes + chargeDurationMinutes - 1) / chargeDurationMinutes;
|
|
||||||
BigDecimal durationCost = durationFee.multiply(BigDecimal.valueOf(chargeUnits));
|
|
||||||
// 时长费用
|
|
||||||
ebikeCostDetailDto.setDurationFee(durationCost);
|
|
||||||
// 总基础费用
|
|
||||||
baseCost = baseFee.add(durationCost);
|
|
||||||
}
|
}
|
||||||
// 计算调度费(按优先级判断附加费用:运营区 > 停车区外 > 禁停区)
|
|
||||||
|
// 4. 起步阶段:免费之后,但未超出起步时长 只收起步费
|
||||||
|
long includedInBaseMinutes = freeDurationMinutes + baseDurationMinutes;
|
||||||
|
if (totalRideMinutes <= includedInBaseMinutes) {
|
||||||
|
dto.setBaseFee(baseFee);
|
||||||
|
dto.setTotalCost(baseFee);
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 超出起步阶段:计算额外时长费用
|
||||||
|
long extraMinutes = totalRideMinutes - includedInBaseMinutes;
|
||||||
|
long chargeUnits = (extraMinutes + chargeDurationMinutes - 1) / chargeDurationMinutes;
|
||||||
|
BigDecimal durationCost = durationFee.multiply(BigDecimal.valueOf(chargeUnits));
|
||||||
|
|
||||||
|
dto.setBaseFee(baseFee);
|
||||||
|
dto.setDurationFee(durationCost);
|
||||||
|
BigDecimal baseCost = baseFee.add(durationCost);
|
||||||
|
|
||||||
|
// 6. 调度费用
|
||||||
BigDecimal additionalFee = BigDecimal.ZERO;
|
BigDecimal additionalFee = BigDecimal.ZERO;
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
// 运营区
|
|
||||||
if (Boolean.FALSE.equals(data.getBikeInRegion())) {
|
if (Boolean.FALSE.equals(data.getBikeInRegion())) {
|
||||||
additionalFee = order.getOutOfServiceAreaFee() != null ? order.getOutOfServiceAreaFee() : BigDecimal.ZERO;
|
additionalFee = Objects.requireNonNullElse(order.getOutOfServiceAreaFee(), BigDecimal.ZERO);
|
||||||
ebikeCostDetailDto.setOutOfServiceAreaFee(additionalFee);
|
dto.setOutOfServiceAreaFee(additionalFee);
|
||||||
} else if (Boolean.FALSE.equals(data.getBikeInParking())) {
|
} else if (Boolean.FALSE.equals(data.getBikeInParking())) {
|
||||||
// 不在运营区内但在停车区内
|
additionalFee = Objects.requireNonNullElse(order.getOutOfParkingAreaFee(), BigDecimal.ZERO);
|
||||||
additionalFee = order.getOutOfParkingAreaFee() != null ? order.getOutOfParkingAreaFee() : BigDecimal.ZERO;
|
dto.setOutOfParkingAreaFee(additionalFee);
|
||||||
ebikeCostDetailDto.setOutOfParkingAreaFee(additionalFee);
|
} else if (Boolean.TRUE.equals(data.getBikeInNoParking())) {
|
||||||
} else if (Boolean.FALSE.equals(data.getBikeInNoParking())) {
|
additionalFee = Objects.requireNonNullElse(order.getNoParkingZoneFee(), BigDecimal.ZERO);
|
||||||
// 不在运营区内也不在停车区内,但在禁停区内
|
dto.setNoParkingZoneFee(additionalFee);
|
||||||
additionalFee = order.getNoParkingZoneFee() != null ? order.getNoParkingZoneFee() : BigDecimal.ZERO;
|
|
||||||
ebikeCostDetailDto.setNoParkingZoneFee(additionalFee);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 计算总费用
|
|
||||||
|
// 7. 总费用 + 封顶
|
||||||
BigDecimal totalCost = baseCost.add(additionalFee);
|
BigDecimal totalCost = baseCost.add(additionalFee);
|
||||||
// 检查是否超过封顶金额
|
|
||||||
BigDecimal maxFee = order.getMaxFeeAmount();
|
BigDecimal maxFee = order.getMaxFeeAmount();
|
||||||
if (maxFee != null && totalCost.compareTo(maxFee) > 0) {
|
if (maxFee != null && totalCost.compareTo(maxFee) > 0) {
|
||||||
totalCost = maxFee;
|
totalCost = maxFee;
|
||||||
}
|
}
|
||||||
ebikeCostDetailDto.setTotalCost(totalCost);
|
dto.setTotalCost(totalCost);
|
||||||
return ebikeCostDetailDto;
|
return dto;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user