Activity
Data Entity
Description
Core business record representing a peer mentor interaction or event, created through the accessible multi-step activity wizard. Captures the type, date, duration, participants, and summary of each peer mentor engagement. Is the primary data written by end users and the unit of measure for Bufdir reporting.
Data Structure
| Name | Type | Description | Constraints |
|---|---|---|---|
id |
uuid |
Primary key — system-generated UUID for the activity record | PKrequiredunique |
organization_id |
uuid |
Foreign key to the partner organization this activity belongs to; enforces multi-tenant data isolation via Supabase RLS | required |
peer_mentor_id |
uuid |
Foreign key to the peer mentor who is the primary actor and owner of this activity — the person whose contribution is being recorded, regardless of who entered the data | required |
activity_type_id |
uuid |
Foreign key to the organization-specific activity type catalogue entry; drives Bufdir category mapping, reimbursement eligibility, and report form requirements | required |
date |
datetime |
Date (and optionally time) on which the peer mentor activity took place; defaults to today in the wizard | required |
duration_minutes |
integer |
Duration of the activity in whole minutes; wizard presets 30 min but accepts custom entry | required |
contact_id |
uuid |
Optional foreign key to the contact (service recipient) associated with this activity; required for NHF multi-chapter duplicate detection and Blindeforbundet assignment tracking | - |
organization_unit_id |
uuid |
Foreign key to the organizational unit (chapter, region) from which this activity originates; used for hierarchical Bufdir aggregation and duplicate detection across NHF chapters | - |
notes |
text |
Optional free-text summary or notes entered by the peer mentor or coordinator; supports speech-to-text input; not required for quick registration | - |
created_by |
uuid |
Foreign key to the authenticated user who submitted this record; equals peer_mentor_id for self-registration and differs from it for proxy or coordinator bulk registration | required |
recorded_by_coordinator_id |
uuid |
Populated only for proxy and bulk registrations; holds the coordinator's user ID to provide an explicit dual-attribution audit trail distinct from created_by | - |
is_proxy |
boolean |
True when a coordinator submitted this record on behalf of a peer mentor; triggers the proxy audit badge in the UI and separates self-reported from proxy-reported data in Bufdir aggregation | required |
is_bulk |
boolean |
True when this record was created as part of a coordinator bulk-registration batch; used for audit reporting and deduplication analytics | required |
bulk_batch_id |
uuid |
Groups all activity records created in the same bulk-registration transaction; enables per-batch status reporting and rollback analysis | - |
duplicate_reviewed |
boolean |
Set to true when a user explicitly acknowledged a duplicate warning and chose to proceed; prevents the record from being flagged again in the coordinator deduplication queue | required |
duplicate_of_activity_id |
uuid |
Populated when the coordinator resolves a duplicate by merging; references the retained canonical activity record | - |
resolution_notes |
text |
Coordinator-entered explanation when resolving a flagged duplicate; stored for audit trail | - |
status |
enum |
Lifecycle status of the activity record | required |
bufdir_category_code |
string |
Cached Bufdir reporting category code resolved from the activity_type at submission time; stored to keep export consistent even if the mapping changes later | - |
has_expense |
boolean |
True when at least one expense record is linked to this activity; used as a quick filter for coordinator attestation queues and Bufdir export | required |
has_post_session_report |
boolean |
True when a structured post-session report has been submitted for this activity (Blindeforbundet); drives coordinator follow-up queue generation | required |
has_document_attachments |
boolean |
True when one or more document attachments are linked to this activity; relevant for NHF Bufdir evidence requirements | required |
created_at |
datetime |
UTC timestamp set automatically when the record is first persisted; immutable after creation | required |
updated_at |
datetime |
UTC timestamp updated automatically on any field change; maintained by a Supabase database trigger | required |
deleted_at |
datetime |
Soft-delete timestamp; non-null indicates the record is logically deleted and excluded from all standard queries and Bufdir aggregation | - |
Database Indexes
idx_activity_peer_mentor_id
Columns: peer_mentor_id
idx_activity_organization_id
Columns: organization_id
idx_activity_date
Columns: date
idx_activity_created_by
Columns: created_by
idx_activity_contact_id
Columns: contact_id
idx_activity_organization_unit_id
Columns: organization_unit_id
idx_activity_duplicate_check
Columns: peer_mentor_id, activity_type_id, date
idx_activity_org_date
Columns: organization_id, date
idx_activity_status_deleted_at
Columns: status, deleted_at
idx_activity_bulk_batch_id
Columns: bulk_batch_id
idx_activity_created_at
Columns: created_at
Validation Rules
required_fields_present
error
Validation failed
duration_positive_integer
error
Validation failed
date_not_excessively_future
error
Validation failed
activity_type_valid_and_active
error
Validation failed
peer_mentor_belongs_to_organization
error
Validation failed
contact_belongs_to_organization
error
Validation failed
notes_max_length
error
Validation failed
proxy_fields_consistent
error
Validation failed
bulk_requires_batch_id
error
Validation failed
duplicate_reviewed_flag_requires_prior_warning
error
Validation failed
Business Rules
proxy_dual_attribution
When a coordinator submits an activity on behalf of a peer mentor, both peer_mentor_id (the attributed actor) and recorded_by_coordinator_id (the submitting coordinator) must be set. is_proxy must be true. The peer mentor is credited for the activity in all statistics and Bufdir reporting; the coordinator identity is preserved solely for audit.
duplicate_detection_gate
Before persisting any activity, the system checks for an existing active record with the same peer_mentor_id, activity_type_id, and date. If a match is found, the submission is blocked and a warning is shown to the user. The user may choose to proceed (sets duplicate_reviewed = true), merge with the existing record, or cancel.
organization_data_isolation
Every activity record must carry the organization_id of the authenticated user's active tenant context. All read queries are automatically scoped to organization_id via Supabase Row Level Security, preventing cross-organization data leakage.
peer_mentor_active_status_required
Activities may only be created for peer mentors whose status is 'active'. Paused or expired-certification mentors cannot accumulate new activity records until they are reactivated. Coordinators registering in bulk must have duplicate-flagged or paused mentors filtered out before submission.
coordinator_proxy_permission_check
A coordinator may only proxy-register activities for peer mentors within their assigned organizational unit scope. The system validates that the target peer_mentor_id is under the acting coordinator's management before persisting.
bulk_pre_submission_deduplication
Before executing a bulk batch insert, the system runs duplicate detection for every mentor in the candidate list. Mentors with confirmed duplicate matches are excluded from the batch unless the coordinator explicitly overrides each conflict. The final batch only includes non-conflicting or coordinator-approved records.
bufdir_category_code_caching
At record creation time, the resolved Bufdir category code from the activity_type mapping is written into the bufdir_category_code column. This ensures Bufdir export results remain consistent even if the mapping configuration is later updated.
multi_chapter_cross_registration_duplicate_flag
For NHF contacts affiliated with multiple chapters, when a new activity is submitted referencing a contact_id, the system queries activities across all chapters that contact belongs to. If the same contact, activity type, and date appear in another chapter, a warning dialog is shown before allowing the coordinator to proceed.
soft_delete_only
Activity records are never physically deleted. Deletion sets status = 'deleted' and populates deleted_at. Soft-deleted records are excluded from all aggregate queries, statistics, and Bufdir exports, but remain in the database for audit purposes.
last_contact_date_propagation
When an activity is created for a peer mentor with an associated contact_id, the system updates the last_contact_date on the corresponding assignment record. This drives the reminder scheduler's inactivity window evaluation.
badge_evaluation_trigger
After each successful activity creation, a badge evaluation is triggered for the peer mentor to detect newly satisfied milestone criteria (e.g., 3rd assignment, 50th session).
CRUD Operations
Storage Configuration
Entity Relationships
Every activity record references the organization-specific activity type that determines its Bufdir category and reimbursement eligibility
An activity record may have multiple supporting document attachments (invitations, screenshots, flyers) for Bufdir audit evidence
A Blindeforbundet activity involving transportation may have one or more driver assignments linked to it
A travel-eligible activity may have exactly one linked expense claim covering all expense lines for that activity
An activity requiring a structured report (based on activity type metadata) has exactly one linked post-session report
Activities are recorded within a specific chapter context for chapter-level Bufdir aggregation and coordinator scope filtering
A peer mentor is the attributed actor for all activities they conduct, regardless of whether they self-registered or a coordinator registered on their behalf
A scenario prompt may reference the specific activity that triggered its generation, enabling deep-link navigation to the related activity record