实时计费

This commit is contained in:
attiya 2025-05-09 09:49:29 +08:00
parent a58c437d98
commit 63687abe0b
3 changed files with 60 additions and 66 deletions

View File

@ -16,6 +16,7 @@ import jakarta.validation.constraints.NotBlank;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import java.util.List; import java.util.List;
import static com.cdzy.orders.model.entity.table.EbikeUserOrdersTableDef.EBIKE_USER_ORDERS; import static com.cdzy.orders.model.entity.table.EbikeUserOrdersTableDef.EBIKE_USER_ORDERS;
@ -108,6 +109,18 @@ public class EbikeUserOrdersController {
return JsonResult.success(orderId); return JsonResult.success(orderId);
} }
/**
* 实时计费
*
* @param orderDto 骑行信息
* @ {@code 200} 删除成功{@code 500} 删除失败
*/
@PostMapping("costCalculation")
public JsonResult<?> costCalculation(@RequestBody @Validated ReqOrderDto orderDto) {
BigDecimal total = userOrdersService.costOrderCalculation(orderDto);
return JsonResult.success(total);
}
/** /**
* 订单支付 * 订单支付
* *

View File

@ -8,6 +8,7 @@ import com.cdzy.orders.model.dto.res.RspBikeDto;
import com.mybatisflex.core.service.IService; import com.mybatisflex.core.service.IService;
import com.cdzy.orders.model.entity.EbikeUserOrders; import com.cdzy.orders.model.entity.EbikeUserOrders;
import java.math.BigDecimal;
import java.util.List; import java.util.List;
/** /**
@ -99,4 +100,11 @@ public interface UserOrdersService extends IService<EbikeUserOrders> {
* @return 详情 * @return 详情
*/ */
RspOrderDetailsInfo orderDetailsInfo(Long orderId); RspOrderDetailsInfo orderDetailsInfo(Long orderId);
/**
* 实时计费订单费用
* @param orderDto 订单信息
* @return 金额
*/
BigDecimal costOrderCalculation(ReqOrderDto orderDto);
} }

View File

@ -13,7 +13,6 @@ import com.cdzy.orders.model.dto.req.ReqOrderDto;
import com.cdzy.orders.model.dto.res.RedisPoint; import com.cdzy.orders.model.dto.res.RedisPoint;
import com.cdzy.orders.model.dto.res.RspBikeDto; import com.cdzy.orders.model.dto.res.RspBikeDto;
import com.cdzy.orders.model.dto.res.RspOrderDetailsInfo; import com.cdzy.orders.model.dto.res.RspOrderDetailsInfo;
import com.cdzy.orders.model.dto.res.TimeSegment;
import com.cdzy.orders.model.entity.EbikeOrderDetails; import com.cdzy.orders.model.entity.EbikeOrderDetails;
import com.cdzy.orders.model.entity.EbikeUserOrders; import com.cdzy.orders.model.entity.EbikeUserOrders;
import com.cdzy.orders.service.UserOrdersService; import com.cdzy.orders.service.UserOrdersService;
@ -23,6 +22,7 @@ import com.cdzy.orders.uitls.TimeUtils;
import com.ebike.feign.clients.MaintenanceFeignClient; import com.ebike.feign.clients.MaintenanceFeignClient;
import com.ebike.feign.clients.OperateFeignClient; import com.ebike.feign.clients.OperateFeignClient;
import com.ebike.feign.model.res.ResFeignEbikeSysRcostsetDto; import com.ebike.feign.model.res.ResFeignEbikeSysRcostsetDto;
import com.ebike.feign.model.res.ResFeignEbikeSysRcostsetTimePeriodDto;
import com.ebike.feign.model.res.ResFeignEbikeSysRcostsetWeekDto; import com.ebike.feign.model.res.ResFeignEbikeSysRcostsetWeekDto;
import com.ebike.feign.model.res.ResFeignOrderPaymentDto; import com.ebike.feign.model.res.ResFeignOrderPaymentDto;
import com.ebike.feign.model.rsp.FeignEbikeBikeInfoDto; import com.ebike.feign.model.rsp.FeignEbikeBikeInfoDto;
@ -163,7 +163,7 @@ public class UserOrdersServiceImpl extends ServiceImpl<UserOrdersMapper, EbikeUs
ResFeignEbikeSysRcostsetDto feignEbikeSysRcostsetDto = operateJsonResult.getData(); ResFeignEbikeSysRcostsetDto feignEbikeSysRcostsetDto = operateJsonResult.getData();
//费用计算 //费用计算
costCalculation(feignEbikeSysRcostsetDto, resGpsDto, regionDto, userOrders); costCalculation(feignEbikeSysRcostsetDto, resGpsDto, regionDto, userOrders,Boolean.TRUE);
userOrdersMapper.update(userOrders); userOrdersMapper.update(userOrders);
//关锁,并且等待结果 //关锁,并且等待结果
CompletableFuture<String> stringCompletableFuture = ebikeCoreHandler.executeCommand(ecuInfo, CmdCode.LOCK, Long.valueOf(bikeInfoDto.getBikeId()), userId); CompletableFuture<String> stringCompletableFuture = ebikeCoreHandler.executeCommand(ecuInfo, CmdCode.LOCK, Long.valueOf(bikeInfoDto.getBikeId()), userId);
@ -315,6 +315,36 @@ public class UserOrdersServiceImpl extends ServiceImpl<UserOrdersMapper, EbikeUs
return this.mapper.selectOneWithRelationsByIdAs(orderId, RspOrderDetailsInfo.class); return this.mapper.selectOneWithRelationsByIdAs(orderId, RspOrderDetailsInfo.class);
} }
@Override
public BigDecimal costOrderCalculation(ReqOrderDto orderDto) {
EbikeUserOrders userOrders = getOrder(orderDto);
userOrders.setEndTime(LocalDateTime.now());
JsonResult<FeignEbikeBikeInfoDto> jsonResult = maintenanceFeignClient.getEbikeInfoByCode(orderDto.getBikeCode());
if (jsonResult.getCode() != Code.SUCCESS) {
throw new RuntimeException("获取车辆信息失败");
}
FeignEbikeBikeInfoDto bikeInfoDto = jsonResult.getData();
FeignEbikeEcuInfo ecuInfo = bikeInfoDto.getEbikeEcuInfo();
String jsonString = JSONObject.toJSONString(redisUtil.get(ecuInfo.getEcuSn()));
ResGPSDto resGpsDto = JSONObject.parseObject(jsonString, ResGPSDto.class);
JsonResult<ResFeignEbikeSysRcostsetDto> operateJsonResult = operateFeignClient.getRegionFeeConfigById(bikeInfoDto.getReginId());
if (operateJsonResult.getCode() != Code.SUCCESS) {
throw new RuntimeException("获取计费规则失败");
}
JsonResult<FeignEbikeRegionDto> regionResult = operateFeignClient.getOperationById(bikeInfoDto.getReginId());
if (regionResult.getCode() != Code.SUCCESS) {
throw new RuntimeException("获取运营区信息失败");
}
FeignEbikeRegionDto regionDto = regionResult.getData();
ResFeignEbikeSysRcostsetDto feignEbikeSysRcostsetDto = operateJsonResult.getData();
//费用计算
costCalculation(feignEbikeSysRcostsetDto, resGpsDto, regionDto, userOrders,Boolean.FALSE);
return userOrders.getTotalAmount();
}
@Override @Override
public void payment(ResFeignOrderPaymentDto paymentDto) { public void payment(ResFeignOrderPaymentDto paymentDto) {
EbikeUserOrders userOrders = this.mapper.selectOneById(paymentDto.getOrderId()); EbikeUserOrders userOrders = this.mapper.selectOneById(paymentDto.getOrderId());
@ -338,7 +368,7 @@ public class UserOrdersServiceImpl extends ServiceImpl<UserOrdersMapper, EbikeUs
* @param regionDto 运营区域信息 * @param regionDto 运营区域信息
* @param userOrders 订单信息 * @param userOrders 订单信息
*/ */
void costCalculation(ResFeignEbikeSysRcostsetDto feignEbikeSysRcostsetDto, ResGPSDto resGpsDto, FeignEbikeRegionDto regionDto, EbikeUserOrders userOrders) { void costCalculation(ResFeignEbikeSysRcostsetDto feignEbikeSysRcostsetDto, ResGPSDto resGpsDto, FeignEbikeRegionDto regionDto, EbikeUserOrders userOrders,boolean orderDetailsCreate) {
BigDecimal totalAmount = BigDecimal.ZERO; BigDecimal totalAmount = BigDecimal.ZERO;
List<EbikeOrderDetails> list = new ArrayList<>(); List<EbikeOrderDetails> list = new ArrayList<>();
//是否在运营区内 //是否在运营区内
@ -391,7 +421,10 @@ public class UserOrdersServiceImpl extends ServiceImpl<UserOrdersMapper, EbikeUs
} }
userOrders.setStatus(OrderStatus.PENDING_PAYMENT); userOrders.setStatus(OrderStatus.PENDING_PAYMENT);
userOrders.setTotalAmount(totalAmount); userOrders.setTotalAmount(totalAmount);
orderDetailsMapper.insertBatch(list); userOrders.setActualAmount(totalAmount);
if (orderDetailsCreate){
orderDetailsMapper.insertBatch(list);
}
} }
/** /**
@ -405,71 +438,11 @@ public class UserOrdersServiceImpl extends ServiceImpl<UserOrdersMapper, EbikeUs
BigDecimal timeSlotCostCalculation(List<EbikeOrderDetails> list, EbikeUserOrders userOrders, ResFeignEbikeSysRcostsetDto feignEbikeSysRcostsetDto) { BigDecimal timeSlotCostCalculation(List<EbikeOrderDetails> list, EbikeUserOrders userOrders, ResFeignEbikeSysRcostsetDto feignEbikeSysRcostsetDto) {
BigDecimal decimal = BigDecimal.ZERO; BigDecimal decimal = BigDecimal.ZERO;
//TODO计算起步费用后时间后移 //TODO计算起步费用后时间后移
List<TimeSegment> timeSegments = TimeUtils.splitByDays(userOrders.getStartTime(), userOrders.getEndTime()); List<ResFeignEbikeSysRcostsetTimePeriodDto> timePeriodDtos = feignEbikeSysRcostsetDto.getEbikeSysRcostsetTimePeriodDtos();
//TODO:时间划分不同自然时间段每一段才判断在高峰时间段内有多长时间收费多少非高峰期多长时间收费多少
for (TimeSegment timeSegment : timeSegments) {
BigDecimal timeFee = timeFee(timeSegment, feignEbikeSysRcostsetDto, list, userOrders.getOrderId());
decimal = decimal.add(timeFee);
}
return decimal; return decimal;
} }
/**
* 根据自然时间段计算出现费用高峰时段
*
* @param timeSegment 自然时间段按天划分
* @param feignEbikeSysRcostsetDto 计算规则
* @param list 订单详细列表
* @param orderId 订单编号
* @return 当前时间段收取金额
*/
BigDecimal timeFee(TimeSegment timeSegment, ResFeignEbikeSysRcostsetDto feignEbikeSysRcostsetDto, List<EbikeOrderDetails> list, long orderId) {
BigDecimal decimal = BigDecimal.ZERO;
// LocalDateTime start = timeSegment.getStart();
// LocalDateTime end = timeSegment.getEnd();
// LocalTime orderStartupTime = LocalTime.of(start.getHour(), start.getMinute(), start.getSecond());
// LocalTime orderEndTime = LocalTime.of(end.getHour(), end.getMinute(), end.getSecond());
// boolean checkedStart = false;
// List<ResFeignEbikeSysRcostsetTimePeriodDto> ebikeSysRcostsetTimePeriodDtos = feignEbikeSysRcostsetDto.getEbikeSysRcostsetTimePeriodDtos();
// //收集订单所满足计费条件的所有时段费用
// for (ResFeignEbikeSysRcostsetTimePeriodDto timePeriodDto : ebikeSysRcostsetTimePeriodDtos) {
// LocalTime timePeriodDtoStartupTime = timePeriodDto.getStartupTime();
// LocalTime timePeriodDtoEndTime = timePeriodDto.getEndTime();
// boolean createBeforeTimePeriodDtoEndTime = orderStartupTime.isBefore(timePeriodDtoEndTime);
// boolean createAfterTimePeriodDtoStartupTime = orderEndTime.isAfter(timePeriodDtoStartupTime);
// //满足计费条件进行计费
// if (createBeforeTimePeriodDtoEndTime && createAfterTimePeriodDtoStartupTime) {
// //起点在高峰内
// boolean after = orderStartupTime.isAfter(timePeriodDtoStartupTime);
// boolean before = orderEndTime.isBefore(timePeriodDtoEndTime);
// if (after) {
// //添加起步费用
// BigDecimal startupCost = timePeriodDto.getStartupCost();
// Integer startupDuration = timePeriodDto.getStartupDuration();
// decimal = decimal.add(startupCost);
// long minutes = TimeUtils.betweenMinutes(orderStartupTime, orderEndTime);
// BigDecimal minutesNew = new BigDecimal(minutes);
// if (minutes > startupDuration) {
// BigDecimal startupDurationNew = new BigDecimal(startupDuration);
// BigDecimal subtract = minutesNew.subtract(startupDurationNew);
// //结束点在高峰内
// if (before) {
// BigDecimal durationCost = timePeriodDto.getDurationCost();
// Integer duration = timePeriodDto.getDuration();
// int ceil = NumberUtils.divideAndCeil(duration, subtract.intValue());
// BigDecimal ceilCost = BigDecimal.valueOf(ceil);
// //最终值
// BigDecimal multiply = durationCost.multiply(ceilCost);
// decimal = decimal.add(multiply);
// }
// }
// }
//
// }
// }
//计算常规费用
return decimal;
}
/** /**
* 按照时间段计费 * 按照时间段计费