Skip to content

Settings ​

The Settings system provides a definition-driven, scoped configuration store for Moon ERP. Every configurable setting is backed by a SettingDefinition that specifies its type, scope, default value, and allowed values. Setting values are resolved through a fallback chain: user+branch -> branch -> company -> definition default.

Purpose ​

  • Define all available settings with metadata (type, scope, allowed values, localized labels)
  • Store company/branch/user-specific overrides in a scoped settings table
  • Resolve values through a hierarchical fallback chain
  • Automatically cast values based on the definition's value_type
  • Cache settings per company for performance (5-minute TTL)

Setting Definitions ​

Setting definitions describe what settings exist. They are seeded during installation and provide the schema for all configurable options.

Definition Attributes ​

FieldTypeDescription
idintegerPrimary key
setting_keystring(100)Unique dot-notation key (e.g., accounting.ar_parent_account)
modulestring(50)Module name (e.g., accounting, sales)
value_typeenumstring, integer, decimal, boolean, json, enum
default_valuetext?Default value when no override exists
allowed_valuesjson?Restricted list of valid values (for enum types)
scopeenumglobal, company, branch, user
label_arstringArabic display label
label_enstringEnglish display label
description_artext?Arabic description
description_entext?English description
display_groupstring(100)UI grouping (e.g., journal_entries, partners)
display_orderintegerSort order within group
is_visiblebooleanWhether to show in settings UI
requires_restartbooleanWhether changes require app restart

Seeded Definitions ​

30 settings are seeded across 6 modules:

ModuleKeyTypeDefaultScope
accountingaccounting.fiscal_year_startstring01-01company
accountingaccounting.auto_post_entriesbooleanfalsecompany
accountingaccounting.auto_create_partner_accountbooleantruecompany
accountingaccounting.ar_parent_accountstring1103company
accountingaccounting.ap_parent_accountstring2101company
accountingaccounting.cost_center_enabledbooleanfalsecompany
accountingaccounting.cost_center_requiredbooleanfalsecompany
accountingaccounting.default_journal_typestringstandardcompany
salessales.default_price_typeenumwholesalecompany
salessales.allow_negative_stockbooleanfalsebranch
salessales.auto_approve_limitdecimal5000branch
salessales.vat_ratedecimal0.00company
salessales.vat_inclusivebooleanfalsecompany
salessales.revenue_accountstring3101company
salessales.returns_accountstring3102company
salessales.discount_accountstring3103company
inventoryinventory.valuation_methodenumweighted_avgcompany
inventoryinventory.allow_negativebooleanfalsebranch
inventoryinventory.stock_accountstring1301company
inventoryinventory.cogs_accountstring4101company
purchasespurchases.vat_inclusivebooleanfalsecompany
purchasespurchases.expense_accountstring4201company
purchasespurchases.returns_accountstring4202company
corecore.company_name_displayenumbothcompany
corecore.default_languageenumaruser
corecore.date_formatenumY-m-dcompany
corecore.timezonestringAsia/Kuwaitcompany
corecore.default_currencystringKWDcompany
corecore.pagination_per_pageinteger25user
corecore.barcode_auto_generatebooleantruecompany
uiui.show_module_navbooleantrueuser

Setting Values ​

Setting values are stored as overrides in the settings table. When no override exists, the definition's default_value is used.

Setting Attributes ​

FieldTypeDescription
idintegerPrimary key
company_idintegerFK to companies
setting_keystring(100)Dot-notation key (e.g., accounting.ar_parent_account)
valuetext?The stored value
branch_idinteger?FK to branches (for branch-level overrides)
user_idinteger?FK to users (for user-level overrides)
updated_byinteger?FK to users (who last updated)
created_atdatetimeCreation timestamp
updated_atdatetimeLast update timestamp
deleted_atdatetime?Soft-delete timestamp

Fallback Chain ​

When resolving a setting value, the system checks for overrides in this order:

  1. User + Branch -- setting for this specific user at this specific branch
  2. Branch -- branch-level override (no user)
  3. Company -- company-level override (no branch, no user)
  4. Definition Default -- the default_value from the setting definition

The first match wins. If no match is found at any level, null is returned.

Type Casting ​

Values are automatically cast based on the definition's value_type:

TypeCast
string(string)
integer(int)
decimal(float)
booleanfilter_var(..., FILTER_VALIDATE_BOOLEAN)
jsonjson_decode()
enum(string)

Relationships ​

API Endpoints ​

MethodPathDescription
GET/api/core/settings/definitionsList setting definitions (filterable by module)
GET/api/core/settingsList settings with current values (filterable by module)
GET/api/core/settings/{key}Get a single setting by dot-notation key
PUT/api/core/settingsUpdate a setting value

Request/Response Examples ​

GET /api/core/settings/definitions ​

List all setting definitions, optionally filtered by module.

bash
curl -X GET "https://moon-erp.test/api/core/settings/definitions?module=accounting" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer {token}"
dart
final response = await http.get(
  Uri.parse('https://moon-erp.test/api/core/settings/definitions?module=accounting'),
  headers: {
    'Accept': 'application/json',
    'Authorization': 'Bearer $token',
  },
);

Response 200 OK

json
{
  "data": [
    {
      "id": 1,
      "setting_key": "accounting.fiscal_year_start",
      "module": "accounting",
      "value_type": "string",
      "default_value": "01-01",
      "allowed_values": null,
      "scope": "company",
      "label": "Fiscal Year Start",
      "label_ar": "بداية السنة المالية",
      "label_en": "Fiscal Year Start",
      "description": null,
      "display_group": "general",
      "display_order": 1,
      "is_visible": true,
      "requires_restart": false
    }
  ]
}

GET /api/core/settings ​

List settings with their current resolved values. Optionally filter by module.

bash
curl -X GET "https://moon-erp.test/api/core/settings?module=accounting" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer {token}"
dart
final response = await http.get(
  Uri.parse('https://moon-erp.test/api/core/settings?module=accounting'),
  headers: {
    'Accept': 'application/json',
    'Authorization': 'Bearer $token',
  },
);

Response 200 OK

json
{
  "data": [
    {
      "definition": {
        "setting_key": "accounting.ar_parent_account",
        "module": "accounting",
        "value_type": "string",
        "scope": "company",
        "label": "AR Parent Account"
      },
      "current_value": "1103"
    },
    {
      "definition": {
        "setting_key": "accounting.auto_post_entries",
        "module": "accounting",
        "value_type": "boolean",
        "scope": "company",
        "label": "Auto Post Entries"
      },
      "current_value": false
    }
  ]
}

GET /api/core/settings/{key} ​

Get a single setting value by its dot-notation key.

bash
curl -X GET "https://moon-erp.test/api/core/settings/accounting.ar_parent_account" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer {token}"
dart
final response = await http.get(
  Uri.parse('https://moon-erp.test/api/core/settings/accounting.ar_parent_account'),
  headers: {
    'Accept': 'application/json',
    'Authorization': 'Bearer $token',
  },
);

Response 200 OK

json
{
  "key": "accounting.ar_parent_account",
  "value": "1103"
}

PUT /api/core/settings ​

Update a setting value.

bash
curl -X PUT https://moon-erp.test/api/core/settings \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Authorization: Bearer {token}" \
  -d '{
    "setting_key": "accounting.ar_parent_account",
    "value": "1201"
  }'
dart
final response = await http.put(
  Uri.parse('https://moon-erp.test/api/core/settings'),
  headers: {
    'Content-Type': 'application/json',
    'Accept': 'application/json',
    'Authorization': 'Bearer $token',
  },
  body: jsonEncode({
    'setting_key': 'accounting.ar_parent_account',
    'value': '1201',
  }),
);

Request Body

FieldTypeRequiredDescription
setting_keystringYesDot-notation key
valuemixedYesNew value
branch_idinteger?NoBranch scope (for branch-level override)
user_idinteger?NoUser scope (for user-level override)

Response 200 OK

json
{
  "message": "Setting updated"
}

Business Rules ​

  • Company scoping -- settings are automatically scoped to the authenticated user's company.
  • Fallback chain -- values resolve through user+branch -> branch -> company -> definition default.
  • Type casting -- values are automatically cast based on the definition's value_type when retrieved.
  • Validation -- when a definition has allowed_values, only those values are accepted.
  • Cache -- settings are cached per company for 5 minutes; the cache is flushed when any setting is updated.
  • No delete -- settings are updated or reset to defaults, not deleted individually. Use PUT to change values.
  • Enum validation -- for definitions with value_type: enum, the submitted value must be in the allowed_values list.

Moon ERP API Documentation