调整手工开票Rate校验和夜数派生

This commit is contained in:
andy
2026-07-22 22:59:28 +07:00
parent 5712f03d4f
commit 68ff9e2b38
10 changed files with 226 additions and 21 deletions

View File

@@ -449,6 +449,8 @@ M009 后端 CP2 已实现:页面可不依赖订单或任务,用户手工填
- Company、Attention、Address、Tel、Email 是一组收件方联系人档案,不是五个互相独立字段;选择 Company 后应刷新 Attention 候选,选择 Attention 后应带出 Address、Tel、Email。Booking Date 展示在同一区域,但不属于联系人档案,应作为 `document.booking_date` 独立提交。
- 第一阶段已确认三组客户 / 旅行社种子数据:`LIAN_TAI` / `LIAN TAI TRAVEL (THAILAND) CO., LTD.` + `Khun Ann``QBD` / `Q.B.D. TRAVEL GROUP CO., LTD` + `Jitdanun Panaphuchong``HANATOUR` / `HANATOUR TD CO., LTD.` + 7 个联系人。完整数据以 `docs/project/requirements/M009-manual-invoice-generation-v1.md` 为准。
- Room Type、Room Rate、Extra Bed 建议也预留“选择 + 可手填 / 可覆盖”能力,后续接 PMS 房型、Rate Code 或价格配置。
- Room Rate / 费用明细 Rate 第一阶段只校验必填、数字格式和非负数,允许 `0`Quantity 和 Nights 仍必须大于 `0`
- No.of Night(s) 前端默认按 `Departure Date - Arrival Date` 自动填入第一条费用明细 Night(s),用户手工修改后保留用户输入,不再因日期变化覆盖。
- Amount、Sub-Total、VAT、Total 是只读计算字段;前端可展示预览,但最终金额以后端计算和模板公式为准。
- 酒店名称、Tax ID、法人主体、银行账户、Logo 和固定付款文案不应作为每张 Invoice 的手工输入;第一阶段可由模板或酒店发票配置提供。
- 正式业务生成接口为 `POST /api/reservation/invoices/manual-generations`,需要 Bearer token、酒店访问权和 `RESERVATION_INVOICE_GENERATE` 权限。

View File

@@ -1175,6 +1175,7 @@ POST /api/reservation/invoices/manual-generations
- 如果前端同时传 `task_id``order_id`,必须保证任务属于该订单;后端不一致时返回 `RESERVATION_INVOICE_CONTEXT_MISMATCH`
- `recipient.company_code``recipient.contact_id` 用于表达目录选择结果;`company``attention``address``telephone``email` 是最终用于生成 PDF 的文本值Manual 覆盖时也必须提交。
- 后端需要重新计算金额、VAT 和合计;前端计算只做预览。
- `charges[].rate` 必填且必须是数字,允许 `0`,不能小于 `0``charges[].quantity``charges[].nights` 仍必须大于 `0`
- 后端需要返回可预览 / 下载的 PDF URL。
- `pdf_url` 第一版可作为预览地址;前端会优先用浏览器 `fetch + Blob` 触发下载,避免跨域场景下 `<a download>` 失效。如果 OSS CORS 不允许浏览器读取文件,前端会退回打开 PDF 页面。后续如要求稳定下载体验,建议后端提供带 `Content-Disposition` 的受控下载代理或签名下载 URL。
- 该接口应走 Bearer 登录、酒店访问权和 `RESERVATION_INVOICE_GENERATE` 权限,不走 M008 调试上传 access key。

View File

@@ -135,11 +135,11 @@
| Arrival Date | 日期输入 | 手工填写;任务预填时来自任务字段 |
| Departure Date | 日期输入 | 手工填写;任务预填时来自任务字段 |
| Due Date | 日期输入 | 手工填写;可按酒店付款规则默认生成 |
| Room Rate | 选择 + 可手填 | 第一阶段可手填;后续接 Rate Code / 房价配置 |
| Room Rate | 选择 + 可手填 | 第一阶段可手填;必填且必须是数字,允许 `0`,不能小于 `0`后续接 Rate Code / 房价配置 |
| Room Rate Note | 输入框 | 例如 `includingBF` |
| Extra bed | 选择 + 可手填 | 第一阶段可手填;后续接加床价格配置 |
| No. of Room(s) | 输入框 / 只读派生 | 可由第一条明细同步,也允许手工覆盖 |
| No. of Night(s) | 输入框 / 日期派生 | 可由 Arrival / Departure 派生,也允许手工覆盖 |
| No. of Night(s) | 输入框 / 日期派生 | 前端默认按 `Departure Date - Arrival Date` 自动填入第一条明细 Night(s),用户手工修改后不再覆盖 |
### 4.3 Description & Amount
@@ -148,7 +148,7 @@
| Description | 输入框 | 手工填写;默认可使用 Group Name 或 Booking No |
| Room Types | 选择 + 可手填 | 第一阶段可手填;后续接 PMS 房型目录 |
| Quantity(s) | 数字输入 | 后端要求正数 |
| Rate | 数字输入 | 后端要求正数 |
| Rate | 数字输入 | 后端要求必填、数字且不能小于 `0`,允许 `0` |
| Night(s) | 数字输入 | 后端要求正数 |
| Amount | 只读 | `quantity * rate * nights` |
| Sub-Total | 只读 | 后端按 VAT 规则计算 |