configuration PK: id 11 required 1 unique

Description

Defines the fixed categories of allowable expenses (kilometers driven, toll road fees, parking, public transit). Expense types carry mutual exclusion group codes that prevent incompatible combinations from being selected simultaneously (e.g., kilometers and public transit cannot be claimed together). Configured per organization with reimbursement formula parameters.

13
Attributes
4
Indexes
8
Validation Rules
13
CRUD Operations

Data Structure

Name Type Description Constraints
id uuid Primary key for the expense type record
PKrequiredunique
organization_id uuid Foreign key to the organization this expense type is configured for. Expense types are scoped per organization to allow different formula parameters and labels.
required
key enum Machine-readable identifier for the expense type. Fixed set of four categories across the entire system.
required
label string Organization-specific display label for this expense type. Resolved through the organization labels system to support different terminology per org.
required
exclusive_group string Group code used to enforce mutual exclusion. Expense types sharing the same exclusive_group cannot be selected simultaneously. E.g., 'transport_mode' groups kilometers and public_transit as mutually exclusive. Null means no exclusion applies.
-
reimbursement_formula json Structured formula parameters governing how reimbursement is calculated for this expense type. Schema varies by key: kilometers uses {type: 'per_km_rate', rate_per_km: decimal}; toll and parking use {type: 'receipt_amount', requires_receipt_above: decimal}; public_transit uses {type: 'declared_amount', max_claimable: decimal}.
required
requires_distance boolean When true, the expense registration UI must collect a distance value in kilometers. Applies to the kilometers expense type.
required
requires_amount boolean When true, the expense registration UI must collect a monetary amount. Applies to toll, parking, and public_transit expense types.
required
receipt_threshold decimal Organization-configured monetary threshold above which a receipt image attachment becomes mandatory for this expense type. Null means no receipt is ever required for this type.
-
is_active boolean Soft-delete flag. When false, this expense type is hidden from registration UI and excluded from validation but preserved for historical records.
required
sort_order integer Display ordering of expense types within the picker UI. Lower values appear first.
required
created_at datetime Timestamp when the expense type record was created.
required
updated_at datetime Timestamp of last modification. Updated automatically on any field change.
required

Database Indexes

idx_expense_type_org_id
btree

Columns: organization_id

idx_expense_type_org_key
btree unique

Columns: organization_id, key

idx_expense_type_exclusive_group
btree

Columns: organization_id, exclusive_group

idx_expense_type_active
btree

Columns: organization_id, is_active

Validation Rules

key_enum_constraint error

Validation failed

label_non_empty error

Validation failed

reimbursement_formula_json_parseable error

Validation failed

receipt_threshold_non_negative error

Validation failed

sort_order_non_negative error

Validation failed

organization_exists error

Validation failed

exclusive_group_max_length error

Validation failed

formula_type_field_required error

Validation failed

Business Rules

fixed_key_catalogue
on_create

Only four expense type keys are permitted system-wide: kilometers, toll, parking, public_transit. No organization may add custom expense type keys. This ensures the mutual exclusion matrix and reimbursement formula logic remain consistent across all feature components.

organization_unique_key
on_create

Each organization may have at most one active expense type record per key value. Attempting to create a duplicate (organization_id, key) pair must be rejected.

mutual_exclusion_group_consistency
always

Expense types assigned to the same exclusive_group within an organization are mutually exclusive at selection time. The kilometers and public_transit types must share an exclusive_group (e.g., 'transport_mode') because claiming mileage reimbursement and public transit reimbursement for the same trip is not permitted.

requires_distance_only_for_kilometers
on_create

The requires_distance flag must be true only for the kilometers expense type. All other types must have requires_distance set to false.

requires_amount_for_non_km_types
on_create

The requires_amount flag must be true for toll, parking, and public_transit expense types. The kilometers type calculates its amount from distance × rate and does not require a direct amount input.

reimbursement_formula_schema_valid
on_create

The reimbursement_formula JSON must conform to the schema for the given key: kilometers requires 'rate_per_km'; toll and parking require 'requires_receipt_above'; public_transit requires 'max_claimable'. Missing or malformed formula fields block expense calculations.

soft_delete_preserves_history
on_delete

Expense types must never be hard-deleted. Setting is_active to false hides the type from new registrations while preserving all historical expense records that reference this type.

receipt_threshold_currency_consistency
on_create

The receipt_threshold value is always expressed in Norwegian Krone (NOK) and must be a non-negative decimal. A value of 0 means a receipt is always required; null means a receipt is never required regardless of amount.

Storage Configuration

Storage Type
lookup_table
Location
main_db
Partitioning
No Partitioning
Retention
Permanent Storage