# 发票财务列表 - 未申请 Tab 与列表行订单信息补齐（管理后台）

> Issue: [#4228](https://git.1814.love:8443/wx/HL/issues/4228) / [#4229](https://git.1814.love:8443/wx/HL/issues/4229)
> PR: [#4233](https://git.1814.love:8443/wx/HL/pulls/4233) / [#4235](https://git.1814.love:8443/wx/HL/pulls/4235)
> 日期: 2026-06-22
> 服务: hl-order-service-v3（invoice 域）
> 端类型: 管理后台

---

## 1. 接口背景

发票财务管理列表（GET /v3/admin/order/invoice/page）本次做两处补齐：

1. **NONE Tab（未申请）**：新增 tab 可选值 NONE，返回「已完成（COMPLETED）且尚无有效发票」的订单列表，作为财务「代客申请」入口的候选。NONE Tab 下每行是「订单维度」，发票相关字段均为空，status 固定返回 NONE、statusText 固定返回「未申请」。
2. **列表行补订单冗余信息**：所有 Tab 下的列表行新增 5 个订单展示字段（产品名、档位名、客户名、定制师名、出发日期），供列表直接渲染，无需二次请求。另，orderNo（订单号）字段此前已定义但未正确回填，本次修复。
3. **tabCounts 新增 noneCount**：Tab 计数对象新增 noneCount 字段，表示「已完成且无发票」的订单数；allCount 含义不变（仍为 requested + issued + pushed 之和，不含 none）。

关联 PR #4233 修复 orderNo 回填 + 新增 5 个订单字段；PR #4235 新增 NONE Tab 查询与 noneCount 统计。

---

## 2. 变更清单

| # | 接口 | 变更类型 | 说明 |
|---|------|----------|------|
| 1 | GET /v3/admin/order/invoice/page | 修改接口 | 入参 tab 新增可选值 NONE |
| 2 | GET /v3/admin/order/invoice/page | 修改接口 | 出参 records[] 新增 5 个字段（productName / tierName / contactName / customizerName / departureDate） |
| 3 | GET /v3/admin/order/invoice/page | 修改接口 | 出参 records[].orderNo 字段由恒 null 修复为正确回填 |
| 4 | GET /v3/admin/order/invoice/page | 修改接口 | 出参 tabCounts 新增 noneCount 字段 |
---

## 3. 接口详情

**接口**：GET /v3/admin/order/invoice/page
**功能描述**：发票管理分页列表，含 Tab 过滤、统计数据与关键词搜索。
**认证**：管理后台 JWT，Header 携带 Authorization: Bearer <token>。
**请求方式**：GET，参数均以 Query String 传入。
**幂等性**：只读查询，天然幂等。
**限流**：网关全局限流，无接口级特殊限流。

---

## 4. 接口入参

### 4.1 路径参数 / Query 参数

| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| page | Integer | 否 | 页码，默认 1 |
| pageSize | Integer | 否 | 每页条数，默认 20 |
| tab | String | 否 | Tab 过滤，默认 ALL；本次新增可选值 NONE，见 6 节枚举 |
| keyword | String | 否 | 关键词搜索（发票号 / 申请人）；NONE Tab 下该参数暂不生效 |
| startDate | String | 否 | 申请开始日期，格式 yyyy-MM-dd；NONE Tab 下暂不生效 |
| endDate | String | 否 | 申请结束日期，格式 yyyy-MM-dd；NONE Tab 下暂不生效 |

### 4.2 请求体字段

GET 接口无请求体。
---

## 5. 出参字段

**响应结构**（Result<PageResult<InvoicePageItemRespVO>>）：

| 字段 | 类型 | 说明 |
|------|------|------|
| records | Array | 发票 / 订单列表（见下方单条字段表） |
| total | Long | 总记录数 |
| page | Integer | 当前页码 |
| pageSize | Integer | 每页条数 |
| tabCounts | Object | 各 Tab 计数，见下方 tabCounts 字段表 |
| stats | Object | 当月统计（currentMonthIssuedCount / currentMonthIssuedAmount） |

**records 单条字段**（含本次新增字段，标注 NEW）：

| 字段 | 类型 | 说明 |
|------|------|------|
| id | String | 发票 ID（Long 序列化）；NONE Tab 下为 null |
| orderId | String | 所属订单 ID（Long 序列化） |
| orderNo | String | 订单号（此前未回填，本次修复） |
| productName | String | 产品名 [NEW] |
| tierName | String | 档位名 [NEW] |
| contactName | String | 客户名（订单联系人） [NEW] |
| customizerName | String | 定制师名 [NEW] |
| departureDate | String | 出发日期，格式 yyyy-MM-dd [NEW] |
| status | String | 发票状态枚举，见 6 节；NONE Tab 下固定返回 NONE |
| statusText | String | 发票状态中文名；NONE Tab 下固定返回「未申请」 |
| amount | String | 开票金额（字符串，单位元）；NONE Tab 下为 null |
| invoiceType | String | 发票类型枚举；NONE Tab 下为 null |
| invoiceTypeName | String | 发票类型中文名；NONE Tab 下为 null |
| titleType | String | 抬头类型；NONE Tab 下为 null |
| title | String | 发票抬头；NONE Tab 下为 null |
| taxNo | String | 税号；NONE Tab 下为 null |
| fileUrl | String | 发票 PDF 地址；NONE Tab 下为 null |
| pdfName | String | PDF 文件名；NONE Tab 下为 null |
| pdfSize | Long | PDF 文件大小（字节）；NONE Tab 下为 null |
| invoiceNo | String | 发票号码；NONE Tab 下为 null |
| issuedAt | String | 开票时间（ISO 8601）；NONE Tab 下为 null |
| issuedBy | String | 开票人姓名；NONE Tab 下为 null |
| requestedAt | String | 申请时间（ISO 8601）；NONE Tab 下为 null |
| requestedBy | String | 申请人；NONE Tab 下为 null |
| createTime | String | 记录创建时间；NONE Tab 下为 null |

**tabCounts 字段**（含本次新增字段，标注 NEW）：

| 字段 | 类型 | 说明 |
|------|------|------|
| requestedCount | Integer | 待开票数量 |
| issuedCount | Integer | 已开票数量 |
| pushedCount | Integer | 已推送数量 |
| allCount | Integer | 全部（= requested + issued + pushed，不含 none） |
| noneCount | Integer | 未申请（已完成订单无发票）数量 [NEW] |
---

## 6. 枚举 / 数据字典

**Tab 过滤值（入参 tab 字段）**

| 值 | 说明 |
|----|------|
| ALL | 全部（默认），仅含有发票记录的数据 |
| REQUESTED | 仅待开票 |
| ISSUED | 仅已开票 |
| PUSHED | 仅已推送 |
| NONE | 未申请（已完成订单且无发票）[NEW] |

**InvoiceStatus - 发票状态（records[].status）**

| 枚举值 | 中文名 | 说明 |
|--------|--------|------|
| REQUESTED | 待开票 | 用户 / 定制师已申请，等待财务处理 |
| ISSUED | 已开票 | 财务已完成开票并上传 PDF |
| PUSHED | 已推送 | 发票已推送给客户 |
| VOIDED | 已作废 | 发票已作废 |
| NONE | 未申请 | 仅 NONE Tab 下返回，表示该订单尚无发票 [NEW] |

**InvoiceType - 发票类型**

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

---

## 7. 错误码

本次修改为纯出参扩展与入参新增可选值，无新增错误码。已有行为：

| 情况 | 行为 |
|------|------|
| tab 传入非法枚举值（如 tab=INVALID） | HTTP 400 参数校验错误 |
---

## 8. 示例

### 8.1 典型成功：ALL Tab 列表（含新增 5 个订单字段）

请求：



响应：


### 8.2 边界情况：NONE Tab（代客申请候选列表，发票字段全 null）

请求：



响应（NONE Tab 下发票相关字段均为 null，id 为 null，status 固定 NONE）：



### 8.3 业务失败：tab 传入非法枚举值

请求：



响应：


---

## 9. 业务边界

**适用：**
- 财务人员查看所有发票记录，按 Tab 分类处理
- NONE Tab：列出已完成（COMPLETED）且尚未申请发票的订单，财务可点击「代客申请」按钮（调 POST /v3/admin/order/{orderId}/invoice/apply，该接口本次未变更）

**不适用：**
- NONE Tab 不展示非 COMPLETED 订单（如 CUSTOMIZING、PAID、TRAVELLING 等状态的订单不出现在 NONE Tab）
- VOIDED 发票不算有效发票，该订单仍可出现在 NONE Tab（后端实现口径以实测为准）

**特殊边界：**
- NONE Tab 下 keyword（关键词）与 startDate / endDate（日期范围）参数暂不生效，传了也不做过滤
- noneCount 不计入 allCount；两者相互独立，前端 Tab 计数需分别展示
- NONE Tab 每行「id」字段为 null，前端渲染「代客申请」按钮时须使用 orderId，而非 id

---

## 10. 修改前后对比

**入参 tab 字段变化：**

| tab 可选值 | 变更前 | 变更后 |
|-----------|--------|--------|
| ALL | 支持 | 不变 |
| REQUESTED | 支持 | 不变 |
| ISSUED | 支持 | 不变 |
| PUSHED | 支持 | 不变 |
| NONE | 不存在 | 新增（未申请订单） |

**出参 records[] 字段变化：**

| 字段名 | 变更前 | 变更后 |
|--------|--------|--------|
| orderNo | 有定义但恒 null（bug） | 正确回填订单号 |
| productName | 不存在 | 新增（产品名） |
| tierName | 不存在 | 新增（档位名） |
| contactName | 不存在 | 新增（客户名） |
| customizerName | 不存在 | 新增（定制师名） |
| departureDate | 不存在 | 新增（出发日期，yyyy-MM-dd） |

**出参 tabCounts 字段变化：**

| 字段名 | 变更前 | 变更后 |
|--------|--------|--------|
| requestedCount | 存在 | 不变 |
| issuedCount | 存在 | 不变 |
| pushedCount | 存在 | 不变 |
| allCount | 存在（= requested+issued+pushed） | 不变（仍不含 none） |
| noneCount | 不存在 | 新增（未申请订单数） |
---

## 11. 影响评估 / 回滚

**破坏兼容性：**
- 出参新增字段（productName / tierName / contactName / customizerName / departureDate / noneCount）为纯新增，不破坏旧字段，向后兼容。
- orderNo 由 null 变为有值：如前端已有 null 防护（判 null 不渲染），行为不变；原先已渲染 orderNo 列但始终空白，现在将正常显示。
- tab=NONE 为新可选值；旧版前端不传，不影响现有功能。

**前端同步上线：**
- 新增 NONE Tab 入口与「代客申请」按钮需前端接线，否则 NONE Tab 功能不可见。
- 新增 5 个订单字段可直接接线渲染到列表列，无需二次请求。

**回滚方案：**
回滚后端至旧版本后：新增字段消失、orderNo 重新恒 null、tab=NONE 入参不识别（返回空列表或 400）、noneCount 消失。前端可对缺失字段做 null 防护兜底。

---

## 12. 注意事项

1. NONE Tab 列表行的 id 为 null，前端渲染「代客申请」按钮须用 orderId（Long 序列化字符串）传给 POST /v3/admin/order/{orderId}/invoice/apply。
2. departureDate 类型为字符串，格式固定 yyyy-MM-dd，前端直接展示，无需额外格式化。
3. noneCount 与 allCount 互不包含，前端 Tab 头需分别渲染。
4. NONE Tab 暂不支持 keyword / startDate / endDate 过滤；前端可在 NONE Tab 时隐藏对应搜索框，或保留但提示「当前 Tab 不支持筛选」。
5. orderNo 恒 null 为历史 bug，本次修复后所有 Tab 下均有值；原先前端若有「有 orderNo 才渲染」的逻辑可直接保留，无需改动。
6. amount 等金额字段均为 String 类型，前端须按字符串接收，避免 JS 大数精度丢失。

---

## 13. 关联 / 联系人

- Issue（订单字段补齐）: https://git.1814.love:8443/wx/HL/issues/4228
- Issue（NONE Tab）: https://git.1814.love:8443/wx/HL/issues/4229
- PR（订单字段补齐 + orderNo 修复 #4233）: https://git.1814.love:8443/wx/HL/pulls/4233
- PR（NONE Tab + noneCount #4235）: https://git.1814.love:8443/wx/HL/pulls/4235
- 后端负责人: yaosutu