Nettoyage
Le plan de nettoyage, les tâches réellement effectuées et les photographies qui le prouvent — trois collections, et ce qu'un enregistrement manquant ne prouve pas.
Le nettoyage, dans l'application, c'est un plan et sa preuve. Le restaurant écrit ce qui doit être nettoyé, où et à quelle fréquence ; le personnel coche les tâches au fur et à mesure ; certaines de ces tâches exigent une photographie. Trois collections, une par couche, et c'est la jointure entre elles qui représente le plus gros du travail.
| Collection | Portée | Ce qu'est un enregistrement |
|---|---|---|
cleaning-tasks | cleaning-tasks:read | Une ligne du plan : ce qui doit être nettoyé, où, à quelle fréquence, et si cela exige une photographie. |
cleaning-task-records | cleaning-task-records:read | Une tâche réellement effectuée — quand, et par qui. |
cleaning-task-pictures | cleaning-task-pictures:read | La photographie qui le prouve. Porte un fichier. |
Toutes les trois partagent l'enveloppe d'instantané :
id, deleted, capturedAt, receivedAt, sequence et le reste entourent
le data décrit ci-dessous.
cleaning-tasks
Le plan lui-même. Ces enregistrements changent rarement — un restaurant écrit son plan une fois et le modifie quand la cuisine change — c'est donc la collection que vous parcourez le moins souvent et que vous gardez en cache le plus longtemps.
| Champ | Type | Signification |
|---|---|---|
index | integer, obligatoire | La position de la tâche dans le plan, telle que l'application l'ordonne. |
name | string, obligatoire | Ce qui doit être nettoyé, avec les mots du restaurant. |
description | string | null | Des instructions plus longues, quand quelqu'un en a écrit. |
areaId | string | null | La zone à laquelle elle appartient. null dans un restaurant qui ne se découpe pas en zones. |
recurrence | integer, obligatoire | À quelle fréquence la tâche revient, sous forme d'entier simple. |
requirePhotoProof | boolean | null | true quand la tâche exige une photographie. null signifie que l'application ne l'a jamais renseigné. |
isDeleted | boolean, obligatoire | La suppression douce propre à l'application. Lisez la note ci-dessous. |
{
"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 ne porte aucune unité. C'est un entier, et l'enregistrement ne
dit pas ce qu'il compte. Affichez-le comme l'application l'affiche plutôt que
d'écrire « tous les 1 jours » sur une supposition.
isDeleted n'est pas le deleted de l'enveloppe. Une tâche que le
restaurant a retirée de son plan revient avec isDeleted: true et
deleted: false : c'est toujours un enregistrement vivant, qui décrit une
ligne qui ne s'applique plus. Filtrez sur les deux, et gardez les supprimées
sous la main — de vieux enregistrements pointent encore vers elles.
cleaning-task-records
Une tâche effectuée. Petit à dessein : quelle tâche, quand, qui.
| Champ | Type | Signification |
|---|---|---|
timestamp | string, obligatoire | Quand la tâche a été effectuée, en millisecondes depuis l'epoch sous forme de chaîne de caractères. |
cleaningTaskId | string, obligatoire | L'enregistrement cleaning-tasks qu'elle satisfait. |
userId | string | null | Le membre du personnel qui l'a effectuée, quand l'application en a enregistré un. |
{
"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 est obligatoire : chaque enregistrement a donc une tâche.
L'inverse n'est pas vrai : une tâche peut rester dans le plan sans aucun
enregistrement en face pendant des semaines, et c'est l'état normal d'une tâche
hebdomadaire un mardi.
cleaning-task-pictures
La photographie. Elle porte un fichier, ce qui en fait la seule collection de cette page que vous ne pouvez pas consommer depuis le seul endpoint des enregistrements.
| Champ | Type | Signification |
|---|---|---|
timestamp | string, obligatoire | Quand la photographie a été prise, en millisecondes depuis l'epoch sous forme de chaîne de caractères. |
cleaningTaskRecordId | string | null | L'enregistrement cleaning-task-records qu'elle prouve. Peut être null — voyez ci-dessous. |
part | number | null | Non documenté, et décimal plutôt qu'un compteur. Transportez-le plutôt que de l'interpréter — la même réserve que sur les étiquettes de traçabilité. |
groupId | string | null | Relie ces photographies entre elles. Des enregistrements qui partagent un groupId appartiennent à la même preuve. |
asset | object, obligatoire | Nomme le fichier : objectKey et status toujours, plus contentType, byteLength et sha256 une fois qu'il est téléversé. |
{
"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…"
}
}
}
Les octets sont un second appel, sur l'identifiant propre à l'enregistrement :
GET /v1/restaurants/{restaurantId}/collections/cleaning-task-pictures/records/{recordId}/assets
Il répond par une liste d'URL signées, valables quinze minutes chacune,
portant chacune sa propre autorisation, si bien que le téléchargement ne
demande aucun en-tête. Récupérez les octets maintenant, stockez les octets
plutôt que le lien, et rappelez l'endpoint quand vous avez besoin d'une URL
fraîche. Les règles — ce qui apparaît, à quoi sert sha256, pourquoi
contentType mérite d'être lu — sont sur
la page des collections, et elles sont les mêmes ici.
asset.status vous dit s'il y a des octets à récupérer. Il vaut pending
ou uploaded. Un asset en pending, c'est une photographie que l'appareil a
annoncée et n'a pas fini d'envoyer : l'enregistrement est réel, le fichier ne
l'est pas, et l'endpoint des fichiers répond sans lui. Lisez le statut avant de
prendre une liste de fichiers vide pour une photographie qui n'a jamais été
prise.
cleaningTaskRecordId peut être null. Une photographie peut exister sans
pointer vers un enregistrement : une jointure qui le suppose toujours présent
laisse tomber des photographies. Comptez-les à part plutôt que de les écarter
en silence.
Joindre les trois
La forme que vous voulez presque certainement, c'est une ligne par tâche effectuée, avec son entrée dans le plan et ses photographies :
cleaning-task-records.cleaningTaskId→cleaning-tasks.idcleaning-task-pictures.cleaningTaskRecordId→cleaning-task-records.id
Trois parcours, joints de votre côté. Aucun endpoint ne le fait pour vous, et il n'y a pas de filtre par tâche ni par date — vous parcourez chaque collection en entier et vous réconciliez, comme le décrit la page de l'enveloppe.
Ordonnez sur capturedAt, pas sur receivedAt : une tablette dans une chambre
froide téléverse quand elle trouve du réseau, et une photographie prise à 09:00
peut arriver à 14:00 — après l'enregistrement auquel elle appartient, ou avant
lui.
Ce qu'un enregistrement manquant ne veut pas dire
Une entrée du plan sans enregistrement correspondant n'est pas la preuve que
la tâche a été sautée. Elle a pu être effectuée sur un appareil qui n'a pas
encore téléversé, ou avant que la capture ne soit activée pour ce restaurant.
Même chose pour une tâche marquée requirePhotoProof: true sans photographie
en face : la photographie peut être en cours de téléversement, et un fichier
dont le téléversement n'est pas achevé est absent plutôt que cassé.
N'imprimez donc pas un taux de réalisation du nettoyage issu de cette API en l'appelant conformité. Ce que vous pouvez dire honnêtement, c'est ce qui est arrivé, et quand — voyez la note sur l'exhaustivité avant de mettre un chiffre sous les yeux de qui que ce soit.