Catálogo
Fornecedores, produtos e preparações da casa — as listas de referência para as quais o resto do registo aponta.
O catálogo é aquilo de que um restaurante mantém uma lista em vez de medir: quem entrega, o que entra pela porta, e o que a cozinha faz por si. Nada aqui é um controlo ou uma leitura. Estas são as linhas que tudo o resto nomeia, por isso costumam ser a primeira coisa que carrega e a última que muda.
| Coleção | Âmbito | O que é um registo |
|---|---|---|
suppliers | suppliers:read | Uma empresa que entrega, e como chegar até ela. |
products | products:read | Algo que o restaurante recebe e utiliza, pelo nome. |
preparations | preparations:read | Algo que a cozinha faz, com o seu prazo de validade e os seus alergénios. |
As três partilham o envelope de instantâneo: id,
deleted, capturedAt, receivedAt, sequence e os restantes ficam ao lado
do data descrito abaixo.
suppliers
Um registo por fornecedor que o restaurante tenha introduzido, tenha ou não chegado alguma coisa deles ultimamente.
| Campo | Tipo | Significado |
|---|---|---|
name | string, obrigatório | O fornecedor tal como o restaurante lhe chama. Texto livre, não um registo comercial. |
isDeleted | boolean, obrigatório | A marca de retirada da própria aplicação. Não é o deleted do envelope — veja abaixo. |
contactMethods | object[] | Como chegar até eles. Cada entrada é { "type": string, "value": string }. |
accountNumber | string | null | A conta do restaurante junto deste fornecedor, quando foi introduzida. |
{
"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ão é uma enumeração. O esquema diz string e fica-se
por aí, e os valores acima são uma ilustração e não uma lista. Ramifique sobre
ele com um caso por omissão, e mostre o value seja qual for a grafia do
type.
Uma entrega traz o seu fornecedor embutido como
{ id, name } — o suficiente para pôr no ecrã, e mais nada. É nesta coleção que
vivem o número de conta e o número de telefone.
products
O que o restaurante recebe e utiliza. O registo é tão magro como parece.
| Campo | Tipo | Significado |
|---|---|---|
name | string, obrigatório | O produto tal como o restaurante lhe chamou. |
isDeleted | boolean, obrigatório | A marca de retirada da aplicação. Veja abaixo. |
{
"id": "6b0d4ea2-91c7-4f3d-a0be-2c5f7d1e8a44",
"collection": "products",
"deleted": false,
"capturedAt": "1789431980551",
"receivedAt": "1789432001903",
"sequence": "413",
"data": {
"name": "Beurre doux 250 g",
"isDeleted": false
}
}
É este o registo todo: sem referência, sem categoria, sem unidade, sem
fornecedor. Se o seu modelo precisar de alguma dessas coisas, é a si que cabe
mantê-las, indexadas pelo id do envelope.
Mais nada aponta para um produto por identificador. Uma entrega regista o
que foi medido em temperatureRecords[].product, texto livre escrito durante o
controlo — veja entregas. Fazer corresponder isso a esta
lista é trabalho de cadeias de caracteres do seu lado, e «Beurre doux 250 g» não
é «beurre doux». Faça-o se for preciso, mas não apresente o resultado como uma
junção.
preparations
Algo feito na casa em vez de recebido — um molho, um caldo, uma terrina.
| Campo | Tipo | Significado |
|---|---|---|
name | string, obrigatório | A preparação tal como a cozinha lhe chama. |
lifespan | number, obrigatório | Quanto tempo se conserva. Um número e mais nada. |
allergens | string[] | O que contém. Cadeias livres, não um conjunto fechado. |
isDeleted | boolean, obrigatório | A marca de retirada da aplicação. Veja abaixo. |
{
"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 não traz unidade nenhuma. O esquema dá-lhe um número e nada com
que o interpretar. Não escreva «3 dias» só porque três parece dias — confirme o
que a aplicação quer dizer com isso para o restaurante que está a ler, e
identifique-o com clareza se não conseguir.
allergens é uma lista de cadeias de caracteres, não uma lista
regulamentar. As entradas vêm da aplicação na língua do restaurante. Não as
mapeie para os catorze alergénios nomeados sem verificar o que as cadeias dizem
de facto, e não trate uma lista vazia como um controlo de alergénios feito e
limpo — também significa que ninguém a preencheu.
isDeleted não é deleted
Todas as coleções desta página trazem os dois, significam coisas diferentes, e quem filtre por um deles fica com uma lista errada.
deleted, no envelope, é a marca de eliminação da cópia sombra.truesignifica que o registo foi apagado na aplicação e que odatadesapareceu. É assim que fica a saber que alguma coisa desapareceu — a página do envelope tem as regras.isDeleted, dentro dodata, é a marca de eliminação lógica da própria aplicação sobre a linha. O registo continua lá, continua a ter o seu nome, e continua a chegar comdeleted: false. O restaurante retirou-o: deixou de o oferecer nos seletores, e guardou-o para que os registos antigos continuem a resolver-se.
Por isso, filtre pelos dois. Respeite só o deleted e a sua lista de
fornecedores enche-se de fornecedores que o restaurante abandonou há dois anos.
Respeite só o isDeleted e fica com linhas que foram apagadas de vez, porque
uma marca de eliminação não tem data de onde ler a marca.
Ainda assim, guarde as linhas retiradas em vez de as deitar fora. Uma entrega de
março passado ainda nomeia um fornecedor que hoje está a isDeleted: true, e
resolver esse nome é a razão inteira por que tem esta lista.
Ler o catálogo
Estas três são pequenas, mudam devagar e são precisas para quase tudo o resto, o que faz delas a parte barata de uma sincronização e a parte fácil de errar sem dar por isso.
- Percorra-as primeiro, guarde-as, atualize-as com regularidade. O catálogo
inteiro de um restaurante são meia dúzia de páginas com
limit=100. Guarde-o no seu próprio armazenamento, indexado peloiddo envelope, e resolva os nomes a partir daí em vez de ir buscar um por registo. - Os nomes mudam, os identificadores não.
nameé texto livre que o restaurante edita durante o serviço. Guarde oidcomo a sua chave e trate o nome como uma etiqueta que vai atualizando — nunca como algo pelo qual unir. - A ausência também é ambígua aqui. Um fornecedor que não apareça pode nunca ter sido introduzido, ou pode ainda não ter chegado até nós. Veja a nota de aviso antes de comunicar uma contagem.