core PK: id 11 required 2 unique

Description

A generated compliance report conforming to Bufdir (Norwegian Directorate for Children, Youth and Family Affairs) grant reporting requirements. Aggregates activity counts, contact categories, and participant totals across the organization hierarchy for a given reporting period. All four partner organizations depend on Bufdir funding and must submit these reports.

20
Attributes
6
Indexes
9
Validation Rules
17
CRUD Operations

Data Structure

Name Type Description Constraints
id uuid Primary key. Universally unique identifier for the report record.
PKrequiredunique
organization_id uuid Foreign key referencing the organization that owns this report. All data is scoped to this organization and its full hierarchy (regions + local associations).
required
reporting_period_start datetime Inclusive start date of the Bufdir reporting period (typically Jan 1 or start of a quarter). Stored as date-only at midnight UTC.
required
reporting_period_end datetime Inclusive end date of the Bufdir reporting period (typically Dec 31 or end of a quarter). Must be after reporting_period_start.
required
period_label string Human-readable label for the reporting period, e.g. '2025', 'Q1 2025', 'H1 2025'. Computed at generation time and stored for display.
required
status enum Lifecycle state of the report. 'generating' is set when the async job starts; 'complete' when the file is ready; 'failed' when aggregation or export encountered an unrecoverable error.
required
format enum Output file format requested by the user. XLSX uses semicolon delimiter matching Norwegian Excel locale; CSV for interoperability; JSON for in-app preview rendering.
required
generated_at datetime Timestamp when the report generation job completed successfully and the file was written to storage. NULL while status is draft or generating.
-
generated_by uuid Foreign key referencing the user (Coordinator, Org Admin, or Global Admin) who triggered this report generation.
required
storage_key string Object storage path for the exported report file (e.g. 'bufdir-reports/{org_id}/{year}/{report_id}.xlsx'). NULL until status is complete.
unique
report_data json Full aggregated Bufdir-mapped data payload as structured JSON. Contains all Bufdir field values, activity breakdowns by type and contact category, participant totals, and hierarchy rollups. Used for in-app preview and as the source for file export.
-
total_activity_count integer Denormalized total count of approved activities included in the report period for quick display without parsing report_data.
-
total_participant_count integer Denormalized total count of unique participants (contacts + event attendees) across all activities in the period.
-
total_hours decimal Denormalized sum of activity durations in hours across the reporting period. Used for KPI display on the report screen.
-
bufdir_schema_version string The Bufdir reporting schema version used when generating this report (e.g. '2025-v1'). Required to interpret report_data correctly if the schema evolves.
required
validation_warnings json Array of pre-export validation warning objects (e.g. missing activity types, unapproved activities, incomplete contact categories). Each entry has: { code, message, severity, affected_count }. Empty array means no warnings.
-
error_message text Human-readable error description when status = 'failed'. Contains the root cause of the generation failure for admin review. NULL for non-failed reports.
-
hierarchy_scope json Snapshot of the organizational hierarchy nodes included in this report at generation time: { organization_id, region_ids[], local_association_ids[] }. Stored to ensure report reproducibility even if hierarchy changes later.
-
created_at datetime Timestamp when the report record was first created (when the generation job was enqueued).
required
updated_at datetime Timestamp of the last status update or data write. Updated on every status transition.
required

Database Indexes

idx_bufdir_report_org_period
btree

Columns: organization_id, reporting_period_start, reporting_period_end, format

idx_bufdir_report_org_status
btree

Columns: organization_id, status

idx_bufdir_report_org_generated
btree

Columns: organization_id, generated_at

idx_bufdir_report_generated_by
btree

Columns: generated_by

idx_bufdir_report_status
btree

Columns: status

idx_bufdir_report_storage_key
btree unique

Columns: storage_key

Validation Rules

period_dates_chronological error

Validation failed

organization_exists error

Validation failed

period_not_in_future error

Validation failed

format_is_valid_enum error

Validation failed

generated_by_has_membership error

Validation failed

period_minimum_duration error

Validation failed

validation_warnings_is_valid_json_array error

Validation failed

duplicate_in_progress_check error

Validation failed

report_data_schema_conformance error

Validation failed

Business Rules

authorized_roles_only
on_create

Only users with Coordinator, Organization Administrator, or Global Administrator roles may create or access Bufdir reports. Peer Mentor role is explicitly blocked. Enforced at the API layer before any database operation.

organization_scope_isolation
on_create

A report may only be generated for an organization that the requesting user belongs to with a sufficient role. Global Administrators may generate for any organization; Org Admins and Coordinators are restricted to their own organization_id.

full_hierarchy_inclusion
on_create

Report aggregation MUST include all local associations and regions under the organization, not just the requesting user's local association. The Report Aggregation Service traverses the full org hierarchy to ensure complete Bufdir submission coverage.

approved_activities_only
on_create

Only activities with approval_status = 'approved' are included in Bufdir report aggregation. Pending, flagged, or rejected activities are excluded. A pre-export validation warning is surfaced if significant unapproved activity count is detected.

status_transition_enforcement
on_update

Report status must follow the defined lifecycle: draft → generating → complete OR draft → generating → failed. Direct transitions skipping intermediate states are rejected. A 'complete' or 'failed' report cannot be moved back to 'generating'.

bufdir_field_completeness
on_update

Before finalizing a report as 'complete', all mandatory Bufdir reporting fields must be populated. The Bufdir Field Mapper validates required fields and blocks completion if any are missing. Missing optional fields produce warnings in validation_warnings.

organization_terminology_mapping
on_create

Each organization uses different terminology for activity types and contact categories. The Bufdir Field Mapper applies organization-specific label overrides from organization_labels to ensure field names in the exported file match the Bufdir schema regardless of internal terminology.

no_future_periods
on_create

A report cannot be generated for a reporting period whose end date is in the future. Partial-period generation is blocked to prevent submission of incomplete data to Bufdir.

storage_key_immutable_after_completion
on_update

Once a report reaches status = 'complete' and a storage_key is assigned, the storage_key must not be overwritten. A new report record must be created for any re-generation. This ensures audit trail integrity.

hierarchy_snapshot_on_creation
on_create

When a report is created, the current organizational hierarchy (organization, regions, local associations) is snapshotted into hierarchy_scope. This ensures the report remains reproducible and auditable even if the hierarchy changes after generation.

Storage Configuration

Storage Type
primary_table
Location
main_db
Partitioning
No Partitioning
Retention
Permanent Storage

Entity Relationships

organization
incoming one_to_many

An organization generates multiple Bufdir compliance reports across reporting periods

required