绑定车辆和还车增加变更车辆状态

This commit is contained in:
2025-08-24 15:29:28 +08:00
parent 541e19fafb
commit dfa1eafe5f
8 changed files with 311 additions and 58 deletions

View File

@ -5,4 +5,6 @@ public interface RedisKeyConstants {
String ORDER_SUB_KEY = SERVICE_PREFIX + "orderSub:";
String BIND_CAR_KEY = SERVICE_PREFIX + "bindCar:";
}

View File

@ -0,0 +1,21 @@
package com.sczx.order.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @Author: 张黎
* @Date: 2024/03/08/17:42
* @Description: 车状态
*/
@AllArgsConstructor
@Getter
public enum CarStatusEnum {
NORMAL("0", "正常"),
REMOVED("1", "下架"),
RENT_ING("9", "租赁中"),
;
private final String code;
private final String msg;
}

View File

@ -0,0 +1,16 @@
package com.sczx.order.mapper;
import com.sczx.order.po.CarPO;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* 电动车信息表 Mapper 接口
* </p>
*
* @author zhangli
* @since 2025-08-24 14:55:02
*/
public interface CarMapper extends BaseMapper<CarPO> {
}

View File

@ -0,0 +1,140 @@
package com.sczx.order.po;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
/**
* <p>
* 电动车信息表
* </p>
*
* @author zhangli
* @since 2025-08-24 14:55:02
*/
@Getter
@Setter
@TableName("zc_car")
@ApiModel(value = "CarPO对象", description = "电动车信息表")
public class CarPO implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("主键ID")
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@ApiModelProperty("车架号(VIN)")
private String vin;
@ApiModelProperty("车牌号码")
private String licensePlate;
@ApiModelProperty("车辆品牌ID")
private Long brandId;
@ApiModelProperty("车辆品牌名称")
private String brandName;
@ApiModelProperty("车辆型号ID")
private Long modelId;
@ApiModelProperty("车辆型号名称")
private String modelName;
@ApiModelProperty("支持电池类型(48V标准版/100km,48V超长版/200km等)")
private String batteryType;
@ApiModelProperty("整车重量(kg)")
private String weight;
@ApiModelProperty("最高时速(km/h)")
private String maxSpeed;
@ApiModelProperty("LOT识别号")
private String lotNumber;
@ApiModelProperty("采购日期")
private LocalDateTime purchaseDate;
@ApiModelProperty("采购价格(元)")
private BigDecimal purchasePrice;
@ApiModelProperty("车辆归属(0归属于合,1归属运营商)")
private String belongType;
@ApiModelProperty("车辆图片(多个图片用逗号分隔)")
private String images;
@ApiModelProperty("BRS车辆状态(空闲/使用中/维修中/丢失报损等)")
private String brsStatus;
@ApiModelProperty("IoT设备状态")
private String iotStatus;
@ApiModelProperty("IoT识别码")
private String iotCode;
@ApiModelProperty("所属运营商ID")
private Long operatorId;
@ApiModelProperty("所属运营商名称")
private String operatorName;
@ApiModelProperty("所属门店ID")
private Long storeId;
@ApiModelProperty("所属门店名称")
private String storeName;
@ApiModelProperty("应用套餐ID")
private Long packageId;
@ApiModelProperty("应用套餐名称")
private String packageName;
@ApiModelProperty("状态0正常 1停用")
private String status;
@ApiModelProperty("删除标志0代表存在 2代表删除")
private String delFlag;
@ApiModelProperty("创建者")
private String createBy;
@ApiModelProperty("创建时间")
private LocalDateTime createTime;
@ApiModelProperty("更新者")
private String updateBy;
@ApiModelProperty("更新时间")
private LocalDateTime updateTime;
@ApiModelProperty("备注信息")
private String remark;
@ApiModelProperty("扩展字段1")
private String extend1;
@ApiModelProperty("扩展字段2")
private String extend2;
@ApiModelProperty("扩展字段3")
private String extend3;
@ApiModelProperty("扩展字段4")
private String extend4;
@ApiModelProperty("扩展字段5")
private String extend5;
}

View File

@ -0,0 +1,16 @@
package com.sczx.order.repository;
import com.sczx.order.po.CarPO;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 电动车信息表 服务类
* </p>
*
* @author zhangli
* @since 2025-08-24 14:55:02
*/
public interface CarRepo extends IService<CarPO> {
}

View File

@ -0,0 +1,20 @@
package com.sczx.order.repository.impl;
import com.sczx.order.po.CarPO;
import com.sczx.order.mapper.CarMapper;
import com.sczx.order.repository.CarRepo;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 电动车信息表 服务实现类
* </p>
*
* @author zhangli
* @since 2025-08-24 14:55:02
*/
@Service
public class CarRepoImpl extends ServiceImpl<CarMapper, CarPO> implements CarRepo {
}

View File

@ -11,9 +11,11 @@ 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;
@ -51,6 +53,9 @@ public class OrderServiceImpl implements OrderService {
@Autowired
private CarInteg carInteg;
@Autowired
private CarRepo carRepo;
@Autowired
private OrderMainRepo orderMainRepo;
@ -712,68 +717,87 @@ public class OrderServiceImpl implements OrderService {
@Transactional(rollbackFor = Exception.class)
@Override
public OrderDTO bindCarToOrder(BindCarToOrderReq bindCarToOrderReq) {
CarDTO carDTO = carInteg.getCarByCarCondition(CarQueryConditionReq.builder().vin(bindCarToOrderReq.getVin()).build());
if(carDTO==null){
throw new BizException("车辆不存在");
}
LambdaQueryWrapper<OrderMainPO> 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.WAIT_PICK.getCode())){
throw new BizException("订单状态异常,非待取车状态");
}
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<OrderMainPO> 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.WAIT_PICK.getCode())){
throw new BizException("订单状态异常,非待取车状态");
}
LambdaQueryWrapper<OrderSubPO> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(OrderSubPO::getOrderId, orderMainPO.getOrderId())
.eq(OrderSubPO::getSuborderType, SubOrderTypeEnum.RENTCAR.getCode())
.isNull(OrderSubPO::getVinBatteryNo)
.orderByDesc(OrderSubPO::getCreatedAt)
.last(" limit 1");
OrderSubPO renOrderSubPO = orderSubRepo.getOne(queryWrapper);
if(renOrderSubPO==null){
throw new BizException("租车子订单不存在");
}
//记录车架号
LambdaUpdateWrapper<OrderSubPO> updateSubWrapper = new LambdaUpdateWrapper<>();
updateSubWrapper.set(OrderSubPO::getVinBatteryNo, carDTO.getVin());
updateSubWrapper.eq(OrderSubPO::getSuborderId, renOrderSubPO.getSuborderId());
orderSubRepo.update(updateSubWrapper);
//变更订单状态,记录租车时间
LocalDateTime currentTime = LocalDateTime.now();
LambdaQueryWrapper<OrderSubPO> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(OrderSubPO::getOrderId, orderMainPO.getOrderId())
.eq(OrderSubPO::getSuborderType, SubOrderTypeEnum.RENTCAR.getCode())
.isNull(OrderSubPO::getVinBatteryNo)
.orderByDesc(OrderSubPO::getCreatedAt)
.last(" limit 1");
OrderSubPO renOrderSubPO = orderSubRepo.getOne(queryWrapper);
if(renOrderSubPO==null){
throw new BizException("租车子订单不存在");
}
//记录车架号
LambdaUpdateWrapper<OrderSubPO> updateSubWrapper = new LambdaUpdateWrapper<>();
updateSubWrapper.set(OrderSubPO::getVinBatteryNo, carDTO.getVin());
updateSubWrapper.eq(OrderSubPO::getSuborderId, renOrderSubPO.getSuborderId());
orderSubRepo.update(updateSubWrapper);
//变更订单状态,记录租车时间
LocalDateTime currentTime = LocalDateTime.now();
//设置预计还车时间
LocalDateTime endRentTime = OrderUtil.getEndRentTime(currentTime,orderMainPO.getRentalDays(), orderMainPO.getRentalType());
//设置预计还车时间
LocalDateTime endRentTime = OrderUtil.getEndRentTime(currentTime,orderMainPO.getRentalDays(), orderMainPO.getRentalType());
LambdaUpdateWrapper<OrderMainPO> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.set(OrderMainPO::getOrderStatus, OrderStatusEnum.RENT_ING.getCode());
updateWrapper.set(OrderMainPO::getStartRentTime, currentTime);
updateWrapper.set(OrderMainPO::getPickCarTime, currentTime);
updateWrapper.set(endRentTime!=null ,OrderMainPO::getEndRentTime, endRentTime);
updateWrapper.set(OrderMainPO::getVehicleId, carDTO.getId());
updateWrapper.eq(OrderMainPO::getOrderNo, bindCarToOrderReq.getOrderNo());
orderMainRepo.update(updateWrapper);
LambdaUpdateWrapper<OrderMainPO> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.set(OrderMainPO::getOrderStatus, OrderStatusEnum.RENT_ING.getCode());
updateWrapper.set(OrderMainPO::getStartRentTime, currentTime);
updateWrapper.set(OrderMainPO::getPickCarTime, currentTime);
updateWrapper.set(endRentTime!=null ,OrderMainPO::getEndRentTime, endRentTime);
updateWrapper.set(OrderMainPO::getVehicleId, carDTO.getId());
updateWrapper.eq(OrderMainPO::getOrderNo, bindCarToOrderReq.getOrderNo());
orderMainRepo.update(updateWrapper);
if(!CollectionUtils.isEmpty(bindCarToOrderReq.getImageList())){
//添加车辆图片
List<OrderCarImgPO> 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);
if(!CollectionUtils.isEmpty(bindCarToOrderReq.getImageList())){
//添加车辆图片
List<OrderCarImgPO> 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<CarPO> carPOLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
carPOLambdaUpdateWrapper.eq(CarPO::getId, carDTO.getId())
.set(CarPO::getBrsStatus, CarStatusEnum.RENT_ING.getCode());
carRepo.update(carPOLambdaUpdateWrapper);
return getOrderInfoByOrderNo(bindCarToOrderReq.getOrderNo());
} catch (Exception e){
log.warn("绑定车辆失败");
throw new InnerException("绑定车辆失败");
} finally {
redisUtil.deleteRedisLock(redisLockKey);
}
orderCarImgRepo.saveBatch(carImagePOList);
} else {
log.warn("绑定车辆失败,锁已被占用");
throw new InnerException("服务器正在处理,请稍后再试");
}
//TODO 变更车辆状态
return getOrderInfoByOrderNo(bindCarToOrderReq.getOrderNo());
}
@Override
@ -800,6 +824,7 @@ public class OrderServiceImpl implements OrderService {
return orderDTO;
}
@Transactional(rollbackFor = Exception.class)
@Override
public OrderDTO confirmReturnCar(ReturnCarReq returnCarReq) {
//变更订单状态,记录还车时间
@ -824,8 +849,16 @@ public class OrderServiceImpl implements OrderService {
}
orderCarImgRepo.saveBatch(carImagePOList);
}
//TODO 变更车辆状态
//T变更车辆状态
CarPO carPO = carRepo.getById(orderDTO.getVehicleId());
if(carPO == null){
throw new BizException("车辆不存在");
}
//变更车辆状态
LambdaUpdateWrapper<CarPO> carPOLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
carPOLambdaUpdateWrapper.eq(CarPO::getId, orderDTO.getVehicleId())
.set(CarPO::getBrsStatus, CarStatusEnum.NORMAL.getCode());
carRepo.update(carPOLambdaUpdateWrapper);
//异步执行分润
ThreadPoolUtils.getThreadPool().execute(() -> {
orderDistribService.saveOrderDistrib(returnCarReq.getOrderNo());

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sczx.order.mapper.CarMapper">
</mapper>