audit PK: id 9 required 2 unique

Description

Records a single execution of an accounting system export to Xledger or the Dynamics portal. Tracks included expense claim IDs, export format, triggering user, and outcome status. Provides the audit trail used to prevent double-export of approved claims and supports re-download of historical export files by administrators.

17
Attributes
5
Indexes
8
Validation Rules
13
CRUD Operations

Data Structure

Name Type Description Constraints
id uuid Globally unique identifier for the export run, generated server-side on creation.
PKrequiredunique
organization_id uuid Foreign key to the organization that owns this export run. All data access is gated by this field via RLS.
required
triggered_by_user_id uuid Foreign key to the user (coordinator or org admin) who initiated the export. Captured at creation time and never updated.
required
target_system enum The destination accounting system for this export run.
required
format enum File format of the generated export artifact.
required
status enum Current lifecycle state of the export run. Transitions: pending → completed | partial | failed.
required
date_range_start datetime Inclusive start of the date window used to query approved expense claims for this export.
required
date_range_end datetime Inclusive end of the date window used to query approved expense claims for this export.
required
included_claim_ids json JSON array of expense_claim UUIDs that were successfully included in this export. Populated atomically when the run transitions to completed or partial status. Used by the double-export guard to prevent re-export.
-
included_count integer Count of expense claims successfully included in the export. Derived from included_claim_ids length; stored explicitly for fast query access.
-
skipped_count integer Number of approved claims within the date range that were excluded from this export run, e.g. due to missing required fields or already-exported status.
-
skipped_claim_details json JSON array of objects describing each skipped claim: {claim_id, reason}. Surfaced in the export confirmation dialog to inform the administrator which claims were excluded and why.
-
file_storage_path string Organization-scoped path within the Supabase Storage bucket where the generated export file is stored. Format: {org_id}/{export_run_id}/{filename}. Null for failed runs.
unique
file_url string Time-limited signed download URL for the generated export file. Regenerated on re-download requests. Null for failed runs or before file generation completes.
-
error_message text Human-readable error description captured when the run transitions to failed status. Null for successful runs.
-
completed_at datetime UTC timestamp when the export run reached a terminal state (completed, partial, or failed). Null while still pending.
-
created_at datetime UTC timestamp of export run creation, set server-side and immutable.
required

Database Indexes

idx_export_run_org_created
btree

Columns: organization_id, created_at

idx_export_run_org_status
btree

Columns: organization_id, status

idx_export_run_triggered_by
btree

Columns: triggered_by_user_id

idx_export_run_target_system
btree

Columns: organization_id, target_system

idx_export_run_date_range
btree

Columns: organization_id, date_range_start, date_range_end

Validation Rules

valid_organization_id error

Validation failed

valid_triggered_by_user_id error

Validation failed

date_range_ordering error

Validation failed

date_range_not_future error

Validation failed

valid_status_transition error

Validation failed

included_claim_ids_are_valid_uuids error

Validation failed

skipped_count_matches_details_length warning

Validation failed

file_storage_path_format error

Validation failed

Business Rules

no_double_export
on_create

An expense claim that already has a non-null export_run_id on its record must not be included in a new export run. The double-export guard filters the candidate claim set before any export is generated, and atomically stamps newly exported claims with the current run's ID after successful generation.

immutable_after_terminal_state
on_update

Once an export run reaches a terminal status (completed, partial, or failed), its core fields — including included_claim_ids and skipped_claim_details — must not be modified. Only file_url may be regenerated (not persisted) for re-download purposes.

Enforced by: Export Run Repository
organization_scoped_access
always

All read and write operations on export_run records are filtered by organization_id via Supabase RLS. A user from organization A must never access export runs belonging to organization B.

coordinator_or_admin_only
on_create

Only users with coordinator or org_admin roles within the organization may create export runs. Peer mentors are blocked at the route and service layer.

atomic_claim_stamping
on_update

The transition from pending to completed/partial must atomically write included_claim_ids to the export_run record and stamp each included expense_claim with this export_run_id in a single database transaction. A partial failure rolls back both writes to preserve consistency.

partial_status_requires_skipped_details
on_update

When an export run transitions to partial status, skipped_count must be greater than zero and skipped_claim_details must be populated with at least one entry explaining the exclusions.

file_storage_path_required_on_success
on_update

An export run transitioning to completed or partial status must have a non-null file_storage_path set at the same time. A run cannot be marked successful without a stored export artifact.

target_system_matches_org_configuration
on_create

The target_system value must correspond to an active integration configured for the organization. Blindeforbundet maps to xledger; HLF maps to dynamics. An export run against an unconfigured target system must be rejected.

Storage Configuration

Storage Type
primary_table
Location
main_db
Partitioning
No Partitioning
Retention
Permanent Storage

Entity Relationships

expense_claim
incoming references

An approved expense claim is stamped with the export_run_id when it is first included in an accounting system export, preventing double-export

optional
organization
incoming one_to_many

Accounting system export runs are scoped to an organization and used to track double-export prevention per organization

required