# 嘉恒仓库全出入库单据纸质化与归档设计

## 背景

嘉恒仓库已经有 6 大库：原材料库、半成品库、成品库、辅料库、废料库、退货库。当前出入库业务主要通过抽屉表单完成，保存后形成库存流水。用户已经认可 `原材料库 · 客料入库` 的纸质填单样板，但该样板目前只完成填写 UI，没有生成 PDF 归档，也没有预览和下载入口。

现有归档体系已覆盖销售订单、采购订单、到货入库单、质量校验单、生产领料出库单、生产入库结算单。仓库里大量非生产分支仍未纳入正式单据化：客料、委外、销售、退货、返工、特殊出入库、期初等。为避免后续继续碎片化，本方案把“所有仓库出入库填单纸质化、保存后 PDF 归档、流水入口预览下载、流水 Excel 导出”作为统一仓库单据化工程。

## 目标

1. 6 大库所有入库、出库填单页面改造成正式纸质化单据风格。
2. 每次出入库保存后生成 PDF 归档，业务保存成功但 PDF 失败不回滚业务。
3. 保存成功提示区提供 `预览PDF`、`下载PDF` 快捷入口。
4. 各库流水抽屉中每条流水展示 `单据留档`，支持预览、下载、重新生成。
5. 物料/库存批次明细中的库存流水也能看到对应 PDF 留档入口。
6. `生产台账入库` 这类一次生成多个仓库流水的动作，使用一张 `生产入库结算单`，多条流水共用同一归档。
7. 各库流水模块支持按当前筛选条件，尤其是时间范围，导出 Excel 清单。
8. PDF 和 Excel 中不使用前端省略号逻辑，长字段完整换行或完整输出。

## 范围

### 覆盖仓库

- 原材料库
- 半成品库
- 成品库
- 辅料库
- 废料库
- 退货库

### 覆盖入口

原材料库：

- 期初入库
- 客料入库
- 生产余料入库
- 委外余料入库
- 特殊入库
- 生产出库
- 委外出库
- 退货出库
- 报废出库
- 特殊出库

半成品库：

- 产中入库
- 期初入库
- 委外入库
- 特殊入库
- 产中出库
- 委外出库
- 特殊出库

成品库：

- 生产入库
- 返工入库
- 委外入库
- 期初入库
- 特殊入库
- 销售出库
- 特殊出库

辅料库：

- 期初入库
- 特殊入库
- 生产出库
- 特殊出库

废料库：

- 生产废料入库
- 返工废料入库
- 期初入库
- 委外废料入库
- 退货废料入库
- 特殊入库
- 售卖出库
- 特殊出库

退货库：

- 期初入库
- 退货入库
- 特殊入库
- 返工出库
- 特殊出库

跨库工具：

- 生产台账入库

## 单据归档类型

### 生产专用单据

保持现有设计：

- `生产领料出库单`
- `生产入库结算单`

这些单据用于生产主链路，不再重复映射到通用仓库作业单，避免一笔生产业务出现两套 PDF。

### 通用仓库作业单

新增通用归档类型：

- `仓库出入库单`

该类型覆盖除生产专用单据外的所有仓库出入库按钮。PDF 标题根据仓库和业务类型动态生成，例如：

- `客料入库单`
- `委外余料入库单`
- `委外出库单`
- `销售出库单`
- `退货入库单`
- `返工出库单`
- `特殊入库单`
- `售卖出库单`

通用类型的好处是后端只需一个归档收集器和一个路由 key，所有仓库业务通过配置映射生成不同标题与字段。

## 归档业务主键

### 单条库存流水动作

以本次业务动作形成的主 `wh_inventory_txn.id` 作为 `business_id`。

适用：

- 客料入库
- 委外出库
- 报废出库
- 售卖出库
- 期初入库
- 大多数普通入库/出库

### 多条库存流水动作

以主库存流水 ID 作为 `business_id`，同一动作产生的其它库存流水通过 `document_batch_no` 或关联表映射到同一归档。

适用：

- `生产台账入库`：使用现有 `生产入库结算单`，主流水优先级为成品入库、余料入库、废料入库。
- 后续若某个普通仓库动作一次形成多条流水，也沿用同样主流水规则。

### 特殊出入库

特殊出入库要保留“必须填写说明”的业务约束。若特殊调整有主表，则优先以特殊调整主表 ID 作为归档业务主键；若当前实现只有库存流水，则以本次特殊调整的主库存流水 ID 作为归档业务主键。PDF 必须完整展示调整说明和每条明细的调整前后数量/重量。

### 已有关联业务单据

如果某个仓库动作本质已经有更上游单据：

- 采购到货入库保留 `到货入库单`
- 销售订单保留 `销售订单`
- 生产主链路保留生产专用单据

但仓库内实际发生出库/入库时，仍应能从仓库流水看到该次仓库作业的留档。如果该仓库动作已有专用归档，则流水指向专用归档；否则指向 `仓库出入库单`。

## 纸质填单 UI 规则

### 通用结构

所有仓库出入库抽屉采用统一纸质单据底座：

- 抬头：嘉恒仓库、单据标题、单据编号或提交后生成提示。
- 基础信息区：仓库、库位、业务类型、来源/去向、经办人、时间。
- 明细区：物料/产品/半成品/废料/退货品、库存批次号、来源库存批次号、数量、重量、单价、金额。
- 辅助信息区：运单号、运费、辅助照片、用途、包装备注、退货/返工/委外方、说明。
- 备注区：用户备注和系统生成说明。
- 签核区：制单、仓库确认、业务确认、复核。
- 底部固定操作区：保存按钮、保存中状态。

### 业务字段不删减

纸质化只是表现层升级，不改变原有业务字段和校验。已有字段必须保留，只调整布局、标题、分区和视觉样式。此前用户明确要求去掉的字段除外。

### 保存后反馈

保存成功后显示：

- 业务保存结果
- PDF 归档状态
- `预览PDF`
- `下载PDF`

如果 PDF 失败：

- 显示 `PDF归档失败`
- 显示中文失败原因
- 提供 `重新生成`
- 不回滚库存流水

## PDF 内容规则

PDF 是业务快照，以保存后的数据库事实为准，不从前端表单重新计算。

PDF 必须包含：

- 单据标题
- 单据编号
- 业务时间
- 仓库和库位
- 业务类型
- 经办人
- 物料/产品/半成品/废料/退货品信息
- 库存批次号
- 来源库存批次号
- 数量/重量
- 单价/金额
- 运单号、运费、辅助照片链接或照片存在标记
- 业务说明和备注
- 关联采购单、销售单、生产台账、发货批次、退货处置等追溯信息

PDF 不得出现：

- 英文状态值
- 前端省略号
- 超出单元格的长文本
- 无业务意义的每库内部批次号

## 流水预览与下载入口

### 各库流水抽屉

在 `嘉恒仓库 -> 工具 -> 流水` 中新增 `单据留档` 列。

每条流水根据后端返回的归档字段展示：

- `未生成`
- `已归档`
- `归档失败`
- `预览PDF`
- `下载PDF`
- `重新生成`

### 库存明细右侧流水

物料/批次详情抽屉中的库存流水也新增 `单据留档`，行为与仓库流水一致。

### 生产台账入库

`生产台账入库` 保存后若一次生成成品、余料、废料多条流水，这几条流水的 `单据留档` 指向同一张 `生产入库结算单`。

## 流水 Excel 导出

### 入口位置

在各库流水抽屉顶部筛选区增加 `导出Excel` 按钮，放在 `查询` 按钮旁边。

### 导出范围

导出使用当前流水筛选条件：

- 当前仓库类型
- 当前仓库 ID
- 关键词
- 流水方向
- 流水类型
- 物料
- 库存批次号
- 开始日期
- 结束日期
- 排序字段
- 排序方向

如果用户没有选择时间范围，允许导出当前筛选条件下所有流水，但前端需要轻提示“当前未选择时间范围，将导出全部匹配流水”。第一版不强制时间范围，避免阻塞真实查账场景。

### Excel 字段

导出的 Excel 至少包含：

- 业务时间
- 仓库
- 库位
- 方向
- 流水类型
- 物料/产品编码
- 物料/产品名称
- 库存批次号
- 来源库存批次号
- 数量变化
- 重量变化
- 单价
- 金额
- 来源单据
- 经办人
- 运单号
- 运费
- 辅助照片
- 备注
- PDF归档状态
- PDF归档业务ID

Excel 需使用中文表头，冻结表头，自动筛选，合理列宽。

## 后端设计

### 归档服务

在 `document_archives.py` 中新增：

- `DOCUMENT_TYPE_WAREHOUSE_OPERATION = "仓库出入库单"`
- `collect_warehouse_operation_archive_context`

通用收集器根据主库存流水读取：

- 主库存流水
- 相关库存流水
- 库存批次
- 来源库存批次
- 仓库和库位
- 关联采购/销售/退货/发货/生产台账信息
- 物流字段
- 特殊调整说明

### 路由

`/document-archives/{document_type_key}/{business_id}/...` 增加：

- `warehouse-operation`

### 仓库保存接口

所有普通仓库出入库保存成功后：

1. 完成库存业务事务。
2. 提交业务数据。
3. 生成 PDF 归档。
4. 返回归档状态。

生产专用动作保持现有生产归档类型。

### 流水接口

`GET /inventory/transaction-ledger` 返回每行归档字段：

- `archive_status`
- `archive_business_id`
- `archive_document_type`
- `archive_error_message`

### Excel 导出接口

新增：

- `GET /inventory/transaction-ledger/export`

该接口接收与流水查询一致的筛选参数，返回 `.xlsx` 文件。

## 前端设计

### 单据化表单

抽出通用仓库纸质表单组件：

- `WarehouseDocumentFormShell`
- `WarehouseDocumentGrid`
- `WarehouseDocumentActionBar`
- `WarehouseArchiveShortcut`

`原材料库 · 客料入库` 样板迁移到通用组件上，其它表单逐步替换。

### PDF 操作组件

复用现有 `DocumentArchiveActions`，不再做第二套预览/下载按钮。

### Excel 导出

仓库流水抽屉筛选区新增 `导出Excel`。

导出时：

- 按钮显示 `导出中...`
- 禁止重复点击
- 使用 `downloadResource`
- 文件名格式：`{仓库名}出入库流水_{开始日期或全部}_{结束日期或全部}.xlsx`

## 实施分期

### Phase 1：底座和入口

- 新增通用 `仓库出入库单` 归档类型。
- 仓库流水接口返回归档字段。
- 仓库流水新增预览/下载/重新生成。
- 流水 Excel 导出。
- 客料入库补齐 PDF 归档。

### Phase 2：通用表单纸质化

- 期初入库
- 客料入库
- 委外余料入库
- 委外出库
- 报废出库
- 售卖出库
- 辅料生产出库
- 半成品产中/委外入出库

### Phase 3：专用业务表单纸质化

- 销售出库
- 退货入库
- 退货废料入库
- 返工出库
- 返工入库
- 返工废料入库
- 特殊出入库

### Phase 4：生产主链路统一入口

- 生产出库、生产台账入库、生产入库、生产余料入库、生产废料入库沿用生产专用 PDF。
- 仓库流水和生产台账详情统一指向同一份归档。

## 验收标准

1. 所有仓库出入库入口打开后都是纸质化单据风格。
2. 客料入库保存后能生成 `仓库出入库单` PDF，并可预览和下载。
3. 任意仓库流水行能看到归档状态；已归档可预览和下载。
4. `生产台账入库` 一次产生多条流水时，多条流水打开同一张 `生产入库结算单`。
5. PDF 失败不影响库存保存，页面显示失败并允许重新生成。
6. 各库流水可按时间范围导出 Excel。
7. Excel 内容符合当前筛选范围，中文表头完整，数值和备注不丢失。
8. PDF 和 Excel 均不出现英文状态值或截断省略号。

## 设计结论

全仓库单据化采用“通用仓库作业单 + 生产专用单据”的双轨方案：

- 普通仓库出入库统一归档为 `仓库出入库单`。
- 生产领料和生产入库结算继续使用生产专用单据。
- 所有单据都通过仓库流水、库存明细流水、保存成功反馈提供预览和下载入口。
- 各库流水导出 Excel 与当前筛选条件保持一致。

该方案能覆盖 6 大库所有出入库入口，又避免为每个按钮单独造一套 PDF 逻辑。
