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

380 lines
12 KiB
Markdown
Raw Permalink Normal View History

2026-02-28 17:26:03 +08:00
# 派单功能根本原因和修复方案
## 🔍 根本原因确认
通过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
**状态:** 待执行修复