core PK: id 12 required 2 unique

Description

Photographic or digital proof of payment attached to an expense claim. Stores metadata about the uploaded receipt file, including its storage location, upload status, and association to a specific expense record.

17
Attributes
6
Indexes
6
Validation Rules
15
CRUD Operations

Data Structure

Name Type Description Constraints
id uuid Primary key, uniquely identifies the receipt record
PKrequiredunique
expense_id uuid Foreign key referencing the parent expense record this receipt belongs to
required
file_name string Original filename of the uploaded receipt image as provided by the device camera or file picker
required
storage_key string Object storage key (path) where the file is stored in cloud storage (e.g. S3-compatible bucket path)
requiredunique
storage_bucket string Name of the cloud storage bucket containing this receipt file
required
mime_type string MIME type of the uploaded file (e.g. image/jpeg, image/png, application/pdf)
required
file_size_bytes integer Size of the uploaded file in bytes, used for storage quota enforcement and display
required
upload_status enum Current upload state of the receipt file, supporting offline-first flow
required
presigned_url text Temporary pre-signed URL for secure client-side access to the file. Regenerated on demand; not persisted long-term.
-
presigned_url_expires_at datetime Expiry timestamp for the presigned URL. After expiry, a new URL must be requested.
-
thumbnail_storage_key string Object storage key for the compressed thumbnail version of the receipt image, used in list views
-
uploaded_by_user_id uuid Foreign key referencing the user who uploaded this receipt
required
uploaded_at datetime Timestamp when the upload was successfully completed in cloud storage
-
created_at datetime Timestamp when the receipt record was first created (may precede upload completion in offline scenarios)
required
updated_at datetime Timestamp of the last modification to this record
required
deleted_at datetime Soft-delete timestamp. Non-null means the receipt has been removed by the user or admin.
-
organization_id uuid Organization context for multi-tenancy scoping. Denormalized from the parent expense for efficient tenant-level queries and access control.
required

Database Indexes

idx_expense_receipts_expense_id
btree

Columns: expense_id

idx_expense_receipts_storage_key
btree unique

Columns: storage_key

idx_expense_receipts_uploaded_by
btree

Columns: uploaded_by_user_id

idx_expense_receipts_organization_id
btree

Columns: organization_id

idx_expense_receipts_upload_status
btree

Columns: upload_status

idx_expense_receipts_deleted_at
btree

Columns: deleted_at

Validation Rules

allowed_mime_types error

Validation failed

max_file_size_10mb error

Validation failed

storage_key_uniqueness error

Validation failed

expense_id_must_exist error

Validation failed

uploaded_by_must_match_expense_owner error

Validation failed

presigned_url_expiry_check warning

Validation failed

Business Rules

receipt_required_above_threshold
on_create

A receipt upload is mandatory for any expense where the amount exceeds 100 NOK. The expense cannot be submitted for approval without at least one successfully uploaded receipt.

receipt_belongs_to_submitters_organization
on_create

The organization_id on the receipt must match the organization context of the user who submitted the expense, enforcing multi-tenant data isolation.

immutable_after_approval
on_update

Once the parent expense has been approved via reimbursement_approvals, receipt records become read-only and cannot be deleted or replaced.

soft_delete_only
on_delete

Receipts are never hard-deleted from the database. Deletion sets deleted_at to preserve audit trails for financial records.

Enforced by: Expense Service
max_receipts_per_expense
on_create

A single expense record may have at most 5 receipt attachments to prevent storage abuse.

offline_pending_upload_sync
always

Receipts created offline (upload_status=pending) must be synced to cloud storage when connectivity is restored. Background sync service is responsible for transitioning status from pending → uploading → uploaded.

Storage Configuration

Storage Type
primary_table
Location
main_db
Partitioning
No Partitioning
Retention
archive_after_1year