# SPEC 设计方向决策

> 创建：2026-04-15
> 关联 Issue：#9

---

## 核心发现

Phase 0-2 实现与原始设计文档（`docs/06_SEAT_MAP_INTEGRATIONATION.md`）存在架构偏差。

---

## ShopXO SPEC 机制

### 机制说明
- 商品有**多个 SPEC 维度**（场馆/分区/时段/座位），每个维度有多个 VALUE
- `goods_spec_base` 表：每行 = 一个完整 SKU（spec_base_id = SKU ID），含 inventory + price
- `goods_spec_value` 表：(spec_base_id, value) 对
- ShopXO 购买流程：`BuyGoods` → `GoodsSpecDetail` → 用 spec 值数组查对应 spec_base_id → 原子扣 inventory

### 关键代码路径
```
BuyService.php:94  GoodsSpecificationsHandle($v)
    → 提取 spec 字段（{type, value} 对）
    → GoodsService.php:2763 GoodsSpecDetail()
    → goods_spec_value 表查 spec_base_id
    → goods_spec_base 表读 inventory + price
```

---

## 原始设计（文档）

`spec_base_id_map` = `{seat_id: {spec_base_id, row, col, price}}`

- key = 具体座位（"1_1" = 第1排第1座）
- spec_base_id = ShopXO 里该座位的完整 SPEC 组合的 SKU ID
- stock = 1（每个座位独立库存）
- 购买：每个座位单独 spec_base_id → ShopXO 原生防超卖

---

## 当前代码实现

`submit()` 发送：
```javascript
{
    spec_base_id: this.sessionSpecId,  // ← zone 级别，不是每个座位
    stock: this.selectedSeats.length,   // ← 座位总数
    extension_data: { seats: [所有选中座位] }
}
```

**问题**：
- spec_base_id 是 zone 级别的，ShopXO 只能检查该 zone 的库存
- seats[] 里包含所有 Zone 的座位，与 spec_base_id 不匹配
- 绕过了 ShopXO spec 验证

---

## 两种方向

### 方案 A：每个座位一个 SPEC（原始设计）
- spec_base_id_map：每个座位一个 key，spec_base_id = 该座位在 ShopXO 的 SKU ID
- 后台：批量在 ShopXO 生成 N 个 SPEC（inventory=1）
- submit()：按 spec_base_id 分组，每组单独一行 goods_params
- ShopXO 原生防超卖

### 方案 B：每个 Zone 一个 SPEC（当前实现）
- spec_base_id_map：每个 Zone 一个 key
- submit()：每个 Zone 单独一行 goods_params
- 自建 FOR UPDATE 锁（在 onOrderPaid）
- Zone 间混买需前端分组

---

## 待确认问题

1. **spec_base_id_map 实际存储格式**：Zone 级还是座位级？
   - 查 ShopXO 数据库：`SELECT id, goods_id, inventory FROM sxo_goods_spec_base WHERE goods_id = ?`
2. **ShopXO SPEC 数量上限**：5000 座 × 多 Zone × 多时段 = 大量 SPEC，上限？
3. **决策**：选择方案 A 还是 B

---

## 关联
- Issue #6：P0-2 价格验证（相关）
- Issue #7：M-04 loadSoldSeats ✅ 已实现（seatSpecMap.inventory 反推已售座位，ShopXO原生防超卖）
