diff --git a/src/main/java/com/sczx/order/common/enums/SubOrderTypeEnum.java b/src/main/java/com/sczx/order/common/enums/SubOrderTypeEnum.java index 03f332e..f41f13d 100644 --- a/src/main/java/com/sczx/order/common/enums/SubOrderTypeEnum.java +++ b/src/main/java/com/sczx/order/common/enums/SubOrderTypeEnum.java @@ -15,7 +15,8 @@ public enum SubOrderTypeEnum { RENTCAR("RENTCAR", "租车订单"), RENTBATTEY("RENTBATTEY", "租电订单"), OVERDUE("OVERDUE", "逾期订单"), - FD_DEPOSIT("FD_DEPOSIT", "退押金订单") + FD_DEPOSIT("FD_DEPOSIT", "退押金订单"), + FD_REJECT("FD_REJECT", "驳回退款订单") ; private final String code; diff --git a/src/main/java/com/sczx/order/controller/StoreOrderController.java b/src/main/java/com/sczx/order/controller/StoreOrderController.java index 2d23888..70d0741 100644 --- a/src/main/java/com/sczx/order/controller/StoreOrderController.java +++ b/src/main/java/com/sczx/order/controller/StoreOrderController.java @@ -36,12 +36,25 @@ public class StoreOrderController { return Result.ok(orderService.pageStoreOrder(pageNo, pageSize, storeOrderQueryReq)); } + @ApiOperation(value = "驳回租车订单") + @PostMapping("/rejectRentOrder") + public Result rejectRentOrder(@RequestBody RejectOrderReq rejectOrderReq){ + orderService.rejectRentOrder(rejectOrderReq); + return Result.ok(true); + } + @ApiOperation(value = "绑定车辆") @PostMapping("/bindCarToOrder") public Result bindCarToOrder(@RequestBody BindCarToOrderReq bindCarToOrderReq){ return Result.ok(orderService.bindCarToOrder(bindCarToOrderReq)); } + @ApiOperation(value = "更换车辆") + @PostMapping("/changeCarToOrder") + public Result changeCarToOrder(@RequestBody BindCarToOrderReq bindCarToOrderReq){ + return Result.ok(orderService.changeCarToOrder(bindCarToOrderReq)); + } + @ApiOperation(value = "确认还车") @PostMapping("/confirmReturnCar") public Result confirmReturnCar(@RequestBody ReturnCarReq returnCarReq){ diff --git a/src/main/java/com/sczx/order/dto/RejectOrderReq.java b/src/main/java/com/sczx/order/dto/RejectOrderReq.java new file mode 100644 index 0000000..9748391 --- /dev/null +++ b/src/main/java/com/sczx/order/dto/RejectOrderReq.java @@ -0,0 +1,19 @@ +package com.sczx.order.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Builder; +import lombok.Data; + + +@Builder +@ApiModel(value = "驳回订单请求") +@Data +public class RejectOrderReq { + + @ApiModelProperty(value = "订单编号") + private String orderNo; + + @ApiModelProperty(value = "驳回原因") + private String rejectReason; +} diff --git a/src/main/java/com/sczx/order/mapper/OrderCarChangeMapper.java b/src/main/java/com/sczx/order/mapper/OrderCarChangeMapper.java new file mode 100644 index 0000000..b4fe111 --- /dev/null +++ b/src/main/java/com/sczx/order/mapper/OrderCarChangeMapper.java @@ -0,0 +1,16 @@ +package com.sczx.order.mapper; + +import com.sczx.order.po.OrderCarChangePO; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 订单车辆变更表 Mapper 接口 + *

+ * + * @author zhangli + * @since 2025-09-03 23:12:55 + */ +public interface OrderCarChangeMapper extends BaseMapper { + +} diff --git a/src/main/java/com/sczx/order/po/OrderCarChangePO.java b/src/main/java/com/sczx/order/po/OrderCarChangePO.java new file mode 100644 index 0000000..ba3c98b --- /dev/null +++ b/src/main/java/com/sczx/order/po/OrderCarChangePO.java @@ -0,0 +1,65 @@ +package com.sczx.order.po; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Getter; +import lombok.Setter; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + *

+ * 订单车辆变更表 + *

+ * + * @author zhangli + * @since 2025-09-03 23:12:55 + */ +@Getter +@Setter +@TableName("zc_order_car_change") +@ApiModel(value = "OrderCarChangePO对象", description = "订单车辆变更表") +public class OrderCarChangePO implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty("ID(主键)") + @TableId(value = "id", type = IdType.AUTO) + private Long id; + + @ApiModelProperty("关联的订单ID(外键)") + private Long orderId; + + @ApiModelProperty("订单编号") + private String orderNo; + + @ApiModelProperty("子订单编号") + private String orderSubNo; + + @ApiModelProperty("原车辆ID") + private Long oldVehicleId; + + @ApiModelProperty("原车车架号") + private String oldVehicleVin; + + @ApiModelProperty("新车辆ID") + private Long newVehicleId; + + @ApiModelProperty("新车车架号") + private String newVehicleVin; + + @ApiModelProperty("删除标志(0代表存在 2代表删除)") + private String delFlag; + + @ApiModelProperty("创建时间") + private LocalDateTime createTime; + + @ApiModelProperty("更新时间") + private LocalDateTime updateTime; + + +} diff --git a/src/main/java/com/sczx/order/repository/OrderCarChangeRepo.java b/src/main/java/com/sczx/order/repository/OrderCarChangeRepo.java new file mode 100644 index 0000000..b3ffe8c --- /dev/null +++ b/src/main/java/com/sczx/order/repository/OrderCarChangeRepo.java @@ -0,0 +1,16 @@ +package com.sczx.order.repository; + +import com.sczx.order.po.OrderCarChangePO; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 订单车辆变更表 服务类 + *

+ * + * @author zhangli + * @since 2025-09-03 23:12:55 + */ +public interface OrderCarChangeRepo extends IService { + +} diff --git a/src/main/java/com/sczx/order/repository/impl/OrderCarChangeRepoImpl.java b/src/main/java/com/sczx/order/repository/impl/OrderCarChangeRepoImpl.java new file mode 100644 index 0000000..c773f3b --- /dev/null +++ b/src/main/java/com/sczx/order/repository/impl/OrderCarChangeRepoImpl.java @@ -0,0 +1,20 @@ +package com.sczx.order.repository.impl; + +import com.sczx.order.po.OrderCarChangePO; +import com.sczx.order.mapper.OrderCarChangeMapper; +import com.sczx.order.repository.OrderCarChangeRepo; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + *

+ * 订单车辆变更表 服务实现类 + *

+ * + * @author zhangli + * @since 2025-09-03 23:12:55 + */ +@Service +public class OrderCarChangeRepoImpl extends ServiceImpl implements OrderCarChangeRepo { + +} diff --git a/src/main/java/com/sczx/order/service/OrderService.java b/src/main/java/com/sczx/order/service/OrderService.java index 6e65b5e..232a9ee 100644 --- a/src/main/java/com/sczx/order/service/OrderService.java +++ b/src/main/java/com/sczx/order/service/OrderService.java @@ -71,7 +71,11 @@ public interface OrderService { */ OrderDetailDTO getCurrentNoEndOrder(Long customerId); - + /** + * 驳回租车订单 + * @param rejectOrderReq + */ + void rejectRentOrder(RejectOrderReq rejectOrderReq); /** * 绑定车辆到订单 @@ -80,6 +84,13 @@ public interface OrderService { */ OrderDTO bindCarToOrder(BindCarToOrderReq bindCarToOrderReq); + /** + * 修改车辆到订单 + * @param bindCarToOrderReq + * @return + */ + OrderDTO changeCarToOrder(BindCarToOrderReq bindCarToOrderReq); + /** * 申请还车 * @param returnCarReq diff --git a/src/main/java/com/sczx/order/service/impl/OrderServiceImpl.java b/src/main/java/com/sczx/order/service/impl/OrderServiceImpl.java index f39925b..30a13b1 100644 --- a/src/main/java/com/sczx/order/service/impl/OrderServiceImpl.java +++ b/src/main/java/com/sczx/order/service/impl/OrderServiceImpl.java @@ -11,14 +11,8 @@ import com.sczx.order.convert.OrderSubConvert; import com.sczx.order.dto.*; import com.sczx.order.exception.BizException; import com.sczx.order.exception.InnerException; -import com.sczx.order.po.CarPO; -import com.sczx.order.po.OrderCarImgPO; -import com.sczx.order.po.OrderMainPO; -import com.sczx.order.po.OrderSubPO; -import com.sczx.order.repository.CarRepo; -import com.sczx.order.repository.OrderCarImgRepo; -import com.sczx.order.repository.OrderMainRepo; -import com.sczx.order.repository.OrderSubRepo; +import com.sczx.order.po.*; +import com.sczx.order.repository.*; import com.sczx.order.service.OrderDistribService; import com.sczx.order.service.OrderService; import com.sczx.order.service.PayService; @@ -63,6 +57,9 @@ public class OrderServiceImpl implements OrderService { @Autowired private OrderSubRepo orderSubRepo; + @Autowired + private OrderCarChangeRepo orderCarChangeRepo; + @Autowired private JwtUtil jwtUtil; @@ -730,6 +727,48 @@ public class OrderServiceImpl implements OrderService { return getOrderDetailByOrderNo(orderMainPO.getOrderNo()); } + @Transactional(rollbackFor = Exception.class) + @Override + public void rejectRentOrder(RejectOrderReq rejectOrderReq) { + OrderMainPO orderMainPO = queryOrderMainPoByOrderNo(rejectOrderReq.getOrderNo(), "0"); + if(!orderMainPO.getOrderStatus().equals(OrderStatusEnum.WAIT_PICK.getCode())){ + throw new BizException("订单状态异常,非待取车状态,无法驳回"); + } + SimpleUserInfoDTO userInfoDTO = jwtUtil.getUserInfoFromToken(); + //获取租车子订单 + LambdaQueryWrapper orderSubWrapper = new LambdaQueryWrapper<>(); + orderSubWrapper.eq(OrderSubPO::getOrderId, orderMainPO.getOrderId()) + .eq(OrderSubPO::getDelFlag, "0") + .eq(OrderSubPO::getSuborderType, SubOrderTypeEnum.RENTCAR.getCode()) + .eq(OrderSubPO::getPayStatus, PayStatusEnum.SUCCESS).last(" limit 1"); + OrderSubPO orderSubPO = orderSubRepo.getOne(orderSubWrapper); + //异步退款订单 + ThreadPoolUtils.getThreadPool().execute(() -> { + //变更订单状态,记录结束订单时间,记录订单备注 + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); + updateWrapper.set(OrderMainPO::getOrderStatus, OrderStatusEnum.MANUAL_END.getCode()); + updateWrapper.set(OrderMainPO::getActEndRentTime, LocalDateTime.now()); + updateWrapper.eq(OrderMainPO::getOrderNo, rejectOrderReq.getOrderNo()); + orderMainRepo.update(updateWrapper); + if (Objects.nonNull(orderSubPO)) { + //退款调用成功则添加退款子订单 + String outRefundNo = payService.refundOrder(orderSubPO.getPaymentMethod(), orderMainPO.getOperatorId(), orderSubPO.getPaymentId(), orderMainPO.getOrderAmount(), orderMainPO.getOrderAmount()); + if (StringUtils.isNotBlank(outRefundNo)) { + OrderSubPO fdSubOrder = new OrderSubPO(); + fdSubOrder.setOrderId(orderMainPO.getOrderId()); + fdSubOrder.setSuborderNo(OrderUtil.generateSubOrderNo(OrderUtil.FD_PREFIX)); + fdSubOrder.setSuborderType(SubOrderTypeEnum.FD_REJECT.getCode()); + fdSubOrder.setAmount(orderMainPO.getOrderAmount()); + fdSubOrder.setPaymentMethod(orderSubPO.getPaymentMethod()); + fdSubOrder.setPayStatus(PayStatusEnum.REFUNDING.getCode()); + fdSubOrder.setRefundId(outRefundNo); + fdSubOrder.setRemark(rejectOrderReq.getRejectReason()); + orderSubRepo.save(fdSubOrder); + } + } + }); + } + @Transactional(rollbackFor = Exception.class) @Override public OrderDTO bindCarToOrder(BindCarToOrderReq bindCarToOrderReq) { @@ -806,7 +845,7 @@ public class OrderServiceImpl implements OrderService { return getOrderInfoByOrderNo(bindCarToOrderReq.getOrderNo()); } catch (Exception e){ log.warn("绑定车辆失败",e); - throw new InnerException("绑定车辆失败"); + throw e; } finally { redisUtil.deleteRedisLock(redisLockKey); } @@ -816,6 +855,94 @@ public class OrderServiceImpl implements OrderService { } } + @Override + public OrderDTO changeCarToOrder(BindCarToOrderReq bindCarToOrderReq) { + String redisLockKey = RedisKeyConstants.BIND_CAR_KEY + bindCarToOrderReq.getVin(); + if(redisUtil.getRedisLock(redisLockKey, "变更车辆")) { + try { + CarDTO carDTO = carInteg.getCarByCarCondition(CarQueryConditionReq.builder().vin(bindCarToOrderReq.getVin()).build()); + if(carDTO==null){ + throw new BizException("车辆不存在"); + } + if(!CarStatusEnum.NORMAL.getCode().equalsIgnoreCase(carDTO.getBrsStatus())){ + throw new BizException("车辆已出租或已下架"); + } + LambdaQueryWrapper queryOrderWrapper = new LambdaQueryWrapper<>(); + queryOrderWrapper.eq(OrderMainPO::getOrderNo, bindCarToOrderReq.getOrderNo()); + OrderMainPO orderMainPO = orderMainRepo.getOne(queryOrderWrapper); + if(orderMainPO==null){ + throw new BizException("订单不存在"); + } + if(!orderMainPO.getOrderStatus().equals(OrderStatusEnum.RENT_ING.getCode())){ + throw new BizException("订单非租车状态,不能变更车辆"); + } + + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(OrderSubPO::getOrderId, orderMainPO.getOrderId()) + .eq(OrderSubPO::getSuborderType, SubOrderTypeEnum.RENTCAR.getCode()) + .isNotNull(OrderSubPO::getVinBatteryNo) + .orderByDesc(OrderSubPO::getCreatedAt) + .last(" limit 1"); + OrderSubPO renOrderSubPO = orderSubRepo.getOne(queryWrapper); + if(renOrderSubPO==null){ + throw new BizException("租车子订单不存在"); + } + //变更车架号 + LambdaUpdateWrapper updateSubWrapper = new LambdaUpdateWrapper<>(); + updateSubWrapper.set(OrderSubPO::getVinBatteryNo, carDTO.getVin()); + updateSubWrapper.eq(OrderSubPO::getSuborderId, renOrderSubPO.getSuborderId()); + orderSubRepo.update(updateSubWrapper); + + //变更订单的关联车辆 + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); + updateWrapper.set(OrderMainPO::getVehicleId, carDTO.getId()); + updateWrapper.eq(OrderMainPO::getOrderNo, bindCarToOrderReq.getOrderNo()); + orderMainRepo.update(updateWrapper); + + if(!CollectionUtils.isEmpty(bindCarToOrderReq.getImageList())){ + //添加车辆图片 + List carImagePOList = new ArrayList<>(); + for(OrderCarImgDTO image:bindCarToOrderReq.getImageList()){ + OrderCarImgPO imgPO = new OrderCarImgPO(); + imgPO.setOrderId(orderMainPO.getOrderId()); + imgPO.setOrderNo(orderMainPO.getOrderNo()); + imgPO.setImgType(image.getImgType()); + imgPO.setImgUrl(image.getImgUrl()); + carImagePOList.add(imgPO); + } + orderCarImgRepo.saveBatch(carImagePOList); + } + + //变更车辆状态 + LambdaUpdateWrapper carPOLambdaUpdateWrapper = new LambdaUpdateWrapper<>(); + carPOLambdaUpdateWrapper.eq(CarPO::getId, carDTO.getId()) + .set(CarPO::getBrsStatus, CarStatusEnum.RENT_ING.getCode()); + carRepo.update(carPOLambdaUpdateWrapper); + + //记录变更记录 + OrderCarChangePO orderCarChangePO = new OrderCarChangePO(); + orderCarChangePO.setOrderId(orderMainPO.getOrderId()); + orderCarChangePO.setOrderNo(orderMainPO.getOrderNo()); + orderCarChangePO.setOrderSubNo(renOrderSubPO.getSuborderNo()); + orderCarChangePO.setOldVehicleId(orderMainPO.getVehicleId()); + orderCarChangePO.setOldVehicleVin(renOrderSubPO.getVinBatteryNo()); + orderCarChangePO.setNewVehicleId(carDTO.getId()); + orderCarChangePO.setNewVehicleVin(carDTO.getVin()); + orderCarChangeRepo.save(orderCarChangePO); + + return getOrderInfoByOrderNo(bindCarToOrderReq.getOrderNo()); + } catch (Exception e){ + log.warn("变更车辆失败",e); + throw e; + } finally { + redisUtil.deleteRedisLock(redisLockKey); + } + } else { + log.warn("变更车辆失败,锁已被占用"); + throw new InnerException("服务器正在处理,请稍后再试"); + } + } + @Override public OrderDTO requestReturnCar(ReturnCarReq returnCarReq) { LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); diff --git a/src/main/resources/mapper/OrderCarChangeMapper.xml b/src/main/resources/mapper/OrderCarChangeMapper.xml new file mode 100644 index 0000000..a5d9f48 --- /dev/null +++ b/src/main/resources/mapper/OrderCarChangeMapper.xml @@ -0,0 +1,5 @@ + + + + +