The InventoryEngine is module M3 of the Anaquel Inteligente 3B system. It is the single authoritative source of stock truth: it acceptsDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/elzackarias/Hackaton3B-Reto1/llms.txt
Use this file to discover all available pages before exploring further.
DetectionEvent objects from M2, applies business rules to update per-SKU counters, and notifies downstream modules (M4, M6, M8) through the observer pattern. All internal state mutations are protected by a threading.Lock, making the engine safe to call from the camera thread while REST and WebSocket handlers read concurrently.
Product Catalog
The engine pre-seeds its state with the following 7 products, drawn directly from thePRODUCTOS list in inventory_engine.py.
sku_id | slot_id | Display Name | Barcode | iventa |
|---|---|---|---|---|
agua_burst | 1 | Agua Natural Burst 1500ml | 7502261250185 | 6 |
burst_energetica_roja | 2 | Bebida Energetica Red Burst 473ml | 7502261254411 | 1 |
burst_energy | 3 | Bebida Energetica Original Burst Energy 600ml | 7502261273047 | 12.5 |
nachos_naturasol | 4 | Nachos Con Sal Naturasol 200gr | 7503052023278 | 22 |
nebraska_mango | 5 | Bebida Mango-Durazno Nebraska 460ml | 7502261273504 | 14 |
sisi_cola | 6 | Refresco Cola Sin Azucar Sisi 355ml | 7502261272415 | 11 |
sun_paradise_naranja | 7 | Bebida Naranja Sun Paradise 900ml | 7502261269576 | 18 |
iventa is the product’s sale velocity index used for restock prioritisation.
Constants
| Constant | Value | Purpose |
|---|---|---|
STOCK_INITIAL | 8 | Starting units per SKU; also the maximum clamp for DEVOLUCION. |
CONFIDENCE_THRESHOLD | 0.15 | Events with confidence below this are silently ignored. |
MIN_THRESHOLD | 0.20 | Alert fires when stock_current ≤ STOCK_INITIAL × 0.20 (≤ 1.6 units, effectively ≤ 1). |
MAX_EVENTS | 1000 | Maximum InventoryEvent objects kept in the in-memory deque. |
MAX_TIMESTAMPS_PER_SKU | 500 | Maximum removal timestamps stored per SKU in _event_timestamps (consumed by M6). |
Constructor
Initial (and maximum) stock units per SKU.
Minimum
DetectionEvent.confidence required for an event to be processed.Fractional stock level that triggers an alert. For example,
0.20 means
an alert fires when stock_current ≤ stock_initial × 0.20.Public Methods
process_event
DetectionEvent from M2 and returns the resulting InventoryEvent, or None if the event was skipped.
Apply business logic (under lock)
RETIRO:stock_current = max(0, stock_current - 1)DEVOLUCION:stock_current = min(stock_initial, stock_current + 1)- Removal timestamps are appended to
_event_timestamps[sku_id](used by PredictionEngine M6).
Recalculate alert state
is_alert = stock_current ≤ stock_initial × min_threshold. An alert transition (was_alert=False → is_alert=True) triggers on_alert callbacks.on_event(callback)
cb(event: InventoryEvent, stock: ProductStock)
on_alert(callback)
was_alert was False).
Callback signature: cb(event: InventoryEvent, stock: ProductStock)
Alerts do not re-fire on subsequent removals while the product is already
in alert state. The transition guard ensures callbacks are called at most once
per alert episode.
get_state()
InventoryState object containing last_updated (datetime) and products (list of ProductStock). Thread-safe.
get_product(sku_id)
ProductStock for a single SKU, or None if the sku_id is not recognised.
get_events(limit=50)
limit inventory events in reverse-chronological order (newest first).
get_history(sku_id)
SKUHistory object containing all removal timestamps for the given SKU. This is consumed by the PredictionEngine (M6) to forecast stockout time.
Timestamps of every
RETIRO event, capped at MAX_TIMESTAMPS_PER_SKU = 500.get_all_histories()
SKUHistory objects for all 7 SKUs. Used by predict_all in M6.
get_analytics()
stock_initial × 7 (maximum possible units across all SKUs).Sum of
stock_current across all products.total_current / total_capacity rounded to 2 decimal places.Total events processed since last reset.
Overall event rate:
total_events / elapsed_minutes.Number of SKUs currently in alert state.
The
sku_id with the highest removal count, or None if no events yet.The
sku_id with the lowest removal count, or None if no events yet.Per-product breakdown including
fill_rate, retiros count, and iventa.get_restock()
priority_score.
Priority score formula:
| Condition | urgency |
|---|---|
is_alert = True | "CRITICA" |
fill_rate ≤ 0.50 | "MEDIA" |
| otherwise | "BAJA" |
reset()
stock_initial, clears the event deque, clears the deduplication set, and clears all removal timestamps. Useful for demos and end-to-end tests.
set_threshold(threshold)
ProductStock entries, and is_alert flags are recomputed.
Alert Logic
An alert fires when both conditions are true:stock_current <= stock_initial * min_threshold(e.g., ≤ 1 unit at the default 20% threshold withSTOCK_INITIAL=8)was_alertwasFalsebefore this event (transition guard)
Code Example
The
InventoryEngine is instantiated once at application startup in
main.py and shared across the camera callback, REST endpoints, and
Socket.IO event handlers. Never create multiple instances — they would
each maintain independent state.