驾驶证管理

This commit is contained in:
磷叶 2025-06-04 16:39:49 +08:00
parent 853be0462f
commit 8ce2a7d800
19 changed files with 146 additions and 70 deletions

View File

@ -5,7 +5,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<mapper namespace="com.ruoyi.bst.device.mapper.DeviceMapper"> <mapper namespace="com.ruoyi.bst.device.mapper.DeviceMapper">
<resultMap type="DeviceVO" id="DeviceResult" autoMapping="true"> <resultMap type="DeviceVO" id="DeviceResult" autoMapping="true">
<result property="modelSuitIds" column="model_suit_ids" typeHandler="com.ruoyi.common.mybatis.typehandler.LongSplitListTypeHandler"/> <result property="areaAuthentication" column="area_authentication" typeHandler="com.ruoyi.common.mybatis.typehandler.StringSplitListTypeHandler"/>
</resultMap> </resultMap>
<sql id="selectDeviceVo"> <sql id="selectDeviceVo">

View File

@ -298,9 +298,6 @@ public class DeviceIotServiceImpl implements DeviceIotService {
// this.updateIot(device); // this.updateIot(device);
// } // }
// 拼接物联网信息
deviceAssembler.assembleIot(deviceList);
// 异步发送命令强制设备上报数据 // 异步发送命令强制设备上报数据
if (onlineType != null) { if (onlineType != null) {
scheduledExecutorService.execute(() -> { scheduledExecutorService.execute(() -> {
@ -435,8 +432,7 @@ public class DeviceIotServiceImpl implements DeviceIotService {
for (Long deviceId : idList) { for (Long deviceId : idList) {
try { try {
// 获取设备最新信息 // 获取设备最新信息
DeviceVO device = deviceMapper.selectDeviceById(deviceId); DeviceVO device = deviceService.selectDeviceById(deviceId);
deviceAssembler.assembleIot(device);
this.monitor(device); this.monitor(device);
} catch (Exception e) { } catch (Exception e) {
log.error("监控设备id={}出错:{}", deviceId, e.getMessage()); log.error("监控设备id={}出错:{}", deviceId, e.getMessage());
@ -448,18 +444,6 @@ public class DeviceIotServiceImpl implements DeviceIotService {
if (device == null) { if (device == null) {
return; return;
} }
// 判断电门与设备锁状态是否一致不一致则发送命令
if (DeviceLockStatus.OPEN.getCode().equals(device.getLockStatus())
&& !DeviceQuality.OPEN.getCode().equals(device.getQuality())) {
CommandResponse res = iotService.unlock(device, SUB_FAST, "重新尝试开锁", 1);
if (device.getOrderId() != null) {
operLogService.operSysLog("【设备监控】发现未开启的车辆", IotUtil.isSuccess(res), LogBizType.ORDER,
device.getOrderId(), device);
} else {
operLogService.operSysLog("【设备监控】发现未开启的车辆", IotUtil.isSuccess(res), LogBizType.DEVICE, device.getId(),
device);
}
}
if (DeviceLockStatus.CLOSE.getCode().equals(device.getLockStatus()) if (DeviceLockStatus.CLOSE.getCode().equals(device.getLockStatus())
&& !DeviceQuality.CLOSE.getCode().equals(device.getQuality())) { && !DeviceQuality.CLOSE.getCode().equals(device.getQuality())) {
CommandResponse res = iotService.lock(device, getDeviceSubSlow(device), "重新尝试锁车", 1); CommandResponse res = iotService.lock(device, getDeviceSubSlow(device), "重新尝试锁车", 1);
@ -476,7 +460,6 @@ public class DeviceIotServiceImpl implements DeviceIotService {
@Override @Override
public void monitor(String mac) { public void monitor(String mac) {
DeviceVO device = deviceService.selectByMac(mac); DeviceVO device = deviceService.selectByMac(mac);
deviceAssembler.assembleIot(device);
this.monitor(device); this.monitor(device);
} }

View File

@ -8,6 +8,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.Function; import java.util.function.Function;
import com.ruoyi.bst.device.service.DeviceAssembler;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate; import org.springframework.transaction.support.TransactionTemplate;
@ -67,6 +68,9 @@ public class DeviceServiceImpl implements DeviceService {
@Autowired @Autowired
private RedisCache redisCache; private RedisCache redisCache;
@Autowired
private DeviceAssembler deviceAssembler;
/** /**
* 查询设备 * 查询设备
* *
@ -99,7 +103,9 @@ public class DeviceServiceImpl implements DeviceService {
*/ */
@Override @Override
public List<DeviceVO> selectDeviceList(DeviceQuery query) { public List<DeviceVO> selectDeviceList(DeviceQuery query) {
return deviceMapper.selectDeviceList(query); List<DeviceVO> list = deviceMapper.selectDeviceList(query);
deviceAssembler.assembleIot(list);
return list;
} }
@Override @Override
@ -502,7 +508,7 @@ public class DeviceServiceImpl implements DeviceService {
query.setEqSn(sn); query.setEqSn(sn);
} }
DeviceVO device = this.selectOne(query); DeviceVO device = this.selectOne(query);
ServiceUtil.assertion(DeviceStatus.AVAILABLE.getCode().equals(device.getStatus()), ServiceUtil.assertion(!DeviceStatus.AVAILABLE.getCode().equals(device.getStatus()),
"当前设备不可用:" + DeviceStatus.getNameByCode(device.getStatus()) ); "当前设备不可用:" + DeviceStatus.getNameByCode(device.getStatus()) );
return device; return device;
} }

View File

@ -39,8 +39,8 @@ public class DeviceUtil {
} }
// 转换经纬度坐标系并赋值 // 转换经纬度坐标系并赋值
// 只有定位是正常的 && 卫星信号大于2颗 才认为是有获取到定位 // 只有定位是正常的 && 卫星信号不弱 才认为是有获取到定位
if (DeviceUtil.validLocation(sys.getLon(), sys.getLat()) && sys.getS() != null && sys.getS() > 2) { if (DeviceUtil.validLocation(sys.getLon(), sys.getLat()) && !DeviceUtil.isLowSatelliteSignal(sys.getS())) {
List<BigDecimal> coordinates = null; List<BigDecimal> coordinates = null;
// 转换坐标 // 转换坐标
@ -188,7 +188,16 @@ public class DeviceUtil {
* @return 是否弱 * @return 是否弱
*/ */
public static boolean isLowSatelliteSignal(DeviceVO device) { public static boolean isLowSatelliteSignal(DeviceVO device) {
return device != null && device.getSatellites() != null && device.getSatellites() <= 5; return device != null && isLowSatelliteSignal(device.getSatellites());
}
/**
* 卫星信号弱
* @param s
* @return
*/
public static boolean isLowSatelliteSignal(Integer s) {
return s == null || s <= 5;
} }
/** /**

View File

@ -15,6 +15,7 @@ import com.ruoyi.bst.driver.domain.dto.DriverVerifyDTO;
import com.ruoyi.bst.driver.domain.enums.DriverStatus; import com.ruoyi.bst.driver.domain.enums.DriverStatus;
import com.ruoyi.bst.driver.mapper.DriverMapper; import com.ruoyi.bst.driver.mapper.DriverMapper;
import com.ruoyi.bst.driver.service.DriverService; import com.ruoyi.bst.driver.service.DriverService;
import com.ruoyi.common.core.domain.vo.UserVO;
import com.ruoyi.common.core.redis.RedisLock; import com.ruoyi.common.core.redis.RedisLock;
import com.ruoyi.common.core.redis.enums.RedisLockKey; import com.ruoyi.common.core.redis.enums.RedisLockKey;
import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.DateUtils;
@ -22,6 +23,7 @@ import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.common.utils.collection.CollectionUtils; import com.ruoyi.common.utils.collection.CollectionUtils;
import com.ruoyi.system.user.domain.enums.UserAuthType; import com.ruoyi.system.user.domain.enums.UserAuthType;
import com.ruoyi.system.user.service.UserService; import com.ruoyi.system.user.service.UserService;
import com.ruoyi.system.user.utils.UserUtil;
/** /**
* 驾驶证认证Service业务层处理 * 驾驶证认证Service业务层处理
@ -83,8 +85,13 @@ public class DriverServiceImpl implements DriverService
boolean lock = redisLock.lock(RedisLockKey.DRIVER_INSERT, lockKey); boolean lock = redisLock.lock(RedisLockKey.DRIVER_INSERT, lockKey);
ServiceUtil.assertion(!lock, "提交过于频繁,请稍后再试"); ServiceUtil.assertion(!lock, "提交过于频繁,请稍后再试");
try { try {
// 查询用户
UserVO user = userService.selectUserById(driver.getUserId());
ServiceUtil.assertion(UserUtil.hasAuth(user, UserAuthType.DRIVER.getCode()), "您已通过驾驶证认证,请勿重复提交");
// 查询上次提交的信息
DriverVO lastOne = this.selectLastOneByUserId(driver.getUserId()); DriverVO lastOne = this.selectLastOneByUserId(driver.getUserId());
ServiceUtil.assertion(lastOne != null && !DriverStatus.FAILED.getCode().equals(lastOne.getStatus()), "您已提交过驾驶证认证,请勿重复提交"); ServiceUtil.assertion(lastOne != null && DriverStatus.WAIT_VERIFY.getCode().equals(lastOne.getStatus()), "您已提交过驾驶证认证,请勿重复提交");
driver.setCreateTime(DateUtils.getNowDate()); driver.setCreateTime(DateUtils.getNowDate());
return driverMapper.insertDriver(driver); return driverMapper.insertDriver(driver);
@ -167,8 +174,10 @@ public class DriverServiceImpl implements DriverService
int rows = driverMapper.updateByQuery(data, query); int rows = driverMapper.updateByQuery(data, query);
ServiceUtil.assertion(rows != 1, "当前数据已发生变化,请刷新后重试"); ServiceUtil.assertion(rows != 1, "当前数据已发生变化,请刷新后重试");
int authType = userService.addAuthType(driver.getUserId(), UserAuthType.DRIVER); if (pass) {
ServiceUtil.assertion(authType != 1, "为用户添加驾驶证认证失败,id=" + driver.getUserId()); int authType = userService.addAuthType(driver.getUserId(), UserAuthType.DRIVER);
ServiceUtil.assertion(authType != 1, "为用户添加驾驶证认证失败,id=" + driver.getUserId());
}
return rows; return rows;
}); });

View File

@ -4,6 +4,7 @@ import java.math.BigDecimal;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List; import java.util.List;
import com.ruoyi.bst.order.domain.vo.OrderCalcPreRideFeeVO;
import com.ruoyi.bst.order.utils.OrderUtil; import com.ruoyi.bst.order.utils.OrderUtil;
import com.ruoyi.bst.orderDevice.domain.OrderDeviceVO; import com.ruoyi.bst.orderDevice.domain.OrderDeviceVO;
import com.ruoyi.common.utils.MathUtils; import com.ruoyi.common.utils.MathUtils;
@ -143,4 +144,9 @@ public class OrderVO extends Order implements IotDevice {
public BigDecimal getTotalDiscountAmount() { public BigDecimal getTotalDiscountAmount() {
return this.getRidingDiscount(); return this.getRidingDiscount();
} }
// 预估骑行费
public OrderCalcPreRideFeeVO getPreRideFee() {
return OrderUtil.calcRideFee(this, LocalDateTime.now());
}
} }

View File

@ -0,0 +1,20 @@
package com.ruoyi.bst.order.domain.vo;
import java.math.BigDecimal;
import lombok.Data;
@Data
public class OrderCalcPreRideFeeVO {
/**
* 使用时长
*/
private Long seconds;
/**
* 骑行费
*/
private BigDecimal rideFee;
}

View File

@ -1,6 +1,7 @@
package com.ruoyi.bst.order.service; package com.ruoyi.bst.order.service;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List; import java.util.List;
import com.ruoyi.bst.device.domain.vo.DeviceIotVO; import com.ruoyi.bst.device.domain.vo.DeviceIotVO;
@ -21,6 +22,7 @@ import com.ruoyi.bst.order.domain.dto.OrderRidePaySuccessDTO;
import com.ruoyi.bst.order.domain.dto.OrderSeatDTO; import com.ruoyi.bst.order.domain.dto.OrderSeatDTO;
import com.ruoyi.bst.order.domain.dto.OrderUpdatePriceDTO; import com.ruoyi.bst.order.domain.dto.OrderUpdatePriceDTO;
import com.ruoyi.bst.order.domain.dto.OrderVerifyDTO; import com.ruoyi.bst.order.domain.dto.OrderVerifyDTO;
import com.ruoyi.bst.order.domain.vo.OrderCalcPreRideFeeVO;
import com.ruoyi.bst.order.domain.vo.OrderCalcRideFeeVO; import com.ruoyi.bst.order.domain.vo.OrderCalcRideFeeVO;
import com.ruoyi.bst.order.domain.vo.OrderEndVO; import com.ruoyi.bst.order.domain.vo.OrderEndVO;
import com.ruoyi.bst.order.domain.vo.OrderFeeVO; import com.ruoyi.bst.order.domain.vo.OrderFeeVO;
@ -271,4 +273,11 @@ public interface OrderService {
* @return * @return
*/ */
public OrderCalcRideFeeVO calcRideFee(OrderVO order, VipUserVO vipUser); public OrderCalcRideFeeVO calcRideFee(OrderVO order, VipUserVO vipUser);
/**
* 计算预估骑行费
* @param orderId
* @return
*/
public OrderCalcPreRideFeeVO calcPreRideFee(Long orderId, LocalDateTime endTime);
} }

View File

@ -160,7 +160,6 @@ public class OrderConverterImpl implements OrderConverter{
// 设备 // 设备
DeviceVO device = deviceService.selectDeviceById(dto.getDeviceId()); DeviceVO device = deviceService.selectDeviceById(dto.getDeviceId());
deviceAssembler.assembleIot(device);
bo.setDevice(device); bo.setDevice(device);
if (device != null) { if (device != null) {
@ -410,7 +409,6 @@ public class OrderConverterImpl implements OrderConverter{
if (orderDevice != null) { if (orderDevice != null) {
// 获取当前设备信息 // 获取当前设备信息
DeviceVO device = deviceService.selectDeviceById(orderDevice.getDeviceId()); DeviceVO device = deviceService.selectDeviceById(orderDevice.getDeviceId());
deviceAssembler.assembleIot(device);
bo.setDevice(device); bo.setDevice(device);
} }
@ -458,7 +456,6 @@ public class OrderConverterImpl implements OrderConverter{
DeviceVO newDevice = null; DeviceVO newDevice = null;
if (dto.getDeviceId() != null) { if (dto.getDeviceId() != null) {
newDevice = deviceService.selectDeviceById(dto.getDeviceId()); newDevice = deviceService.selectDeviceById(dto.getDeviceId());
deviceAssembler.assembleIot(newDevice);
ServiceUtil.assertion(newDevice == null, "ID为%s的设备不存在", dto.getDeviceId()); ServiceUtil.assertion(newDevice == null, "ID为%s的设备不存在", dto.getDeviceId());
} else if (StringUtils.isNotBlank(dto.getDeviceSn())) { } else if (StringUtils.isNotBlank(dto.getDeviceSn())) {
newDevice = deviceService.selectDeviceBySn(dto.getDeviceSn()); newDevice = deviceService.selectDeviceBySn(dto.getDeviceSn());
@ -495,7 +492,6 @@ public class OrderConverterImpl implements OrderConverter{
// 查询旧设备 // 查询旧设备
DeviceVO oldDevice = deviceService.selectDeviceById(oldOrderDevice.getDeviceId()); DeviceVO oldDevice = deviceService.selectDeviceById(oldOrderDevice.getDeviceId());
deviceAssembler.assembleIot(oldDevice);
ServiceUtil.assertion(oldDevice == null, "ID为%s的旧设备不存在", oldOrderDevice.getDeviceId()); ServiceUtil.assertion(oldDevice == null, "ID为%s的旧设备不存在", oldOrderDevice.getDeviceId());
bo.setOldDevice(oldDevice); bo.setOldDevice(oldDevice);

View File

@ -67,6 +67,7 @@ import com.ruoyi.bst.order.domain.dto.OrderVerifyDTO;
import com.ruoyi.bst.order.domain.enums.OrderPayType; import com.ruoyi.bst.order.domain.enums.OrderPayType;
import com.ruoyi.bst.order.domain.enums.OrderReturnType; import com.ruoyi.bst.order.domain.enums.OrderReturnType;
import com.ruoyi.bst.order.domain.enums.OrderStatus; import com.ruoyi.bst.order.domain.enums.OrderStatus;
import com.ruoyi.bst.order.domain.vo.OrderCalcPreRideFeeVO;
import com.ruoyi.bst.order.domain.vo.OrderCalcRideFeeVO; import com.ruoyi.bst.order.domain.vo.OrderCalcRideFeeVO;
import com.ruoyi.bst.order.domain.vo.OrderEndVO; import com.ruoyi.bst.order.domain.vo.OrderEndVO;
import com.ruoyi.bst.order.domain.vo.OrderFeeVO; import com.ruoyi.bst.order.domain.vo.OrderFeeVO;
@ -658,7 +659,6 @@ public class OrderServiceImpl implements OrderService {
// 设备信息 // 设备信息
DeviceVO device = deviceService.selectDeviceById(order.getDeviceId()); DeviceVO device = deviceService.selectDeviceById(order.getDeviceId());
deviceAssembler.assembleIot(device);
if (device == null) { if (device == null) {
return null; return null;
} }
@ -808,7 +808,6 @@ public class OrderServiceImpl implements OrderService {
// 查询设备 // 查询设备
DeviceVO device = deviceService.selectDeviceById(orderDevice.getDeviceId()); DeviceVO device = deviceService.selectDeviceById(orderDevice.getDeviceId());
ServiceUtil.assertion(device == null, "ID为%s的设备不存在", orderDevice.getDeviceId()); ServiceUtil.assertion(device == null, "ID为%s的设备不存在", orderDevice.getDeviceId());
deviceAssembler.assembleIot(device);
// 设置日志参数 // 设置日志参数
this.setLogParam(device); this.setLogParam(device);
// 异步使用手机定位更新设备定位 // 异步使用手机定位更新设备定位
@ -834,7 +833,6 @@ public class OrderServiceImpl implements OrderService {
// 查询设备 // 查询设备
DeviceVO device = deviceService.selectDeviceById(orderDevice.getDeviceId()); DeviceVO device = deviceService.selectDeviceById(orderDevice.getDeviceId());
ServiceUtil.assertion(device == null, "ID为%s的设备不存在", orderDevice.getDeviceId()); ServiceUtil.assertion(device == null, "ID为%s的设备不存在", orderDevice.getDeviceId());
deviceAssembler.assembleIot(device);
// 设置日志参数 // 设置日志参数
this.setLogParam(device); this.setLogParam(device);
// 异步使用手机定位更新设备定位 // 异步使用手机定位更新设备定位
@ -990,7 +988,6 @@ public class OrderServiceImpl implements OrderService {
ServiceUtil.assertion(device == null, "ID为%s的设备不存在", order.getDeviceId()); ServiceUtil.assertion(device == null, "ID为%s的设备不存在", order.getDeviceId());
boolean enableSeat = device.getModelEnableSeat() != null && device.getModelEnableSeat(); boolean enableSeat = device.getModelEnableSeat() != null && device.getModelEnableSeat();
ServiceUtil.assertion(!enableSeat, "ID为%s的设备不允许用户打开坐垫锁", order.getDeviceId()); ServiceUtil.assertion(!enableSeat, "ID为%s的设备不允许用户打开坐垫锁", order.getDeviceId());
deviceAssembler.assembleIot(device);
// 设置日志参数 // 设置日志参数
this.setLogParam(device); this.setLogParam(device);
@ -1277,4 +1274,10 @@ public class OrderServiceImpl implements OrderService {
return vo; return vo;
} }
@Override
public OrderCalcPreRideFeeVO calcPreRideFee(Long orderId, LocalDateTime endTime) {
OrderVO order = this.selectOrderById(orderId);
return OrderUtil.calcRideFee(order, endTime);
}
} }

View File

@ -99,7 +99,7 @@ public class OrderValidatorImpl implements OrderValidator{
if (authTypeEnum == null) { if (authTypeEnum == null) {
throw new ServiceException(String.format("运营区%s认证类型错误", device.getAreaName())); throw new ServiceException(String.format("运营区%s认证类型错误", device.getAreaName()));
} }
throw new ServiceException(String.format("用户%s未认证%s", user.getNickName(), authTypeEnum.getName()), authTypeEnum.getErrorCode()); throw new ServiceException(String.format("用户%s未认证%s", user.getNickName(), authTypeEnum.getName()), authTypeEnum.getErrorCode());
} }
} }
} }
@ -329,7 +329,7 @@ public class OrderValidatorImpl implements OrderValidator{
// 费用 // 费用
OrderCalcRideFeeVO fee = bo.getFee(); OrderCalcRideFeeVO fee = bo.getFee();
ServiceUtil.assertion(fee == null, "参数错误,费用不存在"); ServiceUtil.assertion(fee == null, "参数错误,费用不存在");
// 卡券 // 卡券
if (dto.getVipUserId() != null) { if (dto.getVipUserId() != null) {

View File

@ -20,6 +20,7 @@ import com.ruoyi.bst.order.domain.OrderVO;
import com.ruoyi.bst.order.domain.dto.OrderRefundDTO; import com.ruoyi.bst.order.domain.dto.OrderRefundDTO;
import com.ruoyi.bst.order.domain.dto.OrderRefundDetailDTO; import com.ruoyi.bst.order.domain.dto.OrderRefundDetailDTO;
import com.ruoyi.bst.order.domain.enums.OrderPayType; import com.ruoyi.bst.order.domain.enums.OrderPayType;
import com.ruoyi.bst.order.domain.vo.OrderCalcPreRideFeeVO;
import com.ruoyi.bst.order.domain.vo.OrderCalcRideFeeVO; import com.ruoyi.bst.order.domain.vo.OrderCalcRideFeeVO;
import com.ruoyi.bst.order.domain.vo.OrderFeeVO; import com.ruoyi.bst.order.domain.vo.OrderFeeVO;
import com.ruoyi.bst.order.domain.vo.OrderInParkingVO; import com.ruoyi.bst.order.domain.vo.OrderInParkingVO;
@ -29,6 +30,7 @@ import com.ruoyi.bst.suit.domain.enums.SuitRentalUnit;
import com.ruoyi.bst.suit.domain.enums.SuitRidingRule; import com.ruoyi.bst.suit.domain.enums.SuitRidingRule;
import com.ruoyi.bst.suit.utils.SuitUtil; import com.ruoyi.bst.suit.utils.SuitUtil;
import com.ruoyi.common.utils.MathUtils; import com.ruoyi.common.utils.MathUtils;
import com.ruoyi.common.utils.ServiceUtil;
public class OrderUtil { public class OrderUtil {
@ -42,7 +44,7 @@ public class OrderUtil {
// 挂账支付 // 挂账支付
if (ChannelApiType.CREDIT.getType().equals(channel.getApiType())) { if (ChannelApiType.CREDIT.getType().equals(channel.getApiType())) {
vo.setDepositPrice(BigDecimal.ZERO); vo.setDepositPrice(BigDecimal.ZERO);
} }
// 其他支付 // 其他支付
else { else {
vo.setDepositPrice(suit.getDepositAmount()); vo.setDepositPrice(suit.getDepositAmount());
@ -80,23 +82,9 @@ public class OrderUtil {
OrderFeeVO vo = new OrderFeeVO(); OrderFeeVO vo = new OrderFeeVO();
// 骑行费 // 骑行费
Duration duration = Duration.between(order.getStartTime(), endTime); OrderCalcPreRideFeeVO rideFee = calcRideFee(order, endTime);
long seconds = duration.getSeconds(); // 使用时长 if (rideFee != null) {
Integer freeRideMinutes = order.getSuitFreeRideTime(); // 免费骑行时长 vo.setRidingFee(rideFee.getRideFee());
boolean isFree = freeRideMinutes != null && seconds <= freeRideMinutes * 60; // 是否免费
// 若免费则骑行费为0
if (isFree) {
vo.setRidingFee(BigDecimal.ZERO);
}
// 否则计算骑行费
else {
SuitRentalUnit rentalUnit = SuitRentalUnit.parse(order.getSuitRentalUnit());
if (SuitRidingRule.START_FEE.getCode().equals(order.getSuitRidingRule())) {
vo.setRidingFee(SuitUtil.calcAmountForStartFee(seconds, order.getSuitStartRule(), rentalUnit));
} else {
vo.setRidingFee(SuitUtil.calcAmountForIntervalFee(seconds, order.getSuitIntervalRule(), rentalUnit));
}
} }
// 若需要调度费则计算调度费 // 若需要调度费则计算调度费
@ -277,7 +265,7 @@ public class OrderUtil {
dispatchRefund = dto.getDispatchRefund(); dispatchRefund = dto.getDispatchRefund();
manageRefund = dto.getManageRefund(); manageRefund = dto.getManageRefund();
} }
} }
// 支付退款 // 支付退款
else if (OrderConstants.REFUND_TYPE_RIDE.equals(refundType)) { else if (OrderConstants.REFUND_TYPE_RIDE.equals(refundType)) {
ridingRefund = dto.getRidingRefund(); ridingRefund = dto.getRidingRefund();
@ -310,4 +298,42 @@ public class OrderUtil {
return MathUtils.equals(a.getDiscountAmount(), b.getDiscountAmount()) return MathUtils.equals(a.getDiscountAmount(), b.getDiscountAmount())
&& MathUtils.equals(a.getPayAmount(), b.getPayAmount()); && MathUtils.equals(a.getPayAmount(), b.getPayAmount());
} }
/**
* 计算骑行费
* @param order
* @param endTime
* @return
*/
public static OrderCalcPreRideFeeVO calcRideFee(OrderVO order, LocalDateTime endTime) {
if (order == null || endTime == null || order.getStartTime() == null) {
return null;
}
OrderCalcPreRideFeeVO vo = new OrderCalcPreRideFeeVO();
Duration duration = Duration.between(order.getStartTime(), endTime);
long seconds = duration.getSeconds(); // 使用时长
vo.setSeconds(seconds);
Integer freeRideMinutes = order.getSuitFreeRideTime(); // 免费骑行时长
boolean isFree = freeRideMinutes != null && seconds <= freeRideMinutes * 60; // 是否免费
// 若免费则骑行费为0
if (isFree) {
vo.setRideFee(BigDecimal.ZERO);
}
// 否则计算骑行费
else {
SuitRentalUnit rentalUnit = SuitRentalUnit.parse(order.getSuitRentalUnit());
if (SuitRidingRule.START_FEE.getCode().equals(order.getSuitRidingRule())) {
vo.setRideFee(SuitUtil.calcAmountForStartFee(seconds, order.getSuitStartRule(), rentalUnit));
} else {
vo.setRideFee(SuitUtil.calcAmountForIntervalFee(seconds, order.getSuitIntervalRule(), rentalUnit));
}
}
return vo;
}
} }

View File

@ -39,6 +39,7 @@ import com.ruoyi.common.valid.towEle.TwoEleUtil;
import com.ruoyi.common.valid.towEle.vo.IDResponse; import com.ruoyi.common.valid.towEle.vo.IDResponse;
import com.ruoyi.system.user.domain.enums.UserAuthType; import com.ruoyi.system.user.domain.enums.UserAuthType;
import com.ruoyi.system.user.service.UserService; import com.ruoyi.system.user.service.UserService;
import com.ruoyi.system.user.utils.UserUtil;
/** /**
* 实名认证信息Service业务层处理 * 实名认证信息Service业务层处理
@ -126,7 +127,7 @@ public class RealNameServiceImpl implements RealNameService
public RealNameFaceVO faceRealName(RealName realName) { public RealNameFaceVO faceRealName(RealName realName) {
UserVO user = userService.selectUserById(realName.getUserId()); UserVO user = userService.selectUserById(realName.getUserId());
ServiceUtil.assertion(user == null,"用户信息不存在"); ServiceUtil.assertion(user == null,"用户信息不存在");
ServiceUtil.assertion(user.getIsReal() != null && user.getIsReal(),"用户已实名认证"); ServiceUtil.assertion(UserUtil.hasAuth(user, UserAuthType.REAL_NAME.getCode()),"用户已实名认证");
// 获取活体检测token // 获取活体检测token
LivenessResponseTokenData tokenData = LivenessUtils.getToken(LIVENESS_RETURN_URL, null, null); LivenessResponseTokenData tokenData = LivenessUtils.getToken(LIVENESS_RETURN_URL, null, null);
@ -215,7 +216,7 @@ public class RealNameServiceImpl implements RealNameService
// 判断用户是否已经实名认证 // 判断用户是否已经实名认证
UserVO user = userService.selectUserById(dto.getUserId()); UserVO user = userService.selectUserById(dto.getUserId());
ServiceUtil.assertion(user == null,"用户信息不存在"); ServiceUtil.assertion(user == null,"用户信息不存在");
ServiceUtil.assertion(user.getIsReal() != null && user.getIsReal(),"用户已实名认证"); ServiceUtil.assertion(UserUtil.hasAuth(user, UserAuthType.REAL_NAME.getCode()), "用户已实名认证,请勿重复实名");
IDResponse idRes = TwoEleUtil.verifyIdentity(dto.getIdCard(), dto.getUserName()); IDResponse idRes = TwoEleUtil.verifyIdentity(dto.getIdCard(), dto.getUserName());
ServiceUtil.assertion(idRes == null, "二要素实名认证返回为空,请联系管理员续费"); ServiceUtil.assertion(idRes == null, "二要素实名认证返回为空,请联系管理员续费");

View File

@ -63,5 +63,6 @@ public class IotConstants {
public static final String DS_SYS_Q = "q"; // 钥匙状态 public static final String DS_SYS_Q = "q"; // 钥匙状态
public static final String DS_SYS_LON = "lon"; // 经度 public static final String DS_SYS_LON = "lon"; // 经度
public static final String DS_SYS_LAT = "lat"; // 纬度 public static final String DS_SYS_LAT = "lat"; // 纬度
public static final String DS_CSQ = "CSQ"; // 信号强度
} }

View File

@ -136,16 +136,19 @@ public class IotReceiveServiceImpl implements IotReceiveService {
if (update != 1) { if (update != 1) {
log.error("更新设备软件版本失败: {},版本:{}", msg.getDevName(), msg.getValue()); log.error("更新设备软件版本失败: {},版本:{}", msg.getDevName(), msg.getValue());
} }
}
// CSQ 重启
else if (IotConstants.DS_CSQ.equals(msg.getDsId())) {
this.handleReboot(msg);
} }
} }
// 生命周期暂时不做需要测试 // 生命周期暂时不做需要测试
else if (ReceiveType.DEVICE_STATUS.getType().equals(msg.getType())) { else if (ReceiveType.DEVICE_STATUS.getType().equals(msg.getType())) {
// this.handleReboot(msg);
} }
} }
/** /**
* 处理设备重启 * 处理设备重启事件
*/ */
private void handleReboot(ReceiveMsg msg) { private void handleReboot(ReceiveMsg msg) {
if (msg == null || StringUtils.isBlank(msg.getDevName())) { if (msg == null || StringUtils.isBlank(msg.getDevName())) {
@ -319,9 +322,9 @@ public class IotReceiveServiceImpl implements IotReceiveService {
// 定位日志处理 // 定位日志处理
private void handleLocationLog(DeviceVO device) { private void handleLocationLog(DeviceVO device) {
// 卫星数量小于5不保存定位日志 // 卫星信号弱不保存定位日志
if (device.getSatellites() == null || device.getSatellites() < 5) { if (DeviceUtil.isLowSatelliteSignal(device.getSatellites())) {
log.error("卫星数量小于5,不处理: {}", device.getMac()); log.error("卫星信号弱,不处理: {}", device.getMac());
return; return;
} }
// 转换定位日志 // 转换定位日志

View File

@ -45,7 +45,6 @@ public class AppDeviceController extends BaseController {
} }
query.setStatus(DeviceStatus.AVAILABLE.getCode()); query.setStatus(DeviceStatus.AVAILABLE.getCode());
List<DeviceVO> list = deviceService.selectDeviceList(query); List<DeviceVO> list = deviceService.selectDeviceList(query);
deviceAssembler.assembleIot(list);
return success(list); return success(list);
} }
@ -54,7 +53,6 @@ public class AppDeviceController extends BaseController {
@Anonymous @Anonymous
public AjaxResult getAvailableDetail(@RequestParam(required = false) Long id, @RequestParam(required = false) String sn) { public AjaxResult getAvailableDetail(@RequestParam(required = false) Long id, @RequestParam(required = false) String sn) {
DeviceVO device = deviceService.selectAvaliableDevice(id, sn); DeviceVO device = deviceService.selectAvaliableDevice(id, sn);
deviceAssembler.assembleIot(device);
return success(device); return success(device);
} }

View File

@ -1,5 +1,6 @@
package com.ruoyi.web.app; package com.ruoyi.web.app;
import java.time.LocalDateTime;
import java.util.List; import java.util.List;
import java.util.function.Supplier; import java.util.function.Supplier;
@ -143,6 +144,9 @@ public class AppOrderController extends BaseController {
dto.setReturnType(OrderReturnType.NORMAL.getCode()); dto.setReturnType(OrderReturnType.NORMAL.getCode());
dto.setEndReason("用户【" + getNickName() + "】手动还车"); dto.setEndReason("用户【" + getNickName() + "】手动还车");
dto.setNeedDispatchFee(true); dto.setNeedDispatchFee(true);
if (dto.getRequiredIot() == null) {
dto.setRequiredIot(true);
}
OrderEndVO vo = orderService.endOrder(dto); OrderEndVO vo = orderService.endOrder(dto);
if (vo.getDb() > 0) { if (vo.getDb() > 0) {
return success(vo); return success(vo);
@ -163,6 +167,12 @@ public class AppOrderController extends BaseController {
return success(fee); return success(fee);
} }
@ApiOperation("计算预估骑行费")
@GetMapping("/calcPreRideFee")
public AjaxResult calcPreRideFee(Long orderId) {
return success(orderService.calcPreRideFee(orderId, LocalDateTime.now()));
}
@ApiOperation("订单开锁") @ApiOperation("订单开锁")
@PutMapping("/openDevice") @PutMapping("/openDevice")
@Log(title = "订单开锁", businessType = BusinessType.OTHER, bizIdName = "arg0", bizType = LogBizType.ORDER) @Log(title = "订单开锁", businessType = BusinessType.OTHER, bizIdName = "arg0", bizType = LogBizType.ORDER)

View File

@ -83,7 +83,6 @@ public class DeviceController extends BaseController {
if (query.getRefresh() != null && query.getRefresh()) { if (query.getRefresh() != null && query.getRefresh()) {
deviceIotService.refresh(list, IotConstants.ONLINE_TYPE_COMMAND); deviceIotService.refresh(list, IotConstants.ONLINE_TYPE_COMMAND);
} }
deviceAssembler.assembleIot(list);
return getDataTable(list); return getDataTable(list);
} }
@ -102,7 +101,6 @@ public class DeviceController extends BaseController {
if (query.getRefresh() != null && query.getRefresh()) { if (query.getRefresh() != null && query.getRefresh()) {
deviceIotService.refresh(list, IotConstants.ONLINE_TYPE_COMMAND); deviceIotService.refresh(list, IotConstants.ONLINE_TYPE_COMMAND);
} }
deviceAssembler.assembleIot(list);
return success(list); return success(list);
} }
@ -133,7 +131,6 @@ public class DeviceController extends BaseController {
if (refresh) { if (refresh) {
deviceIotService.refresh(device, IotConstants.ONLINE_TYPE_COMMAND); deviceIotService.refresh(device, IotConstants.ONLINE_TYPE_COMMAND);
} }
deviceAssembler.assembleIot(device);
return success(device); return success(device);
} }

View File

@ -54,7 +54,7 @@ public class DeviceIotController extends BaseController {
/** /**
* 执行带设备锁的操作 * 执行带设备锁的操作
* *
* @param device 设备信息 * @param device 设备信息
* @param operation 具体操作 * @param operation 具体操作
* @return 操作结果 * @return 操作结果
@ -122,7 +122,6 @@ public class DeviceIotController extends BaseController {
DeviceVO device = this.getDevice(id, sn); DeviceVO device = this.getDevice(id, sn);
return executeWithLock(device, () -> { return executeWithLock(device, () -> {
deviceIotService.refresh(device, IotConstants.ONLINE_TYPE_COMMAND); deviceIotService.refresh(device, IotConstants.ONLINE_TYPE_COMMAND);
deviceAssembler.assembleIot(device);
return success(device); return success(device);
}); });
} }