# Catálogo

> Proveedores, productos y elaboraciones propias: las listas de referencia a las que apunta el resto del registro.

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

El catálogo es aquello de lo que un restaurante lleva una lista en lugar de
medirlo: quién entrega, qué entra por la puerta y qué hace la propia cocina.
Nada de esto es un control ni una lectura. Son las filas que nombra todo lo
demás, así que suelen ser lo primero que carga y lo último que cambia.

| Colección | Scope | Qué es un registro |
| --- | --- | --- |
| `suppliers` | `suppliers:read` | Una empresa que entrega, y cómo contactar con ella. |
| `products` | `products:read` | Algo que el restaurante recibe y usa, por su nombre. |
| `preparations` | `preparations:read` | Algo que hace la cocina, con su vida útil y sus alérgenos. |

Las tres comparten el [sobre de snapshot](https://developers.backresto.com/es/docs/collections): `id`,
`deleted`, `capturedAt`, `receivedAt`, `sequence` y los demás campos acompañan
al `data` que se describe más abajo.

## `suppliers`

Un registro por proveedor que el restaurante haya dado de alta, haya llegado
algo de él últimamente o no.

| Campo | Tipo | Significado |
| --- | --- | --- |
| `name` | string, **obligatorio** | El proveedor tal como lo nombra el restaurante. Texto libre, no un registro mercantil. |
| `isDeleted` | boolean, **obligatorio** | La marca de retirada propia de la aplicación. No es el `deleted` del sobre: véase más abajo. |
| `contactMethods` | object[] | Cómo contactar con ellos. Cada entrada es `{ "type": string, "value": string }`. |
| `accountNumber` | string \| null | La cuenta del restaurante con este proveedor, cuando se introdujo una. |

```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` no es un enum.** El esquema dice string y ahí se
acaba, y los valores de arriba son una ilustración, no una lista. Haga el switch
con una rama por defecto, y muestre el `value` esté escrito como esté el `type`.

Una [entrega](https://developers.backresto.com/es/docs/deliveries) apunta a su proveedor por
`supplierDeliveriesId`, el `id` de un registro de esta colección. El nombre, el
número de cuenta y el teléfono viven todos aquí.

## `products`

Lo que el restaurante recibe y usa. El registro es tan escueto como parece.

| Campo | Tipo | Significado |
| --- | --- | --- |
| `name` | string, **obligatorio** | El producto tal como lo nombró el restaurante. |
| `isDeleted` | boolean, **obligatorio** | La marca de retirada de la aplicación. Véase más abajo. |

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

Ese es el registro entero: ni referencia, ni categoría, ni unidad, ni proveedor.
Si su modelo necesita algo de eso, le toca a usted guardarlo, indexado por el
`id` del sobre.

**Nada más apunta a un producto por su id.** Una entrega registra lo que se
midió como `temperatureRecords[].product`, texto libre tecleado durante el
control: véase [entregas](https://developers.backresto.com/es/docs/deliveries). Cuadrar eso con esta lista es
trabajo de cadenas por su parte, y «Beurre doux 250 g» no es «beurre doux».
Hágalo si no le queda más remedio, pero no presente el resultado como un join.

## `preparations`

Algo hecho en casa en lugar de recibido: una salsa, un fondo, una terrina.

| Campo | Tipo | Significado |
| --- | --- | --- |
| `name` | string, **obligatorio** | La elaboración tal como la nombra la cocina. |
| `lifespan` | number, **obligatorio** | Cuánto se conserva. Un número a secas. |
| `allergens` | string[] | Qué contiene. Cadenas libres, no un conjunto cerrado. |
| `isDeleted` | boolean, **obligatorio** | La marca de retirada de la aplicación. Véase más abajo. |

```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` no lleva unidad.** El esquema le da un número y nada con que
interpretarlo. No escriba «3 días» porque tres parezca días: confirme qué
significa para la aplicación en el restaurante que está leyendo, y etiquételo
tal cual si no puede.

**`allergens` es una lista de cadenas, no una lista reglamentaria.** Las
entradas vienen de la aplicación en el idioma del restaurante. No las mapee a
los catorce alérgenos de declaración obligatoria sin comprobar qué dicen
realmente las cadenas, y no tome un array vacío por un control de alérgenos
superado: también significa que nadie lo rellenó.

## `isDeleted` no es `deleted`

Todas las colecciones de esta página llevan los dos, significan cosas distintas,
y quien filtre por uno solo se queda con una lista equivocada.

- **`deleted`, en el sobre**, es el tombstone de la copia en sombra. `true`
  significa que el registro se borró en la aplicación y que `data` ya no está.
  Es la manera de enterarse de que algo ha desaparecido: la
  [página del sobre](https://developers.backresto.com/es/docs/collections) tiene las reglas.
- **`isDeleted`, dentro de `data`**, es la marca de soft delete que la
  aplicación pone en la fila. El registro sigue ahí, sigue teniendo su nombre y
  sigue llegando con `deleted: false`. El restaurante lo retiró: dejó de
  ofrecerlo en los selectores y lo conservó para que los registros antiguos se
  sigan resolviendo.

Así que filtre por los dos. Respete solo `deleted` y su lista de proveedores se
llena de proveedores que el restaurante dejó hace dos años. Respete solo
`isDeleted` y conservará filas que se borraron del todo, porque un tombstone no
tiene `data` de donde leer la marca.

Aun así, conserve las filas retiradas en lugar de descartarlas. Una entrega del
pasado marzo sigue apuntando a un proveedor que hoy tiene `isDeleted: true`, y
resolver ese id en un nombre es toda la razón por la que guarda esta lista.

## Leer el catálogo

Estas tres son pequeñas, cambian despacio y las necesita casi todo lo demás, lo
que las convierte en la parte barata de una sincronización y en la parte fácil
de equivocar sin darse cuenta.

- **Recórralas primero, consérvelas, refrésquelas con una periodicidad fija.**
  El catálogo entero de un restaurante son un puñado de páginas con `limit=100`.
  Guárdelo en su propio almacén indexado por el `id` del sobre, y resuelva los
  nombres desde ahí en lugar de pedirlos registro a registro.
- **Los nombres cambian, los id no.** `name` es texto libre que el restaurante
  edita durante el servicio. Guarde el `id` como clave y trate el nombre como
  una etiqueta que refresca, nunca como algo por lo que cruzar.
- **Aquí la ausencia también es ambigua.** Un proveedor que no aparece puede que
  nunca se diera de alta, o puede que todavía no haya llegado hasta nosotros.
  Consulte [la advertencia](https://developers.backresto.com/es/docs/collections) antes de dar un recuento.
