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

380 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 派单功能根本原因和修复方案
## 🔍 根本原因确认
通过SQL查询结果我找到了问题的根本原因
### 1. 订单309派单失败
**数据库实际状态:**
```
id = 309
order_no = TEST20260121160442
teacher_id = NULL ❌ 应该是10096
status = -1 ❌ 应该是1
pay_status = 1 ✅ 已支付
```
**结论:派单根本没有成功!数据库中的数据没有更新。**
### 2. 大量订单状态异常
从SQL查询结果可以看到
- **78个订单的 `teacher_id = NULL``status = 1`** ❌ 异常
- **50个订单的 `status = -1`** ❌ 未知状态
- 只有4个订单的 `status = 0` (待派单) ✅ 正常
**正常情况应该是:**
- `teacher_id = NULL``status = 0` (待派单)
- `teacher_id != NULL``status = 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` 注解:
```java
@TableLogic
private Integer deleted;
```
这意味着:
1. MyBatis-Plus在更新时会自动添加 `WHERE deleted = 0` 条件
2. 如果订单的 `deleted` 字段不是0更新会失败
3.`updateById()` 仍然返回 `true`这是MyBatis-Plus的一个已知问题
#### 原因B订单初始状态设置错误
从数据可以看到,很多订单在创建时就被设置为 `status=1``status=-1`,但 `teacher_id=NULL`
这说明在订单创建或支付成功时,状态设置逻辑有问题。
#### 原因C并发更新冲突
如果多个请求同时更新同一个订单,可能导致更新失败。
### 问题2待派单查询逻辑不完善
当前待派单查询条件:
```java
pendingQuery.eq("pay_status", 1) // 已支付
.isNull("teacher_id") // 未分配陪伴员
.eq("deleted", 0);
```
**问题:**
- 没有检查 `status` 字段
- 导致 `status=1``teacher_id=NULL` 的异常订单也被计入待派单
**正确的查询条件应该是:**
```java
pendingQuery.eq("pay_status", 1) // 已支付
.eq("status", 0) // 待派单状态
.isNull("teacher_id") // 未分配陪伴员
.eq("deleted", 0);
```
## 🔧 修复方案
### 方案1修复派单逻辑立即执行
#### 步骤1添加更详细的日志和错误处理
```java
@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修复待派单查询条件
```java
// 待派单订单数已支付且状态为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脚本修复状态不一致的订单
```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 定义清晰的订单状态枚举
```java
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 添加订单状态转换验证
```java
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 添加订单状态一致性检查
```java
/**
* 检查订单状态是否一致
*/
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_id``status` 正确更新
- ✅ 待派单数量正确减少
- ✅ 陪伴员能看到派单的订单
- ✅ 不再有状态不一致的订单
---
**创建时间:** 2026-01-26
**分析人员:** Kiro AI
**状态:** 待执行修复