core PK: id 8 required 1 unique

Description

A local chapter or branch within an organization — the primary operational unit for peer mentors and coordinators. Up to 1,400 local associations exist under the four organizations. All activity data, reimbursements, and user assignments are ultimately scoped to a local association.

17
Attributes
6
Indexes
8
Validation Rules
30
CRUD Operations

Data Structure

Name Type Description Constraints
id uuid Globally unique primary key for the local association record, generated server-side on creation.
PKrequiredunique
organization_id uuid Foreign key referencing the parent organization (NHF, Blindeforbundet, HLF, Barnekreftforeningen). Every local association belongs to exactly one organization. This is the multi-tenancy anchor for all data scoped through this entity.
required
region_id uuid Optional foreign key referencing the intermediate regional tier. NHF uses 9 regions; other organizations may not use regional grouping. Must reference a region that belongs to the same organization as this association.
-
name string Human-readable display name of the local association (e.g. 'NHF Oslo og Akershus'). Shown in selection lists, context switcher, reports, and all coordinator-facing views.
required
code string Short alphanumeric identifier for the local association, unique within its parent organization. Used in Bufdir report exports, accounting integrations (Xledger, Dynamics), and internal API references. Typically assigned during initial data seeding from existing organizational records.
required
status enum Operational status of the association. Active associations appear in selection lists and accept new activity registrations. Inactive associations are hidden from peer mentor selection but retain historical data. Archived associations are read-only for historical reporting only.
required
address string Street address of the local association's physical office or meeting place. Used optionally for geographic map display and coordinator context.
-
city string City where the local association operates. Used for geographic matching and display in map views for peer mentor assignment.
-
postal_code string Norwegian postal code (postnummer) for the association's primary location. 4-digit format. Feeds into geocoding for map-based peer mentor matching.
-
country string ISO 3166-1 alpha-2 country code. Defaults to 'NO' (Norway). Included for future internationalization readiness.
-
contact_email string Primary contact email address for the local association's administrative contact. Used for coordinator notifications and Bufdir-related correspondence.
-
contact_phone string Contact phone number for the local association. Stored as a string to accommodate international formatting and leading zeros.
-
honorarium_threshold_enabled boolean Whether this local association uses assignment-count-based honorarium threshold tracking (Blindeforbundet-specific). When true, the threshold_tracking_service monitors assignment counts and fires notifications at configured tier boundaries.
required
settings json Association-level configuration overrides stored as a JSONB object. May include local reporting preferences, feature flag overrides inherited from the parent organization, or Bufdir-specific field mappings. Falls back to parent organization settings when absent.
-
created_at datetime UTC timestamp when this local association record was first created. Immutable after creation.
required
updated_at datetime UTC timestamp of the most recent update to any field on this record. Automatically updated by the database on every write.
required
deleted_at datetime Soft-delete timestamp. When set, the association is excluded from all active queries, selection lists, and reporting. Historical data (activities, reimbursements, assignments) linked to this association is retained for Bufdir audit compliance.
-

Database Indexes

idx_local_association_organization_id
btree

Columns: organization_id

idx_local_association_region_id
btree

Columns: region_id

idx_local_association_org_code
btree unique

Columns: organization_id, code

idx_local_association_status
btree

Columns: status

idx_local_association_deleted_at
btree

Columns: deleted_at

idx_local_association_org_status
btree

Columns: organization_id, status

Validation Rules

name_required_and_bounded error

Validation failed

code_alphanumeric_format error

Validation failed

organization_id_references_existing_organization error

Validation failed

region_id_references_same_organization error

Validation failed

postal_code_norwegian_format error

Validation failed

contact_email_valid_format error

Validation failed

settings_valid_json_schema error

Validation failed

deleted_at_only_set_once error

Validation failed

Business Rules

single_organization_ownership
on_create

A local association must belong to exactly one organization and cannot be reassigned to a different organization after creation. The organization_id is immutable post-creation to preserve data scoping integrity across all linked activities, users, and reimbursements.

region_same_organization_constraint
on_create

When region_id is provided, the referenced region must belong to the same organization as the local association. Cross-organization region assignments are rejected to prevent hierarchy corruption.

code_unique_within_organization
on_create

The association code must be unique within its parent organization. The same code may exist across different organizations (e.g., two organizations may each have an association coded 'OSLO'). Enforced at the database level via a unique composite index on (organization_id, code).

soft_delete_only_when_no_active_dependencies
on_delete

A local association cannot be soft-deleted while it has active (non-deleted, non-paused) peer mentors, pending reimbursement claims, or open encrypted assignments linked to it. Coordinators must resolve all active dependencies before an association can be archived.

active_only_in_selection_lists
always

Only associations with status='active' and deleted_at=NULL are surfaced in user-facing selection lists (onboarding, association context switcher, proxy registration). Inactive and archived associations are hidden from selection but remain readable for historical reporting.

tenant_scoping_on_all_queries
always

Every query touching data scoped to a local association (activities, reimbursements, user roles, assignments) must include the local_association_id filter derived from the authenticated user's JWT claims or active context. The multi-tenancy infrastructure enforces this at the request middleware level.

max_five_associations_per_user
on_create

A single user may hold membership in at most five local associations simultaneously (NHF requirement). The membership service enforces this limit when adding new user_organization_role records linking a user to a new association.

honorarium_threshold_requires_configuration
on_update

When honorarium_threshold_enabled is set to true on a local association, at least one honorarium_threshold configuration record must exist for that association before assignment tracking can fire. The threshold tracking service validates this precondition before processing assignment count events.

status_change_audit_required
on_update

Any change to the status field (active → inactive, inactive → archived, etc.) must produce an audit log entry recording the actor, previous status, new status, and timestamp. Status changes cannot occur without an authenticated actor context.

bufdir_report_scoping
always

Bufdir reports aggregate activity data at the local association level before rolling up to region and organization. The report aggregation service must scope all activity counts to individual local associations and only then aggregate upward through the hierarchy. No cross-organization aggregation is permitted.

Storage Configuration

Storage Type
primary_table
Location
main_db
Partitioning
No Partitioning
Retention
Permanent Storage

Entity Relationships

activity
outgoing one_to_many

A local association owns all activities registered by its members, enabling team reports and Bufdir aggregation

required
event
outgoing one_to_many

A local association hosts many group events within its scope

required
honorarium_threshold
outgoing one_to_many

A local association configures its own honorarium threshold tiers for assignment-count-based compensation

optional
peer_mentor
outgoing one_to_many

A local association has many peer mentors operating within it

required
user_organization_role
outgoing one_to_many

A local association scopes user role assignments for coordinators and peer mentors operating within it

optional
organization
incoming one_to_many

An organization owns all its local associations directly, supporting direct org-to-association queries bypassing region

required
region
incoming one_to_many

A region contains multiple local associations (chapters/branches)

optional