đź—„ Kiosk – Shelf Page Flow¶
This document describes the Shelf page implemented in pages/shelf.py (Qt kiosk).
The Shelf page is a touch-first visual navigator: it renders the physical shelf layout and lets the operator tap a bin to jump directly into Movements for that bin.
Note: This page does not run the vision pipeline. It only visualises bins and navigates to Movements.
1. Overview¶
The Shelf page provides:
- A large shelf drawing (grid of storage bins) rendered on the left
- A simple legend/hint on the right
- Live “has stock / empty” indication per bin
- One-tap navigation into Movements (GI vs INV routing based on whether the bin has stock)
1.1 Reason Routing Rule (authoritative)¶
When a bin is tapped:
- If the bin has stock → open Movements pre-filled for GI (goods issue)
- If the bin is empty → open Movements pre-filled for the default Movements mode (used for INV correction)
This decision is made dynamically from backend data.
1.2 Data Source¶
To decide whether a bin has stock, the page queries the backend per bin using:
api.wines_in_bin_envelope(st_bin)
and interprets:itemsis a non-empty list → has stock- else → empty
1.3 Loading & Responsiveness¶
- All loading is executed in a background worker thread (QThreadPool) to keep the UI responsive.
- A stale-result guard prevents older loads from overwriting newer ones (
_reload_seqcheck). - Status bar feedback is provided throughout loading and error conditions.
2. Flow Diagram¶
sequenceDiagram
participant UI as Shelf Page (Qt)
participant API as ApiClient
participant BE as Backend (FastAPI)
participant DB as MariaDB
UI->>UI: on_show() schedules reload
UI->>API: wines_in_bin_envelope(st_bin) for each bin
API->>BE: GET /bins/{st_bin}/wines (envelope)
BE->>DB: query stock/materials for bin
DB-->>BE: rows
BE-->>API: {items:[...]} envelope
API-->>UI: per-bin results
UI->>UI: set_stock_map() + repaint
UI-->>UI: user taps bin -> open Movements
3. Functions (User Guide Style)¶
This section is control-by-control including constraints and missing-data handling.
3.1 Viewing the Shelf Grid¶
What the user sees
- A shelf diagram consisting of multiple bins (e.g., 08_01, 08_02, …).
- A hint/legend:
- “Tap a bin to open Movements.
Green = has stock (GI), Gray = empty (INV).”
Meaning of colors - Green bins: backend reports at least one wine item in the bin - Gray bins: backend reports zero items in the bin
3.2 Automatic Refresh When Page Opens¶
Purpose: Always display fresh “has stock” state when operator opens the page.
User Action¶
- Navigate to the Shelf page (no manual button needed).
System Behaviour¶
- On show, the page schedules
reload()usingQTimer.singleShot(0, ...)so the widget is fully active before starting background work. - Status bar shows: “Shelf: loading…”
- After completion:
- Status bar shows: “Shelf: updated”
- Colors update immediately.
Missing-Data / Safety Controls¶
- If a reload is already running (
_loading == True), further reload calls are ignored. - If a newer reload starts, older results are discarded (stale result protection via
_reload_seq).
3.3 Tapping a Bin (Primary Action)¶
Purpose: Jump directly into Movements for the chosen bin.
User Action¶
- Tap a bin shape on the shelf diagram.
System Behavior (authoritative)¶
- Determines if the bin currently has stock using the cached
stock_map. - If has stock:
- Opens Movements prefilled for GI:
shell.open_movements_prefill_GI(ref=None, st_bin=<bin>, sender="shelf")
- If empty:
- Opens Movements with default prefill:
shell.open_movements_prefill(ref=None, st_bin=<bin>, sender="shelf")
Missing-Data Handling¶
- If stock state is unknown (e.g., before first reload), bin is treated as empty (
Falsedefault) and routes to the default prefill. - If navigation fails (exception), status shows:
- “Open movements failed: …”
4. Error Handling¶
4.1 Backend / Network Failure During Load¶
If any bin query fails in the worker:
- The worker reports an exception
- UI sets status:
- “Shelf load failed: …”
- The previously drawn shelf state remains visible (no destructive reset)
4.2 Partial Availability¶
Because the worker loads bins sequentially, a failure may occur mid-way.
Operational behavior: - The reload is considered failed (status “bad”) - No partial state is applied unless the worker returns successfully
5. Operational Notes (for maintainers)¶
5.1 Worker Lifetime Guard¶
The page keeps a strong reference to the active worker (_reload_worker) to avoid rare GC-related crashes while threads are running.
5.2 Rendering & Hit Testing¶
- Bins are represented as vector paths (QPainterPath) in
ShelfCanvas. - Click detection uses
path.contains(point)after applying the current canvas fit/transform.
This document defines the authoritative behaviour of the Shelf page (shelf.py) in wine_platform.