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.
The POS system is designed to never block staff from taking orders, regardless of network conditions. Every local action is captured as an idempotent event and safely queued for later delivery.
How offline works
| Scenario | Behavior |
|---|
| Odoo down (direct mode) | Outbox queues HTTP requests, retries with exponential backoff |
| Hub down (hub mode) | Transport falls back to outbox; orders still editable locally |
| Internet down (hub mode) | Hub still works on LAN; terminals sync via hub normally |
| Hub + Internet down | Terminal works fully offline, outbox accumulates |
| Recovery | Outbox drains automatically; hub reconciles on reconnect |
localStorage outbox
nu_pos_react/src/realtime/sync/outbox.ts
The outbox is a queue of pending HTTP actions stored in localStorage under the key pos_sync_outbox. It survives browser refreshes and crashes.
Entry structure
interface OutboxEntry {
id: string; // UUID
action: "orders/create" | "orders/update";
payload: Record<string, unknown>;
createdAt: string; // ISO timestamp
attempts: number; // Number of send attempts
nextAttemptAt: string | null; // Earliest retry time
lastError: string | null; // Last failure message
}
Queuing
queueOutbound("orders/create", {
pos_reference: "POS-001-0001-00001",
lines: [...],
amount_total: 150.00,
});
Entries are deduplicated by pos_reference: if an entry with the same reference already exists, it’s replaced with the newer payload. This prevents duplicate orders.
In hub mode, when connection.send() fails, the snapshot is queued as an outbox entry with an _hubSnapshot field.
Flushing
flushOutbound() processes the queue:
- Reads all entries from localStorage
- Filters entries where
nextAttemptAt <= now (respects backoff)
- For each entry, sends
POST /pos-react/api/orders/{action} to Odoo
- On success: removes entry from queue
- On failure: increments
attempts, computes next retry time, stores error
Retry backoff
| Attempt | Delay |
|---|
| 1 | 1s |
| 2 | 2s |
| 3 | 4s |
| 4 | 8s |
| 5 | 16s |
| 6+ | 32s-60s (capped) |
After maxRetry attempts (default 8), the entry stays in the queue but won’t be retried until app restart.
Outbox depth monitoring
The transport exposes getOutboxDepth() which returns the current number of pending entries. This is reflected in the sync state machine via OUTBOX_CHANGED events and displayed by the SyncStatusIndicator badge.
Hub-side event log
The hub maintains its own event log for upstream forwarding to Odoo. This is a separate mechanism from the terminal outbox.
CREATE TABLE events (
id INTEGER PRIMARY KEY AUTOINCREMENT,
type TEXT NOT NULL, -- 'order_snapshot', 'table_update', etc.
pos_reference TEXT,
terminal_id TEXT,
payload TEXT, -- JSON
forwarded INTEGER DEFAULT 0, -- 0=pending, 1=forwarded to Odoo
created_at TEXT DEFAULT (datetime('now'))
);
Forwarder
nu_pos_hub/src/upstream/forwarder.ts drains the event log to Odoo:
- Runs every 5 seconds (
FORWARD_INTERVAL_MS)
- Queries up to 20 pending events (
FORWARD_BATCH_SIZE), oldest first
- Non-order events are marked as forwarded immediately (no Odoo action needed)
- Order snapshot events are forwarded via the Odoo adapter
- On success: marks events as
forwarded=1
- On first failure: logs error, stops processing batch (preserves ordering)
If Odoo is unreachable, the hub authenticates first, then retries. Events accumulate safely in SQLite.
Idempotency
All order operations are idempotent via pos_reference:
- Odoo’s create endpoint returns the existing order if the reference already exists
- The hub’s
orderStore.upsert() uses INSERT OR REPLACE keyed by pos_reference
- The outbox deduplicates by
pos_reference before queuing
Re-forwarding the same event (after a crash, restart, or retry) is always safe.
Visibility
| Tool | What it shows |
|---|
SyncStatusIndicator (frontend) | Transport state, outbox depth, error indicator |
Hub dashboard (http://hub:8766/) | Connected terminals, pending forwards, event log |
CLI pos-hub stats | Uptime, terminal count, pending/forwarded events |
CLI pos-hub events | Recent event log with forwarded status |