core PK: id 14 required 1 unique

Description

A logged interaction between a peer mentor and a contact — such as a home visit, phone call, group meeting, or event attendance. Activities are the primary unit of work tracked in Meander and form the basis for Bufdir reporting, expense reimbursements, and statistics.

25
Attributes
8
Indexes
8
Validation Rules
29
CRUD Operations

Data Structure

Name Type Description Constraints
id uuid Primary key, generated server-side
PKrequiredunique
organization_id uuid Foreign key to organizations — enforces multi-tenant data isolation
required
user_id uuid Foreign key to the peer mentor who performed (or is credited with) the activity. For proxy registrations this is the peer mentor, not the coordinator.
required
registered_by_user_id uuid Foreign key to the user who created the record. Equal to user_id for self-registered activities; set to coordinator's user_id for proxy/bulk registrations.
required
contact_id uuid Foreign key to the contact the activity was performed with. Nullable for group/organizational activities where no single contact applies.
-
activity_type_id uuid Foreign key to activity_types — classifies the kind of interaction (home visit, phone call, group meeting, etc.)
required
activity_date datetime Date and time the activity took place. Defaults to current date at time of registration. Stored in UTC.
required
duration_minutes integer Duration of the activity in minutes. Defaults to 30 when not explicitly set by the user.
required
summary text Free-text summary or notes describing what happened during the activity. Supports speech-to-text input. Marked as a sensitive field for screen reader warning.
-
location string Optional location description (e.g. 'Home visit', 'Phone call', 'Community centre'). Not a structured geocoordinate.
-
status enum Workflow status of the activity record
required
is_proxy boolean True when the activity was registered by a coordinator on behalf of a peer mentor
required
is_bulk boolean True when this record was created as part of a bulk registration batch
required
bulk_batch_id uuid References the batch_reference_repository batch ID when is_bulk = true. Null for individual registrations.
-
requires_reimbursement boolean Indicates whether any travel expense claim is attached to this activity. 60-70% of activities have no reimbursement claim per HLF data.
required
bufdir_reportable boolean Whether this activity should be included in Bufdir reports. Certain activity types or statuses may be excluded.
required
reporting_period_id uuid Optional link to a Bufdir reporting period. Set when the activity is included in a finalized Bufdir report.
-
flag_reason text Admin-entered reason when the activity has status = 'flagged'. Null otherwise.
-
rejection_reason text Coordinator or admin-entered reason when the activity is rejected during approval workflow.
-
approved_by_user_id uuid Foreign key to the user (coordinator or admin) who approved or rejected this activity. Null until reviewed.
-
approved_at datetime Timestamp when the activity was approved or rejected. Null until reviewed.
-
metadata json Flexible JSON bag for activity-type-specific fields, calendar event references, or speech-to-text session metadata. Schema varies by activity_type.
-
created_at datetime Record creation timestamp in UTC
required
updated_at datetime Record last-modified timestamp in UTC
required
deleted_at datetime Soft-delete timestamp. NULL means active record. Activities are never hard-deleted to preserve Bufdir audit trail.
-

Database Indexes

idx_activities_org_date
btree

Columns: organization_id, activity_date

idx_activities_user_date
btree

Columns: user_id, activity_date

idx_activities_contact
btree

Columns: contact_id

idx_activities_status
btree

Columns: organization_id, status

idx_activities_reporting_period
btree

Columns: reporting_period_id

idx_activities_bulk_batch
btree

Columns: bulk_batch_id

idx_activities_registered_by
btree

Columns: registered_by_user_id

idx_activities_deleted_at
btree

Columns: deleted_at

Validation Rules

activity_date_not_future error

Validation failed

duration_range error

Validation failed

activity_type_belongs_to_org error

Validation failed

contact_same_org error

Validation failed

user_same_org error

Validation failed

summary_sensitive_field_warning warning

Validation failed

status_transition_valid error

Validation failed

offline_conflict_resolution warning

Validation failed

Business Rules

tenant_isolation
always

Every activity query MUST be scoped by organization_id. Cross-organization data access is prohibited even for Global Admins reading operational data.

soft_delete_only
on_delete

Activities must never be hard-deleted. Set deleted_at to preserve Bufdir audit trail and historical statistics integrity.

proxy_registration_coordinator_only
on_create

is_proxy = true may only be set by users with Coordinator or Org Admin role. registered_by_user_id must differ from user_id in this case.

approval_workflow
on_create

Activities above organization-configured thresholds (e.g. with reimbursement or from proxy registration) transition to 'submitted' and require coordinator approval before becoming 'approved'. Activities under threshold auto-approve.

bufdir_locked_after_export
on_update

Once an activity is included in a finalized Bufdir report (reporting_period_id is set and period is closed), the record becomes immutable. Updates and deletes are blocked.

duplicate_detection
on_create

When a new activity is created, check for duplicate records with same user_id + contact_id + activity_date + activity_type_id within the same organization. Surface a warning to the registering user. Required by NHF to prevent coordinator double-reporting.

default_values_applied
on_create

If activity_date is not supplied, default to current date. If duration_minutes is not supplied, default to 30. These defaults are managed by DefaultValuesManager and configurable per organization.

bulk_batch_consistency
on_create

When is_bulk = true, bulk_batch_id must be present and reference a valid batch. All activities in a batch share the same activity_type_id and activity_date.

reimbursement_sync
always

When the last expense linked to this activity is deleted, requires_reimbursement must be set to false. When the first expense is linked, it must be set to true.

flag_requires_reason
on_update

Setting status = 'flagged' requires a non-empty flag_reason. Performed by coordinator or admin only.

Storage Configuration

Storage Type
primary_table
Location
main_db
Partitioning
by_date
Retention
Permanent Storage