Pulizie
Il piano di pulizia, i compiti effettivamente svolti e le fotografie che lo dimostrano — tre collezioni, e cosa non prova un record mancante.
La pulizia nell'app è un piano e la sua prova. Il ristorante mette per iscritto cosa deve essere pulito, dove e con quale frequenza; il personale spunta i compiti man mano che li svolge; alcuni di quei compiti richiedono una fotografia. Tre collezioni, una per livello, e la join fra loro è dove sta la maggior parte del lavoro.
| Collezione | Ambito | Che cos'è un record |
|---|---|---|
cleaning-tasks | cleaning-tasks:read | Una riga del piano: cosa deve essere pulito, dove, ogni quanto, se serve una fotografia. |
cleaning-task-records | cleaning-task-records:read | Un compito effettivamente svolto — quando, e da chi. |
cleaning-task-pictures | cleaning-task-pictures:read | La fotografia che lo dimostra. Porta con sé un file. |
Tutte e tre condividono l'involucro di istantanea: id,
deleted, capturedAt, receivedAt, sequence e gli altri stanno accanto al
data descritto qui sotto.
cleaning-tasks
Il piano stesso. Cambia di rado — un ristorante scrive il suo piano una volta e lo modifica quando cambia la cucina — quindi è la collezione che percorrerà meno spesso e che terrà in cache più a lungo.
| Campo | Tipo | Significato |
|---|---|---|
index | intero, obbligatorio | La posizione del compito nel piano, nell'ordine in cui li dispone l'app. |
name | stringa, obbligatorio | Cosa deve essere pulito, nelle parole del ristorante. |
description | stringa | null | Istruzioni più estese, quando qualcuno le ha scritte. |
areaId | stringa | null | L'area a cui appartiene. null in un ristorante che non si suddivide in aree. |
recurrence | intero, obbligatorio | Ogni quanto il compito si ripresenta, come semplice numero intero. |
requirePhotoProof | booleano | null | true quando il compito richiede una fotografia. null significa che l'app non l'ha mai impostato. |
isDeleted | booleano, obbligatorio | La cancellazione logica propria dell'app. Legga la nota qui sotto. |
{
"id": "c9a4f7e2-1b83-4d05-a6f1-90e3b7c4d218",
"collection": "cleaning-tasks",
"deleted": false,
"capturedAt": "1789601204773",
"receivedAt": "1789601399042",
"sequence": "1",
"data": {
"index": 3,
"name": "Nettoyage de la trancheuse",
"description": "Démonter la lame, dégraisser, désinfecter.",
"areaId": "7d2c0b61-4e8a-49f3-9c27-5a1b8e60d3f4",
"recurrence": 1,
"requirePhotoProof": true,
"isDeleted": false
}
}
recurrence non porta alcuna unità. È un intero e il record non dice cosa
conti. Lo mostri come lo mostra l'app anziché rendere «ogni 1 giorni» a partire
da una supposizione.
isDeleted non è il deleted dell'involucro. Un compito che il ristorante
ha rimosso dal suo piano torna con isDeleted: true e deleted: false: è
ancora un record vivo, che descrive una riga che non si applica più. Filtri su
entrambi, e conservi quelli cancellati — i vecchi record li indicano ancora.
cleaning-task-records
Un compito svolto. Piccolo di proposito: quale compito, quando, chi.
| Campo | Tipo | Significato |
|---|---|---|
timestamp | stringa, obbligatorio | Quando il compito è stato svolto, millisecondi dall'epoch come stringa. |
cleaningTaskId | stringa, obbligatorio | Il record cleaning-tasks che soddisfa. |
userId | stringa | null | Il membro del personale che l'ha svolto, quando l'app ne ha registrato uno. |
{
"id": "5f8b3d16-2c90-4a77-b4e8-31d0a9c65f7b",
"collection": "cleaning-task-records",
"deleted": false,
"capturedAt": "1789775012558",
"receivedAt": "1789775204910",
"sequence": "2",
"data": {
"timestamp": "1789774800000",
"cleaningTaskId": "c9a4f7e2-1b83-4d05-a6f1-90e3b7c4d218",
"userId": "2774953d-8d9b-4a68-8ec4-1209edd90777"
}
}
cleaningTaskId è obbligatorio, quindi ogni record ha un compito. Il contrario
non vale: un compito può restare nel piano senza alcun record a suo carico per
settimane, ed è lo stato normale di un compito settimanale di martedì.
cleaning-task-pictures
La fotografia. Porta con sé un file, il che ne fa l'unica collezione di questa pagina che non può consumare dal solo endpoint dei record.
| Campo | Tipo | Significato |
|---|---|---|
timestamp | stringa, obbligatorio | Quando è stata scattata l'immagine, millisecondi dall'epoch come stringa. |
cleaningTaskRecordId | stringa | null | Il record cleaning-task-records che dimostra. Ammette null — veda qui sotto. |
part | numero | null | Non documentato, ed è un decimale anziché un contatore. Lo porti avanti così com'è anziché interpretarlo — la stessa avvertenza delle etichette di tracciabilità. |
groupId | stringa | null | Lega insieme quelle immagini. I record che condividono un groupId appartengono alla stessa prova. |
asset | oggetto, obbligatorio | Indica il file: sempre objectKey e status, più contentType, byteLength e sha256 una volta caricato. |
{
"id": "2d71c8a9-6e34-4b0f-8517-ac93e25d0b46",
"collection": "cleaning-task-pictures",
"deleted": false,
"capturedAt": "1789775118330",
"receivedAt": "1789775301774",
"sequence": "3",
"data": {
"timestamp": "1789774860000",
"cleaningTaskRecordId": "5f8b3d16-2c90-4a77-b4e8-31d0a9c65f7b",
"part": 1,
"groupId": "a03e5c88-71bd-4f92-b6d4-2e8f10c73a5b",
"asset": {
"objectKey": "cleaning-task-pictures/2d71c8a9/1.jpg",
"status": "uploaded",
"contentType": "image/jpeg",
"byteLength": 812043,
"sha256": "9f2a…"
}
}
}
I byte sono una seconda chiamata, sull'id del record stesso:
GET /v1/restaurants/{restaurantId}/collections/cleaning-task-pictures/records/{recordId}/assets
Risponde con un elenco di URL firmati, ciascuno valido per quindici minuti,
ciascuno con la propria autorizzazione, così il download non richiede alcun
header. Scarichi i byte adesso, conservi i byte anziché il collegamento, e
richiami l'endpoint quando le serve un URL nuovo. Le regole — cosa compare, a
cosa serve sha256, perché vale la pena leggere contentType — sono nella
pagina sulle collezioni, e qui sono le stesse.
asset.status le dice se ci sono byte da scaricare. È pending oppure
uploaded. Un asset pending è una fotografia che il dispositivo ha annunciato
e non ha ancora finito di inviare: il record è reale, il file no, e l'endpoint
degli asset risponde senza di esso. Legga lo stato prima di trattare un elenco
di asset vuoto come una fotografia che non è mai stata scattata.
cleaningTaskRecordId ammette null. Un'immagine può esistere senza puntare
a un record, quindi una join che dà per scontato che ci sia sempre butta via
delle fotografie. Le conti a parte anziché scartarle in silenzio.
Unire le tre
La forma che quasi sicuramente le serve è una riga per compito svolto, con la sua voce di piano e le sue fotografie:
cleaning-task-records.cleaningTaskId→cleaning-tasks.idcleaning-task-pictures.cleaningTaskRecordId→cleaning-task-records.id
Tre percorsi, uniti dalla sua parte. Non esiste un endpoint che lo faccia per lei, e non esiste alcun filtro per compito o per data — percorre ogni collezione per intero e riconcilia, come descrive la pagina sull'involucro.
Ordini su capturedAt, non su receivedAt: un tablet in una cella frigorifera
carica i dati quando trova segnale, e un'immagine scattata alle 09:00 può
arrivare alle 14:00 — dopo il record a cui appartiene, oppure prima.
Cosa non significa un record mancante
Una voce di piano senza un record corrispondente non è la prova che il compito
sia stato saltato. Può essere stato svolto su un dispositivo che non ha ancora
caricato i dati, oppure svolto prima che l'acquisizione venisse attivata per
quel ristorante. Lo stesso vale per un compito contrassegnato
requirePhotoProof: true senza alcuna immagine a suo carico: la fotografia può
essere a metà del caricamento, e un asset che non ha finito di caricarsi è
assente anziché rotto.
Quindi non stampi un tasso di completamento delle pulizie da questa API chiamandolo conformità. Ciò che può dire onestamente è cosa è arrivato, e quando — veda la nota sulla completezza prima di mettere un numero davanti a chiunque.