# 花店开票列表新增花材款

> 运营后台花店开票列表：开票类型新增花材款（按申请单聚合一行），按类型区分操作按钮，新增花材款关联供应商及订单弹窗

- 类型：前端对接
- 分类：分销开票
- 端：运营后台
- 后端服务：admin
- 状态：已上测
- 测试分支：bulky-test/admin
- 更新：2026-10-28
- 网页版：https://doc.xfun.fun/partner-invoice-admin-flower-api

## 总览

运营后台「花店开票列表」原来只展示平台项（供应链服务费 / 干线物流费 / 平台服务费），本次新增 **花材款**：开票类型筛选加「花材款」，列表里花材款 **按申请单聚合成一行**（一行 = 一次申请里所有供应商的花材款），点操作按钮弹出各供应商明细，再下钻看单个供应商的关联订单和发票。

| # | 接口 | 用途 | 何时调用 |
|----|----|----|----|
| ① | `POST /invoice/manage/partnerPlatform/list` | 花店开票列表 | 进入页面、翻页、切筛选 |
| ② | `POST /invoice/manage/partnerPlatform/flower/supplier/list` | 花材款关联供应商及订单 | 花材款行点「查看供应商及关联订单」 |
| ③ | `POST /invoice/manage/partnerPlatform/order/list` | 关联订单 | 服务费行点「关联订单」；花材款弹窗里点「查看关联订单」 |
| ④ | `POST /invoice/manage/partnerPlatform/sendNo/list` | 关联发货单 | 物流费行点「关联发货单」（不变） |

## 通用约定

- 服务：运营后台 `admin`，路径前缀 `/invoice/manage`；全部 `POST` + JSON，沿用后台登录 token。
- 返回：`{ "code": 0, "msg": "success", "data": … }`；`code != 0` 时 `msg` 直接 toast。
- 分页：入参 `index`（从 1 开始）、`size`；出参 `{ index, size, total, records }`。
- 时间 `yyyy-MM-dd HH:mm:ss`，金额单位元、两位小数。

## 枚举

| 枚举 | 取值 |
|----|----|
| `invoiceItemType` 开票类型 | 0 花材款 · 1 供应链服务费 · 2 干线物流费 · 3 平台服务费 |
| `partnerId` 所属平台 | 0 寻梦批发 · 3 优花速达 · 140 繁花惠 |
| `status` 开票状态 | 0 开票中 · 1 已开票 · 2 已逾期 · 3 已撤销 |

## 页面与接口对应

| 页面元素 | 做法 |
|----|----|
| 开票类型筛选 | 「全部」不传 `invoiceItemType`；「花材款」传 0；其余传 1 / 2 / 3 |
| 列表行类型标签 | 用 `invoiceItemTypeDesc` |
| 「供应商 N 家 · 订单 M 笔」 | `supplierCount`、`orderCount`；平台项 `supplierCount` 固定 1 |
| 操作栏（按 `invoiceItemType` 区分） | 0 花材款 →「查看供应商及关联订单」调 ②，传 `applicationId`；2 物流费 →「关联发货单」调 ④，传 `id`；1 / 3 服务费 →「关联订单」调 ③，传 `id` |
| 花材款弹窗标题区 | ② 返回的 `applicationNo`、`supplierCount`、`orderCount` |
| 弹窗供应商行 | 每行都有「查看关联订单」，调 ③ 传该行 `id`；`invoiceUrl` 有值（已开票）时再加「查看发票」，直接打开该 URL |
| 关联订单弹窗 | ③ 返回的订单号、场次、金额 |

> [!IMPORTANT]
> 花材款行的 `id` 为 **null**，弹窗必须用 `applicationId` 调 ②；不要拿 `id` 调 ③ / ④。

## 接口

### POST /invoice/manage/partnerPlatform/list · 花店开票列表

**变更**：`invoiceItemType` 支持 0 花材款；不传时花材款与平台项一起返回；响应新增 `applicationId`、`supplierCount`

- 平台项（1 / 2 / 3）每张票一行，`id` 为该票 ID。
- 花材款（0）每个申请单一行，`id` 为 null，`requestNo` 为申请单号（INV 开头），金额 / 供应商数 / 订单数为该申请单下各供应商花材款合计（已撤销、已转代开的不计；整单撤销时展示撤销前金额）。
- 花材款行状态沿用申请单状态：申请单已完成 → 已开票；已撤销 → 已撤销；开票中且已过截止时间 → 已逾期；其余 → 开票中。
- 三格汇总金额跟随除状态以外的筛选条件，按每张票自身状态累加，切状态不变。
- 所属平台选「全部」或「寻梦批发」时，花材款会包含普通花店（寻梦批发）的开票申请。

#### 请求参数

| 字段 | 类型 | 必填 | 说明 |
|----|----|----|----|
| `index` | Integer | 否 | 页码，从 1 开始 |
| `size` | Integer | 否 | 每页条数 |
| `searchCount` | Boolean | 否 | 是否统计总数 |
| `invoiceItemType` | Integer | 否 | 开票类型，见枚举 `invoiceItemType`；不传为全部（含花材款） |
| `partnerId` | Integer | 否 | 所属平台，见枚举 `partnerId`；不传为全部 |
| `status` | Integer | 否 | 开票状态，见枚举 `status`；不传为全部 |
| `requestNo` | String | 否 | 申请编号，精确；花材款可输申请单号（INV 开头）或其下任一供应商票据编号（REQ 开头） |
| `titleName` | String | 否 | 发票抬头，模糊 |
| `taxNumber` | String | 否 | 税号，精确 |
| `purchaserPhone` | String | 否 | 花店手机号，精确 |
| `createTimeStart` | LocalDateTime | 否 | 申请时间起 |
| `createTimeEnd` | LocalDateTime | 否 | 申请时间止 |

#### 请求示例

```json
{ "index": 1, "size": 20, "searchCount": true, "invoiceItemType": 0, "partnerId": 140 }
```

#### 响应

| 字段 | 类型 | 说明 |
|----|----|----|
| `invoicingTotalAmount` | BigDecimal | 开票中总金额 |
| `invoicedTotalAmount` | BigDecimal | 已开票总金额 |
| `overdueTotalAmount` | BigDecimal | 已逾期总金额 |
| `total` | Long | 总条数 |
| `records[].id` | Long | 票据 ID；**花材款行为 null** |
| `records[].applicationId` | Long | **新增** 申请单 ID；花材款行调 ② 用 |
| `records[].requestNo` | String | 申请编号；花材款行为申请单号 |
| `records[].invoiceItemType` | Integer | 开票类型，见枚举 `invoiceItemType` |
| `records[].invoiceItemTypeDesc` | String | 开票类型文案 |
| `records[].partnerId` | Integer | 所属平台，见枚举 `partnerId` |
| `records[].platformName` | String | 寻梦批发 / 优花速达 / 繁花惠 |
| `records[].purchaserId` | Long | 花店 ID |
| `records[].purchaserName` | String | 花店名称 |
| `records[].purchaserPhone` | String | 花店手机号 |
| `records[].titleName` | String | 发票抬头 |
| `records[].taxNumber` | String | 税号 |
| `records[].requestAmount` | BigDecimal | 申请开票金额 |
| `records[].supplierCount` | Integer | **新增** 供应商数；平台项固定 1 |
| `records[].orderCount` | Integer | 订单数（去重） |
| `records[].status` | Integer | 开票状态，见枚举 `status` |
| `records[].statusDesc` | String | 状态文案 |
| `records[].invoiceUrl` | String | 发票 URL；**花材款行为 null**，在 ② 里按供应商取 |
| `records[].createTime` | LocalDateTime | 申请时间 |
| `records[].uploadTime` | LocalDateTime | 上传时间；花材款行为各供应商最近一次上传时间 |
| `records[].deadline` | LocalDateTime | 开票截止时间 |

#### 响应示例

```json
{
  "code": 0,
  "msg": "success",
  "data": {
    "index": 1, "size": 20, "total": 2,
    "invoicingTotalAmount": 512.00, "invoicedTotalAmount": 386.50, "overdueTotalAmount": 0.00,
    "records": [
      {
        "id": null, "applicationId": 84, "requestNo": "INV202609301091915567936",
        "invoiceItemType": 0, "invoiceItemTypeDesc": "花材款",
        "partnerId": 140, "platformName": "繁花惠",
        "purchaserId": 999102, "purchaserName": "花语花坊", "purchaserPhone": "18758231160",
        "titleName": "花语花坊（昆明）有限公司", "taxNumber": "91530100MA6P8K2X7L",
        "requestAmount": 386.50, "supplierCount": 3, "orderCount": 12,
        "status": 1, "statusDesc": "已开票", "invoiceUrl": null,
        "createTime": "2026-09-28 09:12:33", "uploadTime": "2026-09-28 09:20:11", "deadline": "2026-10-28 09:12:30"
      },
      {
        "id": 192, "applicationId": 84, "requestNo": "REQ0220260930999025876041",
        "invoiceItemType": 1, "invoiceItemTypeDesc": "供应链服务费",
        "partnerId": 140, "platformName": "繁花惠",
        "purchaserId": 999102, "purchaserName": "花语花坊", "purchaserPhone": "18758231160",
        "titleName": "花语花坊（昆明）有限公司", "taxNumber": "91530100MA6P8K2X7L",
        "requestAmount": 23.00, "supplierCount": 1, "orderCount": 7,
        "status": 0, "statusDesc": "开票中", "invoiceUrl": null,
        "createTime": "2026-09-28 09:12:33", "uploadTime": null, "deadline": "2026-10-28 09:12:30"
      }
    ]
  }
}
```

#### 错误码 / 失败文案

| msg | 触发场景 | 前端处理 |
|----|----|----|
| 开票类型参数错误 | `invoiceItemType` 不在 0~3 | 检查传参 |
| 开始时间不能大于结束时间 | 时间区间颠倒 | toast |

### POST /invoice/manage/partnerPlatform/flower/supplier/list · 花材款关联供应商及订单

**新增**

花材款行弹窗。列出该申请单下每个供应商的花材款票据；已撤销、已转代开的不展示（整单撤销时展示已撤销的）。

#### 请求参数

| 字段 | 类型 | 必填 | 说明 |
|----|----|----|----|
| `id` | Long | 是 | 列表 `records[].applicationId` |

#### 请求示例

```json
{ "id": 84 }
```

#### 响应

| 字段 | 类型 | 说明 |
|----|----|----|
| `applicationNo` | String | 申请单号 |
| `supplierCount` | Integer | 供应商数 |
| `orderCount` | Integer | 订单数（去重） |
| `supplierList[].id` | Long | 该供应商票据 ID，「查看关联订单」调 ③ 传此值 |
| `supplierList[].supplierId` | Long | 供应商 ID |
| `supplierList[].supplierName` | String | 供应商名称 |
| `supplierList[].amount` | BigDecimal | 待开票金额 |
| `supplierList[].orderCount` | Integer | 订单数 |
| `supplierList[].status` | Integer | 开票状态，见枚举 `status` |
| `supplierList[].statusDesc` | String | 状态文案 |
| `supplierList[].invoiceUrl` | String | 发票 URL，仅已开票时有值；有值才展示「查看发票」 |

#### 响应示例

```json
{
  "code": 0,
  "msg": "success",
  "data": {
    "applicationNo": "INV202609301091915567936",
    "supplierCount": 3,
    "orderCount": 12,
    "supplierList": [
      { "id": 189, "supplierId": 25563, "supplierName": "昆明斗南花卉产业有限公司", "amount": 186.00, "orderCount": 5, "status": 1, "statusDesc": "已开票", "invoiceUrl": "https://xunmeng-oss.oss-cn-hangzhou.aliyuncs.com/invoice/189.pdf" },
      { "id": 190, "supplierId": 18820, "supplierName": "云南花语供应链有限公司", "amount": 128.50, "orderCount": 4, "status": 0, "statusDesc": "开票中", "invoiceUrl": null },
      { "id": 191, "supplierId": 30215, "supplierName": "广州花材集采中心", "amount": 72.00, "orderCount": 3, "status": 0, "statusDesc": "开票中", "invoiceUrl": null }
    ]
  }
}
```

#### 错误码 / 失败文案

| msg | 触发场景 | 前端处理 |
|----|----|----|
| 信息不存在 | 申请单 ID 不存在（多半是误传了 `id` 而不是 `applicationId`） | 检查传参 |

### POST /invoice/manage/partnerPlatform/order/list · 关联订单

**变更**：原来只支持供应链服务费、平台服务费，现在也支持花材款单个供应商的票据

- 服务费行：传列表 `records[].id`，返回该票关联订单。
- 花材款：传 ② 的 `supplierList[].id`，返回该供应商在本申请单里的订单。

#### 请求参数

| 字段 | 类型 | 必填 | 说明 |
|----|----|----|----|
| `id` | Long | 是 | 票据 ID：服务费行用列表 `records[].id`，花材款用 ② 的 `supplierList[].id` |

#### 请求示例

```json
{ "id": 189 }
```

#### 响应

| 字段 | 类型 | 说明 |
|----|----|----|
| `[].orderSn` | String | 订单编号 |
| `[].roundNo` | String | 场次 |
| `[].amount` | BigDecimal | 该订单对应金额 |

#### 响应示例

```json
{
  "code": 0,
  "msg": "success",
  "data": [
    { "orderSn": "20260722999025682363", "roundNo": "2026-07-22", "amount": 2.00 },
    { "orderSn": "20260810999025735072", "roundNo": "2026-08-11", "amount": 7.00 }
  ]
}
```

#### 错误码 / 失败文案

| msg | 触发场景 | 前端处理 |
|----|----|----|
| 该开票记录不是花材款/供应链服务费/平台服务费类型 | 传了物流费票据 ID | 物流费改调 ④ |
| 信息不存在 | 票据 ID 不存在 | 检查传参 |

### POST /invoice/manage/partnerPlatform/sendNo/list · 关联发货单

**不变**

仅物流费行（`invoiceItemType` = 2）使用，传列表 `records[].id`。返回 `[].sendNo` 发货单号、`[].roundNo` 场次、`[].expressName` 物流商（多个逗号分隔）、`[].amount` 该发货单物流费合计、`[].orderCount` 订单数。

## 联调注意

- 测试环境：`bulky-test/admin` 已部署（2026-10-28）。
- 测试库已有繁花惠申请单，例如申请单 ID 84（`INV202609301091915567936`），可用 `invoiceItemType: 0, partnerId: 140` 查到花材款行。

> [!WARNING]
> 花材款行和平台项行的 `id` 含义不同：花材款行 `id` 为 null、用 `applicationId`；弹窗里的供应商行 `id` 才是票据 ID。按钮取值别混用。
