sen
1 天以前 7ed2a032d0724e68aec8af940f2ce0023a9f0eb7
api/src/main/java/com/ruoyi/api/third/controller/TmsAiDispatchController.java
@@ -90,7 +90,9 @@
    public AjaxResult getVehicleData(
            @RequestParam(value = "licensePlate", required = false) String licensePlate,
            @RequestParam(value = "licenseHk", required = false) String licenseHk,
            @RequestParam(value = "licenseMo", required = false) String licenseMo
            @RequestParam(value = "licenseMo", required = false) String licenseMo,
            @RequestParam(value = "serviceProviderId", required = false) Integer serviceProviderId
    ){
        logger.info("getVehicleData:{},{},{}",licensePlate,licenseHk,licenseMo);
@@ -98,6 +100,7 @@
                .like(StringUtils.isNotEmpty(licensePlate),TmsVehicle::getLicensePlate, licensePlate)
                .like(StringUtils.isNotEmpty(licenseHk),TmsVehicle::getLicenseHk, licenseHk)
                .like(StringUtils.isNotEmpty(licenseMo),TmsVehicle::getLicenseMo, licenseMo)
                .like(serviceProviderId != null,TmsVehicle::getServiceProviderId, serviceProviderId)
                .last("limit 1")
        );
        if (tmsCustomerInfo == null){
@@ -118,12 +121,15 @@
     */
    @GetMapping("/getDriverData")
    public AjaxResult getDriverData(
            @RequestParam(value = "driverName", required = true) String driverName)
            @RequestParam(value = "driverName", required = true) String driverName,
            @RequestParam(value = "vehicleProviderId", required = false) Integer vehicleProviderId
            )
    {
        logger.info("getVehicleData:{}",driverName);
        TmsDriver tmsDriver = tmsDriverMapper.selectOne(new LambdaQueryWrapper<TmsDriver>()
                .like(TmsDriver::getDriverName, driverName)
                        .eq(vehicleProviderId !=null,TmsDriver::getVehicleProviderId, vehicleProviderId)
                .last("limit 1")
        );
@@ -241,7 +247,7 @@
    /**
     * 创建调度单接口 (AI优化版, 需要appId/secret认证)
     *
     * @param vo AI调度单请求对象
     * @param order AI调度单请求对象
     * @param request HTTP请求
     * @return 创建结果
     */
@@ -254,10 +260,154 @@
        }
        try {
            // 验证必填字段
            if (order.getMainDriverId() == null || order.getLicensePlate() == null) {
                return error("派车信息不能为空");
            // ========== 1. 客户验证 ==========
            if (StringUtils.isEmpty(order.getCustomerName())) {
                return error("客户名称不能为空");
            }
            TmsCustomerInfo customer = tmsCustomerInfoMapper.selectOne(new LambdaQueryWrapper<TmsCustomerInfo>()
                    .like(TmsCustomerInfo::getCustomerFullName, order.getCustomerName())
                    .last("limit 1")
            );
            if (customer == null) {
                return error("客户不存在,请确认客户名称或先在系统中维护客户信息");
            }
            order.setCustomerId(customer.getId());
            // ========== 2. 车型验证 ==========
            if (StringUtils.isEmpty(order.getRequiredVehicleTypes())) {
                return error("车型不能为空");
            }
            List<SysDictData> vehicleTypes = sysDictDataMapper.selectDictDataByType("vehicle_type");
            boolean vehicleTypeValid = vehicleTypes.stream()
                    .anyMatch(dict -> dict.getDictValue().equals(order.getRequiredVehicleTypes()));
            if (!vehicleTypeValid) {
                return error("车型不存在,请确认车型或先在字典中维护车型数据");
            }
            // ========== 3. 装货点验证(如果提供了装货点名称)==========
            if (StringUtils.isNotEmpty(order.getShipperName())) {
                TmsConsignor shipper = tmsConsignorMapper.selectOne(new LambdaQueryWrapper<TmsConsignor>()
                        .like(TmsConsignor::getConsignorName, order.getShipperName())
                        .eq(TmsConsignor::getCustomerName, order.getCustomerName())
                        .last("limit 1")
                );
                if (shipper == null) {
                    return error("装货点不存在,请确认装货点名称或先在系统中维护装货点信息");
                }
                order.setShipperId(shipper.getId());
            }
            // ========== 4. 卸货点验证(如果提供了卸货点名称)==========
            if (StringUtils.isNotEmpty(order.getReceiverName())) {
                TmsConsignor receiver = tmsConsignorMapper.selectOne(new LambdaQueryWrapper<TmsConsignor>()
                        .like(TmsConsignor::getConsignorName, order.getReceiverName())
                        .eq(TmsConsignor::getCustomerName, order.getCustomerName())
                        .last("limit 1")
                );
                if (receiver == null) {
                    return error("卸货点不存在,请确认卸货点名称或先在系统中维护卸货点信息");
                }
                order.setReceiverId(receiver.getId());
            }
            // ========== 5. 路线验证(AI必须传quoteDetailId)==========
            if (order.getQuoteDetailId() == null) {
                return error("报价明细ID不能为空,请先调用validateRoute接口获取可用路线并选择一条");
            }
            // 根据quoteDetailId查询路线信息
            TransportRouteVi route = transportRouteViMapper.selectById(order.getQuoteDetailId());
            if (route == null) {
                return error("报价明细不存在,请确认报价明细ID是否正确");
            }
            // 验证路线是否匹配客户
            if (!route.getCustomerFullName().equals(order.getCustomerName())) {
                return error("报价明细与客户不匹配,请确认选择的路线是否属于该客户");
            }
            // 验证路线是否匹配车型
            Integer vehicleTypeInt = null;
            try {
                vehicleTypeInt = Integer.parseInt(order.getRequiredVehicleTypes());
            } catch (NumberFormatException e) {
                return error("车型格式错误");
            }
            if (!route.getVehicleType().equals(vehicleTypeInt)) {
                return error("报价明细与车型不匹配,请确认选择的路线车型是否正确");
            }
            // 使用路线信息填充订单
            order.setTransportLine(route.getTransportRoute());
            order.setStartRegionCode(route.getStartRegionCode());
            order.setEndRegionCode(route.getEndRegionCode());
            order.setProjectId(route.getProjectId());
            order.setProjectName(route.getProjectName());
            order.setContractId(route.getContractId());
            order.setContractName(route.getContractName());
            // ========== 6. 订单类型判断 & 必填校验 ==========
            Integer orderType = order.getOrderType();
            if (orderType == null) {
                return error("订单类型不能为空");
            }
            // 基础订单(0):装货地+卸货地必须齐全
            if (orderType == 0) {
                if (StringUtils.isEmpty(order.getShipperRegionLabel()) || StringUtils.isEmpty(order.getReceiverRegionLabel())) {
                    return error("基础订单的装货地和卸货地不能为空");
                }
            }
            // 预配订单(1):卸货地可为空,但装货地必须有
            else if (orderType == 1) {
                if (StringUtils.isEmpty(order.getShipperRegionLabel())) {
                    return error("预配订单的装货地不能为空");
                }
            }
            // ========== 7. 派车信息验证 ==========
            // 7.1 司机验证(必填)
            if (order.getMainDriverId() == null) {
                return error("司机信息不能为空");
            }
            TmsDriver driver = tmsDriverMapper.selectById(order.getMainDriverId());
            if (driver == null) {
                return error("司机不存在,请确认司机信息");
            }
            order.setMainDriverName(driver.getDriverName());
            // 7.2 车辆验证(必填)
            if (StringUtils.isEmpty(order.getLicensePlate())) {
                return error("车牌号不能为空");
            }
            TmsVehicle vehicle = tmsVehicleMapper.selectOne(new LambdaQueryWrapper<TmsVehicle>()
                    .eq(TmsVehicle::getLicensePlate, order.getLicensePlate())
                    .last("limit 1")
            );
            if (vehicle == null) {
                return error("车辆不存在,请确认车牌号");
            }
            order.setVehicleId(vehicle.getId());
            order.setActualVehicleType(vehicle.getVehicleType());
            // 7.3 运营模式验证
            Integer operationMode = order.getOperationMode();
            if (operationMode == null) {
                return error("运营模式不能为空(1=自营车队,0=外协)");
            }
            // 7.4 外协模式:必须提供车辆服务商
            if (operationMode == 0) {
                if (order.getVehicleProviderId() == null) {
                    return error("外协模式下,车辆服务商不能为空");
                }
                TmsServiceProvider provider = tmsServiceProviderMapper.selectById(order.getVehicleProviderId());
                if (provider == null) {
                    return error("车辆服务商不存在,请确认服务商信息");
                }
                order.setVehicleProviderName(provider.getServiceName());
            }
            // 设置初始状态为待分配 (0)
            order.setStatus(0);
@@ -268,10 +418,16 @@
                // 返回新创建的订单信息
                Map<String, Object> data = new HashMap<>();
                data.put("orderNo", order.getDispatchNo());
                data.put("customerId", order.getCustomerId());
                data.put("customerName", order.getCustomerName());
                data.put("originCity", order.getShipperRegionLabel());
                data.put("destCity", order.getReceiverRegionLabel());
                data.put("cargoName", order.getCargoName());
                data.put("transportLine", order.getTransportLine());
                data.put("vehicleType", order.getRequiredVehicleTypes());
                data.put("mainDriverName", order.getMainDriverName());
                data.put("licensePlate", order.getLicensePlate());
                data.put("operationMode", order.getOperationMode());
                data.put("vehicleProviderName", order.getVehicleProviderName());
                data.put("status", order.getStatus());
                return success(data);
            } else {
@@ -324,62 +480,5 @@
    /**
     * 批量验证订单数据接口 (需要appId/secret认证)
     *
     * @param orders 调度单列表
     * @param request HTTP请求
     * @return 验证结果
     */
    @PostMapping("/batchValidateOrders")
    public AjaxResult batchValidateOrders(@RequestBody List<AiDispatchOrderVO> orders, HttpServletRequest request)
    {
        // appId/secret 认证
        if (!apiAuthUtil.validateAppAuth(request)) {
            return apiAuthUtil.getUnauthorizedResult();
        }
        List<Map<String, Object>> validationResults = new ArrayList<>();
        for (int i = 0; i < orders.size(); i++) {
            AiDispatchOrderVO order = orders.get(i);
            Map<String, Object> result = new HashMap<>();
            result.put("index", i);
            result.put("customerName", order.getCustomerName());
            List<String> errors = new ArrayList<>();
            // 验证必填字段
            if (StringUtils.isEmpty(order.getCustomerName())) {
                errors.add("客户名称不能为空");
            }
            if (StringUtils.isEmpty(order.getOriginCity())) {
                errors.add("起始城市不能为空");
            }
            if (StringUtils.isEmpty(order.getDestCity())) {
                errors.add("目的地城市不能为空");
            }
            if (StringUtils.isEmpty(order.getLoadingDate())) {
                errors.add("装车日期不能为空");
            }
            result.put("isValid", errors.isEmpty());
            result.put("errors", errors);
            validationResults.add(result);
        }
        Map<String, Object> response = new HashMap<>();
        response.put("totalCount", orders.size());
        response.put("validCount", validationResults.stream()
                .filter(r -> (Boolean) r.get("isValid"))
                .count());
        response.put("invalidCount", validationResults.stream()
                .filter(r -> !(Boolean) r.get("isValid"))
                .count());
        response.put("details", validationResults);
        return success(response);
    }
}