# Entregas

> Os controlos de receção e as fotografias tiradas na receção: duas coleções, cada campo, e o que significam no terreno.

Source: https://developers.backresto.com/pt/docs/deliveries

Uma entrega é um controlo de receção: um funcionário a receber uma encomenda, a
registar temperaturas e a decidir se a aceita. É o registo que um inspetor de
segurança alimentar pede. As fotografias tiradas na receção são uma segunda
coleção ao lado dela.

| Coleção | Scope | O que é um registo |
| --- | --- | --- |
| `deliveries` | `deliveries:read` | Um controlo de receção, com uma leitura de temperatura por produto. |
| `delivery-pictures` | `delivery-pictures:read` | Uma fotografia tirada durante uma entrega, que aponta para ela. |

As duas são [coleções](https://developers.backresto.com/pt/docs/collections) comuns: o mesmo envelope de snapshot
à volta de `data`, os mesmos endpoints, o mesmo cursor, a mesma regra dos 90
dias. Trazem o histórico de entregas que a aplicação ainda tinha quando foram
abertas, e não só o que foi registado desde então.

## `deliveries`

| Campo | Tipo | Significado |
| --- | --- | --- |
| `timestamp` | string, **obrigatório** | Quando o controlo aconteceu, em milissegundos desde a época Unix, em forma de cadeia de caracteres. |
| `isCompliant` | boolean, **obrigatório** | O veredito do funcionário sobre a entrega no seu conjunto. |
| `supplierDeliveriesId` | string \| null | O [fornecedor](https://developers.backresto.com/pt/docs/catalogue) de onde veio a mercadoria: o `id` de um registo de `suppliers`. |
| `temperatureRecords` | array \| null | Uma entrada por produto medido. Ver abaixo. |
| `nonComplianceReasons` | string[] \| null | Porque é que a entrega foi recusada ou aceite com reservas. Texto livre escolhido pelo funcionário; vazio quando está conforme. |
| `correctiveActions` | string[] \| null | O que foi feito a esse respeito. Vazio quando não foi preciso nada. |
| `commentary` | string \| null | Nota em texto livre. Muitas vezes `null`. |
| `userId` | string \| null | O [funcionário](https://developers.backresto.com/pt/docs/facilities) que a recebeu, quando a aplicação o registou. |

### `temperatureRecords[]`

| Campo | Tipo | Significado |
| --- | --- | --- |
| `product` | string | O que foi medido, tal como o funcionário lhe chamou. Nunca vazio. |
| `lotNumber` | string \| null | O lote, quando foi registado. |
| `value` | number \| null | A leitura. `null` quando o produto foi registado sem medição. |
| `unit` | `"C"` | Sempre graus Celsius. Ver abaixo. |

**As temperaturas estão sempre em graus Celsius.** Um restaurante cuja
aplicação regista em Fahrenheit continua a enviar leituras em Fahrenheit, e
estas são convertidas quando chegam, antes de serem guardadas. `unit` é `"C"`
em todas as entradas, por isso quem consome nunca tem de converter nem de
adivinhar.

```json
{
  "id": "8f2c1b04-0d5a-4b7e-9f31-6ad2c0e77a51",
  "collection": "deliveries",
  "deleted": false,
  "capturedAt": "1787932805120",
  "receivedAt": "1787932911004",
  "sequence": "88",
  "data": {
    "timestamp": "1787932800000",
    "isCompliant": false,
    "supplierDeliveriesId": "supplier-7",
    "temperatureRecords": [
      { "product": "Poulet fermier", "lotNumber": "L2291", "value": 6.4, "unit": "C" },
      { "product": "Farine T55", "lotNumber": null, "value": null, "unit": "C" }
    ],
    "nonComplianceReasons": ["Température trop élevée"],
    "correctiveActions": ["Produit refusé", "Fournisseur prévenu"],
    "commentary": "Camion en retard, rupture de chaîne du froid probable",
    "userId": "2774953d-8d9b-4a68-8ec4-1209edd90777"
  }
}
```

## `delivery-pictures`

Uma etiqueta, uma palete danificada, uma sonda encostada a um expositor: essas
imagens são a prova por trás de `isCompliant`. Cada uma é um registo que aponta
para a sua entrega, e traz um ficheiro, por isso os bytes vêm do endpoint
`assets`.

| Campo | Tipo | Significado |
| --- | --- | --- |
| `timestamp` | string, **obrigatório** | Quando a fotografia foi tirada, em milissegundos desde a época Unix, em forma de cadeia de caracteres. |
| `deliveryId` | string \| null | O registo de `deliveries` a que pertence. |
| `part` | number \| null | Posição deste registo dentro de uma fotografia que a aplicação guardou em várias partes. Transmita-o tal como está, sem o interpretar. |
| `groupId` | string \| null | Liga essas partes entre si. Os registos que partilham um `groupId` são a mesma fotografia. |
| `asset` | object, **obrigatório** | Indica o ficheiro: `objectKey` e `status` sempre, mais `contentType`, `byteLength` e `sha256` depois de carregado. |

```json
{
  "id": "c61e0a7d-35b2-4f89-a1d4-7e90b2c45f18",
  "collection": "delivery-pictures",
  "deleted": false,
  "capturedAt": "1787932861240",
  "receivedAt": "1787932990517",
  "sequence": "143",
  "data": {
    "timestamp": "1787932860000",
    "deliveryId": "8f2c1b04-0d5a-4b7e-9f31-6ad2c0e77a51",
    "part": 4,
    "groupId": "b4d81f0a-c2e7-4a55-9d10-6f3e8a2b7c91",
    "asset": {
      "objectKey": "delivery-pictures/b4d81f0a/4.jpg",
      "status": "uploaded",
      "contentType": "image/jpeg",
      "byteLength": 902450,
      "sha256": "9f2a…"
    }
  }
}
```

Os bytes são uma segunda chamada, sobre o `id` do próprio registo:

```http
GET /v1/restaurants/{restaurantId}/collections/delivery-pictures/records/{recordId}/assets
```

Responde com URL assinados válidos durante quinze minutos, exatamente como
descrito na [página das coleções](https://developers.backresto.com/pt/docs/collections). Peça sobre qualquer parte
de uma fotografia e recebe o mesmo ficheiro: a API resolve o grupo por si, por
isso não é preciso descobrir que parte o contém.

Para mostrar as fotografias de uma entrega, percorra `delivery-pictures` e
guarde os registos cujo `deliveryId` é o `id` dessa entrega, um por `groupId`.

## Ler isto corretamente

**`isCompliant` é o registo, não um cálculo.** É o que a pessoa que recebeu a
entrega decidiu, e pode divergir do que você concluiria só a partir das
temperaturas: uma leitura tirada com uma sonda de superfície, um produto com um
limiar próprio, um juízo de valor. Apresente-o como o veredito dessa pessoa. Se
quiser o seu, calcule-o ao lado do dela e identifique-o como sendo seu.

**Os campos de texto livre são texto livre.** `nonComplianceReasons`,
`correctiveActions` e `product` são escritos pelo pessoal durante o serviço, na
língua do restaurante, com a ortografia de uma terça-feira atarefada. Não
construa uma enumeração a partir deles, não faça uma junção com base neles, e
não assuma que estão em francês.

**`value` pode ser `null`.** Um produto registado sem leitura é normal: muitas
vezes é um produto seco. Trate `null` como "não medido", nunca como `0`.

**As marcas temporais são cadeias de caracteres.** `timestamp` é uma cadeia
decimal de milissegundos desde a época Unix, porque toda a plataforma BackResto
guarda as marcas temporais dessa maneira. `Number(timestamp)` é seguro hoje e
pelas próximas centenas de milhares de anos, mas não deixe um parser de JSON
convertê-lo em silêncio e voltar a escrevê-lo depois com perda de precisão.

**Uma fotografia pode chegar depois da sua entrega.** Um telemóvel carrega as
fotografias quando pode, às vezes minutos depois do próprio controlo. Uma
entrega ainda sem fotografia pode simplesmente ter uma a caminho; volte a
percorrer mais tarde antes de concluir que não tem nenhuma.
