configuration PK: id 13 required 1 unique

Description

Organisation-scoped catalogue of allowable expense categories with mutual-exclusivity rules, documentation requirements, amount thresholds, and approval policies. Each organisation configures its own set of expense types to enforce reimbursement business rules specific to their Bufdir funding agreements.

25
Attributes
6
Indexes
10
Validation Rules
23
CRUD Operations

Data Structure

Name Type Description Constraints
id uuid Unique identifier for the expense type record
PKrequiredunique
organization_id uuid Foreign key to the owning organisation — expense types are tenant-scoped
required
name string Display name of the expense type shown in selector widgets (e.g. 'Kilometre Allowance', 'Public Transport', 'Parking')
required
slug string URL-safe machine identifier used in API payloads and rule references, unique within an organisation
required
description text User-facing explanation of what this expense type covers, displayed in the selector widget tooltip
-
category enum High-level classification of the expense type for grouping and reporting
required
is_active boolean Soft-delete flag — inactive types are hidden from selectors but preserved for historical expense records
required
requires_receipt boolean Whether a receipt photo attachment is mandatory when submitting an expense of this type
required
receipt_threshold_amount decimal Amount (in NOK) above which a receipt becomes mandatory even if requires_receipt is false. Null means no threshold-based receipt requirement.
-
max_amount decimal Maximum claimable amount per single expense of this type. Null means no cap.
-
unit enum Unit of measurement for the expense — determines which input fields the form renders
required
rate_per_unit decimal Default reimbursement rate per unit (e.g. NOK per km). Null for fixed_amount types where the user enters the total.
-
mutual_exclusivity_group string Group key for mutual exclusivity — expense types sharing the same group key cannot be combined on a single expense claim (e.g. 'transport' group prevents selecting both km and bus ticket)
-
requires_declaration boolean Whether a signed confidentiality or driver declaration is required before submitting this expense type
required
declaration_type enum Type of declaration required when requires_declaration is true
-
auto_approval_eligible boolean Whether expenses of this type can be auto-approved by the auto-approval rule engine
required
auto_approval_max_amount decimal Maximum amount for automatic approval of this type. Claims above this go to manual review. Null defers to org-level auto-approval rules.
-
auto_approval_max_distance_km decimal Maximum distance in km for automatic approval of per_km types (HLF: under 50 km auto-approved). Null means no distance-based auto-approval.
-
accounting_code string Default account code mapping for accounting system export (Xledger/Dynamics). Can be overridden per-org in accounting integration settings.
-
bufdir_category_code string Bufdir reporting category code for mapping this expense type to the required Bufdir report format
-
display_order integer Sort position in the expense type selector widget. Lower numbers appear first.
required
rules_json json Extensible JSON object encoding additional business rules — field visibility conditions, conditional requirements, custom validation logic
-
created_at datetime Timestamp when the expense type was created
required
updated_at datetime Timestamp of the last modification to this expense type record
required
created_by uuid User ID of the administrator who created this expense type
-

Database Indexes

idx_expense_types_organization_id
btree

Columns: organization_id

idx_expense_types_org_slug
btree unique

Columns: organization_id, slug

idx_expense_types_org_active
btree

Columns: organization_id, is_active

idx_expense_types_mutual_exclusivity
btree

Columns: organization_id, mutual_exclusivity_group

idx_expense_types_org_display_order
btree

Columns: organization_id, display_order

idx_expense_types_category
btree

Columns: organization_id, category

Validation Rules

unique_slug_per_organisation error

Validation failed

valid_organisation_reference error

Validation failed

rate_required_for_unit_types error

Validation failed

declaration_type_consistency error

Validation failed

threshold_amount_non_negative error

Validation failed

name_not_blank error

Validation failed

slug_format_validation error

Validation failed

auto_approval_distance_only_for_per_km error

Validation failed

rules_json_schema_validation error

Validation failed

display_order_non_negative error

Validation failed

Business Rules

organisation_scoped_isolation
always

Expense types are always scoped to a single organisation. Queries must filter by organization_id to enforce multi-tenant data isolation. A user can only see and use expense types belonging to their own organisation.

mutual_exclusivity_enforcement
on_create

Expense types sharing the same mutual_exclusivity_group value cannot be combined on a single expense submission. When a user selects one type from a group, all other types in that group must be disabled in the selector. Example: 'km allowance' and 'public transport' in group 'transport' cannot coexist on one claim.

receipt_threshold_escalation
always

If an expense amount exceeds receipt_threshold_amount for its type, a receipt attachment becomes mandatory regardless of the requires_receipt flag. HLF requires receipts for claims over 100 NOK.

soft_delete_preservation
on_delete

Expense types must never be hard-deleted if any expense records reference them. Deactivation (is_active = false) hides the type from new submissions while preserving historical data integrity for reporting and audit.

auto_approval_eligibility_gating
always

Only expense types with auto_approval_eligible = true can be evaluated by the auto-approval rule engine. Types with this flag set to false always require manual coordinator or admin review regardless of amount or distance.

distance_auto_approval_for_travel
always

For per_km expense types, claims under auto_approval_max_distance_km are eligible for automatic approval. Claims above the threshold are routed to manual approval. Derived from HLF requirement: under 50 km without additional expenses = auto-approved.

declaration_prerequisite
on_create

When requires_declaration is true, the user must have a valid, unexpired declaration of the specified declaration_type on file before an expense of this type can be submitted. Derived from Blindeforbundet driver honorarium and confidentiality requirements.

max_amount_cap
on_create

If max_amount is set, any expense claim of this type exceeding the cap must be rejected at submission time with a clear error message indicating the maximum allowed amount.

rate_per_unit_calculation
always

For unit-based types (per_km, per_hour, per_day), the total reimbursement amount is calculated as quantity * rate_per_unit. The user enters the quantity; the rate is fixed by the organisation configuration.

admin_only_configuration
on_create

Only Organisation Administrators and Global Administrators can create, update, or deactivate expense types. Coordinators and Peer Mentors have read-only access to the active type catalogue.

Storage Configuration

Storage Type
lookup_table
Location
main_db
Partitioning
No Partitioning
Retention
Permanent Storage