On field lead source of opportunity object, if currently there are 4 records for the value 'Web', and the user tries to create or update an existing record the trigger should throw an error stating that there can not be more than 4 records for the value web. Till now i have got this

set<ID> userIdset = new set<ID>();
set<string> stageName = new set <string> ();
List<Opportunity> stageList = new List <Opportunity> ();
if (Trigger.isInsert) 
    Schema.DescribeFieldResult fieldResult = Opportunity.stageName.getdescribe();
    List<schema.PicklistEntry> schemaPickList = fieldResult.getPickListvalues();
    System.debug('Schema picklist'+schemaPicklist);

    for (Opportunity o1 : Trigger.new) 


if (Trigger.isUpdate) 
    for (Opportunity o2:trigger.new)
        if (o2.stageName != Trigger.oldMap.get(o2.Id).stageName) 
            System.debug('Update trigger fired');
            system.debug('The old status was'+Trigger.oldMap.get(o2.Id).stageName);
  • 1
    Why are you walking the describe results? That doesn't seem to play into your objective. You'll certainly need a query here, probably a count() query.
    – David Reed
    Jan 10, 2019 at 14:21
  • I removed your update because it was exactly the same code as what you already posted. No reason for it to be there twice.
    – gNerb
    Jan 10, 2019 at 17:33

1 Answer 1


My best guess is that you want to make sure that no account has more than 4 opportunities that were created via leads that came from the web.

Disclaimer: the following is intentionally not copy/paste code and meant as a guide to get you started. Use it as a guide and if you run into any specific issues you can ask another question for more assistance.

trigger oppTriggerTest on Opportunity (before update, before insert) {
    // FIrst step is to get account ids
    Set<id> accountIds = new Set<Id>();

    for (Opportunity opp : trigger.new) {
        if (opp.leadSource = 'Web') { // Make sure we only look at opps that we care about

    // Let's make the database do as much of the work as possible
    List<AggregateResult> ars = [
        SELECT Count(Id) numOfWeb, AccountId
        FROM Opportunity
        WHERE AccountId IN :accountIds
            And LeadSource = 'Web'
        GROUP BY AccountId
        HAVING Count(Id) >= 4

    // Lets make a map that's easier to work with
    Map<Id, Integer> accountToCount = new Map<id, Integer>();

    for (AggregateResult ar : ars) {
        accountToCount.put(ar.get('AccountId'), ar.get('numOfWeb'));

    // Now, lets add an error to opps that violate the rule
    for (Opportunity opp : trigger.new) {
        if (accountToCount.containsKey(opp.accountId)) {
            opp.addError('Too many web opps for the given account');
  • Hi thanks for your help but I need to calculate for all the values of lead source. For example for Web we have 4 account records, then for Phone, we need to have 4 account records ......
    – user52297
    Jan 12, 2019 at 6:21

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .