Activity
Data Entity
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.
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
Columns: user_id
idx_activity_contact_id
Columns: contact_id
idx_activity_local_association_id
Columns: local_association_id
idx_activity_activity_type_id
Columns: activity_type_id
idx_activity_approval_status
Columns: approval_status
idx_activity_deleted_at
Columns: deleted_at
idx_activity_user_date
Columns: user_id, activity_date
idx_activity_assoc_date
Columns: local_association_id, activity_date
idx_activity_assoc_status
Columns: local_association_id, approval_status
idx_activity_duplicate_check
Columns: user_id, contact_id, activity_type_id, activity_date
idx_activity_registered_by
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
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
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
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
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
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
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
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
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
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
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.
CRUD Operations
Storage Configuration
Entity Relationships
An activity can have multiple file attachments (invitations, photos, PDFs) as supporting evidence
An activity may have associated travel and out-of-pocket expenses registered against it
An activity type classifies many activities and determines required fields and Bufdir mappings
A contact (person being supported) is the subject of many activities registered by peer mentors
A local association owns all activities registered by its members, enabling team reports and Bufdir aggregation
A user (peer mentor or coordinator acting as proxy) registers many activities