core PK: id 10 required 1 unique

Description

The central operational record representing a peer mentoring interaction — a visit, phone call, group session, or any contact between a peer mentor and one or more persons they support. Activities are the primary source of data for Bufdir reports, statistics, and coordinator oversight. Supports offline creation with background sync.

20
Attributes
11
Indexes
9
Validation Rules
37
CRUD Operations

Data Structure

Name Type Description Constraints
id uuid Globally unique identifier for the activity record. Generated client-side (UUIDv4) to support offline creation before server sync.
PKrequiredunique
user_id uuid The peer mentor who performed the activity. Foreign key to users table. In proxy registrations, this is the peer mentor on whose behalf the activity is recorded — not the coordinator who submitted it.
required
contact_id uuid The person being supported — the beneficiary of the peer mentoring interaction. Nullable for group events or activities without a specific individual contact (e.g., group sessions tracked under an event instead).
-
local_association_id uuid The local association (chapter/branch) under which this activity is registered. Determines team report scope, Bufdir aggregation hierarchy, and coordinator visibility. Must match one of the peer mentor's active memberships.
required
activity_type_id uuid The classification of the activity (e.g., home visit, phone call, group meeting). Foreign key to activity_types. Determines which fields are required, whether a home visit report structure is triggered, and how data maps to Bufdir reporting fields.
required
activity_date datetime The date and time the peer mentoring activity took place. Stored as UTC timestamp with timezone offset. Must not be in the future. Defaults to current date/time in the simple logging flow.
required
duration_minutes integer Length of the activity in whole minutes. Defaults to 30 minutes per organization configuration. Must be a positive integer. Used in Bufdir reporting aggregations and personal statistics.
required
registered_by uuid The user ID of the coordinator who submitted this activity on behalf of the peer mentor. Null when the peer mentor registered the activity themselves. Set by the proxy registration service. Used in audit trail and Bufdir compliance verification.
-
approval_status enum The coordinator review status of this activity. Defaults to 'pending' on creation. Transitions are managed by the activity oversight service with immutable audit log entries written for every change.
required
notes text Free-text notes entered by the peer mentor during or after the activity. Used for qualitative context in Bufdir reports and coordinator oversight. Supports speech-to-text input. Not end-to-end encrypted — sensitive information should use the encrypted assignment system instead.
-
home_visit_report json Structured home visit report data collected via the Structured Report Form Screen (Blindeforbundet-specific). Contains fields for health status, course interest, assistive device needs, and 'way forward' coordinator task items. Null for non-home-visit activity types.
-
is_proxy_registration boolean Denormalized flag indicating whether this activity was submitted by a coordinator on behalf of a peer mentor. Derived from registered_by != null but stored explicitly for efficient filtering in team reports and audit queries.
required
duplicate_of_activity_id uuid If the user confirmed submission despite a duplicate warning, this field references the conflicting activity ID for audit purposes. Null for activities with no detected duplicate at submission time.
-
sync_status enum Client-side sync state tracking for offline-first operation. Managed by the mobile Flutter app's local SQLite database. Not persisted server-side — server always treats received records as authoritative.
-
approval_note text Optional coordinator review note attached when approving, flagging, or rejecting an activity. Captured via the Approval Workflow Screen. Stored on the activity for direct visibility without joining audit_logs.
-
approved_by uuid User ID of the coordinator who last changed the approval status. Written alongside approval_status updates for direct query access without joining audit_logs.
-
approved_at datetime Timestamp of the most recent approval status change. UTC. Used in Bufdir report date filtering and coordinator oversight sorting.
-
created_at datetime Server-side creation timestamp in UTC. Set on first successful server write. Distinct from activity_date (when the activity happened). Used for audit trails and duplicate detection time windows.
required
updated_at datetime Timestamp of last server-side update in UTC. Managed by the database trigger or ORM. Used for conflict resolution during offline sync.
required
deleted_at datetime Soft-delete timestamp. Null for active records. Set on deletion rather than hard-deleting rows, preserving audit trail integrity and Bufdir historical data.
-

Database Indexes

idx_activity_user_id
btree

Columns: user_id

idx_activity_contact_id
btree

Columns: contact_id

idx_activity_local_association_id
btree

Columns: local_association_id

idx_activity_activity_type_id
btree

Columns: activity_type_id

idx_activity_approval_status
btree

Columns: approval_status

idx_activity_deleted_at
btree

Columns: deleted_at

idx_activity_user_date
btree

Columns: user_id, activity_date

idx_activity_assoc_date
btree

Columns: local_association_id, activity_date

idx_activity_assoc_status
btree

Columns: local_association_id, approval_status

idx_activity_duplicate_check
btree

Columns: user_id, contact_id, activity_type_id, activity_date

idx_activity_registered_by
btree

Columns: registered_by

Validation Rules

duration_positive_integer error

Validation failed

activity_type_id_exists error

Validation failed

contact_id_role_scoped error

Validation failed

notes_max_length error

Validation failed

approval_note_max_length error

Validation failed

home_visit_report_json_schema error

Validation failed

uuid_format error

Validation failed

activity_date_iso8601 error

Validation failed

local_association_tenant_match error

Validation failed

Business Rules

activity_date_not_future
on_create

An activity cannot be registered with a date in the future. activity_date must be less than or equal to the current UTC timestamp at the time of submission. This prevents pre-registration and ensures statistical accuracy.

user_must_belong_to_local_association
on_create

The peer mentor identified by user_id must have an active membership (user_organization_roles record) for the specified local_association_id. Prevents cross-association data contamination in a multi-tenancy context.

proxy_registration_requires_coordinator_role
on_create

When registered_by is set (proxy registration), the submitting user must hold a Coordinator or higher role in the same local association. Peer mentors cannot register activities on behalf of other peer mentors.

default_approval_status_pending
on_create

All newly created activities are set to approval_status = 'pending'. Auto-approval is not applied to activities (only to expenses). Coordinators must explicitly approve activities via the oversight workflow.

soft_delete_only
on_delete

Activities must never be hard-deleted. Setting deleted_at preserves audit trail integrity and historical Bufdir data. Any delete operation sets deleted_at to now() and excludes the record from all standard queries via a WHERE deleted_at IS NULL filter.

approval_status_transition_requires_coordinator
on_update

Only users with Coordinator or higher role for the activity's local_association_id may change approval_status. Peer mentors cannot approve or reject their own activities.

audit_log_on_status_change
on_update

Every change to approval_status must produce an immutable audit_log entry capturing the actor user ID, previous status, new status, timestamp, and optional note. This is required for Bufdir compliance verification.

duplicate_detection_on_submit
on_create

Before persisting a new activity, the system checks for potential duplicates using the same (user_id, contact_id, activity_type_id) combination within a ±1-day fuzzy window scoped to the local_association_id. If a duplicate is detected, the user is warned. Submission is allowed if the user explicitly confirms.

home_visit_report_required_for_home_visit_type
on_create

When activity_type_id maps to a home visit type (as classified by home-visit-activity-type-detector), the home_visit_report JSON field must be populated with a valid structured report before submission. Enforced by the wizard step injection logic.

multi_association_scope_isolation
always

For NHF users who belong to multiple local associations (up to 5), the activity's local_association_id determines its scope. Activities are never visible across association boundaries except to Coordinators and Org Admins with multi-association access.

Storage Configuration

Storage Type
primary_table
Location
main_db
Partitioning
by_date
Retention
Permanent Storage

Entity Relationships

document
outgoing one_to_many

An activity can have multiple file attachments (invitations, photos, PDFs) as supporting evidence

optional cascade delete
expense
outgoing one_to_many

An activity may have associated travel and out-of-pocket expenses registered against it

optional
activity_type
incoming one_to_many

An activity type classifies many activities and determines required fields and Bufdir mappings

required
contact
incoming one_to_many

A contact (person being supported) is the subject of many activities registered by peer mentors

optional
local_association
incoming one_to_many

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

required
user
incoming one_to_many

A user (peer mentor or coordinator acting as proxy) registers many activities

required

Components Managing This Entity

infrastructure Auth Middleware ["backend"] service Role Guard Service ["mobile"] data Activity Repository ["mobile"] infrastructure Activity BLoC ["mobile"] service Activity Service ["mobile"] data Activity Repository ["mobile"] service Activity Service ["mobile"] service Wizard State Manager ["mobile"] service Proxy Registration Service ["mobile","backend"] infrastructure Home Visit Activity Type Detector ["mobile"] service Role Guard Service ["mobile"] ui Contact Detail Screen ["mobile"] data Statistics Repository ["mobile"] infrastructure Statistics API Endpoint ["backend"] service Statistics Service ["mobile"] data Team Report Repository ["backend"] service Team Report Service ["mobile","backend"] data Bufdir Report Repository ["backend"] service Bufdir Report Service ["backend"] service Report Aggregation Service ["backend"] service Duplicate Detection Service ["backend"] ui Duplicate Warning Widget ["mobile"] service Reminder Service ["backend"] data Calendar Sync Repository ["backend"] service Calendar Integration Service ["mobile","backend"] data Dashboard Repository ["mobile"] service Dashboard Service ["mobile"] ui Home Screen (Coordinator) ["mobile"] ui Home Screen (Peer Mentor) ["mobile"] data Analytics Repository ["backend"] service Analytics Service ["backend"] data Activity Approval Repository ["backend"] service Activity Oversight Service ["backend"] service Oversight Audit Log Service ["backend"] data Bufdir Report Repository ["backend"] infrastructure Multi-Tenancy Infrastructure ["backend","frontend","mobile"] infrastructure Association Context Middleware ["backend"] service Annual Summary Aggregation Job ["backend"] service Annual Summary Service ["mobile","backend"] service Statistics Service ["backend"] service Advantage Calculation Service ["mobile"] data Local Cache Repository ["mobile"]