站端预约订单

This commit is contained in:
tzy 2025-04-03 16:37:35 +08:00
parent 27db32363b
commit 08ba470b87
22 changed files with 499 additions and 164 deletions

View File

@ -85,6 +85,9 @@ public interface HDConstant {
String sessionKeyPrefix = "hd:wechat:login:sessionKey:";
String wxToken = "hd:wechat:login:token:";
String tokenRandomStr = "hd:wechat:login:randomStr:";
/**
* 预约单失效前缀
*/
String preOrder="pre_order:";
}

View File

@ -8,6 +8,7 @@ import com.fasterxml.jackson.annotation.JsonFormat;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import org.springframework.format.annotation.DateTimeFormat;
@ -96,6 +97,10 @@ public class OrderSwapBattery implements Serializable {
@Schema(description = "服务费")
private BigDecimal serviceFee;
@Schema(description = "费用标准")
private List<BatteryStationHdFeeStandard> feeStandard; @Schema(description = "费用标准")
private String feeStandardJson;
@Schema(description = "上次租赁电池时车辆里程")
private BigDecimal lastRentBatCarOdo;

View File

@ -39,6 +39,9 @@ public class WalletAccount implements Serializable {
@NotBlank(message = "用户编码不能为空")
private String ownerId;
@Schema(description = "名称")
private String name;
@Schema(description = "编码", hidden = true)
private String code;

View File

@ -92,7 +92,7 @@ public class OrderSwapBatteryController {
@Operation(summary = "查询公司订单")
@GetMapping("/listcompanyorder")
@ApiOperationSupport(order = 7)
@ApiOperationSupport(order = 8)
@Hidden
@Deprecated
public Result<List<OrderSwapBattery>> listByCompany(@ParameterObject PageListSwapOrderRequest plsor) {
@ -101,7 +101,7 @@ public class OrderSwapBatteryController {
@Operation(summary = "查询换电步骤")
@GetMapping("/step/list")
@ApiOperationSupport(order = 8)
@ApiOperationSupport(order = 9)
public Result<List<OrderSwapBatteryStep>> listStep(@NotBlank String orderNo) {
return orderSwapBatteryService.listStep(orderNo);
}
@ -116,7 +116,7 @@ public class OrderSwapBatteryController {
@Operation(summary = "个人账户余额支付")
@PostMapping({"/wallet/pay"})
@ApiOperationSupport(order = 10)
@ApiOperationSupport(order = 11)
public Result<String> walletPay(@RequestParam String orderNo, String wuid, String uname) {
return orderSwapBatteryService.walletPay(orderNo, wuid, uname);
}
@ -124,7 +124,7 @@ public class OrderSwapBatteryController {
@Operation(summary = "公司订单余额支付")
@PostMapping({"/companywallet/pay"})
@ApiOperationSupport(order = 11)
@ApiOperationSupport(order = 12)
public Result<String> companyWalletPay(@RequestParam String orderNo, String wuid, String uname) {
// TODO
return null;
@ -133,16 +133,23 @@ public class OrderSwapBatteryController {
@Operation(summary = "公司订单扫码支付")
@PostMapping({"/wechat/nativepay"})
@ApiOperationSupport(order = 12)
@ApiOperationSupport(order = 13)
public Result<String> companyNativePay(@RequestBody NativePayVO prePay) {
return orderSwapBatteryService.companyNativePay(prePay);
}
@Operation(summary = "扫码支付订单查询状态")
@GetMapping("/paystatus/query")
@ApiOperationSupport(order = 13)
@ApiOperationSupport(order = 14)
public Result<String> orderQuery(String outTradeNo) {
return orderSwapBatteryService.orderQuery(outTradeNo);
}
@Operation(summary = "站端取消订单")
@PostMapping("/pre/cancelOrder")
@ApiOperationSupport(order = 15)
public Result<Integer> cancelOrder(@NotNull String orderNo) {
return orderSwapBatteryService.cancelOrder(orderNo, null);
}
}

View File

@ -2,6 +2,7 @@ package com.evotech.hd.cloud.controller.order;
import java.util.List;
import jakarta.servlet.http.HttpServletRequest;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@ -81,5 +82,11 @@ public class WalletAccountController {
public Result<List<WalletAccountDetail>> listDetail(@ParameterObject PageListWalletRequest plwr) {
return walletAccountService.listDetail(plwr);
}
@Operation(summary = "查询是否开通微信钱包")
@PostMapping("/isOpenAccount")
@ApiOperationSupport(order = 8)
public Result<Boolean> isOpenAccount(String wuid) {
return walletAccountService.isOpenAccount(wuid);
}
}

View File

@ -0,0 +1,11 @@
package com.evotech.hd.cloud.mqtt.message.dto.newer.req.order;
import lombok.Data;
@Data
public class OrdeSwapBatteryPreRespose {
private String stationPreOrderId;
private Integer code;
private String msg;
}

View File

@ -99,6 +99,7 @@ public class MessageUtilService {
MyMqttMessage message = new MyMqttMessage();
message.setHeader(header);
message.setDataBody(dataBody);
String encrypt = aes.encryptBase64(JSONUtil.toJsonStr(message));
// 3. 发送MQTT消息
publishMessage.publish(encrypt, topic.toString());

View File

@ -3,7 +3,17 @@ package com.evotech.hd.cloud.mqtt.message.handle;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Stream;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.evotech.hd.cloud.mqtt.message.dto.newer.req.order.*;
import com.evotech.hd.cloud.service.WechatUserService;
import com.evotech.hd.common.core.dao.wechat.WechatUserDao;
import com.evotech.hd.common.core.entity.Result;
import com.evotech.hd.common.core.entity.wechat.WechatUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@ -24,9 +34,6 @@ import com.evotech.hd.cloud.mqtt.message.dto.newer.req.battery.BatteryInfoRespon
import com.evotech.hd.cloud.mqtt.message.dto.newer.req.carinfo.CarInfoReq;
import com.evotech.hd.cloud.mqtt.message.dto.newer.req.carinfo.CarInfoResponse;
import com.evotech.hd.cloud.mqtt.message.dto.newer.req.carinfo.VehicleData;
import com.evotech.hd.cloud.mqtt.message.dto.newer.req.order.OrderByPlateNumReq;
import com.evotech.hd.cloud.mqtt.message.dto.newer.req.order.OrderByPlateNumResponse;
import com.evotech.hd.cloud.mqtt.message.dto.newer.req.order.OrderData;
import com.evotech.hd.cloud.service.OrderSwapBatteryService;
import com.evotech.hd.cloud.utils.CommonUtil;
import com.evotech.hd.common.core.dao.cloud.OrderSwapBatteryDao;
@ -45,8 +52,10 @@ import jakarta.annotation.Resource;
* request消息 处理
*/
@Service
@Slf4j
public class RequestMessageService {
@Resource
private WechatUserService wechatUserService;
@Resource
private VehicleWechatUserRelationDao vehicleWechatUserRelationDao;
@Resource
@ -55,11 +64,12 @@ public class RequestMessageService {
private BatteryStationDcDao batteryStationDcDao;
@Resource
private OrderSwapBatteryDao orderSwapBatteryDao;
@Resource
private OrderSwapBatteryPreDao orderSwapBatteryPreDao;
@Resource
private OrderSwapBatteryService orderSwapBatteryService;
@Async("taskExecutor")
public void request(MessageTopic topic, MqttMessageHeader header, JSONObject dataBody) {
switch (RequestFunctionTypesEnum.getFunctionType(header.getFunction())) {
@ -72,16 +82,16 @@ public class RequestMessageService {
handleBatteryInfo(topic, header, batteryInfoReq);
break;
case FUN_PREORDER:
OrderSwapBatteryPre orderSwapBatteryPre = JSONUtil.toBean(dataBody, OrderSwapBatteryPre.class);
handlOrderSwapBatteryPre(topic,header,orderSwapBatteryPre);
break;
case FUN_ORDERBYPLATENUM:
OrderByPlateNumReq orderByPlateNumReq = JSONUtil.toBean(dataBody, OrderByPlateNumReq.class);
handleOrderByPlateNum(topic, header, orderByPlateNumReq);
break;
case FUN_CANCELORDER:
CancelOrderReq cancelOrder = JSONUtil.toBean(dataBody, CancelOrderReq.class);
handlOrderCancel(topic,header,cancelOrder);
break;
default:
@ -89,8 +99,78 @@ public class RequestMessageService {
}
}
/**
* 站端取消订单
* @param topic
* @param header
* @param cancelOrder
*/
private void handlOrderCancel(MessageTopic topic, MqttMessageHeader header, CancelOrderReq cancelOrder) {
Date d = new Date();
CancelOrderResponse response = new CancelOrderResponse();
Result<Integer> integerResult = orderSwapBatteryService.cancelOrder(cancelOrder.getOrderNo(), 9);
if (integerResult.getStatus()==0){
response.setCode(0);
response.setMsg(integerResult.getMsg());
response.setOrderNo(cancelOrder.getOrderNo());
}else {
response.setCode(1);
response.setMsg(integerResult.getMsg());
response.setOrderNo("OK");
}
// 发送
topic.setDataDirection("M2S");
topic.setMessageType(MqttMessageTypeEnum.RESPONSE.getType());
header.setFunction(RequestFunctionTypesEnum.FUN_CANCELORDER.getReFunction());
header.setTimeStamp(DateUtil.format(d, DatePattern.NORM_DATETIME_FORMATTER));
log.info("\r\n=====>>>站端取消订单--MQTT发送到消息主题{},头部信息:{}订单编码;{},message:{}", topic,header, cancelOrder.getOrderNo(),JSONUtil.parseObj(response, new JSONConfig().setDateFormat(DatePattern.NORM_DATETIME_PATTERN)));
messageUtilService.publishAESMessage(topic, header, JSONUtil.parseObj(response, new JSONConfig().setDateFormat(DatePattern.NORM_DATETIME_PATTERN)));
}
/**
* 站端添加预约单
* @param topic
* @param header
* @param orderSwapBatteryPre
*/
private void handlOrderSwapBatteryPre(MessageTopic topic, MqttMessageHeader header, OrderSwapBatteryPre orderSwapBatteryPre) {
OrdeSwapBatteryPreRespose response = new OrdeSwapBatteryPreRespose();
Date d = new Date();
// 1. 基础字段校验
if (validateRequiredFields(orderSwapBatteryPre)) {
// 返回错误消息
response.setStationPreOrderId(orderSwapBatteryPre.getSourceId());
response.setMsg("预约信息不完整");
response.setCode(0);
}else {
//添加预约单
WechatUser wechatUser =wechatUserService.selectUcode(orderSwapBatteryPre.getPhone(),orderSwapBatteryPre.getUname());
//查询用户编码
orderSwapBatteryPre.setUcode(wechatUser.getWuid());
orderSwapBatteryPre.setSource(3);
Result<Integer> integerResult = orderSwapBatteryService.addPre(orderSwapBatteryPre);
//添加失败情况
if (integerResult.getStatus()==0){
response.setStationPreOrderId(orderSwapBatteryPre.getSourceId());
//返回失败状态
response.setMsg(integerResult.getMsg());
response.setCode(0);
}else{
response.setStationPreOrderId(orderSwapBatteryPre.getSourceId());
response.setCode(1);
response.setMsg("OK");
}
}
// 发送
topic.setDataDirection("M2S");
topic.setMessageType(MqttMessageTypeEnum.RESPONSE.getType());
header.setFunction(RequestFunctionTypesEnum.FUN_PREORDER.getReFunction());
header.setTimeStamp(DateUtil.format(d, DatePattern.NORM_DATETIME_FORMATTER));
log.info("\r\n=====>>>站端添加预约单--MQTT发送到消息主题{},头部信息:{},message:{}", topic,header, JSONUtil.parseObj(response, new JSONConfig().setDateFormat(DatePattern.NORM_DATETIME_PATTERN)));
messageUtilService.publishAESMessage(topic, header, JSONUtil.parseObj(response, new JSONConfig().setDateFormat(DatePattern.NORM_DATETIME_PATTERN)));
}
/**
* OrderByPlateNum请求处理
* @param topic
@ -136,7 +216,7 @@ public class RequestMessageService {
// // 加上费用标准 - 移到订单服务中了
// osb = orderBasicFeeComponent.orderBasicFee(osb);
log.info("\r\n=====>>>生成订单信息--MQTT发送到消息主题{},订单编码:{}", topic,CommonUtil.swapBatteryOrderNo(orderByPlateNumReq.getStationCode()));
orderSwapBatteryService.add(osb);
}
// 返回数据
@ -152,7 +232,7 @@ public class RequestMessageService {
topic.setMessageType(MqttMessageTypeEnum.RESPONSE.getType());
header.setFunction(RequestFunctionTypesEnum.FUN_ORDERBYPLATENUM.getReFunction());
header.setTimeStamp(DateUtil.format(d, DatePattern.NORM_DATETIME_FORMATTER));
log.info("\r\n=====>>>站端用车牌号查询订单--MQTT发送到消息主题{},头部信息:{},message:{}", topic,header, JSONUtil.parseObj(response, new JSONConfig().setDateFormat(DatePattern.NORM_DATETIME_PATTERN)));
messageUtilService.publishAESMessage(topic, header, JSONUtil.parseObj(response, new JSONConfig().setDateFormat(DatePattern.NORM_DATETIME_PATTERN)));
}
@ -190,7 +270,7 @@ public class RequestMessageService {
topic.setMessageType(MqttMessageTypeEnum.RESPONSE.getType());
header.setFunction(RequestFunctionTypesEnum.FUN_BATTERYINFO.getReFunction());
header.setTimeStamp(DateUtil.format(new Date(), DatePattern.NORM_DATETIME_FORMATTER));
log.info("\r\n=====>>>站端请求电池数据--MQTT发送到消息主题{},头部信息:{},message:{}", topic,header, JSONUtil.parseObj(response, new JSONConfig().setDateFormat(DatePattern.NORM_DATETIME_PATTERN)));
messageUtilService.publishAESMessage(topic, header, JSONUtil.parseObj(response, new JSONConfig().setDateFormat(DatePattern.NORM_DATETIME_PATTERN)));
} while (page.getCurrent() < page.getPages());
@ -231,9 +311,20 @@ public class RequestMessageService {
topic.setMessageType(MqttMessageTypeEnum.RESPONSE.getType());
header.setFunction(RequestFunctionTypesEnum.FUN_CARINFO.getReFunction());
header.setTimeStamp(DateUtil.format(new Date(), DatePattern.NORM_DATETIME_FORMATTER));
log.info("\r\n=====>>>站端请求用户车辆数据--MQTT发送到消息主题{},头部信息:{},message:{}", topic,header, JSONUtil.parseObj(response, new JSONConfig().setDateFormat(DatePattern.NORM_DATETIME_PATTERN)));
messageUtilService.publishAESMessage(topic, header, JSONUtil.parseObj(response, new JSONConfig().setDateFormat(DatePattern.NORM_DATETIME_PATTERN)));
} while (page.getCurrent() < page.getPages());
}
private boolean validateRequiredFields(OrderSwapBatteryPre order) {
return Stream.of(
order.getPlateNum(),
order.getPhone(),
order.getStationCode(),
order.getStationName(),
order.getUname(),
order.getSwapDay(),
order.getSwapDuration(),
order.getReservationTime()
).anyMatch(StrUtil::isBlankIfStr);
}
}

View File

@ -1,7 +1,10 @@
package com.evotech.hd.cloud.mqtt.message.handle;
import java.util.Date;
import java.util.Objects;
import cn.hutool.core.date.DatePattern;
import cn.hutool.json.JSONConfig;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@ -32,14 +35,13 @@ import cn.hutool.json.JSONUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
/**
* state消息 处理
*/
@Service
@Slf4j
public class StateMessageService {
@Resource
private MessageUtilService messageUtilService;
@Resource
@ -56,105 +58,113 @@ public class StateMessageService {
private VehicleInfoDao vehicleInfoDao;
@Resource
private BatteryStationDcDao batteryStationDcDao;
@Async("taskExecutor")
public void state(MessageTopic topic, MqttMessageHeader header, JSONObject dataBody) {
switch (StateFunctionTypesEnum.getFunctionType(header.getFunction())) {
case FUN_ORDERSTATUS:
OrderStatus orderStatus = JSONUtil.toBean(dataBody, OrderStatus.class);
OrderStatusData statusData = JSONUtil.toBean(dataBody.getJSONObject("statusData"), OrderStatusData.class);
handleOrderStatus(orderStatus, statusData);
// TODO 回复一下收到了
break;
case FUN_SWAPSTEP:
SwapStep swapStep = JSONUtil.toBean(dataBody, SwapStep.class);
// 记录换电步骤
OrderSwapBatteryStep step = new OrderSwapBatteryStep();
BeanUtils.copyProperties(swapStep, step);
step.setCtime(new Date());
step.setCreater("SYS");
step.setStepName(hdStepDictComponent.hdStepDictName(step.getStep()));
orderSwapBatteryStepDao.insert(step);
break;
case FUN_TEST:
break;
default:
break;
switch (Objects.requireNonNull(StateFunctionTypesEnum.getFunctionType(header.getFunction()))) {
// 站端反馈订单状态
case FUN_ORDERSTATUS:
OrderStatus orderStatus = JSONUtil.toBean(dataBody, OrderStatus.class);
OrderStatusData statusData = JSONUtil.toBean(dataBody.getJSONObject("statusData"),
OrderStatusData.class);
// 订单状态更新处理
handleOrderStatus(orderStatus, statusData);
// TODO 回复一下收到了
break;
// 站端反馈换电步骤
case FUN_SWAPSTEP:
SwapStep swapStep = JSONUtil.toBean(dataBody, SwapStep.class);
// 记录换电步骤
OrderSwapBatteryStep step = new OrderSwapBatteryStep();
BeanUtils.copyProperties(swapStep, step);
step.setCtime(new Date());
step.setCreater("SYS");
step.setStepName(hdStepDictComponent.hdStepDictName(step.getStep()));
log.info("\r\n=====>>>站端反馈换电步骤--MQTT收到消息主题{},换电步骤名称:{}",topic,hdStepDictComponent.hdStepDictName(step.getStep()) );
orderSwapBatteryStepDao.insert(step);
break;
case FUN_TEST:
break;
default:
break;
}
}
/**
* 订单状态更新处理
*
* @param orderStatus
* @param statusData
*/
private void handleOrderStatus(OrderStatus orderStatus, OrderStatusData statusData) {
switch (orderStatus.getStatus()) {
case 2:
orderStatus2(orderStatus);
break;
case 3:
// 修改订单状态和数据
OrderSwapBattery osb = alterOrderStatus(orderStatus, statusData);
// 换电步骤添加最后一条
OrderSwapBatteryStep step = new OrderSwapBatteryStep();
step.setOrderNo(orderStatus.getOrderNo());
step.setStep(8);
step.setStepTime(orderStatus.getStatusTime());
step.setCtime(new Date());
step.setCreater("SYS");
step.setStepName(hdStepDictComponent.hdStepDictName(step.getStep()));
orderSwapBatteryStepDao.insert(step);
// 修改车上电池编码
VehicleInfo vi = new VehicleInfo();
vi.setBatCode(statusData.getRentBatCode());
vi.setBatSoc(statusData.getRentBatSoc());
vehicleInfoDao.update(vi, new QueryWrapper<VehicleInfo>().eq("plate_num", osb.getPlateNum()));
// 修改2块电池的信息
BatteryStationDc dc1 = new BatteryStationDc();
BatteryStationDc dc2 = new BatteryStationDc();
dc1.setStatus(1);
dc1.setPointType(2);
dc1.setPointCode(osb.getPlateNum());
dc1.setPointName(osb.getPlateNum());
dc1.setSoc(statusData.getRentBatSoc());
dc1.setDccNo(0);
batteryStationDcDao.update(dc1, new QueryWrapper<BatteryStationDc>().eq("bat_code", statusData.getRentBatCode()));
dc2.setStatus(2);
dc2.setPointType(1);
dc2.setPointCode(osb.getStationCode());
dc2.setPointName(osb.getStationName());
dc2.setSoc(statusData.getReturnBatSoc());
dc2.setDccNo(statusData.getReturnBatNo());
batteryStationDcDao.update(dc2, new QueryWrapper<BatteryStationDc>().eq("bat_code", statusData.getReturnBatCode()));
// 添加2块电池的溯源记录
addBatteryTrace(orderStatus, statusData, osb);
break;
case 4:
// 修改订单状态
alterOrderStatus(orderStatus, null);
break;
case 5:
// 修改订单状态和数据
alterOrderStatus(orderStatus, statusData);
// 修改电池状态
BatteryStationDc dc = new BatteryStationDc();
dc.setStatus(3);
dc.setSoc(statusData.getSoc());
batteryStationDcDao.update(dc, new QueryWrapper<BatteryStationDc>().eq("bat_code", statusData.getBatCode()));
break;
default:
break;
case 2:
orderStatus2(orderStatus);
break;
case 3:
// 修改订单状态和数据
OrderSwapBattery osb = alterOrderStatus(orderStatus, statusData);
// 换电步骤添加最后一条
OrderSwapBatteryStep step = new OrderSwapBatteryStep();
step.setOrderNo(orderStatus.getOrderNo());
step.setStep(8);
step.setStepTime(orderStatus.getStatusTime());
step.setCtime(new Date());
step.setCreater("SYS");
step.setStepName(hdStepDictComponent.hdStepDictName(step.getStep()));
orderSwapBatteryStepDao.insert(step);
// 修改车上电池编码
VehicleInfo vi = new VehicleInfo();
vi.setBatCode(statusData.getRentBatCode());
vi.setBatSoc(statusData.getRentBatSoc());
vehicleInfoDao.update(vi, new QueryWrapper<VehicleInfo>().eq("plate_num", osb.getPlateNum()));
// 修改2块电池的信息
BatteryStationDc dc1 = new BatteryStationDc();
BatteryStationDc dc2 = new BatteryStationDc();
dc1.setStatus(1);
dc1.setPointType(2);
dc1.setPointCode(osb.getPlateNum());
dc1.setPointName(osb.getPlateNum());
dc1.setSoc(statusData.getRentBatSoc());
dc1.setDccNo(0);
batteryStationDcDao.update(dc1,
new QueryWrapper<BatteryStationDc>().eq("bat_code", statusData.getRentBatCode()));
dc2.setStatus(2);
dc2.setPointType(1);
dc2.setPointCode(osb.getStationCode());
dc2.setPointName(osb.getStationName());
dc2.setSoc(statusData.getReturnBatSoc());
dc2.setDccNo(statusData.getReturnBatNo());
batteryStationDcDao.update(dc2,
new QueryWrapper<BatteryStationDc>().eq("bat_code", statusData.getReturnBatCode()));
// 添加2块电池的溯源记录
addBatteryTrace(orderStatus, statusData, osb);
break;
case 4:
// 修改订单状态
alterOrderStatus(orderStatus, null);
break;
case 5:
// 修改订单状态和数据
alterOrderStatus(orderStatus, statusData);
// 修改电池状态
BatteryStationDc dc = new BatteryStationDc();
dc.setStatus(3);
dc.setSoc(statusData.getSoc());
batteryStationDcDao.update(dc,
new QueryWrapper<BatteryStationDc>().eq("bat_code", statusData.getBatCode()));
break;
default:
break;
}
}
/**
* 添加电池轨迹记录
*
* @param orderStatus
* @param statusData
* @param osb
@ -180,9 +190,9 @@ public class StateMessageService {
batteryStationDcService.addTrace(bt2);
}
/**
* 换电开始时的处理
*
* @param orderStatus
*/
private void orderStatus2(OrderStatus orderStatus) {
@ -206,12 +216,14 @@ public class StateMessageService {
/**
* 修改订单状态方法
*
* @param orderStatus
* @param statusData
* @return
*/
private OrderSwapBattery alterOrderStatus(OrderStatus orderStatus, OrderStatusData statusData) {
OrderSwapBattery osb = orderSwapBatteryDao.selectOne(new QueryWrapper<OrderSwapBattery>().eq("order_no", orderStatus.getOrderNo()));
OrderSwapBattery osb = orderSwapBatteryDao
.selectOne(new QueryWrapper<OrderSwapBattery>().eq("order_no", orderStatus.getOrderNo()));
osb.setStatus(orderStatus.getStatus());
if (orderStatus.getStatus() == 2) {
osb.setServiceTimeBegin(orderStatus.getStatusTime());
@ -231,12 +243,5 @@ public class StateMessageService {
orderSwapBatteryDao.updateById(osb);
return osb;
}
}

View File

@ -40,4 +40,9 @@ public interface OrderSwapBatteryService {
public Result<String> orderQuery(String outTradeNo);
public Result<Integer> cancelOrder(String orderNo, Integer status);
public Result<Integer> markOrderAsExpired(Integer pkId);
}

View File

@ -23,4 +23,5 @@ public interface WalletAccountService {
public Result<List<WalletAccountDetail>> listDetail(PageListWalletRequest plwr);
public Result<Boolean> isOpenAccount(String wuid);
}

View File

@ -14,4 +14,6 @@ public interface WechatUserService {
public Result<Integer> companyRelation(String wuid, String pcode, String pname);
public WechatUser selectUcode(String phone, String uname);
}

View File

@ -7,6 +7,8 @@ import java.util.Arrays;
import java.util.Date;
import java.util.List;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.evotech.hd.common.redis.utils.RedisUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
@ -70,8 +72,9 @@ public class OrderSwapBatteryServiceImpl implements OrderSwapBatteryService {
private TradeService tradeService;
@Resource
private WechatService wechatService;
@Resource
private RedisUtil redisUtil;
@Override
public Result<Integer> addPre(OrderSwapBatteryPre osbp) {
@ -84,9 +87,10 @@ public class OrderSwapBatteryServiceImpl implements OrderSwapBatteryService {
}
// 2. 检查预约人
boolean b2 = wechatUserDao.exists(new QueryWrapper<WechatUser>()
.ne("phone_number", "")
.ne("phone_number", " ")
.isNotNull("phone_number")
.eq("wuid", osbp.getUcode()));
.eq("wuid", osbp.getUcode())
);
if (!b2) {
return new Result<Integer>().error("用户认证信息不全!");
}
@ -175,20 +179,19 @@ public class OrderSwapBatteryServiceImpl implements OrderSwapBatteryService {
@Override
public Result<List<OrderSwapBattery>> list(PageListSwapOrderRequest plsor) {
Page<OrderSwapBattery> page = new Page<OrderSwapBattery>(plsor.getPageNo(), plsor.getPageSize());
List<String> plateNumList = new ArrayList<String>();
if (StringUtils.hasText(plsor.getCcode())) {
List<VehicleInfo> vehicleList = vehicleInfoDao.selectList(new QueryWrapper<VehicleInfo>().eq("ccode", plsor.getCcode()));
if (vehicleList.isEmpty()) {
return new Result<List<OrderSwapBattery>>().error("未发现该公司车辆");
}
plateNumList = vehicleList.stream().map(i -> i.getPlateNum()).toList();
plateNumList = vehicleList.stream().map(VehicleInfo::getPlateNum).toList();
} else if (StringUtils.hasText(plsor.getPlateNums())) {
plateNumList = Arrays.asList(plsor.getPlateNums().split(","));
}
List<Integer> statusList = new ArrayList<Integer>();
if (StringUtils.hasText(plsor.getStatus())) {
statusList = Arrays.asList(plsor.getStatus().split(",")).stream().map(i -> Integer.valueOf(i)).toList();
statusList = Arrays.asList(plsor.getStatus().split(",")).stream().map(Integer::valueOf).toList();
}
page = orderSwapBatteryDao.selectPage(page, new QueryWrapper<OrderSwapBattery>()
@ -257,25 +260,30 @@ public class OrderSwapBatteryServiceImpl implements OrderSwapBatteryService {
if (order.getStatus() != 5) {
return new Result<String>().error("订单状态异常!");
}
return calculateCost(order);
// // 2. 检查数据
// if (order.getBasicFee() == null || order.getServiceFee() == null) {
// order = orderBasicFeeComponent.orderBasicFee(order);
// if (order.getBasicFee() == null || order.getServiceFee() == null) {
// return new Result<String>().error("订单费用标准异常!");
// }
// }
// // 3. 选择费用计算方式 计算费用
// // 先按电量计算
// if (order.getElectAmount() == null) {
// return new Result<String>().error("充电订单 充电量 异常!");
// }
// BigDecimal fee = order.getServiceFee().add(order.getBasicFee().multiply(order.getElectAmount())).setScale(0, RoundingMode.HALF_UP);
// // 4. 修改订单
// order.setAmount(fee.intValue());
// order.setStatus(6);
// orderSwapBatteryDao.updateById(order);
// return new Result<String>().success(fee);
// 2. 检查数据
if (order.getBasicFee() == null || order.getServiceFee() == null) {
order = orderBasicFeeComponent.orderBasicFee(order);
if (order.getBasicFee() == null || order.getServiceFee() == null) {
return new Result<String>().error("订单费用标准异常!");
}
}
// 3. 选择费用计算方式 计算费用
if (order.getFeeType()==3){
// 先按电量计算
if (order.getElectAmount() == null) {
return new Result<String>().error("充电订单 充电量 异常!");
}
BigDecimal fee = order.getServiceFee().add(order.getBasicFee().multiply(order.getElectAmount())).setScale(0, RoundingMode.HALF_UP);
// 4. 修改订单
order.setAmount(fee.intValue());
order.setStatus(6);
orderSwapBatteryDao.updateById(order);
return new Result<String>().success(fee);
}else {
return new Result<String>().error("此订单不是按照电量计算");
}
}
@ -295,9 +303,17 @@ public class OrderSwapBatteryServiceImpl implements OrderSwapBatteryService {
if (order.getElectAmount() == null) {
return new Result<String>().error("充电订单 充电量 异常!");
}
//基础费用*充电总量
fee = order.getServiceFee().add(order.getBasicFee().multiply(order.getElectAmount())).setScale(0, RoundingMode.HALF_UP);
} else if (order.getFeeType() == 2) {
// TODO 按SOC
if (order.getReturnBatRentSoc() == null || order.getRentBatSoc() == null) {
return new Result<String>().error("充电订单 SOC 异常!");
}
// 计算 SOC
BigDecimal socDifference = new BigDecimal(order.getRentBatSoc() - order.getReturnBatRentSoc());
fee = order.getServiceFee().add(order.getBasicFee().multiply(socDifference)).setScale(0, RoundingMode.HALF_UP);
} else if (order.getFeeType() == 1) {
// TODO 按里程
@ -350,6 +366,7 @@ public class OrderSwapBatteryServiceImpl implements OrderSwapBatteryService {
trade.setPayMsg("OK");
trade.setPayer(wuid);
trade.setWallet(wallet.getCode());
trade.setPayTime(new Date());
tradeService.add(trade);
// 添加明细
@ -394,4 +411,43 @@ public class OrderSwapBatteryServiceImpl implements OrderSwapBatteryService {
return wechatService.orderQuery(2, outTradeNo);
}
@Override
public Result<Integer> cancelOrder(String orderNo, Integer status) {
//根据订单编码查询此订单
OrderSwapBattery order = orderSwapBatteryDao.selectOne(new QueryWrapper<OrderSwapBattery>().eq("order_no", orderNo));
// 1. 查看订单是否存在
OrderSwapBattery cancelOr = new OrderSwapBattery();
if (order == null) {
return new Result<Integer>().error("订单不存在");
}
// 2. 校验当前状态是否允许取消
if (!Arrays.asList(3,4,5,6,7).contains(order.getStatus())) {
return new Result<Integer>().error("当前状态不允许取消,订单状态:" + order.getStatus());
}
cancelOr.setPkId(order.getPkId());
cancelOr.setStatus(9);
cancelOr.setUptime(new Date());
// 3.更新订单状态
int i = orderSwapBatteryDao.updateById(cancelOr);
if (i==1){
return new Result<Integer>().success(i);
}else{
return new Result<Integer>().error("取消换电订单失败");
}
}
@Override
public Result<Integer> markOrderAsExpired(Integer pkId) {
OrderSwapBatteryPre orderSwapBatteryPre = orderSwapBatteryPreDao.selectById(pkId);
orderSwapBatteryPre.setStatus(3);
int re = orderSwapBatteryPreDao.updateById(orderSwapBatteryPre);
if (re==1){
return new Result<Integer>().success(re);
}
else{
return new Result<Integer>().error("换电预约订单失败");
}
}
}

View File

@ -5,6 +5,9 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.evotech.hd.common.core.dao.wechat.WechatUserDao;
import com.evotech.hd.common.core.entity.wechat.WechatUser;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
@ -31,17 +34,30 @@ public class WalletAccountServiceImpl implements WalletAccountService {
private WalletAccountDao walletAccountDao;
@Resource
private WalletAccountDetailDao walletAccountDetailDao;
@Resource
private WechatUserDao wechatUserDao;
@Override
public Result<Integer> add(WalletAccount wa) {
wa.setCtime(new Date());
String prefix = "YTWA" + (wa.getOwnerType() == 1 ? "P" : "C");
wa.setCode(prefix + SnowflakeUtil.getIdStr() + RandomUtil.randomStringUpper(6));
int n = walletAccountDao.insert(wa);
if (n == 1) {
return new Result<Integer>().success(n);
}
return new Result<Integer>().error("添加资金账户出错!");
//查询是否有相同的账户信息
LambdaQueryWrapper<WalletAccount> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(WalletAccount::getOwnerId,wa.getOwnerId());
WalletAccount walletAccount = walletAccountDao.selectOne(queryWrapper);
LambdaQueryWrapper<WechatUser> eq = new LambdaQueryWrapper<>();
eq.eq(WechatUser::getAppid,wa.getOwnerId());
WechatUser wechatUser = wechatUserDao.selectOne(eq);
// 如果账户已存在返回错误信息
if (walletAccount != null) {
return new Result<Integer>().error("该账户已存在,无法重复添加!");
}
wa.setName(wechatUser.getName());
wa.setCtime(new Date());
String prefix = "YTWA" + (wa.getOwnerType() == 1 ? "P" : "C");
wa.setCode(prefix + SnowflakeUtil.getIdStr() + RandomUtil.randomStringUpper(6));
int n = walletAccountDao.insert(wa);
if (n == 1) {
return new Result<Integer>().success(n);
}
return new Result<Integer>().error("添加资金账户出错!");
}
@Override
@ -81,6 +97,8 @@ public class WalletAccountServiceImpl implements WalletAccountService {
.eq(plwr.getOwnerType() != null, "owner_type", plwr.getOwnerType())
.eq(StringUtils.hasText(plwr.getOwnerId()), "owner_id", plwr.getOwnerId())
.orderByDesc("pk_id"));
//获取交易明细对应的微信用户
if (page.getRecords().isEmpty()) {
return new Result<List<WalletAccount>>().error(CodeMsg.DATABASE_RESULT_NULL);
}
@ -122,4 +140,17 @@ public class WalletAccountServiceImpl implements WalletAccountService {
return new Result<List<WalletAccountDetail>>().success(page);
}
@Override
public Result<Boolean> isOpenAccount(String wuid) {
LambdaQueryWrapper<WalletAccount> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(WalletAccount::getOwnerId,wuid);
WalletAccount walletAccount = walletAccountDao.selectOne(queryWrapper);
// 判断账户是否存在
if (walletAccount != null) {
return new Result<Boolean>().success(true); // 账户已开通
} else {
return new Result<Boolean>().success(false); // 账户未开通
}
}
}

View File

@ -73,8 +73,14 @@ public class WechatUserServiceImpl implements WechatUserService {
return new Result<Integer>().error("关联公司信息出错!");
}
@Override
public WechatUser selectUcode(String phone, String uname) {
return wechatUserDao.selectOne(new QueryWrapper<WechatUser>()
.eq("phone_number", phone)
.eq("name", uname));
}
}

View File

@ -0,0 +1,50 @@
package com.evotech.hd.cloud.task;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.evotech.hd.cloud.dao.OrderSwapBatteryPreDao;
import com.evotech.hd.cloud.service.OrderSwapBatteryService;
import com.evotech.hd.common.core.dao.cloud.OrderSwapBatteryDao;
import com.evotech.hd.common.core.entity.cloud.OrderSwapBattery;
import com.evotech.hd.common.core.entity.cloud.OrderSwapBatteryPre;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
@Component
@Slf4j
public class OrderSwapBatteryTask {
@Resource
private OrderSwapBatteryPreDao orderSwapBatteryPreDao;
@Resource
private RedisTemplate redisTemplate;
@Scheduled(cron ="0 0 11,14,16,18,20 * * ?")
public void orderSwapBatteryExpired() {
log.info("\r\n===>>>开始查找预约单更新预约状态..");
QueryWrapper<OrderSwapBatteryPre> eq = new QueryWrapper<>();
eq.ne("status",4)
.ne("status",3)
.eq("del_flag",1);
List<OrderSwapBatteryPre> orderSwapBatteryPreList = orderSwapBatteryPreDao.selectList(eq);
// 获取当前时间
Date currentTime = new Date();
int expiredCount = 0; // 记录过期的预约单数量
for (OrderSwapBatteryPre order : orderSwapBatteryPreList) {
// 检查预约时间是否已过期
if (order.getReservationTime() != null && order.getReservationTime().before(currentTime)) {
// 更新状态为过期假设状态 5 表示过期
order.setStatus(3); // 设置为过期状态
orderSwapBatteryPreDao.updateById(order); // 更新数据库
expiredCount++;
}
}
log.info("\r\n===>>>预约单过期:{} 条数据", expiredCount);
}
}

View File

@ -1,8 +1,10 @@
package com.evotech.hd.cloud.utils.components;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;
import cn.hutool.json.JSONUtil;
import org.springframework.stereotype.Component;
import com.evotech.hd.cloud.dao.BatteryStationHdFeeStandardDao;
@ -16,33 +18,55 @@ import jakarta.annotation.Resource;
@Component
public class SwapOrderBasicFeeComponent {
@Resource
private BatteryStationHdFeeStandardDao batteryStationHdFeeStandardDao;
/**
* 计算订单的基本费用和服务费用
* 更新人:tzy
* 内容:增加注释
* @param osb 订单对象包含站点代码和订单时间
* @return 更新后的订单对象包含计算后的基本费用和服务费用
*/
public OrderSwapBattery orderBasicFee(OrderSwapBattery osb) {
// 根据换电站编码和订单时间查询费用标准列表
List<BatteryStationHdFeeStandard> list = batteryStationHdFeeStandardDao.listFeeStandard(osb.getStationCode(), DateUtil.format(osb.getOrderTime(), DatePattern.PURE_DATE_FORMATTER));
// 如果费用标准列表不为空说明找到了相关的费用标准
if (!list.isEmpty()) {
// 获取第一个费用标准
BatteryStationHdFeeStandard standard = list.get(0);
// 获取该标准下的详细费用列表
List<BatteryStationHdFeeStandardDetail> detailList = standard.getDetailList();
List<BatteryStationHdFeeStandard> battery = new ArrayList<>();
battery.add(standard);
// 如果详细费用列表不为空进行时间范围过滤
if (!detailList.isEmpty()) {
// 过滤出当前时间在有效时间范围内的费用详情
detailList = detailList.stream().filter(i -> i.getTimeBegin().compareTo(LocalTime.now()) <= 0)
.filter(i -> i.getTimeEnd().compareTo(LocalTime.now()) >= 0).toList();
.filter(i -> i.getTimeEnd().compareTo(LocalTime.now()) >= 0).toList();
// 如果过滤后的详细费用列表不为空使用第一个有效的费用详情
if (!detailList.isEmpty()) {
BatteryStationHdFeeStandardDetail detail = detailList.get(0);
// 设置基本费用和服务费用
osb.setFeeStandardJson(JSONUtil.toJsonStr(detail));
osb.setFeeStandard(battery);
osb.setBasicFee(detail.getEachKwhFee());
osb.setServiceFee(detail.getTimeServiceFee());
} else {
// 如果没有有效的详细费用使用标准费用
osb.setFeeStandard(battery);
osb.setBasicFee(standard.getEachKwhFee());
osb.setServiceFee(standard.getCommonRemainFee());
}
} else {
// 如果没有详细费用直接使用标准费用
osb.setFeeStandard(battery);
osb.setBasicFee(standard.getEachKwhFee());
osb.setServiceFee(standard.getCommonRemainFee());
}
}
// 返回更新后的订单对象
return osb;
}

View File

@ -75,6 +75,11 @@ public class WechatUserController {
public Result<List<WalletAccountDetail>> listWalletDetail(String walletCode, @ParameterObject BasePageRequest basePage) {
return wechatUserService.listWalletDetail(walletCode, basePage);
}
@Operation(summary = "查询用户是否开通钱包")
@PostMapping("/wallet/isOpenAccount")
@ApiOperationSupport(order = 7)
public Result<Boolean> isOpenAccount(String wuid, HttpServletRequest request) {
return wechatUserService.isOpenAccount(wuid,request);
}
}

View File

@ -24,4 +24,5 @@ public interface WechatUserService {
public Result<List<WalletAccountDetail>> listWalletDetail(String walletCode, BasePageRequest basePage);
public Result<Boolean> isOpenAccount(String wuid, HttpServletRequest request);
}

View File

@ -63,7 +63,7 @@ public class OrderServiceImpl implements OrderService {
@Override
public Result<String> walletPay(String orderNo, String wuid, String uname) {
// 看账号
if (!wuid.equals(request.getHeader(HDConstant.WECHAT_SERVER_AUTHORIZATION_KEY))) {
return new Result<String>().error("账号错误");
}

View File

@ -1,5 +1,6 @@
package com.evotech.hd.wechat.service.impl;
import java.nio.file.WatchService;
import java.util.List;
import org.springframework.stereotype.Service;
@ -29,8 +30,9 @@ public class WechatUserServiceImpl implements WechatUserService {
private WechatUserDao wechatUserDao;
@Resource
private CloudService cloudService;
@Override
public Result<String> update(WechatUser wuser) {
WechatUser user = new WechatUser();
@ -87,7 +89,7 @@ public class WechatUserServiceImpl implements WechatUserService {
if (wuid == null || !wuid.equals(request.getHeader(HDConstant.WECHAT_SERVER_AUTHORIZATION_KEY))) {
return new Result<List<WalletAccount>>().error("账号错误");
}
return cloudService.listWallet(wuid);
}
@ -101,4 +103,19 @@ public class WechatUserServiceImpl implements WechatUserService {
return cloudService.listWalletDetail(plwr);
}
/**
* 这方法是要查询用户,查询用户需要用到cloudService模块吗?不是 是查询用户时候开通钱包 钱包在cloudserver 这个
* @param wuid
* @param request
* @return
*/
@Override
public Result<Boolean> isOpenAccount(String wuid, HttpServletRequest request) {
// 1. 从请求头获取 Token
if (wuid == null || !wuid.equals(request.getHeader(HDConstant.WECHAT_SERVER_AUTHORIZATION_KEY))) {
return new Result<Boolean>().error("账号错误!");
}
return cloudService.isOpenAccount(wuid);
}
}

View File

@ -79,4 +79,8 @@ public interface CloudService {
consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE})
public Result<String> walletPay(@RequestParam String orderNo, @RequestParam String wuid, @RequestParam String uname);
@PostMapping(value = "/cloud/wallet/isOpenAccount",
consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE})
public Result<Boolean> isOpenAccount( @RequestParam String wuid);
}