---
title: Account Elite-Prescriber rollup
description: Flag every Practice that anchors at least one ENT Elite prescriber so sales' 90-day cadence surfaces the unflagged providers working alongside.
status: Active
owner: Kyle
updated: 2026-05-09
last_verified: 2026-05-09
verification_type: eyeball
verification_ttl_days: 30
---

# Account Elite-Prescriber rollup

> **Owner:** Kyle.
> **Requestor:** Tyler Adcock (Sales), email 2026-05-08.
> **Status:** build-ready, pending Tyler's confirmation on Option A scope (see §4) and Sarah's review of this plan.
> **Build effort:** under an hour of declarative point-and-click setup. Two new fields + one DLRS rollup record.

## 1. Goal

Surface to sales every Practice that anchors at least one `⭐ ENT Elite ⭐` prescriber, so the 90-day call cadence naturally encounters the unflagged NPs / MDs / PAs working at those practices alongside the Elite anchor.

Tyler's framing (verbatim from the 2026-05-08 email):

> Many of our highest volume prescribers may not be captured by our current proactive ENT elite flags but they work at locations with ENT Elites (11 NP Elites flagged retroactively). … Provide sales with a comprehensive list of practices they can call in preset cadence to drive sales touches and ultimately conversions.

**Day-1 result for sales:** 1,245 Practice Accounts will flip to `Has_ENT_Elite_Prescriber__c = TRUE`, parsed from 2,073 Elite Prescriber Contacts in production. On a 90-day cadence that's ~14 practices to call per day — sized for Tyler's stated cadence target.

## 2. Schema state — what already exists

**Verification basis** (2026-05-09): schema verified in ClaudeTest sandbox via `FieldDefinition` / `RecordType` / `dlrs__LookupRollupSummary2__mdt` SOQL. **Production audit run by Kyle the same day in Developer Console** — 8 SOQL queries covering: population sizing, picklist value cleanliness, RT distribution of Elite Prescribers, parent-Account RT distribution, parent-Practice hierarchy depth, parent-Practice / Elite-child overlap, AccountContactRelation usage for Prescribers, and AccountContactRelation usage specific to Elites. Numbers cited throughout this plan are live production values from those queries, not sandbox metadata inference.

| Object                            | Field / RT                                             | Type     | Status                                                                                                                                                                                                                                                                                                                                                                      |
| --------------------------------- | ------------------------------------------------------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Contact`                         | `Prescriber_Tier__c`                                   | Picklist | **Exists.** One active value, verified in prod: `⭐ ENT Elite ⭐` (literal unicode stars in the value). 2,073 Contacts currently set.                                                                                                                                                                                                                                       |
| `Contact`                         | RecordType `Prescriber`                                | RT       | Exists (`DeveloperName='Prescriber'`). 100% of Elite Contacts are this RT.                                                                                                                                                                                                                                                                                                  |
| `Account`                         | RecordType `Practice`                                  | RT       | Exists (`DeveloperName='Practice'`). 100% of Elite Prescribers are parented to this RT. Other Account RTs in the org: `IndustriesBusiness`, `IndustriesHousehold`, `IndustriesIndividual`, `IndustriesPayer`. (Side observation: `business-context/objects/Account.md` lists only 3 RTs and is stale; CORRECTIONS row pending — not blocking this plan.)                    |
| `Account`                         | Tier / Elite / VIP / Top / Target / Key / Anchor field | —        | **None exists.** Naming space is clean for the new fields.                                                                                                                                                                                                                                                                                                                  |
| `dlrs__LookupRollupSummary2__mdt` | (managed CMDT)                                         | —        | **Already installed and active.** 45 active rollups in the org; 1 currently parents on Account (`Account_Number_of_Open_New_Order_Cases`, Realtime — same shape we're replicating). DLRS package owns its own triggers on Account, Contact, Opportunity, Task — Contact-as-child rollup will fire on Contact insert / update / delete with no AdvancedRx-side trigger work. |

**Sandbox data caveat:** ClaudeTest carries metadata + reference data only — no transactional records (per CLAUDE.md §1). 0 Contacts have `Prescriber_Tier__c` set in sandbox; the 2,073 live in production. End-to-end rollup verification requires either (a) seeded sandbox Contacts before deploy or (b) production-side smoke test post-deploy. Plan §6 addresses both paths.

## 3. Design

DLRS Realtime count rollup, scoped by Contact RT + picklist value. Mirrors the only existing Account-as-parent rollup (`Account_Number_of_Open_New_Order_Cases`).

### 3.1 New Account fields

| API Name                                | Type                   | Definition                                                                                                                                                                                                                                             | Page layouts     |
| --------------------------------------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------- |
| `Account.ENT_Elite_Prescriber_Count__c` | Number(5,0), default 0 | Count of child `Contact` records where `RecordType.DeveloperName='Prescriber'` AND `Prescriber_Tier__c='⭐ ENT Elite ⭐'`. **DLRS-managed** — do not edit directly; field-level security should be Read-Only for everyone except System Administrator. | Practice RT only |
| `Account.Has_ENT_Elite_Prescriber__c`   | Formula(Checkbox)      | `ENT_Elite_Prescriber_Count__c > 0`. Sales filters list views / reports on this.                                                                                                                                                                       | Practice RT only |

Why two fields:

- The Number is the load-bearing rollup target (DLRS needs a numeric field for `Count`).
- The Checkbox formula is what sales filters on. Avoids `> 0` boilerplate in every list view.
- Naming is tier-specific — when the next tier ships, sibling fields (`NP_Elite_Prescriber_Count__c`, `Has_NP_Elite_Prescriber__c`, etc.) follow the same shape. See §8.

### 3.2 New DLRS rollup CMDT record

Field names verified via `FieldDefinition` SOQL on `dlrs__LookupRollupSummary2__mdt` 2026-05-09.

| CMDT field                            | Value                                                                                |
| ------------------------------------- | ------------------------------------------------------------------------------------ |
| `Label` / `MasterLabel`               | `Account ENT Elite Prescriber Count`                                                 |
| `DeveloperName`                       | `Account_ENT_Elite_Prescriber_Count`                                                 |
| `dlrs__ParentObject__c`               | `Account`                                                                            |
| `dlrs__ChildObject__c`                | `Contact`                                                                            |
| `dlrs__RelationshipField__c`          | `AccountId`                                                                          |
| `dlrs__FieldToAggregate__c`           | `Id`                                                                                 |
| `dlrs__AggregateOperation__c`         | `Count`                                                                              |
| `dlrs__AggregateResultField__c`       | `ENT_Elite_Prescriber_Count__c`                                                      |
| `dlrs__RelationshipCriteria__c`       | `Prescriber_Tier__c = '⭐ ENT Elite ⭐' AND RecordType.DeveloperName = 'Prescriber'` |
| `dlrs__RelationshipCriteriaFields__c` | `Prescriber_Tier__c,RecordTypeId`                                                    |
| `dlrs__CalculationMode__c`            | `Realtime`                                                                           |
| `dlrs__Active__c`                     | `true`                                                                               |

After deploy, click "Calculate" on the rollup record (DLRS-provided Visualforce action) to backfill historical Practice Accounts in production. Sandbox backfill is moot — there are no Contacts.

### 3.3 Why DLRS, not native rollup or a custom flow

- **Native rollup-summary** isn't available — Account → Contact is a Lookup, not Master-Detail. Native rollups require MD.
- **Record-triggered flow** (AfterSave on Contact, query siblings, update Account) would reinvent what DLRS already does declaratively, and would add a new flow to the Contact trigger surface.
- **DLRS** matches the established org pattern (45 active rollups). The DLRS managed package owns the rollup mechanics; we own one CMDT record + two field definitions. That's it.

## 4. Scope decisions — resolved

These were open questions in the prior draft. Resolved 2026-05-09 from production audit data + Kyle direction; pending Tyler's email confirmation before build.

### 4.1 Practice hierarchy: leaf-only (Option A)

**Question:** When Practice A has Elite prescribers and rolls up to Practice B (the corporate parent) via `Account.Parent_Practice__c`, should B also surface in sales' call list?

**Decision:** No. The rollup flags only the Practice that has the Elite prescriber as a direct child (`Contact.AccountId = Account.Id`). Parent-Practice hierarchy is ignored.

**Rationale:** Production audit shows 155 parent Practices would gain the flag if we extended to bubble-up — including network shells like "ENT AND ALLERGY ASSOCIATES" (35 child clinics with Elites), "KAISER PERMANENTE — WEST (PARENT)" (31), "MASSACHUSETTS EYE & EAR" (8). Per Kyle's read of sales workflow, those parent records are mostly legal/structural shells without a phone to actually call — adding them inflates the call list without adding callable practices. If sales discovers value in calling network-level admin contacts, scope a v2 then.

**Future delta if reversed:** ~155 additional Accounts gain the flag. Implementation would be a second formula referencing `Parent_Practice__r.Has_ENT_Elite_Prescriber__c`, or a second DLRS rollup with a hierarchy-traversing criterion.

### 4.2 Multi-practice prescribers: primary AccountId only (Option A)

**Question:** When a Prescriber Contact has secondary Practice affiliations via `AccountContactRelation` (e.g., split-week coverage at multiple clinics), should every affiliated Practice get the flag?

**Decision:** No. The rollup uses `Contact.AccountId` (the primary parent) only. ACR-based secondary affiliations are not flagged.

**Rationale:** Production audit shows 492 ACR rows where an Elite Prescriber covers a secondary Practice (out of 2,073 Elites — ~24%). Some of these are real (active split coverage); some are stale (prescriber moved practices, secondary record never cleaned up). Per Kyle's read, the cleanliness risk outweighs the comprehensiveness benefit for v1. If sales reports a meaningful missed practice, scope a v2 then.

**Future delta if reversed:** up to ~492 additional Practice-prescriber pairs would surface. Implementation is harder than 4.1 — DLRS does not natively roll up across `AccountContactRelation`; would likely need either an `AccountContactRelation`-rooted rollup (DLRS supports `AccountContactRelation` as parent or child, but the relationship topology is awkward) or a record-triggered flow.

### 4.3 Picklist value with unicode `⭐` characters: inherited as-is

**Question:** The `Prescriber_Tier__c` picklist value is literally `⭐ ENT Elite ⭐` — stars are part of the value, not just the label. Any DLRS criterion / list view filter / future flow has to exact-match the unicode string.

**Decision:** Inherit. Don't change the picklist field or its values.

**Rationale:** Kyle direction 2026-05-09. The picklist is intentional for future tiers (NP Elite, Premier, etc.). Renaming the value now breaks all 2,073 Contacts currently set to it. Side note for whoever adds future tiers: consider whether the unicode-star convention continues — keeps the visual cue but at the cost of fragile filter strings. Not blocking this plan.

## 5. Pre-deploy validation gate (CLAUDE.md §8)

We're shipping declarative metadata only — two field definitions, one DLRS rollup CMDT record, one page-layout edit. The gate is mostly a no-op but we still walk it because every deploy goes through it.

1. Confirm target org = `ClaudeTest` via `mcp__Salesforce_DX__get_username`. **Never deploy outside `ClaudeTest`** — production refresh is the source of truth (CLAUDE.md §1).
2. Code Analyzer runs against the change set. Expected clean in seconds — no logic-bearing files in the change.
3. `sf project deploy validate --target-org ClaudeTest --source-dir <change-dir> --test-level RunLocalTests`. RunLocalTests runs the org's existing test suite to confirm the new fields don't break any current test setup. **We do not author new tests for this change.**
4. No hardcoded user / profile / group / RT IDs in the new metadata. The picklist value `⭐ ENT Elite ⭐` is a string literal; the criterion uses `RecordType.DeveloperName='Prescriber'` (DeveloperName, not RT ID). Conforms to `.claude/rules/flow.md` §3.11.

## 6. Test plan in ClaudeTest

Sandbox has no transactional Contacts. Two-step verification:

### 6.1 Sandbox seeded test

After deploy:

1. Create one Practice-RT Account in sandbox.
2. Create three Contacts under that Account (`AccountId = practice.Id`):
   - Contact A: `RecordType=Prescriber`, `Prescriber_Tier__c='⭐ ENT Elite ⭐'`.
   - Contact B: `RecordType=Prescriber`, `Prescriber_Tier__c=null`.
   - Contact C: `RecordType=Med_Staff`, `Prescriber_Tier__c='⭐ ENT Elite ⭐'` (tests the RT-criterion guard).
3. Verify `practice.ENT_Elite_Prescriber_Count__c == 1` and `practice.Has_ENT_Elite_Prescriber__c == TRUE`. Contact C must NOT count (RT mismatch); Contact B must NOT count (tier blank).
4. Update Contact A's `Prescriber_Tier__c` to null. Verify count drops to 0 and Has\_… flips to FALSE.
5. Re-set Contact A's tier to `⭐ ENT Elite ⭐`. Verify count returns to 1.
6. Reparent Contact A to a different Practice Account. Verify the original Practice's count drops, the new Practice's count increases.
7. Delete Contact A. Verify count drops.

Tests 1–3 confirm the criterion is correctly scoped. Test 4 confirms Realtime fires on update. Test 6 confirms re-parenting (DLRS handles old-parent decrement + new-parent increment). Test 7 confirms delete-trigger.

### 6.2 Production smoke test (post-cutover)

After deploying to production:

1. Click "Calculate" on the rollup record (DLRS UI) to backfill all historical Practice Accounts.
2. Spot-check 3 Practice Accounts known to have Elite prescribers (Tyler / sales picks them). Verify `ENT_Elite_Prescriber_Count__c` matches manual count.
3. Spot-check 2 Practice Accounts known to have NO Elite prescribers. Verify count = 0.
4. Run aggregate sanity:

   ```sql
   SELECT COUNT(Id) FROM Account WHERE Has_ENT_Elite_Prescriber__c = true AND RecordType.DeveloperName = 'Practice'
   ```

   Should return **1,245** (matches the audit number from 2026-05-09). If significantly off — investigate the DLRS trigger before declaring done.

   ```sql
   SELECT COUNT(Id) FROM Contact WHERE Prescriber_Tier__c = '⭐ ENT Elite ⭐' AND RecordType.DeveloperName = 'Prescriber'
   ```

   Should return **2,073** (≥ 1,245; multiple Elites can share one Practice).

## 7. Build steps

Point-and-click setup. No developer console, no source files to author by hand if done via Setup UI.

1. **Create the Number field.** Object Manager → Account → Fields & Relationships → New → Number. API name `ENT_Elite_Prescriber_Count__c`, length 5, decimals 0, default 0. FLS Read-Only for everyone except System Administrator (the DLRS managed package owns the value; users should not edit directly).
2. **Create the Formula Checkbox field.** Object Manager → Account → Fields & Relationships → New → Formula → Checkbox. API name `Has_ENT_Elite_Prescriber__c`. Formula: `ENT_Elite_Prescriber_Count__c > 0`.
3. **Add both fields to the Practice page layout.** Object Manager → Account → Page Layouts → Practice layout → drag both fields onto an appropriate section (Sales Targeting / Practice Information — wherever sales currently reads tier-related fields).
4. **Create the DLRS rollup record.** Setup → Custom Metadata Types → `Lookup Rollup Summary` → Manage Records → New. Fill in the values from §3.2 above. Save.
5. **Pre-deploy gate** (§5). Mostly a confirmation step since there's no code.
6. **Deploy ClaudeTest → run sandbox seeded test** (§6.1).
7. **Pause for Kyle / Tyler review** of sandbox results.
8. **Deploy to production** via the normal change-set / package process. (This plan does not authorize prod deploy — Kyle's normal prod-deploy path applies.)
9. **Click "Calculate"** on the rollup record in the production org's DLRS setup tab to backfill the 1,245 Practice Accounts. Realtime mode handles ongoing changes automatically thereafter.
10. **Run production smoke test** (§6.2).
11. **Sales builds the call-cadence list view / report** off `Has_ENT_Elite_Prescriber__c = TRUE` filtered to RT=Practice. Sales-team owned; not a deliverable of this plan.

## 8. Future direction — additional tiers

When the next tier ships (NP Elite, Premier, etc.):

**Recommended pattern (matches v1 shape):** add sibling per-tier rollups.

- New field `Account.<Tier>_Prescriber_Count__c` (Number).
- New field `Account.Has_<Tier>_Prescriber__c` (Formula Checkbox).
- New DLRS CMDT record with `dlrs__RelationshipCriteria__c` = `Prescriber_Tier__c = '<new picklist value>' AND RecordType.DeveloperName = 'Prescriber'`.

Mechanically identical to v1 — copy + adjust criterion + new fields. ~30 minutes per new tier.

Beyond ~4 tiers, consolidate to a single text rollup using DLRS `Concatenate Distinct` on `Prescriber_Tier__c` and filter via `CONTAINS()` formulas. Defer until the picklist actually grows.

## 9. Effort estimate

- **Build (point-and-click):** 30–45 minutes.
- **Sandbox seeded test:** 30 minutes.
- **Pre-deploy gate + ClaudeTest deploy:** 15 minutes.
- **Production deploy + backfill + smoke test:** Kyle's normal change-set process; not estimated here.

Total Claude-side / hands-on-keyboard effort to land in sandbox: **under 2 hours.**

## 10. Cross-references

- Tyler Adcock email, 2026-05-08 (request).
- `business-context/object-purpose-map.md` — Account RT roles + Prescriber Contact RT framing.
- `business-context/objects/Account.md` — Account schema; CORRECTIONS row pending (RT count discrepancy: doc says 3, live shows 5).
- `business-context/dlrs-rollups.md` — 45-rollup catalog; existing Account-as-parent rollup `Account_Number_of_Open_New_Order_Cases` is the closest pattern reference.
- `.claude/rules/flow.md` §3.11 — RecordType.DeveloperName rule (this plan conforms; uses `'Prescriber'`, not RT ID).
- `CLAUDE.md` §8 — pre-deploy validation gate.
- `CLAUDE.md` §1 — sandbox-vs-prod data caveat.
