Salesforce development
The sales process, built into the CRM
Built and deployed custom Salesforce Flows, Apex classes and integrations to measurably improve the overall client experience, translating the Director’s CX vision into practical, scalable and automated solutions. The work runs from a new lead to a signed job: the sales pipeline, the follow-up messages, the site-visit invitation, the bill comparison a salesperson runs with the customer, and the hand-off to the Job Adding System.
3 orgsevery change passes: Dev, UAT, then production
8,200+production records moved off retired pipeline values, with zero failures
89%test coverage on the follow-up message service
The sales pipeline
A pipeline redesign, released in stages
The CX team’s process map set out how a lead should move from first call to signed job and what the customer should hear at each step. I turned it into lead statuses, opportunity stages, flows, validation rules and page changes, and released it to production in October 2026 after the business signed it off.
Lead to opportunity
New lead statuses for each contact attempt and a new opportunity pipeline, with the flow that sets the starting stage rebuilt to accept only the current stages. Site inspection fields were standardised and the installation address now carries from lead to opportunity. Records sitting on retired values were backed up, then moved to their new stage in bulk with zero failures.
Close Lost asks why
The mobile app asked for a loss reason and the desktop never did. A Close Lost button and a pop-up on the stage path now ask “Why was this opportunity lost?” at the moment it happens. A formula limits the prompt to opportunities closed after go-live, so the old ones never nag.
Booking a site visit
Book Meeting pre-fills the customer’s address, contact details, job type and inspection notes, and a before-save flow adds the same block to any visit booked another way. The customer’s invitation is an HTML email with the calendar file and a link to the company’s assurance document. Duplicate entries in salespeople’s calendars were traced to the salesperson being copied on the customer’s invitation, and fixed.
Follow-up messages that cannot double-send
A text at the early contact attempts and a gentle email at the last. A flow waits fifteen minutes after a status change, then Apex checks the lead is still on that status, sends at most once per step, never sends a step after a later one, and records why it skipped. Sandboxes log the message on the lead instead of sending it. It is built and tested in Dev and UAT, and switches on in production once the wording is signed off.
Bill analysis in Salesforce
RenewCompare, where the salesperson already works
A suite of Lightning Web Components puts RenewCompare inside Salesforce, on its own tab and on the customer’s account page. An outside Salesforce partner built the first version of the screens and also works on the wider org. The comparison engine behind them is mine, and since July 2026 I maintain the suite’s source as its own version-controlled project.
What the salesperson does
- Uploads the customer’s electricity or gas bill. The engine reads it and fills the form: usage, rates, controlled load, tiered feed-in, demand charges and the distributor.
- Checks the figures and corrects anything the bill did not show clearly.
- Gets the market’s plans ranked for that customer, one per retailer, by the price printed.
- Downloads the branded customer report as a PDF, or runs the solar return-on-investment form for the same customer.
What I added
- Demand charges end to end: read from the bill, shown on the form, priced and reported.
- Report rows that add up to the price each plan quotes, ranked by the figure the customer sees.
- The retailer’s plan code on every plan, and a note to re-run the comparison within 30 days before switching.
- The Download customer PDF button, using the engine’s branded report.
- Modelled plans labelled as estimates and printed without catalogue rates, the battery plan’s estimate as a range.
- Errors shown as the engine’s plain message, and no personal data in logs.
Integrations
What the org talks to, and how
The comparison engine
Apex callouts go through a named credential that signs in with the OAuth client-credentials flow from Entra ID. The secret is configured in the org and never sits in metadata or in git, and a permission set decides which users may call it.
The Job Adding System
The Job Adding System creates the signed opportunity, its quote and the Closed Won hand-off through the API. Every Salesforce release is audited against that write path and the full sequence is replayed in UAT, and a rule it cannot satisfy is kept off so a deploy can never break a signing.
Texts, email and calendars
Follow-up texts go through Salesforce Messaging, and their wording, like the follow-up email’s, lives in templates the business edits itself, so a change of words never needs a deploy. Calendar invitations carry an HTML body and a calendar file that keeps its identity, so a moved or cancelled visit updates the customer’s calendar.
Job cards and work boards
A job card editor built in Lightning Web Components and Apex: product lists from custom metadata, a picking slip PDF, a Chatter post listing exactly what changed, and a sync to the operations work boards. The same metadata maps each CRM product to its model, rating and rebate-platform ID.
Testing and release
Built in Dev, tested in UAT, signed off for production
Everything is built in a Dev sandbox, committed to git, promoted to UAT for the business to test, and released to production only after written sign-off. The repository is treated as public: no record data, names or contact details in commits.
Tested
- Apex ships with test classes. Callouts are tested against a shared HTTP mock, never the live engine.
- Decision logic lives in Apex rather than in a flow, so it can be unit-tested. The bar is 70–80% coverage on custom logic, not on boilerplate.
- Each deploy runs the tests for what it touches, and a promotion re-runs the org’s full local suite before and after.
- Behaviour is checked in the org itself with savepoint-and-rollback scripts that leave no records behind, and timed features get a live test: a lead flicked from 1st to 2nd contact and back within a second got exactly one message, fifteen minutes later.
Released
- Work is cut into batches, each with its goal, deploy commands, smoke tests, rollback and a hand-off note. If a batch fails partway, stop rather than guess.
- Before a production release, every component it touches is backed up and production is compared with the build for drift.
- Deploys go in order: fields and access, Apex with its tests, flows deployed inactive and then switched on, picklist values after the flow that handles them, rules last.
- Afterwards Dev and UAT are brought back into step, and old flow versions are archived to git before they are deleted.
When a release found a problem. On the day of the October release, a newly switched-on rule stopped leads converting. I measured why: every lead converted in the previous 30 days had been converted first and booked afterwards. The rule was switched off in all three orgs, conversion was re-verified in production, and the fix was committed within the hour.
Salesforce • Flows • Apex • Lightning Web Components • Named Credentials • Salesforce Messaging • Salesforce CLI • DEX-450