sac-member-operational-widget

AE Member Enrollment Operational Dashboard — SAC Custom Widget

A custom widget for SAP Analytics Cloud rendering the Member Enrollment working-team/operational dashboard: the full Enrollment Status breakdown by Wave (all five statuses, not just Set Up/Completed), election-detail counts and averages (HSA/FSA/Supplemental Life/ Retirement/Vision), and a waiver trend by membership type (Sponsored vs. Retired). This is the second widget of a 3-widget suite (see ../ae-member-enrollment-report/GOLD_VIEW_SPEC.md §10l) mirroring the Employer Election suite’s structure — this widget plays the same role AE Employer Election Operational does there. Headline leadership tiles live on the sibling AE Member Enrollment (Snap) instead; per-member row detail lives on sac-member-detail-widget.

Design doc: GOLD_VIEW_SPEC.md §10d–§10k define the election-detail fields and waiver-trend logic. BUILD_PLAN_FOR_BLAIR.md’s “SUPERSEDED — consolidated into ONE aggregate cube” section has the current authoritative architecture and SQL — this widget binds to a single consolidated Analytic Model (AM_MEMBER_ENROLLMENT_SUMMARY) shared with sac-member-enrollment-widget (Snap), not three 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.4.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, same as the rest of this suite

Files

Data bindings — what it expects

One binding, aggregateData, shared with sac-member-enrollment- widget (Snap) — both bind to the same AM_MEMBER_ENROLLMENT_SUMMARY model, each filtering client-side by a RowKind discriminator dimension. This widget reads three row-kinds (StatusByWave, ElectionSummary, WaiverTrend); the fourth (DailyTrend) exists on the same model for Snap’s timeline. 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. See BUILD_PLAN_FOR_BLAIR.md’s “SUPERSEDED — consolidated into ONE aggregate cube” section for the full cube SQL and design. TotalEligibleLives/TotalCoveredLives (in the StatusByWave row-kind) are still NULL placeholders pending BR-29 — see below.

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. Revisit EOI once it’s no longer parked, and add true YoY volume trending once Blair/Ahmed restore that capability.
  3. Once BR-29 is confirmed fixed and the vDimMember join is restored in Gold, TotalEligibleLives/TotalCoveredLives and the WaiverTrend row-kind’s Membership_Type will start populating for real — no widget change needed, they’re already wired up as placeholders.