Skip to content

fix(tables): preserve reserved destinations - #1143

Merged
khaira777 merged 5 commits into
mainfrom
codex/reserved-table-moves
Oct 15, 2026
Merged

khaira777 merged 5 commits into
mainfrom
codex/reserved-table-moves

Conversation

@khaira777

@khaira777 khaira777 commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Intent

PR 6 - Preserve reserved table destinations (Fixes #1061)
Branch: codex/reserved-table-moves
Title: fix(tables): preserve reserved destinations

Requirements:

  • Check reserved status in the authoritative move transaction.
  • Return 409 before mutating the order or either table.
  • Preserve reservation association, source status and target status.
  • Keep existing inactive/held/occupied checks.
  • Do not introduce a reservation override option.

Acceptance: reserved moves fail without side effects; valid available-table moves succeed; a destination changed after the initial read is checked again.

What Changed

  • Re-read the destination table inside the POST /api/tables/:id/move-order transaction and reject moves with 409 Target table is reserved (alongside active, held, and occupied checks) before mutating the order or either table.
  • Surface server-provided reserved and held 409 error messages in MoveTableModal instead of falling back to the generic occupied-table message.
  • Document POST /api/tables/:id/move-order response and error status codes in docs/reference/api.md, and add backend and E2E tests covering reserved destination rejection and post-read status changes.

Risk Assessment

✅ Low: The change cleanly enforces the reserved destination table check with a 409 response inside the authoritative move transaction before any order or table mutations, surfaces the conflict message in MoveTableModal, and adds thorough integration and E2E coverage without side effects.

Testing

Ran the backend integration and UI unit suites (npm run test:tables-string-ids and npm run test:held-orders), built the backend and static frontend bundle, and drove the live product in headless Chromium via Playwright (frontend/e2e/table-move-live.spec.ts and a targeted live capture) on isolated standalone server ports, gathering 10 visual screenshots and JSON API/database verification artifacts confirming all reserved, stale-read, mid-transaction, no-override, inactive/held/occupied guard, and available-table move scenarios pass.

  • Live validation: ✅ go - 5 of 5 scenarios driven live against the product
Scenario Result Live Evidence
Moving an active dine-in order onto a reserved destination table returns HTTP 409 without mutating the order, source table status, target table status, or target table reservation customer association ✅ pass live ~/.no-mistakes/evidence/01M4YJ4Q7A41SYZBNS5JHF6296/reserved-table-moves-live-verification.json
A destination table that changes to reserved after the initial read (including after opening MoveTableModal or mid-transaction) is re-checked in the authoritative move transaction, rejected with HTTP… ✅ pass live ~/.no-mistakes/evidence/01M4YJ4Q7A41SYZBNS5JHF6296/09-reserved-table-move-rejected.png
Attempting to force or override a move onto a reserved table (passing override: true / force: true) is rejected with HTTP 409 with no reservation override option ✅ pass live ~/.no-mistakes/evidence/01M4YJ4Q7A41SYZBNS5JHF6296/reserved-table-moves-live-verification.json
Existing destination guards for inactive (HTTP 400), held (HTTP 409), and occupied (HTTP 409) tables remain enforced in both the API and MoveTableModal UI ✅ pass live ~/.no-mistakes/evidence/01M4YJ4Q7A41SYZBNS5JHF6296/08-occupied-table-disabled.png
Moving an active order to a valid available destination table (including after releasing a reservation) succeeds with HTTP 200, frees the source table, and marks the destination table occupied with th… ✅ pass live ~/.no-mistakes/evidence/01M4YJ4Q7A41SYZBNS5JHF6296/10-reserved-table-released-move-completed.png

Reserved destination table move rejected with 409 and error toast in MoveTableModal
Table move succeeds after releasing destination table reservation
Occupied and held destination tables disabled and inactive tables excluded in MoveTableModal
Floorplan table move completed
Tables list move completed
POS checkout modal table move completed

Evidence: Live API and database state verification for reserved, held, occupied, inactive, and available table moves

{ "guards": { "inactiveMove": { "status": 400, "data": { "error": "Target table is not active" } }, "heldMove": { "status": 409, "data": { "error": "Target table has a held order" } }, "occupiedMove": { "status": 409, "data": { "error": "Target table already has an active order" } } }, "reservedMoveRejection": { "reserveTableStatus": 200, "directReservedMove": { "status": 409, "data": { "error": "Target table is reserved" } }, "overrideReservedMove": { "status": 409, "data": { "error": "Target table is reserved" } }, "orderAfterReject": { "id": 1, "table_id": "tbl-41dc0d5f", "status": "pending" }, "sourceTableAfterReject": { "id": "tbl-41dc0d5f", "status": "occupied", "activeOrderId": 1 }, "targetTableAfterReject": { "id": "tbl-9817cac2", "status": "reserved", "activeOrder": null, "reservation_customer_id": "e2e-customer", "reservation_customer_name": "E2E Guest", "reservation_customer_phone": "+66800000001" } }, "availableMoveAfterRelease": { "orderAfterSuccess": { "id": 1, "table_id": "tbl-9817cac2" }, "sourceTableAfterSuccess": { "id": "tbl-41dc0d5f", "status": "available", "activeOrder": null }, "targetTableAfterSuccess": { "id": "tbl-9817cac2", "status": "occupied", "activeOrderId": 1 } } }

{
  "guards": {
    "inactiveMove": {
      "status": 400,
      "data": {
        "error": "Target table is not active"
      }
    },
    "heldMove": {
      "status": 409,
      "data": {
        "error": "Target table has a held order"
      }
    },
    "occupiedMove": {
      "status": 409,
      "data": {
        "error": "Target table already has an active order"
      }
    }
  },
  "reservedMoveRejection": {
    "reserveTableStatus": 200,
    "directReservedMove": {
      "status": 409,
      "data": {
        "error": "Target table is reserved"
      }
    },
    "overrideReservedMove": {
      "status": 409,
      "data": {
        "error": "Target table is reserved"
      }
    },
    "orderAfterReject": {
      "id": 1,
      "table_id": "tbl-bfad2414",
      "status": "pending"
    },
    "sourceTableAfterReject": {
      "id": "tbl-bfad2414",
      "status": "occupied",
      "activeOrderId": 1
    },
    "targetTableAfterReject": {
      "id": "tbl-c622249c",
      "status": "reserved",
      "activeOrder": null,
      "reservation_customer_id": "e2e-customer",
      "reservation_customer_name": "E2E Guest",
      "reservation_customer_phone": "+66800000001"
    }
  },
  "availableMoveAfterRelease": {
    "orderAfterSuccess": {
      "id": 1,
      "table_id": "tbl-c622249c"
    },
    "sourceTableAfterSuccess": {
      "id": "tbl-bfad2414",
      "status": "available",
      "activeOrder": null
    },
    "targetTableAfterSuccess": {
      "id": "tbl-c622249c",
      "status": "occupied",
      "activeOrderId": 1
    }
  }
}

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 - 5 of 5 scenarios driven live against the product
Scenario Result Live Evidence
Moving an active dine-in order onto a reserved destination table returns HTTP 409 without mutating the order, source table status, target table status, or target table reservation customer association ✅ pass live ~/.no-mistakes/evidence/01M4YJ4Q7A41SYZBNS5JHF6296/reserved-table-moves-live-verification.json
A destination table that changes to reserved after the initial read (including after opening MoveTableModal or mid-transaction) is re-checked in the authoritative move transaction, rejected with HTTP… ✅ pass live ~/.no-mistakes/evidence/01M4YJ4Q7A41SYZBNS5JHF6296/09-reserved-table-move-rejected.png
Attempting to force or override a move onto a reserved table (passing override: true / force: true) is rejected with HTTP 409 with no reservation override option ✅ pass live ~/.no-mistakes/evidence/01M4YJ4Q7A41SYZBNS5JHF6296/reserved-table-moves-live-verification.json
Existing destination guards for inactive (HTTP 400), held (HTTP 409), and occupied (HTTP 409) tables remain enforced in both the API and MoveTableModal UI ✅ pass live ~/.no-mistakes/evidence/01M4YJ4Q7A41SYZBNS5JHF6296/08-occupied-table-disabled.png
Moving an active order to a valid available destination table (including after releasing a reservation) succeeds with HTTP 200, frees the source table, and marks the destination table occupied with th… ✅ pass live ~/.no-mistakes/evidence/01M4YJ4Q7A41SYZBNS5JHF6296/10-reserved-table-released-move-completed.png
  • npm run test:tables-string-ids
  • npm run test:held-orders
  • E2E_BASE_URL=http://127.0.0.1:4301 E2E_KDS_BASE_URL=http://127.0.0.1:4302 E2E_SERVER_APP_BASE_URL=http://127.0.0.1:4303 EVIDENCE_DIR=~/.no-mistakes/evidence/01M4YJ4Q7A41SYZBNS5JHF6296 npx --prefix frontend playwright test --config=frontend/playwright.config.ts --project=chromium frontend/e2e/table-move-live.spec.ts
  • Live Playwright & API verification against standalone server on ports 4401-4403 capturing 09-reserved-table-move-rejected.png, 10-reserved-table-released-move-completed.png, and reserved-table-moves-live-verification.json
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

@coderabbitai

coderabbitai Bot commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

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
  • Configuration used: Repository: FreeOpenSourcePOS/FloCafe/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 5e9c604b-db51-4377-afa0-879f1a520ce4

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

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: FreeOpenSourcePOS/FloCafe/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 401c026d-1351-45c6-9401-cb7abeac43ad
📥 Commits

Reviewing files that changed from the base of the PR and between 309db4a and fc67076.

📒 Files selected for processing: 3
  • frontend/e2e/table-move-live.spec.ts
  • main/routes/tables.ts
  • tests/tables-string-ids.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 2 included reviews per hour; 0 remain after this review.

Walkthrough

The move-order route now reloads and checks the target table during the transaction. It rejects held or reserved destinations. Integration and end-to-end tests verify conflict responses, preserved reservation and source-table state, and a successful move after the reservation is released.

Changes

Reserved table move

Layer / File(s) Summary
Transaction checks and API coverage
main/routes/tables.ts, tests/tables-string-ids.test.ts
The route reloads the target table and checks that it exists and is active. It returns a conflict when the target is held or reserved. Integration tests cover override flags, reservation changes, unchanged state after rejection, and a successful move after release.
End-to-end rejection and retry
frontend/e2e/table-move-live.spec.ts
The test verifies that an API request and a move submitted through the open modal return HTTP 409 for a reserved destination. It then releases the reservation, retries the move, and verifies the resulting table states.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix · Severity of issue fixed: Medium

Merge Risk: ⚪ Minimal · up to fc670

The reserved-table move guard has no established merge-blocking issue; it is ready for normal merge checks.

Pre-merge checks: Passed 2 · Failed 3

Failed Failed checks: 3 warnings

Check name Status Explanation Resolution
Linked Issues check Warning Issue [#1061] requires reserved-table moves to be rejected with HTTP 409 unless an explicit override flag is provided. The reported route change rejects reserved targets even when override or force fl… Implement and test the explicit override flag required by issue [#1061], or update the linked issue requirement before merging. The override path must define authorization and preserve the existing non-override 409 behavior.
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 3 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check Warning The description provides detailed intent, implementation summary, scope-related behavior, testing commands, results, and evidence. However, it does not follow the repository template and omits or does… Update the description to include every template section. State the related issue, intended scope and exclusions, database/migration/user-visible/offline impact, cross-cutting surface statuses, documentation status, and completed contributo…
Passed Passed checks: 2 passed
Check name Status Explanation
Out of Scope Changes check Passed The reported changes are limited to the move-order route and backend and browser tests for reserved, stale-read, existing guard, and available-table move behavior. These changes support issue [#1061].…
Title check Passed The title clearly and concisely describes the main change: preserving reserved table destinations during order moves.
Full details: Linked Issues check

Explanation

Issue [#1061] requires reserved-table moves to be rejected with HTTP 409 unless an explicit override flag is provided. The reported route change rejects reserved targets even when override or force flags are supplied, and the added tests assert that behavior. The reported implementation satisfies the 409 protection and preserves state, but it does not satisfy the issue's explicit override exception. The route re-check and retained inactive, held, and occupied guards support the other stated requirements.

Full details: Description check

Explanation

The description provides detailed intent, implementation summary, scope-related behavior, testing commands, results, and evidence. However, it does not follow the repository template and omits or does not explicitly complete the Related work, Scope, Compatibility & data safety, Cross-cutting surfaces, Developer documentation, and Contributor checklist sections.

Resolution

Update the description to include every template section. State the related issue, intended scope and exclusions, database/migration/user-visible/offline impact, cross-cutting surface statuses, documentation status, and completed contributor checklist items. Keep the existing testing commands and results under the required Verification section.

✨ Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • 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.

@khaira777

Copy link
Copy Markdown
Contributor Author

@greptileai review

@greptile-apps

greptile-apps Bot commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] The PR appears safe to merge; no new actionable issues were found.

Summary

The PR rejects moves onto reserved destinations before changing the order or either table.

  • Reserved destinations block order moves without losing their reservation.
  • Move-table errors show the reason a destination is reserved or held.
  • The E2E server keeps the same setup and shutdown behavior.

Diagram

sequenceDiagram
  participant Staff
  participant Modal as MoveTableModal
  participant API as Move API
  participant DB as SQLite
  Staff->>Modal: Confirm destination
  Modal->>API: POST move-order
  API->>DB: Read order and destination inside transaction
  API->>DB: Re-read destination
  alt Destination is reserved
    API-->>Modal: 409 Target table is reserved
    Modal-->>Staff: Show conflict and keep modal open
  else Destination passes all checks
    API->>DB: Move order and update both tables
    API-->>Modal: Updated order and tables
    Modal-->>Staff: Show success and close
  end
Loading

Reviews (5) · Last reviewed commit: "Merge branch 'main' into codex/reserved-..." · Reviewed by Greptile

Comment thread main/routes/tables.ts
Comment thread frontend/e2e/table-move-live.spec.ts Outdated
@khaira777

Copy link
Copy Markdown
Contributor Author

@greptileai review

@khaira777
khaira777 force-pushed the codex/reserved-table-moves branch from fc67076 to 649d20e Compare October 15, 2026 01:45
@khaira777

Copy link
Copy Markdown
Contributor Author

@greptileai review

@khaira777

Copy link
Copy Markdown
Contributor Author

@greptileai review

@khaira777

Copy link
Copy Markdown
Contributor Author

@greptileai review

@khaira777
khaira777 merged commit 860a715 into main Oct 15, 2026
24 checks passed
@khaira777
khaira777 deleted the codex/reserved-table-moves branch October 15, 2026 02:10
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.

fix(tables): reject order moves onto reserved tables to prevent overwriting reservations

1 participant