# 【后端内部·无前端改动】团期已报名计数改为写入持久化，修复超卖 P0 B 阶段（PR #3839 / 工单 #3836）

> 端：无前端改动 | 服务：hl-order-service-v3 + hl-product-service-v2 | PR #3839 已合并 dev-v3 + 双实例部署实测 | 2026-06-15

## ⚠️ 关键说明

超卖 P0（#3820）B 阶段：将 `order_group_batch.enrolled_rooms / enrolled_people` 从死列改为写时维护的活跃计数器。product-v2 查团期库存时改从持久列读取，**不再实时扫 order_main**。

- **A 阶段（#3829）**：order-v3 新增 `GET /v3/internal/order/batch-stats` 实时聚合端点，product-v2 改接 v3（修复 v2 查 v3 订单得 0 的根因）。
- **B 阶段（#3839，本 PR）**：进一步将计数下沉到写端，消除循环扫表，enrolled 列成库存权威。

## 1. 变更内容

| 变更点 | 说明 |
|--------|------|
| `order_group_batch.enrolled_rooms` | 团期活跃订单数（1 单 = 1 房）；创单 +1，取消 AFTER_COMMIT -1 |
| `order_group_batch.enrolled_people` | 活跃订单人数 Σ(adult+child+youngChild+baby)；创单 +N，取消 -N |
| `OrderStatsService.batchStats()` | 改读 enrolled 持久列，不再扫 order_main |
| `GroupBatchEnrolledReconcileJob` | 每 5 分钟 + 每天 3:30 对账兜底，发现漂移 WARN 并修正 |
| `V20260615_002` Flyway 迁移 | order_main 加 `(product_batch_id, order_status)` 复合索引，加速对账/回填 |

## 2. 口径定义（四处同源）

- **活跃集** = `order_status != CANCELLED`（含 PENDING_PAY；COMPLETED 仍占名额）
- **enrolled_rooms** = 活跃订单条数（1 订单 = 1 房，不用 room_count 字段）
- **enrolled_people** = Σ(adult+child+youngChild+baby)，null 按 0

## 3. 内部端点（Feign LB 直连，不过网关）

`POST /v3/internal/order/group-batch/backfill-enrolled` — 全量回填对账，幂等，返回修正漂移数。已在部署后执行，返回 0（无漂移）。

## 实测（测试服 2026-06-15）

```
GET /v3/internal/order/batch-stats?batchIds=999999,888888
→ {"999999":{"batchId":999999,"orderCount":0,"peopleCount":0},"888888":{...}}  ✅

POST /v3/internal/order/group-batch/backfill-enrolled
→ {"code":200,"data":0}（无 GROUP 型活跃订单，enrolled 全零，无漂移）  ✅

Flyway V20260615_002 idx_pbid_status 已落地：SHOW INDEX 确认 (product_batch_id,order_status) ✅
order-v3 双实例 8086/8186 均 UP，product-v2 UP  ✅
```
