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

# shb-cli warehouse replacement search（替换记录列表搜索）

物料替换记录列表查询。详情与"按原始物料查有效替换候选"见 [`shb-warehouse-replacement-detail.md`](shb-warehouse-replacement-detail.md)，创建/编辑/删除等写操作先读 [`shb-warehouse-replacement-mutation-common.md`](shb-warehouse-replacement-mutation-common.md)。物料本身的查询见 [`../../shb-warehouse-material/SKILL.md`](../../shb-warehouse-material/SKILL.md)。

## 快捷 flag 方式（推荐）

```bash
# 关键字搜索，用 --condition-type 指定搜的是原始物料还是替换物料
shb-cli warehouse replacement search --condition-type original --keyword <关键字>
shb-cli warehouse replacement search --condition-type replace --keyword <关键字>

# 按原始物料 / 替换物料筛选
shb-cli warehouse replacement search --original-sn <原始物料编号>
shb-cli warehouse replacement search --original-name <原始物料名称>
shb-cli warehouse replacement search --replace-sn <替换物料编号>
shb-cli warehouse replacement search --replace-name <替换物料名称>

# 按适用产品类型筛选
shb-cli warehouse replacement search --catalog-ids 101,102

# 只看启用中的替换记录
shb-cli warehouse replacement search --enabled true

# 按当前有效性筛选（active=生效中，expired=已失效，pending=未生效）
shb-cli warehouse replacement search --state active

# 分页
shb-cli warehouse replacement search --page 1 --page-size 20

# 组合使用
shb-cli warehouse replacement search --original-sn <编号> --state active --enabled true

# 格式化数据输出
shb-cli warehouse replacement search --original-sn <编号> --format-data --fields originalSN,originalName,replaceSN,replaceName,priority,state

# 获取全量数据：仅当用户明确要求"全部/所有/全量"数据时才加 --all
shb-cli warehouse replacement search --state active --all --format-data --fields originalSN,replaceSN,priority
```

## 完整 JSON body 方式

```bash
# 内联 JSON （推荐）
shb-cli warehouse replacement search --data '{"pageNum":1,"pageSize":10,"originalSN":"M-001"}'

# 从文件读取
shb-cli warehouse replacement search --file ./replacement-search.json
```

需要 `priority` 精确匹配、`createTime`/`effectiveDate`/`expirationDate` 范围过滤、`materialIds`/`originalIds`/`replaceIds` 批量 id 过滤等快捷 flag 未覆盖的字段时用 `--data`。

## 支持的搜索字段（JSON body，字段名为 ReplacementSearchModel）

| 字段 | 类型 | 说明 |
|------|------|------|
| `conditionType` | int | `1`=关键字匹配原始物料，`2`=关键字匹配替换物料 |
| `keyword` | string | 关键字模糊搜索，受 `conditionType` 控制 |
| `originalId` | int | 原始物料 id |
| `originalSN` | string | 原始物料编号，模糊匹配 |
| `originalName` | string | 原始物料名称，模糊匹配 |
| `replaceSN` | string | 替换物料编号，模糊匹配 |
| `replaceName` | string | 替换物料名称，模糊匹配 |
| `catalogId` / `catalogIds` | long / long[] | 适用产品类型范围 |
| `priority` | int | 优先级精确匹配 |
| `state` | int | `1`=生效中，`0`=已失效，`2`=未生效 |
| `enable` | int | 启用状态：`1`=启用，`0`=禁用 |
| `effectiveDate` / `startEffectiveDate` / `endEffectiveDate` | - | 生效时间过滤/范围 |
| `expirationDate` / `startExpirationDate` / `endExpirationDate` | - | 失效时间过滤/范围 |
| `createTime` / `createTimeStart` / `createTimeEnd` | - | 创建时间过滤/范围 |
| `createUser` | string[] | 创建人 id 列表 |
| `remark` | string | 备注，模糊匹配 |
| `materialIds` / `originalIds` / `replaceIds` | int[] | 批量 id 过滤，高级/少用，仅 `--data`/`--file` |
| `pageNum` | int | 页码，**从 1 开始**（默认 1） |
| `pageSize` | int | 每页条数（默认 10） |

> **flag 名与 JSON 字段名的对应**：`--condition-type`（`original`/`replace`）↔`conditionType`（`1`/`2`）、`--state`（`active`/`expired`/`pending`）↔`state`（`1`/`0`/`2`）、`--enabled`（`true`/`false`）↔`enable`（**JSON 整数** `1`/`0`，不是布尔——这一点和响应字段 `ReplacementVO.enable` 是布尔值不同，注意搜索请求和响应结果的字段类型不一样）。

> `tenantId` 由服务端根据当前登录用户自动注入，**不需要也不能**在请求里传。

## 获取全量数据：决策规则

**CRITICAL — 默认不要用 `--all`。** 用户没有明确要求"全部/所有/全量"数据时，一律走默认分页（或按需 `--page-size`），不要主动升级成全量拉取。

- **用户明确要求全部/所有/全量数据**时才使用 `--all`：能判断数据量不大（≤500）直接执行一次 `--all` 拿齐，无需先探量；不确定是否超过 500 先用 `--page-size 1` 探一次 `total` 再决定用 `--all` 还是分页叠加。**必须 `--format-data --fields <少数列>` 两者一起**，且每个查询条件最多执行一次 `--all`。
- **只需要总数**：用 `--page-size 1` 取 `page.totalElements`，不要为了数数把全量明细拉进来。
- **用户只是想看看/搜一下，没提"全部"**：用默认分页即可，不要自作主张加 `--all`。

## --format-data 输出结构速查

`--format-data -o raw` 返回：

```json
{
  "page":    {"page": 1, "pageSize": 10, "totalElements": 8, "totalPages": 1},
  "columns": [{"field": "originalSN", "label": "原始物料编号"}, ...],
  "rows":    [{"originalSN": "M-001", "originalName": "空调整机", "replaceSN": "M-002", "replaceName": "备用整机", "priority": "1", "state": "生效中", "enable": "启用", "effectiveDate": "2026-01-01 00:00:00", "expirationDate": "2026-12-31 23:59:59", ...}, ...]
}
```

不加 `--fields` 时默认输出字段：`originalSN`（原始物料编号）、`originalName`（原始物料名称）、`replaceSN`（替换物料编号）、`replaceName`（替换物料名称）、`priority`（优先级）、`state`（状态）、`enable`（启用状态）、`effectiveDate`（生效时间）、`expirationDate`（失效时间）。

其余可选字段：`id`（记录内部 ID，整数）、`originalId`/`replaceId`（物料内部 ID）、`catalogId`/`catalogName`（适用产品类型）、`isPermanently`（是否永久有效）、`remark`（备注）、`createUserName`（创建人）、`createTime`（创建时间）。

### 字段说明

- `enable`/`isPermanently` 是 JSON 布尔值，`--format-data` 转换为「启用」/「停用」、「永久有效」/「非永久」中文展示；**用 `--enabled` 过滤时传字符串 `true`/`false`**（命令内部会转换成请求体需要的 `1`/`0` 整数，不是布尔——`ReplacementSearchModel.enable` 和响应里 `ReplacementVO.enable` 的字段类型不同）。
- `state` 是服务端计算出的当前有效性快照（不是数据库里存的字段），`--state` 过滤和 `state` 展示列用的是同一套三态语义。
- 响应本身带 `{success,code,message,data}` 信封，`--format-data` 已自动解包出 `data`（即 `PageInfo`），无需关心信封细节。

## 典型组合场景

### 查某个物料参与的所有替换关系（不管是当原始物料还是替换物料）

```bash
shb-cli warehouse replacement search --condition-type original --keyword <物料编号或名称>
shb-cli warehouse replacement search --condition-type replace --keyword <物料编号或名称>
```

## 注意

- `warehouse replacement search` 默认输出原始响应（已解包信封后的 `PageInfo`：`{pageNum, pageSize, total, pages, list}`）；需要字段文案和值格式化时显式传 `--format-data`。
- 搜索结果为空时，检查 `originalSN`/`replaceSN`/`catalogIds` 等筛选条件是否匹配当前租户下实际存在的值，以及当前登录用户是否有相应权限。
- **统计需求优先用计数查询**：只需要总数时用 `--page-size 1` 取 `page.totalElements`，不要为了数数把全量明细拉进来。
