derived PK: id 11 required 1 unique

Description

A pre-computed annual impact summary for a peer mentor covering the prior calendar year — total hours, contacts supported, activity count, streaks, and organizational percentile rankings. Powers the 'Peer Mentor Wrapped' feature. Generated by a batch job in January each year and supports shareable image/PDF export.

20
Attributes
5
Indexes
8
Validation Rules
13
CRUD Operations

Data Structure

Name Type Description Constraints
id uuid Primary key — unique identifier for the annual summary record
PKrequiredunique
user_id uuid Foreign key referencing the users table — the peer mentor this summary belongs to
required
peer_mentor_id uuid Foreign key referencing the peer_mentors table — enables fast lookup without joining through users for the Wrapped feature
required
organization_id uuid Foreign key referencing the organizations table — scopes percentile calculations to the correct organization
required
local_association_id uuid Foreign key referencing the local_associations table — scopes the summary to the peer mentor's active local association at year end
-
year integer The calendar year this summary covers (e.g. 2024). Always the prior calendar year relative to generation date.
required
total_activities integer Total number of approved activity records registered by the peer mentor during the calendar year
required
total_hours decimal Sum of activity durations in hours for the full calendar year, rounded to two decimal places
required
contacts_supported integer Count of distinct contacts the peer mentor had at least one approved activity with during the calendar year
required
activity_streaks json Streak metrics as a JSON object: { longest_streak_days, longest_streak_start, longest_streak_end, current_streak_days, total_active_weeks }
-
percentile_rank decimal Peer mentor's percentile rank (0.0–100.0) among all active peer mentors in their organization for total_hours during the year. NULL if fewer than 10 peers exist for statistical significance.
-
activity_type_breakdown json Breakdown of activity counts and hours by activity type: [{ activity_type_id, activity_type_name, count, hours }]
-
payload_json json Full structured slide payload for the Wrapped presentation layer. Contains ordered slide definitions with metric keys, display values, animation hints, and contextual copy. Consumed directly by Annual Summary Service to build slide sequences for Annual Summary Screen.
-
generation_status enum Tracks the status of the batch aggregation for this record
required
generation_error text Error message if generation_status is 'failed', for diagnostics and retry logic
-
viewed_at datetime Timestamp of the peer mentor's first view of their annual summary. NULL until first opened. Set once and never updated again.
-
share_image_key string Object storage key for the generated shareable PNG card. NULL until share is first triggered. Used by Summary Share Asset Service to generate signed GET URLs.
-
share_pdf_key string Object storage key for the generated shareable PDF export. NULL until PDF export is first triggered.
-
created_at datetime Timestamp when the record was first created by the batch aggregation job
required
updated_at datetime Timestamp of the last modification — updated on upsert reruns, viewed_at writes, and share asset key updates
required

Database Indexes

idx_annual_summary_user_year
btree unique

Columns: user_id, year

idx_annual_summary_peer_mentor_year
btree unique

Columns: peer_mentor_id, year

idx_annual_summary_year_org
btree

Columns: year, organization_id

idx_annual_summary_generation_status
btree

Columns: generation_status

idx_annual_summary_created_at
btree

Columns: created_at

Validation Rules

year_range_valid error

Validation failed

metrics_non_negative error

Validation failed

percentile_rank_bounds error

Validation failed

user_id_peer_mentor_relationship error

Validation failed

activity_streaks_schema warning

Validation failed

payload_json_slide_schema warning

Validation failed

share_asset_key_format error

Validation failed

generation_status_transition error

Validation failed

Business Rules

one_summary_per_user_per_year
on_create

Each peer mentor may have at most one annual summary record per calendar year. The batch job uses UPSERT semantics — rerunning aggregation for a year overwrites the existing record rather than creating a duplicate.

peer_mentor_only
on_create

Annual summaries are generated exclusively for users who have an active peer_mentors profile. Users with only Coordinator, Organization Administrator, or Global Administrator roles do not receive annual summaries.

prior_year_only
on_create

The batch aggregation job only generates summaries for the prior completed calendar year. Summaries for the current or future year are never created. The year field must be less than the current calendar year.

approved_activities_only
on_create

Only activities with approval_status = 'approved' are counted toward total_activities, total_hours, and contacts_supported. Pending or flagged activities are excluded to ensure Bufdir-compliant accuracy.

percentile_minimum_cohort
on_create

percentile_rank is only computed when the organization has at least 10 active peer mentors for the given year. Below this threshold, the field is set to NULL to avoid misleading comparisons from statistically insignificant cohorts.

viewed_at_immutable_after_set
on_update

Once viewed_at is written on the peer mentor's first view, it must never be overwritten. Subsequent views of the summary do not update the timestamp.

payload_immutable_after_complete
on_update

Once generation_status transitions to 'complete', the payload_json and all aggregated metric fields (total_activities, total_hours, contacts_supported, activity_streaks, percentile_rank) become read-only except during an explicit admin-triggered recomputation. This preserves the historical integrity of the Wrapped experience.

share_assets_privacy_masking
on_update

Generated share images and PDFs (share_image_key, share_pdf_key) must exclude all personally identifiable contact information. Only aggregate metrics (hours, activity counts, percentile) are rendered in shareable assets. The Summary Share Asset Service enforces this before uploading to object storage.

january_generation_schedule
always

The Annual Summary Scheduler triggers the aggregation job annually in January via cron. If the job fails, automatic retry with exponential backoff is applied up to 3 times before alerting. Manual re-trigger is supported via admin API.

multi_association_deduplication
on_create

For NHF peer mentors who belong to multiple local associations (up to 5), activities are attributed to the local_association_id recorded on each activity record. The summary aggregates across all associations but the percentile_rank is computed within the peer mentor's primary organization.

Storage Configuration

Storage Type
primary_table
Location
main_db
Partitioning
by_date
Retention
Permanent Storage

Entity Relationships

peer_mentor
incoming one_to_many

A peer mentor profile links to its annual summaries enabling quick lookup for the Wrapped feature

optional
user
incoming one_to_many

A user has one annual summary per calendar year computed by the batch aggregation job

required