# 销售/采购订单单据化与 PDF 归档设计

## 背景

当前销售订单、采购订单新增页面主要是抽屉内的卡片式数据录入表单。它能完成业务数据提交，但视觉上更像后台管理系统，不像正式业务单据。

本次先按方案 B 试点：只改造“销售订单”和“采购订单”。目标是验证“真实单据填写 + 保存即归档”的产品方向，跑通后再扩展到到货入库单、仓库出入库单、质检单、盘库单等其他单据。

## 设计目标

1. 销售订单、采购订单新增表单改为真实“单据”形态，用户感觉是在填写正式业务单。
2. 外层仍沿用当前系统抽屉，不改变用户从列表点击新增的入口习惯。
3. 内层采用 v3 效果图方向：工厂联单/归档单风格，而不是普通网页卡片拟纸。
4. 单据保存成功时，后端基于当时业务数据生成不可变 PDF 归档快照。
5. PDF 作为主归档文件，Word 只作为按需辅助导出，不作为原始留档依据。
6. 列表支持单据归档状态展示、单份预览、单份下载、多选批量下载。

## 视觉方向

采用“工厂联单/归档单嵌入系统抽屉”的风格。

已确认的 v3 效果图文件：

- `outputs/document-form-mockups/sales-order-document-form-mockup-v3-real-paper.png`
- `outputs/document-form-mockups/purchase-order-document-form-mockup-v3-real-paper.png`

关键视觉特征：

- 真实纸张底色，偏米白而不是冷白网页卡片。
- 纸张纹理轻量保留，避免影响阅读。
- 外层有档案板/叠纸阴影，体现这是一张正式归档单。
- 顶部使用金属夹/装订元素，增强真实“夹在文件板上”的感觉。
- 单据标题使用黑色居中大字，例如“销售订单”“采购订单”。
- 单据编号使用右上红/绿编号章，不再放在普通卡片角标里。
- 表单字段使用真实单据表格格线，减少圆角输入框感。
- 明细使用表格行，表现为“纸上填写格”，不再使用多张卡片堆叠。
- 底部保留签字/确认栏，例如销售确认、客户确认、财务复核、制单人。
- PDF 归档章弱化为纸面印章，不能遮挡核心数据。

## 交互范围

### 销售订单新增

保持现有字段和业务逻辑，不删字段、不改变提交语义。

单据结构：

1. 单据头部：公司名、销售订单标题、销售订单号、归档联标记。
2. 抬头信息：客户、销售人员、下单日期、交期、税率、送货地址。
3. 订单明细：产品、客户料号、订单数量、销售单价、明细交期、金额。
4. 汇总信息：订单总数、未税金额、含税金额、归档状态。
5. 备注与签字：备注、销售确认、客户确认、财务复核、制单人。
6. 操作区：保存草稿、保存并生成 PDF 归档。

### 采购订单新增

保持现有字段和业务逻辑，不删字段、不改变提交语义。

单据结构：

1. 单据头部：公司名、采购订单标题、采购单号、归档联标记。
2. 采购路径：到货库、采购方式、归档策略。
3. 抬头信息：供应商、采购人员、预计到货、提前预警、税率、关联销售订单。
4. 采购明细：原材料、性能要求、采购重量、辅助吨数、单价、元/吨、明细交期。
5. 汇总信息：采购总重量、折合吨数、含税金额、归档状态。
6. 备注与签字：采购确认、供应商确认、仓库接收、制单人。
7. 操作区：保存草稿、保存并生成 PDF 归档。

## 归档规则

### 主档格式

PDF 是主归档文件。

原因：

- PDF 更适合固定原始单据快照。
- PDF 不易被用户误编辑。
- 后续预览、下载、批量下载更稳定。

Word 只做辅助导出。

原因：

- Word 可编辑，不适合作为原始留档依据。
- 如果后续客户需要对外沟通版本，可以导出 Word，但系统内部追溯以 PDF 为准。

### 生成时机

第一版采用“保存成功后自动生成 PDF 归档”。

具体规则：

- 新增销售订单保存成功后，立即生成销售订单 PDF 归档。
- 新增采购订单保存成功后，立即生成采购订单 PDF 归档。
- 如果 PDF 生成失败，业务单据仍可保存，但列表显示“归档失败”，允许用户重新生成。
- 归档生成时要记录模板版本、生成时间、生成用户、文件路径、文件哈希。

### 编辑后的处理

第一版建议采用版本化归档。

规则：

- 每次关键字段编辑后重新生成新的 PDF 归档版本。
- 历史归档版本保留。
- 列表默认展示最新归档。
- 详情中可查看历史归档版本。

这样不会出现“数据改了，但原来 PDF 覆盖掉了”的追溯风险。

## 数据模型建议

新增通用单据归档表，例如 `document_archives`。

建议字段：

- `id`
- `document_type`：销售订单、采购订单等。
- `business_id`：业务主表 ID。
- `document_no`：业务单号。
- `archive_version`：归档版本号。
- `template_version`：模板版本。
- `file_format`：PDF 或 DOCX。
- `file_name`
- `file_path`
- `file_hash`
- `status`：已生成、生成失败。
- `error_message`
- `created_by`
- `created_at`

第一版只要求销售订单、采购订单接入。

## 前端列表调整

销售订单列表、采购订单列表增加归档相关操作。

列表列建议：

- 归档状态：未生成、已归档、归档失败。
- 操作：预览、下载、重新生成。

批量操作：

- 勾选多张销售订单后可批量下载 PDF。
- 勾选多张采购订单后可批量下载 PDF。
- 批量下载由后端打包 zip。

## 后端接口建议

销售订单：

- `POST /sales/orders/{id}/archive`
- `GET /sales/orders/{id}/archive/latest/preview`
- `GET /sales/orders/{id}/archive/latest/download`
- `POST /sales/orders/archives/batch-download`

采购订单：

- `POST /purchase/orders/{id}/archive`
- `GET /purchase/orders/{id}/archive/latest/preview`
- `GET /purchase/orders/{id}/archive/latest/download`
- `POST /purchase/orders/archives/batch-download`

也可以抽象成通用接口：

- `POST /document-archives/{document_type}/{business_id}/generate`
- `GET /document-archives/{document_type}/{business_id}/latest`
- `POST /document-archives/batch-download`

第一版建议后端服务层通用，路由层可以先按销售/采购分别暴露，便于前端调用和权限控制。

## 技术实现建议

### 前端

新增通用单据表单组件：

- `DocumentFormDrawer`
- `DocumentPaper`
- `DocumentGrid`
- `DocumentLineTable`
- `DocumentArchiveActions`

销售订单和采购订单分别提供字段配置，不建议完全硬编码到一个巨大组件里。

### 后端

新增归档服务：

- 收集业务数据。
- 渲染 HTML 模板。
- 生成 PDF。
- 写入归档记录。
- 提供预览、下载、批量 zip。

PDF 生成建议后端完成，不能只依赖浏览器 `window.print()`。

### 文件存储

第一版可以先存在服务器本地目录，例如：

- `outputs/document_archives/sales_order/`
- `outputs/document_archives/purchase_order/`

后续正式环境再迁移到对象存储也可以。

## 风险与边界

1. 这次不是全系统单据化，只试点销售订单和采购订单。
2. 不改变销售订单、采购订单现有业务字段和计算逻辑。
3. 不把合同生成逻辑和单据归档混在一起。合同是对外合同，订单归档是内部业务原始单据。
4. PDF 归档失败不能阻断核心业务保存，但必须明确提醒并允许补生成。
5. 真实纸张效果要服务阅读，不能为了拟物牺牲表格清晰度。

## 验收标准

1. 新增销售订单页面不再是卡片堆叠，而是 v3 风格单据填写。
2. 新增采购订单页面不再是卡片堆叠，而是 v3 风格单据填写。
3. 保存销售订单后生成 PDF 归档记录。
4. 保存采购订单后生成 PDF 归档记录。
5. 销售订单列表可预览、下载、批量下载归档 PDF。
6. 采购订单列表可预览、下载、批量下载归档 PDF。
7. PDF 归档中显示单据编号、公司名、关键抬头、明细、汇总、制单信息。
8. PDF 主归档、Word 辅助导出的规则在代码和界面文案中保持一致。

## 设计结论

采用方案 B 作为第一版试点：

- 销售订单、采购订单先单据化。
- 使用 v3 工厂联单/归档单视觉方向。
- PDF 作为主归档。
- Word 作为后续按需辅助导出。
- 归档能力做成通用底座，后续再推广到其他业务单据。
