# 通用价目点餐(与美食点餐并存)说明文档 本文描述 **通用价目表(`store_price`)** 点餐能力:与原有 **美食菜品(`store_cuisine`)** 共用订单/明细/购物车等表结构,通过 **`menu_type`、`line_type`、`store_table.type`** 等字段区分;**未删除或替换** 原 `/store/dining`、`/store/order` 接口。 --- ## 1. 概念与约束 | 项目 | 美食点餐 | 通用价目点餐 | |------|----------|----------------| | 商品主数据 | `store_cuisine` | `store_price` | | 桌台 `store_table.type` | `1` 或 `NULL`(按美食处理) | 必须为 **`2`** | | 购物车隔离 | Redis/DB:`menu_type = 1` | Redis 前缀 + DB:`menu_type = 2` | | 订单 `store_order.menu_type` | `1` | `2` | | 明细 `store_order_detail.line_type` | `1`,`cuisine_id` = 菜品 id | `2`,`cuisine_id` 存 **`store_price.id`** | | 优惠规则 `rule_product_type` | `1` 或 `NULL`(指向菜品) | `2`(`product_id` 指向 **`store_price.id`**) | **前端约定:** 通用流程里凡名为 `cuisineId` 的入参(如加购 DTO),语义为 **`store_price.id`**,不是 `store_cuisine.id`。 --- ## 2. 数据库变更 执行脚本(需在目标库执行一次): `alien-dining/src/main/resources/db/generic_ordering_alter.sql` 主要包括:`store_order.menu_type`、`store_order_detail.line_type`、`store_cart.menu_type`、`store_product_discount_rule.rule_product_type` 及索引。 **注意:** 未执行脚本而代码已包含对应实体字段时,读写可能报列不存在。**历史 `store_cart` 行** 建议将美食购物车统一为 `menu_type = 1`(或与脚本默认值一致),否则可能影响美食购物车查询。 --- ## 3. 新接口一览(通用价目) 网关若有统一前缀(如 `/api`),请在下列路径前自行拼接。 **alien-store 透传:** 与美食点餐相同,在 store 侧增加 Feign + 代理控制器后,APP/统一网关可使用 **与 dining 完全一致** 的路径调用: - `GET/POST .../store/generic-dining/...` → `DiningServiceFeign` 透传 alien-dining - `GET/POST .../store/generic-order/...` → 同上;**SSE**:`GET .../store/generic-order/sse/{tableId}`(`DiningSseProxyService.proxyGenericOrderSse`) 支付、订单详情等仍用 **`/store/order/...`**(与美食共用)。 ### 3.1 点餐页 / 券 / 锁单 / 结算预览 **前缀:** `/store/generic-dining` | 方法 | 路径 | 说明 | |------|------|------| | GET | `/page-info` | 开桌/人数,同美食逻辑;**仅 `type=2` 桌** | | GET | `/search` | 按名称搜 `store_price` | | GET | `/cuisines` | 分页列表;可选 `categoryId`(`category_ids` 为 JSON 时用 `JSON_CONTAINS`) | | GET | `/cuisine/{priceItemId}` | 详情,`priceItemId` = `store_price.id` | | GET | `/order/confirm` | 确认页;购物车为通用价目 | | GET | `/coupons/available` | 可领券(与美食共用门店券逻辑) | | POST | `/coupon/receive` | 领券 | | POST | `/order/lock` | 锁单(Redis 键与美食相同:`order:lock:table:{tableId}`) | | POST | `/order/unlock` | 解锁 | | GET | `/order/check-lock` | 查询持锁用户 | | GET | `/order/settlement` | 结算页信息(按 `orderId`) | | POST | `/order/settlement/lock` | 锁结算 | | POST | `/order/settlement/unlock` | 解结算锁 | 以下接口 **仅在美食控制器** 提供,通用桌如需相同能力可继续调旧路径(与桌台业务相关,未复制到 generic): - `/store/dining/walk-in/reservation` - `/store/dining/reservation/detail-by-store-table-record` - `/store/dining/table-dining-status` - `/store/dining/service-fee/estimate` ### 3.2 购物车 / 下单 / SSE **前缀:** `/store/generic-order` | 方法 | 路径 | 说明 | |------|------|------| | GET | `/cart/{tableId}` | 获取通用购物车 | | POST | `/cart/add` | 加购,`AddCartItemDTO.cuisineId` = `store_price.id` | | PUT | `/cart/update` | `tableId`、`cuisineId`(价目 id)、`quantity` | | DELETE | `/cart/remove` | 删除一行 | | DELETE | `/cart/clear` | 清空(保留逻辑与实现一致,参见代码) | | POST | `/cart/set-diner-count` | 用餐人数 | | PUT | `/cart/update-tableware` | 餐具数量 | | POST | `/create` | 创建订单,对应服务方法 **`createGenericOrder`**;须先锁单成功 | | GET | `/sse/{tableId}` | SSE;与美食共用「按桌台」通道,推送内容随业务为购物车或订单事件 | **换桌:** 当前美食侧 `change-table` 未一并迁移通用 Redis 购物车;通用换桌如需与美食一致行为,需在后续迭代扩展(`GenericCartService#migrateCart` 现状为不支持)。 --- ## 4. 与旧接口对照(美食 → 通用) 同一语义的新旧路径对比如下(**旧** 仍保留,并非废弃)。 ### 4.1 点餐域 | 旧(美食) | 新(通用价目) | |------------|----------------| | `GET /store/dining/page-info` | `GET /store/generic-dining/page-info` | | `GET /store/dining/search` | `GET /store/generic-dining/search` | | `GET /store/dining/cuisines` | `GET /store/generic-dining/cuisines` | | `GET /store/dining/cuisine/{cuisineId}` | `GET /store/generic-dining/cuisine/{priceItemId}` | | `GET /store/dining/order/confirm` | `GET /store/generic-dining/order/confirm` | | `GET /store/dining/coupons/available` | `GET /store/generic-dining/coupons/available` | | `POST /store/dining/coupon/receive` | `POST /store/generic-dining/coupon/receive` | | `POST /store/dining/order/lock` | `POST /store/generic-dining/order/lock` | | `POST /store/dining/order/unlock` | `POST /store/generic-dining/order/unlock` | | `GET /store/dining/order/check-lock` | `GET /store/generic-dining/order/check-lock` | | `GET /store/dining/order/settlement` | `GET /store/generic-dining/order/settlement` | | `POST /store/dining/order/settlement/lock` | `POST /store/generic-dining/order/settlement/lock` | | `POST /store/dining/order/settlement/unlock` | `POST /store/generic-dining/order/settlement/unlock` | ### 4.2 订单域(购物车与创建) | 旧(美食) | 新(通用价目) | |------------|----------------| | `GET /store/order/cart/{tableId}` | `GET /store/generic-order/cart/{tableId}` | | `POST /store/order/cart/add` | `POST /store/generic-order/cart/add` | | `PUT /store/order/cart/update` | `PUT /store/generic-order/cart/update` | | `DELETE /store/order/cart/remove` | `DELETE /store/generic-order/cart/remove` | | `DELETE /store/order/cart/clear` | `DELETE /store/generic-order/cart/clear` | | `POST /store/order/cart/set-diner-count` | `POST /store/generic-order/cart/set-diner-count` | | `PUT /store/order/cart/update-tableware` | `PUT /store/generic-order/cart/update-tableware` | | `POST /store/order/create` | `POST /store/generic-order/create` | | `GET /store/order/sse/{tableId}` | `GET /store/generic-order/sse/{tableId}` | --- ## 5. 仍仅使用旧路径的订单能力 以下接口 **未** 提供 `generic-order` 副本,通用价目订单创建后仍通过 **`/store/order/...`** 使用(订单记录上带有 `menu_type=2`): - 支付:`POST /store/order/pay/{orderId}` - 取消:`POST /store/order/cancel/{orderId}` - 详情 / 明细 / 变更记录:`/store/order/detail/...`、`detail/list`、`info`、`change-log` - 分页与我的订单:`/store/order/page`、`/store/order/my-orders` - 换桌:`POST /store/order/change-table`(美食购物车迁移逻辑为主;通用购物车参见上文说明) - 完成订单、商家完成、改券、管理员重置桌等 具体以 `StoreOrderController` 为准。 --- ## 6. 商家后台:创建餐桌、价目进分类(要不要改接口?) ### 6.1 价目表绑定分类 - **一般不需要新接口。** `store_price.category_ids` 存 **JSON 数组字符串**(如 `[1,2,3]`),与 `store_booking_category` 等分类 id 对应即可。 - 使用门店侧已有 **`POST /store/price/save`**、**`POST /store/price/update`**(`StorePriceController`),在 body 里带上 **`categoryIds`**(或实体映射字段)即可。 - 小程序通用点餐列表按分类筛选依赖该字段为 **合法 JSON**;非法 JSON 可能导致 `JSON_CONTAINS` 查询异常。 ### 6.2 创建餐桌(`store_table.type`) - **`POST /store/booking/table/add`**(`StoreBookingTableController`,body:`StoreBookingTableBatchDTO`)**已支持**字段 **`type`**:**`1` = 美食**,**`2` = 通用**;不传默认 **`1`**。建通用价目桌时传 **`type: 2`** 即可,**无需再单独加接口**。 - 若仍使用 **`StoreTableController` 的批量建桌**(如 **`batchCreateTables`** → `StoreTableServiceImpl.batchCreateTables`),当前实现 **不会写入 `type`**,新桌为 **`NULL`**,下单侧会按 **美食桌** 处理。若必须通过该入口建 **通用桌**,需要 **扩展 DTO + 服务**,在落库时设置 **`type = 2`**(或统一改为走预订桌 **`/store/booking/table/add`**)。 --- ## 7. 兼容性说明(旧代码是否仍可用) - **旧 URL 未被移除**:继续使用 `/store/dining`、`/store/order` 的美食流程在设计上仍支持。 - **前提:** 已执行 DDL;美食桌 **`store_table.type` 不为 `2`**(`NULL` 一般仍走美食)。 - **桌台为 `type=2` 时**:美食下单接口会按业务拒绝,须改用 **`/store/generic-order/create`** 等通用入口。 --- ## 8. 关键代码位置(便于维护) | 内容 | 路径 | |------|------| | 常量 | `alien-dining/.../constants/OrderMenuConstants.java` | | DDL | `alien-dining/src/main/resources/db/generic_ordering_alter.sql` | | 通用浏览 | `GenericDiningController`、`GenericDiningServiceImpl` | | 通用购物车 | `GenericCartService`、`GenericCartServiceImpl` | | 通用下单 | `StoreOrderService#createGenericOrder`、`StoreOrderServiceImpl` | | 美食购物车过滤等 | `CartServiceImpl`、`StoreCartMenuFilters` | --- *文档版本:与仓库中通用价目点餐实现同步整理,如有接口增减请以 Swagger / 源码为准。*