# Allotment / Control Block 与 Parent Group

## 权威业务定义

本文件是 Allotment / Control Block 与 Parent Group 语义的权威来源：

```text
Allotment / Control Block = Parent Group
Allotment code = Parent Group code
Parent Group 的 block_code = group_code
```

`Parent` 是完整 split 关系中的角色，不是独立于 Allotment / Control Block 的第二种预订对象。`group_code` 是统一业务主键；`block_code` 是 Parent Group 场景的兼容别名。

对象边界固定为四类：

1. 独立新建 Parent Group：`New Booking`，`booking_object_type=Allotment / Control Block`。
2. 独立整块取消 Parent Group：`Cancel Allotment`。
3. Parent Group 完整拆成 Child Groups：每个 child 为 `New Booking + Group Block`，另有且只有一个 parent `Cancel Allotment`。
4. 部分维护、部分释放或保留 parent 余量：当前不受支持，不得伪装为上述三类。

## Parent Identity

所有当前 producer 生成的 Parent Group 事件都必须使用：

```json
{
  "case_keys": {
    "group_code": "<parent_code>",
    "confirmation_number": null,
    "reservation_number": null,
    "block_code": "<parent_code>"
  }
}
```

固定规则：

- 只取得 `group_code` 或 `block_code` 任一值时，归一后同时写入两个键。
- 两个值同时存在且归一后不同，不得选择其一或输出冲突 key；两键均置为 `null`，在 `context_used.parent_identity_candidates[]` 保留原始候选证据，并在已知业务卡上使用 `manual_review.reason_code=target_object_unclear`。
- Child Group 和普通 Group Block 继续只使用 `group_code`，`block_code=null`。
- Parent code 不得写入 child event 的 `case_keys.group_code`。

## 新建 Parent Group

当前证据要求新建 allotment、allocation、control block、控房、配额、取配或配合房时，路由到 `New Booking`：

```json
{
  "booking_object_type": "Allotment / Control Block"
}
```

它是 Parent Group creation；其 `case_keys.group_code` 与 `case_keys.block_code` 必须按 Parent Identity 规则归一为同一值。

## 整块取消 Parent Group

明确取消整个 Allotment / Control Block 时使用 `Cancel Allotment`。这是取消 Parent Group，不是普通 Group Block 的 `Cancel Booking`。

独立整块取消不需要 split 关系字段，但仍必须满足 Parent 双 key 等值不变量。

减少房量、改部分日期、释放部分 allocation 或保留余量，不得路由为 Update、Cancel 或 `Allotment Maintenance`：整封邮件只有该意图时走 S10；同邮件另有支持事件时按 `03-current-content-completeness.md` 进入 `unhandled_current_intents`。

## 完整 Parent-To-Child Split

当当前证据明确显示 Parent Group 完整拆成 Child Groups，且 parent 不保留余量：

- 每个 child group 一个 `New Booking`，`booking_object_type=Group Block`。
- parent 是被完整取消/释放的 Allotment / Control Block。
- 保留 `allocation_split_from_parent=true`、parent original room summary 和 child group 列表。
- 不得因为文本写 `AMEND` 就归为普通改单。
- 不得因为出现 allocation/allotment/control block 字样就把 child 归为 `Allotment / Control Block`。
- 无论正文是否字面出现 `cancel` / `CXL`，都必须额外输出且只输出一个 linked parent `Cancel Allotment` candidate。

Parent split 事件固定为：

```json
{
  "event_type": "Cancel Allotment",
  "case_keys": {
    "group_code": "<parent_code>",
    "confirmation_number": null,
    "reservation_number": null,
    "block_code": "<parent_code>"
  },
  "extracted_fields": {
    "cancel_scope": "entire_allotment_control_block",
    "parent_release_or_cancel_candidate": true,
    "release_reason": "parent_to_child_allocation_split",
    "parent_group_code": "<parent_code>",
    "child_group_codes": ["<child_code>"],
    "allocation_split_from_parent": true,
    "parent_original_room_summary": null
  },
  "related_source_event_indices": ["<child_event_index>"],
  "related_event_type": "New Booking",
  "relationship_type": "linked_parent_release_after_child_split",
  "requires_downstream_hard_validation": true,
  "manual_review": null
}
```

该事件：

- 不替代 child creation。
- 只是候选事件，不代表 PMS 已取消成功，不创建真实 TaskCard，不写外部系统。
- 不得由 history-only parent-child evidence 触发。
- 复用 `Cancel Allotment / cancel_allotment_control_block` 卡；`relationship_type` 只负责 child 关联和 Preflight，不选择另一个任务卡 subtype。
- 当前 Agent 不得再生成 `Cancel Booking + linked_parent_release_after_child_split`。

## 显式取消去重

- 当前正文的显式 `Cancel Allotment` 与完整 split 派生取消命中同一归一化 parent code 时，合并两类证据，只保留一个上述 linked `Cancel Allotment` 事件。
- 显式取消命中不同 parent code 时，各 parent 独立输出，不得错误合并。
- 一个 split cluster 只能有一个 parent event。
- `child_group_codes[]` 不得重复，并与 `related_source_event_indices[]` 的数量和顺序一一对应。
- 每个 related index 必须指向同一 `message_events[]` 中对应 child code 的 `New Booking + Group Block`。

## 复核与 Fallback

- 完整 split 和 Parent `Cancel Allotment` subtype 已确定，但 parent key 冲突、child list 或关系字段不安全时，保留 `Cancel Allotment` 并附完整 `manual_review`。
- Parent 双 key 冲突使用 `target_object_unclear`；split 关系不完整使用 `parent_child_split_evidence_unclear`。
- 只有无法确认是否为完整 split，或无法在完整 split 与部分维护/保留余量之间裁决时，才输出 `event_type=Need Manual Review` 的 Fallback 复核。

## Legacy 只读兼容

历史 payload 中的 `Cancel Booking + relationship_type=linked_parent_release_after_child_split` 不迁移、不改写。Reader/adapter 可以无损读取后展示为 `Cancel Allotment / cancel_allotment_control_block` 卡；该兼容规则不得被当前 producer 用来继续生成旧组合。

## 默认 Rate / Room

Allotment / Control Block 缺 explicit Rate Code 时，只能在 room mapping 唯一且上下文明显符合 control-block default rules 时使用 `51-rate-code.md` 默认。

必需 room mapping 或 Rate Code 不唯一时保留 raw values、对应 PMS/code 字段为 `null`。当 `New Booking + Allotment / Control Block` 或 `New Booking + Group Block` subtype 已知时，保留原业务事件并附非空 `manual_review`；不得用 downstream hard validation 替代人工确认。
