# 嘉恒仓库库级出入库流水设计

## 背景

嘉恒仓库已经承载原材料库、半成品库、成品库、辅料库、废料库、退货库六类库存。当前页面支持点击某个物料查看该物料的批次台账和库存流水，但缺少“站在某一个仓库整体视角查看所有出入库流水”的入口。

本设计在仓库页新增库级流水入口。入口跟随当前选中的仓库 tab，用于查看当前仓库下所有物料、批次和业务单据产生的出入库流水。

## 目标

- 在嘉恒仓库页面的出入库操作区右侧新增一个“流水”图标按钮，位置对应用户截图红框区域。
- 当前选中哪个仓库 tab，点击按钮就查看该仓库的出入库流水。
- 六大仓库都支持库级流水：原材料库、半成品库、成品库、辅料库、废料库、退货库。
- 流水数据来自统一库存流水表 `wh_inventory_txn`，不新增另一套流水记录体系。
- 库级流水和现有物料级“库存流水”并存，形成“仓库总览 -> 物料明细 -> 批次追溯”的层级。

## 非目标

- 本次不新增复杂趋势图、库存金额图表或 BI 看板。
- 本次不替代物料详情抽屉中的批次台账和物料流水。
- 本次不改变现有出入库业务的入账逻辑。
- 本次不新增导出功能；可在后续版本增加“导出当前筛选流水”。

## 页面入口

在嘉恒仓库页面的出入库操作区右侧新增一个图标按钮。

按钮要求：

- 图标使用符合当前 Ruoyi 风格的“流水/列表/票据”类图标。
- 鼠标悬停显示提示：`查看当前仓库出入库流水`。
- 按钮文本可显示为 `流水`，避免只有图标导致用户不理解。
- 按钮始终跟随当前选中仓库 tab，不在每个仓库 tab 内重复放置。

示例：

```text
仓库 tab：原材料库 / 半成品库 / 成品库 / 辅料库 / 废料库 / 退货库

出入库操作区：
入库  [+ 期初入库] [+ 客料入库] ...
出库  [- 生产出库] [- 委外出库] ...
                                            [流水]
```

## 抽屉交互

点击“流水”按钮后，从右侧弹出大抽屉。

抽屉标题格式：

```text
{当前仓库名} · 出入库流水
```

例如：

```text
原材料库 · 出入库流水
成品库 · 出入库流水
退货库 · 出入库流水
```

抽屉内容分为三块：

1. 顶部汇总卡片
2. 筛选区
3. 流水明细表

抽屉滚动遵循全局抽屉规则：鼠标滚动只控制抽屉，不滚动底层主页面；抽屉必须完整显示在屏幕可视范围内。

## 顶部汇总

汇总数据按当前仓库和当前筛选条件计算。

建议展示：

- 入库笔数
- 出库笔数
- 入库重量(kg)
- 出库重量(kg)
- 最近一笔流水时间

数量口径：

- 原材料库、辅料库、废料库以重量为主，数量不作为核心汇总。
- 半成品库、成品库、退货库同时展示数量和重量。

如果汇总接口暂不单独返回，可前端基于当前分页结果做轻量展示，但最终推荐由后端返回全量筛选条件下的汇总，避免分页导致汇总不完整。

## 筛选与排序

筛选区保留系统全局业务列表筛选规则：

- 搜索框支持任意文字模糊搜索。
- 搜索范围包括物料编码、物料名称、批次号、流水类型、来源单据、运单号、备注。
- 重要业务字段支持排序，字段名旁显示上下箭头。

筛选项：

- 日期范围：按 `biz_time` 过滤。
- 出入库方向：全部、入库、出库、调整。
- 业务类型：采购入库、销售出库、退货入库、返工出库等。
- 物料：可选当前仓库内出现过的物料。
- 批次号：支持输入模糊匹配。

排序字段：

- 流水时间
- 业务类型
- 物料编码
- 批次号
- 变动重量
- 变动数量
- 金额

默认排序：

```text
流水时间倒序，最新流水在最上方。
```

## 流水表字段

通用字段：

- 流水时间
- 方向
- 业务类型
- 物料编码 / 物料名称
- 批次号
- 变动数量
- 变动重量(kg)
- 单价
- 金额
- 来源单据
- 经办人
- 运单号 / 订单照片
- 备注

不同仓库展示口径：

- 原材料库：隐藏或置空数量列，突出重量。
- 辅料库：隐藏或置空数量列，突出重量。
- 废料库：隐藏或置空数量列，突出重量和金额。
- 半成品库：展示数量和重量。
- 成品库：展示数量和重量。
- 退货库：展示数量和重量，并突出发货批次、退货单、返工出库来源。

方向判断：

- `weight_change_kg > 0` 或 `qty_change > 0` 为入库。
- `weight_change_kg < 0` 或 `qty_change < 0` 为出库。
- 盘库造成的正负调整显示为调整，也保留原始正负数。

## 数据接口

新增后端分页接口：

```http
GET /inventory/transaction-ledger
```

参数：

- `warehouse_type`: 必填，枚举 `RAW | SEMI | FINISHED | AUX | SCRAP | RETURN`
- `warehouse_id`: 可选，指定具体仓库 ID
- `keyword`: 可选，模糊搜索
- `direction`: 可选，`IN | OUT | ADJUST | ALL`
- `txn_type`: 可选，业务类型
- `item_id`: 可选，物料 ID
- `lot_no`: 可选，批次号模糊搜索
- `start_date`: 可选
- `end_date`: 可选
- `page`: 默认 1
- `page_size`: 默认 10
- `sort_key`: 默认 `biz_time`
- `sort_direction`: 默认 `desc`

返回：

```json
{
  "items": [],
  "total": 0,
  "summary": {
    "in_count": 0,
    "out_count": 0,
    "adjust_count": 0,
    "in_qty": 0,
    "out_qty": 0,
    "in_weight_kg": 0,
    "out_weight_kg": 0,
    "latest_biz_time": null
  }
}
```

接口内部使用 `wh_inventory_txn` 作为主表，关联：

- `md_item`
- `wh_warehouse`
- `wh_location`
- `wh_stock_lot`
- 操作人表，如果当前流水已有 `operator_user_id`

## 与现有功能关系

库级流水：

- 入口位于出入库操作区。
- 查询当前仓库所有物料和批次的流水。
- 用于回答“这个仓库最近发生了哪些出入库”。

物料级流水：

- 入口是点击库存列表中的某个物料。
- 查询该物料在当前仓库下的流水。
- 用于回答“这个物料为什么变成当前库存”。

批次台账：

- 入口同样是点击库存列表中的物料。
- 查询该物料下面每个批次的现存状态。
- 用于回答“当前还剩哪些批次，批次来源是什么”。

三者保留并互补，不互相替代。

## 错误与空状态

- 当前仓库没有流水时显示空状态：`暂无{仓库名}出入库流水`。
- 接口失败时使用右上角全局提示，几秒后自动收回，鼠标悬停时保持不收。
- 筛选结果为空时显示：`没有符合条件的流水`。
- 如果仓库正在盘库锁库，流水仍可查看，但出入库动作不可操作。

## 测试方案

后端测试：

- 按仓库类型过滤只返回对应仓库流水。
- 方向过滤能区分入库、出库、调整。
- 关键词搜索覆盖物料、批次、来源、备注。
- 分页返回 `items`、`total` 和 `summary`。
- 原材料库流水数量口径保持重量优先，不恢复原材料数量概念。

前端静态测试：

- 嘉恒仓库页面存在“流水”入口。
- 六大仓库 tab 都可打开同一流水抽屉。
- 请求使用 `/inventory/transaction-ledger`。
- 旧物料级库存流水仍保留。

前端构建：

- `npm run build` 通过。

浏览器冒烟：

- 登录后进入嘉恒仓库。
- 切换任意仓库 tab。
- 点击“流水”按钮。
- 抽屉标题和当前仓库一致。
- 搜索、日期筛选、分页能正常工作。

## 后续可选增强

- 增加“导出当前筛选流水”。
- 增加流水趋势图。
- 增加来源单据点击跳转。
- 增加按业务类型聚合的迷你统计。
