General Concepts
This page describes shared mechanisms that appear across multiple entities in the Mando system.
External IDs (ext_id)
Section titled “External IDs (ext_id)”External IDs link Mando entities to records in external systems (accounting, e-commerce, loyalty, etc.). They are stored
in an entity’s data.ext_id array and are not generally for end users — they are used internally by integrations.
Structure
Section titled “Structure”{ "ext_id": [ { "id": "netvisorkey", "data": 3469, "system": "netvisor" }, { "id": "id", "data": "12345", "system": "procountor" } ]}| Field | Type | Description |
|---|---|---|
id | string | Key name within the external system (e.g. "netvisorkey", "id") |
data | any | The external identifier value (number, string, or object) |
system | string | External system name (e.g. "netvisor", "procountor", "fennoa") |
There is no type restriction on the data value. The system and id fields can be any string values.
Supported entities
Section titled “Supported entities”External IDs are available on: Customer, PLU (product), Dpt (department), Grp (product group), * Location*, and POS.
Additional Fields
Section titled “Additional Fields”Additional fields let administrators define custom per-entity fields without code changes. Unlike ext_id, additional fields are visible to end users and appear in forms and detail views.
Definition vs. values
Section titled “Definition vs. values”- Field definitions are stored at
company.data.additional_fields[entity_type]— an array of field descriptors. - Field values are stored on each entity at
entity.data.additional_fields[field_id]— keyed by the field’s GUID.
Field definition structure
Section titled “Field definition structure”{ "additional_fields": { "customer": [ { "id": "550e8400-e29b-41d4-a716-446655440000", "name": "Allergies", "group": "Health", "type": "textarea", "description": "Known food allergies", "required": false } ], "plu": [ { "id": "a1b2c3d4-...", "name": "Origin Country", "type": "text", "required": true } ] }}| Field | Type | Description |
|---|---|---|
id | guid | Unique identifier for the field |
name | string | Display label |
group | string? | Optional group heading (fields with the same group are shown together) |
type | enum | Field type (see below) |
ref | string? | Reference to external system |
description | string? | Placeholder / help text |
required | boolean? | Whether the field is mandatory |
Supported field types
Section titled “Supported field types”text, number, amount, textarea, date, datetime, selection, multiselect, checkbox, measurement,
image
Supported entity types
Section titled “Supported entity types”Additional fields can be defined for: company, customer, plu, dpt, grp, location, pos, * salesorder*.
Sales channels can also define their own additional fields that apply to entities sold through that channel.
How values are stored
Section titled “How values are stored”On each entity, the values are stored as a flat map keyed by the field’s GUID:
{ "data": { "additional_fields": { "550e8400-e29b-41d4-a716-446655440000": "Peanuts, shellfish" } }}Sales Channels
Section titled “Sales Channels”Sales channels represent different ways products are sold — e.g. POS (in-store), kiosk, web shop, or delivery platforms like Wolt. They control which products and menus are available in each channel.
Definition
Section titled “Definition”Sales channels are defined at company level in company.data.sales_channels:
{ "sales_channels": [ { "id": "aaa-...", "active": true, "name": "In-store", "type": "mando" }, { "id": "bbb-...", "active": true, "name": "Wolt", "type": "mando" }, { "id": "ccc-...", "active": true, "name": "Web Shop", "type": "mando" } ]}| Field | Type | Description |
|---|---|---|
id | guid | Unique identifier |
active | boolean | Whether the channel is active |
name | string | Display name |
type | string | Channel type, currently any value is accepted |
additional_fields | object? | Additional field definitions specific to this channel |
How entities reference sales channels
Section titled “How entities reference sales channels”Entities store an array of sales channel IDs to indicate which channels they belong to:
| Entity | Field | Effect |
|---|---|---|
| PLU (product) | plu.data.sales_channels | Product is available only in listed channels |
| Menu | menu.data.sales_channels | Menu is shown only in listed channels |
| POS | pos.data.sales_channels | POS terminal operates in listed channels |
| Wolt integration | location.data.wolt.sales_channel | Single channel ID used for Wolt data sync |
Filtering logic
Section titled “Filtering logic”When a POS terminal loads its data, the backend filters products and menus based on the POS’s assigned sales channels.
If a product has sales_channels defined, it is only included if at least one channel matches the POS’s channels.
Products without any sales channel assignment are available everywhere.
Management UI
Section titled “Management UI”The Sales Channel page provides a matrix view where administrators can assign products, menus, and POS devices to channels using checkboxes.
Translations and Language Settings
Section titled “Translations and Language Settings”Mando supports per-field translations for multilingual environments. Finnish is always the default source language.
Company language configuration
Section titled “Company language configuration”Available languages are configured at company.data.languages — an array of language codes:
{ "languages": [ "en", "sv" ]}This tells the system which additional languages are available. Finnish (fi) is implicit as the source language.
Translatable fields
Section titled “Translatable fields”Certain fields on entities support per-language translations. Common translatable fields include name and description on products, menus, and other user-facing entities.
Translation storage
Section titled “Translation storage”Translations are stored in a translations object on each entity, keyed by field path and language code:
{ "name": "Kahvi", "translations": { "name": { "en": "Coffee", "sv": "Kaffe" }, "description": { "en": "Fresh brewed coffee", "sv": "Nybryggat kaffe" } }}The base field value (e.g. name) holds the Finnish text. The translations object provides the other languages.
Fields without translations fall back to the Finnish value.
The UI provides a field editor for translating fields. If the user has access to Mando AI, the editor also provides machine translation suggestions.
Service Periods
Section titled “Service Periods”Service periods define named time ranges within a business day at a location — for example breakfast, lunch, happy hour,
or dinner. They are stored at location.data.service_periods.
Structure
Section titled “Structure”{ "service_periods": [ { "id": "aaa-...", "name": "Breakfast", "start_time": "06:00", "end_time": "11:00", "description": "Morning service", "weekdays": [ "MON", "TUE", "WED", "THU", "FRI" ], "color": "#F59E0B" }, { "id": "bbb-...", "name": "Happy Hour", "start_time": "15:00", "end_time": "17:00", "weekdays": [ "MON", "TUE", "WED", "THU", "FRI" ], "color": "#8B5CF6" } ]}| Field | Type | Description |
|---|---|---|
id | guid | Unique identifier |
name | string | Period name (e.g. “Breakfast”, “Lunch”) |
start_time | string | Start time in HH:MM format |
end_time | string | End time in HH:MM format |
description | string? | Optional description |
weekdays | string[]? | Days when active: MON, TUE, WED, THU, FRI, SAT, SUN. If omitted, active every day. |
color | color? | UI color for visual representation |
Use cases
Section titled “Use cases”- Reporting: Weekly reports can be segmented by service period to compare breakfast vs. lunch vs. dinner performance.
- Operations: Track which time periods generate the most revenue or require the most staff.
- Menu scheduling: Service periods can inform which menus or products are relevant at different times of day.
Service periods are defined per location, so different locations (e.g. a restaurant vs. a cafe) can have different period definitions.