# 基础目录

> 供应商、产品与自制备料：记录的其余部分所指向的那几份参照清单。

Source: https://developers.backresto.com/zh/docs/catalogue

基础目录，是一家餐厅列成清单、而不是拿去测量的那些东西：谁来送货、什么东西进了
门、厨房自己做了什么。这里没有任何东西是一次查验或一次读数。这些是其他一切都会
点到名的那些行，所以它们通常是你最先加载的东西，也是最后才会变的东西。

| 集合 | 权限范围 | 一条记录是什么 |
| --- | --- | --- |
| `suppliers` | `suppliers:read` | 一家来送货的公司，以及怎么联系它。 |
| `products` | `products:read` | 餐厅收到并使用的某样东西，按名字。 |
| `preparations` | `preparations:read` | 厨房自己做的某样东西，带着它的保质期和过敏原。 |

这三个共用同一个[快照信封](https://developers.backresto.com/zh/docs/collections)：`id`、`deleted`、`capturedAt`、
`receivedAt`、`sequence` 以及其余字段，都摆在下文描述的 `data` 旁边。

## `suppliers`

餐厅录入的每一家供应商一条记录，不论最近有没有东西从他们那里送到。

| 字段 | 类型 | 含义 |
| --- | --- | --- |
| `name` | string, **必填** | 餐厅给这家供应商起的名字。自由文本，不是一份工商登记。 |
| `isDeleted` | boolean, **必填** | 应用自己的停用标记。不是信封上的 `deleted`。见下文。 |
| `contactMethods` | object[] | 怎么联系他们。每一项是 `{ "type": string, "value": string }`。 |
| `accountNumber` | string \| null | 餐厅在这家供应商那里的账户，在录入了一个的时候。 |

```json
{
  "id": "1f3c2a76-5b94-4b0e-9c1a-6d8f0a2e7b31",
  "collection": "suppliers",
  "deleted": false,
  "capturedAt": "1789431600214",
  "receivedAt": "1789431604771",
  "sequence": "412",
  "data": {
    "name": "Metro Nanterre",
    "isDeleted": false,
    "contactMethods": [
      { "type": "phone", "value": "+33 1 41 20 30 40" },
      { "type": "email", "value": "commandes@example.test" }
    ],
    "accountNumber": "FR-884213"
  }
}
```

**`contactMethods[].type` 不是一个枚举。** schema 只说了 string，就到此为止，而
上面那些值是一种示意，不是一份清单。对它做分支时带上一个兜底分支，并且不管 `type`
是怎么写的，都把 `value` 显示出来。

一条[收货记录](https://developers.backresto.com/zh/docs/deliveries)通过 `supplierDeliveriesId` 指向它的供应商，也就是
这个集合里一条记录的 `id`。名字、账户编号和电话号码都住在这里。

## `products`

餐厅收到并使用的东西。这条记录就像它看上去那么薄。

| 字段 | 类型 | 含义 |
| --- | --- | --- |
| `name` | string, **必填** | 餐厅给这个产品起的名字。 |
| `isDeleted` | boolean, **必填** | 应用的停用标记。见下文。 |

```json
{
  "id": "6b0d4ea2-91c7-4f3d-a0be-2c5f7d1e8a44",
  "collection": "products",
  "deleted": false,
  "capturedAt": "1789431980551",
  "receivedAt": "1789432001903",
  "sequence": "413",
  "data": {
    "name": "Beurre doux 250 g",
    "isDeleted": false
  }
}
```

整条记录就这些：没有编号、没有类别、没有单位、没有供应商。如果你的模型需要其中
任何一样，那得由你自己拿着，以信封上的 `id` 为键。

**没有别的东西会按 id 指向一个产品。** 一条收货记录把被测量的对象记成
`temperatureRecords[].product`，那是查验当时打出来的自由文本。见
[收货记录](https://developers.backresto.com/zh/docs/deliveries)。把它和这份清单对上，是你这边的字符串活儿，而且
「Beurre doux 250 g」不是「beurre doux」。你非做不可就做，但不要把结果呈现成一次
连接。

## `preparations`

在店里做出来、而不是收进来的东西：一份酱汁、一锅高汤、一块肉冻派。

| 字段 | 类型 | 含义 |
| --- | --- | --- |
| `name` | string, **必填** | 厨房给这份备料起的名字。 |
| `lifespan` | number, **必填** | 它能放多久。一个光秃秃的数字。 |
| `allergens` | string[] | 它含有什么。自由字符串，不是一个封闭集合。 |
| `isDeleted` | boolean, **必填** | 应用的停用标记。见下文。 |

```json
{
  "id": "c47e8b13-0a52-4d96-8f1b-73ae2905cd6f",
  "collection": "preparations",
  "deleted": false,
  "capturedAt": "1789455120087",
  "receivedAt": "1789455133642",
  "sequence": "418",
  "data": {
    "name": "Sauce béarnaise",
    "lifespan": 3,
    "allergens": ["oeuf", "lait"],
    "isDeleted": false
  }
}
```

**`lifespan` 不带单位。** schema 给你一个数字，却没有给你任何可以拿来解释它的东
西。不要因为三看起来像天数就印出「3 天」。请为你正在读的那家餐厅确认应用用它表示
的到底是什么，如果确认不了，就老老实实地把这一点标出来。

**`allergens` 是一个字符串列表，不是一份法规清单。** 这些条目来自应用，用的是这
家餐厅的语言。在没有核对这些字符串究竟写了什么之前，不要把它们映射到那十四种具名
过敏原上；也不要把一个空数组当成一次通过了的过敏原检查。它同样可能意味着没有人
填过。

## `isDeleted` 不是 `deleted`

这一页上的每个集合都带着这两者，它们的含义不同，而一个只按其中一个来筛的使用方，
会得到一份错的清单。

- **信封上的 `deleted`**，是这份影子副本的 tombstone。`true` 表示这条记录在应用里被删除
  了，而 `data` 已经不在。它正是你得知某个东西消失了的途径。规则在
  [信封那一页](https://developers.backresto.com/zh/docs/collections)上。
- **`data` 里面的 `isDeleted`**，是应用自己打在这一行上的软删除标记。记录仍然在，
  仍然有它的名字，而且仍然带着 `deleted: false` 送达。是餐厅把它停用了：它不再出现
  在选择器里，但被留了下来，好让老记录仍然解得开。

所以两个都要筛。只认 `deleted`，你的供应商清单就会塞满餐厅两年前就不再用的供应
商。只认 `isDeleted`，你就会留下那些被彻底删掉的行，因为一条 tombstone 没有 `data`
可以让你从里面读出那个标记。

不过，请把停用的那些行留着，而不是丢掉。去年三月的一条收货记录，仍然指向一家今天
`isDeleted: true` 的供应商，而把那个 id 解析成一个名字，正是你持有这份清单的全部
理由。

## 怎么读这份目录

这三个都很小、变化很慢，而且几乎其他一切都需要它们，这让它们既是一次同步里最廉价
的那部分，也是最容易在不知不觉间弄错的那部分。

- **先走它们，留住它们，再按一个节奏去刷新它们。** 一家餐厅的整份目录，在
  `limit=100` 下不过是几页。把它以信封上的 `id` 为键存在你自己的库里，并且从那里
  去解名字，而不是每条记录取一次。
- **名字会变，id 不会。** `name` 是餐厅在营业中就会改的自由文本。把 `id` 存下来作
  为你的键，把名字当作一个你会去刷新的标签。绝不要把它当成用来做连接的东西。
- **缺席在这里同样是含糊的。** 一家没有出现的供应商，可能从来没被录入过，也可能
  还没到我们这里。在你把一个计数报出去之前，先看[那条提醒](https://developers.backresto.com/zh/docs/collections)。
