When it comes to managing Opportunities in Salesforce, accuracy in revenue forecasting and seamless team collaboration are critical. Often, sales reps update an Opportunity’s stage but forget to revise the Amount
field accordingly, leading to inconsistent forecasts. Similarly, once a deal is marked as “Closed Won,” there’s usually a need to notify downstream teams to take further action.
This blog introduces a powerful Apex trigger solution that handles both these challenges in one neat implementation. With this trigger in place, your org can automatically:
-
Recalculate and update the
Amount
field whenever theStage
is modified -
Create a Task for the Opportunity owner when the stage is updated to
"Closed Won"
, prompting them to split revenue among the team
It’s an elegant automation that reduces manual effort, enforces business logic, and improves forecast reliability across the board.
🧠 Why This Trigger Is a Game Changer
Salesforce provides robust features for Opportunity tracking, but the actual enforcement of revenue rules and post-sale processes often depends on human accuracy. That’s risky.
By automating the Amount
update based on Probability and Expected Revenue, you ensure that your forecasts stay aligned with reality. Adding a Task when a deal is won helps ensure no key follow-up steps are missed, especially for revenue distribution, team handoffs, or financial operations.
These automations can save hours of manual work every week and improve consistency in your sales process without requiring additional user training.
🔍 What This Blog Covers
-
Automatically updating Opportunity Amount when the Stage changes
-
Creating a Task for Opportunity owners upon deal closure
-
Using Apex triggers in before and after update contexts
-
Writing clean, modular logic using a trigger handler class
-
Enhancing data reliability and team coordination through automation
-
Aligning forecast values with deal progression in real time
The trigger leverages both the before update and after update contexts. It intelligently detects when the StageName
changes and recalculates the Amount
by multiplying the Probability
and ExpectedRevenue
—a common forecasting approach in many orgs.
Then, if the Stage transitions to "Closed Won"
, a Task is automatically created with a clear subject and description for the Opportunity owner, reminding them to initiate revenue distribution among team members. This aligns internal operations with sales closures instantly and efficiently.
🎯 Where This Applies
This automation is especially useful for:
-
Sales-led organizations that use Probability-based forecasting
-
B2B teams with multiple contributors on a deal
-
Sales Ops and Finance teams that depend on precise revenue numbers
-
Organizations with handoff processes post-sale that require reminders
-
Companies that use Closed Won as a trigger point for internal workflows
The logic in this trigger can be adapted or extended based on industry, deal size, or custom fields—making it highly flexible across business models.
👨💻 Admin & Developer Tips
Use schema constants or Custom Metadata if you’d like to replace hardcoded values like "Closed Won"
or High
priority for Tasks. This makes your automation more dynamic and easier to maintain. Also, ensure your test classes cover multiple scenarios—stage unchanged, updated, and transitioning to Closed Won—to keep your trigger robust.
This pattern of splitting logic between before and after contexts is not only scalable but also helps you avoid performance and DML pitfalls that newer developers often run into.
🎥 Learn Visually – YouTube Playlist Linked
If you’re more of a visual learner, don’t worry—we’ve included a YouTube playlist that breaks down this trigger logic in a hands-on demo. You’ll see how the code works, how to deploy it in your org, and how to expand it based on your needs.
Solution:
public class OpportunityTriggerHandler {
public static void handleActivitiesBeforeUpdate (List<Opportunity> newRecords, Map<Id,
Opportunity> oldMap) {
//figure out if stage has been modified or not
//find the record from new list, compare and find the same record in old list and then check if stage
values are differ
//1 record-Opp1, Opp2, Opp3
for (Opportunity newOpp : newRecords) {
if (oldMap.get (newOpp.Id).StageName != newOpp.StageName) { newOpp.Amount = newOpp.Probability * newOpp.ExpectedRevenue;
}
}
}
public static void handleActivitiesAfter Update (List<Opportunity> newRecords) {
List taskListToInsert = new List();
for (Opportunity opp : newRecords) {
if (opp. StageName == ‘Closed Won’) {
//create a related record – Task record
Task taskRecord = new Task ();
taskRecord.Priority = ‘High’;
taskRecord.OwnerId = opp.OwnerId;
taskRecord.Description = ‘Please split the revenue amongst the team members’;
taskRecord.Status = ‘Not Started’;
taskRecord.Subject = ‘Split Revenue’;
taskRecord.WhatId = opp.Id;
taskListToInsert.add(taskRecord);
}
}
}