> ## Documentation Index
> Fetch the complete documentation index at: https://docs.laportenard.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Kitchen display (KDS)

> Set up a dedicated kitchen display terminal that shows sent orders as tickets and lets kitchen staff bump items as done.

The Kitchen Display System (KDS) replaces paper tickets with a real-time screen in the kitchen. Orders appear as ticket cards when sent from the POS, and kitchen staff bump items or full orders as they finish them. Bump state syncs back to POS terminals so servers see a "ready" badge on the floor plan.

## Prerequisites

* Hub sync enabled (`nu_hub_enabled` on `nu.pos.config`) — KDS requires real-time order snapshots via WebSocket
* At least two POS terminals configured under the same shared config: one for order-taking, one for the kitchen display

## Setup

<Steps>
  <Step title="Configure the KDS terminal in Odoo">
    Go to **Point of Sale > Configuration > Point of Sale** and open the terminal you want to designate as a kitchen display.

    Under the **Configuracion NU POS** tab, find the **Modo de Terminal** radio group and select **Pantalla de Cocina (KDS)**.
  </Step>

  <Step title="Open a POS session on the KDS terminal">
    Log in to the POS on the KDS terminal and open a session as usual. The app detects `nu_terminal_mode = "kds"` from the bootstrap config and auto-redirects to `/kds/`.
  </Step>

  <Step title="Start taking orders on POS terminals">
    On regular POS terminals, create orders and send them to the kitchen (the "Send" button that transitions status to `sent`). Orders appear on the KDS within seconds via the hub.
  </Step>
</Steps>

<Note>
  The KDS terminal must be under the same `nu.pos.config` shared configuration as the order-taking terminals so they share the same hub and see the same orders.
</Note>

## How it works

### Ticket lifecycle

Orders appear on the KDS when their kitchen status is `sent` or `changed` and they have not been bumped (`kitchenBumpedAt` is null). The flow:

1. **Order sent** — POS terminal sends order to kitchen. Items are stamped with `kitchenItemStatus: "pending"`. Order appears as a ticket card on the KDS.
2. **Item bump** — Kitchen staff taps an individual item to mark it `done` (green checkmark). The bump counter on the ticket updates.
3. **Order bump** — Kitchen staff taps the "BUMP" button at the bottom of the ticket. The order is stamped with `kitchenBumpedAt` and moves to the recall strip.
4. **Recall** — Bumped orders appear in a bottom strip for 30 seconds. Tapping recalls them back to the grid (clears `kitchenBumpedAt`).
5. **Sync back** — Bump state flows through the hub snapshot pipeline back to all POS terminals. A green checkmark badge appears on the table in the floor plan.

### Ticket urgency

Tickets change color based on elapsed time since the order was sent:

| Elapsed time | Urgency  | Visual                                     |
| ------------ | -------- | ------------------------------------------ |
| \< 5 minutes | Normal   | Green timer, standard border               |
| 5–10 minutes | Warning  | Amber timer, amber border with glow        |
| > 10 minutes | Critical | Red timer, red border with pulse animation |

### Change detection

When a POS terminal modifies a sent order (adds/removes items, changes quantities), the order status flips to `changed` and:

* The ticket gets a **MOD** badge and an amber ring highlight
* `kitchenBumpedAt` is cleared, so bumped orders reappear on the grid
* Added items show a green left border
* Changed quantities show the old and new values

### Ready badge on floor plan

When an order is bumped on the KDS, POS terminals show a green checkmark badge on the corresponding table in the floor plan. The badge:

* Appears when `kitchenBumpedAt` is set on the order
* Can be dismissed by tapping it (local state only, does not affect the order)
* Auto-resets when the order is modified (the badge reappears after the next bump)

### Audio alerts

The KDS plays audio cues for two events:

| Event                     | Sound           | Behavior                                               |
| ------------------------- | --------------- | ------------------------------------------------------ |
| New order arrives         | `new-order.mp3` | Plays once per new order (not on initial page load)    |
| First order goes critical | `overdue.mp3`   | Plays once, resets when all orders drop below critical |

Audio files are at `nu_pos_react/public/sounds/`. Replace the placeholder files with actual notification sounds.

## Data flow

KDS reuses the existing hub sync pipeline — no new protocol message types. Two fields carry bump state:

| Field               | Level      | Type                  | Purpose                        |
| ------------------- | ---------- | --------------------- | ------------------------------ |
| `kitchenItemStatus` | Order item | `"pending" \| "done"` | Individual item bump state     |
| `kitchenBumpedAt`   | Order      | `number` (timestamp)  | When the full order was bumped |

These fields flow through:

* **Sync protocol** — Zod schemas in `nu_pos_sync_protocol` (validated, not stripped)
* **Hub snapshots** — `ORDER_SNAPSHOT` and `SYNC_INIT` messages
* **Backend** — Persisted as `nu_kitchen_item_status` (Selection) and `nu_kitchen_bumped_at` (Datetime) on Odoo models
* **Direct API** — Included in order create/update payloads for non-hub setups

## Odoo configuration reference

| Field                    | Model            | Type      | Purpose                           |
| ------------------------ | ---------------- | --------- | --------------------------------- |
| `nu_terminal_mode`       | `pos.config`     | Selection | `"standard"` (default) or `"kds"` |
| `nu_kitchen_item_status` | `pos.order.line` | Selection | `"pending"` or `"done"`           |
| `nu_kitchen_bumped_at`   | `pos.order`      | Datetime  | Timestamp of last order bump      |

## Source files

```
# Domain
src/domain/kds/constants.ts          # Urgency thresholds, recall duration
src/domain/kds/models.ts             # KDSTicket, RecalledTicket types
src/domain/kds/selectors.ts          # filterKDSOrders, computeTicketUrgency
src/domain/kds/selectors.test.ts     # 10 tests

# UI components
src/features/kds/screens/KDSScreen.tsx           # Main screen
src/features/kds/components/ticket-grid.tsx       # Horizontal ticket grid
src/features/kds/components/ticket-card.tsx       # Individual ticket card
src/features/kds/components/ticket-item.tsx       # Item row within a ticket
src/features/kds/components/recall-strip.tsx      # Bottom recall strip
src/features/kds/components/kds-header.tsx        # Header with stats and clock
src/features/kds/hooks/useKDSAudio.ts             # Audio alert hook
src/features/kds/hooks/useTicketDiff.ts           # Change diff detection

# Route
src/app/kds/page.tsx                 # Next.js /kds route

# Backend
nu_restaurant_pos/models/pos_config.py            # nu_terminal_mode field
nu_restaurant_pos/models/pos_order.py             # nu_kitchen_bumped_at field
nu_restaurant_pos/models/pos_order_line.py        # nu_kitchen_item_status field
nu_restaurant_pos/models/pos_bootstrap_data.py    # Bootstrap payload
```
