Settings¶
eQual provides a centralized settings system for runtime configuration values. Settings are stored as model data, can be edited through the Settings application, and can be resolved dynamically by package code.
A setting is uniquely identified by:
package: the package or domain that owns the setting.section: the shared configuration section.code: the hierarchical path inside the section.
The full logical name follows this structure:
<package>.<section>.<thematic_area>[.<setting>[.<sub_setting>[.<item>]]]
Settings are usually accessed by passing the package, section, and code separately:
Setting::get_value($package, $section, $code, $default);
Examples:
Setting::get_value('core', 'locale', 'date.format', 'd/m/Y');
Setting::get_value('sale', 'features', 'quote.validity_delay', 30);
Setting Object¶
Each Setting defines the metadata of a configurable parameter:
{
"id": 5,
"code": "number.decimal_precision",
"title": "Number of decimal digits",
"package": "core",
"form_control": "select",
"section_id": 1,
"description": "Number of decimal digits",
"help": "Number of decimal digits to store for fields of type 'float'.",
"type": "integer"
}
The actual runtime value is stored separately:
SettingValueholds the value for a setting. Values can be scoped to a context using a selector such asuser_idororganization_id.SettingSequencemanages numeric counters. Sequences can also be scoped with selectors, for example to maintain independent numbering per organization.
Values and sequences use the same naming structure:
value::<package>.<section>.<code>
sequence::<package>.<section>.<code>
Examples:
value::purchase.accounting.invoice.sequence_format
sequence::purchase.accounting.invoice
Package¶
The package identifies the eQual package, module, or application area responsible for the setting.
Examples:
core
sale
documents
purchase
finance
stats
hr
identity
realestate
support
The package should represent the functional or technical domain that owns the setting.
Section¶
Sections are shared high-level configuration groups. They describe the nature of the setting, not the business object itself.
Examples:
core.locale.date.format
sale.features.quote.validity_delay
finance.accounting.accounting_entry.sequence.2024.Q1.SAL
Section names should remain stable and consistent across packages.
| Section | Functional name | Main usage |
|---|---|---|
locale |
Localization and regional conventions | Languages, date/time formats, number formats, currencies, default units of measure |
security |
Security and access control | Authentication, MFA, roles, sessions, audit logs, access rules |
default |
Default values | Default values injected into fields, especially with defaultFromSetting |
accounting |
Accounting, fiscal and numbering logic | Accounting accounts, VAT, invoicing, document numbering, financial sequences |
analytics |
Reporting and analytics | Logs, metrics, KPIs, reporting configuration |
features |
Functional options and customization | Feature flags, configurable behavior, UI labels, templates, delays, business options |
storage |
Storage and data persistence | File paths, quotas, storage backends, persistence settings |
integration |
Integrations and connectors | APIs, tokens, endpoints, webhooks, external services |
system |
Technical and maintenance settings | Debug mode, internal notifications, versions, technical behavior |
workflow |
Business logic and processes | Statuses, transitions, automation rules, process behavior |
schedule |
Scheduling and time configuration | Calendars, working hours, cron jobs, planning rules |
organization |
Structure and organization | Internal organization setup not directly carried by an entity, SKUs, departments, fiscal or HR periods |
Code¶
The code starts with a thematic area, then narrows the meaning progressively through more specific segments.
Examples:
date
time
number
currency
unit
auth
booking
quote
invoice
sku
The thematic area should be broad enough to allow future extension. Prefer:
core.locale.currency.symbol
core.locale.currency.symbol_position
core.locale.currency.decimal_precision
over isolated flat keys:
core.locale.currency_symbol
core.locale.currency_position
Use dots for hierarchy and underscores inside a segment when a concept is composed of multiple words:
decimal_separator
symbol_position
validity_delay
archive_delay
default_value
Locale Settings¶
The locale section contains settings related to localization, regional conventions, and display formats.
Recommended structure:
core.locale.date.*
core.locale.time.*
core.locale.number.*
core.locale.currency.*
core.locale.unit.*
Date and Time¶
{
"core.locale.date.format": "d/m/Y",
"core.locale.time.format": "H:i"
}
Setting::get_value('core', 'locale', 'date.format', 'd/m/Y');
Setting::get_value('core', 'locale', 'time.format', 'H:i');
Number Formatting¶
{
"core.locale.number.thousands_separator": ".",
"core.locale.number.decimal_separator": ",",
"core.locale.number.decimal_precision": 2
}
Setting::get_value('core', 'locale', 'number.thousands_separator', '.');
Setting::get_value('core', 'locale', 'number.decimal_separator', ',');
Setting::get_value('core', 'locale', 'number.decimal_precision', 2);
The segment number is singular for consistency with date, time, currency, and unit.
Currency¶
Currency settings should distinguish the currency code from its display symbol.
{
"core.locale.currency.code": "EUR",
"core.locale.currency.symbol": "€",
"core.locale.currency.symbol_position": "after",
"core.locale.currency.decimal_precision": 2
}
Setting::get_value('core', 'locale', 'currency.code', 'EUR');
Setting::get_value('core', 'locale', 'currency.symbol', '€');
Setting::get_value('core', 'locale', 'currency.symbol_position', 'after');
Setting::get_value('core', 'locale', 'currency.decimal_precision', 2);
The currency code should use an ISO-style code such as EUR, USD, CHF, or GBP. The symbol is only a display value, and can be ambiguous across currencies.
Keep currency.decimal_precision separate from number.decimal_precision:
{
"core.locale.number.decimal_precision": 3,
"core.locale.currency.decimal_precision": 2
}
The first setting applies to generic numbers. The second applies to monetary values.
Units of Measure¶
Default units of measure are stored under core.locale.unit.*.
{
"core.locale.unit.length": "m",
"core.locale.unit.weight": "kg",
"core.locale.unit.volume": "m3",
"core.locale.unit.surface": "m2"
}
Setting::get_value('core', 'locale', 'unit.length', 'm');
Setting::get_value('core', 'locale', 'unit.weight', 'kg');
Setting::get_value('core', 'locale', 'unit.volume', 'm3');
Setting::get_value('core', 'locale', 'unit.surface', 'm2');
For code, configuration, and exports, ASCII values are preferred:
m2
m3
For user display, typographic labels may be used when needed:
m²
m³
If the system needs to distinguish internal values from display labels, use a more explicit structure:
{
"core.locale.unit.surface.code": "m2",
"core.locale.unit.surface.label": "m²",
"core.locale.unit.volume.code": "m3",
"core.locale.unit.volume.label": "m³"
}
Choosing the Right Section¶
The section should describe the nature of the setting.
| Question | Recommended section |
|---|---|
| Is it related to formats, languages, currencies, units, timezones, or regional conventions? | locale |
| Is it related to authentication, access control, MFA, sessions, or audit logs? | security |
| Is it a default value injected into a field? | default |
| Is it related to accounting accounts, VAT, invoicing, fiscal logic, or numbering? | accounting |
| Is it related to reports, KPIs, metrics, or statistics? | analytics |
| Is it a configurable behavior, feature flag, label, template, business option, or delay? | features |
| Is it related to files, paths, quotas, or storage backends? | storage |
| Is it related to an API, webhook, connector, or external service? | integration |
| Is it a technical, internal, or maintenance setting? | system |
| Is it related to statuses, transitions, or business process rules? | workflow |
| Is it related to calendars, opening hours, working hours, or scheduled jobs? | schedule |
| Is it related to internal structure, SKUs, departments, or organization-level references? | organization |
Distinguishing Common Sections¶
Use default when the setting directly provides the default value of a field:
sale.default.booking.sojourn.age_range
This section is used by mechanisms such as defaultFromSetting.
Use features when the setting controls configurable behavior, optional features, delays, labels, templates, or functional customization:
sale.features.quote.validity_delay
sale.features.option.validity_delay
sale.features.booking.archive_delay
Use organization when the setting describes an organizational reference, structural configuration, or internal mapping that does not fit directly within a dedicated entity:
sale.organization.sku.downpayment.1
sale.organization.sku.downpayment.2
sale.organization.sku.bed_linens
sale.organization.sku.transport
sale.organization.sku.make_beds
Naming Guidelines¶
| Principle | Rule |
|---|---|
| Hierarchy | Start from general to specific |
| Consistency | Use dots for hierarchy and underscores inside a segment |
| Clarity | Avoid abbreviations unless they are standard or obvious |
| Stability | Use shared sections consistently across packages |
| Explicitness | Prefer currency.code and currency.symbol over a generic currency value |
| Future extension | Reserve thematic areas for further extension, such as auth.passkey.* |
| Avoid redundancy | Do not repeat the same concept unnecessarily in multiple path segments |
Boolean settings should be grouped by functional area and named according to the behavior they activate.
Recommended:
core.security.auth.passkey.enabled
sale.features.booking.auto_archive
documents.features.ocr.enabled
Avoid vague names such as:
enabled
active
use_feature
unless the parent path is sufficiently explicit, as in:
core.security.auth.passkey.enabled
Examples¶
Locale formatting:
Setting::get_value('core', 'locale', 'date.format', 'd/m/Y');
Setting::get_value('core', 'locale', 'time.format', 'H:i');
Setting::get_value('core', 'locale', 'number.thousands_separator', '.');
Setting::get_value('core', 'locale', 'number.decimal_separator', ',');
Setting::get_value('core', 'locale', 'number.decimal_precision', 2);
Currency settings:
Setting::get_value('core', 'locale', 'currency.code', 'EUR');
Setting::get_value('core', 'locale', 'currency.symbol', '€');
Setting::get_value('core', 'locale', 'currency.symbol_position', 'after');
Setting::get_value('core', 'locale', 'currency.decimal_precision', 2);
Units of measure:
Setting::get_value('core', 'locale', 'unit.length', 'm');
Setting::get_value('core', 'locale', 'unit.weight', 'kg');
Setting::get_value('core', 'locale', 'unit.volume', 'm3');
Setting::get_value('core', 'locale', 'unit.surface', 'm2');
Passkey authentication:
Setting::get_value('core', 'security', 'auth.passkey.rp.id', 'example.com');
Setting::get_value('core', 'security', 'auth.passkey.user_verification', 'preferred');
Setting::get_value('core', 'security', 'auth.passkey.authenticator_support.usb', true);
Accounting sequences:
Setting::assert_sequence('finance', 'accounting', 'accounting_entry.sequence.2024.Q1.SAL');
Sale settings:
Setting::get_value('sale', 'features', 'quote.validity_delay', 30);
Setting::get_value('sale', 'features', 'option.validity_delay', 15);
Setting::get_value('sale', 'features', 'booking.archive_delay', 365);
Setting::get_value('sale', 'organization', 'sku.downpayment.1');
Setting::get_value('sale', 'organization', 'sku.bed_linens');
Setting::get_value('sale', 'organization', 'sku.transport');
Setting::get_value('sale', 'organization', 'sku.make_beds');