S
supero.docs
Documentation/Reference apps/Why a rep and a manager see different forecasts in the Summit sales CRM

Why a rep and a manager see different forecasts in the Summit sales CRM

Summit is an open-source sales CRM with accounts, leads, a deal pipeline and forecasts scoped to each rep. Source on GitHub, live at summit.supero.live.

  • apps
  • crm
  • sales
  • row-scoping
  • workflows

Overview

Nothing in this open-source sales CRM is public, and its dashboard contains no role check.
$184,000 or $1,083,900.
Those are the two weighted forecasts Summit computes from the seed data in setup.py, and which one you see depends on who signed in. The rep, Jordan Blake, owns 6 of the 16 seeded deals and 4 of those are open. The manager sees all 16, of which 11 are open. The Dashboard function in ui/app.js has no branch on role anywhere in it: it multiplies each open deal's amount by its probability, adds the results, and the two totals differ only in the rows the server handed back. The tile rounds them to $184k and $1.1M. The code is all in the summit folder.

A shared book and a private pipeline

Summit splits its five objects into two groups for the same role:
python
PolicyDef(role="tenant_user", default_access="none", rules=[
    # Rep can read all accounts & contacts (shared book of business).
    PolicyRule(entity="account", can_read=True),
    PolicyRule(entity="contact", can_read=True),
    # Owner-scoped CRUD on leads / deals / activities.
    PolicyRule(entity="lead", can_read=True, can_create=True, can_update=True,
               filter_field="owner_username", filter_match="$user.name"),
    PolicyRule(entity="deal", can_read=True, can_create=True, can_update=True,
               filter_field="owner_username", filter_match="$user.name"),
    PolicyRule(entity="activity", can_read=True, can_create=True, can_update=True,
               filter_field="owner_username", filter_match="$user.name"),
]),
A rep can look up any account or contact in the company and cannot edit either. Their pipeline is private. This is policy-based row scoping, applied on the server, and the manager role (tenant_admin) has rules on the same five entities with no filter.
The seed makes the split visible. I counted 12 accounts and 20 contacts in the shared book. The private side has 14 leads, 16 deals and 20 activities, spread across four reps. On a fresh seed the rep's Accounts tab still lists Helios Financial. The rep's Deals tab shows neither Helios deal. Both are owned by Sam Carter.
schemas.py ends by setting PUBLIC_SCHEMAS = []. Two of the 19 apps declare an empty list. The other is Helix, a clinical-trials app running three sites. That makes Summit the only single-organisation app with no public schema, and the landing page a logged-out visitor gets is static markup inside app.js with no data call behind it.

Six columns and no drag handlers

The Pipeline tab is a kanban with one column per deal stage, six in all. Each column filters the deal list by deal_stage and prints a count beside a dollar total.
There is no drag and drop.
Stage changes happen in the deal drawer. The app's own landing copy calls the board "drag-free". Moving a deal to Closed Won writes probability: 100 and then runs the deal_won workflow, declared as a saga in setup.py, whose first step sets the account's account_state to customer and carries a compensate block that puts it back to prospect, and whose two later steps send an email and post to the #wins Slack channel, each set to continue on error.
Two smaller workflows sit beside it. lead_created is bound to the event @create:summit:lead and emails the lead's owner. deal_followup is run from a button in the deal drawer.
The drawer has one more button. It sends the deal's stage and next step to the ai service and asks for one next action plus a draft email. When the service returns nothing, the code in the repo falls back to a written tip keyed on the stage.

Converting a lead is four writes for a manager and two for a rep

No other app in the repo has a convert flow. Summit's is convertLead, under twenty lines of app.js, and it is worth reading for how it handles a role that can only do part of the job.
The full conversion is four writes. It creates an account for the lead's company when none exists. It creates a contact from the lead. It creates a deal named after the company at stage Qualification, with probability 40 and a close date 30 days out. It sets lead_state to converted.
The first two are each wrapped in a question put to the SDK's client.can, once for account and once for contact, and under the policy above a rep may create neither, so a rep's conversion writes only the deal and the lead, with the company and the person carried on the deal as plain strings, while a manager's conversion writes all four rows.
Every create and edit form in the app goes through one EditModal. Five field lists near the bottom of the file (ACCOUNT_FIELDS, DEAL_FIELDS and three more) tell it what to render. A new attribute needs one entry in one list to show up in its form.

Sign in to the sales CRM twice

The login page at summit.supero.live lists two demo accounts, the manager and the rep. Open the dashboard as each and compare the forecast tile with the win rate and the leaderboard below it. On the seed, the rep's win rate is 50% from one won and one lost deal, and the manager's is 80% from four won and one lost. The live figures move as visitors advance deals.
To run it from the source folder:
bash
git clone https://github.com/supero-platform/supero-apps
cd supero-apps/apps/crm/summit
cp .env.example .env    # set SUPERO_DOMAIN and SUPERO_PASSWORD
./run.sh
You do not need an account. run.sh registers the domain named in .env, and the CRM is running in about two minutes on http://localhost:5669. The app code in that folder is MIT, and the platform it calls is a hosted service whose source is closed.
The first edit most teams will want is the stage list. It appears twice, as DEAL_STAGES in schemas.py and as STAGES on line 7 of ui/app.js. OPEN_STAGES on line 8 decides which stages count toward the forecast. Change all three, then begin a project of your own at supero.dev.