Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/EstefanoARG/FridgeRadar/llms.txt

Use this file to discover all available pages before exploring further.

The semáforo (traffic light) is FridgeRadar’s freshness classification engine. It assigns one of four colour-coded states to every inventory item based on how many days remain until its expiry date. Just like a real traffic light the colours have an intuitive meaning: green means all clear, yellow means pay attention, red means act now, and a special fourth state marks items that have already passed their best-before date. The semáforo state of an item is stored as estado_caducidad on every InventarioResponse and drives both the UI colour coding and the Tengo Hambre recipe suggestion engine.

The Four States

StateValueConditionMeaning
🟢 Verde"verde"More than 7 days remaining, or no expiry date setItem is fresh — no action needed
🟡 Amarillo"amarillo"3 to 7 days remaining (dias >= 3)Use soon — approaching expiry
🔴 Rojo"rojo"0 to 2 days remaining (dias >= 0)Use immediately — expires very soon
⚫ Vencido"vencido"Past the expiry date (dias < 0)Item is expired
When fecha_vencimiento is null — meaning no expiry date has been recorded — the item is always classified as "verde". FridgeRadar will never flag an item as expiring unless you have explicitly set a date.

Source: calcular_estado()

The classification logic lives in app/utils/semaforo.py. The complete function is reproduced below exactly as it appears in the codebase:
from datetime import date

VERDE    = "verde"
AMARILLO = "amarillo"
ROJO     = "rojo"
VENCIDO  = "vencido"


def calcular_estado(fecha_vencimiento: date | None) -> str:
    """Calcula el estado del semáforo según la fecha de vencimiento."""
    if fecha_vencimiento is None:
        return VERDE

    dias = (fecha_vencimiento - date.today()).days

    if dias > 7:
        return VERDE
    elif dias >= 3:
        return AMARILLO
    elif dias >= 0:
        return ROJO
    else:
        return VENCIDO
The helper es_critico() is used by the recipe engine to decide whether an item should count as a near-expiry ingredient:
def es_critico(estado: str) -> bool:
    """True si el producto está en amarillo o rojo."""
    return estado in (AMARILLO, ROJO)
And dias_restantes() exposes the raw day count for display purposes:
def dias_restantes(fecha_vencimiento: date | None) -> int | None:
    if fecha_vencimiento is None:
        return None
    return (fecha_vencimiento - date.today()).days

Threshold Reference

Threshold constantDefault valueCondition in calcular_estado
SEMAFORO_AMARILLO_DIAS7dias > 7 → verde; dias >= 3 → amarillo
SEMAFORO_ROJO_DIAS3dias >= 3 → amarillo; dias >= 0 → rojo
Both thresholds are configurable via your .env file using the SEMAFORO_AMARILLO_DIAS and SEMAFORO_ROJO_DIAS environment variables. Adjusting them lets households set tighter or looser freshness windows without touching application code.

Automated Recalculation

States are not recalculated on every request. Instead, FridgeRadar uses APScheduler to run two background tasks each day:
TimeTask
00:05 (midnight + 5 min)Recalculates estado_caducidad for every inventory item across all households
08:00 AMReads the freshly computed states and dispatches in-app alerts for "amarillo" and "rojo" items
This two-step schedule means alerts are always based on states that were updated just a few hours earlier, not on stale data from the previous day.
Because recalculation only happens at midnight, an item added at 11:55 PM will have its state set at creation time by the service layer — you do not need to wait until 00:05 for the first accurate state.

Manual Recalculation API

You can trigger a recalculation on demand without waiting for the scheduled job:
# Recalculate every item across all households
POST /api/v1/semaforo/recalcular
Authorization: Bearer <token>
# Recalculate only items in a specific household
POST /api/v1/semaforo/recalcular/{id_hogar}
Authorization: Bearer <token>
These endpoints are useful after bulk imports or when you need to verify states immediately after changing expiry dates.

Filtering Inventory by State

Because estado_caducidad is stored on each inventory record, you can query items at a specific freshness level directly from the inventory endpoint:
GET /api/v1/inventario/hogar/{id_hogar}?estado=rojo
Authorization: Bearer <token>
GET /api/v1/inventario/hogar/{id_hogar}?estado=vencido
Authorization: Bearer <token>
Accepted estado values: verde, amarillo, rojo, vencido.
Items with estado_caducidad: "vencido" are not removed automatically. It is up to your household members to review and discard them. Consider scheduling a weekly review of the ?estado=vencido list.

How es_critico Drives Recipe Suggestions

The Tengo Hambre engine uses es_critico() to filter the pantry before matching ingredients to recipes. When solo_criticos: true (the default), only items in "amarillo" or "rojo" states are considered as available ingredients. This ensures recipe suggestions are optimised for reducing food waste rather than just maximising what you can cook.

Build docs developers (and LLMs) love