# 代理钱包订单创建功能部署指南

## 部署前检查清单

### 代码检查

- [x] 编译通过：`go build ./...`
- [x] OpenAPI 文档更新：`go run cmd/gendocs/main.go`
- [ ] 测试环境验证通过
- [ ] Code Review 通过

### 数据库准备

- [ ] 测试环境迁移脚本执行成功
- [ ] 生产环境数据库备份完成
- [ ] 回滚脚本准备完毕

---

## 数据库迁移

### 迁移脚本清单

**脚本位置**：`migrations/`

| 序号 | 文件名 | 说明 | 执行时间 |
|------|--------|------|----------|
| 000067 | `add_operator_fields_to_orders.up.sql` | 订单表新增字段和索引 | < 5 秒 |
| 000068 | `add_transaction_subtype_to_wallet_transaction.up.sql` | 钱包流水表新增字段 | < 1 秒 |

**回滚脚本**：
| 序号 | 文件名 | 说明 |
|------|--------|------|
| 000067 | `add_operator_fields_to_orders.down.sql` | 删除订单表字段和索引 |
| 000068 | `add_transaction_subtype_to_wallet_transaction.down.sql` | 删除钱包流水表字段 |

---

### 迁移执行步骤

#### 步骤 1：备份数据库

```bash
# 生产环境数据库备份
pg_dump -h <host> -U <user> -d junhong_cmp -F c -b -v -f "backup_$(date +%Y%m%d_%H%M%S).dump"
```

**验证备份**：
```bash
pg_restore --list backup_*.dump | head -20
```

---

#### 步骤 2：执行迁移（测试环境）

**使用 migrate 工具**：
```bash
# 切换到项目目录
cd /path/to/junhong_cmp_fiber

# 执行迁移
migrate -path migrations -database "postgresql://<user>:<password>@<host>:<port>/junhong_cmp?sslmode=disable" up

# 验证迁移版本
migrate -path migrations -database "postgresql://<user>:<password>@<host>:<port>/junhong_cmp?sslmode=disable" version
```

**手动执行（可选）**：
```bash
# 连接数据库
psql -h <host> -U <user> -d junhong_cmp

# 执行迁移脚本
\i migrations/000067_add_operator_fields_to_orders.up.sql
\i migrations/000068_add_transaction_subtype_to_wallet_transaction.up.sql
```

---

#### 步骤 3：验证迁移结果

**检查字段**：
```sql
-- 验证订单表字段
\d tb_order

-- 预期输出包含：
-- operator_id           | integer                  |           |          |
-- operator_type         | character varying(20)    |           |          |
-- actual_paid_amount    | bigint                   |           |          |
-- purchase_role         | character varying(50)    |           |          |
```

**检查索引**：
```sql
-- 验证索引
SELECT indexname, indexdef
FROM pg_indexes
WHERE tablename = 'tb_order'
  AND indexname IN ('idx_orders_operator_id', 'idx_orders_purchase_role');

-- 预期输出：
-- idx_orders_operator_id | CREATE INDEX idx_orders_operator_id ON public.tb_order USING btree (operator_id)
-- idx_orders_purchase_role | CREATE INDEX idx_orders_purchase_role ON public.tb_order USING btree (purchase_role)
```

**检查钱包流水表**：
```sql
-- 验证钱包流水表字段
\d tb_agent_wallet_transaction

-- 预期输出包含：
-- transaction_subtype   | character varying(50)    |           |          |
-- related_shop_id       | integer                  |           |          |
```

---

#### 步骤 4：数据回填（可选）

**回填历史订单**：
```bash
psql -h <host> -U <user> -d junhong_cmp -f migrations/backfill_order_purchase_role.sql
```

**验证回填结果**：
```sql
SELECT purchase_role, operator_type, COUNT(*) as count
FROM tb_order
WHERE purchase_role IS NOT NULL
GROUP BY purchase_role, operator_type;

-- 预期输出示例：
-- purchased_by_platform | platform | 1234
```

---

#### 步骤 5：执行迁移（生产环境）

**时间窗口**：选择低峰期（凌晨 2:00 - 4:00）

**执行命令**（与测试环境相同）：
```bash
migrate -path migrations -database "postgresql://<prod_host>:<prod_port>/<db>?sslmode=require" up
```

**监控指标**：
- 迁移执行时间
- 索引创建时间（CONCURRENTLY，不锁表）
- 数据库连接数
- 慢查询日志

---

### 回滚步骤

**场景**：迁移失败或发现严重 Bug

#### 步骤 1：停止应用

```bash
# 停止应用服务
systemctl stop junhong-cmp-api
```

#### 步骤 2：执行回滚

```bash
# 回滚到上一版本
migrate -path migrations -database "postgresql://<host>:<port>/<db>?sslmode=disable" down 2
```

**或手动执行回滚脚本**：
```bash
psql -h <host> -U <user> -d junhong_cmp <<EOF
\i migrations/000068_add_transaction_subtype_to_wallet_transaction.down.sql
\i migrations/000067_add_operator_fields_to_orders.down.sql
EOF
```

#### 步骤 3：验证回滚

```sql
-- 验证字段已删除
\d tb_order
\d tb_agent_wallet_transaction

-- 验证索引已删除
SELECT indexname FROM pg_indexes WHERE tablename = 'tb_order';
```

#### 步骤 4：恢复应用（旧版本代码）

```bash
# 回滚代码到上一版本
git checkout <previous_commit>

# 重新编译
go build -o api cmd/api/main.go

# 启动应用
systemctl start junhong-cmp-api
```

---

## 代码部署

### 灰度发布计划

**阶段 1：灰度服务器（10% 流量）**

**时间**：低峰期（周一至周五 02:00 - 04:00）

**步骤**：
1. 部署代码到灰度服务器
2. 切换 10% 流量到灰度服务器
3. 观察 2 小时，监控关键指标
4. 手工测试代理自购、代理代购场景

**验证项**：
- [ ] 应用启动成功
- [ ] 健康检查通过：`curl http://localhost:8080/health`
- [ ] 订单创建成功率 > 95%
- [ ] 钱包扣款成功率 > 99%
- [ ] 无严重错误日志

---

**阶段 2：全量发布（100% 流量）**

**时间**：灰度验证通过后 24 小时

**步骤**：
1. 部署代码到所有服务器
2. 逐步切换流量（20% → 50% → 100%）
3. 持续监控 24 小时

**验证项**：
- [ ] 所有服务器应用启动成功
- [ ] 订单创建成功率 > 95%
- [ ] 钱包扣款成功率 > 99%
- [ ] 错误日志无异常峰值
- [ ] 用户反馈无异常

---

### 发布命令

**构建**：
```bash
# 构建二进制文件
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o api cmd/api/main.go

# 验证版本
./api --version
```

**部署**：
```bash
# 停止服务
systemctl stop junhong-cmp-api

# 备份旧版本
cp /opt/junhong-cmp/api /opt/junhong-cmp/api.backup

# 替换新版本
cp api /opt/junhong-cmp/api

# 启动服务
systemctl start junhong-cmp-api

# 检查状态
systemctl status junhong-cmp-api
```

**验证**：
```bash
# 健康检查
curl http://localhost:8080/health

# 查看日志
journalctl -u junhong-cmp-api -f
```

---

## 监控指标

### 关键业务指标

**订单创建**：
- 订单创建成功率（总体）
- 订单创建成功率（按 payment_method 分组）
- 订单创建耗时（P50、P95、P99）
- 订单创建 QPS

**钱包扣款**：
- 钱包扣款成功率
- 钱包扣款失败原因分布（余额不足、并发冲突、其他）
- 钱包余额不足次数

**订单查询**：
- 订单列表查询耗时（P95）
- OR 查询性能（慢查询日志）

---

### 错误日志监控

**关键错误**：
```bash
# 余额不足
grep "余额不足" /var/log/junhong-cmp/app.log | wc -l

# 并发冲突
grep "并发冲突" /var/log/junhong-cmp/app.log | wc -l

# 套餐激活失败
grep "套餐激活失败" /var/log/junhong-cmp/app.log | wc -l

# 成本价查询失败
grep "店铺没有该套餐的分配配置" /var/log/junhong-cmp/app.log | wc -l
```

---

### 数据库性能监控

**慢查询**：
```sql
-- 查看慢查询
SELECT query, calls, total_time, mean_time
FROM pg_stat_statements
WHERE query LIKE '%tb_order%'
  AND mean_time > 100
ORDER BY mean_time DESC
LIMIT 10;
```

**索引使用率**：
```sql
-- 检查新索引是否被使用
SELECT schemaname, tablename, indexname, idx_scan, idx_tup_read, idx_tup_fetch
FROM pg_stat_user_indexes
WHERE indexname IN ('idx_orders_operator_id', 'idx_orders_purchase_role');
```

**OR 查询性能**：
```sql
-- EXPLAIN 分析
EXPLAIN ANALYZE
SELECT * FROM tb_order
WHERE (buyer_type = 'agent' AND buyer_id = 10) OR operator_id = 10
LIMIT 20;
```

---

### 告警规则

**业务告警**：
| 指标 | 阈值 | 级别 |
|------|------|------|
| 订单创建成功率 | < 95% | P1 |
| 钱包扣款成功率 | < 99% | P1 |
| 订单创建耗时 P99 | > 1000ms | P2 |
| 并发冲突次数 | > 100/分钟 | P2 |
| 余额不足次数 | > 500/小时 | P3 |

**系统告警**：
| 指标 | 阈值 | 级别 |
|------|------|------|
| 应用进程退出 | - | P0 |
| 数据库连接数 | > 80% | P1 |
| 慢查询（订单相关） | > 1000ms | P2 |

---

## 验证测试

### 功能验证清单

**代理自购**：
- [ ] 创建订单成功
- [ ] 钱包余额正确扣减
- [ ] 订单状态为已支付
- [ ] 套餐已激活
- [ ] 钱包流水记录正确（transaction_subtype = "self_purchase"）
- [ ] 订单响应字段完整（operator_id、purchase_role 等）

**代理代购**：
- [ ] 创建订单成功
- [ ] 钱包余额按操作者成本价扣减
- [ ] 订单金额显示买家成本价
- [ ] actual_paid_amount 为操作者成本价
- [ ] 套餐已激活
- [ ] 钱包流水记录正确（transaction_subtype = "purchase_for_subordinate"、related_shop_id、remark 包含店铺名称）
- [ ] 未产生佣金记录

**平台代购**：
- [ ] 创建订单成功
- [ ] 钱包余额未扣减
- [ ] 订单状态为已支付
- [ ] 套餐已激活
- [ ] 产生佣金记录
- [ ] purchase_role = "purchased_by_platform"

**订单查询**：
- [ ] 代理可查询作为买家或操作者的订单
- [ ] purchase_role 筛选生效
- [ ] 订单列表响应包含新字段

**边界场景**：
- [ ] 余额不足时返回明确错误
- [ ] 并发扣款时乐观锁生效
- [ ] 幂等性检查防止重复创建
- [ ] H5 端 wallet 订单不受影响（仍为待支付）

---

### 性能验证

**压力测试**（可选）：
```bash
# 订单创建并发测试
ab -n 1000 -c 50 -H "Authorization: Bearer <token>" \
   -p order_request.json \
   -T "application/json" \
   http://localhost:8080/api/admin/orders

# 订单列表查询性能测试
ab -n 5000 -c 100 -H "Authorization: Bearer <token>" \
   http://localhost:8080/api/admin/orders?page=1&page_size=20
```

**预期结果**：
- 订单创建 QPS > 50
- 订单创建 P95 < 200ms
- 订单列表查询 P95 < 100ms

---

## 回滚预案

### 回滚触发条件

满足以下任一条件时立即回滚：
- 订单创建成功率 < 90%（持续 5 分钟）
- 钱包扣款成功率 < 95%（持续 5 分钟）
- 发现严重 Bug（如：重复扣款、金额计算错误、数据丢失）
- 用户投诉量激增

---

### 快速回滚步骤

**步骤 1：立即回滚代码**（< 5 分钟）

```bash
# 停止服务
systemctl stop junhong-cmp-api

# 恢复旧版本
cp /opt/junhong-cmp/api.backup /opt/junhong-cmp/api

# 启动服务
systemctl start junhong-cmp-api
```

**步骤 2：回滚数据库**（可选，< 10 分钟）

仅当数据异常时执行：
```bash
# 执行回滚脚本
migrate -path migrations -database "..." down 2
```

**步骤 3：验证回滚成功**

- [ ] 应用启动成功
- [ ] 健康检查通过
- [ ] 订单创建成功率恢复
- [ ] 用户反馈恢复正常

---

## 上线后观察

### 观察期（7 天）

**每日检查**：
- [ ] 订单创建成功率
- [ ] 钱包扣款成功率
- [ ] 错误日志无异常
- [ ] 用户反馈无异常
- [ ] 数据库慢查询无新增

**周报总结**：
- 订单创建总量、成功率
- 钱包扣款总量、成功率
- 代理自购 vs 代理代购占比
- 错误类型分布
- 性能指标趋势

---

## 联系人

**技术负责人**：[姓名]
**运维负责人**：[姓名]
**产品负责人**：[姓名]

**紧急联系方式**：
- 技术值班电话：[电话]
- 运维值班电话：[电话]

---

## 附录

### 相关文档

- [功能总结](./功能总结.md)
- [提案文档](../../openspec/changes/fix-agent-wallet-order-creation/proposal.md)
- [设计文档](../../openspec/changes/fix-agent-wallet-order-creation/design.md)
- [任务清单](../../openspec/changes/fix-agent-wallet-order-creation/tasks.md)

### 迁移脚本内容

详见 `migrations/` 目录：
- `000067_add_operator_fields_to_orders.up.sql`
- `000067_add_operator_fields_to_orders.down.sql`
- `000068_add_transaction_subtype_to_wallet_transaction.up.sql`
- `000068_add_transaction_subtype_to_wallet_transaction.down.sql`
- `backfill_order_purchase_role.sql`
