Annual Summary
Data Entity
Description
Derived aggregate of a peer mentor's activity, engagement, and impact metrics for a calendar year, powering the Spotify Wrapped-style 'Annual Summary (Wrapped)' feature in the Achievements & Gamification area.
Data Structure
| Name | Type | Description | Constraints |
|---|---|---|---|
id |
uuid |
Primary key | PKrequiredunique |
user_id |
uuid |
Foreign key to users table — the peer mentor this summary belongs to | required |
year |
integer |
Calendar year this summary covers (e.g. 2024) | required |
total_activities |
integer |
Total number of registered activities in the year | required |
total_hours |
decimal |
Total hours logged across all activities in the year | required |
total_contacts_reached |
integer |
Unique contacts the peer mentor interacted with during the year | required |
total_events_attended |
integer |
Number of events the peer mentor signed up for and attended | - |
activity_type_breakdown |
json |
Map of activity_type → count for the year, e.g. {"home_visit": 12, "phone_call": 40} | - |
monthly_activity_counts |
json |
Array of 12 integers representing activity count per month (index 0 = January) | - |
most_active_month |
integer |
Month number (1–12) with the highest activity count | - |
longest_streak_days |
integer |
Longest consecutive-day streak of activity registration in the year | - |
badges_earned_count |
integer |
Number of achievement badges earned during the year | - |
highlight_stat_key |
string |
Key identifying the single most impressive stat to surface as the hero metric on the Wrapped screen (e.g. 'total_activities', 'total_hours') | - |
highlight_stat_value |
string |
Formatted string value of the hero metric for display (e.g. '380') | - |
organization_id |
uuid |
Organization context at time of generation — ensures multi-tenant isolation | required |
generated_at |
datetime |
Timestamp when this summary was last computed | required |
is_final |
boolean |
True once the year has closed and the summary is locked; false while the year is still in progress (interim summary) | required |
created_at |
datetime |
Row creation timestamp | required |
updated_at |
datetime |
Row last-updated timestamp | required |
Database Indexes
idx_annual_summaries_user_year
Columns: user_id, year
idx_annual_summaries_user_id
Columns: user_id
idx_annual_summaries_organization_year
Columns: organization_id, year
Validation Rules
year_range_valid
error
Validation failed
non_negative_counts
error
Validation failed
monthly_array_length
error
Validation failed
user_exists
error
Validation failed
highlight_stat_consistency
warning
Validation failed
Business Rules
one_summary_per_user_per_year
Only one annual_summaries row may exist per (user_id, year) pair. Regeneration updates the existing row rather than inserting a new one.
interim_summary_allowed_current_year
For the current calendar year, is_final is false and the summary may be recomputed at any time. For past years, is_final is true and the row is immutable after finalization.
module_toggle_gate
Annual summaries may only be generated and displayed if the achievements-gamification module is enabled for the user's organization.
peer_mentor_only
Annual summaries are generated only for users with the Peer Mentor role. Coordinators and admins do not receive Wrapped summaries.
organization_isolation
A summary may only be read by the owning user or by a coordinator/admin within the same organization.