Skip to content

feat(orders): scheduled orders and kitchen release - #1408

Merged
khaira777 merged 12 commits into
mainfrom
fm/flocafe-360-scheduled-orders
Oct 29, 2026
Merged

khaira777 merged 12 commits into
mainfrom
fm/flocafe-360-scheduled-orders

Conversation

@khaira777

@khaira777 khaira777 commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #360

Intent

Implement FloCafe issue #360 (Feature: Scheduled orders with release semantics) for takeaway and delivery orders

What Changed

  • Added database schema migration 123 (scheduled_for, release_status, released_at, release_blocked_reason) and background sweep service (main/services/scheduled-orders.ts) to defer inventory deduction, KDS dispatch, and automatic KOT printing until release at store-timezone scheduled times or manual release.
  • Added scheduled order API endpoints (GET /api/orders/scheduled, PATCH /api/orders/:id/schedule, POST /api/orders/:id/release), allowed prepayment while edit-locking item and customer changes once paid, guarded KDS and KOT printing against unreleased orders, and required full refunds before cancelling paid scheduled orders.
  • Added POS and Orders UI support including a "Send to kitchen at" cart picker with DST and timezone validation, a POS topbar drawer for managing, releasing, and paying scheduled orders, and Orders list and detail view badges with updated edit and refund action guards.

Risk Assessment

✅ Low: Scheduled order release semantics, inventory deferral, cursor pagination, edit locks, and payment reconciliation are cleanly isolated, correct, and well-tested without residual defects.

Testing

Validated scheduled order lifecycle live against real backend, KDS, POS cart, Scheduled Orders drawer, and /orders surfaces with 5 UI screenshots and 344 passing automated backend tests; all scenarios passed.

  • Live validation: ✅ go - 7 of 7 scenarios driven live against the product
Scenario Result Live Evidence
Staff selects takeaway or delivery in POS to reveal 'Send to kitchen at'; past times trigger an inline validation error and disable ordering, while selecting dine-in or online hides the schedule secti… ✅ pass live ~/.no-mistakes/evidence/01M64RGSAQ1AJXAP24KC66FB40/01-pos-send-to-kitchen-at.png
Staff takes prepayment on a scheduled takeaway order; payment is recorded, order status remains pending (not completed), inventory stock is not deducted prematurely, and order is excluded from KDS dis… ✅ pass live ~/.no-mistakes/evidence/01M64RGSAQ1AJXAP24KC66FB40/02-scheduled-drawer-paid-edit-locked.png
Staff opens the Scheduled Orders drawer in POS; prepaid order displays Paid badge with item/financial edit controls locked, while rescheduling to a later delivery time succeeds and records an audited… ✅ pass live ~/.no-mistakes/evidence/01M64RGSAQ1AJXAP24KC66FB40/02-scheduled-drawer-paid-edit-locked.png
Attempted release of a scheduled order with insufficient inventory sets release_status to blocked with actionable shortage details; restocking inventory and clicking Retry release successfully transit… ✅ pass live ~/.no-mistakes/evidence/01M64RGSAQ1AJXAP24KC66FB40/03-scheduled-drawer-blocked-shortage.png
Staff appends items to an existing unreleased delivery scheduled order from the POS drawer; order loads into cart with banner, existing address/notes are preserved, customer selection dialog is bypass… ✅ pass live cd frontend && EVIDENCE_DIR=~/.no-mistakes/evidence/01M64RGSAQ1AJXAP24KC66FB40 npx playwright test --config=playwright.config.ts --project=chromium e2e/scheduled-orders.spec.ts
On /orders, a partially paid released scheduled order displays Partially Paid badge with locked item/customer edits and an exposed Refund button; attempting cancellation without refunding blocks with… ✅ pass live ~/.no-mistakes/evidence/01M64RGSAQ1AJXAP24KC66FB40/04-orders-released-partially-paid.png and ~/.no-mistakes/evidence/01M64RGSAQ1AJXAP24KC66FB40/05-orders-releas…
Server-side background due sweep identifies scheduled orders reaching their release time, executes atomic transactional release, deducts item and recipe inventory, and broadcasts release to active KDS… ✅ pass live npm run test:scheduled-orders (344/344 passed)

POS Send to kitchen at schedule picker and validation
Scheduled orders drawer paid badge and edit lock
Scheduled orders drawer blocked inventory shortage reason
/orders released scheduled order with partial payment badge and exposed refund
/orders released scheduled order partially refunded badge with suppressed checkout

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

✅ **Review** - passed

✅ No issues found.

✅ **Test** - passed

✅ No issues found.

  • Live validation: ✅ go - 7 of 7 scenarios driven live against the product
Scenario Result Live Evidence
Staff selects takeaway or delivery in POS to reveal 'Send to kitchen at'; past times trigger an inline validation error and disable ordering, while selecting dine-in or online hides the schedule secti… ✅ pass live ~/.no-mistakes/evidence/01M64RGSAQ1AJXAP24KC66FB40/01-pos-send-to-kitchen-at.png
Staff takes prepayment on a scheduled takeaway order; payment is recorded, order status remains pending (not completed), inventory stock is not deducted prematurely, and order is excluded from KDS dis… ✅ pass live ~/.no-mistakes/evidence/01M64RGSAQ1AJXAP24KC66FB40/02-scheduled-drawer-paid-edit-locked.png
Staff opens the Scheduled Orders drawer in POS; prepaid order displays Paid badge with item/financial edit controls locked, while rescheduling to a later delivery time succeeds and records an audited… ✅ pass live ~/.no-mistakes/evidence/01M64RGSAQ1AJXAP24KC66FB40/02-scheduled-drawer-paid-edit-locked.png
Attempted release of a scheduled order with insufficient inventory sets release_status to blocked with actionable shortage details; restocking inventory and clicking Retry release successfully transit… ✅ pass live ~/.no-mistakes/evidence/01M64RGSAQ1AJXAP24KC66FB40/03-scheduled-drawer-blocked-shortage.png
Staff appends items to an existing unreleased delivery scheduled order from the POS drawer; order loads into cart with banner, existing address/notes are preserved, customer selection dialog is bypass… ✅ pass live cd frontend && EVIDENCE_DIR=~/.no-mistakes/evidence/01M64RGSAQ1AJXAP24KC66FB40 npx playwright test --config=playwright.config.ts --project=chromium e2e/scheduled-orders.spec.ts
On /orders, a partially paid released scheduled order displays Partially Paid badge with locked item/customer edits and an exposed Refund button; attempting cancellation without refunding blocks with… ✅ pass live ~/.no-mistakes/evidence/01M64RGSAQ1AJXAP24KC66FB40/04-orders-released-partially-paid.png and ~/.no-mistakes/evidence/01M64RGSAQ1AJXAP24KC66FB40/05-orders-releas…
Server-side background due sweep identifies scheduled orders reaching their release time, executes atomic transactional release, deducts item and recipe inventory, and broadcasts release to active KDS… ✅ pass live npm run test:scheduled-orders (344/344 passed)
  • npm run build
  • npm run build:frontend
  • npm run test:scheduled-orders
  • cd frontend && EVIDENCE_DIR=~/.no-mistakes/evidence/01M64RGSAQ1AJXAP24KC66FB40 npx playwright test --config=playwright.config.ts --project=chromium e2e/scheduled-orders.spec.ts
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

@coderabbitai

coderabbitai Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

Run configuration

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Add scheduled orders with deferred kitchen release

✨ Enhancement 🧪 Tests 📝 Documentation ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Schedule takeaway and delivery orders in store time without sending them to the kitchen early.
• Release due orders server-side, holding the whole order when stock or catalog validation fails.
• Support prepayment, audited rescheduling, refunds, and staff retries across POS and order
 workflows.
Diagram

graph TD
  POS["POS scheduling"] --> Time["Timezone validation"] --> DB["Order records"] --> Sweep["Due sweep"] --> Release{"Release valid?"} --> Inventory["Inventory snapshots"] --> Kitchen["KDS and KOT"]
  Release --> Hold["Blocked queue"] --> POS
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Persist one job per release
  • ➕ Could trigger closer to the exact scheduled instant.
  • ➕ Avoids repeatedly querying the due-order index.
  • ➖ Adds durable job state and recovery coordination to a local SQLite deployment.
  • ➖ Still needs reconciliation after downtime, rescheduling, and failed release.

Recommendation: Keep the indexed, server-owned sweep and shared transactional release operation. It makes restart and resume recovery straightforward without a second scheduling authority; persistent jobs add coordination for limited benefit at a 10-second target interval.

Files changed (69) +8595 / -551

Enhancement (28) +3968 / -453
page.tsxRespect scheduled payment and cancellation guards +61/-32

Respect scheduled payment and cancellation guards

• Shows payment-locked edit failures and refund-before-cancel guidance while preventing locked item additions.

frontend/src/app/(dashboard)/orders/page.tsx

page.tsxWire scheduling and queue actions into POS +275/-5

Wire scheduling and queue actions into POS

• Submits validated schedule times through prepaid and postpaid flows, polls the scheduled queue, and connects payment, refund, append, release, and printer settings.

frontend/src/app/(dashboard)/pos/page.tsx

OrderCard.tsxShow release and payment states on order cards +73/-42

Show release and payment states on order cards

• Adds scheduled and blocked badges and shared payment states; gates edits and exposes eligible checkout and refund actions.

frontend/src/components/orders/OrderCard.tsx

OrderDetailPanel.tsxExpose scheduled-order controls in details +64/-39

Expose scheduled-order controls in details

• Displays release and refund states and uses shared payment rules to gate item, customer, checkout, and refund actions.

frontend/src/components/orders/OrderDetailPanel.tsx

OrdersMasterList.tsxDistinguish unreleased orders in the list +29/-8

Distinguish unreleased orders in the list

• Shows scheduled or blocked release badges instead of ordinary kitchen-status badges for unreleased orders.

frontend/src/components/orders/OrdersMasterList.tsx

RefundModal.tsxBase late-refund guidance on release +8/-4

Base late-refund guidance on release

• Treats unreleased orders as within the normal refund window and uses released_at for released scheduled orders.

frontend/src/components/orders/RefundModal.tsx

CartPanel.tsxAdd store-timezone scheduling input +140/-7

Add store-timezone scheduling input

• Offers “Send to kitchen at” for new takeaway and delivery orders, validates the time, and identifies scheduled append mode.

frontend/src/components/pos/CartPanel.tsx

PaymentModal.tsxLock paid scheduled-order financial controls +4/-1

Lock paid scheduled-order financial controls

• Suppresses discount and charge edits after a scheduled order has recorded payment.

frontend/src/components/pos/PaymentModal.tsx

PosTopbar.tsxAdd scheduled-queue entry point +39/-0

Add scheduled-queue entry point

• Adds a scheduled-order button with counts and a visual alert when releases are blocked.

frontend/src/components/pos/PosTopbar.tsx

ScheduledOrdersDrawer.tsxManage unreleased orders from POS +736/-0

Manage unreleased orders from POS

• Lists upcoming and blocked orders with reasons and payment state, and supports release, retry, reschedule, edit, payment, refund, and cancellation actions.

frontend/src/components/pos/ScheduledOrdersDrawer.tsx

scheduled-time.tsExpose shared scheduling-time utilities to frontend +14/-0

Expose shared scheduling-time utilities to frontend

• Re-exports timezone parsing, formatting, and future-time suggestions from the shared module.

frontend/src/lib/scheduled-time.ts

types.tsType scheduled release fields +4/-0

Type scheduled release fields

• Adds scheduled instant, release status, actual release time, and blocked reason to the Order type.

frontend/src/lib/types.ts

cart.tsTrack schedule time in the cart +7/-0

Track schedule time in the cart

• Stores the selected wall-clock time and clears it when the cart resets or switches to an unsupported order type.

frontend/src/store/cart.ts

db.tsMigrate release state and share kitchen/payment guards +192/-1

Migrate release state and share kitchen/payment guards

• Adds migration 122 and its due index, released-only KDS selection, and helpers for settled-order completion after kitchen service.

main/db.ts

index.tsSweep scheduled orders after desktop resume +2/-0

Sweep scheduled orders after desktop resume

• Triggers overdue-release recovery when Electron receives a system-resume event.

main/index.ts

kds-server.tsEnforce release state on standalone KDS +29/-13

Enforce release state on standalone KDS

• Excludes unreleased orders, rejects their item-status changes, and completes eligible prepaid orders when kitchen work is served.

main/kds-server.ts

bills.tsKeep prepayment separate from kitchen completion +134/-66

Keep prepayment separate from kitchen completion

• Allows payment before release without completing the order or requiring kitchen delivery, and locks scheduled-order financial edits after payment.

main/routes/bills.ts

kds.tsGate KDS reads and writes by release +30/-11

Gate KDS reads and writes by release

• Filters unreleased orders from KDS feeds, rejects premature item updates, and completes settled orders after service.

main/routes/kds.ts

kitchen.tsHide unreleased orders from kitchen feed +94/-49

Hide unreleased orders from kitchen feed

• Uses the shared released-order query so scheduled and blocked orders stay out of kitchen views.

main/routes/kitchen.ts

order-items.tsProtect order-item kitchen transitions +33/-4

Protect order-item kitchen transitions

• Rejects KDS-style changes before release and completes eligible settled orders when their final active item is served.

main/routes/order-items.ts

orders.tsAdd scheduled-order creation and management APIs +551/-152

Add scheduled-order creation and management APIs

• Adds queue, reschedule, and release endpoints; defers stock on creation and edits, enforces post-payment locks and refund-before-cancel, and avoids premature kitchen notifications.

main/routes/orders.ts

printers.tsPrint KOT only after kitchen release +87/-0

Print KOT only after kitchen release

• Rejects manual KOT printing before release and adds backend auto-printing for released orders using configured printers and language settings.

main/routes/printers.ts

server.tsOwn scheduled sweeps in server lifecycle +4/-0

Own scheduled sweeps in server lifecycle

• Starts the due sweep with the API server and stops its interval during shutdown.

main/server.ts

customer-display-tokens.tsHide unreleased orders from pickup boards +4/-2

Hide unreleased orders from pickup boards

• Restricts board-eligible order queries to released orders.

main/services/customer-display-tokens.ts

kds.tsApply release rules to KDS WebSockets +34/-11

Apply release rules to KDS WebSockets

• Filters unreleased orders, refuses their status changes, and records completion when prepaid kitchen work finishes.

main/services/kds.ts

refund.tsAnchor scheduled refund windows to release +12/-6

Anchor scheduled refund windows to release

• Exempts unreleased orders from late-refund timing and uses released_at instead of creation time after release.

main/services/refund.ts

scheduled-orders.tsImplement transactional kitchen release service +963/-0

Implement transactional kitchen release service

• Shares manual and due-sweep release, validates current catalog and stock, atomically records depletion or a whole-order hold, and emits kitchen and print effects after commit.

main/services/scheduled-orders.ts

scheduled-time.tsParse scheduled store times safely +345/-0

Parse scheduled store times safely

• Converts valid store wall-clock inputs to UTC, rejects past and skipped or repeated DST times, and formats saved instants for entry and display.

shared/scheduled-time.ts

Bug fix (2) +14 / -5
database.tsPreserve scheduled columns during import +10/-3

Preserve scheduled columns during import

• Includes per-row order columns on import while allowing legacy rows to receive the released-state default.

main/routes/database.ts

reports.tsExclude unreleased orders from kitchen counts +4/-2

Exclude unreleased orders from kitchen counts

• Limits running and pending daily-stat counts to orders released to the kitchen.

main/routes/reports.ts

Refactor (1) +184 / -0
order-payment-state.tsCentralize order payment-state decisions +184/-0

Centralize order payment-state decisions

• Provides shared bill, collected-funds, edit-lock, checkout, refund, and cancellation-error helpers for POS and Orders views.

frontend/src/lib/order-payment-state.ts

Tests (8) +3446 / -4
database-export-import.spec.tsAdvance export/import schema fixture +1/-1

Advance export/import schema fixture

• Updates the expected schema version to 122.

frontend/e2e/database-export-import.spec.ts

scheduled-orders.spec.tsExercise scheduled POS workflow end to end +553/-0

Exercise scheduled POS workflow end to end

• Covers scheduling, prepayment without early release, queue actions, rescheduling, refund-before-cancel, and blocked-release retry.

frontend/e2e/scheduled-orders.spec.ts

settings-request-budget.spec.tsTest printer-setting hydration and persistence +51/-0

Test printer-setting hydration and persistence

• Verifies KOT auto-print, Unicode, and Arabic shaping settings hydrate and save, including explicit false values.

frontend/e2e/settings-request-budget.spec.ts

package.jsonRegister scheduled-order regression suite +2/-1

Register scheduled-order regression suite

• Adds a dedicated test command to the main test sequence.

package.json

backup-restore-production.test.tsExpect schema version 122 after restore +2/-2

Expect schema version 122 after restore

• Updates the restored-database migration expectation.

tests/backup-restore-production.test.ts

ingredient-cost-lifecycle.test.tsAdvance ingredient-cost fixture through migrations +6/-0

Advance ingredient-cost fixture through migrations

• Runs migrations after version 117 so ingredient-cost lifecycle assertions execute against the current schema.

tests/ingredient-cost-lifecycle.test.ts

issue-360-scheduled-orders.test.tsCover scheduled release invariants +2751/-0

Cover scheduled release invariants

• Exercises DST validation, deferred stock and kitchen effects, sweeps, atomic holds, retries, payment locks, refunds, cancellation, and the shared release hook.

tests/issue-360-scheduled-orders.test.ts

upgrade-path.test.tsVerify migration 122 upgrade path +80/-0

Verify migration 122 upgrade path

• Checks release columns, due index, legacy-order defaults, and schema health after upgrading a version-121 database.

tests/upgrade-path.test.ts

Documentation (28) +922 / -88
business-time.mdDocument scheduled-time and refund anchors +26/-5

Document scheduled-time and refund anchors

• Explains store-timezone input, DST rejection, UTC persistence, and refund windows anchored to release for scheduled orders.

docs/architecture/business-time.md

order-lifecycle.mdDefine scheduled-order lifecycle +65/-4

Define scheduled-order lifecycle

• Documents deferred inventory and kitchen effects, automatic and manual release, blocked holds, payment locks, cancellation, and completion.

docs/architecture/order-lifecycle.md

api.mdDocument scheduled-order API contracts +27/-22

Document scheduled-order API contracts

• Adds queue, scheduling, and release endpoints and describes scheduling parameters, payment-edit conflicts, and refund-before-cancel responses.

docs/reference/api.md

product-invariants.mdClarify scheduled refund approval timing +12/-9

Clarify scheduled refund approval timing

• Specifies that unreleased scheduled orders do not age into late-refund restrictions and released orders use their release timestamp.

docs/reference/product-invariants.md

ar.jsonTranslate scheduled-order UI into Arabic +33/-2

Translate scheduled-order UI into Arabic

• Adds release, payment, queue, scheduling, DST, and refund guidance strings.

frontend/src/lib/i18n/messages/ar.json

bn.jsonTranslate scheduled-order UI into Bengali +33/-2

Translate scheduled-order UI into Bengali

• Adds release, payment, queue, scheduling, DST, and refund guidance strings.

frontend/src/lib/i18n/messages/bn.json

de.jsonTranslate scheduled-order UI into German +33/-2

Translate scheduled-order UI into German

• Adds release, payment, queue, scheduling, DST, and refund guidance strings.

frontend/src/lib/i18n/messages/de.json

en.jsonDefine English scheduled-order messages +33/-2

Define English scheduled-order messages

• Adds labels and explanations for queue actions, release states, payments, refunds, and invalid scheduling times.

frontend/src/lib/i18n/messages/en.json

es.jsonTranslate scheduled-order UI into Spanish +33/-2

Translate scheduled-order UI into Spanish

• Adds release, payment, queue, scheduling, DST, and refund guidance strings.

frontend/src/lib/i18n/messages/es.json

fa.jsonTranslate scheduled-order UI into Persian +33/-2

Translate scheduled-order UI into Persian

• Adds release, payment, queue, scheduling, DST, and refund guidance strings.

frontend/src/lib/i18n/messages/fa.json

fil.jsonTranslate scheduled-order UI into Filipino +33/-2

Translate scheduled-order UI into Filipino

• Adds release, payment, queue, scheduling, DST, and refund guidance strings.

frontend/src/lib/i18n/messages/fil.json

fr.jsonTranslate scheduled-order UI into French +33/-2

Translate scheduled-order UI into French

• Adds release, payment, queue, scheduling, DST, and refund guidance strings.

frontend/src/lib/i18n/messages/fr.json

hi.jsonTranslate scheduled-order UI into Hindi +33/-2

Translate scheduled-order UI into Hindi

• Adds release, payment, queue, scheduling, DST, and refund guidance strings.

frontend/src/lib/i18n/messages/hi.json

id.jsonTranslate scheduled-order UI into Indonesian +33/-2

Translate scheduled-order UI into Indonesian

• Adds release, payment, queue, scheduling, DST, and refund guidance strings.

frontend/src/lib/i18n/messages/id.json

it.jsonTranslate scheduled-order UI into Italian +33/-2

Translate scheduled-order UI into Italian

• Adds release, payment, queue, scheduling, DST, and refund guidance strings.

frontend/src/lib/i18n/messages/it.json

ja.jsonTranslate scheduled-order UI into Japanese +33/-2

Translate scheduled-order UI into Japanese

• Adds release, payment, queue, scheduling, DST, and refund guidance strings.

frontend/src/lib/i18n/messages/ja.json

ko.jsonTranslate scheduled-order UI into Korean +33/-2

Translate scheduled-order UI into Korean

• Adds release, payment, queue, scheduling, DST, and refund guidance strings.

frontend/src/lib/i18n/messages/ko.json

ne.jsonTranslate scheduled-order UI into Nepali +33/-2

Translate scheduled-order UI into Nepali

• Adds release, payment, queue, scheduling, DST, and refund guidance strings.

frontend/src/lib/i18n/messages/ne.json

nl.jsonTranslate scheduled-order UI into Dutch +33/-2

Translate scheduled-order UI into Dutch

• Adds release, payment, queue, scheduling, DST, and refund guidance strings.

frontend/src/lib/i18n/messages/nl.json

pt.jsonTranslate scheduled-order UI into Portuguese +33/-2

Translate scheduled-order UI into Portuguese

• Adds release, payment, queue, scheduling, DST, and refund guidance strings.

frontend/src/lib/i18n/messages/pt.json

ru.jsonTranslate scheduled-order UI into Russian +33/-2

Translate scheduled-order UI into Russian

• Adds release, payment, queue, scheduling, DST, and refund guidance strings.

frontend/src/lib/i18n/messages/ru.json

sq.jsonTranslate scheduled-order UI into Albanian +33/-2

Translate scheduled-order UI into Albanian

• Adds release, payment, queue, scheduling, DST, and refund guidance strings.

frontend/src/lib/i18n/messages/sq.json

th.jsonTranslate scheduled-order UI into Thai +33/-2

Translate scheduled-order UI into Thai

• Adds release, payment, queue, scheduling, DST, and refund guidance strings.

frontend/src/lib/i18n/messages/th.json

tr.jsonTranslate scheduled-order UI into Turkish +33/-2

Translate scheduled-order UI into Turkish

• Adds release, payment, queue, scheduling, DST, and refund guidance strings.

frontend/src/lib/i18n/messages/tr.json

ur.jsonTranslate scheduled-order UI into Urdu +33/-2

Translate scheduled-order UI into Urdu

• Adds release, payment, queue, scheduling, DST, and refund guidance strings.

frontend/src/lib/i18n/messages/ur.json

vi.jsonTranslate scheduled-order UI into Vietnamese +33/-2

Translate scheduled-order UI into Vietnamese

• Adds release, payment, queue, scheduling, DST, and refund guidance strings.

frontend/src/lib/i18n/messages/vi.json

zh-tw.jsonTranslate scheduled-order UI into Traditional Chinese +33/-2

Translate scheduled-order UI into Traditional Chinese

• Adds release, payment, queue, scheduling, DST, and refund guidance strings.

frontend/src/lib/i18n/messages/zh-tw.json

zh.jsonTranslate scheduled-order UI into Chinese +33/-2

Translate scheduled-order UI into Chinese

• Adds release, payment, queue, scheduling, DST, and refund guidance strings.

frontend/src/lib/i18n/messages/zh.json

Other (2) +61 / -1
page.tsxPersist shared printer behavior settings +52/-0

Persist shared printer behavior settings

• Hydrates and saves backend KOT auto-print, Unicode, and Arabic shaping flags used during server-side release printing.

frontend/src/app/(dashboard)/settings/page.tsx

settings.tsExpose backend printing flags +9/-1

Expose backend printing flags

• Adds defaults and batch-setting support for KOT auto-print, Unicode, and Arabic shaping.

main/routes/settings.ts

@qodo-code-review

qodo-code-review Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Rescheduling can silently retry a held order ✓ Resolved
Description
PATCH /:id/schedule changes a blocked order back to release_status = 'scheduled' and clears its
hold reason when staff change only its release time. Once the new time is due, the automatic sweep
attempts release again without an explicit retry, including when the stock or catalog problem has
not been resolved.
Code

main/routes/orders.ts[R2384-2386]

+           SET scheduled_for = ?,
+               release_status = 'scheduled',
+               release_blocked_reason = NULL,
Relevance

●●● Strong

Rescheduling explicitly retries blocked orders, contradicting the stated requirement that blocked
releases need manual retry.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The reschedule endpoint accepts an unreleased blocked order and unconditionally sets it to
scheduled. The sweep selects due scheduled rows but deliberately excludes blocked rows, so the
timing edit changes whether an automatic retry occurs.

main/routes/orders.ts[2358-2389]
main/services/scheduled-orders.ts[851-879]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Rescheduling a blocked order clears its hold and enrolls it in automatic release, bypassing the explicit-retry path.

## Fix Focus Areas
- main/routes/orders.ts[2365-2389]
- main/services/scheduled-orders.ts[851-879]

## Recommended Fix
For an order already blocked, update only its scheduled instant; retain its blocked status and reason. Keep the transition out of blocked state in the explicit manual release operation.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. One failing order stalls every later release ✓ Resolved
Description
sweepDueScheduledOrders awaits releaseScheduledOrder for each due row with no per-order
try/catch. releaseScheduledOrder only turns stock/catalog errors (the listed error classes or
statusCode 400/404) into a blocked hold and rethrows everything else, so any other error escapes
the loop and the whole sweep ends in triggerScheduledOrderSweep's catch. Rows are ordered by
scheduled_for ASC, so the same failing order comes up first again every 10 seconds, and every
order due after it never reaches the kitchen until staff release it by hand.
Code

main/services/scheduled-orders.ts[R888-894]

+  for (const row of dueRows) {
+    const result = await releaseScheduledOrder(db, row.id, {
+      trigger,
+      nowDate,
+      autoPrintKot: options?.autoPrintKot,
+      checkPreconditions: options?.checkPreconditions,
+    });
Relevance

●●● Strong

Uncaught per-order failures can stall the entire sweep; resilient background processing generally
isolates failed items.

PR-#1384

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The release transaction rethrows any error that is not a hold error (lines 739-744). The sweep loop
calls the release once per row with no catch (888-902). The outer catch only logs and returns an
empty summary (927-936), and nothing marks the failing order as blocked or skips it. The due query
(869-879) sorts by scheduled_for ASC, so the next sweep picks the same order first and fails the
same way. Possible sources include SQLite constraint or IO errors from audit, recipe or stock
writes, and plain Errors from helpers that carry no statusCode.

main/services/scheduled-orders.ts[739-744]
main/services/scheduled-orders.ts[869-902]
main/services/scheduled-orders.ts[924-937]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`sweepDueScheduledOrders` has no per-order error handling. If one order hits an error that is not a stock/catalog hold, the whole sweep aborts. That order is first in `scheduled_for ASC` order, so it blocks every later due order on every 10-second sweep.

## Fix Focus Areas
- main/services/scheduled-orders.ts[888-902]
- main/services/scheduled-orders.ts[739-744]

## Recommended Fix
Wrap each `releaseScheduledOrder` call in the loop in try/catch. On an unexpected error, log it with the order id and trigger, push the id to `skippedIds` (or a new `failedIds`) and move on to the next row. You can also persist `release_status = 'blocked'` with a generic reason, so staff see the failure in the scheduled queue and the sweep stops retrying a poison row forever.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Orders beyond the queue limit disappear ✓ Resolved
Description
GET /orders/scheduled applies LIMIT 200 without a cursor or another way for the drawer to
request subsequent rows. When more than 200 unreleased orders exist, the drawer omits the
rest—including newer scheduled orders when blocked orders occupy the first 200 slots—so staff cannot
manage those orders from the scheduled queue.
Code

main/routes/orders.ts[R1454-1457]

+             ORDER BY CASE WHEN release_status = 'blocked' THEN 0 ELSE 1 END ASC,
+                      scheduled_for ASC,
+                      id ASC
+             LIMIT 200`,
Relevance

●●● Strong

A fixed limit without pagination hides active orders; recent history accepts correcting
limit-ordering omissions.

PR-#1105

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The endpoint returns only the first 200 rows, sorted with blocked orders first. The POS consumes
that single response as its complete scheduled-order state, and the drawer renders only the supplied
orders.

main/routes/orders.ts[1441-1462]
frontend/src/app/(dashboard)/pos/page.tsx[988-1000]
frontend/src/components/pos/ScheduledOrdersDrawer.tsx[119-129]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The scheduled queue silently truncates at 200 orders and provides no route to later entries.

## Fix Focus Areas
- main/routes/orders.ts[1441-1462]
- frontend/src/app/(dashboard)/pos/page.tsx[989-1000]
- frontend/src/components/pos/ScheduledOrdersDrawer.tsx[659-736]

## Recommended Fix
Add cursor-based pagination to the endpoint and a way to load subsequent pages in the drawer. Ensure blocked and upcoming orders remain reachable beyond the first page.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. Partly paid orders lose their Pay button ✓ Resolved
Description
canPayScheduledOrder recognizes partial but not the persisted partially_paid bill status, and
handlePayScheduledOrder repeats that exclusion when selecting and validating a bill. A scheduled
order with an outstanding balance in that status cannot continue payment through the new POS drawer,
although the backend accepts the bill as payable.
Code

frontend/src/components/pos/ScheduledOrdersDrawer.tsx[R63-66]

+  return (
+    bills.length === 0 ||
+    bills.some((b) => b.payment_status === 'unpaid' || b.payment_status === 'partial')
+  );
Relevance

●●● Strong

Missing persisted payable status is a deterministic UI correctness bug, and both frontend checks
must include it.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Both new UI checks exclude partially_paid, while existing backend bill synchronization and payment
validation include it among payable statuses.

frontend/src/components/pos/ScheduledOrdersDrawer.tsx[61-66]
frontend/src/app/(dashboard)/pos/page.tsx[2476-2493]
main/routes/bills.ts[2285-2289]
main/routes/bills.ts[2449-2455]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The scheduled-order Pay action excludes bills in the backend-supported `partially_paid` state.

## Fix Focus Areas
- frontend/src/components/pos/ScheduledOrdersDrawer.tsx[61-66]
- frontend/src/app/(dashboard)/pos/page.tsx[2476-2493]
- frontend/src/lib/types.ts[288-288]

## Recommended Fix
Use one payable-bill predicate for the drawer button, bill selection, and fetched-bill validation. Include `partially_paid` in the bill type so the supported persisted state is represented accurately.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View medium (1)
5. Future orders inflate cloud activity ✓ Resolved
Description
Scheduled-order creation persists kitchen status = 'pending' even while `release_status =
'scheduled', but buildHeartbeatPayload` counts active orders using kitchen status alone. Every
unreleased scheduled order therefore increases the active_orders value sent to cloud monitoring
before any kitchen release.
Code

main/routes/orders.ts[R1894-1896]

+          scheduled_for, release_status, released_at, release_blocked_reason,
+          status, created_at, updated_at)
+        VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, NULL, 'pending', ?, ?)
Relevance

●● Moderate

The mismatch is plausible, but historical evidence does not establish whether scheduled pending
orders count as active telemetry.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The new insert pairs a scheduled release state with pending kitchen status. The unchanged heartbeat
query counts all pending orders and places that count in the cloud payload.

main/routes/orders.ts[1890-1919]
main/services/cloud-sync.ts[2942-2948]
main/services/cloud-sync.ts[2966-2978]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The cloud heartbeat counts future scheduled orders as active because its query checks only kitchen status.

## Fix Focus Areas
- main/routes/orders.ts[1890-1919]
- main/services/cloud-sync.ts[2942-2949]

## Recommended Fix
Filter the heartbeat's active-order count to `release_status = 'released'`, consistent with the kitchen-facing active-order queries.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
⚠️ Tickets: not configured — No jira, linear integration is connected for the linked tickets
✅ Compliance rules (platform): 5 rules
✅ Cross-repo context — repo relationships
  Explored: repo: FreeOpenSourcePOS/docs.flopos.com (sha: abe7cff3) — View relationship
Review mode: Auto: 🧠 Deep: Dense cross-cutting scheduling, inventory, payment, timezone, and migration logic.

Grey Divider

Tip of the day
💡 Did you know, you can add REVIEW.md to your repo root and Qodo follows it on every PR

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread main/routes/orders.ts Outdated
Comment thread frontend/src/components/pos/ScheduledOrdersDrawer.tsx Outdated
Comment thread main/routes/orders.ts Outdated
Comment thread main/routes/orders.ts
Comment thread main/services/scheduled-orders.ts Outdated
Add scheduled takeaway and delivery orders with store-timezone DST validation, deferred inventory depletion and KDS/KOT suppression before release, a 10-second server due sweep with startup and resume triggers, atomic whole-order hold on insufficient stock or unusable catalog items with explicit staff retry, prepaid settlement without early release, payment-locked item/financial edits with audited timing-only reschedules, refund-before-cancel enforcement, POS scheduled queue UI, 24-locale translations, and canonical docs.
@khaira777
khaira777 force-pushed the fm/flocafe-360-scheduled-orders branch from 298ff12 to 561b07b Compare October 29, 2026 20:43
@khaira777 khaira777 changed the title feat(orders): scheduled orders with kitchen release semantics feat(orders): scheduled orders and kitchen release Oct 29, 2026
: 1. **Playwright E2E (Shard 1/4) (`frontend/e2e/database-export-import.spec.ts:198:7`)**: - **Invariant**: Every test and JSON import fixture that targets the live database schema version without a Master PIN must match the latest schema version (`123` from migration `add_scheduled_orders` in `main/db.ts`) so that `DatabaseSettingsTab` and `POST /api/db/import` recognize it as a matching-version import. - **Cause**: Migration `123` added scheduled orders and incremented `user_version` to `123`. `frontend/e2e/database-export-import.spec.ts` still specified `schema_version: '122'` in `contaminatedPayload`, causing `DatabaseSettingsTab.tsx` to detect a version mismatch (`122 !== 123`) and gate the import behind an owner Master PIN instead of proceeding with the merge import, timing out waiting for `Database imported successfully`. - **Fix**: Updated `schema_version` from `'122'` to `'123'` in `frontend/e2e/database-export-import.spec.ts`. 2. **Playwright E2E (Shard 3/4) (`frontend/e2e/scheduled-orders.spec.ts:23:5`)**: - **Invariant**: Visual evidence screenshots in E2E tests must resolve the target directory cross-platform (supporting `process.env.EVIDENCE_DIR`, local evidence fallback, and temp directory fallback), ensure the target directory exists before writing, and capture screenshots safely without throwing `ENOENT` on environments where specific local host directories do not exist. - **Cause**: `frontend/e2e/scheduled-orders.spec.ts` hardcoded `evidenceDir = '/Users/gurkiratkhaira/.no-mistakes/evidence/01M64J866EWP5Q41XVW3W8J3Q9'`. On Linux CI runners (`ubuntu-24.04`), that path does not exist, causing `page.screenshot()` to throw `ENOENT: no such file or directory`. - **Fix**: Added dynamic `EVIDENCE_DIR` resolution with a safe `captureScreenshot(page, filename)` helper that ensures directory existence and catches filesystem errors without aborting test execution, and converted all 5 screenshot call sites in `frontend/e2e/scheduled-orders.spec.ts`. 3. **End-to-End Playwright Tests & Required Checks Gate**: - Downstream aggregator jobs that failed solely due to Shards 1/4 and 3/4 failing. **Verification run and passed**: - `git diff --check` - `npm run lint` (0 errors) - `npm run docs:check` - `npm run i18n:check` - `npm run build` - `npm run build:frontend` - `npm run test:scheduled-orders` (315/315 passed) - `cd frontend && CI=true npx playwright test --config=playwright.config.ts --project=chromium e2e/database-export-import.spec.ts` (2/2 passed) - `cd frontend && CI=true npx playwright test --config=playwright.config.ts --project=chromium e2e/scheduled-orders.spec.ts` (1/1 passed) - `node scripts/ci/check-changed-format.cjs --base b27799e` - `npm run test:script-coverage`
- Preserve release_status = 'blocked' and blocked reason on reschedule
- Isolate unexpected release errors during sweep to prevent stall
- Add cursor pagination and load more to GET /orders/scheduled
- Use shared payable bill predicate supporting partially_paid
- Filter heartbeat active-orders query to release_status = 'released'
@khaira777 khaira777 changed the title feat(orders): scheduled orders and kitchen release feat(orders): scheduled takeaway and delivery orders with kitchen release Oct 29, 2026
@khaira777 khaira777 changed the title feat(orders): scheduled takeaway and delivery orders with kitchen release feat(orders): scheduled orders and kitchen release Oct 29, 2026
@khaira777
khaira777 merged commit 988e545 into main Oct 29, 2026
23 checks passed
@khaira777
khaira777 deleted the fm/flocafe-360-scheduled-orders branch October 29, 2026 22:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature: Scheduled orders with release semantics

1 participant