Skip to content

Table Sections

Overview

Table sections organize a location's tables into named groups (e.g. "Dining Room", "Bar", "Terrace") used for Table QR ordering and in-house management.

Key Purpose: Group a location's tables into named sections, each generating downloadable QR codes for table-based QR ordering.

Purpose

This page lets you define the areas of a venue as named sections and, optionally, the tables within each section. Each section can generate QR codes (an image ZIP and an ordering-card PDF) for table-based QR ordering.

Key Concepts

  • Table Section: A named group belonging to a single location, stored in the tenant settings collection (model TableSection) with soft-delete support. A section holds a name, a table_name_type, and a list of table names — not individual table records.
  • Table Name Type: An enum (TableNameType) with two values: Automatic Tables Names and Custom Tables Name. Automatic generates names from a label plus a count; Custom takes an explicit list of names.
  • Tables as names only: A section's tables are stored as a flat array of name strings (table_names). There are no per-table seats, table_number, qr_code, or active/inactive fields.
  • Include Tables: A per-section toggle (include_tables). When off, the section has no tables (the section can still exist as an area). When on, tables are defined per the naming type.
  • QR Code Generation: QR files are generated asynchronously via the GenerateQrCodesForSection job and stored in Cloudflare R2; the section exposes read-only paths qr_code_zip_path (image ZIP) and qr_code_pdf_path (ordering-card PDF).
  • MplusKassa Tables section: The auto-created section named exactly MplusKassa Tables is protected — it is skipped from deletion and from UI updates when saving in-house settings.
  • Lightspeed K-Series sections are flagged read-only: TableSection::getUneditableFields() returns ['name', 'tableNameType', 'tableLabel', 'tableNumbers', 'tableNames', 'details'] for any section carrying external_ids.lightspeed and for any manual section at a Lightspeed K-Series-mapped location (external_data.lightspeed_locked). This is a wider lock than the MplusKassa one: at a K-Series location it covers sections the merchant created themselves, not just imported ones. Sections come back with those uneditable_fields so the UI can disable the inputs.

Actions

Create a Table Section

In In-House Settings, open the section form ("Add Section"). Enter a Section Name (required, must be unique within the location). Optionally toggle Include tables on, choose a Naming type (Automatic or Custom), and configure the tables.

Edit a Table Section

Open an existing section ("Edit Section") and change its name, naming type, or tables. When table names change on save (or QR files are missing), a GenerateQrCodesForSection job is dispatched to regenerate the QR files.

Delete a Table Section

Sections can be deleted from the section form ("Delete Section") or, via the in-house settings save, by listing the section ID in deleted_sections. Deletion is blocked when the section is in use by QR Ordering. The MplusKassa Tables section is never deleted through the in-house settings flow.

Download QR Codes

QR codes are downloaded from the QR Ordering screen, not from the section form. See QR Ordering for the download flow and formats.

Location

  • Backoffice Route: /in-house/settings (In-House Settings -> Sections & Tables) — this is where sections are created, edited and deleted (InHouseSettingsForm.vue -> SectionsAndTables.vue -> SectionFormDialog.vue, with deletions pushed into deleted_sections). /in-house/qr-ordering only selects already-existing sections (SectionsAndTablesSelected.vue); it cannot create or edit them.
  • Section Form Component: src/views/in-house/components/settings/SectionFormDialog.vue
  • Standalone Backend: controller app/Http/Controllers/Api/BackOffice/TableSectionController.php, request app/Http/Requests/BackOffice/TableSection/StoreAndUpdateTableSectionRequest.php
  • In-House Settings Flow: request app/Http/Requests/BackOffice/InHouseSettings/StoreInHouseSettingsRequest.php, orchestrator app/Services/Orchestrators/BackOffice/InHouseSettingsOrchestrator.php

Fields

Section Name

PropertyValue
Field IDname
LabelSection Name
TypeText
RequiredYes
Validationunique within the location; required. The 25-character cap is enforced only by the standalone /back-office/table-sections API (max:25) — the in-house-settings save path used by this form has no max rule, and the field shows an "x/25" counter without blocking

Description: Name of the area (placeholder "e.g. Dining Room, Bar"). Uniqueness within the location is enforced server-side (UniqueInConnectionWithModel in the in-house settings flow; max:25 in the standalone request).


Include Tables

PropertyValue
Field IDinclude_tables
LabelInclude tables
TypeToggle (boolean)
Defaultfalse (section form)

Description: When off, the section has no tables and table fields are cleared on save. When on, tables are configured per the naming type below.


Table Name Type

PropertyValue
Field IDtable_name_type (frontend form field: table_naming_type)
LabelNaming
TypeSelect (enum TableNameType)
OptionsAutomatic Tables Names, Custom Tables Name
RequiredYes

Description: How the section's tables are named. The UI radio labels read "Automatic Table Names" and "Custom Table Names"; the stored/enum values are Automatic Tables Names and Custom Tables Name.


Table Label (Automatic only)

PropertyValue
Field IDtable_label
LabelLabel
TypeText
RequiredNo
Validationmax 10 characters (Automatic mode)

Description: Optional prefix used to build automatic names (placeholder "e.g. Table"). Names become "{section} {label} {n}", or "{section} {n}" when blank.


Number of Tables (Automatic only)

PropertyValue
Field IDtable_numbers
LabelNumber of Tables
TypeInteger
RequiredYes in Automatic mode
Validationmin 1 (Automatic mode); generally nullable|integer|min:0

Description: How many tables to auto-generate. In Custom mode this is set to the count of provided names.


Table Names (Custom only)

PropertyValue
Field IDtable_names (frontend form field: tables, an array of { name })
LabelTables
TypeArray of strings
RequiredYes in Custom mode
Validationeach name required, max 20 characters (Custom mode)

Description: The explicit list of table names. There is no per-table seats, table_number, qr_code, or active field — tables are plain name strings.


Generated QR Paths (read-only)

PropertyValue
Field IDsqr_code_zip_path, qr_code_pdf_path
TypeString (R2 path)

Description: Paths to the generated downloadable QR files for the section, populated by the background generation job.


Business Logic

Section Organization

Location
├── Section: Dining Room  (Automatic, label "Table", 4 tables)
│   ├── Dining Room Table 1
│   ├── Dining Room Table 2
│   ├── Dining Room Table 3
│   └── Dining Room Table 4

├── Section: Terrace  (Automatic, no label, 3 tables)
│   ├── Terrace 1
│   ├── Terrace 2
│   └── Terrace 3

└── Section: Bar  (Custom)
    ├── Bar 1
    ├── Bar 2
    └── Window Seat

Save & QR Regeneration Flow

Save in-house settings (sections + deleted_sections)


Skip the "MplusKassa Tables" section (delete + update)


For each deleted_section id (non-MplusKassa):
├── In use by QR Ordering?  → abort 400
└── otherwise              → delete section


For each section:
├── include_tables off / no tables → clear table fields
├── Automatic → build table_names from label + count
└── Custom    → table_numbers = count(table_names)


If table_names changed or QR files missing


Dispatch GenerateQrCodesForSection (ZIP + PDF → R2)

Business Rules

  • Section names are required and must be unique within the location. The 25-character limit is not enforced on the path the back office actually uses: StoreInHouseSettingsRequest validates sections.{i}.name as only required|string plus a uniqueness and a distinct rule, with no max. The counter in the UI is cosmetic. Only the standalone /back-office/table-sections API applies max:25.
  • A section needs the Include tables toggle on to define tables. With it off (or with zero tables), the table fields are cleared on save.
  • For Automatic naming, table_numbers (min 1) is required and table_label is optional (max 10 chars). For Custom naming, table_names is required and each name must be a non-empty string of at most 20 characters.
  • Automatic names are generated as "{section} {label} {n}" (or "{section} {n}" when the label is blank).
  • A section in use by QR Ordering cannot be deleted via the in-house settings flow (returns a 400 prompting you to remove it from QR Ordering first).
  • The section named exactly MplusKassa Tables is protected: it is skipped from both deletion and UI updates in the in-house settings flow.
  • QR files (image ZIP + ordering-card PDF) are regenerated by the GenerateQrCodesForSection job when a section's table names change or its R2 paths are missing.

FAQs

  • "Do tables have seat counts or table numbers as separate fields?" No. A section's tables are stored only as a list of name strings (table_names). There are no seats, table_number, or per-table qr_code fields.
  • "How are table names generated in Automatic mode?" As "{section} {label} {n}" (e.g. "Dining Room Table 1"). If no label is set, names are "{section} {n}" (e.g. "Dining Room 1").
  • "What's the difference between Automatic and Custom naming?" Automatic generates a numbered set from a label and a count; Custom lets you type each table name (each up to 20 characters).
  • "What is the 'Include tables' toggle for?" It controls whether the section has tables at all. A section can exist as an area with no tables when the toggle is off.
  • "Why can't I delete a section?" It is in use by QR Ordering (remove it there first), or it is the protected MplusKassa Tables section, which is managed by the MplusKassa integration and skipped from UI deletion.
  • "What happens to QR codes when I change table names?" A background job (GenerateQrCodesForSection) regenerates the section's image ZIP and ordering-card PDF; this is asynchronous, so allow a short time before downloading.

Troubleshooting

  • Section not saving → Verify the name is unique within the location (the 25-character counter does not block saving through In-House Settings). In Custom mode each table name must be filled in and 20 characters or fewer; in Automatic mode the number of tables must be at least 1.
  • Cannot delete a section → The section is in use by QR Ordering (remove it there first), or it is the protected MplusKassa Tables section.
  • QR codes not generating → Generation runs as a background job (GenerateQrCodesForSection). Ensure the queue worker is running and allow a few minutes after the table names change. (QR file generation is verified server-side; storefront QR rendering is not verified here.)
  • Table names not updating on QR codes → QR files regenerate only when the section's table names change or its R2 paths are missing. Confirm the save succeeded and check for background-job failures.

Relations

Depends On

  • Locations: Sections belong to one location
  • QR Ordering: Sections are selected for a location's QR ordering

Affects

  • QR Ordering: Table QR codes and table identification
  • Transactions: Orders bind to a table session (see QR Ordering)

Examples

Section Resource (API response)

json
{
  "id": "section-1",
  "location_id": "loc-123",
  "name": "Dining Room",
  "details": {},
  "table_name_type": "Automatic Tables Names",
  "table_label": "Table",
  "table_numbers": 4,
  "table_names": [
    "Dining Room Table 1",
    "Dining Room Table 2",
    "Dining Room Table 3",
    "Dining Room Table 4"
  ],
  "qr_code_zip_path": "...",
  "qr_code_pdf_path": "..."
}

Automatic Section (request payload)

json
{
  "name": "Terrace",
  "table_name_type": "Automatic Tables Names",
  "table_label": "T",
  "table_numbers": 3,
  "location_id": "loc-123"
}

This auto-generates table names "Terrace T 1", "Terrace T 2", "Terrace T 3".

Custom Section (request payload)

json
{
  "name": "Bar",
  "table_name_type": "Custom Tables Name",
  "table_names": ["Bar 1", "Bar 2", "Window Seat"],
  "location_id": "loc-123"
}