# 订单变更记录完善说明

## 更新时间

2025-10-18

## 更新内容

根据**变更记录规范**，完善订单创建过程中的变更历史记录，确保所有关键操作都有完整的可追溯记录。

## 变更详情

### 新增的变更记录点

#### 1. 订单创建失败时的变更记录

**位置**: `internal/logic/jd_cookie/order_create.go` - `CreateOrder` 方法

**代码**:

```go
if retryErr != nil {
    // 京东订单创建失败，更新本地订单状态和失败原因
    _ = s.updateOrderFailure(ctx, internalOrderId, retryErr.Error())
    
    // 记录订单创建失败的变更历史 ✅ 新增
    _ = s.RecordOrderHistory(ctx, internalOrderId, consts.OrderChangeTypeCkFailed, "")
    
    return nil, retryErr
}
```

**说明**:

- 当京东订单创建失败时，记录 `OrderChangeTypeCkFailed` 类型的变更
- 记录时间点：在更新订单失败状态之后
- 确保失败原因可追溯

#### 2. 订单绑定京东订单的变更记录

**位置**: `internal/logic/jd_cookie/order_create.go` - `CreateOrder` 方法

**代码**:

```go
// 京东订单创建成功，更新本地订单的京东订单ID和支付链接
if jdOrderErr == nil {
    err = s.updateOrderJdOrderId(ctx, internalOrderId, jdOrderId, wxPayUrl)
    // ... 其他逻辑
    
    // 记录订单绑定京东订单的变更历史 ✅ 新增
    _ = s.RecordOrderHistory(ctx, internalOrderId, consts.OrderChangeTypeRebind, jdOrderId)
}
```

**说明**:

- 当订单成功绑定京东订单时，记录 `OrderChangeTypeRebind` 类型的变更
- 记录关联的京东订单ID
- 便于追踪订单与京东订单的绑定关系

#### 3. 失败订单重试失败的变更记录

**位置**: `internal/logic/jd_cookie/order_create.go` - `retryCreateJdOrderForFailedOrder` 方法

**代码**:

```go
if retryErr != nil {
    // 京东订单创建失败，更新本地订单失败原因
    _ = s.updateOrderFailure(ctx, existingOrder.OrderId, retryErr.Error())
    
    // 记录订单重试失败的变更历史 ✅ 新增
    _ = s.RecordOrderHistory(ctx, existingOrder.OrderId, consts.OrderChangeTypeCkFailed, "")
    
    return nil, retryErr
}
```

**说明**:

- 失败订单重试仍然失败时，记录变更历史
- 可以追踪订单的重试次数和失败时间点
- 便于分析订单失败模式

## 完整的变更记录流程

### 订单创建成功流程的变更记录

```mermaid
sequenceDiagram
    participant U as 用户
    participant S as 系统
    participant H as 变更历史表
    
    U->>S: 创建订单请求
    S->>S: 创建本地订单
    S->>H: 记录订单创建(OrderChangeTypeCreate)
    
    S->>S: 创建京东订单
    alt 创建成功
        S->>S: 更新订单状态
        S->>H: 记录订单绑定京东订单(OrderChangeTypeRebind)
        S->>U: 返回支付链接
    else 创建失败
        S->>S: 更新订单为失败状态
        S->>H: 记录订单创建失败(OrderChangeTypeCkFailed)
        S->>U: 返回错误信息
    end
```

### 失败订单重试流程的变更记录

```mermaid
sequenceDiagram
    participant U as 用户
    participant S as 系统
    participant H as 变更历史表
    
    U->>S: 再次请求订单
    S->>S: 检测到失败状态
    S->>S: 触发自动重试
    
    alt 重试成功
        S->>S: 创建京东订单成功
        S->>S: 更新订单为待支付状态
        S->>H: 记录订单重新绑定(OrderChangeTypeRebind)
        S->>U: 返回支付链接
    else 重试失败
        S->>S: 保持失败状态
        S->>H: 记录订单重试失败(OrderChangeTypeCkFailed)
        S->>U: 返回错误信息
    end
```

## 变更记录类型说明

### OrderChangeType 枚举值

位置: `internal/consts/jd_cookie.go`

| 类型       | 常量                        | 说明           | 使用场景        |
|----------|---------------------------|--------------|-------------|
| 创建       | `OrderChangeTypeCreate`   | 订单首次创建       | 本地订单创建时     |
| 支付       | `OrderChangeTypePay`      | 订单支付完成       | 用户支付成功时     |
| 过期       | `OrderChangeTypeExpire`   | 订单过期         | 订单超时未支付时    |
| 重新绑定     | `OrderChangeTypeRebind`   | 绑定/换绑京东订单    | 订单关联京东订单时   |
| Cookie失败 | `OrderChangeTypeCkFailed` | Cookie失效导致失败 | 京东订单创建失败时 ✅ |

## 完整的变更记录点清单

### 1. 创建新订单

- ✅ 本地订单创建时: `OrderChangeTypeCreate`
- ✅ 京东订单创建成功: `OrderChangeTypeRebind`
- ✅ 京东订单创建失败: `OrderChangeTypeCkFailed` (新增)

### 2. 失败订单重试

- ✅ 重试成功绑定京东订单: `OrderChangeTypeRebind`
- ✅ 重试失败: `OrderChangeTypeCkFailed` (新增)

### 3. 订单支付

- ✅ 支付成功: `OrderChangeTypePay` (已有)
- ✅ 订单过期: `OrderChangeTypeExpire` (已有)

## 数据示例

### 订单变更历史表记录示例

#### 场景1: 订单创建成功

```sql
-- 记录1: 订单创建
INSERT INTO jd_cookie_order_change_history 
VALUES (1, 'uuid-001', 'JD_123', 'create', NULL, NOW());

-- 记录2: 绑定京东订单
INSERT INTO jd_cookie_order_change_history 
VALUES (2, 'uuid-002', 'JD_123', 'rebind', 'JD_ORDER_456', NOW());
```

#### 场景2: 订单创建失败

```sql
-- 记录1: 订单创建
INSERT INTO jd_cookie_order_change_history 
VALUES (1, 'uuid-001', 'JD_123', 'create', NULL, NOW());

-- 记录2: 创建失败
INSERT INTO jd_cookie_order_change_history 
VALUES (2, 'uuid-002', 'JD_123', 'ck_failed', NULL, NOW());
```

#### 场景3: 失败订单重试成功

```sql
-- 记录1: 订单创建
INSERT INTO jd_cookie_order_change_history 
VALUES (1, 'uuid-001', 'JD_123', 'create', NULL, NOW());

-- 记录2: 首次失败
INSERT INTO jd_cookie_order_change_history 
VALUES (2, 'uuid-002', 'JD_123', 'ck_failed', NULL, NOW());

-- 记录3: 重试成功
INSERT INTO jd_cookie_order_change_history 
VALUES (3, 'uuid-003', 'JD_123', 'rebind', 'JD_ORDER_789', NOW());
```

## 查询示例

### 查询订单的完整变更历史

```sql
SELECT 
    id,
    history_uuid,
    order_id,
    change_type,
    jd_order_id,
    created_at
FROM jd_cookie_order_change_history
WHERE order_id = 'JD_123'
ORDER BY created_at ASC;
```

### 查询失败订单的重试记录

```sql
SELECT 
    order_id,
    COUNT(*) as retry_count,
    MAX(created_at) as last_retry_at
FROM jd_cookie_order_change_history
WHERE change_type = 'ck_failed'
GROUP BY order_id
HAVING COUNT(*) > 1
ORDER BY retry_count DESC;
```

### 查询订单从失败到成功的时间

```sql
SELECT 
    a.order_id,
    a.created_at as failed_at,
    b.created_at as success_at,
    TIMESTAMPDIFF(SECOND, a.created_at, b.created_at) as recovery_seconds
FROM jd_cookie_order_change_history a
JOIN jd_cookie_order_change_history b 
    ON a.order_id = b.order_id
WHERE a.change_type = 'ck_failed'
    AND b.change_type = 'rebind'
    AND b.created_at > a.created_at;
```

## 优势

### 1. 完整的可追溯性

- ✅ 每个订单的所有状态变更都有记录
- ✅ 可以追踪订单的完整生命周期
- ✅ 便于问题排查和数据分析

### 2. 便于运营分析

- ✅ 统计订单失败率
- ✅ 分析失败订单的恢复时间
- ✅ 识别问题模式

### 3. 支持审计需求

- ✅ 满足合规要求
- ✅ 完整的操作日志
- ✅ 支持追责和溯源

## 相关文件

- `internal/logic/jd_cookie/order_create.go`: 订单创建逻辑
- `internal/consts/jd_cookie.go`: 变更类型常量定义
- `sql/jd_cookie_tables.sql`: 变更历史表结构

## 测试建议

### 功能测试

1. **创建订单成功**: 验证记录了 `create` 和 `rebind` 两条历史
2. **创建订单失败**: 验证记录了 `create` 和 `ck_failed` 两条历史
3. **失败订单重试成功**: 验证记录了完整的重试链路
4. **失败订单持续失败**: 验证每次重试都有记录

### 数据验证

```go
// 验证订单变更历史记录
func TestOrderChangeHistory(t *testing.T) {
    // 1. 创建订单
    order := createOrder()
    
    // 2. 查询变更历史
    history := getOrderHistory(order.OrderId)
    
    // 3. 验证记录数量和类型
    assert.Equal(t, 2, len(history))
    assert.Equal(t, "create", history[0].ChangeType)
    assert.Equal(t, "rebind", history[1].ChangeType)
}
```

## 注意事项

1. **异步记录**: 变更历史记录失败不应影响主流程
2. **性能考虑**: 使用异步方式记录，避免阻塞
3. **数据清理**: 定期归档历史数据，避免表过大

## 下一步优化

1. **详细字段**: 添加 `remark` 字段记录详细失败原因
2. **操作人**: 添加 `operator` 字段记录操作人信息
3. **数据快照**: 记录变更前后的完整数据状态
