hl-api-changelog/changelogs-v2/2026-06/21_4172_4173_发票财务开票闭环+定制师代申请-新增接口-管理后台.md

12 KiB

发票补齐 - 财务开票闭环 + 定制师代申请(管理后台)

Issue: #4172 / #4173 PR: #4179 / #4180 日期: 2026-06-21 服务: hl-order-service-v3invoice 域) 端类型: 管理后台


1. 接口背景

order-v3 发票模块此前缺少财务侧开票操作和定制师代客申请入口。本次补齐:

  • 财务开票闭环PR2 / Issue #4172财务人员上传发票 PDF 至 OSS,完成开票REQUESTED 变 ISSUED,支持重新上传覆盖;以及发票管理列表分页 + Tab 统计 + 当月金额统计 + 关键词搜索)。
  • 定制师代客申请PR3 / Issue #4173定制师代用户提交开票申请,门槛与小程序端统一订单 COMPLETED + 一单一票 + 申请金额不超订单总价)。
  • 已有接口字段补全GET /v3/admin/order/{id}/invoices 出参补充 8 个原来恒为 null 的字段。

2. 变更清单

# 接口 变更类型 说明
1 POST /v3/admin/order/invoice/upload 新增接口 财务上传发票文件至 OSS,返回 fileUrl不绑定发票记录
2 PUT /v3/admin/order/invoice/{id}/issue 新增接口 完成开票,状态 REQUESTED 变 ISSUED
3 PUT /v3/admin/order/invoice/{id}/reupload 新增接口 重新上传覆盖文件ISSUED / PUSHED 均可)
4 GET /v3/admin/order/invoice/page 新增接口 发票管理列表(分页 + Tab 计数 + 当月统计 + 搜索)
5 POST /v3/admin/order/{orderId}/invoice/apply 新增接口 定制师代客申请开票
6 GET /v3/admin/order/{id}/invoices已有 修改接口(字段补全) 出参新增fileUrl / pdfName / pdfSize / invoiceNo / issuedAt / issuedBy / requestedAt / requestedBy

3. 接口详情

认证:所有接口走管理后台 JWT,Header 携带 Authorization: Bearer token。upload 使用 multipart/form-data,其余 application/json。 幂等性upload 每次生成新 OSS 文件,无幂等。issue / reupload 依赖发票状态守卫,状态不符报业务错误。 限流:网关全局限流,无接口级特殊限流。


4. 接口入参

4.1 路径参数 / Query 参数

接口 参数名 类型 必填 说明
PUT /issue/{id} id Long 发票记录 ID
PUT /reupload/{id} id Long 发票记录 ID
GET /page page Integer 页码,默认 1
GET /page pageSize Integer 每页条数,默认 20
GET /page tab String Tab 过滤,见 6 节,默认 ALL
GET /page keyword String 关键词搜索(发票号 / 申请人)
GET /page startDate String 申请开始日期 yyyy-MM-dd
GET /page endDate String 申请结束日期 yyyy-MM-dd
POST /{orderId}/apply orderId Long 路径参数,订单 ID

4.2 请求体字段

POST /v3/admin/order/invoice/upload

字段 类型 必填 说明
file MultipartFile 发票 PDF 文件multipart/form-data

PUT /v3/admin/order/invoice/{id}/issue

字段 类型 必填 说明
fileUrl String upload 接口返回的 OSS 地址
pdfName String PDF 文件名(展示用)
pdfSize Long PDF 文件大小(字节)
invoiceNo String 发票号码

PUT /v3/admin/order/invoice/{id}/reupload

字段 类型 必填 说明
fileUrl String 新发票 PDF 的 OSS 地址
pdfName String 新 PDF 文件名
pdfSize Long 新 PDF 文件大小(字节)

POST /v3/admin/order/{orderId}/invoice/apply

字段 类型 必填 说明
amount String 开票金额(字符串,单位元),不超过订单总价
invoiceType String 发票类型,枚举见 6 节
titleType String 抬头类型PERSONAL / COMPANY
title String 发票抬头(姓名或公司名)
taxNo String 条件必填 税号titleType=COMPANY 时必填)
bankName String 条件必填 开户行invoiceType=VAT_SPECIAL 时必填)
bankAccount String 条件必填 银行账号invoiceType=VAT_SPECIAL 时必填)
registAddress String 条件必填 注册地址invoiceType=VAT_SPECIAL 时必填)
registPhone String 条件必填 注册电话invoiceType=VAT_SPECIAL 时必填)
email String 条件必填 收票邮箱invoiceType=ELECTRONIC 时必填)
remark String 备注

5. 出参字段

POST /v3/admin/order/invoice/upload

字段 类型 说明
data String 上传成功后的 OSS 文件 URL,用于后续 issue / reupload 接口

PUT issue 和 reupload 操作成功返回 HTTP 200,data 为 null。

GET /v3/admin/order/invoice/page

字段 类型 说明
records Array 发票列表(见下表)
total Long 总记录数
page Integer 当前页码
pageSize Integer 每页条数
tabCounts Object 各 Tab 计数requestedCount / issuedCount / pushedCount
stats Object 当月统计currentMonthIssuedCount / currentMonthIssuedAmount

records 单条字段:

字段 类型 说明
id String 发票 IDLong 序列化)
orderId String 所属订单 IDLong 序列化)
status String 发票状态枚举,见 6 节
statusName String 状态中文名
amount String 开票金额(字符串,单位元)
invoiceType String 发票类型枚举
invoiceTypeName String 发票类型中文名
titleType String 抬头类型
title String 发票抬头
taxNo String 税号
fileUrl String 发票 PDF 地址ISSUED / PUSHED 有值,其余 null
pdfName String PDF 文件名
pdfSize Long PDF 文件大小(字节)
invoiceNo String 发票号码
issuedAt String 开票时间ISO 8601
issuedBy String 开票人姓名(财务真实姓名)
requestedAt String 申请时间ISO 8601
requestedBy String 申请人定制师姓名;mp 端为 userId 字符串)
createTime String 记录创建时间

POST /v3/admin/order/{orderId}/invoice/apply

字段 类型 说明
id String 新建发票 IDLong 序列化)
status String 固定为 REQUESTED申请后待开票

GET /v3/admin/order/{id}/invoices已有接口,字段补全

以下字段由恒 null 变为有值fileUrl / pdfName / pdfSize / invoiceNo / issuedAt / issuedBy / requestedAt / requestedBy。字段含义同 /page 出参表。


6. 枚举 / 数据字典

InvoiceStatus - 发票状态

枚举值 中文名 说明
REQUESTED 待开票 用户 / 定制师已申请,等待财务处理
ISSUED 已开票 财务已完成开票并上传 PDF
PUSHED 已推送 发票已推送给客户
VOIDED 已作废 发票已作废

Tab 过滤值GET /page 入参 tab 字段)

说明
ALL 全部(默认)
REQUESTED 仅待开票
ISSUED 仅已开票
PUSHED 仅已推送

InvoiceType - 发票类型

枚举值 中文名
VAT_NORMAL 增值税普通发票
VAT_SPECIAL 增值税专用发票
ELECTRONIC 电子发票

TitleType - 抬头类型

枚举值 中文名
PERSONAL 个人
COMPANY 公司

7. 错误码

错误码 常量 触发场景
581502 INVOICE_CANNOT_ISSUE 发票状态非 REQUESTED,不允许开票
581503 INVOICE_CANNOT_REUPLOAD 发票状态非 ISSUED / PUSHED,不允许重新上传
581504 INVOICE_FILE_UPLOAD_FAILED 文件上传失败OSS 或 hl-user-service 不可用)
581510 INVOICE_ORDER_NOT_COMPLETED 订单状态非 COMPLETED,不可申请开票
581511 INVOICE_ALREADY_EXISTS 该订单已有有效发票,不可重复申请(一单一票)
581512 INVOICE_AMOUNT_EXCEED 开票金额超过订单总价
581513 INVOICE_TYPE_INVALID 发票类型枚举值非法
581514 INVOICE_TAX_NO_REQUIRED 公司抬头 / 专票时税号为必填
581515 INVOICE_VAT_SPECIAL_FIELDS_REQUIRED 专票时开户行 / 银行账号 / 注册地址 / 注册电话为必填
581516 INVOICE_EMAIL_REQUIRED 电子发票时邮箱为必填

8. 示例

8.1 典型成功:财务两步完成开票

Step 1 上传文件:

POST /v3/admin/order/invoice/upload,Content-Type: multipart/form-data,file 字段传 PDF 文件。

响应:

Step 2 完成开票:

PUT /v3/admin/order/invoice/1234567890123456789/issue,请求体

响应:

8.2 边界情况:发票列表 tab=PUSHED 无记录

GET /v3/admin/order/invoice/page?tab=PUSHED&page=1&pageSize=20

响应:

8.3 业务失败:订单未完成,定制师代申请被拒

POST /v3/admin/order/9876543210987654321/invoice/apply,请求体

订单状态为 CUSTOMIZING定制中时,响应


9. 业务边界

适用:

  • 财务开票:发票状态必须为 REQUESTED
  • 重新上传:发票状态为 ISSUED 或 PUSHED
  • 定制师代申请:订单状态必须为 COMPLETED出行结束后

不适用:

  • 订单处于 PAID、CUSTOMIZING、TRAVELLING 等非 COMPLETED 状态
  • 已存在有效发票(一单一票),不可重复申请
  • 开票金额超过订单 orderAmount产品原售价

特殊边界:

  • PUSHED 状态重新上传,状态自动降级为 ISSUED,需重新推送给客户
  • 发票列表 NONE Tab未申请的 COMPLETED 订单)当前未实现,传 tab=NONE 返回空集合

10. 修改前后对比

GET /v3/admin/order/{id}/invoices 出参字段补全:

字段名 变更前 变更后
fileUrl 恒 null ISSUED / PUSHED 时有值OSS URL
pdfName 恒 null 有值
pdfSize 恒 null 有值(字节数)
invoiceNo 恒 null 有值(发票号码)
issuedAt 恒 null 有值ISO 8601 时间戳)
issuedBy 恒 null 有值(开票人姓名)
requestedAt 恒 null 有值(申请时间)
requestedBy 恒 null 有值(申请人姓名)

11. 影响评估 / 回滚

  • 破坏兼容性GET /{id}/invoices 字段由 null 变为有值,前端对 null 的防护代码可安全保留。新增 5 个接口对旧版本无影响。
  • 前端同步上线:无强制要求,新接口按需接线,/invoices 字段补全向后兼容。
  • 回滚方案:回滚旧版本,新接口返回 404,/invoices 出参回退为 null,已写入 DB 的开票信息保留不丢失。

12. 注意事项

  1. upload 接口仅上传,不绑定发票:返回的 fileUrl 须在调用 issue / reupload 时传入,否则 OSS 文件闲置。
  2. PUSHED 状态重新上传后降级为 ISSUED,前端应提示操作者需要重新推送给客户。
  3. 专票五项taxNo / bankName / bankAccount / registAddress / registPhone缺任一即报 581515。
  4. requestedBy 记录的是登录管理员真实姓名(来自网关注入的 X-Admin-RealName,不是用户姓名。
  5. amount、currentMonthIssuedAmount 均为 String 类型,前端须按字符串接收,避免 JS 大数精度丢失。

13. 关联 / 联系人