hl-api-changelog/changelogs-v2/2026-06/24_4337_发票管理page-ALL改订单视角-修改接口-管理后台.md

14 KiB

财务发票管理列表 - ALL tab 改订单视角(破坏性变更)

  • 接口GET /v3/admin/order/invoice/page
  • 变更类型:修改接口 破坏性变更tab=ALL 列表语义 + tabCounts.ALL 计数口径均变)
  • 端类型:管理后台
  • 日期2026-06-24
  • Issue#4337
  • PR#4338

1 接口背景

财务发票管理列表原先以发票记录为视角。ALL tab 只返回已有发票记录的订单行,tabCounts.ALL 计数只统计发票记录总数,导致:

  • ALL 数量 < NONE未申请数量,前端展示出现矛盾
  • ALL 列表无法让财务在一个页面纵览所有已完成订单的发票状态

本次将 ALL tab 切换为订单视角:以全部 COMPLETED已完成订单为数据源,有发票的行展示发票字段,无发票的行 status=NONE,对齐前端原型设计。


2 变更清单

# 变更项 变更前 变更后
1 tabCounts.ALL 计数口径 仅统计发票记录数REQUESTED+ISSUED+PUSHED,不含未申请 统计全部 COMPLETED 订单数(含未申请),永远 >= 任何单个 tab
2 tab=ALL 列表数据源 只返回有发票记录的订单行 返回全部 COMPLETED 订单,无发票行 status=NONE
3 titleName/requestedBy 在 ALL/NONE tab 的行为 未定义(可能干扰结果) 静默忽略(两字段仅在 REQUESTED/ISSUED/PUSHED 三个发票视角 tab 生效)

3 接口详情

属性
方法 GET
路径 /v3/admin/order/invoice/page
描述 财务发票管理列表(分页),含 tab 计数与汇总统计
认证 Bearer JWT管理员
幂等性 只读,天然幂等
限流 无特殊限制

4 接口入参

4.1 Query 参数

参数名 类型 必填 说明
tab string 当前 tab,枚举值见第 6 节;默认 ALL
pageNo integer 页码,默认 1
pageSize integer 每页条数,默认 20
keyword string 关键词搜索(订单号 / 产品名 / 联系人),所有 tab 均生效
titleName string 发票抬头名称,仅 REQUESTED/ISSUED/PUSHED tab 生效,ALL/NONE tab 静默忽略
requestedBy string 申请人(定制师),仅 REQUESTED/ISSUED/PUSHED tab 生效,ALL/NONE tab 静默忽略
departureStartDate string 出发日期起,格式 YYYY-MM-DD
departureEndDate string 出发日期止,格式 YYYY-MM-DD

4.2 请求体

GET 接口)


5 出参字段

响应外层结构:

{
  "code": 200,
  "data": {
    "tabCounts": [...],
    "stats": [...],
    "records": [...],
    "total": 0,
    "pageNo": 1,
    "pageSize": 20
  }
}

5.1 tabCounts5 项固定顺序)

字段 类型 说明
code string tab 枚举值(见第 6 节)
name string tab 中文标签
count integer 该 tab 对应的记录数

固定顺序REQUESTED → ISSUED → PUSHED → NONE → ALL

ALL.count 语义已变:现为全部 COMPLETED 订单数(含未申请);之前仅含发票记录数。

5.2 stats4 项固定顺序)

字段 类型 说明
code string 枚举值(见第 6 节)
name string 统计项中文标签
count integer 数量
amount number 金额元,JSON number

固定顺序REQUESTED → ISSUED → PUSHED → CURRENT_MONTH_ISSUED

5.3 records 列表行InvoicePageItemRespVO

字段 类型 说明
id string 发票记录 ID雪花无发票行为 null
orderId string 订单 ID雪花
orderNo string 订单号
productName string 产品名称
tierName string 档期名称
contactName string 联系人姓名
customizerName string 定制师姓名
departureDate string 出发日期,格式 YYYY-MM-DD
adultCount integer 成人数
childCount integer 儿童数
youngChildCount integer 婴幼儿数
invoiceType string 发票类型枚举(见第 6 节);无发票行为 null
invoiceTypeText string 发票类型中文;无发票行为 null
titleType string 抬头类型枚举(见第 6 节);无发票行为 null
titleName string 抬头名称;无发票行为 null
taxNo string 税号;无发票行为 null
amount number 发票金额(元);无发票行为 null
email string 接收邮箱;无发票行为 null
status string 发票状态枚举(见第 6 节);无发票行固定为 NONE
statusText string 发票状态中文;无发票行固定为 未申请
requestedBy string 申请人(定制师);无发票行为 null
requestedAt string 申请时间 ISO 8601;无发票行为 null
issuedAt string 开票时间 ISO 8601;无发票行为 null
issuedBy string 开票人;无发票行为 null
invoiceNo string 发票号;无发票行为 null
fileUrl string 发票文件 URL;无发票行为 null
pdfName string PDF 文件名;无发票行为 null
pdfSize string PDF 文件大小(字符串,如 128KB;无发票行为 null

6 枚举 / 数据字典

6.1 tab 枚举(查询参数 & tabCounts.code

code name 说明
REQUESTED 待开票 已申请、待财务开票
ISSUED 待推送 已开票、待推送给客户
PUSHED 已推送 已推送给客户
NONE 未申请 已完成订单但尚未申请发票
ALL 全部 订单视角:全部 COMPLETED 订单(含无发票行)

6.2 stats.code 枚举

code name
REQUESTED 待开票
ISSUED 已开票(待推送)
PUSHED 已推送
CURRENT_MONTH_ISSUED 本月已开票

6.3 发票状态枚举records.status

code statusText 说明
REQUESTED 待开票 已申请
ISSUED 待推送 已开票
PUSHED 已推送 已推送
NONE 未申请 tab=ALL/NONE 时无发票行专用

6.4 发票类型枚举invoiceType

code 说明
ELECTRONIC 电子发票
PAPER 纸质发票

6.5 抬头类型枚举titleType

code 说明
PERSONAL 个人
COMPANY 企业

7 错误码

错误码 含义 前端处理建议
200 成功 正常渲染
401 未认证 跳登录
403 无权限 提示无访问权限
500 服务端异常 通用错误提示

8 示例

8.1 典型成功——tab=ALL,混合行有发票 + 无发票)

请求

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

响应

{
  "code": 200,
  "data": {
    "tabCounts": [
      {"code": "REQUESTED", "name": "待开票", "count": 3,},
      {"code": "ISSUED",    "name": "待推送", "count": 1,},
      {"code": "PUSHED",    "name": "已推送", "count": 5,},
      {"code": "NONE",      "name": "未申请", "count": 12,},
      {"code": "ALL",       "name": "全部",   "count": 21}
    ],
    "stats": [
      {"code": "REQUESTED",            "name": "待开票",     "count": 3,  "amount": 8800.00},
      {"code": "ISSUED",               "name": "已开票",     "count": 1,  "amount": 3200.00},
      {"code": "PUSHED",               "name": "已推送",     "count": 5,  "amount": 15600.00},
      {"code": "CURRENT_MONTH_ISSUED", "name": "本月已开票", "count": 4,  "amount": 12000.00}
    ],
    "records": [
      {
        "id": "1923456789012345678",
        "orderId": "1823456789012345678",
        "orderNo": "HL20260620001",
        "productName": "云南深度游7日",
        "tierName": "2026-07-01班期",
        "contactName": "张三",
        "customizerName": "李定制",
        "departureDate": "2026-07-01",
        "adultCount": 2,
        "childCount": 1,
        "youngChildCount": 0,
        "invoiceType": "ELECTRONIC",
        "invoiceTypeText": "电子发票",
        "titleType": "COMPANY",
        "titleName": "北京科技有限公司",
        "taxNo": "91110000123456789X",
        "amount": 6800.00,
        "email": "finance@example.com",
        "status": "REQUESTED",
        "statusText": "待开票",
        "requestedBy": "李定制",
        "requestedAt": "2026-06-20T10:30:00+08:00",
        "issuedAt": null,
        "issuedBy": null,
        "invoiceNo": null,
        "fileUrl": null,
        "pdfName": null,
        "pdfSize": null
      },
      {
        "id": null,
        "orderId": "1823456789012345679",
        "orderNo": "HL20260619002",
        "productName": "西藏圣地朝圣8日",
        "tierName": "2026-06-25班期",
        "contactName": "王五",
        "customizerName": "赵定制",
        "departureDate": "2026-06-25",
        "adultCount": 4,
        "childCount": 0,
        "youngChildCount": 0,
        "invoiceType": null,
        "invoiceTypeText": null,
        "titleType": null,
        "titleName": null,
        "taxNo": null,
        "amount": null,
        "email": null,
        "status": "NONE",
        "statusText": "未申请",
        "requestedBy": null,
        "requestedAt": null,
        "issuedAt": null,
        "issuedBy": null,
        "invoiceNo": null,
        "fileUrl": null,
        "pdfName": null,
        "pdfSize": null
      }
    ],
    "total": 21,
    "pageNo": 1,
    "pageSize": 20
  }
}

8.2 边界情况——tab=ALL 传了 titleName被静默忽略

请求

GET /v3/admin/order/invoice/page?tab=ALL&titleName=北京科技&pageNo=1&pageSize=20

说明titleName 参数不参与过滤,接口正常返回全量 COMPLETED 订单分页。records 中仍会出现 status=NONE 的无发票行,响应结构与 8.1 相同,此处不重复。

8.3 业务失败——无已完成订单时 tab=ALL 返回空列表

请求

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

响应(无 COMPLETED 订单时)

{
  "code": 200,
  "data": {
    "tabCounts": [
      {"code": "REQUESTED", "name": "待开票", "count": 0},
      {"code": "ISSUED",    "name": "待推送", "count": 0},
      {"code": "PUSHED",    "name": "已推送", "count": 0},
      {"code": "NONE",      "name": "未申请", "count": 0},
      {"code": "ALL",       "name": "全部",   "count": 0}
    ],
    "stats": [
      {"code": "REQUESTED",            "name": "待开票",     "count": 0, "amount": 0},
      {"code": "ISSUED",               "name": "已开票",     "count": 0, "amount": 0},
      {"code": "PUSHED",               "name": "已推送",     "count": 0, "amount": 0},
      {"code": "CURRENT_MONTH_ISSUED", "name": "本月已开票", "count": 0, "amount": 0}
    ],
    "records": [],
    "total": 0,
    "pageNo": 1,
    "pageSize": 20
  }
}

9 业务边界

适用

  • 订单状态为 COMPLETED已完成的订单才出现在 ALL/NONE tab
  • REQUESTED/ISSUED/PUSHED 三个 tab 仍以发票记录为视角,只返回有对应状态发票的订单行

不适用

  • 进行中(未完成)订单不出现在任何 tab
  • 已取消订单不出现

特殊边界

  • ALL tab 下tabCounts.ALL.count = REQUESTED + ISSUED + PUSHED + NONE,四者无重叠
  • 同一订单只有一张有效发票记录,不会重复出现
  • titleName/requestedBy 在 ALL/NONE tab 传入后静默忽略,不报错、不影响结果

10 修改前后对比

字段级对比

字段 变更前 变更后
tabCounts.ALL.count 仅 REQUESTED+ISSUED+PUSHED 发票记录数之和 全部 COMPLETED 订单数(含无发票订单)
recordstab=ALL 时) 仅返回有发票记录的订单行,无 status=NONE 行 返回全部 COMPLETED 订单,无发票行 status=NONE
records[].idtab=ALL 时) 所有行均有值 无发票行为 null
records[].amounttab=ALL 时) 所有行均有值 无发票行为 null

tab=ALL 计数对比(假设 2 张发票 + 12 个未申请)

变更前:

ALL.count = 2   仅发票记录,ALL < NONE,矛盾
NONE.count = 12

变更后:

ALL.count = 14  = 2 + 12,ALL >= NONE,正确
NONE.count = 12

11 影响评估 / 回滚

破坏兼容性:是

  • 前端若假设 tab=ALL 列表行的 id 一定不为 null,需修改无发票行 id 为 null
  • 前端若用 id !== null 判断是否显示开票按钮,需改为判断 status 是否为 NONE
  • tabCounts.ALL.count 现在总是 >= 之前的值,若前端有基于此的断言需同步更新
  • stats 块不受影响,无需改动

前端同步上线:建议与本次后端部署同期上线,避免显示数据矛盾窗口期。

回滚方案:回滚后端至上一个版本 jar 即可恢复旧行为;若前端已适配新结构则需同步回滚前端。


12 注意事项

  1. 无发票行的 id 字段为 null,前端不可用 id 做有无发票判断,应改用 status 字段值是否为 NONE。
  2. amount 字段类型为 JSON number,不是字符串,渲染时直接用数值格式化。
  3. titleName/requestedBy 在 ALL/NONE tab 下静默忽略,搜索框可保留,后端不过滤,行为符合预期。
  4. stats 块不受 tab 切换影响,始终返回全局四项汇总统计,与当前 tab 无关。
  5. tabCounts 固定 5 项、顺序不变,前端可按 code 匹配或按索引渲染。

13 关联 / 联系人