🚚 物流配送系统

# 🚚 物流配送系统

在跨境电商的世界里,物流配送是连接商家与消费者的最后一公里。当用户完成支付后,商品需要跨越国界,经历复杂的物流网络,最终安全送达用户手中。这个过程涉及多个物流服务商、海关清关、运输追踪等复杂环节。

# 📋 系统概述

# 核心功能

  • 多渠道物流路由:智能选择最优物流方案
  • 实时运输追踪:全程可视化物流状态
  • 海关清关处理:自动化报关流程
  • 配送时效预估:基于大数据的时效预测
  • 异常处理机制:物流异常自动处理
  • 成本优化算法:动态物流成本计算
  • 多语言通知:本地化物流通知服务

# 🏗️ 系统架构设计

graph TB
    A[订单系统] --> B[物流路由引擎]
    B --> C[物流服务商API]
    B --> D[海关清关系统]
    B --> E[运输追踪系统]
    
    C --> F[DHL API]
    C --> G[FedEx API]
    C --> H[UPS API]
    C --> I[本地物流API]
    
    D --> J[报关数据处理]
    D --> K[税费计算]
    D --> L[清关状态追踪]
    
    E --> M[GPS追踪]
    E --> N[RFID追踪]
    E --> O[条码扫描]
    
    P[Redis缓存] --> B
    Q[MongoDB] --> E
    R[MySQL] --> D
    
    S[消息队列] --> T[通知服务]
    T --> U[邮件通知]
    T --> V[短信通知]
    T --> W[推送通知]

# 💻 核心代码实现

# 1. 物流订单实体模型

@Entity
@Table(name = "logistics_orders")
public class LogisticsOrder {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(name = "order_id", nullable = false)
    private String orderId;
    
    @Column(name = "tracking_number", unique = true)
    private String trackingNumber;
    
    @Enumerated(EnumType.STRING)
    @Column(name = "status")
    private LogisticsStatus status;
    
    @Embedded
    private ShippingAddress senderAddress;
    
    @Embedded
    @AttributeOverrides({
        @AttributeOverride(name = "country", column = @Column(name = "receiver_country")),
        @AttributeOverride(name = "province", column = @Column(name = "receiver_province")),
        @AttributeOverride(name = "city", column = @Column(name = "receiver_city")),
        @AttributeOverride(name = "address", column = @Column(name = "receiver_address")),
        @AttributeOverride(name = "zipCode", column = @Column(name = "receiver_zip_code"))
    })
    private ShippingAddress receiverAddress;
    
    @Column(name = "logistics_provider")
    private String logisticsProvider;
    
    @Column(name = "service_type")
    private String serviceType;
    
    @Column(name = "estimated_delivery_date")
    private LocalDateTime estimatedDeliveryDate;
    
    @Column(name = "actual_delivery_date")
    private LocalDateTime actualDeliveryDate;
    
    @Column(name = "shipping_cost", precision = 10, scale = 2)
    private BigDecimal shippingCost;
    
    @Column(name = "insurance_amount", precision = 10, scale = 2)
    private BigDecimal insuranceAmount;
    
    @OneToMany(mappedBy = "logisticsOrder", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<LogisticsEvent> events = new ArrayList<>();
    
    @OneToMany(mappedBy = "logisticsOrder", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<CustomsDeclaration> customsDeclarations = new ArrayList<>();
    
    @CreationTimestamp
    @Column(name = "created_at")
    private LocalDateTime createdAt;
    
    @UpdateTimestamp
    @Column(name = "updated_at")
    private LocalDateTime updatedAt;
    
    // 构造函数、getter、setter方法
    public LogisticsOrder() {}
    
    public LogisticsOrder(String orderId, ShippingAddress senderAddress, 
                         ShippingAddress receiverAddress) {
        this.orderId = orderId;
        this.senderAddress = senderAddress;
        this.receiverAddress = receiverAddress;
        this.status = LogisticsStatus.PENDING;
    }
    
    // 添加物流事件
    public void addEvent(LogisticsEventType eventType, String description, String location) {
        LogisticsEvent event = new LogisticsEvent(this, eventType, description, location);
        this.events.add(event);
    }
    
    // 更新物流状态
    public void updateStatus(LogisticsStatus newStatus) {
        this.status = newStatus;
        addEvent(LogisticsEventType.STATUS_UPDATE, 
                "Status updated to " + newStatus, null);
    }
    
    // getter和setter方法省略...
}

@Embeddable
public class ShippingAddress {
    @Column(name = "country")
    private String country;
    
    @Column(name = "province")
    private String province;
    
    @Column(name = "city")
    private String city;
    
    @Column(name = "address")
    private String address;
    
    @Column(name = "zip_code")
    private String zipCode;
    
    @Column(name = "contact_name")
    private String contactName;
    
    @Column(name = "contact_phone")
    private String contactPhone;
    
    // 构造函数、getter、setter方法省略...
}

public enum LogisticsStatus {
    PENDING,           // 待处理
    PICKED_UP,         // 已揽收
    IN_TRANSIT,        // 运输中
    CUSTOMS_CLEARANCE, // 海关清关
    OUT_FOR_DELIVERY,  // 派送中
    DELIVERED,         // 已送达
    EXCEPTION,         // 异常
    RETURNED           // 退回
}

# 2. 物流路由引擎

@Service
@Slf4j
public class LogisticsRoutingEngine {
    
    @Autowired
    private List<LogisticsProvider> logisticsProviders;
    
    @Autowired
    private LogisticsRuleEngine ruleEngine;
    
    @Autowired
    private CostCalculationService costCalculationService;
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    /**
     * 选择最优物流方案
     */
    public LogisticsRoute selectOptimalRoute(LogisticsRequest request) {
        log.info("开始为订单 {} 选择最优物流方案", request.getOrderId());
        
        // 1. 获取可用的物流方案
        List<LogisticsOption> availableOptions = getAvailableOptions(request);
        
        // 2. 应用业务规则过滤
        List<LogisticsOption> filteredOptions = ruleEngine.applyRules(availableOptions, request);
        
        // 3. 计算综合评分
        List<LogisticsScoredOption> scoredOptions = calculateScores(filteredOptions, request);
        
        // 4. 选择最优方案
        LogisticsScoredOption bestOption = selectBestOption(scoredOptions);
        
        // 5. 构建路由结果
        LogisticsRoute route = buildRoute(bestOption, request);
        
        // 6. 缓存路由结果
        cacheRoute(request.getOrderId(), route);
        
        log.info("为订单 {} 选择物流方案: {}", request.getOrderId(), 
                bestOption.getProvider().getName());
        
        return route;
    }
    
    /**
     * 获取可用的物流选项
     */
    private List<LogisticsOption> getAvailableOptions(LogisticsRequest request) {
        List<LogisticsOption> options = new ArrayList<>();
        
        for (LogisticsProvider provider : logisticsProviders) {
            try {
                if (provider.isServiceAvailable(request.getSenderAddress(), 
                                              request.getReceiverAddress())) {
                    List<LogisticsOption> providerOptions = 
                        provider.getAvailableOptions(request);
                    options.addAll(providerOptions);
                }
            } catch (Exception e) {
                log.warn("获取物流服务商 {} 的方案时出错: {}", 
                        provider.getName(), e.getMessage());
            }
        }
        
        return options;
    }
    
    /**
     * 计算物流方案综合评分
     */
    private List<LogisticsScoredOption> calculateScores(List<LogisticsOption> options, 
                                                       LogisticsRequest request) {
        return options.stream()
                .map(option -> {
                    double score = calculateOptionScore(option, request);
                    return new LogisticsScoredOption(option, score);
                })
                .sorted((a, b) -> Double.compare(b.getScore(), a.getScore()))
                .collect(Collectors.toList());
    }
    
    /**
     * 计算单个物流方案评分
     */
    private double calculateOptionScore(LogisticsOption option, LogisticsRequest request) {
        // 成本权重 (30%)
        double costScore = calculateCostScore(option.getCost(), request.getBudget()) * 0.3;
        
        // 时效权重 (25%)
        double timeScore = calculateTimeScore(option.getEstimatedDays(), 
                                            request.getUrgency()) * 0.25;
        
        // 可靠性权重 (20%)
        double reliabilityScore = option.getProvider().getReliabilityScore() * 0.2;
        
        // 服务质量权重 (15%)
        double serviceScore = option.getProvider().getServiceScore() * 0.15;
        
        // 覆盖范围权重 (10%)
        double coverageScore = calculateCoverageScore(option, request) * 0.1;
        
        return costScore + timeScore + reliabilityScore + serviceScore + coverageScore;
    }
    
    /**
     * 计算成本评分
     */
    private double calculateCostScore(BigDecimal cost, BigDecimal budget) {
        if (budget == null || budget.compareTo(BigDecimal.ZERO) <= 0) {
            return 0.5; // 默认评分
        }
        
        double ratio = cost.divide(budget, 4, RoundingMode.HALF_UP).doubleValue();
        
        if (ratio <= 0.7) {
            return 1.0; // 成本很低
        } else if (ratio <= 0.9) {
            return 0.8; // 成本适中
        } else if (ratio <= 1.0) {
            return 0.6; // 成本接近预算
        } else {
            return Math.max(0.1, 1.0 / ratio); // 超出预算
        }
    }
    
    /**
     * 计算时效评分
     */
    private double calculateTimeScore(int estimatedDays, UrgencyLevel urgency) {
        switch (urgency) {
            case URGENT:
                return estimatedDays <= 3 ? 1.0 : Math.max(0.1, 3.0 / estimatedDays);
            case NORMAL:
                return estimatedDays <= 7 ? 1.0 : Math.max(0.3, 7.0 / estimatedDays);
            case RELAXED:
                return estimatedDays <= 15 ? 1.0 : Math.max(0.5, 15.0 / estimatedDays);
            default:
                return 0.5;
        }
    }
    
    /**
     * 计算覆盖范围评分
     */
    private double calculateCoverageScore(LogisticsOption option, LogisticsRequest request) {
        // 检查是否支持目标地区
        boolean supportsDestination = option.getProvider()
                .supportsDestination(request.getReceiverAddress().getCountry());
        
        if (!supportsDestination) {
            return 0.0;
        }
        
        // 检查是否有本地配送网络
        boolean hasLocalNetwork = option.getProvider()
                .hasLocalNetwork(request.getReceiverAddress().getCountry());
        
        return hasLocalNetwork ? 1.0 : 0.7;
    }
    
    /**
     * 选择最佳方案
     */
    private LogisticsScoredOption selectBestOption(List<LogisticsScoredOption> scoredOptions) {
        if (scoredOptions.isEmpty()) {
            throw new LogisticsException("没有可用的物流方案");
        }
        
        return scoredOptions.get(0); // 已按评分排序
    }
    
    /**
     * 构建路由结果
     */
    private LogisticsRoute buildRoute(LogisticsScoredOption bestOption, LogisticsRequest request) {
        LogisticsRoute route = new LogisticsRoute();
        route.setOrderId(request.getOrderId());
        route.setProvider(bestOption.getOption().getProvider());
        route.setServiceType(bestOption.getOption().getServiceType());
        route.setEstimatedCost(bestOption.getOption().getCost());
        route.setEstimatedDays(bestOption.getOption().getEstimatedDays());
        route.setScore(bestOption.getScore());
        route.setCreatedAt(LocalDateTime.now());
        
        return route;
    }
    
    /**
     * 缓存路由结果
     */
    private void cacheRoute(String orderId, LogisticsRoute route) {
        String cacheKey = "logistics:route:" + orderId;
        redisTemplate.opsForValue().set(cacheKey, route, Duration.ofHours(24));
    }
}

# 3. 运输追踪服务

@Service
@Slf4j
public class TrackingService {
    
    @Autowired
    private LogisticsOrderRepository logisticsOrderRepository;
    
    @Autowired
    private LogisticsEventRepository logisticsEventRepository;
    
    @Autowired
    private List<LogisticsProvider> logisticsProviders;
    
    @Autowired
    private NotificationService notificationService;
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    /**
     * 获取物流追踪信息
     */
    public TrackingInfo getTrackingInfo(String trackingNumber) {
        log.info("获取追踪号 {} 的物流信息", trackingNumber);
        
        // 1. 从缓存获取
        TrackingInfo cachedInfo = getCachedTrackingInfo(trackingNumber);
        if (cachedInfo != null && !isTrackingInfoExpired(cachedInfo)) {
            return cachedInfo;
        }
        
        // 2. 从数据库获取物流订单
        LogisticsOrder logisticsOrder = logisticsOrderRepository
                .findByTrackingNumber(trackingNumber)
                .orElseThrow(() -> new TrackingNotFoundException(
                        "追踪号不存在: " + trackingNumber));
        
        // 3. 从物流服务商获取最新信息
        TrackingInfo latestInfo = fetchLatestTrackingInfo(logisticsOrder);
        
        // 4. 更新数据库
        updateLogisticsOrder(logisticsOrder, latestInfo);
        
        // 5. 缓存结果
        cacheTrackingInfo(trackingNumber, latestInfo);
        
        return latestInfo;
    }
    
    /**
     * 从物流服务商获取最新追踪信息
     */
    private TrackingInfo fetchLatestTrackingInfo(LogisticsOrder logisticsOrder) {
        LogisticsProvider provider = findProvider(logisticsOrder.getLogisticsProvider());
        
        if (provider == null) {
            throw new LogisticsException("未找到物流服务商: " + 
                    logisticsOrder.getLogisticsProvider());
        }
        
        try {
            return provider.getTrackingInfo(logisticsOrder.getTrackingNumber());
        } catch (Exception e) {
            log.error("获取追踪信息失败: {}", e.getMessage(), e);
            // 返回数据库中的历史信息
            return buildTrackingInfoFromDatabase(logisticsOrder);
        }
    }
    
    /**
     * 更新物流订单信息
     */
    private void updateLogisticsOrder(LogisticsOrder logisticsOrder, TrackingInfo trackingInfo) {
        // 更新状态
        LogisticsStatus newStatus = mapToLogisticsStatus(trackingInfo.getStatus());
        if (newStatus != logisticsOrder.getStatus()) {
            logisticsOrder.updateStatus(newStatus);
            
            // 发送状态变更通知
            notificationService.sendStatusUpdateNotification(
                    logisticsOrder.getOrderId(), newStatus);
        }
        
        // 更新预计送达时间
        if (trackingInfo.getEstimatedDeliveryDate() != null) {
            logisticsOrder.setEstimatedDeliveryDate(trackingInfo.getEstimatedDeliveryDate());
        }
        
        // 添加新的追踪事件
        for (TrackingEvent event : trackingInfo.getEvents()) {
            if (!isEventExists(logisticsOrder, event)) {
                logisticsOrder.addEvent(
                        mapToLogisticsEventType(event.getType()),
                        event.getDescription(),
                        event.getLocation()
                );
            }
        }
        
        logisticsOrderRepository.save(logisticsOrder);
    }
    
    /**
     * 批量更新追踪信息
     */
    @Scheduled(fixedDelay = 300000) // 每5分钟执行一次
    public void batchUpdateTrackingInfo() {
        log.info("开始批量更新追踪信息");
        
        List<LogisticsOrder> activeOrders = logisticsOrderRepository
                .findByStatusIn(Arrays.asList(
                        LogisticsStatus.PICKED_UP,
                        LogisticsStatus.IN_TRANSIT,
                        LogisticsStatus.CUSTOMS_CLEARANCE,
                        LogisticsStatus.OUT_FOR_DELIVERY
                ));
        
        int updateCount = 0;
        for (LogisticsOrder order : activeOrders) {
            try {
                TrackingInfo latestInfo = fetchLatestTrackingInfo(order);
                updateLogisticsOrder(order, latestInfo);
                cacheTrackingInfo(order.getTrackingNumber(), latestInfo);
                updateCount++;
                
                // 避免频繁调用API
                Thread.sleep(100);
            } catch (Exception e) {
                log.warn("更新追踪信息失败,订单: {}, 错误: {}", 
                        order.getOrderId(), e.getMessage());
            }
        }
        
        log.info("批量更新追踪信息完成,更新数量: {}", updateCount);
    }
    
    /**
     * 预测送达时间
     */
    public DeliveryPrediction predictDeliveryTime(String trackingNumber) {
        TrackingInfo trackingInfo = getTrackingInfo(trackingNumber);
        
        // 基于历史数据和当前状态预测
        DeliveryPredictionModel model = new DeliveryPredictionModel();
        
        return model.predict(
                trackingInfo.getCurrentLocation(),
                trackingInfo.getDestination(),
                trackingInfo.getStatus(),
                trackingInfo.getProvider(),
                trackingInfo.getServiceType()
        );
    }
    
    /**
     * 缓存追踪信息
     */
    private void cacheTrackingInfo(String trackingNumber, TrackingInfo trackingInfo) {
        String cacheKey = "tracking:" + trackingNumber;
        redisTemplate.opsForValue().set(cacheKey, trackingInfo, Duration.ofMinutes(30));
    }
    
    /**
     * 从缓存获取追踪信息
     */
    private TrackingInfo getCachedTrackingInfo(String trackingNumber) {
        String cacheKey = "tracking:" + trackingNumber;
        return (TrackingInfo) redisTemplate.opsForValue().get(cacheKey);
    }
    
    // 其他辅助方法省略...
}

### 4. 海关清关服务

```java
@Service
@Slf4j
public class CustomsClearanceService {
    
    @Autowired
    private CustomsDeclarationRepository customsDeclarationRepository;
    
    @Autowired
    private TaxCalculationService taxCalculationService;
    
    @Autowired
    private DocumentGenerationService documentGenerationService;
    
    @Autowired
    private CustomsApiClient customsApiClient;
    
    /**
     * 创建报关单
     */
    public CustomsDeclaration createDeclaration(LogisticsOrder logisticsOrder, 
                                               List<OrderItem> items) {
        log.info("为物流订单 {} 创建报关单", logisticsOrder.getId());
        
        CustomsDeclaration declaration = new CustomsDeclaration();
        declaration.setLogisticsOrder(logisticsOrder);
        declaration.setDeclarationNumber(generateDeclarationNumber());
        declaration.setStatus(CustomsStatus.PENDING);
        
        // 设置发件人信息
        declaration.setSenderInfo(buildSenderInfo(logisticsOrder.getSenderAddress()));
        
        // 设置收件人信息
        declaration.setReceiverInfo(buildReceiverInfo(logisticsOrder.getReceiverAddress()));
        
        // 设置商品信息
        List<CustomsItem> customsItems = buildCustomsItems(items);
        declaration.setItems(customsItems);
        
        // 计算税费
        TaxCalculationResult taxResult = taxCalculationService.calculateTax(
                customsItems, logisticsOrder.getReceiverAddress().getCountry());
        declaration.setTaxAmount(taxResult.getTotalTax());
        declaration.setDutyAmount(taxResult.getTotalDuty());
        
        // 生成报关文件
        List<CustomsDocument> documents = documentGenerationService
                .generateCustomsDocuments(declaration);
        declaration.setDocuments(documents);
        
        return customsDeclarationRepository.save(declaration);
    }
    
    /**
     * 提交报关申请
     */
    public void submitDeclaration(Long declarationId) {
        CustomsDeclaration declaration = customsDeclarationRepository
                .findById(declarationId)
                .orElseThrow(() -> new CustomsException("报关单不存在"));
        
        try {
            // 验证报关单数据
            validateDeclaration(declaration);
            
            // 提交到海关系统
            CustomsSubmissionResult result = customsApiClient.submitDeclaration(declaration);
            
            // 更新状态
            declaration.setStatus(CustomsStatus.SUBMITTED);
            declaration.setSubmissionReference(result.getReferenceNumber());
            declaration.setSubmittedAt(LocalDateTime.now());
            
            customsDeclarationRepository.save(declaration);
            
            log.info("报关单 {} 提交成功,参考号: {}", 
                    declaration.getDeclarationNumber(), result.getReferenceNumber());
            
        } catch (Exception e) {
            declaration.setStatus(CustomsStatus.FAILED);
            declaration.setErrorMessage(e.getMessage());
            customsDeclarationRepository.save(declaration);
            
            log.error("报关单 {} 提交失败: {}", 
                    declaration.getDeclarationNumber(), e.getMessage(), e);
            throw new CustomsException("报关提交失败: " + e.getMessage());
        }
    }
    
    /**
     * 查询清关状态
     */
    @Scheduled(fixedDelay = 600000) // 每10分钟检查一次
    public void checkClearanceStatus() {
        List<CustomsDeclaration> pendingDeclarations = customsDeclarationRepository
                .findByStatusIn(Arrays.asList(
                        CustomsStatus.SUBMITTED,
                        CustomsStatus.UNDER_REVIEW
                ));
        
        for (CustomsDeclaration declaration : pendingDeclarations) {
            try {
                CustomsStatusResult statusResult = customsApiClient
                        .checkStatus(declaration.getSubmissionReference());
                
                updateDeclarationStatus(declaration, statusResult);
                
            } catch (Exception e) {
                log.warn("检查报关单 {} 状态失败: {}", 
                        declaration.getDeclarationNumber(), e.getMessage());
            }
        }
    }
    
    /**
     * 更新报关单状态
     */
    private void updateDeclarationStatus(CustomsDeclaration declaration, 
                                       CustomsStatusResult statusResult) {
        CustomsStatus oldStatus = declaration.getStatus();
        CustomsStatus newStatus = mapToCustomsStatus(statusResult.getStatus());
        
        if (oldStatus != newStatus) {
            declaration.setStatus(newStatus);
            
            if (newStatus == CustomsStatus.CLEARED) {
                declaration.setClearedAt(LocalDateTime.now());
                // 通知物流系统继续配送
                notifyLogisticsSystem(declaration);
            } else if (newStatus == CustomsStatus.REJECTED) {
                declaration.setRejectionReason(statusResult.getRejectionReason());
                // 处理拒绝情况
                handleRejection(declaration);
            }
            
            customsDeclarationRepository.save(declaration);
            
            log.info("报关单 {} 状态更新: {} -> {}", 
                    declaration.getDeclarationNumber(), oldStatus, newStatus);
        }
    }
    
    // 其他辅助方法省略...
}

# 5. 异常处理服务

@Service
@Slf4j
public class LogisticsExceptionHandler {
    
    @Autowired
    private LogisticsOrderRepository logisticsOrderRepository;
    
    @Autowired
    private ExceptionRecordRepository exceptionRecordRepository;
    
    @Autowired
    private NotificationService notificationService;
    
    @Autowired
    private CompensationService compensationService;
    
    /**
     * 处理物流异常
     */
    public void handleException(String trackingNumber, LogisticsExceptionType exceptionType, 
                              String description, String location) {
        log.warn("处理物流异常 - 追踪号: {}, 类型: {}, 描述: {}", 
                trackingNumber, exceptionType, description);
        
        LogisticsOrder logisticsOrder = logisticsOrderRepository
                .findByTrackingNumber(trackingNumber)
                .orElseThrow(() -> new LogisticsException("物流订单不存在"));
        
        // 创建异常记录
        ExceptionRecord exceptionRecord = createExceptionRecord(
                logisticsOrder, exceptionType, description, location);
        
        // 更新订单状态
        logisticsOrder.updateStatus(LogisticsStatus.EXCEPTION);
        logisticsOrderRepository.save(logisticsOrder);
        
        // 根据异常类型执行相应处理
        switch (exceptionType) {
            case PACKAGE_LOST:
                handlePackageLost(logisticsOrder, exceptionRecord);
                break;
            case PACKAGE_DAMAGED:
                handlePackageDamaged(logisticsOrder, exceptionRecord);
                break;
            case DELIVERY_FAILED:
                handleDeliveryFailed(logisticsOrder, exceptionRecord);
                break;
            case CUSTOMS_ISSUE:
                handleCustomsIssue(logisticsOrder, exceptionRecord);
                break;
            case ADDRESS_INCORRECT:
                handleAddressIncorrect(logisticsOrder, exceptionRecord);
                break;
            case WEATHER_DELAY:
                handleWeatherDelay(logisticsOrder, exceptionRecord);
                break;
            default:
                handleGenericException(logisticsOrder, exceptionRecord);
        }
    }
    
    /**
     * 处理包裹丢失
     */
    private void handlePackageLost(LogisticsOrder logisticsOrder, ExceptionRecord exceptionRecord) {
        // 1. 立即通知客户
        notificationService.sendPackageLostNotification(logisticsOrder.getOrderId());
        
        // 2. 启动调查流程
        initiateInvestigation(logisticsOrder, exceptionRecord);
        
        // 3. 准备补偿方案
        CompensationPlan compensationPlan = compensationService
                .createCompensationPlan(logisticsOrder, CompensationType.PACKAGE_LOST);
        exceptionRecord.setCompensationPlan(compensationPlan);
        
        // 4. 设置自动处理时间
        scheduleAutoResolution(exceptionRecord, Duration.ofDays(7));
        
        exceptionRecordRepository.save(exceptionRecord);
    }
    
    /**
     * 处理包裹损坏
     */
    private void handlePackageDamaged(LogisticsOrder logisticsOrder, ExceptionRecord exceptionRecord) {
        // 1. 通知客户并要求提供损坏照片
        notificationService.sendPackageDamagedNotification(logisticsOrder.getOrderId());
        
        // 2. 创建损坏评估任务
        DamageAssessmentTask assessmentTask = new DamageAssessmentTask(
                logisticsOrder.getId(), exceptionRecord.getId());
        
        // 3. 根据保险情况处理
        if (logisticsOrder.getInsuranceAmount().compareTo(BigDecimal.ZERO) > 0) {
            initiateInsuranceClaim(logisticsOrder, exceptionRecord);
        } else {
            // 提供基础补偿
            CompensationPlan compensationPlan = compensationService
                    .createCompensationPlan(logisticsOrder, CompensationType.PACKAGE_DAMAGED);
            exceptionRecord.setCompensationPlan(compensationPlan);
        }
        
        exceptionRecordRepository.save(exceptionRecord);
    }
    
    /**
     * 处理配送失败
     */
    private void handleDeliveryFailed(LogisticsOrder logisticsOrder, ExceptionRecord exceptionRecord) {
        // 1. 分析失败原因
        DeliveryFailureReason reason = analyzeFailureReason(exceptionRecord.getDescription());
        exceptionRecord.setFailureReason(reason);
        
        // 2. 根据失败原因处理
        switch (reason) {
            case RECIPIENT_NOT_AVAILABLE:
                scheduleRedelivery(logisticsOrder, exceptionRecord);
                break;
            case ADDRESS_NOT_FOUND:
                requestAddressVerification(logisticsOrder, exceptionRecord);
                break;
            case REFUSED_BY_RECIPIENT:
                initiateReturnProcess(logisticsOrder, exceptionRecord);
                break;
            default:
                scheduleRedelivery(logisticsOrder, exceptionRecord);
        }
        
        exceptionRecordRepository.save(exceptionRecord);
    }
    
    /**
     * 自动重新配送
     */
    private void scheduleRedelivery(LogisticsOrder logisticsOrder, ExceptionRecord exceptionRecord) {
        // 检查重试次数
        int retryCount = getRetryCount(logisticsOrder.getId());
        if (retryCount >= 3) {
            // 超过重试次数,转为人工处理
            exceptionRecord.setRequiresManualIntervention(true);
            notificationService.sendManualInterventionRequired(logisticsOrder.getOrderId());
            return;
        }
        
        // 计算下次配送时间
        LocalDateTime nextDeliveryTime = calculateNextDeliveryTime(retryCount);
        
        // 创建重新配送任务
        RedeliveryTask redeliveryTask = new RedeliveryTask(
                logisticsOrder.getId(), nextDeliveryTime, retryCount + 1);
        
        // 通知客户重新配送安排
        notificationService.sendRedeliveryNotification(
                logisticsOrder.getOrderId(), nextDeliveryTime);
        
        log.info("安排重新配送 - 订单: {}, 时间: {}, 重试次数: {}", 
                logisticsOrder.getOrderId(), nextDeliveryTime, retryCount + 1);
    }
    
    /**
     * 异常自动恢复检查
     */
    @Scheduled(fixedDelay = 3600000) // 每小时检查一次
    public void checkAutoRecovery() {
        List<ExceptionRecord> pendingExceptions = exceptionRecordRepository
                .findByStatusAndAutoResolutionTimeBefore(
                        ExceptionStatus.PENDING, LocalDateTime.now());
        
        for (ExceptionRecord exception : pendingExceptions) {
            try {
                processAutoResolution(exception);
            } catch (Exception e) {
                log.error("自动处理异常失败: {}", exception.getId(), e);
            }
        }
    }
    
    // 其他辅助方法省略...
}

# 🔧 技术亮点

# 1. 智能路由算法

  • 多维度评分:综合考虑成本、时效、可靠性等因素
  • 动态权重调整:根据业务需求调整评分权重
  • 实时可用性检查:确保选择的物流方案当前可用

# 2. 实时追踪系统

  • 多源数据整合:整合多个物流服务商的追踪数据
  • 智能缓存策略:减少API调用,提高响应速度
  • 异常自动检测:基于追踪数据自动识别异常情况

# 3. 海关清关自动化

  • 文档自动生成:根据商品信息自动生成报关文件
  • 税费智能计算:支持多国税收政策的自动计算
  • 状态实时同步:与海关系统实时同步清关状态

# ⚡ 性能优化

# 1. 缓存策略

@Configuration
@EnableCaching
public class LogisticsCacheConfig {
    
    @Bean
    public CacheManager cacheManager() {
        RedisCacheManager.Builder builder = RedisCacheManager
                .RedisCacheManagerBuilder
                .fromConnectionFactory(redisConnectionFactory())
                .cacheDefaults(cacheConfiguration());
        
        return builder.build();
    }
    
    private RedisCacheConfiguration cacheConfiguration() {
        return RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofMinutes(30))
                .serializeKeysWith(RedisSerializationContext.SerializationPair
                        .fromSerializer(new StringRedisSerializer()))
                .serializeValuesWith(RedisSerializationContext.SerializationPair
                        .fromSerializer(new GenericJackson2JsonRedisSerializer()));
    }
    
    // 物流路由缓存配置
    @Bean
    public RedisCacheConfiguration routeCacheConfiguration() {
        return RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofHours(24))
                .prefixCacheNameWith("logistics:route:");
    }
    
    // 追踪信息缓存配置
    @Bean
    public RedisCacheConfiguration trackingCacheConfiguration() {
        return RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofMinutes(30))
                .prefixCacheNameWith("logistics:tracking:");
    }
}

# 2. 异步处理

@Configuration
@EnableAsync
public class LogisticsAsyncConfig {
    
    @Bean(name = "logisticsTaskExecutor")
    public TaskExecutor logisticsTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(50);
        executor.setQueueCapacity(200);
        executor.setThreadNamePrefix("logistics-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
    
    @Bean(name = "trackingTaskExecutor")
    public TaskExecutor trackingTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(20);
        executor.setQueueCapacity(100);
        executor.setThreadNamePrefix("tracking-");
        executor.initialize();
        return executor;
    }
}

# 📊 监控与分析

# 1. 物流监控指标

@Component
public class LogisticsMetrics {
    
    private final MeterRegistry meterRegistry;
    private final Counter deliverySuccessCounter;
    private final Counter deliveryFailureCounter;
    private final Timer deliveryTimeTimer;
    private final Gauge activeShipmentsGauge;
    
    public LogisticsMetrics(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
        
        this.deliverySuccessCounter = Counter.builder("logistics.delivery.success")
                .description("成功配送数量")
                .register(meterRegistry);
        
        this.deliveryFailureCounter = Counter.builder("logistics.delivery.failure")
                .description("配送失败数量")
                .register(meterRegistry);
        
        this.deliveryTimeTimer = Timer.builder("logistics.delivery.time")
                .description("配送时长")
                .register(meterRegistry);
        
        this.activeShipmentsGauge = Gauge.builder("logistics.shipments.active")
                .description("活跃运输数量")
                .register(meterRegistry, this, LogisticsMetrics::getActiveShipments);
    }
    
    public void recordDeliverySuccess(String provider, String serviceType) {
        deliverySuccessCounter.increment(
                Tags.of(
                        "provider", provider,
                        "service_type", serviceType
                )
        );
    }
    
    public void recordDeliveryFailure(String provider, String reason) {
        deliveryFailureCounter.increment(
                Tags.of(
                        "provider", provider,
                        "failure_reason", reason
                )
        );
    }
    
    public void recordDeliveryTime(Duration deliveryTime, String provider) {
        deliveryTimeTimer.record(deliveryTime, Tags.of("provider", provider));
    }
    
    private double getActiveShipments() {
        // 实现获取活跃运输数量的逻辑
        return 0.0;
    }
}

# 2. 物流分析服务

@Service
public class LogisticsAnalyticsService {
    
    @Autowired
    private LogisticsOrderRepository logisticsOrderRepository;
    
    /**
     * 物流服务商性能分析
     */
    public ProviderPerformanceReport analyzeProviderPerformance(
            String provider, LocalDate startDate, LocalDate endDate) {
        
        List<LogisticsOrder> orders = logisticsOrderRepository
                .findByLogisticsProviderAndCreatedAtBetween(
                        provider, startDate.atStartOfDay(), endDate.atTime(23, 59, 59));
        
        ProviderPerformanceReport report = new ProviderPerformanceReport();
        report.setProvider(provider);
        report.setPeriod(startDate + " to " + endDate);
        
        // 计算成功率
        long totalOrders = orders.size();
        long successfulDeliveries = orders.stream()
                .mapToLong(order -> order.getStatus() == LogisticsStatus.DELIVERED ? 1 : 0)
                .sum();
        report.setSuccessRate((double) successfulDeliveries / totalOrders * 100);
        
        // 计算平均配送时间
        double avgDeliveryDays = orders.stream()
                .filter(order -> order.getActualDeliveryDate() != null)
                .mapToLong(order -> ChronoUnit.DAYS.between(
                        order.getCreatedAt(), order.getActualDeliveryDate()))
                .average()
                .orElse(0.0);
        report.setAverageDeliveryDays(avgDeliveryDays);
        
        // 计算异常率
        long exceptionsCount = orders.stream()
                .mapToLong(order -> order.getStatus() == LogisticsStatus.EXCEPTION ? 1 : 0)
                .sum();
        report.setExceptionRate((double) exceptionsCount / totalOrders * 100);
        
        return report;
    }
    
    /**
     * 配送时效分析
     */
    public DeliveryTimeAnalysis analyzeDeliveryTime(String country, 
                                                   LocalDate startDate, LocalDate endDate) {
        // 实现配送时效分析逻辑
        return new DeliveryTimeAnalysis();
    }
}

# 📝 关键要点

# 技术特色

  1. 智能路由选择:多维度评分算法选择最优物流方案
  2. 实时状态追踪:整合多个物流服务商的追踪数据
  3. 自动化清关:支持多国海关政策的自动化处理
  4. 异常智能处理:基于规则引擎的异常自动处理
  5. 性能监控分析:全方位的物流性能监控和分析

# 业务价值

  1. 提升用户体验:实时追踪和主动异常处理
  2. 降低运营成本:智能路由和自动化处理
  3. 提高配送效率:优化物流路径和时效预测
  4. 增强风险控制:异常预警和自动补偿机制

# 未来发展

  1. AI智能预测:基于机器学习的配送时效预测
  2. 区块链溯源:利用区块链技术实现物流全程溯源
  3. IoT设备集成:集成物联网设备实现实时位置追踪
  4. 绿色物流:碳足迹计算和绿色配送路径优化