From 1b5719fc1a264037b05c7ea423dc6ab4ad22ea9e Mon Sep 17 00:00:00 2001 From: yaosutu <770858045@qq.com> Date: Tue, 4 Aug 2026 16:27:09 +0800 Subject: [PATCH] =?UTF-8?q?=E9=80=9A=E7=9F=A5=E7=AE=A1=E7=90=86=E5=90=8E?= =?UTF-8?q?=E5=8F=B0=E6=A0=B8=E5=8D=95=E5=85=B6=E4=BB=96=E6=94=B6=E5=85=A5?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=E6=94=B6=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ..._核单其他收入字段收口-修改接口-管理后台.md | 590 ++++++++++++++++++ 1 file changed, 590 insertions(+) create mode 100644 changelogs-v2/2026-08/04_5477_核单其他收入字段收口-修改接口-管理后台.md diff --git a/changelogs-v2/2026-08/04_5477_核单其他收入字段收口-修改接口-管理后台.md b/changelogs-v2/2026-08/04_5477_核单其他收入字段收口-修改接口-管理后台.md new file mode 100644 index 0000000..de09c8a --- /dev/null +++ b/changelogs-v2/2026-08/04_5477_核单其他收入字段收口-修改接口-管理后台.md @@ -0,0 +1,590 @@ +--- +schema: "hl-changelog/v2" +ticket: "5477" +title: "核单其他收入移除项目类别与票种规格字段" +consumer: "admin" +change_type: "修改接口" +author: "yaosutu(GIT)" +backend_status: "deployed" +gateway_status: "verified" +frontend_status: "pending" +frontend_owner: "" +frontend_ref: "" +target_release: "" +verified_at: "2026-08-04" +status_note: "PR #5488 已合并 dev-v3;测试服真实网关已验证 POST 无旧字段成功、PUT 多传旧字段被忽略、GET/POST/PUT 响应均不含 projectCategory/projectCategoryName/specification。前端需删除项目类别与票种规格控件及相关字段读写。" +updated_at: "2026-08-04" +base: "dev-v3" +--- + +# 【⚠️ 修改接口·管理后台】核单其他收入移除项目类别与票种规格字段(#5477) + +> **PR**: [#5488](https://git.1814.love:8443/wx/HL/pulls/5488) | **服务**: hl-order-service-v3 | **更新时间**: 2026-08-04 16:30 + +## 1. 接口背景 + +“其他收入”页签本身已表达项目类型,继续要求填写“项目类别”属于重复信息;“票种/规格”也不适用于其他收入。此次统一收口新增、修改和查询契约,前端应删除这两个控件及相关字段读写。 + +## 2. 变更清单 + +| # | 接口 | 方法 | 路径 | 变更类型 | 前端动作 | +|---|---|---|---|---|---| +| 1 | 查询其他收入核单明细及增减费汇总 | GET | `/v3/admin/order/{orderId}/settlement/other-incomes` | 删除出参字段 | 停止读取 `projectCategory`、`projectCategoryName`、`specification` | +| 2 | 新增其他收入并原子创建订单增费 | POST | `/v3/admin/order/{orderId}/settlement/other-incomes` | 删除入参、出参字段 | 删除项目类别与票种规格控件;停止传两个旧入参 | +| 3 | 修改其他收入 | PUT | `/v3/admin/order/{orderId}/settlement/other-incomes/{incomeId}` | 删除入参、出参字段 | 删除项目类别与票种规格控件;停止传两个旧入参 | + +> DELETE 接口签名与返回结构未变化,不属于本次契约变更。 + +## 3. 接口详情 + +### 3.1 查询其他收入核单明细及增减费汇总 + +- **方法/路径**:`GET /v3/admin/order/{orderId}/settlement/other-incomes` +- **使用场景**:进入其他收入页签,以及新增、修改、删除后刷新明细和汇总。 +- **认证**:需要管理后台登录态;配房角色不可访问。 +- **幂等性**:只读接口,可安全重复调用。 +- **限流**:未声明接口专属限流。 + +**路径参数**: + +| 字段 | 类型 | 必填 | 说明 | 校验 | +|---|---|---:|---|---| +| `orderId` | String(Long) | 是 | 订单 ID | 必须大于 0 | + +**请求体**:无。 + +**成功响应 `data`**: + +| 字段 | 类型 | 可空 | 说明 | +|---|---|---:|---| +| `items` | `OtherIncomeItem[]` | 否 | 其他收入明细;无数据返回 `[]` | +| `deductions` | `Deduction[]` | 否 | 只读减费明细;无数据返回 `[]` | +| `summary` | `Summary` | 否 | 当前有效增减费汇总 | + +`OtherIncomeItem` 完整字段: + +| 字段 | 类型 | 可空 | 说明 | +|---|---|---:|---| +| `id` | String(Long) | 否 | 其他收入 ID | +| `requestId` | String | 是 | 手工新增幂等请求 ID;自动投影时为空 | +| `incomeDate` | LocalDate | 否 | 收入日期,`YYYY-MM-DD` | +| `projectName` | String | 否 | 项目名称 | +| `quantity` | Decimal | 否 | 数量 | +| `unitPrice` | Decimal | 否 | 核算单价 | +| `settlementAmount` | Decimal | 否 | 核算金额 | +| `paymentMethod` | String | 否 | 付款类型,见 §6.1 | +| `paymentMethodName` | String | 否 | 付款类型中文名 | +| `voucherUrls` | String[] | 是 | 凭证 URL 列表 | +| `settlementConfirmStatus` | String | 否 | 确认状态,见 §6.2 | +| `settlementConfirmStatusName` | String | 否 | 确认状态中文名 | +| `remark` | String | 是 | 备注 | +| `sourceType` | String | 否 | 来源类型,见 §6.3 | +| `sourceTypeName` | String | 否 | 来源类型中文名 | +| `sourceId` | String(Long) | 是 | 来源附加费 ID | + +`Deduction` 完整字段: + +| 字段 | 类型 | 可空 | 说明 | +|---|---|---:|---| +| `id` | String(Long) | 否 | 减费 ID | +| `discountName` | String | 否 | 减费名称 | +| `discountAmount` | Decimal | 否 | 减费金额 | +| `sourceType` | String | 是 | 来源类型 | +| `sourceId` | String(Long) | 是 | 来源业务 ID | +| `createdAt` | LocalDateTime | 是 | 创建时间 | + +`Summary` 完整字段: + +| 字段 | 类型 | 说明 | +|---|---|---| +| `surchargeAmount` | Decimal | 有效增费合计 | +| `discountAmount` | Decimal | 有效减费合计 | +| `netAdjustmentAmount` | Decimal | 净调整额,即增费减去减费 | + +**本接口错误码与业务边界**:见 §7、§9;查询不允许再依赖三个已删除字段。 + +**典型成功示例**: + +```http +GET /v3/admin/order/2084000000000002978/settlement/other-incomes +Authorization: Bearer +``` + +```json +{ + "code": 200, + "message": "success", + "data": { + "items": [{ + "id": "2084000000000004978", + "requestId": "oi-5477-0001", + "incomeDate": "2026-08-04", + "projectName": "酒店升级补差", + "quantity": 2, + "unitPrice": 12.34, + "settlementAmount": 24.68, + "paymentMethod": "COMPANY_PAID", + "paymentMethodName": "公司付款", + "voucherUrls": [], + "settlementConfirmStatus": "UNCONFIRMED", + "settlementConfirmStatusName": "未确认", + "remark": null, + "sourceType": "MANUAL", + "sourceTypeName": "手工", + "sourceId": "2084000000000004979" + }], + "deductions": [], + "summary": { + "surchargeAmount": 24.68, + "discountAmount": 0, + "netAdjustmentAmount": 24.68 + } + }, + "success": true +} +``` + +**边界示例(空列表)**: + +```http +GET /v3/admin/order/2084000000000002978/settlement/other-incomes +Authorization: Bearer +``` + +```json +{ + "code": 200, + "message": "success", + "data": { + "items": [], + "deductions": [], + "summary": {"surchargeAmount": 0, "discountAmount": 0, "netAdjustmentAmount": 0} + }, + "success": true +} +``` + +**异常示例(非法订单 ID)**: + +```http +GET /v3/admin/order/0/settlement/other-incomes +Authorization: Bearer +``` + +```json +{"code": 400, "message": "订单 ID 必须大于 0", "data": null, "success": false} +``` + +### 3.2 新增其他收入并原子创建订单增费 + +- **方法/路径**:`POST /v3/admin/order/{orderId}/settlement/other-incomes` +- **使用场景**:核单人员新增一条手工其他收入。 +- **认证**:需要管理后台登录态;仅超级管理员、管理员或财务可写。 +- **幂等性**:`requestId` 是同一订单内永久唯一的稳定幂等键;同一 `requestId` 与相同载荷重试返回同一结果,不同载荷冲突返回 `584087`。 +- **限流**:未声明接口专属限流。 + +**路径参数**:`orderId`,String(Long),必填且必须大于 0。 + +**请求体完整字段**: + +| 字段 | 类型 | 必填 | 校验与说明 | +|---|---|---:|---| +| `requestId` | String | 是 | 最长 64;同订单内永久唯一 | +| `incomeDate` | LocalDate | 是 | `YYYY-MM-DD` | +| `projectName` | String | 是 | 非空,最长 100 | +| `quantity` | Decimal | 是 | ≥0,最多 8 位整数、4 位小数 | +| `unitPrice` | Decimal | 是 | ≥0,最多 8 位整数、2 位小数 | +| `settlementAmount` | Decimal | 是 | ≥0.01,最多 8 位整数、2 位小数;必须等于 `quantity × unitPrice` 四舍五入到 2 位 | +| `paymentMethod` | String | 是 | 见 §6.1 | +| `settlementConfirmStatus` | String | 是 | 新增只能为 `UNCONFIRMED` | +| `voucherUrls` | String[] | 否 | 最多 9 项;每项最长 1024,必须为 `http/https` URL | +| `remark` | String | 否 | 最长 500 | + +**成功响应**:`data` 为 §3.1 的完整 `OtherIncomeItem`;不含 `projectCategory`、`projectCategoryName`、`specification`。 + +**典型成功请求与响应**: + +```http +POST /v3/admin/order/2084000000000002978/settlement/other-incomes +Authorization: Bearer +Content-Type: application/json +``` + +```json +{ + "requestId": "oi-5477-0001", + "incomeDate": "2026-08-04", + "projectName": "酒店升级补差", + "quantity": 2, + "unitPrice": 12.34, + "settlementAmount": 24.68, + "paymentMethod": "COMPANY_PAID", + "settlementConfirmStatus": "UNCONFIRMED", + "voucherUrls": [], + "remark": null +} +``` + +```json +{ + "code": 200, + "message": "success", + "data": { + "id": "2084000000000004978", + "requestId": "oi-5477-0001", + "incomeDate": "2026-08-04", + "projectName": "酒店升级补差", + "quantity": 2, + "unitPrice": 12.34, + "settlementAmount": 24.68, + "paymentMethod": "COMPANY_PAID", + "paymentMethodName": "公司付款", + "voucherUrls": [], + "settlementConfirmStatus": "UNCONFIRMED", + "settlementConfirmStatusName": "未确认", + "remark": null, + "sourceType": "MANUAL", + "sourceTypeName": "手工", + "sourceId": "2084000000000004979" + }, + "success": true +} +``` + +**边界请求与响应(旧字段仍被旧客户端多传)**: + +```json +{ + "requestId": "oi-5477-legacy-0001", + "incomeDate": "2026-08-04", + "projectName": "历史客户端补差", + "projectCategory": "HOTEL", + "specification": "VIP", + "quantity": 1, + "unitPrice": 0.01, + "settlementAmount": 0.01, + "paymentMethod": "CASH_PAID", + "settlementConfirmStatus": "UNCONFIRMED", + "voucherUrls": [] +} +``` + +```json +{ + "code": 200, + "message": "success", + "data": { + "id": "2084000000000004980", + "requestId": "oi-5477-legacy-0001", + "incomeDate": "2026-08-04", + "projectName": "历史客户端补差", + "quantity": 1, + "unitPrice": 0.01, + "settlementAmount": 0.01, + "paymentMethod": "CASH_PAID", + "paymentMethodName": "现付", + "voucherUrls": [], + "settlementConfirmStatus": "UNCONFIRMED", + "settlementConfirmStatusName": "未确认", + "remark": null, + "sourceType": "MANUAL", + "sourceTypeName": "手工", + "sourceId": "2084000000000004981" + }, + "success": true +} +``` + +旧字段会被忽略,响应不会回显。该兼容仅用于过渡;前端仍必须停止发送。 + +**异常请求与响应(缺少确认状态)**: + +```json +{ + "requestId": "oi-5477-invalid-0001", + "incomeDate": "2026-08-04", + "projectName": "无确认状态", + "quantity": 1, + "unitPrice": 10, + "settlementAmount": 10, + "paymentMethod": "CASH_PAID" +} +``` + +```json +{"code": 400, "message": "确认状态不能为空", "data": null, "success": false} +``` + +### 3.3 修改其他收入 + +- **方法/路径**:`PUT /v3/admin/order/{orderId}/settlement/other-incomes/{incomeId}` +- **使用场景**:修改已有其他收入的公开业务字段。 +- **认证**:需要管理后台登录态;仅超级管理员、管理员或财务可写。 +- **幂等性**:无单独幂等键;重复提交相同最终载荷不会改变公开结果。调用方不得依赖并发请求顺序。 +- **限流**:未声明接口专属限流。 + +**路径参数**: + +| 字段 | 类型 | 必填 | 说明 | 校验 | +|---|---|---:|---|---| +| `orderId` | String(Long) | 是 | 订单 ID | 必须大于 0 | +| `incomeId` | String(Long) | 是 | 其他收入 ID | 必须大于 0,且必须属于该订单 | + +**请求体完整字段**:与 POST 相同,但没有 `requestId`;`settlementConfirmStatus` 可为 `UNCONFIRMED` 或 `CONFIRMED`。字段长度、金额一致性、凭证约束均与 §3.2 相同。 + +**成功响应**:`data` 为 §3.1 的完整 `OtherIncomeItem`;不含 `projectCategory`、`projectCategoryName`、`specification`。 + +**典型成功请求与响应**: + +```http +PUT /v3/admin/order/2084000000000002978/settlement/other-incomes/2084000000000004978 +Authorization: Bearer +Content-Type: application/json +``` + +```json +{ + "incomeDate": "2026-08-04", + "projectName": "酒店升级补差-已更新", + "quantity": 3, + "unitPrice": 15.00, + "settlementAmount": 45.00, + "paymentMethod": "CASH_PAID", + "settlementConfirmStatus": "UNCONFIRMED", + "voucherUrls": [], + "remark": "金额已核对" +} +``` + +```json +{ + "code": 200, + "message": "success", + "data": { + "id": "2084000000000004978", + "requestId": "oi-5477-0001", + "incomeDate": "2026-08-04", + "projectName": "酒店升级补差-已更新", + "quantity": 3, + "unitPrice": 15, + "settlementAmount": 45, + "paymentMethod": "CASH_PAID", + "paymentMethodName": "现付", + "voucherUrls": [], + "settlementConfirmStatus": "UNCONFIRMED", + "settlementConfirmStatusName": "未确认", + "remark": "金额已核对", + "sourceType": "MANUAL", + "sourceTypeName": "手工", + "sourceId": "2084000000000004982" + }, + "success": true +} +``` + +**边界请求与响应(夹带旧字段)**:请求可额外包含 `projectCategory`、`specification`,服务端会忽略,仍按上述公开字段更新,响应不会出现三个旧字段。 + +```json +{ + "incomeDate": "2026-08-04", + "projectName": "酒店升级补差-兼容请求", + "projectCategory": "OLD_JSON_CATEGORY_SHOULD_BE_IGNORED", + "specification": "OLD_JSON_SPEC_SHOULD_BE_IGNORED", + "quantity": 3, + "unitPrice": 15, + "settlementAmount": 45, + "paymentMethod": "CASH_PAID", + "settlementConfirmStatus": "UNCONFIRMED", + "voucherUrls": [] +} +``` + +```json +{ + "code": 200, + "message": "success", + "data": { + "id": "2084000000000004978", + "requestId": "oi-5477-0001", + "incomeDate": "2026-08-04", + "projectName": "酒店升级补差-兼容请求", + "quantity": 3, + "unitPrice": 15, + "settlementAmount": 45, + "paymentMethod": "CASH_PAID", + "paymentMethodName": "现付", + "voucherUrls": [], + "settlementConfirmStatus": "UNCONFIRMED", + "settlementConfirmStatusName": "未确认", + "remark": null, + "sourceType": "MANUAL", + "sourceTypeName": "手工", + "sourceId": "2084000000000004982" + }, + "success": true +} +``` + +**异常请求与响应(金额不一致)**: + +```json +{ + "incomeDate": "2026-08-04", + "projectName": "金额错误", + "quantity": 3, + "unitPrice": 15, + "settlementAmount": 44, + "paymentMethod": "CASH_PAID", + "settlementConfirmStatus": "UNCONFIRMED" +} +``` + +```json +{"code": 584076, "message": "其他收入核算金额必须等于数量乘以核算单价", "data": null, "success": false} +``` + +## 4. 接口入参汇总 + +| 接口 | 路径参数 | 请求体差异 | 已删除字段 | +|---|---|---|---| +| GET | `orderId` | 无 | 无入参;响应删除三个字段 | +| POST | `orderId` | 比 PUT 多必填 `requestId`;新增必须从 `UNCONFIRMED` 开始 | `projectCategory`、`specification` | +| PUT | `orderId`、`incomeId` | 无 `requestId`;确认状态可为两种合法值 | `projectCategory`、`specification` | + +完整字段、类型和校验均已在 §3 对应接口内列出。 + +## 5. 出参字段汇总 + +POST、PUT 返回单个 `OtherIncomeItem`;GET 返回 `items[] + deductions[] + summary`。`OtherIncomeItem` 的完整当前字段见 §3.1,三种接口均不再返回: + +| 已删除字段 | 原类型 | 当前替代 | +|---|---|---| +| `projectCategory` | String | 无;前端删除对应状态与控件 | +| `projectCategoryName` | String | 无;前端删除对应展示读取 | +| `specification` | String | 无;前端删除对应状态与控件 | + +## 6. 枚举 / 数据字典 + +### 6.1 `paymentMethod`(付款类型) + +**所属字段**:POST/PUT 入参、`OtherIncomeItem.paymentMethod` | **类型**:String | **必填**:是 + +| 值 | 中文 | 说明 | +|---|---|---| +| `CASH_PAID` | 现付 | 已现场支付 | +| `COMPANY_PAID` | 公司付款 | 由公司付款 | +| `SIGNED` | 签单 | 签单结算 | + +### 6.2 `settlementConfirmStatus`(确认状态) + +**所属字段**:POST/PUT 入参、`OtherIncomeItem.settlementConfirmStatus` | **类型**:String | **必填**:是 + +| 值 | 中文 | 说明 | +|---|---|---| +| `UNCONFIRMED` | 未确认 | POST 新增时唯一允许的初始值 | +| `CONFIRMED` | 已确认 | 仅对已有明细通过 PUT 更新使用 | + +### 6.3 `sourceType`(公开来源类型) + +**所属字段**:`OtherIncomeItem.sourceType` | **类型**:String | **必填**:响应必有 + +| 值 | 中文 | 说明 | +|---|---|---| +| `MANUAL` | 手工 | 管理后台手工新增 | +| `SYSTEM` | 系统 | 系统投影来源 | + +`projectCategory` 对应的数据字典不再属于其他收入接口契约;前端应删除该字典请求和映射逻辑。 + +## 7. 错误码 + +| code | 含义 | 触发场景 | +|---:|---|---| +| `400` | 参数校验失败 | 缺必填字段、长度/格式超限、非法枚举、订单 ID 非正数等 | +| `401` | 未登录或登录态失效 | 缺少有效管理后台凭证 | +| `584073` | 其他收入不存在或不属于当前订单 | PUT 的 `incomeId` 不存在或订单归属不符 | +| `584074` | 当前核单状态不允许修改其他收入 | 订单核单状态不是待核单或核单中 | +| `584075` | 其他收入关联的附加费来源无效 | 关联来源无法建立或已失效 | +| `584076` | 核算金额不等于数量乘以单价 | `quantity × unitPrice` 四舍五入到 2 位后与金额不一致 | +| `584086` | 无权修改核单资金数据 | 写接口调用角色不是超级管理员、管理员或财务 | +| `584087` | `requestId` 已用于另一笔其他收入 | POST 重用幂等键但载荷不同 | +| `584088` | 核单凭证数据损坏 | 历史凭证数据无法读取 | +| `584089` | 核单或结算已完成,资金数据不可修改 | 对完成后的资金事实调用 POST/PUT | +| `584106` | 确认状态非法 | 非 `UNCONFIRMED/CONFIRMED` | +| `584107` | 手工新增必须先保存为未确认 | POST 直接传 `CONFIRMED` | + +旧错误码 `584103`(项目类别非法)、`584104`(规格非法)、`584105`(相关字典不可用)不再由这三个接口触发。 + +## 8. 示例索引 + +三类示例均已与接口放在一起,避免跨节拼接: + +| 接口 | 典型成功 | 边界 | 业务失败 | +|---|---|---|---| +| GET | §3.1 有明细 | §3.1 空列表 | §3.1 非法 `orderId` | +| POST | §3.2 不传旧字段创建 | §3.2 旧请求多传字段被忽略 | §3.2 缺确认状态 | +| PUT | §3.3 正常更新 | §3.3 夹带旧字段被忽略 | §3.3 金额不一致 | + +## 9. 业务边界 + +- ✅ GET 用于读取当前其他收入、减费与汇总;空数据稳定返回空数组。 +- ✅ POST/PUT 仅适用于核单资金仍可修改的订单,且调用角色必须具备资金写权限。 +- ✅ POST 必须携带稳定 `requestId`,并以 `UNCONFIRMED` 创建;后续可通过 PUT 改为 `CONFIRMED`。 +- ✅ `settlementAmount` 必须等于 `quantity × unitPrice` 四舍五入到 2 位。 +- ⚠️ 旧客户端继续多传 `projectCategory/specification` 时,新接口会忽略;这不是继续保留控件的理由。 +- ❌ 核单或结算完成后禁止 POST/PUT;不存在或跨订单的 `incomeId` 禁止更新。 +- ❌ 前端不得从其他字段猜测、拼装或恢复已删除的项目类别与票种规格。 + +## 10. 修改前后对比 + +### 10.1 字段级对比 + +| 接口字段 | 原来 | 现在 | +|---|---|---| +| POST/PUT `projectCategory` | 必填 String,受项目类别字典校验 | 已从契约删除;旧 JSON 多传会被忽略 | +| POST/PUT `specification` | 可选 String,受规格字典校验 | 已从契约删除;旧 JSON 多传会被忽略 | +| GET/POST/PUT `projectCategory` | 响应返回 | 不再返回 | +| GET/POST/PUT `projectCategoryName` | 响应返回中文名 | 不再返回 | +| GET/POST/PUT `specification` | 响应返回 | 不再返回 | + +### 10.2 行为级对比 + +| 行为 | 原来 | 现在 | +|---|---|---| +| 新增/修改表单 | 必须维护项目类别,可选维护票种规格 | 两个控件都删除,只提交当前公开字段 | +| 旧客户端多传旧字段 | 参与校验和保存 | 被忽略,且响应不回显 | +| 查询展示 | 可读取类别、类别名称和规格 | 三个字段不存在,禁止继续读取或设置默认值 | +| 相关字典异常 | 可能阻断写入 | 不再属于其他收入接口错误面 | + +## 11. 影响评估 / 回滚 + +### 11.1 影响评估 + +- **是否破坏向后兼容**:响应字段删除属于破坏性变化;但旧前端继续多传两个旧请求字段时,新接口会忽略,因此后端先上线兼容旧请求。 +- **前端是否必须同步上线**:必须。删除项目类别与票种规格控件、请求字段、响应读取和相关字典依赖。 +- **上线顺序边界**:允许“新后端 → 旧前端”短暂过渡;不允许“新前端 → 旧后端”,因为旧后端仍要求 `projectCategory`。 + +### 11.2 回滚方案 + +- 若接口契约回滚到旧版本,必须同步恢复前端 `projectCategory` 必填提交,否则旧接口会拒绝新增/修改。 +- 仅回滚前端到旧版本不会阻断新接口写入,但旧页面读取不到三个已删除响应字段,类别/规格区域会为空,因此不建议长期维持。 + +## 12. 注意事项 + +- 删除项目类别控件、票种规格控件及其表单校验。 +- 停止在 POST/PUT 请求中传 `projectCategory`、`specification`。 +- 停止读取 GET/POST/PUT 响应中的 `projectCategory`、`projectCategoryName`、`specification`。 +- 删除其他收入页面对项目类别字典、票种规格字典的加载与映射。 +- Long ID 继续按 String 消费;空明细继续按 `[]` 处理。 + +## 13. 关联 / 联系人 + +### 13.1 链接 + +- **Issue**: [#5477](https://git.1814.love:8443/wx/HL/issues/5477) +- **PR**: [#5488](https://git.1814.love:8443/wx/HL/pulls/5488) +- **Merge commit**: [da1ee4ebc106](https://git.1814.love:8443/wx/HL/commit/da1ee4ebc1068e5ca20b683769238a3cf165b4b5) + +### 13.2 联系人 + +- **后端负责人**: @yaosutu +- **QA 验证**: Issue #5477 接口验收已完成(管理后台真实网关,TARGETED_FALLBACK)