- 配比秤采样提交接口新增字段 cookStart,传递烹饪开始时间 - 食材构成中调料项新增 putTime 字段,记录调料首次使用时间 - 设备端提交采样时食材构造调整,调料按名称匹配 putTime 填充 - 新增对烹饪时长的后端计算功能,时长单位为分钟自动向上取整 - 采样列表接口响应新增 cookStart 与 cookDuration 字段,用于显示烹饪时长 - 配比秤采样模式相关API文档同步更新,废弃制作模式接口及字段 - 烹饪完成接口要求强化传递 cookStart,后端基于此计算并更新烹饪时长 - 关联数据库迁移支持烹饪时长字段持久化及历史记录完善
352 lines
11 KiB
Markdown
352 lines
11 KiB
Markdown
# 配比秤(新设备)— 采样模式 API 文档
|
||
|
||
> Controller: `NutRatioScaleController`
|
||
> 路径前缀: `/neglect/ratio-scale`(Nacos 白名单 `/nutrition/neglect/**`,无需 Sa-Token)
|
||
> 设备上下文通过请求头 `X-DEVICE-CODE` 解析(`TerminalContextHelper`,据此拿到食堂 id)
|
||
> 日期: 2026-09-10
|
||
>
|
||
> **序列化规则**:Long 类型字段响应中均为字符串(Jackson `ToStringSerializer`),`BigDecimal` 为普通数字
|
||
> **单位约定**:
|
||
> - 提交采样的熟重 `foodWeight` 单位为 **克 (g)**
|
||
> - 食材称量用量 `useWeight` 单位为 **克 (g)**
|
||
|
||
---
|
||
|
||
## 业务背景
|
||
|
||
配比秤「采样」复用 **味养创新(nut_innovation)** 的人工创新实验流程,不再直接落 `nut_food` 主表。
|
||
|
||
### 完整流程(3 步)
|
||
|
||
```
|
||
① 提交采样(设备端) → 落库味养创新实验,状态 = 1 实验中
|
||
② 提交评测(味养创新后台)→ 计算营养 + 完善检验信息,状态 = 2 已评测
|
||
③ 转化餐品(味养创新后台)→ 走 nut_food 新建餐品流程关联,状态 = 9 已转化
|
||
```
|
||
|
||
### 设备端职责边界
|
||
|
||
配比秤设备端只负责 **① 提交采样**(称量食材 + 熟重 → 写味养创新实验)。后续的 **② 提交评测**、**③ 转化餐品** 走味养创新已有的后台接口(`/nut/innovation`),不在设备端范围内。
|
||
|
||
### 采样交互流程
|
||
|
||
```
|
||
搜菜品(food-search)
|
||
│
|
||
├─ 有目标餐品 → 查菜品构成(food/{foodId}/composition)回显 → 可增删构成
|
||
│
|
||
└─ 无目标餐品 → 食材模糊搜索(mater-search)自己添加食材/调料
|
||
│
|
||
▼
|
||
提交采样(constitute/save)→ 落库味养创新
|
||
```
|
||
|
||
### 食材分类枚举
|
||
|
||
| 分类 | 名称 | 说明 |
|
||
|:----:|------|------|
|
||
| 1 | 主材 | 菜品主要食材 |
|
||
| 2 | 辅材 | 菜品辅助食材 |
|
||
| 3 | 调料 | 油盐酱醋等 |
|
||
|
||
---
|
||
|
||
## 接口清单
|
||
|
||
| 序号 | 接口 | 路径 | 用途 |
|
||
|:----:|------|------|------|
|
||
| 一 | 搜菜品 | `POST /neglect/ratio-scale/food-search` | 按名称模糊查上架菜品 |
|
||
| 二 | 查菜品构成 | `GET /neglect/ratio-scale/food/{foodId}/composition` | 按菜品id查主辅料+调料,回显构成 |
|
||
| 三 | 食材模糊搜索 | `POST /neglect/ratio-scale/mater-search` | 采样称量前检索食材 |
|
||
| 四 | 提交采样 | `POST /neglect/ratio-scale/constitute/save` | **落库味养创新实验** |
|
||
| 五 | 已提交采样列表 | `POST /neglect/ratio-scale/sample-list` | 按日期查已提交采样,默认当天 |
|
||
|
||
---
|
||
|
||
## 一、搜菜品
|
||
|
||
```
|
||
POST /neglect/ratio-scale/food-search
|
||
Content-Type: application/json
|
||
X-DEVICE-CODE: <设备编码>
|
||
```
|
||
|
||
根据餐厅查餐品名称,供硬件端选择目标菜品(有该餐品时回显其构成)。
|
||
|
||
### 请求体
|
||
|
||
```json
|
||
{
|
||
"keyword": "西兰花", // 选填 — 菜品名称或编号模糊搜索
|
||
"pageNum": 1, // 必填 — 页码
|
||
"pageSize": 20 // 必填 — 每页条数
|
||
}
|
||
```
|
||
|
||
### 响应
|
||
|
||
```json
|
||
{
|
||
"code": "00000",
|
||
"msg": "操作成功",
|
||
"data": [
|
||
{
|
||
"foodId": "2091839370283118593", // 菜品id
|
||
"foodCode": "FOOD00012", // 菜品编号
|
||
"foodName": "清炒西兰花" // 菜品名称
|
||
}
|
||
],
|
||
"total": 1
|
||
}
|
||
```
|
||
|
||
### 逻辑说明
|
||
|
||
- 数据源:`nut_food`(`status=1` 上架)
|
||
- 过滤:`canteen_id` = 当前食堂
|
||
- 关键词模糊匹配 `food_name` 和 `food_code`
|
||
- 排序:`id DESC`
|
||
|
||
---
|
||
|
||
## 二、查菜品构成
|
||
|
||
```
|
||
GET /neglect/ratio-scale/food/{foodId}/composition
|
||
X-DEVICE-CODE: <设备编码>
|
||
```
|
||
|
||
根据菜品 id 查询已有菜品的主辅料+调料构成及熟重,供硬件端回显构成数据。
|
||
|
||
### 响应
|
||
|
||
```json
|
||
{
|
||
"code": "00000",
|
||
"msg": "操作成功",
|
||
"data": {
|
||
"foodId": "2091839370283118593", // 菜品id
|
||
"foodName": "清炒西兰花", // 菜品名称
|
||
"foodWeight": 450.0, // 熟重(g)
|
||
"ingredients": [
|
||
{
|
||
"materId": "1979825467306471454", // 食材id
|
||
"materName": "樱桃萝卜", // 食材名称
|
||
"useWeight": 300.0, // 用量(g)
|
||
"isMain": 1, // 1=主材 / 2=辅材 / 3=调料
|
||
"isMainName": "主材"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
### 逻辑说明
|
||
|
||
- 数据源:`nut_food_composition`(按 `food_id` 查全部构成)
|
||
- 食材名称从 `nut_mater_base` **批量反查**(无 N+1)
|
||
- `foodWeight` 从 `nut_food_cook.output_weight` 反查
|
||
|
||
---
|
||
|
||
## 三、食材模糊搜索
|
||
|
||
```
|
||
POST /neglect/ratio-scale/mater-search
|
||
Content-Type: application/json
|
||
X-DEVICE-CODE: <设备编码>
|
||
```
|
||
|
||
称量食材前,从食材库检索食材(设备对应食堂食材)。
|
||
|
||
### 请求体
|
||
|
||
```json
|
||
{
|
||
"keyword": "萝卜", // 选填 — 模糊匹配食材名称和别名
|
||
"pageNum": 1, // 必填 — 页码
|
||
"pageSize": 20 // 必填 — 每页条数
|
||
}
|
||
```
|
||
|
||
### 响应
|
||
|
||
```json
|
||
{
|
||
"code": "00000",
|
||
"msg": "操作成功",
|
||
"data": [
|
||
{
|
||
"id": "1979825467306471454", // 食材id
|
||
"materName": "樱桃萝卜", // 食材名称
|
||
"materCode": "04041012", // 食材编码
|
||
"alias": null, // 别名
|
||
"materFirstClass": "04", // 食材一级分类
|
||
"materSecondClass": "043", // 食材二级分类
|
||
"materUrl": null, // 食材图片url
|
||
"canteenId": "2" // 归属食堂id
|
||
}
|
||
],
|
||
"total": 1
|
||
}
|
||
```
|
||
|
||
### 逻辑说明
|
||
|
||
- 数据源:`nut_mater_base`
|
||
- 过滤:`canteen_id` = 当前食堂(由 `X-DEVICE-CODE` 解析)
|
||
- 关键词模糊匹配 `mater_name` 和 `alias`
|
||
- 排序:`mater_name ASC`
|
||
|
||
---
|
||
|
||
## 四、提交采样(落库味养创新)
|
||
|
||
```
|
||
POST /neglect/ratio-scale/constitute/save
|
||
Content-Type: application/json
|
||
X-DEVICE-CODE: <设备编码>
|
||
```
|
||
|
||
> ⚠️ **接口变更标注**:原提交接口含 `cookMode`(区分制作/采样),现制作模式已废弃,本接口统一为「提交采样」,入参去掉 `cookMode`、`foodId` 字段。
|
||
|
||
后厨称量食材 + 熟重后提交,后端落库到 **味养创新实验**(`nut_innovation`,人工创新,状态 = 实验中)。
|
||
|
||
### 请求体
|
||
|
||
```json
|
||
{
|
||
"foodName": "清炒西兰花", // 必填 — 菜品名称
|
||
"foodWeight": 500, // 必填 — 熟重(g),必须 > 0
|
||
"items": [ // 必填 — 食材构成列表,至少1条
|
||
{
|
||
"materId": 20001, // 必填 — 食材id(nut_mater_base.id)
|
||
"useWeight": 300, // 必填 — 食材称量用量(g),必须 > 0
|
||
"isMain": 1 // 必填 — 食材分类: 1=主材 / 2=辅材 / 3=调料
|
||
},
|
||
{
|
||
"materId": 30001,
|
||
"useWeight": 50,
|
||
"isMain": 3
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
### 响应
|
||
|
||
```json
|
||
{
|
||
"code": "00000",
|
||
"msg": "操作成功",
|
||
"data": null
|
||
}
|
||
```
|
||
|
||
### 处理流程
|
||
|
||
```
|
||
1. 校验食材构成非空 + materId 非空且唯一
|
||
2. 反查食材名称(nut_mater_base) + 一级分类名称(nut_mater_class)
|
||
3. 构建味养创新实验 DTO:
|
||
- foodName → food_name
|
||
- foodWeight → food_weight(熟重)
|
||
- items → 食材构成(mater_id + mater_name + mater_cat + amount_g + is_main)
|
||
- canteenId → 从 X-DEVICE-CODE 解析
|
||
- startDate → 回填当天(实验开始日期)
|
||
- source / deviceCode → 来源标识(2) + 设备编码
|
||
- innovGoal → 默认值「配比秤采样」
|
||
4. 调用味养创新 manualAdd,落库 nut_innovation(status=1 实验中)+ nut_innovation_ing(食材构成)
|
||
5. 自动初始化营养:按食材构成 + 熟重计算每100g熟重营养,写入草稿评测事件 nut_innovation_eval(status=0)+ 营养维度 nut_innovation_eval_nutri(7 项:热量/蛋白/碳水/脂肪/维C/膳食纤维/钠,mineral 留空)
|
||
```
|
||
|
||
> 注:设备端不传 `foodCategory`(餐品分类),落库为空,后期在味养创新后台维护;`innovGoal`(创新目标)后端填默认值「配比秤采样」,后续可改。
|
||
|
||
### 异常场景
|
||
|
||
| 场景 | 错误信息 |
|
||
|------|---------|
|
||
| 食材构成列表为空 | `请完善菜品构成信息` |
|
||
| 食材id为空 | `菜品食材不能为空` |
|
||
| 食材id重复 | `菜品食材不能重复,重复食材id:xxx` |
|
||
| 熟重/用量 ≤ 0 | 参数校验:`熟重必须大于0` / `食材用量必须大于0` |
|
||
|
||
### 涉及数据表
|
||
|
||
| 表名 | 操作 | 说明 |
|
||
|------|:--:|------|
|
||
| `nut_innovation` | 新增 | 味养创新实验(status=1 实验中,含熟重 food_weight) |
|
||
| `nut_innovation_ing` | 新增 | 食材构成(mater_id + mater_name + mater_cat + amount_g + is_main) |
|
||
| `nut_innovation_eval` | 新增 | 草稿评测事件(status=0,采样时初始化) |
|
||
| `nut_innovation_eval_nutri` | 新增 | 营养维度(7 项自动计算值,mineral 留空) |
|
||
| `nut_mater_base` | 查询 | 反查食材名称 + 营养数据(计算营养) |
|
||
| `nut_mater_class` | 查询 | 反查一级分类名称 |
|
||
|
||
---
|
||
|
||
## 五、已提交采样列表
|
||
|
||
```
|
||
POST /neglect/ratio-scale/sample-list
|
||
Content-Type: application/json
|
||
X-DEVICE-CODE: <设备编码>
|
||
```
|
||
|
||
查询本食堂已提交的采样记录(味养创新实验 `source=2`),分页返回、按提交时间倒序,供硬件端回看。
|
||
|
||
### 请求体
|
||
|
||
```json
|
||
{
|
||
"pageNum": 1, // 必填 — 页码
|
||
"pageSize": 20 // 必填 — 每页条数
|
||
}
|
||
```
|
||
|
||
### 响应
|
||
|
||
```json
|
||
{
|
||
"code": "00000",
|
||
"msg": "操作成功",
|
||
"data": [
|
||
{
|
||
"innovId": "2097486806812893186", // 味养创新实验id
|
||
"innovNo": "INN-H-2026-001", // 实验编号
|
||
"foodName": "清炒西兰花", // 餐品名称
|
||
"foodWeight": 500.0, // 熟重(g)
|
||
"status": 1, // 状态: 1实验中/2已评测/9已转化
|
||
"statusName": "实验中", // 状态中文
|
||
"createTime": "2026-09-11 10:30:00" // 提交时间
|
||
}
|
||
],
|
||
"total": 1
|
||
}
|
||
```
|
||
|
||
### 逻辑说明
|
||
|
||
- 数据源:`nut_innovation`
|
||
- 过滤:`canteen_id` = 当前食堂 + `source` = 2(配比秤采样,后台手动为 1)
|
||
- 排序:`create_time DESC`(查所有,不分日期)
|
||
|
||
---
|
||
|
||
## 数据链路图(提交采样 → 味养创新)
|
||
|
||
```
|
||
nut_mater_base (食材库)
|
||
│
|
||
│ 称量 mater_id + use_weight(g) + 熟重 food_weight(g)
|
||
▼
|
||
POST /constitute/save
|
||
│
|
||
├── 生成 nut_innovation (味养创新实验,status=1 实验中,含 food_weight)
|
||
├── 生成 nut_innovation_ing (食材构成:mater_id + mater_name + mater_cat + amount_g + is_main)
|
||
└── 自动算营养 → nut_innovation_eval(草稿) + nut_innovation_eval_nutri(7项)
|
||
|
||
后续(味养创新后台,非设备端):
|
||
├── 提交评测 → 复核营养 + 补味道/口感/色泽,status=2 已评测
|
||
└── 转化餐品 → nut_food(新建餐品流程),convert_food_id 关联,status=9 已转化
|
||
```
|