Skip to content

🖥 Kiosk – Movements Flow

This page documents the Movements workflow in the Qt kiosk: how users search/select a wine, how quantity options are computed, and how a movement is posted safely via the API.


1. Overview

A movement is a controlled stock change executed from the touchscreen kiosk. The kiosk never updates the database directly; it calls the backend API, which applies business rules and performs a transactional update.

1.1 Reason Types

Code Meaning Typical Use
GI Goods Issue Removing bottles (consume / take out)
GR Goods Receipt Adding bottles (restock / bring in)
INV Inventory Correction Align system to physical count

1.2 Responsibilities

  • UI (Qt Kiosk): collect user inputs, guide the flow, show status/errors.
  • API (FastAPI): validate request, route to service layer.
  • Service layer: enforce rules, lock stock, update quantities, write movement audit row.
  • DB (MariaDB): transaction + row locks ensure integrity.

1.3 Flow Diagram (authoritative)

sequenceDiagram
    participant UI
    participant API
    participant Service
    participant DB

    UI->>API: POST /movements (ref, st_bin, reason, qty, user)
    API->>Service: create_movement()
    Service->>DB: SELECT ... FOR UPDATE
    Service->>DB: update stock quantity
    Service->>DB: insert movement record
    DB-->>Service: commit
    Service-->>API: success (movement id / summary)
    API-->>UI: 200 OK

1.4 Key Characteristics

  • Transactional: update stock + insert movement audit record in one commit.
  • Locked: backend locks stock rows during update (SELECT ... FOR UPDATE).
  • Rules-driven quantity: quantity options are computed server-side (UI only displays valid choices).
  • Auditability: movements are always persisted; stock changes are not “silent”.
  • Asynchronous UI: lookup, quantity-options, and post calls run in background threads (UI stays responsive).

2. Functions (User Guide Style)

This section describes the page behavior button-by-button (and control-by-control) including missing-data controls and what the user sees.


2.1 Lookup Button

Purpose: Query the backend and list candidate wines to move.

User Action

  1. Optionally fill one (or more) of:
  2. Barcode (scanner input)
  3. Storage Bin
  4. Ref (normally filled after selecting a row; the ref field itself is read-only)
  5. Press Lookup (or press Enter in Barcode/Bin fields).

System Behavior

  • Clears any previous selection and hides the selected material panel.
  • Performs an asynchronous API call based on the current Reason and provided inputs.
  • Displays results as a list grouped by “Storage Bin: …” headers.
  • Shows a status message like “Found N item(s). Tap one to select.”

Missing-Data Handling

  • If no search field is provided (barcode empty, bin empty, ref missing), the page still performs a default lookup (fallback list) depending on reason:
  • GI: “available inventory” list
  • GR/INV: “all materials” list
  • If the backend returns an error, the status bar shows an error message and the results list remains unchanged/hidden.

Typical Error Cases (UI-visible)

  • Backend unreachable / timeout → “Lookup failed: …”
  • Invalid bin format (server validation) → “Lookup failed: …”

2.2 Results List (tap row)

Purpose: Choose which wine/material is the subject of the movement.

User Action

  • Tap a wine row (not the “Storage Bin:” header).

System Behavior

  • Stores the selected row data internally.
  • Fills input fields:
  • Ref (read-only)
  • Storage Bin (pre-filled from selection; user may still edit)
  • Shows:
  • Left “selected material” panel (compact summary)
  • Right details panel (full details)
  • Resets Qty dropdown to a “calculating” placeholder.
  • Schedules a recalculation of quantity options (debounced).

Missing-Data Handling

  • Header rows are not selectable; tapping them does nothing.
  • If the item has no label image, the row shows no icon (does not block selection).

2.3 Reason Dropdown (GI / GR / INV)

Purpose: Define movement type and enforce correct quantity rules.

User Action

  • Change reason in the dropdown.

System Behavior

  • Debounced recomputation (prevents excessive API calls while user is still interacting).
  • When sufficient data exists (see below), calls:
  • GET /movements/qty-options?ref=...&st_bin=...&reason=...
  • Updates Qty dropdown to valid options returned by backend.

Required Data (to compute qty-options)

Qty options are computed only when both are present: - A valid Ref (from selection) - A valid Storage Bin (minimum format length check in UI)

If either is missing, the UI keeps Qty in “— select —” state and does not call the backend.


2.4 Storage Bin Field

Purpose: Define the bin impacted by the movement (source/target depending on business rules).

User Action

  • Type or scan a bin code (e.g. 08_03).

System Behavior

  • As the user types: schedules qty-options recomputation (debounced).
  • On Enter: performs Lookup (same as pressing Lookup button).

Missing-Data Handling

  • If user edits bin but no Ref is selected yet, qty-options will not run (because ref is required).
  • If bin is too short/invalid format, qty-options is skipped until it becomes valid.

2.5 Barcode Field

Purpose: Fast lookup by scanning a bottle barcode (scanner typically sends Enter).

User Action

  • Scan barcode.
  • Press Enter (or scanner triggers Enter).

System Behavior

  • On Enter: triggers Lookup immediately.
  • On text change: schedules qty-options recomputation, but this only matters after a selection exists (ref + bin required).

2.6 Quantity Dropdown

Purpose: Select the movement amount from server-approved options.

Behavior

  • Options are computed by backend rules and returned as an integer list.
  • UI shows:
  • “— select —” before computation
  • “— calculating —” during computation
  • If backend returns no options, UI displays an empty/limited dropdown and status message: “No qty options available.”

Why this matters

  • Prevents illegal moves (e.g., GI greater than stock, GR exceeding bin capacity).
  • Keeps kiosk logic simple; business rules live server-side.

2.7 Post Button

Purpose: Execute the movement (write to DB through the backend).

User Action

  • After selecting a wine and a quantity, press Post.

Client-side Validation (before calling API)

The UI blocks posting unless ALL are satisfied: - Ref exists (from selection or ref field value) - Storage Bin is not empty - Reason is selected - Qty is selected and convertible to integer - User is available (taken from OS session)

If validation fails, the UI shows a clear error in the status bar (example: “Select a wine first” / “Select quantity”).

System Behavior (when validation passes)

  • Builds the payload:
  • ref, st_bin, reason, qty, user
  • Sends asynchronously:
  • POST /movements
  • On success:
  • Clears barcode + ref (and resets selection)
  • Resets Qty to default state
  • Shows success status “Movement posted.”
  • Updates details panels to reflect cleared/idle state
  • On failure:
  • Shows error in status bar
  • Keeps current selection so user can correct and retry

Expected Backend Guarantees

  • Stock row locking prevents race conditions.
  • Update + movement row insert committed atomically.
  • Backend validation may reject:
  • quantity out of range
  • invalid bin
  • ref not found
  • conflicting inventory rules

2.8 Clear Button

Purpose: Return page to a neutral “ready to scan” state.

User Action

  • Press Clear.

System Behavior

  • Clears:
  • Barcode
  • Ref
  • Storage Bin
  • Qty selection
  • Resets reason to default (GI).
  • Hides results list and detail panels.
  • Focus returns to barcode field for next scan.
  • Cancels “meaningful” state so accidental Post is impossible.

3. Operational Notes (for maintainers)

3.1 Debounce & Background Threads

  • Quantity-options calls are debounced (~180ms) to avoid bursts while typing/scanning.
  • Lookup and Post run in a background worker to keep UI responsive.

3.2 UI Source of Truth

  • The UI is not authoritative for business constraints; the backend is.
  • The UI shows only server-approved quantities to reduce operator errors.

3.3 Multi-wine per Bin

  • Results are grouped under “Storage Bin: …” headers.
  • Only actual wine rows are selectable; headers are “labels” only.

This page is the authoritative behavior definition for the Movements UI workflow.