From dfa1eafe5faf981c0d81b386717a0b645173ee3a Mon Sep 17 00:00:00 2001 From: zhangli <123879394@qq.com> Date: Sun, 24 Aug 2025 15:29:28 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=91=E5=AE=9A=E8=BD=A6=E8=BE=86=E5=92=8C?= =?UTF-8?q?=E8=BF=98=E8=BD=A6=E5=A2=9E=E5=8A=A0=E5=8F=98=E6=9B=B4=E8=BD=A6?= =?UTF-8?q?=E8=BE=86=E7=8A=B6=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/constant/RedisKeyConstants.java | 2 + .../order/common/enums/CarStatusEnum.java | 21 +++ .../java/com/sczx/order/mapper/CarMapper.java | 16 ++ src/main/java/com/sczx/order/po/CarPO.java | 140 ++++++++++++++++ .../com/sczx/order/repository/CarRepo.java | 16 ++ .../order/repository/impl/CarRepoImpl.java | 20 +++ .../order/service/impl/OrderServiceImpl.java | 149 +++++++++++------- src/main/resources/mapper/CarMapper.xml | 5 + 8 files changed, 311 insertions(+), 58 deletions(-) create mode 100644 src/main/java/com/sczx/order/common/enums/CarStatusEnum.java create mode 100644 src/main/java/com/sczx/order/mapper/CarMapper.java create mode 100644 src/main/java/com/sczx/order/po/CarPO.java create mode 100644 src/main/java/com/sczx/order/repository/CarRepo.java create mode 100644 src/main/java/com/sczx/order/repository/impl/CarRepoImpl.java create mode 100644 src/main/resources/mapper/CarMapper.xml diff --git a/src/main/java/com/sczx/order/common/constant/RedisKeyConstants.java b/src/main/java/com/sczx/order/common/constant/RedisKeyConstants.java index 0a2c4de..ef56aa7 100644 --- a/src/main/java/com/sczx/order/common/constant/RedisKeyConstants.java +++ b/src/main/java/com/sczx/order/common/constant/RedisKeyConstants.java @@ -5,4 +5,6 @@ public interface RedisKeyConstants { String ORDER_SUB_KEY = SERVICE_PREFIX + "orderSub:"; + String BIND_CAR_KEY = SERVICE_PREFIX + "bindCar:"; + } diff --git a/src/main/java/com/sczx/order/common/enums/CarStatusEnum.java b/src/main/java/com/sczx/order/common/enums/CarStatusEnum.java new file mode 100644 index 0000000..d8b3ec4 --- /dev/null +++ b/src/main/java/com/sczx/order/common/enums/CarStatusEnum.java @@ -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; +} diff --git a/src/main/java/com/sczx/order/mapper/CarMapper.java b/src/main/java/com/sczx/order/mapper/CarMapper.java new file mode 100644 index 0000000..0102d7c --- /dev/null +++ b/src/main/java/com/sczx/order/mapper/CarMapper.java @@ -0,0 +1,16 @@ +package com.sczx.order.mapper; + +import com.sczx.order.po.CarPO; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + *

+ * 电动车信息表 Mapper 接口 + *

+ * + * @author zhangli + * @since 2025-08-24 14:55:02 + */ +public interface CarMapper extends BaseMapper { + +} diff --git a/src/main/java/com/sczx/order/po/CarPO.java b/src/main/java/com/sczx/order/po/CarPO.java new file mode 100644 index 0000000..1cd7c13 --- /dev/null +++ b/src/main/java/com/sczx/order/po/CarPO.java @@ -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; + +/** + *

+ * 电动车信息表 + *

+ * + * @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; + + +} diff --git a/src/main/java/com/sczx/order/repository/CarRepo.java b/src/main/java/com/sczx/order/repository/CarRepo.java new file mode 100644 index 0000000..1153e2a --- /dev/null +++ b/src/main/java/com/sczx/order/repository/CarRepo.java @@ -0,0 +1,16 @@ +package com.sczx.order.repository; + +import com.sczx.order.po.CarPO; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + *

+ * 电动车信息表 服务类 + *

+ * + * @author zhangli + * @since 2025-08-24 14:55:02 + */ +public interface CarRepo extends IService { + +} diff --git a/src/main/java/com/sczx/order/repository/impl/CarRepoImpl.java b/src/main/java/com/sczx/order/repository/impl/CarRepoImpl.java new file mode 100644 index 0000000..d4eab09 --- /dev/null +++ b/src/main/java/com/sczx/order/repository/impl/CarRepoImpl.java @@ -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; + +/** + *

+ * 电动车信息表 服务实现类 + *

+ * + * @author zhangli + * @since 2025-08-24 14:55:02 + */ +@Service +public class CarRepoImpl extends ServiceImpl implements CarRepo { + +} 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 7d29076..a0e1510 100644 --- a/src/main/java/com/sczx/order/service/impl/OrderServiceImpl.java +++ b/src/main/java/com/sczx/order/service/impl/OrderServiceImpl.java @@ -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 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 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 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 updateSubWrapper = new LambdaUpdateWrapper<>(); - updateSubWrapper.set(OrderSubPO::getVinBatteryNo, carDTO.getVin()); - updateSubWrapper.eq(OrderSubPO::getSuborderId, renOrderSubPO.getSuborderId()); - orderSubRepo.update(updateSubWrapper); - //变更订单状态,记录租车时间 - LocalDateTime currentTime = LocalDateTime.now(); + LambdaQueryWrapper 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 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 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 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 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 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); + + 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 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()); diff --git a/src/main/resources/mapper/CarMapper.xml b/src/main/resources/mapper/CarMapper.xml new file mode 100644 index 0000000..f8a452f --- /dev/null +++ b/src/main/resources/mapper/CarMapper.xml @@ -0,0 +1,5 @@ + + + + +