Annual Summary
Data Entity
Description
Derived yearly aggregate of a peer mentor's activity, storing the computed snapshot data that powers the Annual Summary (Wrapped) screen — total activities, hours, contacts reached, badges earned, and highlighted moments for the calendar year.
Data Structure
| Name | Type | Description | Constraints |
|---|---|---|---|
id |
uuid |
Primary key | PKrequiredunique |
user_id |
uuid |
FK to users — the peer mentor this summary belongs to | required |
organization_id |
uuid |
FK to organizations — tenant scoping for multi-org isolation | required |
year |
integer |
Calendar year this summary covers (e.g. 2024) | required |
total_activities |
integer |
Total number of logged activities for the year | required |
total_hours |
decimal |
Sum of all activity durations in hours for the year | required |
total_contacts_reached |
integer |
Distinct contacts the peer mentor interacted with during the year | required |
total_events_attended |
integer |
Number of events the user participated in during the year | required |
badges_earned_count |
integer |
Number of achievement badges earned during the year | required |
top_activity_type |
string |
Slug of the activity type logged most frequently during the year | - |
most_active_month |
integer |
Month number (1–12) with the highest activity count | - |
streak_days |
integer |
Longest consecutive-day streak of activity logging during the year | - |
highlight_moments |
json |
Array of up to 5 curated highlight objects {type, date, description} for the wrapped story display | - |
monthly_activity_counts |
json |
Array of 12 integers representing activity counts per month (index 0 = January) | - |
generation_status |
enum |
Lifecycle state of this summary record | required |
generated_at |
datetime |
Timestamp when the summary was last successfully computed | - |
viewed_at |
datetime |
Timestamp when the peer mentor first opened their wrapped summary | - |
created_at |
datetime |
Record creation timestamp | required |
updated_at |
datetime |
Last update timestamp (set on recomputation) | required |
Database Indexes
idx_annual_summaries_user_year
Columns: user_id, year
idx_annual_summaries_org_year
Columns: organization_id, year
idx_annual_summaries_status
Columns: generation_status
Validation Rules
year_range_valid
error
Validation failed
non_negative_counts
error
Validation failed
monthly_counts_array_length
error
Validation failed
highlight_moments_max_five
warning
Validation failed
org_tenant_matches_user
error
Validation failed
Business Rules
one_summary_per_user_per_year
Each user may have at most one annual_summaries record per calendar year. The unique index on (user_id, year) enforces this; recomputation updates the existing row rather than inserting a new one.
only_peer_mentor_role_generates_summary
Annual summaries are generated only for users holding the Peer Mentor role. Coordinators and admins do not receive wrapped summaries.
module_toggle_gate
Summary generation and display are only available when the achievements-gamification module is enabled for the user's organization. The annual-summary-screen must check the module registry before rendering.
year_boundary_completeness
A summary for the current year may only transition to status=ready after December 31 of that year, or may be generated as a year-to-date preview flagged in highlight_moments. Partial-year summaries must not claim to be full-year totals.
recomputation_on_data_correction
If activities for a given year are corrected, deleted, or added retroactively, the corresponding annual_summaries row must be marked generation_status=pending and re-queued for recomputation.