docs(changelog): #7741 订单用餐信息与用餐模版接口(新增 7 个接口·管理后台)
changelog-filename-gate / validate (push) Failing after 2s
changelog-filename-gate / validate (push) Failing after 2s
这个提交包含在:
@@ -0,0 +1,831 @@
|
|||||||
|
---
|
||||||
|
schema: "hl-changelog/v2"
|
||||||
|
ticket: "7741"
|
||||||
|
title: "订单用餐信息与用餐模版接口(查询、生成、整单保存、重置、查模版、存模版、套模版)"
|
||||||
|
consumer: "admin"
|
||||||
|
author: "lc(GIT)"
|
||||||
|
change_type: "新增接口"
|
||||||
|
backend_status: "deployed"
|
||||||
|
gateway_status: "verified"
|
||||||
|
frontend_status: "pending"
|
||||||
|
frontend_owner: ""
|
||||||
|
frontend_ref: ""
|
||||||
|
target_release: ""
|
||||||
|
verified_at: ""
|
||||||
|
status_note: "新增 7 个接口:订单详情「用餐」页签的用餐信息查询 / 按产品快照生成 / 整单一次保存 / 重置,以及用餐模版的查询 / 保存 / 套用。前端需按本文契约对接;人数与桌数二选一、类别字典过滤 SELF 两点见「四、契约约束」。"
|
||||||
|
updated_at: "2026-09-18"
|
||||||
|
base: "dev-v3"
|
||||||
|
---
|
||||||
|
|
||||||
|
# order-v3: 订单用餐信息与用餐模版接口
|
||||||
|
|
||||||
|
> **服务**: hl-order-service-v3(订单库新建两张表,随服务部署由 Flyway 创建)
|
||||||
|
> **PR**: #7945(主体)、#7954(3.1 团期编号回显补充)
|
||||||
|
> **Issue**: #7741、#7953
|
||||||
|
> **日期**: 2026-09-18
|
||||||
|
> **影响范围**: 管理后台订单详情「用餐」页签(新接口,老接口不变)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚠️ 关键变化
|
||||||
|
|
||||||
|
🔴 **新增 7 个接口,路径前缀 `/v3/admin/order/meal-info` 与 `/v3/admin/order/meal-template`。**
|
||||||
|
|
||||||
|
🔴 **订单用餐的增、删、改只有一个接口:3 号「整单保存」。** 页面上加行、改值、删行都不调后端,点「保存」时把这张订单页面上的全部行一次提交:带 `mealInfoId` 的整行覆盖,不带的新增,原来有而这次没传上来的行被删除。
|
||||||
|
|
||||||
|
🔴 **金额由前端按公式算好传上来,后端逐行重算核对,对不上返回 589613,整批不保存。** 桌数为 0 按人算,不为 0 按桌算(公式见 3 号接口)。
|
||||||
|
|
||||||
|
🔴 **类别字典 `meal_type` 在 TEST 有 BREAKFAST / LUNCH / DINNER / SELF 四个值,接口只接受前三个,页面下拉请过滤掉 SELF。**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、背景
|
||||||
|
|
||||||
|
订单详情新增「用餐」页签:按订单产品快照里每天早午晚餐的安排,自动生成需要安排的用餐行;运营逐行选餐厅、餐食,填桌数或人数,保存金额;排好的几天可以存成「用餐模版」,以后套到别的订单上。
|
||||||
|
|
||||||
|
生成规则(快照里行程天的早 / 午 / 晚餐取值,字典 `meal_option`):
|
||||||
|
|
||||||
|
| 取值 | 中文 | 是否生成用餐行 |
|
||||||
|
|------|------|----------------|
|
||||||
|
| `HOTEL` | 含(酒店) | 不生成 |
|
||||||
|
| `SELF` | 自理 | 不生成 |
|
||||||
|
| `CAMP` | 含(营地) | 生成这一天这一餐的一行空行 |
|
||||||
|
| `SPECIAL` | 含(特色餐) | 生成这一天这一餐的一行空行 |
|
||||||
|
| `REGULAR` | 含(正餐) | 生成这一天这一餐的一行空行 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、变更接口清单
|
||||||
|
|
||||||
|
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|
||||||
|
|---|------|------|------|----------|------|
|
||||||
|
| 1 | 查询用餐信息列表 | GET | `/v3/admin/order/meal-info/list` | 新增 | 页签查询行和合计 |
|
||||||
|
| 2 | 生成用餐信息 | POST | `/v3/admin/order/meal-info/generate` | 新增 | 按产品快照生成空行,已有行不重复生成 |
|
||||||
|
| 3 | 保存用餐信息(整单一次保存) | POST | `/v3/admin/order/meal-info/save` | 新增 | 增、改、删一次提交 |
|
||||||
|
| 4 | 重置用餐信息 | POST | `/v3/admin/order/meal-info/reset` | 新增 | 删掉全部行后按快照重新生成空行 |
|
||||||
|
| 5 | 查询用餐模版 | GET | `/v3/admin/order/meal-template/list` | 新增 | 按模版ID或模版名查,按模版分组 |
|
||||||
|
| 6 | 保存为用餐模版 | POST | `/v3/admin/order/meal-template/save` | 新增 | 选几行存成一个新模版 |
|
||||||
|
| 7 | 套用用餐模版 | POST | `/v3/admin/order/meal-template/apply` | 新增 | 把模版套到一张订单上 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、接口详情
|
||||||
|
|
||||||
|
### 1. 查询用餐信息列表 `GET /v3/admin/order/meal-info/list`
|
||||||
|
|
||||||
|
**VO**: `OrderMealInfoListReqVO` → `OrderMealInfoListRespVO`
|
||||||
|
|
||||||
|
#### 使用场景
|
||||||
|
|
||||||
|
订单详情「用餐」页签打开时传当前订单的 `orderId`,取这张订单的全部用餐行、合计金额和订单信息;`generated=false` 且 `orderEditable=true` 时再调 2 号接口生成。按团期查询时传 `groupBatchId` 或 `batchNo`。
|
||||||
|
|
||||||
|
#### 入参
|
||||||
|
|
||||||
|
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||||||
|
|------|------|------|------|------|------|
|
||||||
|
| orderId | Query | String | 否 | 正数 | 订单ID |
|
||||||
|
| groupBatchId | Query | String | 否 | 正数 | 团期ID |
|
||||||
|
| batchNo | Query | String | 否 | ≤64 | 团期编号,精确匹配 |
|
||||||
|
| mealType | Query | String | 否 | BREAKFAST / LUNCH / DINNER | 类别 |
|
||||||
|
| mealDateStart | Query | String | 否 | yyyy-MM-dd | 用餐日期起(含) |
|
||||||
|
| mealDateEnd | Query | String | 否 | yyyy-MM-dd,≥ mealDateStart | 用餐日期止(含) |
|
||||||
|
| dayNumber | Query | Integer | 否 | ≥1 | 第几天 |
|
||||||
|
| settleType | Query | String | 否 | cash / sign / company | 付款方式 |
|
||||||
|
| keyword | Query | String | 否 | ≤64 | 模糊匹配餐厅名称、餐食名称;`%`、`_` 按字面量匹配 |
|
||||||
|
| limit | Query | Integer | 否 | 1–500,默认 200 | 最大返回条数 |
|
||||||
|
|
||||||
|
#### 出参 `Result<OrderMealInfoListRespVO>`
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| orderId | String | 入参订单ID;没传为 null |
|
||||||
|
| groupBatchId | String | 订单所属团期ID;订单没挂团期或没传订单ID时为入参团期ID;都没有为 null |
|
||||||
|
| batchNo | String | 与 `groupBatchId` 对应的团期编号;没有为 null |
|
||||||
|
| departDate | String | 订单出发日期 yyyy-MM-dd;没传订单ID为 null |
|
||||||
|
| returnDate | String | 订单返回日期;没传订单ID为 null |
|
||||||
|
| personCount | Integer | 订单人数:成人 + 儿童 + 幼童 + 婴儿;没传订单ID为 null |
|
||||||
|
| orderEditable | Boolean | 订单是否可改:已完成、已取消为 false;没传订单ID为 null |
|
||||||
|
| generated | Boolean | 该订单是否已有用餐行(不受筛选条件影响);没传订单ID为 null |
|
||||||
|
| totalAmount | Number | 本次返回各行金额之和 |
|
||||||
|
| items[].mealInfoId | String | 用餐信息ID |
|
||||||
|
| items[].orderId | String | 订单ID,可为 null |
|
||||||
|
| items[].groupBatchId | String | 团期ID,可为 null |
|
||||||
|
| items[].batchNo | String | 团期编号,可为 null |
|
||||||
|
| items[].restaurantId | String | 餐厅ID,可为 null |
|
||||||
|
| items[].restaurantName | String | 餐厅名称,可为 null |
|
||||||
|
| items[].dishId | String | 餐食ID,没选餐食为 null |
|
||||||
|
| items[].dishCode | String | 餐食编码,没选餐食为 null |
|
||||||
|
| items[].dishName | String | 餐食名称,没选餐食为 null |
|
||||||
|
| items[].mealType | String | 类别 BREAKFAST / LUNCH / DINNER |
|
||||||
|
| items[].mealDate | String | 用餐日期 yyyy-MM-dd |
|
||||||
|
| items[].dayNumber | Integer | 第几天;手动添加的行为 null |
|
||||||
|
| items[].unitPrice | Number | 单价(按人时是每人单价,按桌时是每桌单价) |
|
||||||
|
| items[].tableCount | Integer | 桌数;0 表示按人算 |
|
||||||
|
| items[].personCount | Integer | 人数 |
|
||||||
|
| items[].freePersonCount | Integer | 免人数 |
|
||||||
|
| items[].freeAmount | Number | 免金额 |
|
||||||
|
| items[].otherCost | Number | 其他成本 |
|
||||||
|
| items[].amount | Number | 金额 |
|
||||||
|
| items[].settleType | String | 付款方式编码 cash / sign / company,可为 null |
|
||||||
|
| items[].settleTypeName | String | 付款方式中文,可为 null |
|
||||||
|
| items[].createTime | String | 创建时间 yyyy-MM-dd HH:mm:ss |
|
||||||
|
|
||||||
|
#### 请求示例
|
||||||
|
|
||||||
|
```http
|
||||||
|
GET /v3/admin/order/meal-info/list?orderId=2100864597505286145
|
||||||
|
Authorization: Bearer <admin token>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 响应示例
|
||||||
|
|
||||||
|
TEST 实测返回(节选 1 行):
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"message": "成功",
|
||||||
|
"success": true,
|
||||||
|
"data": {
|
||||||
|
"orderId": "2100864597505286145",
|
||||||
|
"groupBatchId": null,
|
||||||
|
"batchNo": null,
|
||||||
|
"departDate": "2026-10-23",
|
||||||
|
"returnDate": "2026-10-25",
|
||||||
|
"personCount": 2,
|
||||||
|
"orderEditable": true,
|
||||||
|
"generated": true,
|
||||||
|
"totalAmount": 60.00,
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"mealInfoId": "2100883161750687746",
|
||||||
|
"orderId": "2100864597505286145",
|
||||||
|
"groupBatchId": null,
|
||||||
|
"batchNo": null,
|
||||||
|
"restaurantId": "2023382108491247617",
|
||||||
|
"restaurantName": "七间房全羊馆",
|
||||||
|
"dishId": "2100864423122898946",
|
||||||
|
"dishCode": "HL7741A",
|
||||||
|
"dishName": "HL7741-TEST-餐食A",
|
||||||
|
"mealType": "LUNCH",
|
||||||
|
"mealDate": "2026-10-20",
|
||||||
|
"dayNumber": 1,
|
||||||
|
"unitPrice": 30.00,
|
||||||
|
"tableCount": 0,
|
||||||
|
"personCount": 0,
|
||||||
|
"freePersonCount": 0,
|
||||||
|
"freeAmount": 0.00,
|
||||||
|
"otherCost": 0.00,
|
||||||
|
"amount": 0.00,
|
||||||
|
"settleType": "sign",
|
||||||
|
"settleTypeName": "签单",
|
||||||
|
"createTime": "2026-09-18 17:42:33"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 空数据 / 降级响应
|
||||||
|
|
||||||
|
订单还没有用餐行时 `generated=false`、`items=[]`、`totalAmount=0`,其余订单字段照常返回。按团期编号查不到团期时返回空列表。
|
||||||
|
|
||||||
|
#### 错误响应
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "code": 400, "message": "用餐日期起不能晚于用餐日期止", "success": false, "data": null }
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 业务边界
|
||||||
|
|
||||||
|
- 只查未删除的行,各条件之间是「并且」;排序:用餐日期升序 → 早、午、晚 → 创建时间升序。
|
||||||
|
- 传 `orderId`:订单不存在按订单模块现有错误返回;房务角色返回 581045;需对该订单有查看权限。
|
||||||
|
- 不传 `orderId`、传团期ID或团期编号:需要团期查看权限(不足 589507),范围是挂在该团期上的行。
|
||||||
|
- 三个都不传:房务角色返回 581045;只查「没挂订单也没挂团期」的行。
|
||||||
|
|
||||||
|
### 2. 生成用餐信息 `POST /v3/admin/order/meal-info/generate`
|
||||||
|
|
||||||
|
**VO**: `OrderMealInfoGenerateReqVO` → `OrderMealInfoListRespVO`
|
||||||
|
|
||||||
|
#### 使用场景
|
||||||
|
|
||||||
|
1 号接口返回 `generated=false` 且订单可改时调用,按订单产品快照生成空行(规则见「一、背景」表)。生成不读模版,要模版的调 7 号接口。
|
||||||
|
|
||||||
|
#### 入参
|
||||||
|
|
||||||
|
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||||||
|
|------|------|------|------|------|------|
|
||||||
|
| orderId | Body | String | ✅ | 正数 | 订单ID |
|
||||||
|
|
||||||
|
#### 出参 `Result<OrderMealInfoListRespVO>`
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| data | Object | 生成后按该订单查询的结果,字段同 1 号接口出参 |
|
||||||
|
|
||||||
|
#### 请求示例
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "orderId": "2100864614022451201" }
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 响应示例
|
||||||
|
|
||||||
|
TEST 实测(订单 B 生成时返回,节选 1 行):第 1 天午餐 = 含(营地),生成的行餐厅、餐食、付款方式为空,数值全为 0:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"message": "成功",
|
||||||
|
"success": true,
|
||||||
|
"data": {
|
||||||
|
"orderId": "2100864614022451201",
|
||||||
|
"departDate": "2026-10-20",
|
||||||
|
"returnDate": "2026-10-22",
|
||||||
|
"personCount": 2,
|
||||||
|
"orderEditable": true,
|
||||||
|
"generated": true,
|
||||||
|
"totalAmount": 0.00,
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"mealInfoId": "2100882946096353281",
|
||||||
|
"orderId": "2100864614022451201",
|
||||||
|
"restaurantId": null,
|
||||||
|
"restaurantName": null,
|
||||||
|
"dishId": null,
|
||||||
|
"dishCode": null,
|
||||||
|
"dishName": null,
|
||||||
|
"mealType": "LUNCH",
|
||||||
|
"mealDate": "2026-10-20",
|
||||||
|
"dayNumber": 1,
|
||||||
|
"unitPrice": 0.00,
|
||||||
|
"tableCount": 0,
|
||||||
|
"personCount": 0,
|
||||||
|
"freePersonCount": 0,
|
||||||
|
"freeAmount": 0.00,
|
||||||
|
"otherCost": 0.00,
|
||||||
|
"amount": 0.00,
|
||||||
|
"settleType": null,
|
||||||
|
"settleTypeName": null,
|
||||||
|
"createTime": "2026-09-18 17:41:42"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 空数据 / 降级响应
|
||||||
|
|
||||||
|
订单出发或返回日期为空时不生成,**返回成功**(`code` 200),`message` 为「订单出发或返回日期为空,无法生成用餐信息」(错误码 589602 的文案,只作提示),`data.items` 为 `[]`。快照里没有需要生成的餐时也返回成功、`items` 为空。
|
||||||
|
|
||||||
|
#### 错误响应
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "code": 589607, "message": "订单已完成或已取消,不能修改用餐信息", "success": false, "data": null }
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 业务边界
|
||||||
|
|
||||||
|
- 用餐日期 = 出发日期 + d − 1,第几天 = d;天数按出发到返回日期算,快照里超出的天不生成。
|
||||||
|
- 幂等:该订单已有未删除的行时不再生成,直接返回现有列表。
|
||||||
|
- 订单不存在、对订单无操作权限按订单模块现有错误返回;已完成或已取消 589607;返回日期早于出发日期 589612。
|
||||||
|
|
||||||
|
### 3. 保存用餐信息(整单一次保存) `POST /v3/admin/order/meal-info/save`
|
||||||
|
|
||||||
|
**VO**: `OrderMealInfoBatchSaveReqVO` → `OrderMealInfoListRespVO`
|
||||||
|
|
||||||
|
#### 使用场景
|
||||||
|
|
||||||
|
「用餐」页签点「保存」,把这张订单页面上的全部行一次提交。页面上的「添加」「删除」和行内改值都不调后端。
|
||||||
|
|
||||||
|
#### 入参
|
||||||
|
|
||||||
|
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||||||
|
|------|------|------|------|------|------|
|
||||||
|
| orderId | Body | String | ✅ | 正数 | 订单ID |
|
||||||
|
| groupBatchId | Body | String | 否 | 正数 | 传了须与订单所属团期一致,否则 589601 |
|
||||||
|
| items | Body | Array | ✅ | 可为空数组 | 这张订单保存后应有的全部行;空数组表示一行都不留 |
|
||||||
|
| items[].mealInfoId | Body | String | 否 | — | 传了更新这一行,不传新增一行 |
|
||||||
|
| items[].restaurantId | Body | String | 否 | — | 餐厅ID(来自餐厅选项接口),原样保存 |
|
||||||
|
| items[].restaurantName | Body | String | 否 | ≤128 | 餐厅名称,原样保存 |
|
||||||
|
| items[].dishId | Body | String | 否 | — | 餐食ID(来自餐食下拉),没选餐食不传 |
|
||||||
|
| items[].dishCode | Body | String | 否 | ≤20 | 餐食编码,原样保存 |
|
||||||
|
| items[].dishName | Body | String | 否 | 去首尾空格后 ≤500 | 餐食名称,原样保存 |
|
||||||
|
| items[].mealType | Body | String | 否 | BREAKFAST / LUNCH / DINNER,默认 LUNCH | 类别 |
|
||||||
|
| items[].mealDate | Body | String | ✅ | yyyy-MM-dd | 用餐日期 |
|
||||||
|
| items[].unitPrice | Body | Number | 否 | 0–99999999.99,两位小数,默认 0 | 单价 |
|
||||||
|
| items[].tableCount | Body | Integer | 否 | 0–999,默认 0 | 桌数;0 按人算,不为 0 按桌算 |
|
||||||
|
| items[].personCount | Body | Integer | 否 | 0–9999,默认 0 | 人数 |
|
||||||
|
| items[].freePersonCount | Body | Integer | 否 | ≥0,默认 0 | 免人数;不校验与人数的大小关系 |
|
||||||
|
| items[].freeAmount | Body | Number | 否 | 0–99999999.99,两位小数,默认 0 | 免金额 |
|
||||||
|
| items[].otherCost | Body | Number | 否 | 0–99999999.99,两位小数,默认 0 | 其他成本 |
|
||||||
|
| items[].amount | Body | Number | 否 | 0–99999999.99,两位小数,默认 0 | 金额,前端按公式算好传上来 |
|
||||||
|
| items[].settleType | Body | String | 否 | cash / sign / company | 付款方式编码 |
|
||||||
|
| items[].settleTypeName | Body | String | 否 | ≤32 | 付款方式中文,原样保存 |
|
||||||
|
|
||||||
|
#### 出参 `Result<OrderMealInfoListRespVO>`
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| data | Object | 保存后按该订单查询的结果,字段同 1 号接口出参;新增行是新生成的 `mealInfoId`,`dayNumber` 为 null |
|
||||||
|
|
||||||
|
#### 请求示例
|
||||||
|
|
||||||
|
示例(金额取自 TEST 实测数据;节选:改一行按人、改一行按桌、新增一行,没传上来的行被删除):
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"orderId": "2100864597505286145",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"mealInfoId": "2100883161750687746",
|
||||||
|
"restaurantId": "2023382108491247617", "restaurantName": "七间房全羊馆",
|
||||||
|
"dishId": "2100864423122898946", "dishCode": "HL7741A", "dishName": "HL7741-TEST-餐食A",
|
||||||
|
"mealType": "LUNCH", "mealDate": "2026-10-20",
|
||||||
|
"unitPrice": 30, "tableCount": 0, "personCount": 4, "freePersonCount": 1,
|
||||||
|
"freeAmount": 0, "otherCost": 10, "amount": 100.00,
|
||||||
|
"settleType": "sign", "settleTypeName": "签单"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"mealInfoId": "2100883161754882049",
|
||||||
|
"restaurantId": "2023382108491247617", "restaurantName": "七间房全羊馆",
|
||||||
|
"dishId": "2100864435710009346", "dishCode": "HL7741B", "dishName": "HL7741-TEST-餐食B",
|
||||||
|
"mealType": "DINNER", "mealDate": "2026-10-20",
|
||||||
|
"unitPrice": 800, "tableCount": 2, "personCount": 0, "freePersonCount": 0,
|
||||||
|
"freeAmount": 100, "otherCost": 50, "amount": 1550.00,
|
||||||
|
"settleType": "cash", "settleTypeName": "现付"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"restaurantId": "2023382108491247617", "restaurantName": "七间房全羊馆",
|
||||||
|
"dishId": "2100864423122898946", "dishCode": "HL7741A", "dishName": "HL7741-TEST-餐食A",
|
||||||
|
"mealType": "BREAKFAST", "mealDate": "2026-10-21",
|
||||||
|
"unitPrice": 30, "personCount": 2, "amount": 60.00,
|
||||||
|
"settleType": "sign", "settleTypeName": "签单"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 响应示例
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"message": "成功",
|
||||||
|
"success": true,
|
||||||
|
"data": {
|
||||||
|
"orderId": "2100864597505286145",
|
||||||
|
"generated": true,
|
||||||
|
"orderEditable": true,
|
||||||
|
"totalAmount": 1710.00,
|
||||||
|
"items": [
|
||||||
|
{ "mealInfoId": "2100883161750687746", "mealType": "LUNCH", "mealDate": "2026-10-20", "dayNumber": 1, "tableCount": 0, "personCount": 4, "freePersonCount": 1, "amount": 100.00 },
|
||||||
|
{ "mealInfoId": "2100883161754882049", "mealType": "DINNER", "mealDate": "2026-10-20", "dayNumber": 1, "tableCount": 2, "personCount": 0, "freePersonCount": 0, "amount": 1550.00 },
|
||||||
|
{ "mealInfoId": "2100883192117448705", "mealType": "BREAKFAST", "mealDate": "2026-10-21", "dayNumber": null, "tableCount": 0, "personCount": 2, "freePersonCount": 0, "amount": 60.00 }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
(`items` 每行实际返回 1 号接口出参的全部字段,此处省略餐厅、餐食等字段。)
|
||||||
|
|
||||||
|
#### 空数据 / 降级响应
|
||||||
|
|
||||||
|
`items` 传空数组表示这张订单一行都不留:原有行全部删除,返回 `items=[]`、`totalAmount=0`、`generated=false`。
|
||||||
|
|
||||||
|
#### 错误响应
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "code": 589613, "message": "金额与明细对不上,请刷新后重试", "success": false, "data": null }
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 业务边界
|
||||||
|
|
||||||
|
- 金额公式:桌数为 0 时 **金额 = 单价 ×(人数 − 免人数)− 免金额 + 其他成本**;桌数不为 0 时 **金额 = 单价 × 桌数 − 免金额 + 其他成本**;算出负数存 0,四舍五入到两位小数。后端按同一公式逐行核对,任何一行对不上返回 589613,整批不保存。
|
||||||
|
- 带 `mealInfoId` 的行整行覆盖:可选字段不传按清空处理(数值取 0,类别取 LUNCH);`dayNumber` 保持原值。
|
||||||
|
- `mealInfoId` 必须是这张订单未删除的行:查不到或已删除 589606;原来挂的不是这张订单 589611。
|
||||||
|
- 餐厅、餐食、单价、付款方式按页面传的原样保存,不回查资源服务;保存前餐食被下架或删除也照常保存。
|
||||||
|
- 订单已完成或已取消 589607;`groupBatchId` 与订单所属团期不一致 589601;整批一个事务,任何错误都不写入。
|
||||||
|
|
||||||
|
### 4. 重置用餐信息 `POST /v3/admin/order/meal-info/reset`
|
||||||
|
|
||||||
|
**VO**: `OrderMealInfoResetReqVO` → `OrderMealInfoListRespVO`
|
||||||
|
|
||||||
|
#### 使用场景
|
||||||
|
|
||||||
|
把这张订单的用餐行全部删掉(含人工改过的、手动加的),再按产品快照重新生成一套空行,结果与第一次调 2 号接口一致。要模版的,重置后再调 7 号接口。
|
||||||
|
|
||||||
|
#### 入参
|
||||||
|
|
||||||
|
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||||||
|
|------|------|------|------|------|------|
|
||||||
|
| orderId | Body | String | ✅ | 正数 | 订单ID |
|
||||||
|
|
||||||
|
#### 出参 `Result<OrderMealInfoListRespVO>`
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| data | Object | 重置后按该订单查询的结果,字段同 1 号接口出参;行ID全部是新的 |
|
||||||
|
|
||||||
|
#### 请求示例
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "orderId": "2100864597505286145" }
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 响应示例
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"message": "成功",
|
||||||
|
"success": true,
|
||||||
|
"data": {
|
||||||
|
"orderId": "2100864597505286145",
|
||||||
|
"generated": true,
|
||||||
|
"totalAmount": 0.00,
|
||||||
|
"items": [
|
||||||
|
{ "mealInfoId": "2100883161750687746", "mealType": "LUNCH", "mealDate": "2026-10-20", "dayNumber": 1, "dishName": null, "restaurantName": null, "unitPrice": 0.00, "tableCount": 0, "personCount": 0, "amount": 0.00 }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
(TEST 实测,节选 1 行与部分字段,字段同 1 号接口。)
|
||||||
|
|
||||||
|
#### 空数据 / 降级响应
|
||||||
|
|
||||||
|
订单出发或返回日期为空时:原有行照样删除、不生成新行,**返回成功**,`message` 为 589602 的提示文案,`items=[]`。
|
||||||
|
|
||||||
|
#### 错误响应
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "code": 589607, "message": "订单已完成或已取消,不能修改用餐信息", "success": false, "data": null }
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 业务边界
|
||||||
|
|
||||||
|
- 删除和重新生成在一个事务里;返回日期早于出发日期 589612,此时不删也不生成。
|
||||||
|
- 不受 2 号接口「已有行就不再生成」的限制。
|
||||||
|
- 订单不存在、无操作权限按订单模块现有错误返回;已完成或已取消 589607。
|
||||||
|
|
||||||
|
### 5. 查询用餐模版 `GET /v3/admin/order/meal-template/list`
|
||||||
|
|
||||||
|
**VO**: `MealTemplateListReqVO` → `List<MealTemplateRespVO>`
|
||||||
|
|
||||||
|
#### 使用场景
|
||||||
|
|
||||||
|
「用餐」页签选择模版时,列出模版及其内容。
|
||||||
|
|
||||||
|
#### 入参
|
||||||
|
|
||||||
|
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||||||
|
|------|------|------|------|------|------|
|
||||||
|
| templateId | Query | String | 否 | — | 模版ID精确匹配;传了忽略 templateName |
|
||||||
|
| templateName | Query | String | 否 | ≤500 | 模版名精确匹配;两个都不传返回全部模版 |
|
||||||
|
|
||||||
|
#### 出参 `Result<List<MealTemplateRespVO>>`
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| [].templateId | String | 模版ID;同一个模版的行共用 |
|
||||||
|
| [].templateName | String | 模版名;允许重名,重名的是各自独立的模版 |
|
||||||
|
| [].items[].id | String | 模版行ID |
|
||||||
|
| [].items[].dayNumber | Integer | 第几日,从 1 开始 |
|
||||||
|
| [].items[].mealType | String | 餐次 BREAKFAST / LUNCH / DINNER |
|
||||||
|
| [].items[].restaurantId | String | 餐厅ID,可为 null |
|
||||||
|
| [].items[].restaurantName | String | 餐厅名称,可为 null |
|
||||||
|
| [].items[].dishId | String | 餐食ID,可为 null |
|
||||||
|
| [].items[].dishCode | String | 餐食编码,可为 null |
|
||||||
|
| [].items[].dishName | String | 餐食名称,可为 null |
|
||||||
|
| [].items[].unitPrice | Number | 价钱 |
|
||||||
|
| [].items[].settleType | String | 付款方式编码,可为 null |
|
||||||
|
| [].items[].settleTypeName | String | 付款方式中文,可为 null |
|
||||||
|
|
||||||
|
#### 请求示例
|
||||||
|
|
||||||
|
```http
|
||||||
|
GET /v3/admin/order/meal-template/list?templateId=2100883046935748610
|
||||||
|
Authorization: Bearer <admin token>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 响应示例
|
||||||
|
|
||||||
|
TEST 实测返回(节选 1 行):
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"message": "成功",
|
||||||
|
"success": true,
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"templateId": "2100883046935748610",
|
||||||
|
"templateName": "HL7741-TEST-含营地",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"id": "2100883046935748611",
|
||||||
|
"dayNumber": 1,
|
||||||
|
"mealType": "LUNCH",
|
||||||
|
"restaurantId": "2023382108491247617",
|
||||||
|
"restaurantName": "七间房全羊馆",
|
||||||
|
"dishId": "2100864423122898946",
|
||||||
|
"dishCode": "HL7741A",
|
||||||
|
"dishName": "HL7741-TEST-餐食A",
|
||||||
|
"unitPrice": 30.00,
|
||||||
|
"settleType": "sign",
|
||||||
|
"settleTypeName": "签单"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 空数据 / 降级响应
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "code": 200, "message": "成功", "success": true, "data": [] }
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 错误响应
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "code": 581045, "message": "房务角色无权查看订单详情,房务仅可配房", "success": false, "data": null }
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 业务边界
|
||||||
|
|
||||||
|
- 按模版ID分组,模版之间按保存先后排序;同一个模版内按第几日升序、早午晚排序。
|
||||||
|
- 模版里存的是快照:餐食或餐厅后来被下架、删除,照常返回存下的名称和价钱。
|
||||||
|
- 模版不存用餐日期、桌数、人数、免人数、免金额、其他成本、金额。
|
||||||
|
|
||||||
|
### 6. 保存为用餐模版 `POST /v3/admin/order/meal-template/save`
|
||||||
|
|
||||||
|
**VO**: `MealTemplateSaveReqVO` → `MealTemplateRespVO`
|
||||||
|
|
||||||
|
#### 使用场景
|
||||||
|
|
||||||
|
在「用餐」页签把已排好的几行存成模版,模版名自己取。
|
||||||
|
|
||||||
|
#### 入参
|
||||||
|
|
||||||
|
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||||||
|
|------|------|------|------|------|------|
|
||||||
|
| templateName | Body | String | ✅ | 去首尾空格后 1–500 | 模版名;允许和已有模版重名 |
|
||||||
|
| mealInfoIds | Body | Array<String> | ✅ | 非空,自动去重 | 要存进模版的用餐信息行ID |
|
||||||
|
|
||||||
|
#### 出参 `Result<MealTemplateRespVO>`
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| data | Object | 新模版,结构同 5 号接口的一个元素(含新生成的 `templateId`) |
|
||||||
|
|
||||||
|
#### 请求示例
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"templateName": "HL7741-TEST-含营地",
|
||||||
|
"mealInfoIds": ["2100883161750687746", "2100883161754882049", "2100883192117448705", "2100883161759076354"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 响应示例
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"message": "成功",
|
||||||
|
"success": true,
|
||||||
|
"data": {
|
||||||
|
"templateId": "2100883046935748610",
|
||||||
|
"templateName": "HL7741-TEST-含营地",
|
||||||
|
"items": [
|
||||||
|
{ "id": "2100883046935748611", "dayNumber": 1, "mealType": "LUNCH", "dishName": "HL7741-TEST-餐食A", "unitPrice": 30.00, "settleType": "sign", "settleTypeName": "签单" },
|
||||||
|
{ "id": "2100883047007051777", "dayNumber": 1, "mealType": "DINNER", "dishName": "HL7741-TEST-餐食B", "unitPrice": 800.00, "settleType": "cash", "settleTypeName": "现付" },
|
||||||
|
{ "id": "2100883047032217601", "dayNumber": 2, "mealType": "BREAKFAST", "dishName": "HL7741-TEST-餐食A", "unitPrice": 30.00, "settleType": "sign", "settleTypeName": "签单" },
|
||||||
|
{ "id": "2100883047007051778", "dayNumber": 2, "mealType": "LUNCH", "dishName": "HL7741-TEST-餐食A", "unitPrice": 30.00, "settleType": "sign", "settleTypeName": "签单" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
(请求为示例;响应行取自 TEST 实测模版,节选字段,实际返回 5 号接口 `items[]` 的全部字段。第 2 日早餐是手动加的行,按最早日期补成第 2 日。)
|
||||||
|
|
||||||
|
#### 空数据 / 降级响应
|
||||||
|
|
||||||
|
`mealInfoIds` 一行都取不到(都已删除或不存在)时返回 589606,不建模版;部分取不到时只存取到的行。
|
||||||
|
|
||||||
|
#### 错误响应
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "code": 400, "message": "用餐信息行ID不能为空; 模版名不能为空", "success": false, "data": null }
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 业务边界
|
||||||
|
|
||||||
|
- 每次保存都新建一个模版(新的 `templateId`),不覆盖任何已有模版,名字一样也一样。
|
||||||
|
- 第几日:行上有第几天直接用;没有(手动加的行)时以这批行里最早的用餐日期为第 1 日,按实际相差天数补。
|
||||||
|
- 同一日同一餐出现多条返回 400,提示「第 d 日某餐重复」。
|
||||||
|
- 存餐厅、餐食、餐次、第几日、价钱、付款方式(编码和中文);房务角色 581045。
|
||||||
|
|
||||||
|
### 7. 套用用餐模版 `POST /v3/admin/order/meal-template/apply`
|
||||||
|
|
||||||
|
**VO**: `MealTemplateApplyReqVO` → `OrderMealInfoListRespVO`
|
||||||
|
|
||||||
|
#### 使用场景
|
||||||
|
|
||||||
|
「用餐」页签选一个模版套到当前订单上。
|
||||||
|
|
||||||
|
#### 入参
|
||||||
|
|
||||||
|
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||||||
|
|------|------|------|------|------|------|
|
||||||
|
| orderId | Body | String | ✅ | 正数 | 订单ID |
|
||||||
|
| templateId | Body | String | ✅ | — | 模版ID |
|
||||||
|
|
||||||
|
#### 出参 `Result<OrderMealInfoListRespVO>`
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| data | Object | 套用后按该订单查询的结果,字段同 1 号接口出参 |
|
||||||
|
|
||||||
|
#### 请求示例
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "orderId": "2100864597505286145", "templateId": "2100883046935748610" }
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 响应示例
|
||||||
|
|
||||||
|
TEST 实测:模版第 1 日午餐覆盖到出发日那天已有的午餐行(同一行ID),模版第 2 日早餐订单上没有,新建一行:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"message": "成功",
|
||||||
|
"success": true,
|
||||||
|
"data": {
|
||||||
|
"orderId": "2100864597505286145",
|
||||||
|
"generated": true,
|
||||||
|
"items": [
|
||||||
|
{ "mealInfoId": "2100883161750687746", "mealType": "LUNCH", "mealDate": "2026-10-20", "dayNumber": 1, "dishName": "HL7741-TEST-餐食A", "unitPrice": 30.00, "settleType": "sign", "tableCount": 0, "personCount": 0, "amount": 0.00 },
|
||||||
|
{ "mealInfoId": "2100883192117448705", "mealType": "BREAKFAST", "mealDate": "2026-10-21", "dayNumber": 2, "dishName": "HL7741-TEST-餐食A", "unitPrice": 30.00, "settleType": "sign", "tableCount": 0, "personCount": 0, "amount": 0.00 },
|
||||||
|
{ "mealInfoId": "2100883161759076355", "mealType": "DINNER", "mealDate": "2026-10-21", "dayNumber": 2, "restaurantName": "HL7741-TEST-原行", "dishName": null, "unitPrice": 20.00, "settleType": null, "tableCount": 0, "personCount": 3, "amount": 60.00 }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
(TEST 实测,节选字段与行:模版没有第 2 日晚餐,订单原来的那一行不动。)
|
||||||
|
|
||||||
|
#### 空数据 / 降级响应
|
||||||
|
|
||||||
|
订单出发日期为空时不套用,**返回成功**,`message` 为 589602 的提示文案,行不变。模版ID不存在或模版没有行时什么都不改,返回订单当前的行。
|
||||||
|
|
||||||
|
#### 错误响应
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "code": 589607, "message": "订单已完成或已取消,不能修改用餐信息", "success": false, "data": null }
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 业务边界
|
||||||
|
|
||||||
|
- 订单出发日是第 1 日,模版第 d 日落到出发日 + d − 1。
|
||||||
|
- 模版第 d 日某餐有安排:订单上已有那天那一餐的行,覆盖餐厅(ID、名称)、餐食(ID、编码、名称)、价钱、付款方式(编码、中文),金额按新价钱用同一公式重算;没有那一行就新建一行,桌数、人数、免人数、免金额、其他成本为 0。
|
||||||
|
- 模版里没有的第 d 日、或第 d 日没有的那一餐,订单原来的行不动。
|
||||||
|
- 模版里的餐食、餐厅被下架或删除,仍用模版里存的名称和价钱。订单已完成或已取消 589607。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、契约约束与正确调用方式
|
||||||
|
|
||||||
|
### ✅ 正确 / ❌ 错误 payload 对照
|
||||||
|
|
||||||
|
| 场景 | payload | 结果 |
|
||||||
|
|------|---------|------|
|
||||||
|
| ✅ 按人算 | `{ "unitPrice": 30, "tableCount": 0, "personCount": 4, "freePersonCount": 1, "otherCost": 10, "amount": 100.00 }` | 保存成功 |
|
||||||
|
| ✅ 按桌算 | `{ "unitPrice": 800, "tableCount": 2, "personCount": 0, "freePersonCount": 0, "freeAmount": 100, "otherCost": 50, "amount": 1550.00 }` | 保存成功 |
|
||||||
|
| ✅ 算出负数 | `{ "unitPrice": 30, "personCount": 2, "freeAmount": 100, "amount": 0 }` | 保存成功,金额 0 |
|
||||||
|
| ❌ 金额对不上 | `{ "unitPrice": 30, "personCount": 4, "freePersonCount": 1, "otherCost": 10, "amount": 99.99 }` | 589613,整批不保存 |
|
||||||
|
| ❌ 类别传 SELF | `{ "mealType": "SELF", "mealDate": "2026-10-20" }` | 400 |
|
||||||
|
|
||||||
|
### 需要前端配合的两点
|
||||||
|
|
||||||
|
1. **人数与桌数二选一**:人数不为 0 时,桌数不能点击并设成 0;桌数不为 0 时,人数、免人数不能点击并设成 0。后端只按「桌数是否为 0」选公式。
|
||||||
|
2. **类别下拉过滤 SELF**:字典 `meal_type` 的 SELF 值不要出现在类别下拉里。
|
||||||
|
|
||||||
|
### 保存时的整单语义
|
||||||
|
|
||||||
|
3 号接口的 `items` 必须是页面上这张订单的**全部**行。只提交改动过的行会把其余行删掉。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、数据库行为
|
||||||
|
|
||||||
|
| 前端操作 | 结果 |
|
||||||
|
|----------|------|
|
||||||
|
| 2 号生成 | 该订单没有用餐行时写入一批空行;已有行时不写 |
|
||||||
|
| 3 号保存 | 带ID的行整行覆盖,不带ID的新增,没传上来的原有行软删除;任一行失败整批不写 |
|
||||||
|
| 4 号重置 | 软删除该订单全部用餐行,再写入一批新空行;一个事务 |
|
||||||
|
| 6 号存模版 | 新增一组模版行(新模版ID),不改任何已有模版 |
|
||||||
|
| 7 号套模版 | 覆盖对应日期对应餐次的行、新建缺少的行;其余行不动 |
|
||||||
|
|
||||||
|
被删除的行不会再出现在任何查询结果里。订单后来改出发日期或人数,已生成的用餐行不会跟着变(需要时调 4 号重置)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六、边界行为
|
||||||
|
|
||||||
|
- 未登录 → 401(网关拦截)。
|
||||||
|
- 房务角色调 1、5、6 号及写接口 → 581045。
|
||||||
|
- 订单不存在 → 订单模块现有「订单不存在」错误。
|
||||||
|
- 订单已完成或已取消 → 2、3、4、7 号返回 589607,不写入;1 号照常可查,`orderEditable=false`。
|
||||||
|
- 餐食、餐厅被下架或删除 → 已保存的用餐行与模版照常显示存下的名称和价钱。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六.5、枚举 / 数据字典
|
||||||
|
|
||||||
|
### mealType(类别 / 餐次)
|
||||||
|
|
||||||
|
**所属字段**: `mealType`(3、5、6、7 号入参或出参) | **类型**: `String`
|
||||||
|
|
||||||
|
| 值 | 中文 | 说明 |
|
||||||
|
|----|------|------|
|
||||||
|
| `BREAKFAST` | 早餐 | — |
|
||||||
|
| `LUNCH` | 午餐 | 3 号接口不传时的默认值 |
|
||||||
|
| `DINNER` | 晚餐 | — |
|
||||||
|
|
||||||
|
### settleType(付款方式,字典 `resource_settle_type`)
|
||||||
|
|
||||||
|
**所属字段**: `settleType` / `settleTypeName` | **类型**: `String`
|
||||||
|
|
||||||
|
| 值 | 中文 | 说明 |
|
||||||
|
|----|------|------|
|
||||||
|
| `cash` | 现付 | — |
|
||||||
|
| `sign` | 签单 | — |
|
||||||
|
| `company` | 公司付款 | — |
|
||||||
|
|
||||||
|
### 错误码(hl-order-service-v3,段位 589600–589699)
|
||||||
|
|
||||||
|
| code | message | 触发接口 |
|
||||||
|
|------|---------|----------|
|
||||||
|
| 589601 | 订单不属于该团期 | 3 |
|
||||||
|
| 589602 | 订单出发或返回日期为空,无法生成用餐信息 | 2、4、7(只作提示:`code` 200,文案放在 `message`) |
|
||||||
|
| 589606 | 用餐信息不存在 | 3、6 |
|
||||||
|
| 589607 | 订单已完成或已取消,不能修改用餐信息 | 2、3、4、7 |
|
||||||
|
| 589611 | 已挂订单或团期的用餐信息不能改挂或清空 | 3 |
|
||||||
|
| 589612 | 返回日期早于出发日期,无法生成用餐信息 | 2、4 |
|
||||||
|
| 589613 | 金额与明细对不上,请刷新后重试 | 3 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 七、不影响范围
|
||||||
|
|
||||||
|
- **仅影响**:订单详情「用餐」页签(全新接口)。
|
||||||
|
- **零影响**:
|
||||||
|
- 订单、团期、核单等现有接口的入参出参;
|
||||||
|
- 餐食管理、餐厅选项接口(本单只读用它们的数据);
|
||||||
|
- 历史订单:不会自动生成用餐行,打开页签时才按 2 号接口生成。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 八、测试环境已验证
|
||||||
|
|
||||||
|
部署 hl-order-service-v3(dev-v3,最终部署提交 6a121038b,含 #7945 与 #7954),经 Gateway 用管理员身份逐项实测,假数据名称均带 `HL7741-TEST`:
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /v3/admin/order/meal-info/generate → 只为含营地/特色餐/正餐生成 6 行空行,含酒店、自理不生成;再调不重复 ✓
|
||||||
|
POST /v3/admin/order/meal-info/save → 新增+改+少传一行:新增有、改的变、少传的软删;按人 100.00、按桌 1550.00、负数存 0、免人数>人数照存 ✓
|
||||||
|
POST /v3/admin/order/meal-info/save → 金额写错 → 589613,库里行不变 ✓;餐食下架/删除后照存页面值 ✓
|
||||||
|
POST /v3/admin/order/meal-info/save → 行ID已删除/不存在 → 589606;别的订单的行 → 589611,两单行不变 ✓
|
||||||
|
POST /v3/admin/order/meal-template/save → 模版只存模版名/第几日/餐次/餐厅/餐食/价钱/付款方式;同名再存是新模版,老模版不变 ✓
|
||||||
|
POST /v3/admin/order/meal-info/reset → 原有行(含改过的、手动加的)全部软删,重新生成与首次一致 ✓
|
||||||
|
POST /v3/admin/order/meal-template/apply → 第 1 日落出发日;已有行覆盖、缺的新建、模版缺的不动;餐食下架/删除后仍用模版名称和价钱 ✓
|
||||||
|
POST /v3/admin/order/{id}/adjustment/submit(改出发日期)→ 已生成的用餐行不变 ✓
|
||||||
|
已取消 / 已完成订单调 2、3、4、7 号 → 589607,零写入 ✓
|
||||||
|
GET /v3/admin/order/meal-info/list(没挂团期的订单 + 团期ID / 团期编号)→ 回显同一团期的ID和编号 ✓
|
||||||
|
```
|
||||||
|
|
||||||
|
验证订单:`2100864597505286145`(HL7741-TEST-orderA)、`2100864614022451201`(HL7741-TEST-orderB,已取消)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 十、相关文档
|
||||||
|
|
||||||
|
- 关联 Issue: [wx/HL#7741](https://git.1814.love:8443/wx/HL/issues/7741)、[wx/HL#7953](https://git.1814.love:8443/wx/HL/issues/7953)
|
||||||
|
- 关联 PR: [wx/HL#7945](https://git.1814.love:8443/wx/HL/pulls/7945)、[wx/HL#7954](https://git.1814.love:8443/wx/HL/pulls/7954)
|
||||||
|
- 依赖接口:餐食下拉 `GET /admin/dish/items/list`(#7737)、餐厅选项 `GET /admin/resource-options/restaurants`
|
||||||
|
|
||||||
|
## 关联 / 联系人
|
||||||
|
|
||||||
|
### 链接
|
||||||
|
|
||||||
|
- **Issue**: [#7741](https://git.1814.love:8443/wx/HL/issues/7741)、[#7953](https://git.1814.love:8443/wx/HL/issues/7953)
|
||||||
|
- **PR**: [#7945](https://git.1814.love:8443/wx/HL/pulls/7945)、[#7954](https://git.1814.love:8443/wx/HL/pulls/7954)
|
||||||
|
- **Merge commit**: [f284bad1](https://git.1814.love:8443/wx/HL/commit/f284bad157f0b7da9f10d36e7a5f0ad5a0d1978b)(#7945)、[6a121038](https://git.1814.love:8443/wx/HL/commit/6a121038b5ae4b5fac8af9ee7b89482f860e810e)(#7954)
|
||||||
|
|
||||||
|
### 联系人
|
||||||
|
|
||||||
|
- **后端负责人**: @lc
|
||||||
在新工单中引用
屏蔽一个用户