# Quickstart: 订单 ezPay 电子发票开立

**Date**: 2026-06-16

**范围**：客户端前端 UI 不在本期——开票/查询通过 curl/Postman 调 API（`/system/userOrder/applyInvoice`、`/getInvoice`）；查看/重试/作废通过平台后台 UI。客户端团队后续对接 UI。

手测验收步骤（项目无强制 TDD，按此手测 + 可选单测）。前置：009 已上线（门店 ezPay 已开通启用 + 凭证录入）。

## 0. 准备
1. 执行 `updatesql/sql.md` 中 010 段落（建 `pos_order_invoice` 表 + 菜单权限）。
2. 选一个**已完成订单**：`pos_order.state=3`、`pay_status=1`，其所属门店在 009 中 `ezpay_status=2 且 is_enabled=1`、`invoice_exempt=0`。
3. ezPay 测试环境 `cinv.ezpay.com.tw` 的商店代号/HashKey/HashIV 已通过 009 录入验证。

## 1. B2C 个人发票（邮箱）— US1 / SC-001 / SC-004
- 客户端调 `POST /system/userOrder/applyInvoice`：`{orderId, category:"B2C", buyerName, buyerEmail}`。
- **预期**：返回 `invoiceNumber` + 凭证；DB `pos_order_invoice.invoice_status=1`、`invoice_number` 已填、`total_amt/sales_amt/tax_amt` 三栏自洽（`sales+tax=total`）。
- **重复开票**：再调一次 → 拒绝（已开票），SC-004 通过。

## 2. B2B 公司发票（统编）— US2 / SC-003
- `applyInvoice`：`{orderId, category:"B2B", buyerName:"某公司", buyerUbn:"12345678"}`。
- **预期**：开立成功，发票记录买方统编。
- **非法统编**：传 `buyerUbn:"12A"` → 提交前被拦截、不调 ezPay，SC-003 通过。

## 3. 载具（手机条码）— US3
- `applyInvoice`：`{orderId, category:"B2C", buyerName, carrierType:"0", carrierNum:"/AB1234+"}`。
- **预期**：校验条码后开立，发票存入载具（PrintFlag=N）。

## 4. 不可开票门店 — US1-场景2 / SC-002 / SC-006
- 对一个**免用发票**（`invoice_exempt=1`）或 ezPay 未开通/未启用的门店订单调 `applyInvoice`。
- **预期**：拒绝并提示门店暂不支持开票；`getInvoice` 返回 `invoiceStatus=null`，前端不显示入口。SC-002、SC-006 通过。

## 5. 开票失败 + 重试 — US4 / SC-005
- 临时把门店 HashKey 改错 → `applyInvoice` → ezPay 回 `Status≠SUCCESS`。
- **预期**：`invoice_status=2 失败`、`fail_reason` 记录原因、订单状态不变。
- 平台后台 `PUT /system/orderInvoice/retry/{orderId}`（先恢复正确凭证）→ 重试成功，状态变 `1 已开`。SC-005 通过。

## 6. 优惠/运费对账 — D1/D3
- 对一笔**带优惠的外送订单**开票。
- **预期**：发票 `total_amt` = `amount − freight`（不含运费）；优惠按比例分摊到各商品明细，`ΣItemAmt = total_amt`；运费不出现。
- 自查：发票总额 < 订单 `amount`（差额 = 运费）。

## 7. 作废 + 重开 — US5
- 平台后台 `PUT /system/orderInvoice/invalid/{orderId}`（一张本月开具的发票）。
- **预期**：ezPay `invoice_invalid` 成功 → `invoice_status=3 作废`、`invalid_time` 记录。
- 超期作废：对一张不可作废的发票 → 提示不可作废（以 ezPay 返回为准）。
- 重开：作废后客户重新 `applyInvoice` → 生成新 `invoice_number`。

## 8. 三端一致性 — SC-006
- 同一订单：客户端 `getInvoice`、商家端订单详情、平台后台 `list/{orderId}` 显示的发票号与状态一致。

---

## 验收核对（对照 spec Success Criteria）
- [ ] SC-001 客户 1 分钟内 / 3 步完成开票拿到凭证
- [ ] SC-002 不可开票门店 100% 无入口
- [ ] SC-003 非法统编调用前拦截
- [ ] SC-004 无重复发票
- [ ] SC-005 失败可重试成功
- [ ] SC-006 三端发票号/状态一致
