Bufdir Report
Data Entity
Description
Aggregated government funding compliance report submitted to Bufdir (Norwegian Directorate for Children, Youth and Family Affairs). One report per organization per reporting period, containing structured activity statistics required for grant documentation.
Data Structure
| Name | Type | Description | Constraints |
|---|---|---|---|
id |
uuid |
Primary key, generated server-side on report creation | PKrequiredunique |
organization_id |
uuid |
Foreign key to organizations table — identifies which tenant this report belongs to | required |
report_period_year |
integer |
Calendar year of the reporting period (e.g. 2024). Used for human-readable identification and unique constraint with organization_id | required |
report_period_start |
datetime |
Inclusive start timestamp of the reporting window (typically 01-01 of the year) | required |
report_period_end |
datetime |
Inclusive end timestamp of the reporting window (typically 31-12 of the year) | required |
status |
enum |
Lifecycle state of the report | required |
bufdir_schema_version |
string |
Version identifier of the Bufdir reporting schema used when generating report_data (e.g. '2024.1'). Ensures exports can be re-validated against the schema version active at generation time | required |
report_data |
json |
Full aggregated payload conforming to the Bufdir reporting schema: activity counts by type, peer mentor headcount, volunteer hours, unique contacts served, and all other mandatory Bufdir fields. Populated by report-data-aggregation-service at generation time | - |
activity_count |
integer |
Total number of approved activities included in this report period. Denormalized for fast KPI display without parsing report_data | - |
peer_mentor_count |
integer |
Number of distinct peer mentors with at least one registered activity in the period | - |
volunteer_hours_total |
decimal |
Sum of all logged activity durations in hours across the period. Bufdir requires this figure for grant calculation | - |
unique_contacts_count |
integer |
Number of distinct contacts (recipients of peer mentor support) served during the period | - |
validation_status |
enum |
Result of schema validation against the active Bufdir schema version | required |
validation_errors |
json |
Array of structured validation error objects (field path, code, message) produced when validation_status is 'invalid'. Null when valid or pending | - |
generated_at |
datetime |
Timestamp when report_data was last fully computed. Null for draft reports not yet generated | - |
generated_by |
uuid |
User ID of the org admin or coordinator who triggered report generation | - |
last_exported_at |
datetime |
Timestamp of the most recent successful export. Null if never exported. Used to drive export-history-list-widget display | - |
export_count |
integer |
Total number of times this report has been exported. Incremented on each successful export for rate-limiting and audit purposes | required |
notes |
text |
Optional free-text annotation by the org admin, e.g. notes about data corrections before submission | - |
created_at |
datetime |
Row creation timestamp, set server-side | required |
updated_at |
datetime |
Row last-modified timestamp, updated on every write | required |
Database Indexes
idx_bufdir_reports_org_year
Columns: organization_id, report_period_year
idx_bufdir_reports_organization_id
Columns: organization_id
idx_bufdir_reports_status
Columns: status
idx_bufdir_reports_period
Columns: report_period_start, report_period_end
idx_bufdir_reports_generated_by
Columns: generated_by
Validation Rules
required_bufdir_fields_populated
error
Validation failed
activity_count_consistency
error
Validation failed
volunteer_hours_non_negative
error
Validation failed
schema_version_recognized
error
Validation failed
report_period_year_matches_dates
error
Validation failed
organization_exists_and_active
error
Validation failed
Business Rules
one_report_per_org_per_year
Each organization may have at most one Bufdir report per calendar year. Enforced by the unique index on (organization_id, report_period_year). Attempting to create a second report for the same org/year returns a conflict error
export_requires_valid_status
A report may only be exported (triggering export-generation-service) when validation_status is 'valid'. Exports of invalid or pending reports are rejected
period_end_after_period_start
report_period_end must be strictly after report_period_start. Prevents zero-duration or inverted reporting windows
org_admin_only_generation
Only users with the Organization Admin role (scoped to the same organization) or Global Admin may create or regenerate a Bufdir report. Coordinators may view but not generate
immutable_after_submission
Once status transitions to 'submitted', the report_data and aggregated counters are locked. Any update attempt returns an error. A new report must be created to correct data (with notes documenting the amendment)
export_count_increment
Each successful export appends a row to export_logs and atomically increments export_count on the report record. Ensures audit trail and powers rate-limit checks
rate_limit_exports
No more than 5 exports per report per hour per organization to prevent abuse of the generation pipeline. export-rate-limiter checks export_count and last_exported_at before allowing generation
tenant_isolation
All read and write operations must be scoped to the requesting user's organization_id. Cross-organization report access is forbidden even for coordinators