Enfriamiento y procesos alimentarios
Enfriamiento, congelación, recalentamiento y transporte: cuatro colecciones que registran una transición de temperatura, y qué aspecto tiene una sin terminar.
Un plato caliente que se enfría despacio pasa horas en el rango en que las bacterias se multiplican, así que la regla es bajarlo rápido y poder demostrar que se hizo. Cuatro colecciones registran ese tipo de transición. Tres son una transición en el tiempo —bajar, bajar más, volver a subir— y la cuarta es la misma idea en el espacio.
| Colección | Permiso | Qué es un registro |
|---|---|---|
cooling | cooling:read | Un producto caliente bajado a temperatura de conservación en frío. |
freezing | freezing:read | Un producto bajado hasta la congelación. |
reheating | reheating:read | Un producto frío subido de nuevo a temperatura de servicio. |
transport | transport:read | Un producto trasladado de un sitio a otro, con la temperatura en cada extremo. |
Las cuatro comparten el sobre de instantánea: id,
deleted, capturedAt, receivedAt, sequence y los demás campos acompañan
al data que se describe más abajo.
cooling
Un ciclo: un producto, cuándo empezó y a qué temperatura estaba, cuándo terminó y a qué temperatura acabó.
| Campo | Tipo | Significado |
|---|---|---|
timestamp | string, obligatorio | La marca propia del registro, en milisegundos desde la época Unix como cadena. No es el reloj del ciclo: eso son las dos fechas de abajo. |
product | string, obligatorio | Qué se enfrió, como texto. |
beginDate | string, obligatorio | Cuándo empezó el ciclo, en milisegundos desde la época Unix como cadena. |
beginTemperature | number, obligatorio | La temperatura a la que empezó. |
endDate | string | null | Cuándo terminó. null mientras no lo haya hecho. |
endTemperature | number | null | La temperatura a la que terminó. null junto con endDate. |
reminderId | string | null | El recordatorio que la aplicación asoció al ciclo, cuando hubo uno. |
userId | string | null | El miembro del personal que lo registró, cuando la aplicación registró uno. |
{
"id": "0e5d1a7c-9f24-4b13-8d60-c1a7f0b25e94",
"collection": "cooling",
"deleted": false,
"capturedAt": "1789779612441",
"receivedAt": "1789779910228",
"sequence": "1",
"data": {
"timestamp": "1789772400000",
"product": "Blanquette de veau",
"beginDate": "1789772400000",
"beginTemperature": 63.5,
"endDate": "1789779600000",
"endTemperature": 8.2,
"userId": "2774953d-8d9b-4a68-8ec4-1209edd90777"
}
}
product es un nombre, no una referencia. No hay ningún productId en
estos registros, así que no puede unirlos a products sin comparar cadenas, y
las cadenas se teclean durante el servicio, en el idioma del restaurante.
reminderId es opaco. Ninguna colección de esta API lo resuelve. Llévelo
consigo si le ayuda a agrupar registros; no espere poder consultarlo.
freezing
La misma forma, para un producto bajado a congelación en lugar de a temperatura
de nevera. Campo a campo, es cooling.
| Campo | Tipo | Significado |
|---|---|---|
timestamp | string, obligatorio | La marca propia del registro. |
product | string, obligatorio | Qué se congeló. |
beginDate | string, obligatorio | Cuándo empezó la operación. |
beginTemperature | number, obligatorio | La temperatura a la que empezó. |
endDate | string | null | Cuándo terminó, o null. |
endTemperature | number | null | La temperatura a la que terminó, o null. |
reminderId | string | null | Como arriba. |
userId | string | null | Quién lo registró. |
Nada en el registro dice cuál de las tres es: eso lo dice la colección de la que
viene, y el campo collection del sobre lo refleja. Una canalización que
fusione las tres en una sola tabla tiene que conservar esa columna.
reheating
Un producto frío que se vuelve a subir. De nuevo la misma forma, leída en el
otro sentido: beginTemperature es la baja y endTemperature la alta.
| Campo | Tipo | Significado |
|---|---|---|
timestamp | string, obligatorio | La marca propia del registro. |
product | string, obligatorio | Qué se recalentó. |
beginDate | string, obligatorio | Cuándo entró. |
beginTemperature | number, obligatorio | La temperatura a la que empezó. |
endDate | string | null | Cuándo salió, o null. |
endTemperature | number | null | La temperatura que alcanzó, o null. |
reminderId | string | null | Como arriba. |
userId | string | null | Quién lo registró. |
Una operación sin final tiene este aspecto:
{
"id": "b4c8e21d-3a76-4f58-9c02-77ad5e1b8f30",
"collection": "reheating",
"deleted": false,
"capturedAt": "1789783221907",
"receivedAt": "1789783402115",
"sequence": "2",
"data": {
"timestamp": "1789783200000",
"product": "Gratin dauphinois",
"beginDate": "1789783200000",
"beginTemperature": 4.1,
"endDate": null,
"endTemperature": null,
"userId": "2774953d-8d9b-4a68-8ec4-1209edd90777"
}
}
transport
La misma transición, en el espacio en lugar de en el tiempo: de dónde salió el producto y adónde llegó, con una temperatura en cada extremo.
| Campo | Tipo | Significado |
|---|---|---|
timestamp | string, obligatorio | La marca propia del registro. |
product | string, obligatorio | Qué se transportó, como texto. |
departureLocation | string, obligatorio | De dónde salió, como texto. |
departureTime | string, obligatorio | Cuándo salió, en milisegundos desde la época Unix como cadena. |
departureTemperature | number, obligatorio | La temperatura a la salida. |
arrivalLocation | string | null | Adónde llegó. null mientras no lo haya hecho. |
arrivalTime | string | null | Cuándo llegó, o null. |
arrivalTemperature | number | null | La temperatura a la llegada, o null. |
reminderId | string | null | Como arriba. |
userId | string | null | Quién lo registró. |
{
"id": "f31b6a08-5c47-4de9-b1a5-6e0c9d247b82",
"collection": "transport",
"deleted": false,
"capturedAt": "1789786944610",
"receivedAt": "1789787101883",
"sequence": "3",
"data": {
"timestamp": "1789785000000",
"product": "Plats préparés — service traiteur",
"departureLocation": "Cuisine centrale",
"departureTime": "1789785000000",
"departureTemperature": 3.4,
"arrivalLocation": "Salle Montparnasse",
"arrivalTime": "1789786800000",
"arrivalTemperature": 5.9,
"userId": "2774953d-8d9b-4a68-8ec4-1209edd90777"
}
}
Los dos lugares son texto libre, no zonas ni direcciones. Son lo que tecleó la persona, y el extremo de llegada es exactamente tan opcional como la temperatura de llegada: un registro puede llevar una salida y nada más.
Trabajar con estas colecciones
Un final nulo son dos cosas distintas. endDate y endTemperature —y
arrivalTime, arrivalTemperature y arrivalLocation en transport— admiten
null, y el registro no le dice por qué. Puede ser una operación que sigue en
curso mientras la lee, o una que nadie cerró nunca. Las dos son idénticas.
Eso importa en cuanto calcule una duración. Las fechas son cadenas, así que
endDate - beginDate resta sin problema en un registro cerrado y, en uno
abierto, convierte null en cero y le devuelve un número negativo enorme en
lugar de un error. No salta ninguna excepción; su media simplemente está mal.
Filtre primero los registros cerrados, cuente los abiertos aparte y decida usted
a partir de qué antigüedad un registro abierto deja de estar en curso y pasa a
estar abandonado: nada en esta API toma esa decisión por usted.
Calcule sobre beginDate y endDate, no sobre timestamp. Las fechas son
el reloj de la operación. timestamp es el del propio registro, y no es la
materia de la que se hace una duración.
Ordene por capturedAt, no por receivedAt. Una tableta en una cámara
frigorífica sube los datos cuando encuentra cobertura, así que un ciclo empezado
a las 09:00 puede llegar a las 14:00.
La página del sobre cuenta la historia completa.
La ausencia no prueba nada. Un producto sin registro de enfriamiento puede que nunca se enfriara, o puede estar en un dispositivo que todavía no ha subido nada. No convierta un recuento de estos en una cifra de cumplimiento: consulte la nota sobre exhaustividad.