Bufdir Column Schema
Data Entity
Description
Stores the per-organization mapping from internal activity fields to official Bufdir export column names, date formats, and decimal separators. Versioned so schema changes do not break historical report regeneration. Organizations may override default mappings where their activity terminology differs from the Bufdir standard column set.
Data Structure
| Name | Type | Description | Constraints |
|---|---|---|---|
id |
uuid |
Primary key — surrogate UUID generated on insert | PKrequiredunique |
organization_id |
uuid |
Foreign key to the organization this schema belongs to. NULL indicates the system-wide default schema used when no org-specific override exists. | - |
version |
integer |
Monotonically increasing version number scoped per organization_id. Version 1 is the initial schema; each structural change increments by 1. Historical reports reference this version to reproduce the exact column layout used at export time. | required |
column_mappings |
json |
JSONB object mapping internal activity field keys to their official Bufdir export column names. Each entry has the shape { internal_field: string, bufdir_column: string, transform: string|null }. The transform field holds an optional value-transformation expression (e.g. uppercase, date reformat). Required Bufdir columns not covered by internal fields may carry a static_value override. | required |
date_format |
string |
Date format string applied to all date-type fields during serialization. Must be a valid Java/Unicode date pattern (e.g. 'dd.MM.yyyy'). Defaults to 'dd.MM.yyyy' per Norwegian Bufdir conventions. | required |
decimal_separator |
enum |
Decimal separator character used in numeric export fields. Bufdir's standard template uses comma; some accounting integrations require period. | required |
is_active |
boolean |
Marks this as the currently active schema version for its organization. Only one row per organization_id may have is_active = true. The system default row (organization_id IS NULL) may also have is_active = true independently. | required |
is_default |
boolean |
True when this row represents the system-wide default schema (organization_id IS NULL). Exactly one default row should exist at any time. Org-specific schemas inherit and override the default. | required |
parent_version_id |
uuid |
Self-referential FK to the schema row this version was derived from. NULL for the initial version of a schema. Enables diff computation between versions for audit and preview UI. | - |
notes |
text |
Human-readable description of what changed in this version relative to the previous one. Displayed in the admin interface version history panel. | - |
created_by |
uuid |
User ID of the administrator who created this schema version. References Supabase auth.users. NULL for system-generated default schemas. | - |
created_at |
datetime |
UTC timestamp when this schema version was created. Immutable after insert. | required |
updated_at |
datetime |
UTC timestamp of the last modification to any mutable field (notes, is_active). Updated via trigger on row change. | required |
Database Indexes
idx_bufdir_column_schema_org_version
Columns: organization_id, version
idx_bufdir_column_schema_org_active
Columns: organization_id, is_active
idx_bufdir_column_schema_default
Columns: is_default
idx_bufdir_column_schema_parent
Columns: parent_version_id
idx_bufdir_column_schema_created_at
Columns: organization_id, created_at
Validation Rules
column_mappings_valid_json
error
Validation failed
date_format_valid_pattern
error
Validation failed
decimal_separator_enum_value
error
Validation failed
organization_id_exists
error
Validation failed
no_duplicate_bufdir_columns
error
Validation failed
notes_max_length
error
Validation failed
version_positive_integer
error
Validation failed
is_default_organization_null_consistency
error
Validation failed
Business Rules
single_active_schema_per_org
At most one schema row per organization_id may have is_active = true at any time. When a new version is activated, the previous active version must be deactivated in the same transaction to prevent split-brain export behavior.
version_monotonic_increase
The version number for a given organization_id must always be strictly greater than the highest existing version for that organization. This ensures the version history is append-only and unambiguous.
active_schema_not_deletable
A schema row with is_active = true cannot be deleted. The caller must first activate a replacement version, which automatically deactivates the current one, before deletion is permitted.
default_schema_always_present
At all times exactly one row with is_default = true and organization_id IS NULL must exist. This row acts as the fallback when an organization has no override. Deletion of the default row is blocked unless a replacement default exists.
org_schema_inherits_default
When creating a new org-specific schema, if no column_mappings are provided for a given required Bufdir field, the system inherits the mapping from the current active default schema. The resulting merged mapping is stored explicitly to ensure historical reproducibility.
historical_export_version_lock
An export audit record references this entity by id (not organization_id + is_active). Once an export has been generated and its audit record created, the referenced schema row must never be mutated — only new versions may be created.
required_bufdir_columns_covered
Before a schema version can be set as active, the column_mappings must cover all mandatory Bufdir column names as defined in the integration type registry. Activation is blocked if any mandatory column is unmapped and has no static_value fallback.
CRUD Operations
Storage Configuration
Entity Relationships
Each organization has one active Bufdir column schema that maps internal fields to official Bufdir export columns