Преглед изворни кода

提交收费系统对外对接接口包装

chenxiaofei пре 14 часа
родитељ
комит
efa9d000d2

+ 12 - 1
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/handler/ComeIntoHandler.java

@@ -20,7 +20,9 @@ import com.sckw.system.api.model.dto.res.SysDictResDto;
 import com.sckw.transport.model.*;
 import com.sckw.transport.model.enuma.WeighbridgeTypeEnum;
 import com.sckw.transport.model.param.WaybillOrderCmeIntoWeighParam;
+import com.sckw.transport.util.ParkingNotificationAsyncService;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -41,6 +43,10 @@ import java.util.stream.Collectors;
 @Service
 public class ComeIntoHandler extends AbstractWaybillOrderHandler<WaybillOrderCmeIntoWeighParam> {
 
+    @Autowired
+    private ParkingNotificationAsyncService parkingNotificationAsyncService;
+
+
     @Override
     protected KwtWaybillOrder getWaybillOrder(WaybillOrderCmeIntoWeighParam param) {
         return getWaybillOrder(param.getWaybillOrderId());
@@ -60,9 +66,14 @@ public class ComeIntoHandler extends AbstractWaybillOrderHandler<WaybillOrderCme
         if (orderTicket == null) {
             throw new BusinessPlatfromException(ErrorCodeEnum.WAYBILL_ORDER_TICKET_NOT_FOUND, "当前物流运单装卸货信息不存在,无法记录皮重!");
         }
-        if (checkIsFirst(waybillOrder)) {
+        // 校验是否是第一次过磅
+        checkIsFirst(waybillOrder);
+        if (waybillOrder.getIsExistWeighbridges()) {
             //第一次过磅
             firstWeighbridge(param, waybillOrder, orderTicket);
+
+            // 异步通知第三方车辆入场
+            parkingNotificationAsyncService.asyncEntryNotification(param, waybillOrder);
         } else {
             //第二次过磅
             laterWeighbridge(param,waybillOrder, orderTicket);

+ 6 - 1
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/model/KwtParkingStrategySwitch.java

@@ -23,7 +23,7 @@ public class KwtParkingStrategySwitch implements Serializable {
     private Long id;
 
     /**
-     * 状态(0-关闭,1-开启)
+     * 服务费状态(0-关闭,1-开启)
      */
     private Integer status;
 
@@ -33,6 +33,11 @@ public class KwtParkingStrategySwitch implements Serializable {
     @TableField("default_fee")
     private BigDecimal defaultFee;
 
+    /**
+     * 入场状态(0-关闭,1-开启)
+     */
+    private Integer intoStatus;
+
     /**
      * 创建人
      */

+ 6 - 0
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/model/param/OrderTakingResp.java

@@ -25,5 +25,11 @@ public class OrderTakingResp implements Serializable {
     @Schema(description = "运单id")
     private Long waybillOrderId;
 
+    /**
+     * 充值url
+     */
+    @Schema(description = "充值url")
+    private String chargeUrl;
+
 
 }

+ 7 - 0
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/model/param/ParkingStrategySwitchSaveParam.java

@@ -40,4 +40,11 @@ public class ParkingStrategySwitchSaveParam implements Serializable {
      * 默认费用
      */
     private BigDecimal defaultFee;
+
+    /**
+     * 入场状态开关(0-关闭、1-开启)
+     */
+    @NotNull(message = "入场状态开关不能为空")
+    @Schema(description = "入场状态开关")
+    private Integer intoStatus;
 }

+ 1 - 0
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/service/ParkingChangeStrategyService.java

@@ -314,6 +314,7 @@ public class ParkingChangeStrategyService {
         }
         strategySwitch.setStatus(param.getStatus());
         strategySwitch.setDefaultFee(param.getDefaultFee());
+        strategySwitch.setIntoStatus(param.getIntoStatus());
         parkingStrategySwitchRepository.updateById(strategySwitch);
     }
 

+ 136 - 4
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/service/app/GatekeeperOrderService.java

@@ -13,6 +13,7 @@ import com.sckw.core.model.constant.Global;
 import com.sckw.core.model.enums.CarWaybillV1Enum;
 import com.sckw.core.model.enums.ForkliftStatusEnum;
 import com.sckw.core.model.enums.GatekeeperStatusEnum;
+import com.sckw.core.model.enums.GatekeeperTypeEnum;
 import com.sckw.core.utils.CollectionUtils;
 import com.sckw.core.utils.DateUtils;
 import com.sckw.core.utils.StringUtils;
@@ -30,6 +31,7 @@ import com.sckw.transport.model.param.forklift.request.GatekeeperOrderPassReason
 import com.sckw.transport.model.param.forklift.request.GatekeeperOrderQueryParam;
 import com.sckw.transport.model.vo.StatisticsWaybillResp;
 import com.sckw.transport.repository.*;
+import com.sckw.transport.util.ParkingNotificationAsyncService;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.dubbo.config.annotation.DubboReference;
@@ -37,6 +39,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.math.BigDecimal;
 import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.function.Function;
@@ -68,6 +71,10 @@ public class GatekeeperOrderService {
     @Autowired
     protected KwtLogisticsOrderUnitRepository logisticsOrderUnitRepository;
 
+    @Autowired
+    private ParkingNotificationAsyncService parkingNotificationAsyncService;
+
+
     @DubboReference(version = "1.0.0", group = "design", check = false)
     private RemoteContractService remoteContractService;
 
@@ -576,11 +583,136 @@ public class GatekeeperOrderService {
         if (gatekeeper == null) {
             throw new BusinessPlatfromException(ErrorCodeEnum.FORKLIFT_ORDER_NOT_FOUND, "当前门卫订单不存在!");
         }
-        //1. 更改门卫状态为:已放行
-        updateGatekeeperOrderStatus(gatekeeper, param);
 
-        //2. 更改司机状态为:已放行未离场
-        updateWaybillOrderStatus(gatekeeper, param);
+        //放行后直接抬杆离场
+        driverPass(param, gatekeeper);
+    }
+
+
+    /**
+     * 放行后直接离场
+     * @param param
+     * @param gatekeeper
+     */
+    private void driverPass(GatekeeperOrderPassParam param, KwtGatekeeperWaybillOrder gatekeeper) {
+        // 查询运单
+        KwtWaybillOrder waybillOrder = waybillOrderRepository.getById(gatekeeper.getWOrderId());
+        if (waybillOrder == null) {
+            throw new BusinessPlatfromException(ErrorCodeEnum.FORKLIFT_ORDER_NOT_FOUND, "[门卫放行]当前运单数据不存在!");
+        }
+
+        //1. 计算是否空载离场
+        Boolean isEmptyLoadLeave = calculateEmptyLoad(waybillOrder);
+
+        //2. 更改门卫状态为:已离场
+        updateGatekeeperOrderStatus2(gatekeeper, param, isEmptyLoadLeave);
+
+        //3. 更改司机状态为:已离场
+        updateWaybillOrderStatus2(gatekeeper, param, waybillOrder, isEmptyLoadLeave);
+
+        //4. 创建门卫卸货订单
+//        creatGatekeeperUnLoadingOrder(gatekeeper, waybillOrder);
+
+        // 异步通知第三方出场收费接口
+        parkingNotificationAsyncService.asyncExitNotification(waybillOrder, gatekeeper, isEmptyLoadLeave);
+    }
+    /**
+     * 更改司机状态为:已离场
+     * @param gatekeeper
+     */
+    private void updateWaybillOrderStatus2(KwtGatekeeperWaybillOrder gatekeeper, GatekeeperOrderPassParam param,
+                                           KwtWaybillOrder waybillOrder, Boolean isEmptyLoadLeave) {
+        // 1. 修改运单状态:已离场
+        updateWaybillStatus2(gatekeeper, waybillOrder, isEmptyLoadLeave);
+
+        // 2. 修改子运单状态:已离场
+        updateWaybillSubtaskStatus2(gatekeeper, isEmptyLoadLeave);
+
+        // 3.创建运单轨迹日日志
+        creatWaybillOrderNode(gatekeeper, param);
+    }
+
+    /**
+     * 修改运单状态
+     * @param gatekeeper
+     */
+    private void updateWaybillStatus2(KwtGatekeeperWaybillOrder gatekeeper, KwtWaybillOrder waybillOrder,Boolean isEmptyLoadLeave) {
+        log.info("[门卫放行]更改运单状态为已离场/空载离场:{}", JSON.toJSONString(gatekeeper));
+        //装货单
+        if (Objects.equals(gatekeeper.getType(), GatekeeperTypeEnum.LOADING.getCode())) {
+            if (!CarWaybillV1Enum.WAIT_RELEASE.getCode().equals(waybillOrder.getStatus())) {
+                throw new BusinessPlatfromException(ErrorCodeEnum.WAYBILL_ORDER_STATUS_ERROR, "当前运单状态异常,不能推进为已离场!");
+            }
+            // 校验状态:若是空载离场,运单状态为已完成
+            CarWaybillV1Enum status = isEmptyLoadLeave ? CarWaybillV1Enum.COMPLETED : CarWaybillV1Enum.WAIT_LOADING;
+            if (isEmptyLoadLeave) {
+                waybillOrder.setRemark("空载离场");
+            }
+            waybillOrder.setStatus(status.getCode());
+        }
+        waybillOrderRepository.updateById(waybillOrder);
+        log.info("[门卫放行]更改运单状态为已离场/空载离场完成!");
+    }
+    /**
+     * 修改子运单状态
+     * @param gatekeeper
+     */
+    private void updateWaybillSubtaskStatus2(KwtGatekeeperWaybillOrder gatekeeper, Boolean isEmptyLoadLeave) {
+        log.info("[门卫放行]更改子运单状态为已离场/空载离场:{}", JSON.toJSONString(gatekeeper));
+        KwtWaybillOrderSubtask waybillSubtask = waybillOrderSubtaskRepository.queryByWOrderId(gatekeeper.getWOrderId());
+        if (waybillSubtask == null) {
+            throw new BusinessPlatfromException(ErrorCodeEnum.WAYBILL_ORDER_SUB_NOT_FOUND, "未找到关联的子运单!");
+        }
+        //装货单
+        if (Objects.equals(gatekeeper.getType(), GatekeeperTypeEnum.LOADING.getCode())) {
+            if (!CarWaybillV1Enum.WAIT_RELEASE.getCode().equals(waybillSubtask.getStatus())) {
+                throw new BusinessPlatfromException(ErrorCodeEnum.WAYBILL_ORDER_STATUS_ERROR, "当前子运单状态异常,不能推进为已离场!");
+            }
+            // 校验状态:若是空载离场,运单状态为已完成
+            CarWaybillV1Enum status = isEmptyLoadLeave ? CarWaybillV1Enum.COMPLETED : CarWaybillV1Enum.WAIT_LOADING;
+            waybillSubtask.setStatus(status.getCode());
+        }
+        waybillOrderSubtaskRepository.updateById(waybillSubtask);
+        log.info("[门卫放行]更改子运单状态为已离场/空载离场完成!");
+    }
+
+    /**
+     * 更改门卫状态为:已放行
+     * @param gatekeeper
+     */
+    private void updateGatekeeperOrderStatus2(KwtGatekeeperWaybillOrder gatekeeper, GatekeeperOrderPassParam param, Boolean isEmptyLoadLeave) {
+        log.info("[门卫放行]更改门卫状态为已放行:{}", JSON.toJSONString(gatekeeper));
+        if (!GatekeeperStatusEnum.PENDING_RELEASE.getCode().equals(gatekeeper.getStatus())) {
+            throw new BusinessPlatfromException(ErrorCodeEnum.FORKLIFT_ORDER_STATUS_ERROR, "当前门卫订单状态异常,不能放行!");
+        }
+        //门卫放行后状态更改为:已离场/空载离场
+        GatekeeperStatusEnum targetStatus = isEmptyLoadLeave ? GatekeeperStatusEnum.EMPTY_EXITED : GatekeeperStatusEnum.EXITED;
+        gatekeeper.setStatus(targetStatus.getCode());
+        gatekeeper.setLeaveTime(new Date());
+        gatekeeper.setGatekeeperUserId(param.getGatekeeperUserId());
+        gatekeeper.setGatekeeperName(param.getGatekeeperName());
+        gatekeeper.setUpdateUser(param.getGatekeeperUserId());
+        gatekeeperWaybillOrderRepository.updateById(gatekeeper);
+        log.info("[门卫放行]更改门卫状态已放行完成!");
+    }
+    /**
+     * 计算是否空载离场
+     * @param waybillOrder
+     * @return
+     */
+    private Boolean calculateEmptyLoad(KwtWaybillOrder waybillOrder) {
+        log.info("[门卫放行]计算是否空载离场:{}", JSON.toJSONString(waybillOrder));
+        //查询运单装卸货信息
+        KwtWaybillOrderTicket orderTicket = waybillOrderTicketRepository.queryByWOrderIdByIdAndType(waybillOrder.getId(), 1);
+        if (orderTicket == null) {
+            throw new BusinessPlatfromException(ErrorCodeEnum.WAYBILL_ORDER_TICKET_NOT_FOUND, "当前物流运单装卸货信息不存在,无法记录皮重!");
+        }
+        BigDecimal loadAmount = orderTicket.getAmount();
+
+        //空载离场,净重<=0.5
+        boolean result = loadAmount != null && loadAmount.compareTo(BigDecimal.valueOf(0.5)) <= 0;
+        log.info("[门卫放行]计算是否空载离场完成:{}", JSON.toJSONString(result));
+        return result;
     }
 
     /**

+ 47 - 1
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/service/app/WaybillOrderService.java

@@ -35,6 +35,7 @@ import com.sckw.transport.model.vo.OrderTotalTakeVo;
 import com.sckw.transport.model.vo.StatisticsWaybillResp;
 import com.sckw.transport.repository.*;
 import com.sckw.transport.service.KwtWaybillOrderV1Service;
+import com.sckw.transport.service.ParkingPlateInfoService;
 import jakarta.annotation.Resource;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -75,6 +76,10 @@ public class WaybillOrderService {
     private final KwtWaybillOrderAddressRepository waybillOrderAddressRepository;
     private final KwtWaybillOrderTicketRepository waybillOrderTicketRepository;
     private final KwtWaybillOrderNodeRepository waybillOrderNodeRepository;
+    private final KwtWaybillOrderWeighbridgeRepository waybillOrderWeighbridgeRepository;
+    private final KwtLogisticsOrderContractRepository logisticsOrderContractRepository;
+    private final KwtParkingStrategySwitchRepository parkingStrategySwitchRepository;
+    private final ParkingPlateInfoService parkingPlateInfoService;
 
     @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 6000)
     RemoteSystemService remoteSystemService;
@@ -1200,7 +1205,7 @@ public class WaybillOrderService {
             checkIdempotent(param);
 
             // 5. 执行接单
-            return takingOrderHandler.handler(param);
+            return takingOrder(param);
 
         } finally {
             // 6. 释放分布式锁
@@ -1211,6 +1216,47 @@ public class WaybillOrderService {
         }
     }
 
+    /**
+     * 接单
+     * @param param
+     */
+    private OrderTakingResp takingOrder(OrderCirculateTakingQueryParam param) {
+        // 访问第三方接口,校验车辆费用情况
+        ParkingPlatformResult<PlateInfoResp> result = checkTruckFee(param);
+        boolean isAvailable = (result == null || Objects.equals(1, result.getData().getAcceptOrder()));
+        log.info("调用第三方接口校验车辆是否可以通行,reslt:{}", isAvailable);
+        if (isAvailable) {
+           return takingOrderHandler.handler(param);
+        } else {
+            OrderTakingResp resp = new OrderTakingResp();
+            resp.setChargeUrl(result.getData().getChargeUrl());
+            return resp;
+        }
+    }
+
+    /**
+     * 校验车辆是否在车场有效期、充值缴费、是否是免费车
+     * @param param
+     */
+    private ParkingPlatformResult<PlateInfoResp> checkTruckFee(OrderCirculateTakingQueryParam param) {
+        KwtParkingStrategySwitch strategySwitch = parkingStrategySwitchRepository.queryParkingStrategySwitch();
+        // 入场收费开关关闭,不校验
+        if (strategySwitch == null || Objects.equals(strategySwitch.getIntoStatus(), 0)) {
+            log.info("入场收费开关,reslt:{}", "关闭");
+            return null;
+        }
+
+        // 校验
+        PlateInfoQueryParam queryParam = new PlateInfoQueryParam();
+        queryParam.setCarLicense(param.getTruckNo());
+        ParkingPlatformResult<PlateInfoResp> parkingPlatformResult = parkingPlateInfoService.queryPlateInfo(queryParam);
+        if (parkingPlatformResult == null || parkingPlatformResult.getData() == null) {
+            throw new BusinessPlatfromException(ErrorCodeEnum.WAYBILL_ORDER_NOT_UNFINISHED, "第三发车辆信息查询接口,当前车辆未查出信息");
+        }
+        log.info("校验车辆是否在车场有效期,reslt:{}", JSON.toJSONString(parkingPlatformResult));
+        return parkingPlatformResult;
+    }
+
     /**
      * 幂等性校验:检查是否已经存在该车辆针对该物流订单的有效运单
      * @param param 接单参数

+ 75 - 0
sckw-modules/sckw-transport/src/main/java/com/sckw/transport/util/ParkingNotificationAsyncService.java

@@ -0,0 +1,75 @@
+package com.sckw.transport.util;
+
+import com.sckw.transport.model.KwtGatekeeperWaybillOrder;
+import com.sckw.transport.model.KwtParkingStrategySwitch;
+import com.sckw.transport.model.KwtWaybillOrder;
+import com.sckw.transport.model.param.EntryNotificationParam;
+import com.sckw.transport.model.param.ExitNotificationParam;
+import com.sckw.transport.model.param.WaybillOrderCmeIntoWeighParam;
+import com.sckw.transport.repository.KwtParkingStrategySwitchRepository;
+import com.sckw.transport.service.ParkingPlateInfoService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Service;
+
+import java.util.Objects;
+
+@Service
+@Slf4j
+public class ParkingNotificationAsyncService {
+
+    @Autowired
+    private ParkingPlateInfoService parkingPlateInfoService;
+    @Autowired
+    private KwtParkingStrategySwitchRepository parkingStrategySwitchRepository;
+
+    /**
+     * 异步通知第三方车辆入场
+     * 注意:此方法必须放在另一个 Bean 中,否则 @Async 会失效
+     */
+    @Async
+    public void asyncEntryNotification(WaybillOrderCmeIntoWeighParam param, KwtWaybillOrder waybillOrder) {
+        try {
+            log.info("异步调用第三方车辆入场通知接口,运单号:{}", waybillOrder.getId());
+
+            EntryNotificationParam entryParam = new EntryNotificationParam();
+            entryParam.setCarLicense(param.getTruckNo());
+            entryParam.setGateId(String.valueOf(param.getWeighbridgeId()));
+            entryParam.setBusinessId(waybillOrder.getWOrderNo());
+
+            parkingPlateInfoService.entryNotification(entryParam);
+            log.info("异步调用第三方车辆入场通知接口成功,运单号:{}", waybillOrder.getId());
+        } catch (Exception e) {
+            log.error("异步通知第三方车辆入场失败, 运单号: {}, 车牌号: {}", waybillOrder.getWOrderNo(), param.getTruckNo(), e);
+        }
+    }
+
+    /**
+     * 异步通知第三方出场扣费
+     * 注意:此方法必须放在另一个 Bean 中,否则 @Async 会失效
+     */
+    @Async
+    public void asyncExitNotification(KwtWaybillOrder waybillOrder, KwtGatekeeperWaybillOrder gatekeeperWaybillOrder, Boolean isEmptyLoadLeave) {
+        try {
+            log.info("异步调用第三方车辆出场扣费通知接口,运单号:{}", waybillOrder.getId());
+            KwtParkingStrategySwitch strategySwitch = parkingStrategySwitchRepository.queryParkingStrategySwitch();
+            // 入场收费开关关闭,不做扣费
+            if (strategySwitch == null || Objects.equals(strategySwitch.getIntoStatus(), 0)) {
+                log.info("入场收费开关,reslt:{}", "关闭");
+                return;
+            }
+
+            ExitNotificationParam exitParam = new ExitNotificationParam();
+            exitParam.setCarLicense(waybillOrder.getTruckNo());
+            exitParam.setGateId(String.valueOf(gatekeeperWaybillOrder.getWeighbridgeId()));
+            exitParam.setBusinessId(gatekeeperWaybillOrder.getWOrderNo());
+            exitParam.setNeedDeduct(isEmptyLoadLeave ? 0 : 1);
+
+            parkingPlateInfoService.exitNotification(exitParam);
+            log.error("异步调用第三方车辆出场扣款通知接口成功, 运单号: {}, 车牌号: {}, 是否空载:{}", waybillOrder.getWOrderNo(), waybillOrder.getTruckNo(), isEmptyLoadLeave);
+        } catch (Exception e) {
+            log.error("异步调用第三方车辆出场扣款通知失败, 运单号: {}, 车牌号: {}", waybillOrder.getWOrderNo(), waybillOrder.getTruckNo(), e);
+        }
+    }
+}

+ 3 - 2
sql/2026/06/2026_06_16_create.sql

@@ -66,8 +66,9 @@ CREATE TABLE `kwt_parking_wallet_fee_balance` (
 
 CREATE TABLE `kwt_parking_strategy_switch` (
                                                `id`                            bigint          NOT NULL AUTO_INCREMENT COMMENT '主键',
-                                               status                          int             NOT NULL DEFAULT '0' COMMENT '状态(0-关闭,1-开启)',
-                                               default_fee                decimal(16,2)   NOT NULL DEFAULT '0.00' COMMENT '默认服务费',
+                                               status                          int             NOT NULL DEFAULT '0' COMMENT '服务费状态(0-关闭,1-开启)',
+                                               default_fee                     decimal(16,2)   NOT NULL DEFAULT '0.00' COMMENT '默认服务费',
+                                               into_status                     int             NOT NULL DEFAULT '0' COMMENT '入参状态(0-关闭,1-开启)',
                                                create_time                     datetime        NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
                                                update_time                     datetime        NOT NULL DEFAULT CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP COMMENT '更新时间',
                                                create_user                     bigint          NOT NULL DEFAULT '-1' COMMENT '创建人',