sac-member-enrollment-widget

AE Member Enrollment — SAC Custom Widget (“Snap” report)

A custom widget for SAP Analytics Cloud rendering the Member Enrollment executive/leadership “Snap” dashboard: Set Up/Completed counts by Wave, a headline Enrollment Status breakdown, Defaulted broken out by Wave 1/Wave 2a, a multiple-attempts count, and a combined bar+cumulative- line daily timeline. This is one of a 3-widget suite (see GOLD_VIEW_SPEC.md §10l) mirroring the Employer Election suite’s structure — this widget plays the same role as AE Snap Report does there. The fuller Enrollment-Status-per-Wave breakdown, election-detail metrics (HSA/FSA/ Supp Life/Retirement/Vision), and the waiver-trend-by-membership-type metric live on the sibling sac-member-operational-widget instead; per-member row detail lives on sac-member-detail-widget.

Design doc: ../ae-member-enrollment-report/GOLD_VIEW_SPEC.md defines the Gold-layer dataset. BUILD_PLAN_FOR_BLAIR.md’s “SUPERSEDED — consolidated into ONE aggregate cube” section has the current authoritative cube SQL and architecture — this widget binds to a single consolidated Analytic Model (AM_MEMBER_ENROLLMENT_SUMMARY) shared with sac-member-operational-widget, not two separate cubes as originally designed. That redesign happened 2026-09-30 after discovering a SAC custom widget can only bind to one Analytic Model total, no matter how many named dataBindings its widget.json declares.

FLEX members are excluded (v1.5.0, 2026-10-05)

GLD_AE_Member_Enrollment is shared with the FLEX dashboard (sac-flex-member-widget). FLEX members carry Wave “Group A”–”Group F”, and this widget drops any row whose Wave starts with Group , next to its Portico exclusion. Blank-Wave rows are kept, so Traditional numbers don’t change. In a headless check, output was byte-identical with and without FLEX rows injected. Gold’s Employer column is also no longer NULL: it now holds “Name (Number)”. Details: ../flex-member-enrollment-report/GOLD_CHANGES.md.

Two lessons carried over from the start, not discovered the hard way again

The Employer Selections widget went through a real debugging cycle to learn that SAC’s Optimized-story View mode doesn’t deliver internal click/change events to a custom widget’s shadow DOM. This widget applies that lesson from day one:

Files

Data bindings — what it expects

One binding, aggregateData, shared with sac-member-operational- widget — both bind to the same AM_MEMBER_ENROLLMENT_SUMMARY model, each filtering client-side by a RowKind discriminator dimension. This widget only reads two row-kinds (StatusByWave and DailyTrend); the other two (ElectionSummary, WaiverTrend) exist on the same model for Operational’s use. See main.js’s own header comment for the exact dimension/measure order (SAC binds by position, not name — order matters when binding in the SAC Builder panel: Measures before Dimensions, then each list in the documented order).

Never Gold-layer member-level rows directly (Gold is one row per Member — this widget only ever sees counts). See BUILD_PLAN_FOR_BLAIR.md’s “SUPERSEDED — consolidated into ONE aggregate cube” section for the full cube SQL and design.

Status of this build

Next steps

  1. ✅ Done (2026-10-03): native SAC Input Controls for Wave (priority) and Enrollment_Status exist on this page, wired to the same model — not built into the widget, per the lesson above. They are safe here because the cube carries a real value for those dimensions in every row-kind (see BUILD_PLAN_FOR_BLAIR.md’s cube design rule). Never add an EventDate control — the YoY timeline/waiver panels need both cycles.
  2. Once BR-29 (see BUILD_PLAN_FOR_BLAIR.md) is confirmed fixed and the vDimMember join is restored in Gold, TotalEligibleLives/ TotalCoveredLives will start populating for real — no widget change needed, they’re already wired up as placeholders.