# Catalogue

> Fournisseurs, produits et préparations maison : les listes de référence que le reste de l'enregistrement désigne.

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

Le catalogue, c'est ce dont un restaurant tient la liste plutôt qu'il ne le
mesure : qui livre, ce qui passe la porte, et ce que la cuisine fabrique
elle-même. Rien ici n'est un contrôle ni un relevé. Ce sont les lignes que tout
le reste nomme : c'est donc en général la première chose que vous chargez et la
dernière qui change.

| Collection | Scope | Ce qu'est un enregistrement |
| --- | --- | --- |
| `suppliers` | `suppliers:read` | Une entreprise qui livre, et comment la joindre. |
| `products` | `products:read` | Quelque chose que le restaurant reçoit et utilise, par son nom. |
| `preparations` | `preparations:read` | Quelque chose que la cuisine fabrique, avec sa durée de vie et ses allergènes. |

Toutes les trois partagent l'[enveloppe de snapshot](https://developers.backresto.com/fr/docs/collections) :
`id`, `deleted`, `capturedAt`, `receivedAt`, `sequence` et le reste entourent
le `data` décrit ci-dessous.

## `suppliers`

Un enregistrement par fournisseur que le restaurant a saisi, que quelque chose
en soit arrivé récemment ou non.

| Champ | Type | Signification |
| --- | --- | --- |
| `name` | string, **obligatoire** | Le fournisseur tel que le restaurant le nomme. Texte libre, pas un registre d'entreprises. |
| `isDeleted` | boolean, **obligatoire** | L'indicateur de retrait propre à l'application. Ce n'est pas le `deleted` de l'enveloppe. Voyez ci-dessous. |
| `contactMethods` | object[] | Comment les joindre. Chaque entrée est `{ "type": string, "value": string }`. |
| `accountNumber` | string \| null | Le compte du restaurant chez ce fournisseur, quand il a été saisi. |

```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` n'est pas une énumération.** Le schéma dit string et
s'arrête là, et les valeurs ci-dessus sont une illustration, pas une liste.
Aiguillez dessus avec une branche par défaut, et affichez la `value` quelle que
soit l'orthographe du `type`.

Une [livraison](https://developers.backresto.com/fr/docs/deliveries) désigne son fournisseur par
`supplierDeliveriesId`, l'`id` d'un enregistrement de cette collection. Le nom,
le numéro de compte et le numéro de téléphone vivent tous ici.

## `products`

Ce que le restaurant reçoit et utilise. L'enregistrement est aussi maigre qu'il
en a l'air.

| Champ | Type | Signification |
| --- | --- | --- |
| `name` | string, **obligatoire** | Le produit tel que le restaurant l'a nommé. |
| `isDeleted` | boolean, **obligatoire** | L'indicateur de retrait de l'application. Voyez ci-dessous. |

```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
  }
}
```

C'est tout l'enregistrement : pas de référence, pas de catégorie, pas d'unité,
pas de fournisseur. Si votre modèle a besoin de l'un de ces éléments, c'est à
vous de le détenir, indexé sur l'`id` de l'enveloppe.

**Rien d'autre ne désigne un produit par son identifiant.** Une livraison
consigne ce qui a été mesuré dans `temperatureRecords[].product`, du texte
libre saisi pendant le contrôle. Voyez [les livraisons](https://developers.backresto.com/fr/docs/deliveries).
Faire correspondre cela à cette liste est un travail sur les chaînes de
caractères, de votre côté, et "Beurre doux 250 g" n'est pas "beurre doux".
Faites-le s'il le faut, mais ne présentez pas le résultat comme une jointure.

## `preparations`

Quelque chose de fabriqué maison plutôt que reçu : une sauce, un fond, une
terrine.

| Champ | Type | Signification |
| --- | --- | --- |
| `name` | string, **obligatoire** | La préparation telle que la cuisine la nomme. |
| `lifespan` | number, **obligatoire** | Combien de temps elle se garde. Un nombre nu. |
| `allergens` | string[] | Ce qu'elle contient. Des chaînes libres, pas un ensemble fermé. |
| `isDeleted` | boolean, **obligatoire** | L'indicateur de retrait de l'application. Voyez ci-dessous. |

```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` ne porte aucune unité.** Le schéma vous donne un nombre et rien
pour l'interpréter. N'écrivez pas "3 jours" parce que trois ressemble à des
jours. Vérifiez ce que l'application entend par là pour le restaurant que vous
lisez, et dites-le franchement si vous n'y parvenez pas.

**`allergens` est une liste de chaînes de caractères, pas une liste
réglementaire.** Les entrées viennent de l'application, dans la langue du
restaurant. Ne les faites pas correspondre aux quatorze allergènes nommés sans
vérifier ce que les chaînes disent réellement, et ne prenez pas un tableau vide
pour un contrôle des allergènes soldé : cela veut aussi dire que personne ne
l'a rempli.

## `isDeleted` n'est pas `deleted`

Toutes les collections de cette page portent les deux, ils ne veulent pas dire
la même chose, et un consommateur qui filtre sur l'un des deux obtient une
liste fausse.

- **`deleted`, sur l'enveloppe**, est le tombstone de la copie fantôme.
  `true` signifie que l'enregistrement a été supprimé dans l'application et que
  `data` a disparu. C'est ainsi que vous apprenez que quelque chose s'en est
  allé. [La page de l'enveloppe](https://developers.backresto.com/fr/docs/collections) en donne les règles.
- **`isDeleted`, à l'intérieur de `data`**, est l'indicateur de soft delete que
  l'application porte sur la ligne. L'enregistrement est toujours là, a toujours
  son nom, et arrive toujours avec `deleted: false`. Le restaurant l'a retiré :
  il a cessé de le proposer dans les sélecteurs, et l'a gardé pour que les
  anciens enregistrements se résolvent encore.

Filtrez donc sur les deux. Respectez `deleted` seul et votre liste de
fournisseurs se remplit de fournisseurs que le restaurant a abandonnés il y a
deux ans. Respectez `isDeleted` seul et vous gardez des lignes qui ont été
supprimées purement et simplement, parce qu'un tombstone n'a pas de
`data` où lire l'indicateur.

Gardez tout de même les lignes retirées plutôt que de les jeter. Une livraison
de mars dernier pointe encore vers un fournisseur qui est `isDeleted: true`
aujourd'hui, et résoudre cet id en un nom est toute la raison pour laquelle vous détenez
cette liste.

## Lire le catalogue

Ces trois collections sont petites, lentes à bouger et nécessaires à presque
tout le reste, ce qui en fait la partie peu coûteuse d'une synchronisation et
celle où l'on se trompe le plus facilement sans s'en apercevoir.

- **Parcourez-les en premier, gardez-les, actualisez-les à intervalle
  régulier.** Le catalogue entier d'un restaurant, c'est une poignée de pages à
  `limit=100`. Détenez-le dans votre propre stockage, indexé sur l'`id` de
  l'enveloppe, et résolvez les noms depuis là plutôt que de faire une requête
  par enregistrement.
- **Les noms changent, les identifiants non.** `name` est du texte libre que le
  restaurant modifie pendant le service. Stockez l'`id` comme clé et traitez le
  nom comme une étiquette que vous rafraîchissez, jamais comme quelque chose
  sur quoi joindre.
- **L'absence est ambiguë ici aussi.** Un fournisseur qui n'apparaît pas n'a
  peut-être jamais été saisi, ou ne nous est peut-être pas encore parvenu.
  Voyez [la mise en garde](https://developers.backresto.com/fr/docs/collections) avant de communiquer un décompte.
