> **前置条件** — 执行前请先确认已完成认证（参见 [`../../shb-shared/SKILL.md`](../../shb-shared/SKILL.md)）。输出措辞禁令、id 复用规则、传参优先级见本 skill 的 [`SKILL.md`](../SKILL.md)。

# BOM 域公共变更规范（全部写操作的强制前置）

本文档是物料服务BOM域**所有跨命令变更规则的唯一出处**，执行任何写操作（`bom create` / `bom edit` / `bom edit status` / `bom delete` / `bom delete materials` / `bom revert`）前必须已加载本文档，再加载对应操作的专属文档（[`create`](shb-warehouse-bom-create.md) / [`edit`](shb-warehouse-bom-edit.md) / [`delete`](shb-warehouse-bom-delete.md)）。

## 变更操作安全规则

**CRITICAL** — 写命令按风险分两档，动手前先判断落在哪一档：

| 档位 | 命令 | 需要 `--yes`/`--dry-run` |
|---|---|---|
| 低风险 | `bom create` / `bom edit` / `bom edit status` / `bom revert` | 否 |
| 高风险（批量/级联） | `bom delete` / `bom delete materials` | **是** |

1. **`bom delete` / `bom delete materials` 必须传 `--yes`**（或 `--dry-run` 仅预览），否则拒绝执行。`--yes`/`--dry-run` 不要代用户自动加上，除非用户已明确表达了执行意图。
2. **`bom edit` 内部自动 fetch-then-merge**：后端对组成物料列表（`materialList`）是"全量替换式 diff"——本次没提交的现有组件会被删除，产品目录关联（`relationProductCatalog`）同理可能被全量替换。快捷 flag 模式下命令会自动先查当前完整状态（组件列表 + 产品目录关联）再叠加本次改动一起提交，正常使用快捷 flag 即可，不用担心清空问题。**`--data`/`--file` 模式不做这个自动保护**——如果确实要用这种方式，必须先拿到当前完整组件列表再在此基础上只改要改的部分（操作步骤见 [`shb-warehouse-bom-edit.md`](shb-warehouse-bom-edit.md)）。
3. **绝不要在 `materialList` 的任何一项里带 `children` 字段**：后端把非空 `children` 当作"自动创建/编辑一个嵌套子 BOM"的触发器，这是一个隐藏副作用，会在你不知情的情况下改动*其它*BOM 记录。CLI 的快捷 flag 路径从不产生 `children`；如果用户坚持用 `--data` 手写请求体，必须提醒不要加这个字段。本条对 `bom create` 和 `bom edit` 同时生效。
4. **`bom delete materials` 摘除全部剩余组件会级联删除整个 BOM 头**：命令执行前会先查当前组件列表，若 `--material-ids` 覆盖了全部现存组件，会在确认信息里明确提示"这会级联删除整个 BOM"。
5. **`bom edit status` 是对纯翻转接口的包装**：后端 `enabled` 接口本身没有"设为 X"的参数，每调用一次就翻一次当前状态。命令会先查当前状态，若已经是目标值就直接返回、不调用接口；只有状态确实需要变化时才调用一次翻转，因此可以放心重复执行同一个 `--status` 而不会来回抖动。
6. **`bom create` 的组件物料只能通过 `--data`/`--file` 提交**：快捷 flag 只能创建"零组件"的 BOM 头（仅 `--material-id`/`--remark`），这是有意设计（避免 flag↔JSON 映射出错，也顺带避免 `children` 被误传）。
7. 变更操作失败时如实告知用户失败原因（整理成可读信息），不要谎称成功、不要盲目重试。

## 写操作通用注意

- 所有变更命令默认输出未格式化的原始响应（已解包信封）；`create`/`edit` 支持 `--format-data` 在成功后立即按查询格式展示最新状态，便于确认改动生效。
- `edit`/`edit status`/`delete`/`delete materials` 操作前，如果不确定目标 BOM 范围，先用 `bom search` 或 `bom detail` 确认一遍，不要凭用户口头描述直接批量操作。
- `bom delete`/`bom delete materials` 提交前，如果用户没有明确说"确认执行"，先复述一遍将要影响的 id 范围和操作，等用户确认意图后再加 `--yes` 执行。
- 变更请求失败时，报错信息通常已包含具体原因（必填字段缺失、`--yes` 未传、主物料已存在 BOM、组成物料重复等），整理成人话讲给用户，不要笼统说"失败了"；也不要在没有新信息的情况下重复重试同一个失败请求。

## 命令速查表

| 命令 | 必填 flag | 是否需要 `--yes` |
|---|---|---|
| `bom create` | `--material-id`（或 `--data`/`--file`） | 否 |
| `bom edit` | `--id` | 否（内部自动 fetch-then-merge） |
| `bom edit status` | `--id` `--status` | 否 |
| `bom delete` | `--ids` | **是** |
| `bom delete materials` | `--bom-id` `--material-ids` | **是** |
| `bom revert` | `--id` | 否 |
