diff --git a/changelogs-v2/2026-09/29_proto-align_进项发票登记表单原型对齐与前端自查-修改接口-管理后台.md b/changelogs-v2/2026-09/29_proto-align_进项发票登记表单原型对齐与前端自查-修改接口-管理后台.md new file mode 100644 index 00000000..67d70eb8 --- /dev/null +++ b/changelogs-v2/2026-09/29_proto-align_进项发票登记表单原型对齐与前端自查-修改接口-管理后台.md @@ -0,0 +1,249 @@ +--- +schema: "hl-changelog/v2" +ticket: "proto-align" +title: "进项发票登记表单原型对齐:以既有后端契约为准,附前端实现自查清单" +consumer: "admin" +author: "yst(GIT)" +change_type: "修改接口" +backend_status: "not_required" +gateway_status: "not_required" +frontend_status: "required" +frontend_owner: "" +frontend_ref: "" +target_release: "" +verified_at: "" +status_note: "后端收票(进项发票)接口(/admin/finance/invoice-in/*,#7857 已于 2026-09-17 上线并部署)入参/出参/枚举/错误码零改动。本文档非接口变更,是【原型稿纠偏 + 前端实现自查单】:财务域原型稿「登记进项发票」弹窗此前画成简化版(关联团号自由文本 + 缺发票类型/发票代码/收票日期/税率/发票影像),与真实后端契约不符,已修订原型对齐。请前端对照第五节自查清单核对当前已实现表单是否逐项覆盖;前端 2026-09-17 已按契约对接(见 #7857),本单主要用于留档防回归 + 原型稿同步,预计前端零改动。" +updated_at: "2026-09-29" +base: "dev-v3" +--- + +# finance:进项发票登记表单原型对齐(后端接口零改动)(管理后台) + +**服务**: hl-order-service-v3(finance 模块,同进程) +**PR**: 无(原型稿纠偏 + 前端自查单,无后端改动) +**Issue**: 无(原型稿纠偏,无后端改动) +**关联上线单**: #7857 收票(进项发票)域上线(2026-09-17,前端已对接 verified) + +--- + +## 一、接口背景 + +管理后台「发票管理 → 收票(进项)」里,「**登记进项发票**」弹窗用于:已收到供应商发票时直接登记为已收票,挂供应商 + 关联应付/预付单,与已付款勾稽消除进项缺口。 + +后端接口 `POST /admin/finance/invoice-in/create`(及配套 `/biz-candidates`、`/update`)**自 2026-09-17 上线后未曾变更**。 + +本次起因:财务域**原型稿**(`finance-prototype.html`)里的「登记进项发票」弹窗画的是**简化版**——只有一个「关联团号」自由文本框,且缺发票类型 / 发票代码 / 收票日期 / 税率 / 发票影像 5 个字段,与真实后端契约不一致。**前端实际实现并未照此错误原型**(mmg 2026-09-17 已按契约正确对接),但原型稿滞后易误导后续维护 / 新人。现已修订原型对齐契约,并出本单请前端对照自查、留档防回归。 + +--- + +## 二、变更清单 + +| 项 | 变更 | +|---|---| +| 提交接口 `POST /admin/finance/invoice-in/create` | **无变更**(签名 / 字段 / 枚举 / 错误码均未变) | +| `GET /biz-candidates` / `PUT /update` 等其余端点 | **无变更** | +| 原型稿「登记进项发票」弹窗 | **已纠偏**:删「关联团号」自由文本 → 改「关联应付单」多选;补齐发票类型 / 发票代码 / 收票日期 / 税率 / 发票影像;「金额」改标签「价税合计」 | +| 前端实现 | **预期零改动**:本单为自查确认单,请按第五节逐项核对已实现表单 | +| 数据库表 | 零 DDL | + +--- + +## 三、接口详情 + +| 端点 | 方法 | 说明 | +|---|---|---| +| `/admin/finance/invoice-in/create` | POST | 登记进项发票(落 RECEIVED 已收票;可挂多笔应付/预付/费用报销,也可纯挂供应商) | +| `/admin/finance/invoice-in/biz-candidates?supplierId=` | GET | 按供应商捞可勾选业务单据(应付/预付中已生效且未收齐票的,供登记关联勾选) | +| `/admin/finance/invoice-in/update` | PUT | 编辑进项发票(仅 RECEIVED 态;关联走全删重插) | +| `/admin/file/upload/token` + `/admin/file/confirm` | POST | 发票影像上传(OSS 两步:取预签名凭证 → 直传 → 确认,拿 URL 回填 `voucherUrl`) | + +> 完整出入参加 #7857 上线单。本单只列与「登记表单字段对齐」直接相关的入参。 + +--- + +## 四、接口入参 + +### 4.1 `POST /admin/finance/invoice-in/create` 请求体(`InvoiceInCreateReqVO`) + +| 字段 | 类型 | 必填 | 说明 | +|---|---|---|---| +| `invoiceNo` | string | ✅ | 发票号码(≤40;查重锚点,撞号 599401) | +| `invoiceCode` | string | ❌ | 发票代码(纸质票填,电子票可空;≤20) | +| `invoiceType` | string | ✅ | 发票类型(字典 `fin_invoice_in_type`:SPECIAL 专票 / NORMAL 普票 / ELECTRONIC 电子票;≤20) | +| `supplierId` | long | ✅ | 开票供应商 ID(服务端反查落 `supplierName` 快照,前端不传名称) | +| `invoiceAmount` | number | ✅ | **价税合计**(>0,否则 599405) | +| `taxRate` | number | ❌ | 税率%(仅记录,不管进项抵扣) | +| `taxAmount` | number | ❌ | 税额(仅记录) | +| `invoiceDate` | date | ❌ | 开票日期 | +| `receiveDate` | date | ❌ | 收票日期 | +| `voucherUrl` | string | ❌ | 发票影像 URL(OSS 上传后回填;≤500) | +| `remark` | string | ❌ | 备注(≤500) | +| `relations` | array | ❌ | 关联业务源列表(可空=纯挂供应商;见 4.2) | + +### 4.2 `relations[]` 元素(`InvoiceInRelReqVO`) + +| 字段 | 类型 | 必填 | 说明 | +|---|---|---|---| +| `bizType` | string | ✅ | PAYMENT 应付款 / PREPAY 预付款 / EXPENSE 费用报销 | +| `bizId` | long | ✅ | 业务单据 ID(PAYMENT/PREPAY 校验归属本供应商 599407 + 须 APPROVED/PAID 生效态 599412;EXPENSE 仅验存在) | +| `matchAmount` | number | ✅ | 本票对该笔的匹配金额(>0;ΣmatchAmount ≤ invoiceAmount 否则 599406) | + +### 4.3 `GET /biz-candidates?supplierId=` 出参元素(`InvoiceInBizCandidateRespVO`,返回 `List` 非分页) + +| 字段 | 说明 | +|---|---| +| `bizType` / `bizTypeName` | 业务类型 + 中文名(PAYMENT 应付款 / PREPAY 预付款;**EXPENSE 不进候选**) | +| `bizId` | 业务单据 ID | +| `bizNo` | 业务单号(如 FK-20260817-008) | +| `amount` | 单据金额 | +| `matchedAmount` | 已被有效发票匹配金额合计 | +| `remainingAmount` | 剩余可收票金额 = amount − matchedAmount(>0 才返回) | + +> ⚠️ **`biz-candidates` 不返回团号**。候选行只能展示「业务类型 + 单号 + 金额 + 剩余可收票额」;团信息由被挂应付单间接带出,不在进项票上单独录团号。 + +--- + +## 五、前端实现自查清单(请逐项核对已实现表单) + +| # | 契约关键点 | 期望前端行为 | +|---|---|---| +| 1 | **关联维度是「关联业务单据」不是「团号」** | 表单**无团号输入框**;改为「关联应付/预付单」多选:选定 `supplierId` 后调 `/biz-candidates` 拉候选,勾选得 `relations[]`(每笔带 `matchAmount`);换供应商重拉;可不勾 = 纯挂供应商(create 不带 `relations`) | +| 2 | **发票类型必填下拉** | `invoiceType` 走字典 `fin_invoice_in_type`,勿硬编码 | +| 3 | **发票代码可空** | `invoiceCode` 输入框,电子票可空 | +| 4 | **金额字段叫「价税合计」** | 标签为「价税合计(元)」,必填 >0 | +| 5 | **税率 + 税额(金额三角)** | `taxRate` + `taxAmount` 均可空;可在录入层做「价税合计+税率 → 自动反算税额 = 价税合计÷(1+税率)×税率」,税额允许手填覆盖(后端只记录不校验) | +| 6 | **收票日期独立字段** | `receiveDate` 与 `invoiceDate` 分开 | +| 7 | **发票影像走附件上传** | `voucherUrl` 由 OSS 上传(`/admin/file/upload/token` → 直传 → `/admin/file/confirm`)回填 URL,**非手填文本** | +| 8 | **ΣmatchAmount ≤ invoiceAmount** | NForm 预校验,触发后端 599406 时透 message | +| 9 | **编辑态关联全删重插** | update 恒带整包 `relations`;EXPENSE 已挂行只读保留(仅可移除),防全删重插静默清掉 | + +> 前端 2026-09-17 交付记录显示第 1/2/5/8/9 条已落实(详见 #7857 status_note)。请重点复核第 3/4/6/7 条在「登记」「编辑」两个弹窗里是否都已覆盖。 + +--- + +## 六、枚举 / 数据字典 + +### status 单据状态(状态机枚举) +`RECEIVED` 已收票 → `VERIFIED` 已核对;`RECEIVED`/`VERIFIED` → `VOIDED` 已作废(终态,作废原因必填 599408) + +### bizType 业务类型(FinInvoiceInBizTypeEnum) +`PAYMENT` 应付款 / `PREPAY` 预付款 / `EXPENSE` 费用报销 + +### invoiceType 发票类型(数据字典 `fin_invoice_in_type`) +`SPECIAL` 增值税专用发票 / `NORMAL` 增值税普通发票 / `ELECTRONIC` 电子发票(数电票) + +--- + +## 七、错误码 + +| 码 | 含义 | +|---|---| +| 599400 | 进项发票不存在 | +| 599401 | 发票号码重复 | +| 599402/599403/599404 | 非 RECEIVED 态不可编辑 / VERIFIED 不可编辑 / VOIDED 不可编辑 | +| 599405 | 金额非法(invoiceAmount/matchAmount 须 >0) | +| 599406 | ΣmatchAmount 超过价税合计 | +| 599407 | 关联单据不存在或不归属本供应商 | +| 599408 | 作废原因必填 | +| 599409 | 发票类型非法(不在字典取值域) | +| 599410 | 供应商反查失败 | +| 599411 | 同票重复关联同一单据 | +| 599412 | 关联单据非 APPROVED/PAID 生效态 | + +--- + +## 八、示例 + +### 8.1 登记(关联两笔应付单) + +```json +POST /admin/finance/invoice-in/create +{ + "invoiceNo": "032002600199", + "invoiceCode": "", + "invoiceType": "ELECTRONIC", + "supplierId": 1001, + "invoiceAmount": 8960.00, + "taxRate": 6, + "taxAmount": 507.17, + "invoiceDate": "2026-08-19", + "receiveDate": "2026-08-19", + "voucherUrl": "https://files.example.com/uploads/inv_032002600199.pdf", + "remark": "", + "relations": [ + { "bizType": "PAYMENT", "bizId": 9001, "matchAmount": 8960.00 } + ] +} +``` + +### 8.2 边界(纯挂供应商,不关联任何单据) + +```json +POST /admin/finance/invoice-in/create +{ + "invoiceNo": "032002600200", + "invoiceType": "NORMAL", + "supplierId": 1001, + "invoiceAmount": 1200.00 +} +``` + +> 不带 `relations`(或空数组)= 纯挂供应商,不进单据维度勾稽。 + +### 8.3 业务失败(ΣmatchAmount 超票面 → 599406) + +```json +{ "code": 599406, "message": "关联匹配金额合计超过价税合计" } +``` + +--- + +## 九、业务边界 + +- 进项发票只管**票据勾稽**(钱先付、票后到,消除进项缺口),**不管进项税抵扣、不接税务查验**——`taxRate`/`taxAmount` 仅记录,后端不做税额反算与校验(反算若有,纯前端录入体验)。 +- 一张票可挂多笔业务(N:N),允许部分匹配(ΣmatchAmount ≤ invoiceAmount)。 +- EXPENSE(费用报销)无供应商锚点,不进 `/biz-candidates` 候选,但可被 `relations` 挂接(仅验存在)。 +- 作废(VOIDED)为终态不可恢复,作废票匹配额自动释放回可收票池。 + +--- + +## 十、修改前后对比(原型稿) + +| 维度 | 旧原型稿(误) | 修订后原型 / 真实契约(正) | +|---|---|---| +| 关联维度 | 「关联团号」自由文本(如 26-8875) | 「关联应付/预付单」多选(biz-candidates),无团号 | +| 发票类型 | 无 | 必填下拉(字典 fin_invoice_in_type) | +| 发票代码 | 无 | 可空输入框 | +| 金额字段 | 「金额(元)」 | 「价税合计(元)」 | +| 税率 | 无 | 可空,参与税额反算 | +| 收票日期 | 无 | 独立日期字段 | +| 发票影像 | 无 | OSS 附件上传回填 voucherUrl | + +--- + +## 十一、影响评估 / 回滚 + +- 后端接口 / 数据库 / 网关:**零改动**,无需发版、无需回滚。 +- 前端:预期零改动(已按契约对接)。本单为自查 + 留档,若自查发现某弹窗漏了第 3/4/6/7 条字段,补齐即可,不影响已登记数据。 +- 原型稿:已修订对齐,仅文档层面。 + +--- + +## 十二、注意事项 + +- `supplierName` / `bizNo` 由服务端反查 / 回链落快照,前端**不传**名称类字段,传 ID 即可。 +- 长整型 ID(`id`/`supplierId`/`bizId`/`invoiceInId`)JSON 序列化为字符串,前端按字符串处理防精度丢失。 +- 发票影像预览 / 下载走 `/admin/file/{fileId}/preview`、`/admin/file/preview-by-url`(网关已白名单)。 + +--- + +## 十三、关联 / 联系人 + +### 13.1 链接 + +- 关联上线单:`https://git.1814.love/wx/HL/issues/7857`(收票(进项发票)域上线,2026-09-17 前端已对接 verified) +- 本单:无独立 Issue / PR(原型稿纠偏 + 前端自查单) + +### 13.2 联系人 + +- 后端 / 财务域:yst(腰苏图)