380 lines
12 KiB
Markdown
380 lines
12 KiB
Markdown
|
|
# 派单功能根本原因和修复方案
|
|||
|
|
|
|||
|
|
## 🔍 根本原因确认
|
|||
|
|
|
|||
|
|
通过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:派单更新失败的原因
|
|||
|
|
|
|||
|
|
虽然后端日志显示"派单成功",但数据库没有更新。可能的原因:
|
|||
|
|
|
|||
|
|
#### 原因A:MyBatis-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) {
|
|||
|
|
// 检查1:teacher_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;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 检查2:pay_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
|
|||
|
|
|
|||
|
|
**状态:** 待执行修复
|