自动识别
parent
1fc09bb9d3
commit
8e2427369f
|
|
@ -0,0 +1,27 @@
|
||||||
|
package com.njzscloud.dispose.cst.order.config;
|
||||||
|
|
||||||
|
import com.njzscloud.dispose.cst.order.service.TruckWeighingEventListener;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.boot.CommandLineRunner;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 车辆称重配置
|
||||||
|
* 用于初始化车辆称重事件监听器
|
||||||
|
*
|
||||||
|
* @author ljw
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Configuration
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class TruckWeighingConfig implements CommandLineRunner {
|
||||||
|
|
||||||
|
private final TruckWeighingEventListener truckWeighingEventListener;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(String... args) {
|
||||||
|
log.info("启动车辆称重事件监听器");
|
||||||
|
truckWeighingEventListener.init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
package com.njzscloud.dispose.cst.order.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 语音提示常量
|
||||||
|
*
|
||||||
|
* @author ljw
|
||||||
|
*/
|
||||||
|
public class VoiceConstants {
|
||||||
|
|
||||||
|
private VoiceConstants() {
|
||||||
|
// 工具类,防止实例化
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String VOICE_WELCOME = "欢迎光临";
|
||||||
|
public static final String VOICE_WEIGHING = "正在称重请稍候";
|
||||||
|
public static final String VOICE_PLEASE_PASS = "请通行";
|
||||||
|
public static final String VOICE_WEIGH_COMPLETE = "称重完成";
|
||||||
|
public static final String VOICE_ORDER_NOT_FOUND = "订单不存在";
|
||||||
|
public static final String VOICE_SYSTEM_ERROR = "系统异常";
|
||||||
|
public static final String VOICE_WEIGH_FAILED = "称重失败";
|
||||||
|
public static final String VOICE_STATUS_ERROR = "状态异常";
|
||||||
|
public static final String VOICE_SETTLEMENT_ERROR = "结算异常";
|
||||||
|
public static final String VOICE_UNCHECKED = "未看料";
|
||||||
|
}
|
||||||
|
|
@ -109,7 +109,7 @@ public class OrderController {
|
||||||
* 车辆进场
|
* 车辆进场
|
||||||
*/
|
*/
|
||||||
@PostMapping("/truck_coming")
|
@PostMapping("/truck_coming")
|
||||||
public R<?> truckComing(@RequestBody TruckComingParam param) {
|
public synchronized R<?> truckComing(@RequestBody TruckComingParam param) {
|
||||||
orderService.truckComing(param);
|
orderService.truckComing(param);
|
||||||
return R.success();
|
return R.success();
|
||||||
}
|
}
|
||||||
|
|
@ -118,7 +118,7 @@ public class OrderController {
|
||||||
* 看料
|
* 看料
|
||||||
*/
|
*/
|
||||||
@PostMapping("/check")
|
@PostMapping("/check")
|
||||||
public R<?> check(@RequestBody CheckGoodsParam checkGoodsParam) {
|
public synchronized R<?> check(@RequestBody CheckGoodsParam checkGoodsParam) {
|
||||||
orderService.check(checkGoodsParam);
|
orderService.check(checkGoodsParam);
|
||||||
return R.success();
|
return R.success();
|
||||||
}
|
}
|
||||||
|
|
@ -127,7 +127,7 @@ public class OrderController {
|
||||||
* 车辆出场
|
* 车辆出场
|
||||||
*/
|
*/
|
||||||
@PostMapping("/truck_leaving")
|
@PostMapping("/truck_leaving")
|
||||||
public R<?> truckLeaving(@RequestBody TruckLeavingParam leavingParam) {
|
public synchronized R<?> truckLeaving(@RequestBody TruckLeavingParam leavingParam) {
|
||||||
orderService.truckLeaving(leavingParam);
|
orderService.truckLeaving(leavingParam);
|
||||||
return R.success();
|
return R.success();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,4 +21,11 @@ public interface OrderTransMapper extends BaseMapper<OrderTransEntity> {
|
||||||
|
|
||||||
IPage<OrderTransResult> paging(Page<Object> page, @Param("ew") QueryWrapper<?> ew);
|
IPage<OrderTransResult> paging(Page<Object> page, @Param("ew") QueryWrapper<?> ew);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据车牌号查找运输订单
|
||||||
|
* @param licensePlate 车牌号
|
||||||
|
* @return 运输订单结果
|
||||||
|
*/
|
||||||
|
OrderTransResult getByLicensePlate(@Param("licensePlate") String licensePlate);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import com.njzscloud.common.core.ex.Exceptions;
|
import com.njzscloud.common.core.ex.Exceptions;
|
||||||
import com.njzscloud.common.core.fastjson.Fastjson;
|
import com.njzscloud.common.core.fastjson.Fastjson;
|
||||||
import com.njzscloud.common.core.tuple.Tuple2;
|
|
||||||
import com.njzscloud.common.mp.support.PageParam;
|
import com.njzscloud.common.mp.support.PageParam;
|
||||||
import com.njzscloud.common.mp.support.PageResult;
|
import com.njzscloud.common.mp.support.PageResult;
|
||||||
import com.njzscloud.common.security.util.SecurityUtil;
|
import com.njzscloud.common.security.util.SecurityUtil;
|
||||||
|
|
@ -27,9 +26,6 @@ import com.njzscloud.dispose.cst.order.pojo.result.OrderTransResult;
|
||||||
import com.njzscloud.dispose.cst.order.pojo.vo.Scope;
|
import com.njzscloud.dispose.cst.order.pojo.vo.Scope;
|
||||||
import com.njzscloud.dispose.cst.truck.mapper.TruckMapper;
|
import com.njzscloud.dispose.cst.truck.mapper.TruckMapper;
|
||||||
import com.njzscloud.dispose.cst.truck.pojo.entity.TruckEntity;
|
import com.njzscloud.dispose.cst.truck.pojo.entity.TruckEntity;
|
||||||
import com.njzscloud.dispose.dev.DiscoverTruckMsg;
|
|
||||||
import com.njzscloud.dispose.dev.ObtainTruckDataResultMsg;
|
|
||||||
import com.njzscloud.dispose.dev.WbsHandle;
|
|
||||||
import com.njzscloud.dispose.finance.constant.ScopeStrategy;
|
import com.njzscloud.dispose.finance.constant.ScopeStrategy;
|
||||||
import com.njzscloud.dispose.finance.pojo.entity.ExpenseItemEntity;
|
import com.njzscloud.dispose.finance.pojo.entity.ExpenseItemEntity;
|
||||||
import com.njzscloud.dispose.finance.service.ExpenseItemService;
|
import com.njzscloud.dispose.finance.service.ExpenseItemService;
|
||||||
|
|
@ -42,12 +38,8 @@ import org.springframework.transaction.annotation.Transactional;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static com.njzscloud.dispose.dev.DevMittEvent.DISCOVER_TRUCK;
|
|
||||||
import static com.njzscloud.dispose.dev.DevMittEvent.OBTAIN_TRUCK_DATA_REPLY;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 收/销订单
|
* 收/销订单
|
||||||
*
|
*
|
||||||
|
|
@ -66,55 +58,6 @@ public class OrderService extends ServiceImpl<OrderMapper, OrderEntity> {
|
||||||
private final CustomerMapper customerMapper;
|
private final CustomerMapper customerMapper;
|
||||||
private final OrderExpenseItemsService orderExpenseItemsService;
|
private final OrderExpenseItemsService orderExpenseItemsService;
|
||||||
|
|
||||||
{
|
|
||||||
DISCOVER_TRUCK.on(this::a);
|
|
||||||
OBTAIN_TRUCK_DATA_REPLY.on(this::b);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void a(Tuple2<DiscoverTruckMsg, WbsHandle> param) {
|
|
||||||
DiscoverTruckMsg param0 = param.get_0();
|
|
||||||
WbsHandle param1 = param.get_1();
|
|
||||||
|
|
||||||
// 车头照
|
|
||||||
String image = param0.getImage();
|
|
||||||
// 写库要加锁
|
|
||||||
String licensePlate = param0.getLicensePlate();
|
|
||||||
// 找订单
|
|
||||||
|
|
||||||
// 发语音
|
|
||||||
|
|
||||||
// 进前置、出前置
|
|
||||||
|
|
||||||
// 进场
|
|
||||||
|
|
||||||
// 获取磅重、车斗照片
|
|
||||||
param1.obtainTruckData(1L);
|
|
||||||
param1.playVoice(image, 2);
|
|
||||||
param1.open();
|
|
||||||
return;
|
|
||||||
// 出场
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ReentrantLock reentrantLock = new ReentrantLock();
|
|
||||||
|
|
||||||
public void b(Tuple2<ObtainTruckDataResultMsg, WbsHandle> param) {
|
|
||||||
ObtainTruckDataResultMsg it0 = param.get_0();
|
|
||||||
WbsHandle it1 = param.get_1();
|
|
||||||
// 车斗照
|
|
||||||
Long orderId = it0.getOrderId();
|
|
||||||
String image = it0.getImage();
|
|
||||||
Integer weight = it0.getWeight();
|
|
||||||
it1.open();
|
|
||||||
it1.playVoice(image, 2);
|
|
||||||
|
|
||||||
synchronized (this) {
|
|
||||||
// 写库要加锁
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void add(CreateOrderParam param) {
|
public void add(CreateOrderParam param) {
|
||||||
// 订单信息
|
// 订单信息
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,481 @@
|
||||||
|
package com.njzscloud.dispose.cst.order.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
|
import com.njzscloud.common.core.tuple.Tuple2;
|
||||||
|
import com.njzscloud.common.oss.util.AliOSS;
|
||||||
|
import com.njzscloud.dispose.cst.order.constant.*;
|
||||||
|
import com.njzscloud.dispose.cst.order.mapper.OrderTransMapper;
|
||||||
|
import com.njzscloud.dispose.cst.order.pojo.entity.OrderEntity;
|
||||||
|
import com.njzscloud.dispose.cst.order.pojo.entity.OrderTransEntity;
|
||||||
|
import com.njzscloud.dispose.cst.order.pojo.result.OrderTransResult;
|
||||||
|
import com.njzscloud.dispose.dev.DiscoverTruckMsg;
|
||||||
|
import com.njzscloud.dispose.dev.ObtainTruckDataResultMsg;
|
||||||
|
import com.njzscloud.dispose.dev.WbsHandle;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Base64;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 车辆称重业务服务
|
||||||
|
* 处理磅房称重相关的所有业务逻辑
|
||||||
|
*
|
||||||
|
* @author ljw
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class TruckWeighingBusinessService {
|
||||||
|
|
||||||
|
private final OrderService orderService;
|
||||||
|
private final OrderTransMapper orderTransMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求数据 - 处理车辆识别
|
||||||
|
*/
|
||||||
|
public void requestData(Tuple2<DiscoverTruckMsg, WbsHandle> param) {
|
||||||
|
DiscoverTruckMsg truckMsg = param.get_0();
|
||||||
|
WbsHandle handle = param.get_1();
|
||||||
|
// 车牌号
|
||||||
|
String licensePlate = truckMsg.getLicensePlate();
|
||||||
|
// 是否为前置道闸
|
||||||
|
boolean isFront = truckMsg.isFront();
|
||||||
|
// 根据车牌号查找运输订单
|
||||||
|
OrderTransResult orderTrans = orderTransMapper.getByLicensePlate(licensePlate);
|
||||||
|
if (orderTrans == null) {
|
||||||
|
log.warn("未找到车牌号 {} 对应的运输订单", licensePlate);
|
||||||
|
handle.playVoice(VoiceConstants.VOICE_ORDER_NOT_FOUND);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 验证订单业务状态
|
||||||
|
if (!validateOrderBusinessStatus(orderTrans)) {
|
||||||
|
handle.playVoice(VoiceConstants.VOICE_STATUS_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用同步锁确保数据一致性
|
||||||
|
synchronized (this) {
|
||||||
|
try {
|
||||||
|
log.info("开始处理车辆 {} 进出场请求,前置道闸: {}", licensePlate, isFront ? "是" : "否");
|
||||||
|
|
||||||
|
// 判断是进场还是出场
|
||||||
|
boolean isComing = isTruckComing(orderTrans);
|
||||||
|
boolean isLeaving = isTruckLeaving(orderTrans);
|
||||||
|
if (isLeaving) {
|
||||||
|
// 出场时检查是否已看料
|
||||||
|
if (!CheckStatus.YiKanLiao.equals(orderTrans.getCheckStatus())) {
|
||||||
|
handle.playVoice(licensePlate + VoiceConstants.VOICE_UNCHECKED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isComing && !isLeaving) {
|
||||||
|
log.warn("订单 {} 状态不允许进出场操作,当前状态:订单={},运输={}",
|
||||||
|
orderTrans.getId(), orderTrans.getOrderStatus(), orderTrans.getTransStatus());
|
||||||
|
handle.playVoice(VoiceConstants.VOICE_STATUS_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isFront) {
|
||||||
|
// 前置道闸:还未上磅,只负责开门让车辆通过
|
||||||
|
log.info("前置道闸开门,车辆 {} 进入磅区", licensePlate);
|
||||||
|
handle.playVoice(VoiceConstants.VOICE_WELCOME);
|
||||||
|
handle.open();
|
||||||
|
} else {
|
||||||
|
// 后置道闸:车辆已过磅,负责称重和算账,但不开门
|
||||||
|
log.info("后置道闸开始称重,车辆 {},订单ID: {}", licensePlate, orderTrans.getId());
|
||||||
|
handle.playVoice(VoiceConstants.VOICE_WEIGHING);
|
||||||
|
handle.obtainTruckData(orderTrans.getId());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("处理车辆 {} 识别异常", licensePlate, e);
|
||||||
|
handle.playVoice(VoiceConstants.VOICE_SYSTEM_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理数据 - 处理磅重数据
|
||||||
|
*/
|
||||||
|
public void disposeData(Tuple2<ObtainTruckDataResultMsg, WbsHandle> param) {
|
||||||
|
ObtainTruckDataResultMsg dataMsg = param.get_0();
|
||||||
|
WbsHandle wbsHandle = param.get_1();
|
||||||
|
|
||||||
|
Long orderTransId = dataMsg.getOrderId();
|
||||||
|
String image = dataMsg.getImage();
|
||||||
|
Integer weight = dataMsg.getWeight();
|
||||||
|
Boolean success = dataMsg.getSuccess();
|
||||||
|
|
||||||
|
// 检查数据获取是否成功
|
||||||
|
if (!Boolean.TRUE.equals(success) || weight == null || weight <= 0) {
|
||||||
|
log.warn("获取车辆数据失败或重量无效,订单ID: {}, 重量: {}", orderTransId, weight);
|
||||||
|
wbsHandle.playVoice(VoiceConstants.VOICE_WEIGH_FAILED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized (this) {
|
||||||
|
try {
|
||||||
|
log.info("开始处理称重数据,运输ID: {}, 重量: {}kg", orderTransId, weight);
|
||||||
|
|
||||||
|
// 根据运输ID获取订单信息
|
||||||
|
OrderTransResult orderTrans = orderTransMapper.getById(orderTransId);
|
||||||
|
if (orderTrans == null) {
|
||||||
|
log.warn("未找到运输订单 {}", orderTransId);
|
||||||
|
wbsHandle.playVoice(VoiceConstants.VOICE_ORDER_NOT_FOUND);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!CheckStatus.YiKanLiao.equals(orderTrans.getCheckStatus())) {
|
||||||
|
wbsHandle.playVoice(orderTrans.getTruckLicensePlate() + VoiceConstants.VOICE_UNCHECKED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据当前状态处理称重数据
|
||||||
|
processWeighingData(orderTrans, weight, image, wbsHandle);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("处理车辆称重数据异常,订单ID: {}", orderTransId, e);
|
||||||
|
wbsHandle.playVoice(VoiceConstants.VOICE_SYSTEM_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理称重数据
|
||||||
|
*/
|
||||||
|
private void processWeighingData(OrderTransResult orderTrans, Integer weight, String image, WbsHandle wbsHandle) {
|
||||||
|
// 根据当前状态判断是进场还是出场
|
||||||
|
if (TransStatus.YunShuZhong.equals(orderTrans.getTransStatus())) {
|
||||||
|
// 进场:设置相应重量,完成后开门
|
||||||
|
handleTruckComingData(orderTrans, weight, image);
|
||||||
|
wbsHandle.playVoice(VoiceConstants.VOICE_PLEASE_PASS);
|
||||||
|
wbsHandle.open();
|
||||||
|
} else if (TransStatus.YiJinChang.equals(orderTrans.getTransStatus())) {
|
||||||
|
// 出场:设置相应重量并计算净重、账目,等待支付完成后再开门
|
||||||
|
handleTruckLeavingData(orderTrans, weight, image);
|
||||||
|
wbsHandle.playVoice(VoiceConstants.VOICE_WEIGH_COMPLETE);
|
||||||
|
// TODO: 触发算账流程,支付完成后调用 completePaymentAndOpenGate 方法开门
|
||||||
|
processSettlementAndWaitForPayment(orderTrans, wbsHandle);
|
||||||
|
} else {
|
||||||
|
log.warn("运输订单 {} 状态 {} 不支持称重操作", orderTrans.getId(), orderTrans.getTransStatus());
|
||||||
|
wbsHandle.playVoice(VoiceConstants.VOICE_STATUS_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理进场称重数据
|
||||||
|
*/
|
||||||
|
private void handleTruckComingData(OrderTransResult orderTrans, Integer weight, String bodyPhoto) {
|
||||||
|
OrderTransEntity transEntity = new OrderTransEntity();
|
||||||
|
transEntity.setId(orderTrans.getId());
|
||||||
|
transEntity.setTransStatus(TransStatus.YiJinChang);
|
||||||
|
transEntity.setInTime(LocalDateTime.now());
|
||||||
|
|
||||||
|
// 上传车斗照片并设置URL
|
||||||
|
if (bodyPhoto != null && !bodyPhoto.trim().isEmpty()) {
|
||||||
|
String photoUrl = uploadBase64Image(bodyPhoto, "truck_body_in_" + orderTrans.getId());
|
||||||
|
transEntity.setInBodyPhoto(photoUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置重量(进场)
|
||||||
|
setWeightByOrderType(transEntity, orderTrans, weight, true);
|
||||||
|
|
||||||
|
orderTransMapper.updateById(transEntity);
|
||||||
|
log.info("车辆进场称重完成,订单ID: {}, 重量: {}kg", orderTrans.getId(), weight);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理出场称重数据
|
||||||
|
*/
|
||||||
|
private void handleTruckLeavingData(OrderTransResult orderTrans, Integer weight, String bodyPhoto) {
|
||||||
|
OrderTransEntity transEntity = new OrderTransEntity();
|
||||||
|
transEntity.setId(orderTrans.getId());
|
||||||
|
transEntity.setTransStatus(TransStatus.YiChuChang);
|
||||||
|
transEntity.setOutTime(LocalDateTime.now());
|
||||||
|
|
||||||
|
// 上传车斗照片并设置URL
|
||||||
|
if (bodyPhoto != null && !bodyPhoto.trim().isEmpty()) {
|
||||||
|
String photoUrl = uploadBase64Image(bodyPhoto, "truck_body_out_" + orderTrans.getId());
|
||||||
|
transEntity.setOutBodyPhoto(photoUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置重量(出场)
|
||||||
|
setWeightByOrderType(transEntity, orderTrans, weight, false);
|
||||||
|
|
||||||
|
// 计算净重
|
||||||
|
calculateAndSetNetWeight(transEntity, orderTrans);
|
||||||
|
|
||||||
|
orderTransMapper.updateById(transEntity);
|
||||||
|
Integer settleWeight = transEntity.getSettleWeight();
|
||||||
|
log.info("车辆出场称重完成,订单ID: {}, 重量: {}kg, 净重: {}kg",
|
||||||
|
orderTrans.getId(), weight, settleWeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据订单类型设置重量
|
||||||
|
*/
|
||||||
|
private void setWeightByOrderType(OrderTransEntity transEntity, OrderTransResult orderTrans, Integer weight, boolean isComing) {
|
||||||
|
if (OrderCategory.HuiShouYuYue.equals(orderTrans.getOrderCategory())) {
|
||||||
|
// 回收预约单:进场称毛重,出场称皮重
|
||||||
|
if (isComing) {
|
||||||
|
transEntity.setRoughWeight(weight);
|
||||||
|
} else {
|
||||||
|
transEntity.setTareWeight(weight);
|
||||||
|
// 更新车辆皮重
|
||||||
|
orderService.updateTruckHisTareWeight(orderTrans.getTruckId(), weight);
|
||||||
|
}
|
||||||
|
} else if (OrderCategory.XiaoShouYuYue.equals(orderTrans.getOrderCategory())) {
|
||||||
|
// 销售预约单:进场称皮重,出场称毛重
|
||||||
|
if (isComing) {
|
||||||
|
transEntity.setTareWeight(weight);
|
||||||
|
// 更新车辆皮重
|
||||||
|
orderService.updateTruckHisTareWeight(orderTrans.getTruckId(), weight);
|
||||||
|
} else {
|
||||||
|
transEntity.setRoughWeight(weight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算并设置净重
|
||||||
|
*/
|
||||||
|
private void calculateAndSetNetWeight(OrderTransEntity transEntity, OrderTransResult orderTrans) {
|
||||||
|
Integer roughWeight = transEntity.getRoughWeight() != null ? transEntity.getRoughWeight() : orderTrans.getRoughWeight();
|
||||||
|
Integer tareWeight = transEntity.getTareWeight() != null ? transEntity.getTareWeight() : orderTrans.getTareWeight();
|
||||||
|
|
||||||
|
if (roughWeight != null && tareWeight != null && roughWeight > tareWeight) {
|
||||||
|
Integer settleWeight = roughWeight - tareWeight;
|
||||||
|
transEntity.setSettleWeight(settleWeight);
|
||||||
|
log.debug("计算净重完成,毛重: {}kg, 皮重: {}kg, 净重: {}kg", roughWeight, tareWeight, settleWeight);
|
||||||
|
} else {
|
||||||
|
log.warn("无法计算净重,毛重: {}, 皮重: {}", roughWeight, tareWeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传base64编码的图片到阿里云OSS
|
||||||
|
*/
|
||||||
|
private String uploadBase64Image(String base64Image, String fileNamePrefix) {
|
||||||
|
if (base64Image == null || base64Image.trim().isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 移除base64前缀(如"data:image/jpeg;base64,")
|
||||||
|
String base64Data;
|
||||||
|
if (base64Image.contains(",")) {
|
||||||
|
base64Data = base64Image.substring(base64Image.indexOf(",") + 1);
|
||||||
|
} else {
|
||||||
|
base64Data = base64Image;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解码base64字符串为字节数组
|
||||||
|
byte[] imageBytes = Base64.getDecoder().decode(base64Data);
|
||||||
|
|
||||||
|
// 生成文件名
|
||||||
|
String fileName = fileNamePrefix + "_" + System.currentTimeMillis() + ".jpg";
|
||||||
|
|
||||||
|
// 创建ByteArrayInputStream并上传到OSS
|
||||||
|
try (ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes)) {
|
||||||
|
// 使用AliOSS直接上传
|
||||||
|
String url = AliOSS.uploadFile(fileName, "image/jpeg", inputStream);
|
||||||
|
|
||||||
|
log.info("车斗照片上传成功: {}", url);
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("上传base64车斗照片失败", e);
|
||||||
|
// 上传失败时返回原始base64字符串作为降级方案
|
||||||
|
return base64Image;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否为进场操作
|
||||||
|
* 订单状态为进行中,运输状态为运输中
|
||||||
|
*/
|
||||||
|
private boolean isTruckComing(OrderTransResult orderTrans) {
|
||||||
|
return OrderStatus.JinXingZhong.equals(orderTrans.getOrderStatus()) &&
|
||||||
|
TransStatus.YunShuZhong.equals(orderTrans.getTransStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否为出场操作
|
||||||
|
* 订单状态为进行中,运输状态为已进场
|
||||||
|
*/
|
||||||
|
private boolean isTruckLeaving(OrderTransResult orderTrans) {
|
||||||
|
return OrderStatus.JinXingZhong.equals(orderTrans.getOrderStatus()) &&
|
||||||
|
TransStatus.YiJinChang.equals(orderTrans.getTransStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证订单业务状态
|
||||||
|
*/
|
||||||
|
private boolean validateOrderBusinessStatus(OrderTransResult orderTrans) {
|
||||||
|
// 检查订单状态
|
||||||
|
if (!OrderStatus.JinXingZhong.equals(orderTrans.getOrderStatus())) {
|
||||||
|
log.warn("订单状态异常,订单ID: {}, 当前状态: {}", orderTrans.getId(), orderTrans.getOrderStatus());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查运输状态
|
||||||
|
TransStatus transStatus = orderTrans.getTransStatus();
|
||||||
|
if (!TransStatus.YunShuZhong.equals(transStatus) && !TransStatus.YiJinChang.equals(transStatus)) {
|
||||||
|
log.warn("运输状态异常,订单ID: {}, 当前状态: {}", orderTrans.getId(), transStatus);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查订单类型
|
||||||
|
if (orderTrans.getOrderCategory() == null) {
|
||||||
|
log.warn("订单类型为空,订单ID: {}", orderTrans.getId());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查订单下所有运输记录是否都已完成
|
||||||
|
*/
|
||||||
|
private boolean checkAllTransCompleted(Long orderId) {
|
||||||
|
try {
|
||||||
|
// 查询该订单下的所有运输记录
|
||||||
|
List<OrderTransEntity> transList = orderTransMapper.selectList(
|
||||||
|
Wrappers.<OrderTransEntity>lambdaQuery()
|
||||||
|
.eq(OrderTransEntity::getOrderId, orderId)
|
||||||
|
.eq(OrderTransEntity::getDeleted, Boolean.FALSE)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (transList.isEmpty()) {
|
||||||
|
log.warn("订单 {} 下没有找到运输记录", orderId);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查所有运输记录的状态是否都为已完成
|
||||||
|
boolean allCompleted = transList.stream()
|
||||||
|
.allMatch(trans -> TransStatus.YiWanCheng.equals(trans.getTransStatus()));
|
||||||
|
|
||||||
|
if (allCompleted) {
|
||||||
|
log.info("订单 {} 下所有 {} 条运输记录都已完成", orderId, transList.size());
|
||||||
|
} else {
|
||||||
|
long completedCount = transList.stream()
|
||||||
|
.filter(trans -> TransStatus.YiWanCheng.equals(trans.getTransStatus()))
|
||||||
|
.count();
|
||||||
|
log.info("订单 {} 下 {}/{} 条运输记录已完成", orderId, completedCount, transList.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
return allCompleted;
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("检查订单 {} 运输完成状态异常", orderId, e);
|
||||||
|
// 出现异常时保守处理,返回false
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理结算并等待支付完成
|
||||||
|
*/
|
||||||
|
private void processSettlementAndWaitForPayment(OrderTransResult orderTrans, WbsHandle wbsHandle) {
|
||||||
|
try {
|
||||||
|
log.info("开始处理订单 {} 的结算流程", orderTrans.getId());
|
||||||
|
|
||||||
|
// TODO: 执行算账逻辑
|
||||||
|
// 这里应该调用财务结算服务,计算费用并生成支付订单
|
||||||
|
// calculateSettlement(orderTrans);
|
||||||
|
|
||||||
|
// 模拟支付完成通知(实际应该通过支付回调或消息队列处理)
|
||||||
|
// 在实际生产环境中,应该:
|
||||||
|
// 1. 调用财务服务计算费用
|
||||||
|
// 2. 生成支付订单
|
||||||
|
// 3. 等待支付完成的通知(通过消息队列或回调)
|
||||||
|
// 4. 支付完成后调用 completePaymentAndOpenGate 方法
|
||||||
|
|
||||||
|
log.info("订单 {} 结算流程启动,等待支付完成", orderTrans.getId());
|
||||||
|
|
||||||
|
// TODO: 在实际支付完成后调用以下方法
|
||||||
|
// completePaymentAndOpenGate(orderTrans, wbsHandle);
|
||||||
|
|
||||||
|
// 临时实现:直接完成(用于测试)
|
||||||
|
simulatePaymentCompletion(orderTrans, wbsHandle);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("处理订单 {} 结算异常", orderTrans.getId(), e);
|
||||||
|
handleBusinessException(wbsHandle, "结算处理失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模拟支付完成(测试用)
|
||||||
|
*/
|
||||||
|
private void simulatePaymentCompletion(OrderTransResult orderTrans, WbsHandle wbsHandle) {
|
||||||
|
// 在实际应用中,这里应该通过消息队列或定时任务等待支付完成
|
||||||
|
// 这里只是为了演示流程,实际应该移除
|
||||||
|
try {
|
||||||
|
// 模拟支付处理时间
|
||||||
|
Thread.sleep(2000);
|
||||||
|
completePaymentAndOpenGate(orderTrans, wbsHandle);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
log.error("模拟支付完成被中断", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付完成并开门
|
||||||
|
*/
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void completePaymentAndOpenGate(OrderTransResult orderTrans, WbsHandle wbsHandle) {
|
||||||
|
synchronized (this) {
|
||||||
|
try {
|
||||||
|
// 更新运输状态为已完成
|
||||||
|
OrderTransEntity transEntity = new OrderTransEntity();
|
||||||
|
transEntity.setId(orderTrans.getId());
|
||||||
|
transEntity.setTransStatus(TransStatus.YiWanCheng);
|
||||||
|
transEntity.setFinishTime(LocalDateTime.now());
|
||||||
|
orderTransMapper.updateById(transEntity);
|
||||||
|
|
||||||
|
// 检查该订单下所有运输记录是否都已完成
|
||||||
|
boolean allTransCompleted = checkAllTransCompleted(orderTrans.getOrderId());
|
||||||
|
|
||||||
|
if (allTransCompleted) {
|
||||||
|
// 更新订单状态为已完成
|
||||||
|
OrderEntity orderEntity = new OrderEntity();
|
||||||
|
orderEntity.setId(orderTrans.getOrderId());
|
||||||
|
orderEntity.setOrderStatus(OrderStatus.YiWanCheng);
|
||||||
|
orderEntity.setFinishTime(LocalDateTime.now());
|
||||||
|
orderService.updateById(orderEntity);
|
||||||
|
log.info("订单 {} 所有运输记录已完成,订单状态更新为已完成", orderTrans.getOrderId());
|
||||||
|
} else {
|
||||||
|
log.info("订单 {} 还有未完成的运输记录,暂不更新订单状态", orderTrans.getOrderId());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 开门放行
|
||||||
|
wbsHandle.playVoice(VoiceConstants.VOICE_PLEASE_PASS);
|
||||||
|
wbsHandle.open();
|
||||||
|
|
||||||
|
log.info("运输记录 {} 支付完成,开门放行", orderTrans.getId());
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
handleBusinessException(wbsHandle, "完成订单 " + orderTrans.getId() + " 支付并开门异常", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理业务异常
|
||||||
|
*/
|
||||||
|
private void handleBusinessException(WbsHandle wbsHandle, String message, Exception e) {
|
||||||
|
log.error("业务处理异常: {}", message, e);
|
||||||
|
try {
|
||||||
|
wbsHandle.playVoice(VoiceConstants.VOICE_SYSTEM_ERROR);
|
||||||
|
} catch (Exception voiceException) {
|
||||||
|
log.error("播放语音失败", voiceException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
package com.njzscloud.dispose.cst.order.service;
|
||||||
|
|
||||||
|
import com.njzscloud.common.core.tuple.Tuple2;
|
||||||
|
import com.njzscloud.dispose.dev.DiscoverTruckMsg;
|
||||||
|
import com.njzscloud.dispose.dev.ObtainTruckDataResultMsg;
|
||||||
|
import com.njzscloud.dispose.dev.WbsHandle;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import static com.njzscloud.dispose.dev.DevMittEvent.DISCOVER_TRUCK;
|
||||||
|
import static com.njzscloud.dispose.dev.DevMittEvent.OBTAIN_TRUCK_DATA_REPLY;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 车辆称重事件监听器
|
||||||
|
* 负责处理磅房设备的车辆识别和称重数据事件
|
||||||
|
*
|
||||||
|
* @author ljw
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class TruckWeighingEventListener {
|
||||||
|
|
||||||
|
private final TruckWeighingBusinessService businessService;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化事件监听器
|
||||||
|
*/
|
||||||
|
public void init() {
|
||||||
|
log.info("初始化车辆称重事件监听器");
|
||||||
|
DISCOVER_TRUCK.on(this::requestData);
|
||||||
|
OBTAIN_TRUCK_DATA_REPLY.on(this::disposeData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求数据 - 处理车辆识别
|
||||||
|
*/
|
||||||
|
public void requestData(Tuple2<DiscoverTruckMsg, WbsHandle> param) {
|
||||||
|
businessService.requestData(param);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理数据 - 处理磅重数据
|
||||||
|
*/
|
||||||
|
public void disposeData(Tuple2<ObtainTruckDataResultMsg, WbsHandle> param) {
|
||||||
|
businessService.disposeData(param);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -140,4 +140,18 @@
|
||||||
${ew.customSqlSegment}
|
${ew.customSqlSegment}
|
||||||
</if>
|
</if>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="getByLicensePlate" resultMap="BaseResultMap">
|
||||||
|
SELECT
|
||||||
|
<include refid="Base_Column_List"/>
|
||||||
|
FROM cst_order_trans cot
|
||||||
|
LEFT JOIN cst_order co on co.id = cot.order_id
|
||||||
|
LEFT JOIN gds_goods gg on gg.id = co.goods_id
|
||||||
|
LEFT JOIN gds_goods_category ggc on ggc.id = gg.goods_category_id
|
||||||
|
WHERE cot.truck_license_plate = #{licensePlate}
|
||||||
|
AND cot.trans_status IN ('YunShuZhong', 'YiJinChang')
|
||||||
|
AND cot.deleted = 0
|
||||||
|
ORDER BY cot.create_time DESC
|
||||||
|
LIMIT 1
|
||||||
|
</select>
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue