peixue-dev/Archive/[一次性]派单功能根本原因和修复方案.md

12 KiB
Raw Blame History

派单功能根本原因和修复方案

🔍 根本原因确认

通过SQL查询结果我找到了问题的根本原因

1. 订单309派单失败

数据库实际状态:

id = 309
order_no = TEST20260121160442
teacher_id = NULL  ❌ 应该是10096
status = -1        ❌ 应该是1
pay_status = 1     ✅ 已支付

结论:派单根本没有成功!数据库中的数据没有更新。

2. 大量订单状态异常

从SQL查询结果可以看到

  • 78个订单的 teacher_id = NULLstatus = 1 异常
  • 50个订单的 status = -1 未知状态
  • 只有4个订单的 status = 0 (待派单) 正常

正常情况应该是:

  • teacher_id = NULLstatus = 0 (待派单)
  • teacher_id != NULLstatus = 1 (已派单/待接单)

3. 订单状态统计

status = -1:  50个订单  (未知状态)
status =  0:   4个订单  (待派单) ✅
status =  1:  78个订单  (已派单/待接单) ⚠️ 但很多teacher_id为NULL
status =  2:   3个订单  (待服务)
status =  3:  87个订单  (服务中)
status =  4:  35个订单  (已完成)

🚨 问题分析

问题1派单更新失败的原因

虽然后端日志显示"派单成功",但数据库没有更新。可能的原因:

原因AMyBatis-Plus逻辑删除机制

Order实体类有 @TableLogic 注解:

@TableLogic
private Integer deleted;

这意味着:

  1. MyBatis-Plus在更新时会自动添加 WHERE deleted = 0 条件
  2. 如果订单的 deleted 字段不是0更新会失败
  3. updateById() 仍然返回 true这是MyBatis-Plus的一个已知问题

原因B订单初始状态设置错误

从数据可以看到,很多订单在创建时就被设置为 status=1status=-1,但 teacher_id=NULL

这说明在订单创建或支付成功时,状态设置逻辑有问题。

原因C并发更新冲突

如果多个请求同时更新同一个订单,可能导致更新失败。

问题2待派单查询逻辑不完善

当前待派单查询条件:

pendingQuery.eq("pay_status", 1)    // 已支付
           .isNull("teacher_id")     // 未分配陪伴员
           .eq("deleted", 0);

问题:

  • 没有检查 status 字段
  • 导致 status=1teacher_id=NULL 的异常订单也被计入待派单

正确的查询条件应该是:

pendingQuery.eq("pay_status", 1)    // 已支付
           .eq("status", 0)          // 待派单状态
           .isNull("teacher_id")     // 未分配陪伴员
           .eq("deleted", 0);

🔧 修复方案

方案1修复派单逻辑立即执行

步骤1添加更详细的日志和错误处理

@ApiOperation("派单")
@PostMapping("/assign")
public Result<Boolean> assignOrder(@RequestBody Map<String, Object> requestParams) {
    // ... 参数解析 ...
    
    try {
        com.peidu.entity.Order order = orderService.getById(orderId);
        if (order == null) {
            return Result.error("订单不存在");
        }
        
        // 🔥 检查订单状态
        if (order.getDeleted() != null && order.getDeleted() == 1) {
            return Result.error("订单已删除,无法派单");
        }
        
        if (order.getPayStatus() == null || order.getPayStatus() != 1) {
            return Result.error("订单未支付,无法派单");
        }
        
        System.out.println("派单前订单信息:");
        System.out.println("  ID: " + order.getId());
        System.out.println("  状态: " + order.getStatus());
        System.out.println("  陪伴员ID: " + order.getTeacherId());
        System.out.println("  删除标记: " + order.getDeleted());
        
        // 更新订单信息
        order.setTeacherId(teacherId);
        order.setStatus(1); // 1-已派单/待接单
        
        // 🔥 使用LambdaUpdateWrapper确保更新条件正确
        LambdaUpdateWrapper<com.peidu.entity.Order> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(com.peidu.entity.Order::getId, orderId)
                    .eq(com.peidu.entity.Order::getDeleted, 0);  // 确保未删除
        
        updateWrapper.set(com.peidu.entity.Order::getTeacherId, teacherId)
                    .set(com.peidu.entity.Order::getStatus, 1);
        
        boolean success = orderService.update(updateWrapper);
        
        System.out.println("数据库更新结果: " + success);
        
        if (!success) {
            System.out.println("❌ 数据库更新失败");
            return Result.error("派单失败:数据库更新失败");
        }
        
        // 🔥 验证更新结果
        com.peidu.entity.Order updatedOrder = orderService.getById(orderId);
        System.out.println("更新后订单验证:");
        System.out.println("  ID: " + updatedOrder.getId());
        System.out.println("  状态: " + updatedOrder.getStatus());
        System.out.println("  陪伴员ID: " + updatedOrder.getTeacherId());
        System.out.println("  删除标记: " + updatedOrder.getDeleted());
        
        // 🔥 验证更新是否真的成功
        if (updatedOrder.getTeacherId() == null || !updatedOrder.getTeacherId().equals(teacherId)) {
            System.out.println("❌ 验证失败陪伴员ID未更新");
            return Result.error("派单失败陪伴员ID未更新");
        }
        
        if (updatedOrder.getStatus() == null || updatedOrder.getStatus() != 1) {
            System.out.println("❌ 验证失败:订单状态未更新");
            return Result.error("派单失败:订单状态未更新");
        }
        
        System.out.println("✅ 订单状态更新成功");
        
        // ... 发送通知 ...
        
        return Result.success(true, "派单成功");
    } catch (Exception e) {
        e.printStackTrace();
        return Result.error("派单失败:" + e.getMessage());
    }
}

步骤2修复待派单查询条件

// 待派单订单数已支付且状态为0的订单
QueryWrapper<com.peidu.entity.Order> pendingQuery = new QueryWrapper<>();
pendingQuery.eq("pay_status", 1)      // 已支付
           .eq("status", 0)            // 🔥 添加:待派单状态
           .isNull("teacher_id")       // 未分配陪伴员
           .eq("deleted", 0);
long pendingOrders = orderService.count(pendingQuery);

方案2修复历史数据立即执行

创建SQL脚本修复状态不一致的订单

-- 1. 修复已派单但状态不是1的订单
UPDATE `order`
SET status = 1
WHERE teacher_id IS NOT NULL 
  AND status != 1
  AND pay_status = 1
  AND deleted = 0;

-- 2. 修复未派单但状态不是0的订单
UPDATE `order`
SET status = 0
WHERE teacher_id IS NULL 
  AND status NOT IN (0, 4, 5)  -- 排除已完成和已取消
  AND pay_status = 1
  AND deleted = 0;

-- 3. 检查修复结果
SELECT 
    status,
    COUNT(*) as count,
    CASE 
        WHEN status = 0 THEN '待派单'
        WHEN status = 1 THEN '已派单/待接单'
        WHEN status = 2 THEN '待服务'
        WHEN status = 3 THEN '服务中'
        WHEN status = 4 THEN '已完成'
        WHEN status = 5 THEN '已取消'
        ELSE '未知状态'
    END as status_name
FROM `order`
WHERE pay_status = 1 AND deleted = 0
GROUP BY status
ORDER BY status;

-- 4. 检查是否还有异常订单
SELECT 
    id,
    order_no,
    teacher_id,
    status,
    pay_status,
    CASE 
        WHEN teacher_id IS NULL AND status != 0 THEN '❌ 异常未派单但状态不是0'
        WHEN teacher_id IS NOT NULL AND status = 0 THEN '❌ 异常已派单但状态是0'
        ELSE '✅ 正常'
    END as check_result
FROM `order`
WHERE pay_status = 1 AND deleted = 0
  AND (
    (teacher_id IS NULL AND status NOT IN (0, 4, 5)) OR
    (teacher_id IS NOT NULL AND status = 0)
  )
ORDER BY create_time DESC;

方案3优化订单状态管理长期优化

3.1 定义清晰的订单状态枚举

public enum OrderStatus {
    PENDING_ASSIGN(0, "待派单"),      // 已支付,等待管理师派单
    PENDING_ACCEPT(1, "待接单"),      // 已派单,等待陪伴员接单
    PENDING_SERVICE(2, "待服务"),     // 已接单,等待服务开始
    IN_SERVICE(3, "服务中"),          // 服务进行中
    COMPLETED(4, "已完成"),           // 服务已完成
    CANCELLED(5, "已取消");           // 订单已取消
    
    private final int code;
    private final String desc;
    
    OrderStatus(int code, String desc) {
        this.code = code;
        this.desc = desc;
    }
    
    public int getCode() {
        return code;
    }
    
    public String getDesc() {
        return desc;
    }
}

3.2 添加订单状态转换验证

public class OrderStatusValidator {
    
    /**
     * 验证订单状态转换是否合法
     */
    public static boolean isValidTransition(Integer fromStatus, Integer toStatus) {
        if (fromStatus == null || toStatus == null) {
            return false;
        }
        
        // 定义合法的状态转换
        Map<Integer, List<Integer>> validTransitions = new HashMap<>();
        validTransitions.put(0, Arrays.asList(1, 5));     // 待派单 → 待接单/已取消
        validTransitions.put(1, Arrays.asList(2, 0, 5));  // 待接单 → 待服务/待派单(拒单)/已取消
        validTransitions.put(2, Arrays.asList(3, 5));     // 待服务 → 服务中/已取消
        validTransitions.put(3, Arrays.asList(4));        // 服务中 → 已完成
        validTransitions.put(4, Arrays.asList());         // 已完成 → 无
        validTransitions.put(5, Arrays.asList());         // 已取消 → 无
        
        List<Integer> allowedNextStatuses = validTransitions.get(fromStatus);
        return allowedNextStatuses != null && allowedNextStatuses.contains(toStatus);
    }
}

3.3 添加订单状态一致性检查

/**
 * 检查订单状态是否一致
 */
public boolean checkOrderConsistency(Order order) {
    // 检查1teacher_id和status的一致性
    if (order.getTeacherId() == null && order.getStatus() != 0 && order.getStatus() != 4 && order.getStatus() != 5) {
        log.warn("订单{}状态不一致teacher_id为空但status不是0/4/5", order.getId());
        return false;
    }
    
    if (order.getTeacherId() != null && order.getStatus() == 0) {
        log.warn("订单{}状态不一致teacher_id不为空但status是0", order.getId());
        return false;
    }
    
    // 检查2pay_status和status的一致性
    if (order.getPayStatus() != 1 && order.getStatus() != 0 && order.getStatus() != 5) {
        log.warn("订单{}状态不一致未支付但status不是0或5", order.getId());
        return false;
    }
    
    return true;
}

📝 修复步骤

立即执行(修复当前问题)

  1. 修复历史数据

    • 运行SQL脚本修复状态不一致的订单
    • 验证修复结果
  2. 修改派单逻辑

    • 使用 LambdaUpdateWrapper 替代 updateById()
    • 添加更新结果验证
    • 添加详细的错误日志
  3. 修改待派单查询条件

    • 添加 status=0 条件
    • 确保只查询真正待派单的订单
  4. 测试验证

    • 重新测试派单功能
    • 验证待派单数量是否正确
    • 验证陪伴员能否看到派单

长期优化(提升系统稳定性)

  1. 添加订单状态枚举
  2. 添加状态转换验证
  3. 添加状态一致性检查
  4. 添加单元测试

🎯 预期结果

修复后:

  • 派单成功后,订单的 teacher_idstatus 正确更新
  • 待派单数量正确减少
  • 陪伴员能看到派单的订单
  • 不再有状态不一致的订单

创建时间: 2026-01-26

分析人员: Kiro AI

状态: 待执行修复