Reimbursements
Data Entity
Description
Derived entity representing the approval and payout state of a submitted expense. One reimbursement is generated per expense and tracks its lifecycle from pending review through approval (auto or manual) to payout via accounting integration or export.
Data Structure
| Name | Type | Description | Constraints |
|---|---|---|---|
id |
uuid |
Unique identifier for the reimbursement record | PKrequiredunique |
expense_id |
uuid |
Foreign key to the expense this reimbursement settles (one-to-one) | requiredunique |
organization_id |
uuid |
Tenant scope for multi-organization isolation | required |
user_id |
uuid |
User receiving the reimbursement (the peer mentor or coordinator who submitted the expense) | required |
amount |
decimal |
Monetary amount to be reimbursed, in NOK | required |
currency |
string |
ISO 4217 currency code | required |
status |
enum |
Current lifecycle state of the reimbursement | required |
approval_type |
enum |
Whether approval was made automatically by rules engine or manually by an admin | - |
approved_by |
uuid |
User ID of the Org Admin who approved (null for auto-approved) | - |
approved_at |
datetime |
Timestamp of approval decision | - |
rejection_reason |
text |
Free-text reason provided when status is rejected | - |
approval_rule_id |
uuid |
Reference to the auto-approval rule that fired, if applicable | - |
paid_at |
datetime |
Timestamp when the reimbursement was marked as paid out | - |
payment_reference |
string |
External payment or accounting system reference (e.g. Xledger/Dynamics voucher number) | - |
accounting_export_id |
uuid |
Reference to the accounting export batch that included this reimbursement | - |
notes |
text |
Internal admin notes attached to the reimbursement | - |
created_at |
datetime |
Record creation timestamp | required |
updated_at |
datetime |
Last modification timestamp | required |
Database Indexes
idx_reimbursements_expense_id
Columns: expense_id
idx_reimbursements_organization_id
Columns: organization_id
idx_reimbursements_user_id
Columns: user_id
idx_reimbursements_status
Columns: organization_id, status
idx_reimbursements_created_at
Columns: created_at
idx_reimbursements_accounting_export_id
Columns: accounting_export_id
Validation Rules
amount_non_negative
error
Validation failed
currency_iso_4217
error
Validation failed
status_valid_enum
error
Validation failed
valid_status_transition
error
Validation failed
approver_role_check
error
Validation failed
expense_exists
error
Validation failed
paid_at_after_approved_at
error
Validation failed
Business Rules
one_reimbursement_per_expense
Exactly one reimbursement record exists per expense (one-to-one relationship)
auto_approval_threshold
Reimbursements under the org-defined threshold (e.g. HLF: under 50 km / no out-of-pocket) are auto-approved by the rules engine without manual review
manual_approval_required_above_threshold
Reimbursements exceeding auto-approval thresholds require manual attestation by an Org Admin
receipt_required_for_threshold
Reimbursements above the receipt-required threshold (e.g. 100 NOK for HLF) must have an associated receipt before approval
no_modification_after_paid
Reimbursements in paid status are immutable except for accounting reference back-fills
rejection_requires_reason
Status rejected requires a non-empty rejection_reason
tenant_isolation
Reimbursements are strictly scoped to their organization; cross-tenant reads or writes are forbidden
audit_state_transitions
Every status change must be recorded in the audit log