Activity
Data Entity
Description
A logged interaction between a peer mentor and a contact — home visit, phone call, meeting, group event, or other support activity. The primary operational record of peer mentor work, driving Bufdir reporting, statistics, reimbursement, and oversight workflows.
Data Structure
| Name | Type | Description | Constraints |
|---|---|---|---|
id |
uuid |
Primary key, generated on client for offline-first creation | PKrequiredunique |
organization_id |
uuid |
Tenant isolation — the organization this activity belongs to | required |
user_id |
uuid |
The peer mentor who performed the activity (author of record) | required |
proxy_reporter_id |
uuid |
Coordinator who registered this activity on behalf of the peer mentor (null if self-reported) | - |
contact_id |
uuid |
The contact (person receiving support) this activity was performed for. Null for group activities with no single contact. | - |
activity_type_id |
uuid |
Foreign key to activity_types — categorizes the kind of interaction | required |
activity_date |
datetime |
Date and time the activity actually took place (not when it was registered) | required |
duration_minutes |
integer |
Duration of the activity in minutes. Default 30. | required |
summary |
text |
Free-text summary of the activity content, entered by the peer mentor. May be dictated via speech-to-text. | - |
status |
enum |
Lifecycle state of the activity record | required |
is_proxy_reported |
boolean |
True if a coordinator registered this activity on behalf of the peer mentor | required |
is_bulk_registration |
boolean |
True if created via bulk registration flow (coordinator registering multiple at once) | required |
has_expense |
boolean |
True if a reimbursement expense is linked to this activity. Denormalized for fast query. | required |
has_report |
boolean |
True if a formalized home-visit report (activity_reports) is linked. Denormalized for fast query. | required |
has_attachments |
boolean |
True if one or more document attachments (activity_attachments) are linked. Denormalized. | required |
location |
string |
Optional free-text location description (e.g. 'Home visit', 'Telephone', 'Community center') | - |
participant_count |
integer |
Number of participants for group activities. Null for 1:1 interactions. | - |
approval_status |
enum |
Administrative approval state, separate from lifecycle status | required |
approved_by_user_id |
uuid |
Coordinator or admin who approved the activity. Null if auto-approved or pending. | - |
approved_at |
datetime |
Timestamp of approval action | - |
rejection_reason |
text |
Admin-provided reason if activity was rejected. Required when approval_status = rejected. | - |
flag_reason |
text |
Reason text when activity is flagged for review by an admin | - |
flagged_by_user_id |
uuid |
Admin or coordinator who flagged the activity | - |
duplicate_of_activity_id |
uuid |
References the canonical activity if this record is identified as a duplicate | - |
bufdir_eligible |
boolean |
Whether this activity qualifies for inclusion in Bufdir grant reports, determined by activity type and org configuration | required |
source |
enum |
How the activity was created — for audit and analytics | required |
offline_created |
boolean |
True if the activity was first created offline and synced later | required |
client_created_at |
datetime |
Timestamp when the record was created on the client device (may predate server created_at due to offline queue) | required |
metadata |
json |
Extensible JSON bag for org-specific fields, calendar event IDs, STT transcript references, and future extensions | - |
created_at |
datetime |
Server-side record creation timestamp | required |
updated_at |
datetime |
Last server-side update timestamp | required |
Database Indexes
idx_activities_org_user_date
Columns: organization_id, user_id, activity_date
idx_activities_org_status
Columns: organization_id, status
idx_activities_org_approval_status
Columns: organization_id, approval_status
idx_activities_contact_id
Columns: contact_id
idx_activities_activity_type_id
Columns: activity_type_id
idx_activities_activity_date
Columns: activity_date
idx_activities_bufdir_eligible
Columns: organization_id, bufdir_eligible, activity_date
idx_activities_duplicate_of
Columns: duplicate_of_activity_id
idx_activities_created_at
Columns: created_at
Validation Rules
duration_positive_integer
error
Validation failed
activity_type_exists_in_org
error
Validation failed
contact_belongs_to_org
error
Validation failed
summary_required_for_formalized_report_type
error
Validation failed
participant_count_required_for_group_type
error
Validation failed
client_created_at_not_future
error
Validation failed
metadata_valid_json
error
Validation failed
approved_by_required_when_approved
error
Validation failed
Business Rules
activity_date_not_future
An activity cannot be logged with a date in the future. Peer mentors register activities after they happen.
proxy_reporter_must_be_coordinator
If proxy_reporter_id is set, that user must hold the Coordinator or Org Admin role within the same organization.
tenant_isolation
All reads and writes are scoped to organization_id. A user may only access activities belonging to their own organization.
duplicate_detection_on_submit
On status transition to 'submitted', the system checks for near-duplicate activities (same user_id, contact_id, activity_type_id, activity_date ± 60 minutes) and flags them for coordinator review.
approval_required_for_expense_reimbursement
If has_expense is true, the activity must reach approval_status = 'approved' before the linked expense can be processed for reimbursement.
bulk_registration_peer_mentor_scope
Bulk-registered activities (is_bulk_registration = true) must all belong to peer mentors within the coordinator's own organization.
bufdir_eligibility_derived_from_type
bufdir_eligible is computed from the linked activity_type's bufdir_reportable flag at create time. It may be overridden by an Org Admin.
rejection_requires_reason
Setting approval_status = 'rejected' requires rejection_reason to be non-null and non-empty.
status_transition_forward_only
Status transitions follow a directed graph: draft → submitted → approved/rejected/flagged. Approved or rejected activities cannot revert to draft without an explicit admin correction action that creates an audit entry.
offline_sync_id_deduplication
Activities created offline use client-generated UUIDs. On sync, the server detects duplicate UUIDs and returns the existing record rather than creating a second row.
audit_trail_on_admin_action
Any approval, rejection, flagging, or duplicate-marking action by an admin or coordinator is written to audit_logs with the acting user_id, action, and timestamp.