Skip to content

In-House Settings ​

Overview ​

In-House Settings configure dine-in operations for a location: table sections, tip collection, checkout notes, and the menus shown for in-house ordering.

Key Purpose: Configure dine-in / in-house ordering settings for a location.

The page requires a POS to be connected. If no POS channel is connected for the selected location, the form redirects to the home screen (InHouseSettingsForm.vue mounted()).

QR code generation, ordering hours, customer name/email requirements, and the customer-facing table-ordering flow are configured on a separate page — see QR Table Ordering. This doc covers only the in-house dining settings cluster.

Purpose ​

This page lets you configure dine-in ordering for a location: organize tables into sections, optionally collect tips, optionally allow checkout notes, and choose the default and extra menus used for in-house ordering.

Key Concepts ​

  • In-House Setting: Configuration stored per location as in_house_setting on the Location model. The persisted object stores only collect_tips, allow_notes, allow_order_notes, default_menu_id, and extra_menu_ids (InHouseSettingsService::update). Table sections are stored separately as TableSection models, not inside in_house_setting.
  • Table Sections: Named groups of tables (e.g. "Dining Room", "Bar") with a table_name_type of either Automatic or Custom. Sections are created/updated/deleted as TableSection records and are shared with QR Ordering (see QR Table Ordering).
  • Tip Collection: Optional gratuity collection with three percentage options (default [10, 15, 20]) and a choice of calculating tips before or after taxes (default: After taxes).
  • Checkout Notes: Optional free-text note field; when enabled you set the placeholder shown to customers. The placeholder is validated as a string by the backend; the back-office editor caps it at 150 characters.
  • Menus: A required default menu (default_menu_id) and optional extra menus (extra_menu_ids) with scheduled availability. Extra menus cannot duplicate the default or each other, and their schedules must not overlap (InHouseSettingsService::update).

Actions ​

Manage Table Sections ​

Add, edit, or delete table sections. Each section has a name and a Naming type (Automatic or Custom — see Fields). Deletions are queued in deleted_sections and applied on save; sections can't be deleted while in use by QR Ordering, and the MplusKassa Tables section is skipped from UI updates and deletion.

Enable Tip Collection ​

Toggle Collect Tips, set three tip percentage options, and choose whether tips are calculated before or after taxes. A POS warning is shown: tips must be enabled in the POS before they can be collected.

Enable Checkout Notes ​

Toggle Allow Notes and set the placeholder text shown in the "add note" field.

Assign Menus ​

Set a default menu (must be eligible for in-house visibility) and optionally add extra menus with scheduled availability. Extra menus cannot duplicate the default or each other, and schedules cannot overlap.

Location ​

  • Backoffice Route: /in-house/settings (file-based router; src/pages/in-house/settings.vue, registered in typed-router.d.ts as in-house-settings)
  • Backoffice View: src/views/in-house/InHouseSettingsForm.vue
  • Form Components: src/views/in-house/components/forms/SectionsAndTables.vue, CollectTips.vue, CheckoutNotes.vue, and src/components/DefaultMenusSection.vue
  • Section Editor: src/views/in-house/components/settings/SectionFormDialog.vue
  • Store Module: src/store/modules/inHouse.ts (saveInHouseSettingsForm → PUT /back-office/in-house-settings/{locationId})
  • Backend Controller: app/Http/Controllers/Api/BackOffice/InHouseSettingsController.php
  • Backend Request: app/Http/Requests/BackOffice/InHouseSettings/StoreInHouseSettingsRequest.php
  • Backend Orchestrator/Service: app/Services/Orchestrators/BackOffice/InHouseSettingsOrchestrator.php, app/Services/BackOffice/InHouseSettingsService.php
  • API: GET and PUT /back-office/in-house-settings/{locationId} (routes/api/backoffice/in-house-settings.php); GET requires permission view-sales-channel, PUT requires edit-in-house-channel.

Fields ​

These are the fields validated by StoreInHouseSettingsRequest (the request body of the in-house settings PUT). The back-office form sends an additional order_capacity block, but the backend request does not validate it and InHouseSettingsService::update does not persist it for in-house — order capacity belongs to Online Ordering, not the in-house setting.

Collect Tips — Enabled ​

PropertyValue
Field IDcollect_tips.enabled
LabelCollect Tips
TypeBoolean (toggle)
Defaultfalse

Description: Master switch for tip collection. When off, the percentage and calculation fields are nullable.


Collect Tips — Options ​

PropertyValue
Field IDcollect_tips.options (array of numbers)
LabelTip Percentage
TypeArray of numeric values
RulesRequired when tips enabled; each value numeric, min:0, max:100
Default[10, 15, 20]

Description: The tip percentage options offered at checkout. The back-office form exposes exactly three percentage inputs (tip_percentage_1/2/3), each requiring a value of at least 1.


Collect Tips — Calculate Tips ​

PropertyValue
Field IDcollect_tips.calculate_tips
LabelCalculate Tips
TypeEnum (CalculateTipsOptions)
OptionsAfter taxes, Before taxes
DefaultAfter taxes

Description: Whether the tip is calculated on the amount after or before taxes. Enum values are the literal strings After taxes / Before taxes (lowercase "taxes").


Allow Notes — Enabled ​

PropertyValue
Field IDallow_notes.enabled
LabelAllow Notes
TypeBoolean (toggle)
Defaultfalse

Description: Whether customers can add a free-text note to items at checkout.


Allow Notes — Placeholder ​

PropertyValue
Field IDallow_notes.placeholder
LabelPlaceholder text
TypeString
RulesRequired when notes enabled; backend rule is string (no length limit); back-office editor caps at 150 characters
DefaultE.g. "For Oliver" or "I'm allergic to mushrooms

Description: The placeholder shown in the "add note" field. The default string is defined in Constants::getDefaultInHouseSettings() (note: the stored default has an unbalanced closing quote in code).


Allow Order Notes — Enabled ​

PropertyValue
Field IDallow_order_notes.enabled
LabelAllow Order Notes
TypeBoolean (toggle)
Defaultfalse

Description: Whether customers can add one free-text note covering the whole order, as opposed to allow_notes, which is the per-item note. The two are independent toggles on the same Checkout Notes card.

Backward compatibility: order notes were split out of allow_notes after launch. StoreInHouseSettingsRequest merges allow_notes into allow_order_notes as a fallback, so a tenant saved before the split — which sends only allow_notes — keeps the old combined behaviour until the merchant configures the split explicitly (StoreInHouseSettingsRequest.php:36-45).


Allow Order Notes — Placeholder ​

PropertyValue
Field IDallow_order_notes.placeholder
LabelPlaceholder text
TypeString
RulesRequired when order notes enabled; backend rule is string (no length limit); back-office editor caps at 150 characters
DefaultAdd a note for your whole order

Description: The placeholder shown in the order-level note field (Constants::getDefaultInHouseSettings(), Constants.php:252-254).


Default Menu ​

PropertyValue
Field IDdefault_menu_id
LabelDefault Menu
TypeString (menu id)
Rules`required
Defaultnull (until set)

Description: The menu shown for in-house ordering. Must be an eligible menu (InHouseSettingsService::update calls isMenuEligible).


Extra Menus ​

PropertyValue
Field IDextra_menu_ids (array of strings)
LabelExtra Menus
TypeArray of menu ids
Rules`nullable
Default[]

Description: Additional menus with scheduled availability. Each must be eligible, cannot equal the default menu, cannot be duplicated, and cannot have an overlapping schedule.


Sections (table sections) ​

PropertyValue
Field IDsections (array)
TypeArray of section objects
Rules`nullable

Description: Table sections to create or update on save. See Table Sections below for per-section fields. Deletions are sent separately via deleted_sections (array of section id strings).


Table Sections ​

A location's tables are organized into sections (e.g. "Dining Room", "Bar"). Each section is persisted as a TableSection model and is shared with QR Ordering. Per-section fields validated by the request:

Section Name ​

PropertyValue
Field IDsections.*.name
LabelSection Name
TypeString
Rulesrequired, string, unique per location (UniqueInConnectionWithModel), and distinct across the submitted list

Description: Section names must be unique within the location. The back-office editor shows a {count}/25 character hint, but the 25-character cap is a UI display hint only — it is not enforced by a validation rule on the field.


Naming (per section) ​

PropertyValue
Field IDsections.*.table_name_type
LabelNaming
TypeEnum (TableNameType)
OptionsAutomatic Tables Names, Custom Tables Name

Description: How a section's tables are named. Note the literal enum strings: Automatic Tables Names and Custom Tables Name (these exact strings are used by both backend and front-end).

Options:

  • Automatic (Automatic Tables Names): set a table_label (optional, max 10 chars) and table_numbers (required integer, min:1); the backend generates names like {section} {label} {n} (or {section} {n} when no label).
  • Custom (Custom Tables Name): enter each table name in table_names (required array; each string, max:20); table_numbers is set to the count of names.

Include Tables ​

PropertyValue
Field IDsections.*.include_tables
TypeBoolean (nullable)
Defaultfalse (section editor)

Description: When include_tables is false (or table_numbers is 0 with no custom names), the section is saved with no tables (table_names = [], table_numbers = 0, table_label = '') and the Automatic/Custom table rules are not enforced.


Order Acceptance & POS Forwarding ​

In-house orders placed via Kiosk, Table QR, or staff are processed automatically. There is no toggle to hold orders for manual acceptance, and no in-house setting to stop forwarding orders to a connected POS — none of these are fields on StoreInHouseSettingsRequest.

The in-house setting does not store enabled, service_mode, table_service, counter_service, show_order_number, order_number_format, starting_number, prep_time, auto_accept, send_to_kds, print_kitchen_ticket, or print_receipt — those are not real fields of this feature. It manages table sections, tip collection, checkout notes, and the default/extra menus.

To manage incoming order volume, use the channel-level controls and Order Capacity in Online Ordering / QR Ordering settings instead (not configured here).

To stop taking table QR orders temporarily, use the Snooze dropdown on the Table QR Code Ordering page (/in-house/qr-ordering) — 20 / 40 / 60 minutes, the rest of the day, or "Don't accept orders". It writes qr_ordering_setting.snoozed_until on the location and is independent of the Online Ordering snooze. There is no snooze control on the In-House settings page itself. (Verified: POST /back-office/qr-ordering/{locationId}/snooze in upvendo-backend routes/api/backoffice/qr-ordering.php line 11, QrOrderingService::snooze; UI in upvendo-backoffice src/views/in-house/components/qr-ordering/QROrderingForm.vue lines 76-87 and 229-266. See QR Ordering.)


Business Logic ​

Save flow ​

On save, the back-office form sends a PUT /back-office/in-house-settings/{locationId}. The orchestrator (InHouseSettingsOrchestrator::update):

  1. Loads existing table sections and partitions out the MplusKassa Tables integration section.
  2. Processes deleted_sections, skipping the MplusKassa integration section, and aborts with HTTP 400 if a section is still in use by QR Ordering.
  3. Creates/updates submitted sections (skipping the MplusKassa Tables section), generating table names for Automatic sections.
  4. Persists collect_tips, allow_notes, allow_order_notes, default_menu_id, and extra_menu_ids to in_house_setting (InHouseSettingsService::update) and fires a ReloadMenu event.
  5. Dispatches GenerateQrCodesForSection for any sections whose table names changed or that are missing their R2 QR path.

order_capacity is not persisted here ​

The back-office store includes order_capacity in the PUT payload (saveInHouseSettingsForm), but the backend request does not validate it and the service does not store it in in_house_setting. Order capacity is an Online Ordering setting (see Order Capacity), not part of the in-house setting.


Relations ​

Depends On ​

  • Locations: Settings are stored per location (in_house_setting).
  • Menus: The default/extra menus must be eligible menus.
  • POS connection: The settings page is only accessible when a POS channel is connected.

Affects ​

  • QR Ordering: Shares the same table sections.
  • Kiosk / Table QR: In-house ordering uses these settings (storefront behavior not verified here).
  • KDS / Transactions: In-house orders flow downstream (not verified here).

Business Rules ​

  • The default menu (default_menu_id) is required and must be an eligible menu.
  • Extra menus cannot equal the default menu, cannot be duplicated, and their schedules cannot overlap (validated server-side with HTTP 400 errors).
  • Section names must be unique within the location and distinct across the submitted list.
  • A section currently used by QR Ordering cannot be deleted — the save aborts with HTTP 400 until it is removed from QR Ordering first.
  • The MplusKassa Tables section (exact name) is protected: it is skipped from UI section updates and cannot be deleted through this form.
  • Saving fires a ReloadMenu event and may dispatch GenerateQrCodesForSection jobs when section table names change.
  • There is no front-end "at least one section required" enforcement on this page (the only such check exists, commented out, on the QR Ordering page).

FAQs ​

  • "What does the in-house setting actually store?" Only collect_tips, allow_notes, allow_order_notes, default_menu_id, and extra_menu_ids. Table sections are stored separately as TableSection models. It does not store service_mode, prep_time, auto_accept, print_kitchen_ticket, etc.
  • "Why is order_capacity in the save payload but not saved?" The front-end form includes it, but the backend in-house request doesn't accept it and the service doesn't persist it. Order capacity is an Online Ordering setting.
  • "How does tip collection work?" When enabled, three percentage options are offered (default 10/15/20) and tips can be calculated before or after taxes (default After taxes).
  • "What happens when I delete a section?" The save blocks deletion if the section is in use by QR Ordering (HTTP 400) and skips the MplusKassa Tables integration section; otherwise it deletes the section and may regenerate QR codes.
  • "Do changes apply immediately?" Saving fires a ReloadMenu event; QR code regeneration runs asynchronously via background jobs.

Troubleshooting ​

  • Can't open the In-House Settings page → A POS must be connected for the selected location; otherwise the page redirects to home.
  • Table section won't save → The section name must be unique within the location and distinct from other sections in the same submission. For Custom naming each table name must be ≤ 20 characters; for Automatic naming the label is ≤ 10 characters and the number of tables must be ≥ 1.
  • Cannot delete a table section → The section may be in use by QR Ordering (remove it there first), or it may be the MplusKassa Tables integration section, which cannot be deleted through this form.
  • Default menu won't accept a menu → The menu must be eligible for in-house visibility.
  • Extra menu rejected → It cannot equal the default menu, be duplicated, or have an overlapping schedule.

Examples ​

Tips + notes enabled, one Automatic section, one menu (PUT body) ​

json
{
  "collect_tips": {
    "enabled": true,
    "options": [10, 15, 20],
    "calculate_tips": "After taxes"
  },
  "allow_notes": {
    "enabled": true,
    "placeholder": "E.g. \"For Oliver\" or \"I'm allergic to mushrooms\""
  },
  "allow_order_notes": {
    "enabled": true,
    "placeholder": "Add a note for your whole order"
  },
  "sections": [
    {
      "name": "Dining Room",
      "table_name_type": "Automatic Tables Names",
      "table_label": "Table",
      "table_numbers": 10,
      "table_names": [],
      "include_tables": true
    }
  ],
  "deleted_sections": [],
  "default_menu_id": "menu_abc123",
  "extra_menu_ids": []
}

Tips disabled, Custom-named section (PUT body) ​

json
{
  "collect_tips": {
    "enabled": false
  },
  "allow_notes": {
    "enabled": false
  },
  "allow_order_notes": {
    "enabled": false
  },
  "sections": [
    {
      "name": "Terrace",
      "table_name_type": "Custom Tables Name",
      "table_names": ["T1", "T2", "Window seat"],
      "include_tables": true
    }
  ],
  "deleted_sections": [],
  "default_menu_id": "menu_abc123",
  "extra_menu_ids": ["menu_brunch"]
}