core PK: id 13 required 1 unique

Description

Travel and out-of-pocket expense claims registered by peer mentors and coordinators against a logged activity, classified by expense type and routed through approval to reimbursement.

19
Attributes
7
Indexes
7
Validation Rules
14
CRUD Operations

Data Structure

Name Type Description Constraints
id uuid Primary key for the expense record
PKrequiredunique
activity_id uuid Foreign key to the activity this expense is claimed against
required
expense_type_id uuid Foreign key to the configured expense type (e.g. mileage, toll, parking, transit, driver-honorarium)
required
user_id uuid User who submitted the expense (peer mentor or coordinator on behalf)
required
organization_id uuid Tenant organization scope for multi-tenant isolation
required
amount decimal Monetary amount claimed in NOK
required
currency string ISO 4217 currency code
required
distance_km decimal Distance in kilometers for mileage-type expenses; null for non-mileage types
-
expense_date datetime Date the expense was incurred
required
description text Optional free-text note describing the expense
-
status enum Lifecycle status of the expense claim
required
auto_approved boolean Whether the expense was automatically approved by rules engine (below threshold and no receipt required)
required
requires_receipt boolean Whether a receipt is required based on expense type and amount threshold (e.g. >100 NOK for HLF)
required
approver_id uuid User who approved or rejected the expense
-
approved_at datetime Timestamp of approval/rejection decision
-
rejection_reason text Reason text when status is rejected
-
created_at datetime Record creation timestamp
required
updated_at datetime Record last update timestamp
required
synced_at datetime Timestamp when offline-created record was synced to backend
-

Database Indexes

idx_expenses_activity_id
btree

Columns: activity_id

idx_expenses_user_id
btree

Columns: user_id

idx_expenses_organization_id
btree

Columns: organization_id

idx_expenses_expense_type_id
btree

Columns: expense_type_id

idx_expenses_status
btree

Columns: status

idx_expenses_org_status
btree

Columns: organization_id, status

idx_expenses_expense_date
btree

Columns: expense_date

Validation Rules

amount_non_negative error

Validation failed

distance_required_for_mileage error

Validation failed

expense_date_not_future error

Validation failed

valid_expense_type error

Validation failed

valid_status_transition error

Validation failed

rejection_reason_required error

Validation failed

currency_iso_code error

Validation failed

Business Rules

expense_must_link_to_activity
on_create

Every expense must be attached to an existing activity record

auto_approval_under_threshold
on_create

Expenses under 50 km mileage with no receipt requirement are auto-approved per HLF rule; configurable per organization

manual_approval_above_threshold
on_create

Expenses above the configured threshold require manual approval by Org Admin

receipt_required_above_amount
on_create

When amount exceeds the receipt-required threshold (e.g. 100 NOK), a receipt must be attached before submission

mutually_exclusive_expense_types
on_create

Mutually exclusive expense type combinations (e.g. mileage and transit ticket for the same trip) are rejected by the type rules

no_modification_after_reimbursement
on_update

Reimbursed expenses are immutable

tenant_isolation
always

Expenses are scoped to the submitter's organization and never visible across tenants

Storage Configuration

Storage Type
primary_table
Location
main_db
Partitioning
No Partitioning
Retention
archive_after_1year