Skip to content

🗄 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:
  • items is 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_seq check).
  • 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() using QTimer.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)

  1. Determines if the bin currently has stock using the cached stock_map.
  2. If has stock:
  3. Opens Movements prefilled for GI:
    • shell.open_movements_prefill_GI(ref=None, st_bin=<bin>, sender="shelf")
  4. If empty:
  5. 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 (False default) 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.