configuration PK: id 12 required 1 unique

Description

Configurable catalogue of reimbursable expense categories per organization. Defines the fixed set of selectable expense types (mileage, toll, parking, public transport, etc.) that peer mentors can choose from when logging travel expenses, preventing invalid combinations and enforcing receipt and declaration requirements per type.

19
Attributes
3
Indexes
8
Validation Rules
13
CRUD Operations

Data Structure

Name Type Description Constraints
id uuid Primary key — surrogate UUID generated on insert
PKrequiredunique
organization_id uuid Owning organization. Expense types are configured per organization, so each org has its own catalogue.
required
code string Machine-readable identifier for this expense type within the organization (e.g. 'mileage', 'toll', 'parking', 'public_transport', 'honorarium'). Used in API payloads and accounting system mappings.
required
name string Human-readable display label shown to peer mentors in the Expense Type Selector (e.g. 'Mileage', 'Toll Road', 'Parking', 'Public Transport').
required
description text Optional explanatory text shown as help text in the UI, clarifying when to use this expense type.
-
category enum Broad grouping for display and reporting purposes.
required
unit enum Unit of measurement for cost calculation. 'km' uses rate_per_unit Ă— distance; 'fixed' means the user enters an arbitrary amount; 'hours' uses rate_per_unit Ă— duration.
required
rate_per_unit decimal Government-set or org-set reimbursement rate per unit (NOK per km, NOK per hour). Required when unit is 'km' or 'hours'. NULL for 'fixed' types where user enters total amount.
-
max_amount decimal Maximum reimbursable amount in NOK for a single expense of this type. NULL means no cap. Enforced at registration time.
-
requires_receipt boolean Whether a receipt photo upload is mandatory for this expense type. Overridden by receipt_threshold_amount when both are set.
required
receipt_threshold_amount decimal If set, a receipt is required only when the expense amount exceeds this threshold (e.g. 100 NOK for HLF). Takes precedence over the flat requires_receipt flag when amount is below threshold.
-
requires_declaration boolean When true, the peer mentor must complete a confidentiality declaration (taushetserklæring) before this expense type can be submitted. Used for driver honorarium types (Blindeforbundet).
required
auto_approval_threshold_km decimal For mileage expense types: expenses at or below this distance (km) are auto-approved without coordinator review. NULL means manual approval always required. (HLF: 50 km threshold.)
-
mutually_exclusive_with json Array of expense type codes that cannot be selected on the same expense registration as this type (e.g. mileage and public_transport are mutually exclusive — you cannot claim both for the same trip). Enforced in Expense Type Service at submission time.
-
accounting_code string Ledger account code used when exporting to external accounting systems (Xledger, Dynamics). Populated during accounting integration configuration.
-
is_active boolean Soft-delete flag. Inactive types are hidden from the Expense Type Selector but retained for historical expense records.
required
sort_order integer Display ordering within the Expense Type Selector. Lower values appear first.
required
created_at datetime Record creation timestamp (UTC).
required
updated_at datetime Last modification timestamp (UTC). Updated on any field change.
required

Database Indexes

idx_expense_types_org_active
btree

Columns: organization_id, is_active

idx_expense_types_code_org
btree unique

Columns: organization_id, code

idx_expense_types_org_sort
btree

Columns: organization_id, sort_order

Validation Rules

code_format error

Validation failed

name_not_empty error

Validation failed

rate_required_for_unit_types error

Validation failed

max_amount_positive error

Validation failed

receipt_threshold_positive error

Validation failed

mutually_exclusive_codes_exist error

Validation failed

no_self_reference_in_exclusions error

Validation failed

accounting_code_format warning

Validation failed

Business Rules

mutually_exclusive_type_enforcement
on_create

When a peer mentor selects an expense type that declares mutually_exclusive_with entries, all conflicting expense types are immediately disabled in the Expense Type Selector. A single expense registration cannot contain two mutually exclusive types (e.g. mileage and public transport for the same trip). This is a hard technical block, not just a warning.

receipt_required_above_threshold
on_create

If receipt_threshold_amount is set and the expense amount exceeds it, the file-upload-service must receive a receipt attachment before the expense can be submitted. If requires_receipt is true and no threshold is set, receipt is always required.

declaration_required_before_submission
on_create

For expense types where requires_declaration is true, the peer mentor must have a valid confidentiality declaration on file (via Declaration Service) for the relevant period before the expense can be saved.

auto_approval_below_threshold
on_create

For mileage types with auto_approval_threshold_km set: if the distance field on the expense is ≤ threshold and no receipt is required, the expense_approval_service automatically sets approval status to 'approved' without routing to the coordinator queue.

organization_scoped_catalogue
always

An expense type belongs to exactly one organization. Peer mentors and coordinators only see expense types belonging to their own organization. Cross-organization type visibility is never allowed.

soft_delete_preserves_history
on_delete

Expense types cannot be hard-deleted if any expense record references them. Setting is_active = false hides them from selection while keeping historical expense records intact and reportable.

Enforced by: Expense Type Service
accounting_code_required_for_export
always

If the organization has an active accounting integration (accounting_integration_service), all active expense types must have a non-null accounting_code before Bufdir export or accounting sync can proceed.

Storage Configuration

Storage Type
lookup_table
Location
main_db
Partitioning
No Partitioning
Retention
Permanent Storage