Date: 2026-06-16
范围:客户端前端 UI 不在本期——开票/查询通过 curl/Postman 调 API(/system/userOrder/applyInvoice、/getInvoice);查看/重试/作废通过平台后台 UI。客户端团队后续对接 UI。
手测验收步骤(项目无强制 TDD,按此手测 + 可选单测)。前置:009 已上线(门店 ezPay 已开通启用 + 凭证录入)。
updatesql/sql.md 中 010 段落(建 pos_order_invoice 表 + 菜单权限)。pos_order.state=3、pay_status=1,其所属门店在 009 中 ezpay_status=2 且 is_enabled=1、invoice_exempt=0。cinv.ezpay.com.tw 的商店代号/HashKey/HashIV 已通过 009 录入验证。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)。applyInvoice:{orderId, category:"B2B", buyerName:"某公司", buyerUbn:"12345678"}。buyerUbn:"12A" → 提交前被拦截、不调 ezPay,SC-003 通过。applyInvoice:{orderId, category:"B2C", buyerName, carrierType:"0", carrierNum:"/AB1234+"}。invoice_exempt=1)或 ezPay 未开通/未启用的门店订单调 applyInvoice。getInvoice 返回 invoiceStatus=null,前端不显示入口。SC-002、SC-006 通过。applyInvoice → ezPay 回 Status≠SUCCESS。invoice_status=2 失败、fail_reason 记录原因、订单状态不变。PUT /system/orderInvoice/retry/{orderId}(先恢复正确凭证)→ 重试成功,状态变 1 已开。SC-005 通过。total_amt = amount − freight(不含运费);优惠按比例分摊到各商品明细,ΣItemAmt = total_amt;运费不出现。amount(差额 = 运费)。PUT /system/orderInvoice/invalid/{orderId}(一张本月开具的发票)。invoice_invalid 成功 → invoice_status=3 作废、invalid_time 记录。applyInvoice → 生成新 invoice_number。getInvoice、商家端订单详情、平台后台 list/{orderId} 显示的发票号与状态一致。