# 签单 sign-voucher 金额改取「协议成本价」（原取客户成交价，取错字段）

**接口路径**：GET /v3/admin/order/{id}/sign-voucher
**服务**：hl-order-service-v3
**PR**：[#4724](https://git.1814.love:8443/wx/HL/pulls/4724)｜ **Issue**：[#4722](https://git.1814.love:8443/wx/HL/issues/4722)｜ **前序**：[#4716](https://git.1814.love:8443/wx/HL/pulls/4716)（移除服务/接送单）/ #4072（house 协议价）｜ **合并至**：dev-v3
**变更类型**：修改接口（出参金额取值来源变更，字段名不变）

---

## 1. 接口背景

签单（预订通知单）接口给**供应商核对成本**用。此前 `entries[].items[].unitPrice/amount` 与 `entries[].totalAmount` 取的是「客户成交价」，与"供应商核成本"语义不符，属取错字段。本次改为取「协议成本价」。**入参不变，出参结构与字段名均不变，仅金额取值来源变。**

---

## 2. 变更清单

| 位置 | 变更 |
|------|------|
| 景点单价 | 取值来源 `node.sell_price`（成交价）→ `node.unit_price`（协议价） |
| 酒店单价 | 取值来源 `house.sell_price`（成交价）→ `house.proto_price`（协议价） |
| 合计金额 | = 协议单价 × 数量（景点按人数、酒店按间数），后端现算 |

**入参无变化，出参 JSON 结构 / 字段名无变化，无 DDL。**

---

## 3. 接口详情

- 方法：GET ｜ 路径：`/v3/admin/order/{id}/sign-voucher` ｜ 鉴权：管理后台 JWT（房务角色无权，返 581045）
- 响应：`Result<SignVoucherRespVO>`

---

## 4. 入参

| 位置 | 字段 | 类型 | 必填 | 说明 |
|------|------|------|:---:|------|
| Path | `id` | Long | 是 | 订单 ID |
| Query | `showAmount` | Boolean | 否 | 是否展示金额（false=脱敏成 null，默认 false） |

本次入参无变化。

---

## 5. 出参

`SignVoucherRespVO.entries[]` 结构不变，受影响金额字段：

| 字段 | 类型 | 说明（变更后语义） |
|------|------|------|
| `entries[].items[].unitPrice` | BigDecimal | 单价 = **协议成本价**（景点 node.unit_price / 酒店 house.proto_price） |
| `entries[].items[].amount` | BigDecimal | 明细金额 = 协议单价 × 数量 |
| `entries[].totalAmount` | BigDecimal | 该通知单合计 = 协议单价 × 数量 |

`showAmount=false` 时上述金额字段均为 null（脱敏，行为不变）。

---

## 6. 枚举 / 数据字典

无枚举变更。

---

## 7. 错误码

无新增错误码。房务角色返 `581045`；订单不存在返 `581007`。

---

## 8. 示例

### 8.1 典型成功（酒店有协议价 320、景点协议价 0）

请求：
```
GET /v3/admin/order/2072534227441627138/sign-voucher?showAmount=true
```
响应片段：
```json
{
  "code": 200,
  "data": {
    "entries": [
      {"type": "HOTEL", "supplierName": "呼伦贝尔香格里拉大酒店", "totalAmount": "1280.00",
        "items": [{"name": "大床房", "qty": 4, "unitPrice": "320.00", "amount": "1280.00"}]},
      {"type": "SCENIC", "supplierName": "呼和诺尔草原旅游区", "totalAmount": "0.00",
        "items": [{"name": "门票", "qty": 10, "unitPrice": "0.00", "amount": "0.00"}]}
    ]
  }
}
```
> 说明：单价取协议价——酒店 proto_price=320；景点 unit_price=0（该订单资源价格日历未配景点协议价，故为 0）。

### 8.2 边界（showAmount=false，脱敏）

```json
{ "type": "HOTEL", "totalAmount": null, "items": [{"unitPrice": null, "amount": null}] }
```

### 8.3 协议价缺失

协议价字段 NULL → 对应 unitPrice/amount 为 null（前端展示空）；协议价为 0 → 展示 0.00。

---

## 9. 业务边界

- 签单金额自此代表**给供应商的协议成本价**，不再是客户成交价。
- 景点协议价来源 = 创单固化时从资源价格日历写入 `order_itinerary_node.unit_price`；酒店协议价来源 = 房务维护的 `house_hotel_assignment.proto_price`（resource 单源，#4072）。
- 协议价未配置的资源，签单金额会显示 0 或空，属数据源（价格日历/房务协议价）未维护，非接口问题。

---

## 10. 修改前后对比

| 条目 | 修改前 unitPrice | 修改后 unitPrice |
|------|--------|--------|
| 景点 | node.sell_price（客户成交价） | node.unit_price（协议成本价） |
| 酒店 | house.sell_price（客户成交价） | house.proto_price（协议成本价） |

出参 JSON 结构、字段名不变，仅数值来源与语义变化。

---

## 11. 影响评估 / 回滚

**取值语义变更（前端需知晓）**：签单展示的金额从「客户成交价」变为「协议成本价」。字段名不变，前端渲染代码无需改，但若页面上有"成交价"文案标注需同步为"协议价/成本价"。

**回滚**：接口层回退到 PR #4724 之前版本。零 DDL，无数据迁移。

---

## 12. 注意事项

- 已部署测试服并行为验证：酒店 unitPrice=proto_price（320）、景点 unitPrice=unit_price（0.00，原取 sell_price 时为 null，现为 0.00，证明已切协议价来源）；showAmount=false 金额全 null。
- 协议价数据未维护的订单签单会显示 0/空，与本次改动无关。

---

## 13. 关联 / 联系人

- Issue：[#4722](https://git.1814.love:8443/wx/HL/issues/4722)
- PR：[#4724](https://git.1814.love:8443/wx/HL/pulls/4724)
- 前序：[#4716](https://git.1814.love:8443/wx/HL/pulls/4716) / #4072
- 负责人：腰苏图（yst）
