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

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

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

## 变更操作安全规则

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

| 档位 | 命令 | 需要 `--yes`/`--dry-run` |
|---|---|---|
| 低风险 | `replacement create` / `replacement create batch` / `replacement edit` / `replacement edit enable` | 否 |
| 高风险（批量） | `replacement delete` | **是** |

1. **`replacement delete` 必须传 `--yes`**（或 `--dry-run` 仅预览），否则拒绝执行。`--yes`/`--dry-run` 不要代用户自动加上，除非用户已明确表达了执行意图。
2. **`originalId` 不能等于 `replaceId`（一个物料不能替换它自己）**：后端**没有**这项校验，会静默接受这种脏数据。CLI 在 `create`、`edit`、`create batch` 的每一条路径（快捷 flag 和 `--data`/`--file` 都算）都会做这道客户端硬校验，检测到相等会在发请求前直接拒绝，不产生网络请求——这是本域唯一一条"连 `--data` 模式也拦"的规则。
3. **`replacement edit` 内部自动 fetch-then-merge**：后端对已有记录是**整行覆盖式更新**（不是选择性更新）——只有 `remark`/`enable` 两个字段在漏传时会自动沿用旧值，`catalogId`/`catalogIds`/`effectiveDate`/`expirationDate`/`priority`/`isPermanently`/`originalId`/`replaceId` 漏传都会被清空成默认值。快捷 flag 模式下命令会自动先查当前完整记录（`replacement detail`）再叠加本次改动一起提交，正常使用快捷 flag 即可，不用担心清空问题。**`--data`/`--file` 模式不做这个自动保护**，需要自己先查后改（操作步骤见 [`shb-warehouse-replacement-edit.md`](shb-warehouse-replacement-edit.md)）。
4. **`replacement edit` 的快捷 flag 不能改 `originalId`/`replaceId`**：编辑一条记录去改"谁替换谁"，本质是在同一个记录 `id` 下换成完全不同的业务关系，容易造成误解，超出"编辑元数据"的合理范围。快捷 flag 只暴露 `catalogIds`/`effectiveDate`/`expirationDate`/`permanently`/`remark`/`enable` 这些元数据字段；要改 `originalId`/`replaceId` 只能用 `--data` 显式指定。
5. **`priority` 不出现在 `create`/`edit` 任何一方的快捷 flag 里**：创建时后端自动把新记录追加到该原始物料现有优先级末尾；单独改一条记录的优先级而不同步调整同一原始物料下的其它兄弟记录，会造成优先级冲突/重复。真正安全的调整入口是 `--data` 里的 `replacementList`/`sortList` 批量重排机制，不是本命令族当前覆盖的场景。
6. **同一 `(originalId, replaceId)` 组合不能重复创建**：服务端会拒绝并返回"该替换物料已替换过该原始物料，无需重复替换"（错误码 411000），这是服务端强校验，CLI 不需要额外查重，报错信息直接透传给用户即可。
7. **`replacement edit enable` 是纯直通调用**：后端 `enable` 接口本身就接受显式目标值（`id`+`enable`），不是翻转接口，因此命令直接把 `--id`/`--enable` 拼成请求发出去，不会像 BOM 域那样先查当前状态再决定要不要调用——每次调用都是确定性的"设为 X"，重复调用同一目标状态是安全、幂等的。
8. 变更操作失败时如实告知用户失败原因（整理成可读信息），不要谎称成功、不要盲目重试。

## 写操作通用注意

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

## 命令速查表

| 命令 | 必填 flag | 是否需要 `--yes` |
|---|---|---|
| `replacement create` | `--original-id` `--replace-id`（或 `--data`/`--file`） | 否 |
| `replacement create batch` | `--data`/`--file` | 否 |
| `replacement edit` | `--id` | 否（内部自动 fetch-then-merge） |
| `replacement edit enable` | `--id` `--enable` | 否 |
| `replacement delete` | `--ids` | **是** |
