每个门店一份菜单
每个门店只有一份菜单。一个门店不存在多份命名菜单(例如分开的“早餐菜单”和“晚餐菜单”)的概念,不同时段的差异是在这唯一的菜单_内部_通过供应时段来表达的。 发布会整体替换这份菜单(以差异方式应用,见下文)。Maple 在内部保留版本历史,并始终提供当前版本,但从您这一侧看,模型很简单:一个门店,一份菜单,由您完整发布。如果您自己的系统为每个门店建模了多份菜单,请在发布之前把它们合并成一份 Maple 菜单,通常做法是拆成各自带有供应时段的独立分类。
树结构
菜单是由三层嵌套对象组成的树,其中引用了共享的定义:- 分类(Category):菜单中的一个板块(饮品、主菜)。可以设置分时段,使其只在特定时间窗口内显示。
- 菜品(Item):一个菜品。有一个或多个规格,并可携带加料组、税和费用。
- 规格(Variation):菜品的一种可购买形态(小杯 / 大杯,或只是“常规”)。价格在这里。 每个菜品至少有一个规格。
- 加料组(Modifier group):一组带有选择规则的选项(牛奶、加料选项)。可以定义一次后共享,也可以内联在菜品上。选项本身还可以带有嵌套的加料组。
映射您自己的商品目录
大多数集成方已经有自己的菜单模型。下表是常见概念的映射方式,一开始就做对可以避免最常见的错误:外部 ID 归您所有
每个对象(分类、菜品、规格、加料组、选项、税率、费用)都带有一个由您分配并拥有的externalId。Maple 绝不会更改它。这是整个模型的支柱:
- 使用相同的
externalId重新发布,会更新同一个对象,而不是创建重复对象。 - 订单行项目通过这些 ID(
menu_entity_id)引用菜单,因此传入的订单可以直接映射回您的商品目录。 - Maple 也会在响应中生成自己的 ID(
item_…、var_…、ctg_…)供参考,但您始终通过自己的externalId来寻址一切。 - 对象之间同样通过
externalId相互引用。 当加料组引用使用groupId、菜品通过taxRateIds指向税率,或促销通过discountId指定折扣时,这些值都是您分配的externalId,而不是 Maple 生成的 ID。
定价
价格是对象,而不是单纯的数字,因此模型可以表达的不止一个固定金额。基本结构是以整数最小货币单位表示的金额加上币种:fixed、variable 开放金额、用于称重商品的 per_unit、按数量分档的 bulk)、含税定价、按币种覆盖,以及划线价(compare-at)。对于常见情况,即单一币种的固定价格,您只需要 amount。请参阅金额与货币。
加料选项
加料组包含选择规则和一组选项。规则比简单的最小/最大值更丰富,这让您可以表达诸如“最多选 3 个,但同一种不超过 2 个”之类的要求:
通过
groupId 从菜品或规格中引用共享加料组,或者内联定义一个。在同一个条目中,这两种形式互斥:引用只带 groupId;定义则带 name 和 options。混用会被拒绝,而不是被悄悄截断。选项可以带有自己的嵌套加料组,用于自选组合流程。请参阅菜单示例了解完整示例。
订单资源目前会在每个行项目上展示直接选择的第一级加料选项。更深层的嵌套选择暂时不会展开到订单资源中。
税费
这些是顶层定义,您通过 ID 将它们挂接到菜品上:- 税类别和税率:税率可以是
percentage、flat或基于bracket,计税基数可配置,可含税或不含税。通过taxCategoryId/taxRateIds挂接。 - 费用:附加费和押金(瓶装押金或 CRV),通过
feeIds挂接。 - 折扣、促销和优惠券:用于降价的可选顶层集合。
供应时段与分时段菜单
供应时段是您表达分时段菜单的方式,它取代了多份菜单的想法。- 设置了供应时段的分类只会在该时段内显示(早餐供应到 11:00)。
- 菜品也可以带有自己的时段。
- 没有设置供应时段的对象始终可供应。
dayOfWeek:0(星期日)到6(星期六)。每个供应日添加一个时段。startTime/endTime:本地HH:MM,24 小时制。
timezone 字段设置(IANA,例如 America/New_York)。未设置时默认为 UTC,因此请在首次发布时设置,请参阅为供应时段设置时区。
“每日特供”或早餐板块,就是一个设置了相应时段、位于唯一那份菜单中的分类(或菜品)。请参阅每日特供示例。
库存状态
库存状态为in_stock、out_of_stock 或 low_stock。发布时,省略该字段会保留当前值;全新的对象默认为 in_stock。您可以用它给某个菜品“下架”(86),而无需重新发布整份菜单的结构。
发布会替换整份菜单
您始终需要把整份菜单作为期望状态发送。Maple 按externalId 以差异方式应用:
- 校验是全有或全无:
400会列出所有问题,并且不做任何更改。 - 相同内容的重新发布不会产生任何变化,对象标识保持稳定,因此您可以在每次菜单变化时发布,而不会产生波动。