Skip to content

Compliance

Overview

There is no implemented Compliance settings page in the product today. The Settings sidebar shows a "Compliance" entry that links to /settings/compliance, but the page is an empty placeholder that displays the text "Compliance content will be here". It contains no settings, forms, or saved configuration.

This document describes what actually exists in code: the placeholder page itself, and the genuinely code-backed compliance-related behaviour that lives elsewhere in the product — alcohol/age and allergen data on individual menu items, the storefront's General Conditions page, and a backend-only GDPR erasure path.

IMPORTANT

Earlier versions of this document described GDPR consent flows, a fiscal module (Fiskaly/EFSTA/TSE), cookie-consent banners, data-retention settings, and sequential-receipt toggles as things you configure here. None of those exist as configurable features in the codebase. They have been removed. Two clarifications, because they do exist elsewhere:

  • A checkout-time age-verification prompt exists in Online Ordering and Kiosk — see the NOTE under Key Concepts. What does not exist is any age-verification setting on this page.
  • A backend GDPR right-to-erasure path exists: deleting a merchant or reseller records durable erasure intent in an Odoo erasure ledger before any teardown, and an hourly odoo:erasure-sweep command reconciles it (app/Services/Odoo/OdooErasureLedger.php, app/Console/Commands/SweepOdooErasures.php). It has no back-office UI or setting and is not exposed on this page.

Legal/regulatory questions (what GDPR, NF525, or age laws actually require of you) are outside the scope of this product behaviour and are not verified here.

Key Purpose: A reserved/placeholder Settings page. No functionality is wired up behind it yet.

Purpose

The /settings/compliance page is a stub. The Vue component (ComplianceComponent.vue) renders only placeholder text and has an unused addNewBilling() handler that logs "features coming soon...". No data is loaded, no API is called, and nothing can be saved.

If you are looking for the compliance-related capabilities that do work in the product, they are not on this page:

  • Alcohol / minimum-age data on items — configured per item in the Item Database (not here).
  • Allergen data on items — configured per item in the Item Database (not here).
  • Storefront General Terms & Conditions — a built-in Belgian general-conditions document served by the Online Ordering storefront. Nothing to switch on; its merchant-identity header is fed from your billing profile and location data (see below).

Key Concepts

  • Compliance page (placeholder): A Settings route (/settings/compliance) and sidebar item exist and are gated by a view-compliance permission, but the page has no content. Treat it as a reserved slot for future work.
  • Item alcohol flag (contains_alcohol): A boolean on a menu item indicating it contains alcohol. Set when creating/editing an item in the Item Database.
  • Alcohol type (alcohol_type): When an item contains alcohol, its type is one of two values: beer_wine or spirits_liquors.
  • Minimum age (minimum_age): An integer stored on the item. It is derived automatically from the item's location country and alcohol type when the item is saved — it is not free-text and there is no merchant-level "minimum age" setting.
  • Allergens (allergens): A list of allergen tags stored per item, plus an optional calorie_count. Configured per item in the Item Database.

NOTE

The alcohol fields (contains_alcohol, alcohol_type, minimum_age) are stored on items and passed through to/from external POS integrations (e.g. Square, Deliveroo). The Compliance settings page itself has nothing to configure. However, Online Ordering and Kiosk checkout do enforce a customer-facing age-verification step: when the cart contains an item with a derived minimum_age, a modal asks the customer to self-confirm they meet the highest required age ("Are you [age] or older?"). Declining removes the flagged items, and the customer cannot submit the order without confirming. This is a self-attestation, not an ID check, and it is not applied by external POS-driven sales.

Actions

Open the Compliance page

Navigating to Settings → Compliance opens /settings/compliance. The page currently shows only the placeholder text "Compliance content will be here". There is nothing to configure.

Set alcohol / minimum age on an item (Item Database)

Alcohol handling is configured per item, not on this page:

  1. Go to the Item Database and create or edit an item.
  2. Toggle Contains alcohol (contains_alcohol).
  3. Choose the alcohol type (alcohol_type): beer/wine or spirits/liquors.
  4. On save, the backend sets the item's minimum_age automatically from the item's location country and the chosen alcohol type.

The country-to-age mapping applied by the backend (ItemService::getMinimumAge) is:

CountryBeer/WineSpirits/Liquors
Belgium (BE)1618
Germany (DE)1618
France (FR)1818
Netherlands (NL)1818
Portugal (PT)1818
Spain (ES)1818
Ireland (IE)1818
Italy (IT)1818
United States (US)2121
Any other / default1818

Set allergens on an item (Item Database)

Allergen tags and calorie information are configured per item in the Item Database (Allergens tab), not on this page.

Storefront General Terms & Conditions (Belgium)

The Online Ordering storefront ships a built-in General Conditions document. It is not a setting — there is nothing to enable, upload, or edit — but the merchant identity printed at the top of it comes from data you maintain elsewhere in the back office.

What it is: a 19-article Belgian general terms & conditions text, available in all seven supported storefront languages. The article order is scope, orders, products, prices, payment, delivery or collection, cancellation, right of withdrawal, allergens, alcohol, complaints, refunds, liability, technical issues, force majeure, intellectual property, privacy, amendments, governing law. The article numbers are generated from that list rather than written into each translation, so numbering cannot drift between languages.

Where customers reach it: from the storefront's account/burger menu (a Legal entry that sits between the personal-info items and Logout) and from the checkout page. The Legal entry is deliberately rendered for guests as well as signed-in customers, because guests can check out.

Where the identity block gets its data — every line renders only if the underlying value exists:

Line on the pageSource
Registered company nameThe location's billing profile company name; falls back to the merchant business name when the billing profile has none
Postal addressThe location's own full address
VAT numberThe location's billing profile VAT number; the line is omitted entirely when the billing profile has no VAT
E-mail and phoneThe location's contact information
WebsiteThe location's online-ordering URL (a custom domain is preferred when one is configured)

(app/RawModels/Location.php builds the legal block; the storefront renders it in TermsDialog.vue.)

Location

  • Backoffice Route: /settings/compliance (route name settings-compliance)
  • Vue Component: src/views/settings/ComplianceComponent.vue (placeholder only)
  • Navigation entry: src/navigation/settings/index.ts (sidebar item, view/compliance)
  • Permission: view-compliance (app/Constants/Permissions.php, constant VIEW_COMPLIANCE)
  • Item alcohol/age logic (backend): app/Services/BackOffice/ItemService.php (getMinimumAge)
  • Item alcohol type enum (backend): app/Enums/AlcoholTypes.php (beer_wine, spirits_liquors)
  • Item fields (backend model): app/RawModels/Item.php (contains_alcohol, alcohol_type, minimum_age, allergens, calorie_count)

WARNING

There is no ComplianceController, no compliance API route, and no compliance settings record. None of the following fields exist anywhere in the product: privacy_policy_url, terms_url, cookie_consent_enabled, data_retention_days, marketing_consent_required, fiscal_enabled, fiscal_provider, fiscal_id, allergen_display, nutritional_display, alcohol_age_check, minimum_alcohol_age, vat_on_receipt, company_reg_on_receipt, sequential_receipts.

Business Rules

  • The Compliance page is a placeholder; it has no settings and saves nothing.
  • A menu item's minimum_age is derived automatically from its location country and alcohol_type at save time — it cannot be set to an arbitrary value through this page, and there is no global minimum-age setting.
  • For countries with split ages (Belgium and Germany: 16 for beer/wine, 18 for spirits/liquors), the age is chosen by the item's alcohol_type. Unknown countries fall back to 18.
  • Alcohol/allergen data is stored on items and passed to external POS integrations. Online Ordering and Kiosk checkout enforce a self-attestation age-verification modal when the cart contains an item with a derived minimum_age: the customer must confirm they meet the highest required age, or the flagged items are removed before checkout. The Compliance settings page itself performs no enforcement.

FAQs

  • "What can I configure on the Compliance settings page?" Nothing currently. The page is a placeholder ("Compliance content will be here") with no functionality wired up.
  • "Where do I configure GDPR / cookie consent / data retention / fiscal modules?" There is nothing to configure for any of these in the back office. (A backend-only right-to-erasure path does run when a merchant or reseller is deleted, but it is not configurable and has no UI.) Anything else you need for legal compliance in those areas is handled outside this software (not verified here).
  • "Where do the company name and VAT number on my storefront's General Conditions page come from?" From the location's billing profile (Settings → Billing) — not from branding or the location name. The address, e-mail and phone come from the location itself.
  • "Does the app verify a customer's age when alcohol is in the cart?" Yes, at checkout. Online Ordering and Kiosk show an age-verification modal when the cart contains an item with a derived minimum_age, asking the customer to confirm they meet the required age. It is a self-attestation (Yes/No), not an ID/document check — declining removes the flagged items so the rest of the order can proceed. External POS-driven sales are not gated this way.
  • "How is the minimum age for an alcoholic item decided?" The backend sets it automatically from the item's location country and alcohol type (beer/wine vs spirits/liquors). See the table under Actions.
  • "Can I set different minimum ages for beer vs. spirits?" Not directly — you choose the item's alcohol type, and the backend applies the country-appropriate age for that type.
  • "Where do allergens come from?" Allergens are set per item in the Item Database, not on the Compliance page.

Troubleshooting

Problem: The Compliance page is blank / shows "Compliance content will be here"

Cause: This is expected. The page is an unimplemented placeholder.

Solution: There is nothing to fix or configure here. Use the Item Database for alcohol/allergen data on items.

Problem: An alcoholic item shows an unexpected minimum age

Causes:

  1. The item's location country drives the age, and that country may differ from what you expect.
  2. The alcohol_type (beer/wine vs spirits/liquors) selected determines the age in split-age countries (BE, DE).
  3. The country is not in the mapping, so the default (18) is applied.

Solutions:

  1. Check the item's location/country.
  2. Verify the chosen alcohol type on the item.
  3. Remember the country mapping is fixed in code (see the table under Actions); there is no per-merchant override.

Problem: Customer wasn't asked to confirm their age at checkout

Cause: The age-verification modal (Online Ordering and Kiosk) only appears when the cart contains an item with a derived minimum_age greater than 0 — i.e. an item with contains_alcohol enabled and a valid alcohol_type whose location country produced a minimum age. If nothing in the cart has a minimum age, no prompt shows.

Solution: Confirm the item has Contains alcohol enabled and a valid alcohol type so the backend derives a minimum_age. Note the check is a self-attestation (not an ID check) and applies to Online Ordering and Kiosk checkout only — external POS-driven sales are not gated.

Problem: My VAT number or company name is missing / wrong on the storefront's General Conditions page

Cause: Both are read from the location's billing profile, not from the branding profile or the location name. A billing profile with no VAT number simply omits the VAT line, and a missing company name falls back to the merchant business name.

Solution: Open Settings → Billing, open the billing profile assigned to that location, and fill in the company name and VAT number in the Billing Details dialog.

Relations

Depends On

  • Locations: An item's country (from its location) determines the derived minimum age for alcoholic items.

Affects

  • Menu Items: Stores alcohol flag, alcohol type, derived minimum age, allergens, and calorie count.