function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
SeanCenoSeanCeno 

Trades_CascadeAccounts: System.LimitException: Too many code statements: 200001

Trades_CascadeAccounts had worked fine until about a week ago when our trade volume increased substantially. Can someone help me figure out why it's hitting governor limits?

 

public class Trades_CascadeAccounts {
    public Trades__c[] tradesOldList { set; get; }
    public Trades__c[] tradesNewList { set; get; }
    public Map<Id, Trades__c> tradesOldListMap { set; get; }
    
    public Trades_CascadeAccounts(Trades__c[] tradesOldList, Trades__c[] tradesNewList) {
        this.tradesNewList = tradesNewList == null ? new Trades__c[] {} : tradesNewList.clone();
        this.tradesOldList = tradesOldList == null ? new Trades__c[] {} : tradesOldList.clone();
        this.tradesOldListMap = new Map<Id, Trades__c>(this.tradesOldList);
    }
    
    public void execute() {
        Set<Id> tradesAccountIds = new Set<Id> {};
        
        for(Trades__c tradesNew : tradesNewList) {
            Trades__c tradesOld = tradesOldListMap.get(tradesNew.Id);
            tradesOld = tradesOld == null ? new Trades__c() : tradesOld;
            
            tradesAccountIds.add(tradesOld.Resolved_Firm_Trading_ID__c);
            tradesAccountIds.add(tradesNew.Resolved_Firm_Trading_ID__c);
        }
        
        if (tradesAccountIds.size() == 0)
            return;
        
        Account[] accountList = new Account[] {};
        
        for(Id accountId : tradesAccountIds) {
            if (accountId == null)
                continue;
            
            Account account = new Account(Id = accountId);
            account.Rollup_Trades__c = null;
            accountList.add(account);
        }
        
        update accountList;
    }
}

 

 

Also, hear is the batch job if that helps:

global class Account_RollupTradesBatchable implements Database.Batchable<sObject>, Database.Stateful {
    global Database.QueryLocator start(Database.BatchableContext batchableContext){
        return Database.getQueryLocator('select Id from Account where ParentId = null');
    }
    
    global void execute(Database.BatchableContext batchableContext, Account[] accountList) {
        for(Account account : accountList)
            account.Rollup_Trades__c = null;
        update accountList;
    }
    
    global void finish(Database.BatchableContext batchableContext) {
        
    }
}

 

 

Best Answer chosen by Admin (Salesforce Developers) 
sfdcfoxsfdcfox

You could do this in a batch, but for now, you can use this code:

 

public class Contact_RollupTrades {
	Set<Id> contactIds;
	Contact_Setting__c setting;

	public Contact_RollupTrades(Set<Id> contactIds) {
		this.contactIds = contactIds;
		setting = Contact_Setting__c.getInstance();
	}

	public void execute() {
		if(setting.Disable_Contact_Rollup__c != true) {
			Map<Id, Contact> contacts = new Map<Id, Contact>();
			for(Id contactId:contactIds) {
				contacts.put(contactId,
					new Contact(
						Id=contactId,
						Total_NIOR_I_Sales__c = 0,
						Total_NIOR_I_Shares__c = 0,
						YTD_NIOR_I_Sales__c = 0,
						YTD_NIOR_I_Shares__c = 0,
						QTD_NIOR_I_Sales__c = 0,
						QTD_NIOR_I_Shares__c = 0,
						MTD_NIOR_I_Sales__c = 0,
						MTD_NIOR_I_Shares__c = 0,
						PY_NIOR_I_Sales__c = 0,
						PY_NIOR_I_Shares__c = 0,

						Total_NS_REIT_Sales__c = 0,
						Total_NS_REIT_Shares__c = 0,
						YTD_NS_REIT_Sales__c = 0,
						YTD_NS_REIT_Shares__c = 0,
						QTD_NS_REIT_Sales__c = 0,
						QTD_NS_REIT_Shares__c = 0,
						MTD_NS_REIT_Sales__c = 0,
						MTD_NS_REIT_Shares__c = 0,
						PY_NS_REIT_Sales__c = 0,
						PY_NS_REIT_Shares__c = 0,

						Total_NS_HIT_Sales__c = 0,
						Total_NS_HIT_Shares__c = 0,
						YTD_NS_HIT_Sales__c = 0,
						YTD_NS_HIT_Shares__c = 0,
						QTD_NS_HIT_Sales__c = 0,
						QTD_NS_HIT_Shares__c = 0,
						MTD_NS_HIT_Sales__c = 0,
						MTD_NS_HIT_Shares__c = 0,
						PY_NS_HIT_Sales__c = 0,
						PY_NS_HIT_Shares__c = 0,
						
						Rollup_Trades__c = DateTime.now()
					)
				);
			}
			
			Trades__c[] tradesList = [
				select Dollar_Amount_of_the_transaction__c, Fund_Number__c, Number_of_Shares_of_the_transaction__c,
					 Resolved_to_Rep_Trading_ID__c, Resolved_Firm_Trading_ID__c, Resolved_Firm_Trading_IDs__c,
					 Trade_Date__c
				from Trades__c
				where Resolved_to_Rep_Trading_ID__c in :contactIds
				   and Fund_Number__c in ('3910', '3911', '3912')       // NIOR I; NS REIT; NS HIT
				   and Dollar_Amount_of_the_transaction__c != null      // prevents null pointers below
				   and Number_of_Shares_of_the_transaction__c != null   // prevents null pointers below
				   and Trade_Date__c != null                            // prevents null pointers below
				   // Negative values are ignored for roll-up purposes
				   and Dollar_Amount_of_the_transaction__c >= 0
				   and Number_of_Shares_of_the_transaction__c >= 0
			];

			Map<String, SObjectField[]>
				ytd = new map<string, sobjectfield[]> {
					'3910' => new sobjectfield[] { contact.YTD_NIOR_I_Sales__c , contact.YTD_NIOR_I_Shares__c },
					'3911' => new sobjectfield[] { contact.YTD_NS_REIT_Sales__c , contact.YTD_NS_REIT_Shares__c },
					'3912' => new sobjectfield[] { contact.YTD_NS_HIT_Sales__c , contact.YTD_NS_HIT_Shares__c }
				},
				qtd = new map<string, sobjectfield[]> {
					'3910' => new sobjectfield[] { contact.QTD_NIOR_I_Sales__c , contact.QTD_NIOR_I_Shares__c },
					'3911' => new sobjectfield[] { contact.QTD_NS_REIT_Sales__c , contact.QTD_NS_REIT_Shares__c },
					'3912' => new sobjectfield[] { contact.QTD_NS_HIT_Sales__c , contact.QTD_NS_HIT_Shares__c }
				},
				mtd = new map<string, sobjectfield[]> {
					'3910' => new sobjectfield[] { contact.MTD_NIOR_I_Sales__c , contact.MTD_NIOR_I_Shares__c },
					'3911' => new sobjectfield[] { contact. MTD_NS_REIT_Sales__c, contact.MTD_NS_REIT_Shares__c },
					'3912' => new sobjectfield[] { contact.MTD_NS_HIT_Sales__c , contact.MTD_NS_HIT_Shares__c }
				},
				py = new map<string, sobjectfield[] {
					'3910' => new sobjectfield[] { contact.PY_NIOR_I_Sales__c , contact.PY_NIOR_I_Shares__c },
					'3911' => new sobjectfield[] { contact.PY_NS_REIT_Sales__c , contact.PY_NS_REIT_Shares__c },
					'3912' => new sobjectfield[] { contact.PY_NS_HIT_Sales__c , contact.PY_NS_HIT_Shares__c }
				},
				total = new map<string, sobjectfield[] {
					'3910' => new sobjectfield[] { contact.Total_NIOR_I_Sales__c , contact.Total_NIOR_I_Shares__c},
					'3911' => new sobjectfield[] { contact.Total_NS_REIT_Sales__c , contact.Total_NS_REIT_Shares__c },
					'3912' => new sobjectfield[] { contact.Total_NS_HIT_Sales__c , contact.Total_NS_HIT_Shares__c }
				};

			for(trades__c trade:tradeslist) {
				if(date.today().year() == trade.trade_date__c.year()) {
					contacts.get(trade.Resolved_to_Rep_Trading_ID__c).put(
						ytd.get(trade.Fund_Number__c)[0],
						((decimal)contacts.get(ytd.get(trade.fund_number__c)[0]))+
						trade.Dollar_Amount_of_the_transaction__c
					);
					contacts.get(trade.Resolved_to_Rep_Trading_ID__c).put(
						ytd.get(trade.Fund_Number__c)[1],
						((decimal)contacts.get(ytd.get(trade.fund_number__c)[1]))+
						trade.Number_of_Shares_of_the_transaction__c
					);
					if( (date.today().month()/3).intValue() == (trade.trade_date__c.month()/3).intValue() ) {
						contacts.get(trade.Resolved_to_Rep_Trading_ID__c).put(
							qtd.get(trade.Fund_Number__c)[0],
							((decimal)contacts.get(qtd.get(trade.fund_number__c)[0]))+
							trade.Dollar_Amount_of_the_transaction__c
						);
						contacts.get(trade.Resolved_to_Rep_Trading_ID__c).put(
							qtd.get(trade.Fund_Number__c)[1],
							((decimal)contacts.get(qtd.get(trade.fund_number__c)[1]))+
							trade.Number_of_Shares_of_the_transaction__c
						);
						if(date.today().month()==trade_date__c.month()) {
							contacts.get(trade.Resolved_to_Rep_Trading_ID__c).put(
								mtd.get(trade.Fund_Number__c)[0],
								((decimal)contacts.get(mtd.get(trade.fund_number__c)[0]))+
								trade.Dollar_Amount_of_the_transaction__c
							);
							contacts.get(trade.Resolved_to_Rep_Trading_ID__c).put(
								mtd.get(trade.Fund_Number__c)[1],
								((decimal)contacts.get(mtd.get(trade.fund_number__c)[1]))+
								trade.Number_of_Shares_of_the_transaction__c
							);						
						}
					}
				} else if(date.today().year()-1==trade.trade_date__c.year()) {
					contacts.get(trade.Resolved_to_Rep_Trading_ID__c).put(
						py.get(trade.Fund_Number__c)[0],
						((decimal)contacts.get(py.get(trade.fund_number__c)[0]))+
						trade.Dollar_Amount_of_the_transaction__c
					);
					contacts.get(trade.Resolved_to_Rep_Trading_ID__c).put(
						py.get(trade.Fund_Number__c)[1],
						((decimal)contacts.get(py.get(trade.fund_number__c)[1]))+
						trade.Number_of_Shares_of_the_transaction__c
					);						
				}
				contacts.get(trade.Resolved_to_Rep_Trading_ID__c).put(
					total.get(trade.Fund_Number__c)[0],
					((decimal)contacts.get(total.get(trade.fund_number__c)[0]))+
					trade.Dollar_Amount_of_the_transaction__c
				);
				contacts.get(trade.Resolved_to_Rep_Trading_ID__c).put(
					total.get(trade.Fund_Number__c)[1],
					((decimal)contacts.get(total.get(trade.fund_number__c)[1]))+
					trade.Number_of_Shares_of_the_transaction__c
				);						
			}
		}
	}
}

If this is all correct (I don't have time to replicate the db model to test right now), this should reduce your script statements to approximately 2% of your current usage. The major killer was the 30 lines of variable assignment, which could have been done in a single line (as outlined above). I also took out the asserts and so on; they should never fail anyways, so they are redundant. I also optimized the if-then structure to take advantage of logic; if a date isn't in this year, then it won't be in this quarter, and a date not in this quarter won't be in this month. I figure this should save you about 30-40 lines of script per contact, and up to approximately 10 scripts per trade. You should be able to handle at least 10,000 trades per contact with this code, if my estimates are correct.

All Answers

sfdcfoxsfdcfox

I don't see how this code could be the problem; it's succinct. There are a few minor optimizations I could offer, but I don't think it'd do you much good. However, try it and see what you get:

 

public class Trades_CascadeAccounts {
    public Trades__c[] tradesOldList { set; get; }
    public Trades__c[] tradesNewList { set; get; }
    public Map<Id, Trades__c> tradesOldListMap { set; get; }
    
    public Trades_CascadeAccounts(Trades__c[] tradesOldList, Trades__c[] tradesNewList) {
        this.tradesNewList = tradesNewList == null ? new Trades__c[0] : tradesNewList.clone();
        this.tradesOldList = tradesOldList == null ? new Trades__c[0] : tradesOldList.clone();
        this.tradesOldListMap = new Map<Id, Trades__c>(this.tradesOldList);
    }
    
    public void execute() {
        Set<Id> tradesAccountIds = new Set<Id> {};
        
        for(Trades__c tradesNew : tradesNewList) {
            // Ternary operator, like above, saves a script statement here, saves up to 200 scripts.
			Trades__c tradesOld = tradesOldListMap.containsKey(tradesNew.Id) ? tradesOldListMap.get(tradesNew.Id) : new Trades__c();
//            tradesOld = tradesOld == null ? new Trades__c() : tradesOld;
            
			// Construct and add, converting two script statements into 1, saving up to 200 scripts.
			tradesAccountIds.addAll(new Set<Id> { tradesOld.Resolved_Firm_Trading_Id__c, tradesNew.Resolved_Firm_Trading_ID__c });
//            tradesAccountIds.add(tradesOld.Resolved_Firm_Trading_ID__c);
//            tradesAccountIds.add(tradesNew.Resolved_Firm_Trading_ID__c);
        }
		
		// Remove null ID value instead of if statement in loop
		tradesAccountIds.remove(null);
        
		// Actually no need to do this...
		// Loop will take only 1 script if empty, and DML will take 1 script,
		// So removing this saves 2 scripts per execute().
//        if (tradesAccountIds.size() == 0)
//            return;
        
        Account[] accountList = new Account[0];
        
        for(Id accountId : tradesAccountIds) {
//		No longer need to check each ID for null; saves one script line per ID,
//		I presume up to 201 scripts will be saved here.
//            if (accountId == null)
//                continue;
            
//            Account account = new Account(Id = accountId);
//            account.Rollup_Trades__c = null;
//            accountList.add(account);

// Create object and add to list in one statement instead of 3, saving up to 400 scripts.
			accountList.add(new Account(Id=AccountId,Rollup_Trades__c=null));
        }
        
        update accountList;
    }
}

If my maths are correct, this will optimize your code by up to 1,002 script statements per 200 records.

SeanCenoSeanCeno

Wow this is great, thanks! I will try it out now.

SeanCenoSeanCeno

The new Trades_CascadeAccounts worked fine, but now it's showing Contact_RollupTrades as hitting too many code statements:

 

public class Contact_RollupTrades {
    public Contact[] contactOldList { set; get; }
    public Contact[] contactNewList { set; get; }
    public Contact_Setting__c setting { set; get; }
    
    public Contact_RollupTrades(Contact[] contactOldList, Contact[] contactNewList) {

        this.contactOldList = contactOldList == null ? new Contact[] {} : contactOldList.clone();
        this.contactNewList = contactNewList == null ? new Contact[] {} : contactNewList.clone();

        this.setting = Contact_Setting__c.getInstance();
        this.setting = setting == null ? new Contact_Setting__c() : setting;

    }
    
    public void execute() {
        if (setting.Disable_Contact_Rollup__c == true)
            return;
        
        Contact[] contactUpdateableList = new Contact[] {};
        
        for(Contact contactNew : this.contactNewList) {
            if (contactNew == null || contactNew.Id == null)
                continue;
/*            if (contactNew.Rollup_Trades__c != null) //removed this to allow manual updates to recalculate the fields
                continue; */  
            contactUpdateableList.add(contactNew);
        }
        execute(contactUpdateableList);
    }
    
    public void execute(Contact[] contactList) {

        if (contactList == null || contactList.size() == 0)
            return;
        
        // Reset contacts
        Map<Id, Contact> contactListMap = new Map<Id, Contact>(contactList);

        for(Contact contact : contactList) {
            contact.Total_NIOR_I_Sales__c = 0;
            contact.Total_NIOR_I_Shares__c = 0;
            contact.YTD_NIOR_I_Sales__c = 0;
            contact.YTD_NIOR_I_Shares__c = 0;
            contact.QTD_NIOR_I_Sales__c = 0;
            contact.QTD_NIOR_I_Shares__c = 0;
            contact.MTD_NIOR_I_Sales__c = 0;
            contact.MTD_NIOR_I_Shares__c = 0;
            contact.PY_NIOR_I_Sales__c = 0;
            contact.PY_NIOR_I_Shares__c = 0;
            
            contact.Total_NS_REIT_Sales__c = 0;
            contact.Total_NS_REIT_Shares__c = 0;
            contact.YTD_NS_REIT_Sales__c = 0;
            contact.YTD_NS_REIT_Shares__c = 0;
            contact.QTD_NS_REIT_Sales__c = 0;
            contact.QTD_NS_REIT_Shares__c = 0;
            contact.MTD_NS_REIT_Sales__c = 0;
            contact.MTD_NS_REIT_Shares__c = 0;
            contact.PY_NS_REIT_Sales__c = 0;
            contact.PY_NS_REIT_Shares__c = 0;
            
            contact.Total_NS_HIT_Sales__c = 0;
            contact.Total_NS_HIT_Shares__c = 0;
            contact.YTD_NS_HIT_Sales__c = 0;
            contact.YTD_NS_HIT_Shares__c = 0;
            contact.QTD_NS_HIT_Sales__c = 0;
            contact.QTD_NS_HIT_Shares__c = 0;
            contact.MTD_NS_HIT_Sales__c = 0;
            contact.MTD_NS_HIT_Shares__c = 0;
            contact.PY_NS_HIT_Sales__c = 0;
            contact.PY_NS_HIT_Shares__c = 0;
            
            contact.Rollup_Trades__c = DateTime.now();
        }
        
        // Roll up the trades based on the Resolved Firm Trading ID field
        Trades__c[] tradesList = [
            select Dollar_Amount_of_the_transaction__c
                 , Fund_Number__c
                 , Number_of_Shares_of_the_transaction__c
                 , Resolved_to_Rep_Trading_ID__c //Contact Lookup
                 , Resolved_Firm_Trading_ID__c //Account Lookup
                 , Resolved_Firm_Trading_IDs__c 
                 , Trade_Date__c
              from Trades__c
             where Resolved_to_Rep_Trading_ID__c in :contactListMap.keySet()
               and Fund_Number__c in ('3910', '3911', '3912')       // NIOR I; NS REIT; NS HIT
               and Dollar_Amount_of_the_transaction__c != null      // prevents null pointers below
               and Number_of_Shares_of_the_transaction__c != null   // prevents null pointers below
               and Trade_Date__c != null                            // prevents null pointers below
               
               // Negative values are ignored for roll-up purposes
               and Dollar_Amount_of_the_transaction__c >= 0
               and Number_of_Shares_of_the_transaction__c >= 0
        ];
        
        // Nothing to do?
        if (tradesList.size() == 0)
            return;
        
        // Update contacts

        for(Trades__c trades : tradesList) {
            Contact account = contactListMap.get(trades.Resolved_to_Rep_Trading_ID__c);

            if (account == null || trades == null || trades.Trade_Date__c == null) {
                continue;
            } else if ('3910'.equals(trades.Fund_Number__c)) {
                processFund_3910(account, trades);
            } else if ('3911'.equals(trades.Fund_Number__c)) {
                processFund_3911(account, trades);
            } else if ('3912'.equals(trades.Fund_Number__c)) {
                processFund_3912(account, trades);
            }
        }
    }
    
    void processFund_3910(Contact contact, Trades__c trades) {

        system.assert(null != contact);
        system.assert(null != trades);
        system.assert(null != trades.Trade_Date__c);
        
        Boolean isYTD = (date.today().year() == trades.Trade_Date__c.year());
        Boolean isMTD = (date.today().month() == trades.Trade_Date__c.month()) && isYTD;
        Boolean isQTD = (((date.today().month() - 1) / 3) + 1) == (((trades.Trade_Date__c.month() - 1) / 3) + 1) && isYTD;
        Boolean isPY = ((date.today().year() - 1) == trades.Trade_Date__c.year());
        Boolean isTotal = true;
        
        // YTD
        if (isYTD) {
            contact.YTD_NIOR_I_Sales__c += trades.Dollar_Amount_of_the_transaction__c;
            contact.YTD_NIOR_I_Shares__c += trades.Number_of_Shares_of_the_transaction__c;
        }
        
        // QTD
        if (isQTD) {
            contact.QTD_NIOR_I_Sales__c += trades.Dollar_Amount_of_the_transaction__c;
            contact.QTD_NIOR_I_Shares__c += trades.Number_of_Shares_of_the_transaction__c;
        }
        
        // MTD
        if (isMTD) {
            contact.MTD_NIOR_I_Sales__c += trades.Dollar_Amount_of_the_transaction__c;
            contact.MTD_NIOR_I_Shares__c += trades.Number_of_Shares_of_the_transaction__c;
        }
        
        // PY
        if (isPY) {
            contact.PY_NIOR_I_Sales__c += trades.Dollar_Amount_of_the_transaction__c;
            contact.PY_NIOR_I_Shares__c += trades.Number_of_Shares_of_the_transaction__c;
        }
        
        // Total
        if (isTotal) {
            contact.Total_NIOR_I_Sales__c += trades.Dollar_Amount_of_the_transaction__c;
            contact.Total_NIOR_I_Shares__c += trades.Number_of_Shares_of_the_transaction__c;
        }
    }

    void processFund_3911(Contact contact, Trades__c trades) {

        system.assert(null != contact);
        system.assert(null != trades);
        system.assert(null != trades.Trade_Date__c);
        
        Boolean isYTD = (date.today().year() == trades.Trade_Date__c.year());
        Boolean isMTD = (date.today().month() == trades.Trade_Date__c.month()) && isYTD;
        Boolean isQTD = (((date.today().month() - 1) / 3) + 1) == (((trades.Trade_Date__c.month() - 1) / 3) + 1) && isYTD;
        Boolean isPY = ((date.today().year() - 1) == trades.Trade_Date__c.year());
        Boolean isTotal = true;
        
        // YTD
        if (isYTD) {
            contact.YTD_NS_REIT_Sales__c += trades.Dollar_Amount_of_the_transaction__c;
            contact.YTD_NS_REIT_Shares__c += trades.Number_of_Shares_of_the_transaction__c;
        }
        
        // QTD
        if (isQTD) {
            contact.QTD_NS_REIT_Sales__c += trades.Dollar_Amount_of_the_transaction__c;
            contact.QTD_NS_REIT_Shares__c += trades.Number_of_Shares_of_the_transaction__c;
        }
        
        // MTD
        if (isMTD) {
            contact.MTD_NS_REIT_Sales__c += trades.Dollar_Amount_of_the_transaction__c;
            contact.MTD_NS_REIT_Shares__c += trades.Number_of_Shares_of_the_transaction__c;
        }
        
        // 
        if (isPY) {
            contact.PY_NS_REIT_Sales__c += trades.Dollar_Amount_of_the_transaction__c;
            contact.PY_NS_REIT_Shares__c += trades.Number_of_Shares_of_the_transaction__c;
        }
        
        // 
        if (isTotal) {
            contact.Total_NS_REIT_Sales__c += trades.Dollar_Amount_of_the_transaction__c;
            contact.Total_NS_REIT_Shares__c += trades.Number_of_Shares_of_the_transaction__c;
        }
    }
    
    void processFund_3912(Contact contact, Trades__c trades) {
        system.assert(null != contact);
        system.assert(null != trades);
        system.assert(null != trades.Trade_Date__c);
        
        Boolean isYTD = (date.today().year() == trades.Trade_Date__c.year());
        Boolean isMTD = (date.today().month() == trades.Trade_Date__c.month()) && isYTD;
        Boolean isQTD = (((date.today().month() - 1) / 3) + 1) == (((trades.Trade_Date__c.month() - 1) / 3) + 1) && isYTD;
        Boolean isPY = ((date.today().year() - 1) == trades.Trade_Date__c.year());
        Boolean isTotal = true;
        
        // YTD
        if (isYTD) {
            contact.YTD_NS_HIT_Sales__c += trades.Dollar_Amount_of_the_transaction__c;
            contact.YTD_NS_HIT_Shares__c += trades.Number_of_Shares_of_the_transaction__c;
        }
        
        // QTD
        if (isQTD) {
            contact.QTD_NS_HIT_Sales__c += trades.Dollar_Amount_of_the_transaction__c;
            contact.QTD_NS_HIT_Shares__c += trades.Number_of_Shares_of_the_transaction__c;
        }
        
        // MTD
        if (isMTD) {
            contact.MTD_NS_HIT_Sales__c += trades.Dollar_Amount_of_the_transaction__c;
            contact.MTD_NS_HIT_Shares__c += trades.Number_of_Shares_of_the_transaction__c;
        }
        
        // 
        if (isPY) {
            contact.PY_NS_HIT_Sales__c += trades.Dollar_Amount_of_the_transaction__c;
            contact.PY_NS_HIT_Shares__c += trades.Number_of_Shares_of_the_transaction__c;
        }
        
        // 
        if (isTotal) {
            contact.Total_NS_HIT_Sales__c += trades.Dollar_Amount_of_the_transaction__c;
            contact.Total_NS_HIT_Shares__c += trades.Number_of_Shares_of_the_transaction__c;
        }
    }
}

 

sfdcfoxsfdcfox

You need to use the profiler to figure out where the bottleneck is; we could go through this class and fix it, too, but if that's not the problem, we'll just be going in a circle. Do this:

 

1) Click on Developer Console.

2) Click on Debug > Change Log Levels.

3) Set Profiling to Finest.

4) Attempt to run your code with the Developer Console open. This will show a new log.

5) Open the log file, and look at the cumulative usage at the bottom.

 

You'll see something like this:

 

Class.className1.functionName1: line 107, column 1: public void functionName2(): executed 1 time in 45 ms
Class.className1.functionName2: line 221, column 1: public void functionName3(): executed 1 time in 44 ms
Class.className1.functionName3: line 249, column 1: public void functionName4(): executed 1 time in 44 ms
Class.className2.functionName5: line 153, column 1: global public SET<Id>(Integer): executed 10 times in 34 ms
Class.className1.functionName6: line 117, column 1: global String getId(): executed 2 times in 28 ms
Class.className1.functionName4: line 193, column 1: global public LIST<String>(): executed 12 times in 18 ms
Class.className2.functionName7: line 44, column 1: public static Schema.DescribeSObjectResult Describe(Schema.SObjectType): executed 16 times in 15 ms
Class.className2.functionName5: line 140, column 1: public static void functionName5(MAP<Id,SObject>, SET<Id>): executed 2 times in 13 ms
Class.className2.functionName5: line 130, column 1: global public LIST<Schema.SObjectField>(): executed 6 times in 13 ms
Class.className2.functionName5: line 144, column 1: global public Object clone(): executed 4 times in 13 ms
Class.className1.functionName4: line 210, column 1: global public Object values(): executed 4 times in 13 ms

(Function and class names have been changed to protect the innocent).

 

You'll see the functions that were executed most frequently, and using this data, you can then tell where you need to optimize. I can help you once we know what class we're supposed to be looking at.

SeanCenoSeanCeno

Thanks for the response. This is basically all that is being displayed in the logs for profiling:

 

09:55:00.838|CUMULATIVE_PROFILING_BEGIN
09:55:00.838|CUMULATIVE_PROFILING|No profiling information for SOQL operations
09:55:00.838|CUMULATIVE_PROFILING|No profiling information for SOSL operations
09:55:00.838|CUMULATIVE_PROFILING|No profiling information for DML operations
09:55:00.838|CUMULATIVE_PROFILING|method invocations|
AnonymousBlock: line 1, column 1: global public static void debug(ANY): executed 1 time in 0 ms
External entry point: public static void execute(): executed 1 time in 0 ms

09:55:00.838|CUMULATIVE_PROFILING_END
09:55:00.032 (32914000)|CODE_UNIT_FINISHED|execute_anonymous_apex
09:55:00.032 (32923000)|EXECUTION_FINISHED

 

I've come to the conclusion that maybe a batch file to handle the roll-up fields calculation may be the best solution?

 

The problem is in the number of trades. 

For instance, for 5 new added trades are maximum 5 related contacts (one for each) 

The code:

1. sets the roll-up fields to 0 on all the contacts roll-up fields that should be calculated again.

2. then selects all the trades for these 5 contacts - line 78 (here we can have hundreds or thousands of trades). If the number of trades selected here is too big we receive an error for that block (that's why some trades parse correctly and go to the system and some others don't) 

3. and then goes through all those trades to recalculate the roll-up fields on Contact (for year, month, quarter, previous year) the iteration on line 104

 

I think this last step should be handled with a batch file. How do I write a batch class using this last piece of code (from line 104 till the end) into a batch file and just send the list of trades selected here to the batch, that way the code will handle only max 200 records(trades) at a time?

 

sfdcfoxsfdcfox

You could do this in a batch, but for now, you can use this code:

 

public class Contact_RollupTrades {
	Set<Id> contactIds;
	Contact_Setting__c setting;

	public Contact_RollupTrades(Set<Id> contactIds) {
		this.contactIds = contactIds;
		setting = Contact_Setting__c.getInstance();
	}

	public void execute() {
		if(setting.Disable_Contact_Rollup__c != true) {
			Map<Id, Contact> contacts = new Map<Id, Contact>();
			for(Id contactId:contactIds) {
				contacts.put(contactId,
					new Contact(
						Id=contactId,
						Total_NIOR_I_Sales__c = 0,
						Total_NIOR_I_Shares__c = 0,
						YTD_NIOR_I_Sales__c = 0,
						YTD_NIOR_I_Shares__c = 0,
						QTD_NIOR_I_Sales__c = 0,
						QTD_NIOR_I_Shares__c = 0,
						MTD_NIOR_I_Sales__c = 0,
						MTD_NIOR_I_Shares__c = 0,
						PY_NIOR_I_Sales__c = 0,
						PY_NIOR_I_Shares__c = 0,

						Total_NS_REIT_Sales__c = 0,
						Total_NS_REIT_Shares__c = 0,
						YTD_NS_REIT_Sales__c = 0,
						YTD_NS_REIT_Shares__c = 0,
						QTD_NS_REIT_Sales__c = 0,
						QTD_NS_REIT_Shares__c = 0,
						MTD_NS_REIT_Sales__c = 0,
						MTD_NS_REIT_Shares__c = 0,
						PY_NS_REIT_Sales__c = 0,
						PY_NS_REIT_Shares__c = 0,

						Total_NS_HIT_Sales__c = 0,
						Total_NS_HIT_Shares__c = 0,
						YTD_NS_HIT_Sales__c = 0,
						YTD_NS_HIT_Shares__c = 0,
						QTD_NS_HIT_Sales__c = 0,
						QTD_NS_HIT_Shares__c = 0,
						MTD_NS_HIT_Sales__c = 0,
						MTD_NS_HIT_Shares__c = 0,
						PY_NS_HIT_Sales__c = 0,
						PY_NS_HIT_Shares__c = 0,
						
						Rollup_Trades__c = DateTime.now()
					)
				);
			}
			
			Trades__c[] tradesList = [
				select Dollar_Amount_of_the_transaction__c, Fund_Number__c, Number_of_Shares_of_the_transaction__c,
					 Resolved_to_Rep_Trading_ID__c, Resolved_Firm_Trading_ID__c, Resolved_Firm_Trading_IDs__c,
					 Trade_Date__c
				from Trades__c
				where Resolved_to_Rep_Trading_ID__c in :contactIds
				   and Fund_Number__c in ('3910', '3911', '3912')       // NIOR I; NS REIT; NS HIT
				   and Dollar_Amount_of_the_transaction__c != null      // prevents null pointers below
				   and Number_of_Shares_of_the_transaction__c != null   // prevents null pointers below
				   and Trade_Date__c != null                            // prevents null pointers below
				   // Negative values are ignored for roll-up purposes
				   and Dollar_Amount_of_the_transaction__c >= 0
				   and Number_of_Shares_of_the_transaction__c >= 0
			];

			Map<String, SObjectField[]>
				ytd = new map<string, sobjectfield[]> {
					'3910' => new sobjectfield[] { contact.YTD_NIOR_I_Sales__c , contact.YTD_NIOR_I_Shares__c },
					'3911' => new sobjectfield[] { contact.YTD_NS_REIT_Sales__c , contact.YTD_NS_REIT_Shares__c },
					'3912' => new sobjectfield[] { contact.YTD_NS_HIT_Sales__c , contact.YTD_NS_HIT_Shares__c }
				},
				qtd = new map<string, sobjectfield[]> {
					'3910' => new sobjectfield[] { contact.QTD_NIOR_I_Sales__c , contact.QTD_NIOR_I_Shares__c },
					'3911' => new sobjectfield[] { contact.QTD_NS_REIT_Sales__c , contact.QTD_NS_REIT_Shares__c },
					'3912' => new sobjectfield[] { contact.QTD_NS_HIT_Sales__c , contact.QTD_NS_HIT_Shares__c }
				},
				mtd = new map<string, sobjectfield[]> {
					'3910' => new sobjectfield[] { contact.MTD_NIOR_I_Sales__c , contact.MTD_NIOR_I_Shares__c },
					'3911' => new sobjectfield[] { contact. MTD_NS_REIT_Sales__c, contact.MTD_NS_REIT_Shares__c },
					'3912' => new sobjectfield[] { contact.MTD_NS_HIT_Sales__c , contact.MTD_NS_HIT_Shares__c }
				},
				py = new map<string, sobjectfield[] {
					'3910' => new sobjectfield[] { contact.PY_NIOR_I_Sales__c , contact.PY_NIOR_I_Shares__c },
					'3911' => new sobjectfield[] { contact.PY_NS_REIT_Sales__c , contact.PY_NS_REIT_Shares__c },
					'3912' => new sobjectfield[] { contact.PY_NS_HIT_Sales__c , contact.PY_NS_HIT_Shares__c }
				},
				total = new map<string, sobjectfield[] {
					'3910' => new sobjectfield[] { contact.Total_NIOR_I_Sales__c , contact.Total_NIOR_I_Shares__c},
					'3911' => new sobjectfield[] { contact.Total_NS_REIT_Sales__c , contact.Total_NS_REIT_Shares__c },
					'3912' => new sobjectfield[] { contact.Total_NS_HIT_Sales__c , contact.Total_NS_HIT_Shares__c }
				};

			for(trades__c trade:tradeslist) {
				if(date.today().year() == trade.trade_date__c.year()) {
					contacts.get(trade.Resolved_to_Rep_Trading_ID__c).put(
						ytd.get(trade.Fund_Number__c)[0],
						((decimal)contacts.get(ytd.get(trade.fund_number__c)[0]))+
						trade.Dollar_Amount_of_the_transaction__c
					);
					contacts.get(trade.Resolved_to_Rep_Trading_ID__c).put(
						ytd.get(trade.Fund_Number__c)[1],
						((decimal)contacts.get(ytd.get(trade.fund_number__c)[1]))+
						trade.Number_of_Shares_of_the_transaction__c
					);
					if( (date.today().month()/3).intValue() == (trade.trade_date__c.month()/3).intValue() ) {
						contacts.get(trade.Resolved_to_Rep_Trading_ID__c).put(
							qtd.get(trade.Fund_Number__c)[0],
							((decimal)contacts.get(qtd.get(trade.fund_number__c)[0]))+
							trade.Dollar_Amount_of_the_transaction__c
						);
						contacts.get(trade.Resolved_to_Rep_Trading_ID__c).put(
							qtd.get(trade.Fund_Number__c)[1],
							((decimal)contacts.get(qtd.get(trade.fund_number__c)[1]))+
							trade.Number_of_Shares_of_the_transaction__c
						);
						if(date.today().month()==trade_date__c.month()) {
							contacts.get(trade.Resolved_to_Rep_Trading_ID__c).put(
								mtd.get(trade.Fund_Number__c)[0],
								((decimal)contacts.get(mtd.get(trade.fund_number__c)[0]))+
								trade.Dollar_Amount_of_the_transaction__c
							);
							contacts.get(trade.Resolved_to_Rep_Trading_ID__c).put(
								mtd.get(trade.Fund_Number__c)[1],
								((decimal)contacts.get(mtd.get(trade.fund_number__c)[1]))+
								trade.Number_of_Shares_of_the_transaction__c
							);						
						}
					}
				} else if(date.today().year()-1==trade.trade_date__c.year()) {
					contacts.get(trade.Resolved_to_Rep_Trading_ID__c).put(
						py.get(trade.Fund_Number__c)[0],
						((decimal)contacts.get(py.get(trade.fund_number__c)[0]))+
						trade.Dollar_Amount_of_the_transaction__c
					);
					contacts.get(trade.Resolved_to_Rep_Trading_ID__c).put(
						py.get(trade.Fund_Number__c)[1],
						((decimal)contacts.get(py.get(trade.fund_number__c)[1]))+
						trade.Number_of_Shares_of_the_transaction__c
					);						
				}
				contacts.get(trade.Resolved_to_Rep_Trading_ID__c).put(
					total.get(trade.Fund_Number__c)[0],
					((decimal)contacts.get(total.get(trade.fund_number__c)[0]))+
					trade.Dollar_Amount_of_the_transaction__c
				);
				contacts.get(trade.Resolved_to_Rep_Trading_ID__c).put(
					total.get(trade.Fund_Number__c)[1],
					((decimal)contacts.get(total.get(trade.fund_number__c)[1]))+
					trade.Number_of_Shares_of_the_transaction__c
				);						
			}
		}
	}
}

If this is all correct (I don't have time to replicate the db model to test right now), this should reduce your script statements to approximately 2% of your current usage. The major killer was the 30 lines of variable assignment, which could have been done in a single line (as outlined above). I also took out the asserts and so on; they should never fail anyways, so they are redundant. I also optimized the if-then structure to take advantage of logic; if a date isn't in this year, then it won't be in this quarter, and a date not in this quarter won't be in this month. I figure this should save you about 30-40 lines of script per contact, and up to approximately 10 scripts per trade. You should be able to handle at least 10,000 trades per contact with this code, if my estimates are correct.

This was selected as the best answer
SeanCenoSeanCeno

Wow thanks for taking the time to rewrite the code. I'm not as familiar with SObject (dynamic) methods. In lines 86 and 91 I added ">" as it seemed to be missing and it was throwing an error.

 

	86			py = new map<string, sobjectfield[]> {
					'3910' => new sobjectfield[] { contact.PY_NIOR_I_Sales__c , contact.PY_NIOR_I_Shares__c },
					'3911' => new sobjectfield[] { contact.PY_NS_REIT_Sales__c , contact.PY_NS_REIT_Shares__c },
					'3912' => new sobjectfield[] { contact.PY_NS_HIT_Sales__c , contact.PY_NS_HIT_Shares__c }
				},
	91			total = new map<string, sobjectfield[]> {
					'3910' => new sobjectfield[] { contact.Total_NIOR_I_Sales__c , contact.Total_NIOR_I_Shares__c},
					'3911' => new sobjectfield[] { contact.Total_NS_REIT_Sales__c , contact.Total_NS_REIT_Shares__c },
					'3912' => new sobjectfield[] { contact.Total_NS_HIT_Sales__c , contact.Total_NS_HIT_Shares__c }
				};

 

 

In line 101 it's giving me: Incompatible key type Schema.SObjectField for MAP <Id,Contact>

 

((decimal)contacts.get(ytd.get(trade.fund_number__c)[0]))+

 Is there a way to solve this easily?

 

SeanCenoSeanCeno
			for(trades__c trades: tradeslist) {
				if(date.today().year() == trades.trade_date__c.year()) {
					contacts.get(trades.Resolved_to_Rep_Trading_ID__c).put(
						ytd.get(trades.Fund_Number__c)[0],
						((decimal)trades.get(ytd.get(trades.Fund_Number__c)[0]))+
						trades.Dollar_Amount_of_the_transaction__c
					);

 This fixed the last problem.

 
The code was referencing "contacts" twice in the same statement, instead of "contacts" and then "trades":
 
[Object].put(Schema.SObjectField, Decimal)
 
 
Now it's showing me an error in line 109:
if( (date.today().month()/3).intValue() == (trade.trade_date__c.month()/3).intValue()
 
Method does not exist or incorrect signature: [Integer].intValue()
 
I tried changing it to:
 
if ((date.today().month()).divide(3, 0) == (trades.trade_date__c.month()).divide(3, 0) )
 
But it's giving me the same type of error:
 
Method does not exist or incorrect signature: [Integer].divide(Integer, Integer)
 
I'm not seeing the problem here...
 
SeanCenoSeanCeno

I  had to do some minute editing to your code, but it has now saved correctly. Thank you.

 

public class Contact_RollupTrades {
	Set<Id> contactIds;
	Contact_Setting__c setting;

	public Contact_RollupTrades(Set<Id> contactIds) {
		this.contactIds = contactIds;
		setting = Contact_Setting__c.getInstance();
	}

	public void execute() {
		if(setting.Disable_Contact_Rollup__c != true) {
			Map<Id, Contact> contacts = new Map<Id, Contact>();
			for(Id contactId:contactIds) {
				contacts.put(contactId,
					new Contact(
						Id=contactId,
						Total_NIOR_I_Sales__c = 0,
						Total_NIOR_I_Shares__c = 0,
						YTD_NIOR_I_Sales__c = 0,
						YTD_NIOR_I_Shares__c = 0,
						QTD_NIOR_I_Sales__c = 0,
						QTD_NIOR_I_Shares__c = 0,
						MTD_NIOR_I_Sales__c = 0,
						MTD_NIOR_I_Shares__c = 0,
						PY_NIOR_I_Sales__c = 0,
						PY_NIOR_I_Shares__c = 0,

						Total_NS_REIT_Sales__c = 0,
						Total_NS_REIT_Shares__c = 0,
						YTD_NS_REIT_Sales__c = 0,
						YTD_NS_REIT_Shares__c = 0,
						QTD_NS_REIT_Sales__c = 0,
						QTD_NS_REIT_Shares__c = 0,
						MTD_NS_REIT_Sales__c = 0,
						MTD_NS_REIT_Shares__c = 0,
						PY_NS_REIT_Sales__c = 0,
						PY_NS_REIT_Shares__c = 0,

						Total_NS_HIT_Sales__c = 0,
						Total_NS_HIT_Shares__c = 0,
						YTD_NS_HIT_Sales__c = 0,
						YTD_NS_HIT_Shares__c = 0,
						QTD_NS_HIT_Sales__c = 0,
						QTD_NS_HIT_Shares__c = 0,
						MTD_NS_HIT_Sales__c = 0,
						MTD_NS_HIT_Shares__c = 0,
						PY_NS_HIT_Sales__c = 0,
						PY_NS_HIT_Shares__c = 0,
						
						Rollup_Trades__c = DateTime.now()
					)
				);
			}
			
			Trades__c[] tradesList = [
				select Dollar_Amount_of_the_transaction__c, Fund_Number__c, Number_of_Shares_of_the_transaction__c,
					 Resolved_to_Rep_Trading_ID__c, Resolved_Firm_Trading_ID__c, Resolved_Firm_Trading_IDs__c,
					 Trade_Date__c
				from Trades__c
				where Resolved_to_Rep_Trading_ID__c in :contactIds
				   and Fund_Number__c in ('3910', '3911', '3912')       // NIOR I; NS REIT; NS HIT
				   and Dollar_Amount_of_the_transaction__c != null      // prevents null pointers below
				   and Number_of_Shares_of_the_transaction__c != null   // prevents null pointers below
				   and Trade_Date__c != null                            // prevents null pointers below
				   // Negative values are ignored for roll-up purposes
				   and Dollar_Amount_of_the_transaction__c >= 0
				   and Number_of_Shares_of_the_transaction__c >= 0
			];

			Map<String, SObjectField[]>
				ytd = new map<string, sobjectfield[]> {
					'3910' => new sobjectfield[] { contact.YTD_NIOR_I_Sales__c , contact.YTD_NIOR_I_Shares__c },
					'3911' => new sobjectfield[] { contact.YTD_NS_REIT_Sales__c , contact.YTD_NS_REIT_Shares__c },
					'3912' => new sobjectfield[] { contact.YTD_NS_HIT_Sales__c , contact.YTD_NS_HIT_Shares__c }
				},
				qtd = new map<string, sobjectfield[]> {
					'3910' => new sobjectfield[] { contact.QTD_NIOR_I_Sales__c , contact.QTD_NIOR_I_Shares__c },
					'3911' => new sobjectfield[] { contact.QTD_NS_REIT_Sales__c , contact.QTD_NS_REIT_Shares__c },
					'3912' => new sobjectfield[] { contact.QTD_NS_HIT_Sales__c , contact.QTD_NS_HIT_Shares__c }
				},
				mtd = new map<string, sobjectfield[]> {
					'3910' => new sobjectfield[] { contact.MTD_NIOR_I_Sales__c , contact.MTD_NIOR_I_Shares__c },
					'3911' => new sobjectfield[] { contact.MTD_NS_REIT_Sales__c, contact.MTD_NS_REIT_Shares__c },
					'3912' => new sobjectfield[] { contact.MTD_NS_HIT_Sales__c , contact.MTD_NS_HIT_Shares__c }
				},
				py = new map<string, sobjectfield[]> {
					'3910' => new sobjectfield[] { contact.PY_NIOR_I_Sales__c , contact.PY_NIOR_I_Shares__c },
					'3911' => new sobjectfield[] { contact.PY_NS_REIT_Sales__c , contact.PY_NS_REIT_Shares__c },
					'3912' => new sobjectfield[] { contact.PY_NS_HIT_Sales__c , contact.PY_NS_HIT_Shares__c }
				},
				total = new map<string, sobjectfield[]> {
					'3910' => new sobjectfield[] { contact.Total_NIOR_I_Sales__c , contact.Total_NIOR_I_Shares__c},
					'3911' => new sobjectfield[] { contact.Total_NS_REIT_Sales__c , contact.Total_NS_REIT_Shares__c },
					'3912' => new sobjectfield[] { contact.Total_NS_HIT_Sales__c , contact.Total_NS_HIT_Shares__c }
				};

			for(trades__c trades: tradeslist) {
				if(date.today().year() == trades.trade_date__c.year()) {
					contacts.get(trades.Resolved_to_Rep_Trading_ID__c).put(
						ytd.get(trades.Fund_Number__c)[0],
						((decimal)trades.get(ytd.get(trades.Fund_Number__c)[0]))+
						trades.Dollar_Amount_of_the_transaction__c
					);
					contacts.get(trades.Resolved_to_Rep_Trading_ID__c).put(
						ytd.get(trades.Fund_Number__c)[1],
						((decimal)trades.get(ytd.get(trades.fund_number__c)[1]))+
						trades.Number_of_Shares_of_the_transaction__c
					);
                    if( (Decimal.ValueOf(date.today().month()).divide(3, 0) == Decimal.ValueOf(trades.trade_date__c.month()).divide(3, 0)) )   {
						contacts.get(trades.Resolved_to_Rep_Trading_ID__c).put(
							qtd.get(trades.Fund_Number__c)[0],
							((decimal)trades.get(qtd.get(trades.fund_number__c)[0]))+
							trades.Dollar_Amount_of_the_transaction__c
						);
						contacts.get(trades.Resolved_to_Rep_Trading_ID__c).put(
							qtd.get(trades.Fund_Number__c)[1],
							((decimal)trades.get(qtd.get(trades.fund_number__c)[1]))+
							trades.Number_of_Shares_of_the_transaction__c
						);
						if(date.today().month()== trades.trade_date__c.month()) {
							contacts.get(trades.Resolved_to_Rep_Trading_ID__c).put(
								mtd.get(trades.Fund_Number__c)[0],
								((decimal)trades.get(mtd.get(trades.fund_number__c)[0]))+
								trades.Dollar_Amount_of_the_transaction__c
							);
							contacts.get(trades.Resolved_to_Rep_Trading_ID__c).put(
								mtd.get(trades.Fund_Number__c)[1],
								((decimal)trades.get(mtd.get(trades.fund_number__c)[1]))+
								trades.Number_of_Shares_of_the_transaction__c
							);						
						}
					}
				} else if(date.today().year()-1==trades.trade_date__c.year()) {
					contacts.get(trades.Resolved_to_Rep_Trading_ID__c).put(
						py.get(trades.Fund_Number__c)[0],
						((decimal)trades.get(py.get(trades.fund_number__c)[0]))+
						trades.Dollar_Amount_of_the_transaction__c
					);
					contacts.get(trades.Resolved_to_Rep_Trading_ID__c).put(
						py.get(trades.Fund_Number__c)[1],
						((decimal)trades.get(py.get(trades.fund_number__c)[1]))+
						trades.Number_of_Shares_of_the_transaction__c
					);						
				}
				contacts.get(trades.Resolved_to_Rep_Trading_ID__c).put(
					total.get(trades.Fund_Number__c)[0],
					((decimal)trades.get(total.get(trades.fund_number__c)[0]))+
					trades.Dollar_Amount_of_the_transaction__c
				);
				contacts.get(trades.Resolved_to_Rep_Trading_ID__c).put(
					total.get(trades.Fund_Number__c)[1],
					((decimal)trades.get(total.get(trades.fund_number__c)[1]))+
					trades.Number_of_Shares_of_the_transaction__c
				);						
			}
		}
	}
}

 

SeanCenoSeanCeno
Error: Invalid Data. 
Review all error messages below to correct your data.
Apex trigger Trades_CascadeContacts caused an unexpected exception, 
contact your administrator: Trades_CascadeContacts: execution of AfterInsert caused by: 
System.DmlException: Update failed. First exception on row 0 with id 003J000000SmTU6IAN; 
first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, 
Contact_RollupTrades: execution of BeforeUpdate caused by: line 2, column 3: 
trigger body is invalid and failed recompilation: 
Constructor not defined: [Contact_RollupTrades].(LIST, LIST): []: 
Class.Trades_CascadeContacts.execute: line 37, column 1
 
This is the error I'm getting now when I try and process a trade. Here is the following code that this is now affecting:
 
public class Trades_CascadeContacts {
    public Trades__c[] tradesOldList { set; get; }
    public Trades__c[] tradesNewList { set; get; }
    public Map<Id, Trades__c> tradesOldListMap { set; get; }
    
    public Trades_CascadeContacts(Trades__c[] tradesOldList, Trades__c[] tradesNewList) {
        this.tradesNewList = tradesNewList == null ? new Trades__c[] {} : tradesNewList.clone();
        this.tradesOldList = tradesOldList == null ? new Trades__c[] {} : tradesOldList.clone();
        this.tradesOldListMap = new Map<Id, Trades__c>(this.tradesOldList);
    }
    
    public void execute() {
        Set<Id> tradesContactIds = new Set<Id> {};
        
        for(Trades__c tradesNew : tradesNewList) {
            Trades__c tradesOld = tradesOldListMap.get(tradesNew.Id);
            tradesOld = tradesOld == null ? new Trades__c() : tradesOld;
            
            tradesContactIds.add(tradesOld.Resolved_to_Rep_Trading_ID__c);
            tradesContactIds.add(tradesNew.Resolved_to_Rep_Trading_ID__c);
        }
        
        if (tradesContactIds.size() == 0)
            return;
        
        Contact[] contactList = new Contact[] {};
        
        for(Id contactId : tradesContactIds) {
            if (contactId == null)
                continue;
            
            Contact contact = new Contact(Id = contactId);
            contact.Rollup_Trades__c = null;
            contactList.add(contact);
        }
        
        update contactList;
    }
}

 

trigger Trades_CascadeContacts on Trades__c (after delete, after insert, after undelete, after update) {
	    Trades__c[] tradesOldList = trigger.IsDelete ? null : trigger.old;
        Trades__c[] tradesNewList = trigger.IsDelete ? trigger.old : trigger.new;
        new Trades_CascadeContacts(tradesOldList, tradesNewList).execute();

}

 

trigger Contact_RollupTrades on Contact (before update) {
		new Contact_RollupTrades(trigger.old, trigger.new).execute();
}

 

What do I need to change in these classes and triggers?

 

SeanCenoSeanCeno

Changed Trigger to:

 

trigger Contact_RollupTrades on Contact (before update) {
		Set<ID> sID = new Set<ID>(trigger.newMap.keySet());
		new Contact_RollupTrades(sID).execute();
}

 New Error:

 

Error: Invalid Data. 
Review all error messages below to correct your data.
Apex trigger Trades_CascadeContacts caused an unexpected exception, contact your administrator: Trades_CascadeContacts: execution of AfterInsert caused by: System.DmlException: Update failed. First exception on row 0 with id 003J000000SmTU6IAN; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, Contact_RollupTrades: execution of BeforeUpdate caused by: System.SObjectException: Contact.YTD_NS_HIT_Sales__c does not belong to SObject type Trades__c Class.Contact_RollupTrades.execute: line 99, column 1 Trigger.Contact_RollupTrades: line 3, column 1: []: Class.Trades_CascadeContacts.execute: line 37, column 1

sfdcfoxsfdcfox
Let me go over the code, and I'll get back with you shortly. I'm sure there's something simple.
sfdcfoxsfdcfox

Try this revision:

 

public class Contact_RollupTrades {
    Set<Id> contactIds;
    Contact_Setting__c setting;

    public Contact_RollupTrades(Set<Id> contactIds) {
        this.contactIds = contactIds;
        setting = Contact_Setting__c.getInstance();
    }

    public void execute() {
        if(setting.Disable_Contact_Rollup__c != true) {
            Map<Id, Contact> contacts = new Map<Id, Contact>();
            for(Id contactId:contactIds) {
                contacts.put(contactId,
                    new Contact(
                        Id=contactId,				 Total_NIOR_I_Sales__c = 0, Total_NIOR_I_Shares__c = 0,	YTD_NIOR_I_Sales__c = 0,
                        YTD_NIOR_I_Shares__c = 0,	 QTD_NIOR_I_Sales__c = 0,	QTD_NIOR_I_Shares__c = 0,	MTD_NIOR_I_Sales__c = 0,
                        MTD_NIOR_I_Shares__c = 0,	 PY_NIOR_I_Sales__c = 0,	PY_NIOR_I_Shares__c = 0,	Total_NS_REIT_Sales__c = 0,
                        Total_NS_REIT_Shares__c = 0, YTD_NS_REIT_Sales__c = 0,	YTD_NS_REIT_Shares__c = 0,	QTD_NS_REIT_Sales__c = 0,
                        QTD_NS_REIT_Shares__c = 0,	 MTD_NS_REIT_Sales__c = 0,	MTD_NS_REIT_Shares__c = 0,	PY_NS_REIT_Sales__c = 0,
                        PY_NS_REIT_Shares__c = 0,	 Total_NS_HIT_Sales__c = 0, Total_NS_HIT_Shares__c = 0,	YTD_NS_HIT_Sales__c = 0,
                        YTD_NS_HIT_Shares__c = 0,	 QTD_NS_HIT_Sales__c = 0,	QTD_NS_HIT_Shares__c = 0,	MTD_NS_HIT_Sales__c = 0,
                        MTD_NS_HIT_Shares__c = 0,	 PY_NS_HIT_Sales__c = 0,	PY_NS_HIT_Shares__c = 0,	Rollup_Trades__c = DateTime.now()
                    )
                );
            }
            
            Trades__c[] tradesList = [
                select Dollar_Amount_of_the_transaction__c, Fund_Number__c, Number_of_Shares_of_the_transaction__c,
                     Resolved_to_Rep_Trading_ID__c, Resolved_Firm_Trading_ID__c, Resolved_Firm_Trading_IDs__c,
                     Trade_Date__c
                from Trades__c
                where Resolved_to_Rep_Trading_ID__c in :contactIds
                   and Fund_Number__c in ('3910', '3911', '3912')       // NIOR I; NS REIT; NS HIT
                   and Dollar_Amount_of_the_transaction__c != null      // prevents null pointers below
                   and Number_of_Shares_of_the_transaction__c != null   // prevents null pointers below
                   and Trade_Date__c != null                            // prevents null pointers below
                   // Negative values are ignored for roll-up purposes
                   and Dollar_Amount_of_the_transaction__c >= 0
                   and Number_of_Shares_of_the_transaction__c >= 0
            ];

            Map<String, SObjectField[]>
                ytd = new map<string, sobjectfield[]> {
                    '3910' => new sobjectfield[] { contact.YTD_NIOR_I_Sales__c , contact.YTD_NIOR_I_Shares__c },
                    '3911' => new sobjectfield[] { contact.YTD_NS_REIT_Sales__c , contact.YTD_NS_REIT_Shares__c },
                    '3912' => new sobjectfield[] { contact.YTD_NS_HIT_Sales__c , contact.YTD_NS_HIT_Shares__c }
                },
                qtd = new map<string, sobjectfield[]> {
                    '3910' => new sobjectfield[] { contact.QTD_NIOR_I_Sales__c , contact.QTD_NIOR_I_Shares__c },
                    '3911' => new sobjectfield[] { contact.QTD_NS_REIT_Sales__c , contact.QTD_NS_REIT_Shares__c },
                    '3912' => new sobjectfield[] { contact.QTD_NS_HIT_Sales__c , contact.QTD_NS_HIT_Shares__c }
                },
                mtd = new map<string, sobjectfield[]> {
                    '3910' => new sobjectfield[] { contact.MTD_NIOR_I_Sales__c , contact.MTD_NIOR_I_Shares__c },
                    '3911' => new sobjectfield[] { contact. MTD_NS_REIT_Sales__c, contact.MTD_NS_REIT_Shares__c },
                    '3912' => new sobjectfield[] { contact.MTD_NS_HIT_Sales__c , contact.MTD_NS_HIT_Shares__c }
                },
                py = new map<string, sobjectfield[] {
                    '3910' => new sobjectfield[] { contact.PY_NIOR_I_Sales__c , contact.PY_NIOR_I_Shares__c },
                    '3911' => new sobjectfield[] { contact.PY_NS_REIT_Sales__c , contact.PY_NS_REIT_Shares__c },
                    '3912' => new sobjectfield[] { contact.PY_NS_HIT_Sales__c , contact.PY_NS_HIT_Shares__c }
                },
                total = new map<string, sobjectfield[] {
                    '3910' => new sobjectfield[] { contact.Total_NIOR_I_Sales__c , contact.Total_NIOR_I_Shares__c},
                    '3911' => new sobjectfield[] { contact.Total_NS_REIT_Sales__c , contact.Total_NS_REIT_Shares__c },
                    '3912' => new sobjectfield[] { contact.Total_NS_HIT_Sales__c , contact.Total_NS_HIT_Shares__c }
                };

            for(trades__c trade:tradeslist) {
                if(date.today().year() == trade.trade_date__c.year()) {
					contacts.get(trade.Resolved_to_Rep_Trading_Id__c).put(ytd.get(trade.fund_number__c)[0], ((Decimal)contacts.get(trade.Resolved_to_Rep_Trading_Id__c).get(ytd.get(trade.fund_number__c)[0]))+trade.Dollar_Amount_of_The_Transaction__c);
					contacts.get(trade.Resolved_to_Rep_Trading_Id__c).put(ytd.get(trade.fund_number__c)[1], ((Decimal)contacts.get(trade.Resolved_to_Rep_Trading_Id__c).get(ytd.get(trade.fund_number__c)[1]))+trade.Number_of_Shares_of_the_transaction__c);

                    if( (date.today().month()/3).intValue() == (trade.trade_date__c.month()/3).intValue() ) {
						contacts.get(trade.Resolved_to_Rep_Trading_Id__c).put(qtd.get(trade.fund_number__c)[0], ((Decimal)contacts.get(trade.Resolved_to_Rep_Trading_Id__c).get(qtd.get(trade.fund_number__c)[0]))+trade.Dollar_Amount_of_The_Transaction__c);
						contacts.get(trade.Resolved_to_Rep_Trading_Id__c).put(qtd.get(trade.fund_number__c)[1], ((Decimal)contacts.get(trade.Resolved_to_Rep_Trading_Id__c).get(qtd.get(trade.fund_number__c)[1]))+trade.Number_of_Shares_of_the_transaction__c);

                        if(date.today().month()==trade_date__c.month()) {
							contacts.get(trade.Resolved_to_Rep_Trading_Id__c).put(mtd.get(trade.fund_number__c)[0], ((Decimal)contacts.get(trade.Resolved_to_Rep_Trading_Id__c).get(mtd.get(trade.fund_number__c)[0]))+trade.Dollar_Amount_of_The_Transaction__c);
							contacts.get(trade.Resolved_to_Rep_Trading_Id__c).put(mtd.get(trade.fund_number__c)[1], ((Decimal)contacts.get(trade.Resolved_to_Rep_Trading_Id__c).get(mtd.get(trade.fund_number__c)[1]))+trade.Number_of_Shares_of_the_transaction__c);
                        }
                    }
                } else if(date.today().year()-1==trade.trade_date__c.year()) {
					contacts.get(trade.Resolved_to_Rep_Trading_Id__c).put(py.get(trade.fund_number__c)[0], ((Decimal)contacts.get(trade.Resolved_to_Rep_Trading_Id__c).get(py.get(trade.fund_number__c)[0]))+trade.Dollar_Amount_of_The_Transaction__c);
					contacts.get(trade.Resolved_to_Rep_Trading_Id__c).put(py.get(trade.fund_number__c)[1], ((Decimal)contacts.get(trade.Resolved_to_Rep_Trading_Id__c).get(py.get(trade.fund_number__c)[1]))+trade.Number_of_Shares_of_the_transaction__c);
                }
				contacts.get(trade.Resolved_to_Rep_Trading_Id__c).put(total.get(trade.fund_number__c)[0], ((Decimal)contacts.get(trade.Resolved_to_Rep_Trading_Id__c).get(total.get(trade.fund_number__c)[0]))+trade.Dollar_Amount_of_The_Transaction__c);
				contacts.get(trade.Resolved_to_Rep_Trading_Id__c).put(total.get(trade.fund_number__c)[1], ((Decimal)contacts.get(trade.Resolved_to_Rep_Trading_Id__c).get(total.get(trade.fund_number__c)[1]))+trade.Number_of_Shares_of_the_transaction__c);
            }
        }
    }
}

 

SeanCenoSeanCeno

Line 75: Method does not exist or incorrect signature: [Integer].intValue()

 

if( (date.today().month()/3).intValue() == (trade.trade_date__c.month()/3).intValue() ) {

 Does this need to be changed to something like this?

 

if( (Decimal.ValueOf(date.today().month()).divide(3, 0) == Decimal.ValueOf(trades.trade_date__c.month()).divide(3, 0)) )   {

 

SeanCenoSeanCeno

Basically I've been having trouble with that set of code in particular and have been trying to fix it.

 

Changed line 75 to this:

 

if( (Decimal.ValueOf(date.today().month()).divide(3, 0) == Decimal.ValueOf(trade.trade_date__c.month()).divide(3, 0)) )   {

 it saves successfully, and when I post a trade in the Sandbox, it saves it, but the values are not effected. In other words the fields are not updating.

 

My trigger:

 

trigger Contact_RollupTrades on Contact (before update) {
		Set<ID> sID = new Set<ID>(trigger.newMap.keySet());
    
    	new Contact_RollupTrades(sID).execute();
    
}

 Associated Class:

 

public class Trades_CascadeContacts {
    public Trades__c[] tradesOldList { set; get; }
    public Trades__c[] tradesNewList { set; get; }
    public Map<Id, Trades__c> tradesOldListMap { set; get; }
    
    public Trades_CascadeContacts(Trades__c[] tradesOldList, Trades__c[] tradesNewList) {
        this.tradesNewList = tradesNewList == null ? new Trades__c[] {} : tradesNewList.clone();
        this.tradesOldList = tradesOldList == null ? new Trades__c[] {} : tradesOldList.clone();
        this.tradesOldListMap = new Map<Id, Trades__c>(this.tradesOldList);
    }
    
    public void execute() {
        Set<Id> tradesContactIds = new Set<Id> {};
        
        for(Trades__c tradesNew : tradesNewList) {
            Trades__c tradesOld = tradesOldListMap.get(tradesNew.Id);
            tradesOld = tradesOld == null ? new Trades__c() : tradesOld;
            
            tradesContactIds.add(tradesOld.Resolved_to_Rep_Trading_ID__c);
            tradesContactIds.add(tradesNew.Resolved_to_Rep_Trading_ID__c);
        }
        
        if (tradesContactIds.size() == 0)
            return;
        
        Contact[] contactList = new Contact[] {};
        
        for(Id contactId : tradesContactIds) {
            if (contactId == null)
                continue;
            
            Contact contact = new Contact(Id = contactId);
            contact.Rollup_Trades__c = null;
            contactList.add(contact);
        }
        
        update contactList;
    }
}

 Associated Trigger:

 

trigger Trades_CascadeContacts on Trades__c (after delete, after insert, after undelete, after update) {
	    Trades__c[] tradesOldList = trigger.IsDelete ? null : trigger.old;
        Trades__c[] tradesNewList = trigger.IsDelete ? trigger.old : trigger.new;
        new Trades_CascadeContacts(tradesOldList, tradesNewList).execute();
    
}

 

 

SeanCenoSeanCeno

Here is the following code that worked:

 

Had to do a little bit of editing on this class:

 

public class Contact_RollupTrades {
    public Static Contact_Setting__c setting = Contact_Setting__c.getInstance();
	public static boolean inprog = false;

    public static void execute(Set<Id> contactIds, List<Contact> contactsList) {
        Map<Id, Contact> contacts = new Map<Id, Contact>(ContactsList);
        system.debug('execut');
        if(setting.Disable_Contact_Rollup__c != true) {
            //Map<Id, Contact> contacts = new Map<Id, Contact>();
            for(Id contactId:contactIds) {
                system.debug(contactid);
                contacts.put(contactId,
                    new Contact(
                        Id=contactId,				 Total_NIOR_I_Sales__c = 0, Total_NIOR_I_Shares__c = 0,	YTD_NIOR_I_Sales__c = 0,
                        YTD_NIOR_I_Shares__c = 0,	 QTD_NIOR_I_Sales__c = 0,	QTD_NIOR_I_Shares__c = 0,	MTD_NIOR_I_Sales__c = 0,
                        MTD_NIOR_I_Shares__c = 0,	 PY_NIOR_I_Sales__c = 0,	PY_NIOR_I_Shares__c = 0,	Total_NS_REIT_Sales__c = 0,
                        Total_NS_REIT_Shares__c = 0, YTD_NS_REIT_Sales__c = 0,	YTD_NS_REIT_Shares__c = 0,	QTD_NS_REIT_Sales__c = 0,
                        QTD_NS_REIT_Shares__c = 0,	 MTD_NS_REIT_Sales__c = 0,	MTD_NS_REIT_Shares__c = 0,	PY_NS_REIT_Sales__c = 0,
                        PY_NS_REIT_Shares__c = 0,	 Total_NS_HIT_Sales__c = 0, Total_NS_HIT_Shares__c = 0,	YTD_NS_HIT_Sales__c = 0,
                        YTD_NS_HIT_Shares__c = 0,	 QTD_NS_HIT_Sales__c = 0,	QTD_NS_HIT_Shares__c = 0,	MTD_NS_HIT_Sales__c = 0,
                        MTD_NS_HIT_Shares__c = 0,	 PY_NS_HIT_Sales__c = 0,	PY_NS_HIT_Shares__c = 0,	Rollup_Trades__c = DateTime.now()
                    )
                );
                system.debug(contacts.get(contactId).FirstName);
            }

            Trades__c[] tradesList = [
                select Dollar_Amount_of_the_transaction__c, Fund_Number__c, Number_of_Shares_of_the_transaction__c,
                     Resolved_to_Rep_Trading_ID__c, Resolved_Firm_Trading_ID__c, Resolved_Firm_Trading_IDs__c,
                     Trade_Date__c
                from Trades__c
                where Resolved_to_Rep_Trading_ID__c in :contactIds
                   and Fund_Number__c in ('3910', '3911', '3912')       // NIOR I; NS REIT; NS HIT
                   and Dollar_Amount_of_the_transaction__c != null      // prevents null pointers below
                   and Number_of_Shares_of_the_transaction__c != null   // prevents null pointers below
                   and Trade_Date__c != null                            // prevents null pointers below
                   // Negative values are ignored for roll-up purposes
                   and Dollar_Amount_of_the_transaction__c >= 0
                   and Number_of_Shares_of_the_transaction__c >= 0
            ];

            Map<String, SObjectField[]>
                ytd = new map<string, sobjectfield[]> {
                    '3910' => new sobjectfield[] { contact.YTD_NIOR_I_Sales__c , contact.YTD_NIOR_I_Shares__c },
                    '3911' => new sobjectfield[] { contact.YTD_NS_REIT_Sales__c , contact.YTD_NS_REIT_Shares__c },
                    '3912' => new sobjectfield[] { contact.YTD_NS_HIT_Sales__c , contact.YTD_NS_HIT_Shares__c }
                },
                qtd = new map<string, sobjectfield[]> {
                    '3910' => new sobjectfield[] { contact.QTD_NIOR_I_Sales__c , contact.QTD_NIOR_I_Shares__c },
                    '3911' => new sobjectfield[] { contact.QTD_NS_REIT_Sales__c , contact.QTD_NS_REIT_Shares__c },
                    '3912' => new sobjectfield[] { contact.QTD_NS_HIT_Sales__c , contact.QTD_NS_HIT_Shares__c }
                },
                mtd = new map<string, sobjectfield[]> {
                    '3910' => new sobjectfield[] { contact.MTD_NIOR_I_Sales__c , contact.MTD_NIOR_I_Shares__c },
                    '3911' => new sobjectfield[] { contact.MTD_NS_REIT_Sales__c, contact.MTD_NS_REIT_Shares__c },
                    '3912' => new sobjectfield[] { contact.MTD_NS_HIT_Sales__c , contact.MTD_NS_HIT_Shares__c }
                },
                py = new map<string, sobjectfield[]> {
                    '3910' => new sobjectfield[] { contact.PY_NIOR_I_Sales__c , contact.PY_NIOR_I_Shares__c },
                    '3911' => new sobjectfield[] { contact.PY_NS_REIT_Sales__c , contact.PY_NS_REIT_Shares__c },
                    '3912' => new sobjectfield[] { contact.PY_NS_HIT_Sales__c , contact.PY_NS_HIT_Shares__c }
                },
                total = new map<string, sobjectfield[]> {
                    '3910' => new sobjectfield[] { contact.Total_NIOR_I_Sales__c , contact.Total_NIOR_I_Shares__c},
                    '3911' => new sobjectfield[] { contact.Total_NS_REIT_Sales__c , contact.Total_NS_REIT_Shares__c },
                    '3912' => new sobjectfield[] { contact.Total_NS_HIT_Sales__c , contact.Total_NS_HIT_Shares__c }
                };

            for(trades__c trade:tradeslist) {
                if(date.today().year() == trade.trade_date__c.year()) {
					contacts.get(trade.Resolved_to_Rep_Trading_Id__c).put(ytd.get(trade.fund_number__c)[0], ((Decimal)contacts.get(trade.Resolved_to_Rep_Trading_Id__c).get(ytd.get(trade.fund_number__c)[0]))+trade.Dollar_Amount_of_The_Transaction__c);
					contacts.get(trade.Resolved_to_Rep_Trading_Id__c).put(ytd.get(trade.fund_number__c)[1], ((Decimal)contacts.get(trade.Resolved_to_Rep_Trading_Id__c).get(ytd.get(trade.fund_number__c)[1]))+trade.Number_of_Shares_of_the_transaction__c);

                    if( (Decimal.ValueOf(date.today().month()).divide(3, 0) == Decimal.ValueOf(trade.trade_date__c.month()).divide(3, 0)) )   {
						contacts.get(trade.Resolved_to_Rep_Trading_Id__c).put(qtd.get(trade.fund_number__c)[0], ((Decimal)contacts.get(trade.Resolved_to_Rep_Trading_Id__c).get(qtd.get(trade.fund_number__c)[0]))+trade.Dollar_Amount_of_The_Transaction__c);
						contacts.get(trade.Resolved_to_Rep_Trading_Id__c).put(qtd.get(trade.fund_number__c)[1], ((Decimal)contacts.get(trade.Resolved_to_Rep_Trading_Id__c).get(qtd.get(trade.fund_number__c)[1]))+trade.Number_of_Shares_of_the_transaction__c);

                        if(date.today().month()==trade.trade_date__c.month()) {
							contacts.get(trade.Resolved_to_Rep_Trading_Id__c).put(mtd.get(trade.fund_number__c)[0], ((Decimal)contacts.get(trade.Resolved_to_Rep_Trading_Id__c).get(mtd.get(trade.fund_number__c)[0]))+trade.Dollar_Amount_of_The_Transaction__c);
							contacts.get(trade.Resolved_to_Rep_Trading_Id__c).put(mtd.get(trade.fund_number__c)[1], ((Decimal)contacts.get(trade.Resolved_to_Rep_Trading_Id__c).get(mtd.get(trade.fund_number__c)[1]))+trade.Number_of_Shares_of_the_transaction__c);
                        }
                    }
                } else if(date.today().year()-1==trade.trade_date__c.year()) {
					contacts.get(trade.Resolved_to_Rep_Trading_Id__c).put(py.get(trade.fund_number__c)[0], ((Decimal)contacts.get(trade.Resolved_to_Rep_Trading_Id__c).get(py.get(trade.fund_number__c)[0]))+trade.Dollar_Amount_of_The_Transaction__c);
					contacts.get(trade.Resolved_to_Rep_Trading_Id__c).put(py.get(trade.fund_number__c)[1], ((Decimal)contacts.get(trade.Resolved_to_Rep_Trading_Id__c).get(py.get(trade.fund_number__c)[1]))+trade.Number_of_Shares_of_the_transaction__c);
                }
				contacts.get(trade.Resolved_to_Rep_Trading_Id__c).put(total.get(trade.fund_number__c)[0], ((Decimal)contacts.get(trade.Resolved_to_Rep_Trading_Id__c).get(total.get(trade.fund_number__c)[0]))+trade.Dollar_Amount_of_The_Transaction__c);
				contacts.get(trade.Resolved_to_Rep_Trading_Id__c).put(total.get(trade.fund_number__c)[1], ((Decimal)contacts.get(trade.Resolved_to_Rep_Trading_Id__c).get(total.get(trade.fund_number__c)[1]))+trade.Number_of_Shares_of_the_transaction__c);
            }
        }
        inprog = true;
        update contacts.values();
        inprog = false;
    }
}

 

And change this trigger to 'after update':

trigger Contact_RollupTrades on Contact (after update) {
    if(contact_rollupTrades.inprog == false) {
        Set<ID> sID = new Set<ID>(trigger.newMap.keySet());
        Contact_RollupTrades.execute(sID, trigger.new);
    }
}

 

public class Trades_CascadeContacts {
    public Trades__c[] tradesOldList { set; get; }
    public Trades__c[] tradesNewList { set; get; }
    public Map<Id, Trades__c> tradesOldListMap { set; get; }
    
    public Trades_CascadeContacts(Trades__c[] tradesOldList, Trades__c[] tradesNewList) {
        this.tradesNewList = tradesNewList == null ? new Trades__c[] {} : tradesNewList.clone();
        this.tradesOldList = tradesOldList == null ? new Trades__c[] {} : tradesOldList.clone();
        this.tradesOldListMap = new Map<Id, Trades__c>(this.tradesOldList);
    }
    
    public void execute() {
        Set<Id> tradesContactIds = new Set<Id> {};
        
        for(Trades__c tradesNew : tradesNewList) {
            Trades__c tradesOld = tradesOldListMap.get(tradesNew.Id);
            tradesOld = tradesOld == null ? new Trades__c() : tradesOld;
            
            tradesContactIds.add(tradesOld.Resolved_to_Rep_Trading_ID__c);
            tradesContactIds.add(tradesNew.Resolved_to_Rep_Trading_ID__c);
        }
        
        if (tradesContactIds.size() == 0)
            return;
        
        Contact[] contactList = new Contact[] {};
        
        for(Id contactId : tradesContactIds) {
            if (contactId == null)
                continue;
            
            Contact contact = new Contact(Id = contactId);
            contact.Rollup_Trades__c = null;
            contactList.add(contact);
        }
        
        update contactList;
    }
}

 

trigger Trades_CascadeContacts on Trades__c (after delete, after insert, after undelete, after update) {
	    Trades__c[] tradesOldList = trigger.IsDelete ? null : trigger.old;
        Trades__c[] tradesNewList = trigger.IsDelete ? trigger.old : trigger.new;
        new Trades_CascadeContacts(tradesOldList, tradesNewList).execute();
    
}

 

Thanks for all your help!

sfdcfoxsfdcfox
Glad I could help. I know this code is "more difficult' to read, but unfortunately you've got so much code in there, it's the only way to get the performance you're looking for.
SeanCenoSeanCeno

Yeah there's a lot going on in it. It was a good experience learning a bit of dynamic apex as well. Really appreciate the help!

SeanCenoSeanCeno

I find it very strange that altering this code would affect another class. Especially a class that doesn't have much to do with trades except an updated Event when it happens. Is there an underlying issue you can think of?

 

public class Contact_UpdateEventDatesAndCount {
    protected final Contact[] contactNewList = new Contact[] {};
    protected final Contact[] contactOldList = new Contact[] {};
    
    public Contact_UpdateEventDatesAndCount(Contact[] contactOldList, Contact[] contactNewList) {
        this.contactNewList.addAll(contactNewList == null ? new Contact[] {} : contactNewList);
        this.contactOldList.addAll(contactOldList == null ? new Contact[] {} : contactOldList);
    }
    
    public void execute() {
        // Find all events associated to these contacts
        Event[] eventList = [
            select ActivityDate, WhoId
              from Event
             where WhoId in :contactNewList
        ];
        
        Map<Id, Contact> contactMap = new Map<Id, Contact>(contactNewList);
        
        for(Contact contact : contactNewList) {
            contact.Events_Prior_To_First_Trade_Date__c = 0;
            contact.Last_Event_Date__c = null;
        }
        
        for(Event event : eventList) {
            Contact contact = contactMap.get(event.WhoId);
            
            if (contact == null)
                continue;
            if (contact.Last_Event_Date__c == null)
                contact.Last_Event_Date__c = event.ActivityDate;
            else if (contact.Last_Event_Date__c < event.ActivityDate)
                contact.Last_Event_Date__c = event.ActivityDate;
            
            if (contact.First_Trade_date_for_the_Rep_Auto__c != null && event.ActivityDate > contact.First_Trade_date_for_the_Rep_Auto__c)
                continue; // event was after first trade date, so the rest of this is skipped
            
            contact.Events_Prior_To_First_Trade_Date__c ++;
        }
    }
}

 

trigger Contact_UpdateTradeDates on Contact (before update) {
    // see the tradeDateUpdate trigger. When these legacy fields are deleted this trigger can be deleted.
    
    for(Contact contact : trigger.new) {
        contact.First_Trade_date_for_the_Rep__c = contact.First_Trade_date_for_the_Rep_Auto__c;
        contact.Last_Trade_date_for_the_Rep__c = contact.Last_Trade_date_for_the_Rep_Auto__c;
    }
}

 

SeanCenoSeanCeno

Wrong trigger...sorry

 

trigger Contact_UpdateEventDatesAndCount on Contact (before update) {
    new Contact_UpdateEventDatesAndCount(trigger.old, trigger.new).execute();
}

 

sfdcfoxsfdcfox
I don't see any reason why that should be; we were working on another class entirely. What's the problem with that trigger now?
SeanCenoSeanCeno

Apologies. The developer I was working with that was running the trades test was running the test in production, not the sandbox, and didn't tell me. Everything it working well now.

SeanCenoSeanCeno
sfdcfox,
I'm revisiting this because this code has worked for the past 2 years, but we've gotten into a situation where we have grown as a firm and added new products. What's happening now is that when an Account gets past 9000 trades, we start to hit some governor limits, specifically CPU Limit error. I'm not sure if you'll get this notification, but if so I'd love if you could help me modify my code again. This is in a batch job, which should allow for 60 seconds, but the debug log is only returning 10 seconds.

One class updates the trades into the system, the next sums the trades into the correlating Account page.

CPU Limit Error Line 94: 25000/10000

Sales Summary Class
public class Account_RollupTrades {
    public Static Account_Setting__c setting = Account_Setting__c.getInstance();
    public Static boolean inprog = false;

    public static void execute (Set<Id> accountIds, List<Account> accountsList) {
        Map<Id, Account> accounts = new Map<Id, Account> (AccountsList);
        system.debug ('execute');
        if(setting.Disable_RollupTrades__c != true) {
            //Map<Id, Account> accounts = new Map<Id, Account>();
            for(Id accountId:accountIds) {
                system.debug(accountid);
                accounts.put(accountId,
                   new Account(
                       Id=accountId,
                       /**YTD_NIOR_I_Sales__c = 0,         YTD_NIOR_I_Shares__c = 0,         QTD_NIOR_I_Sales__c = 0,         QTD_NIOR_I_Shares__c = 0,
                       MTD_NIOR_I_Sales__c = 0,         MTD_NIOR_I_Shares__c = 0,         PY_NIOR_I_Sales__c = 0,           PY_NIOR_I_Shares__c = 0,
                       Total_NIOR_I_Sales__c = 0,       Total_NIOR_I_Shares__c = 0,       YTD_NS_Income_Sales__c = 0,       YTD_NS_Income_Shares__c = 0,
                       QTD_NS_Income_Sales__c = 0,      QTD_NS_Income_Shares__c = 0,      MTD_NS_Income_Sales__c = 0,       MTD_NS_Income_Shares__c = 0,
                       PY_NS_Income_Sales__c = 0,       PY_NS_Income_Shares__c = 0,       Total_NS_Income_Sales__c = 0,     Total_NS_Income_Shares__c = 0,**/
                       Total_NS_HI_Sales__c = 0,        Total_NS_HI_Shares__c = 0,        YTD_NS_HI_Sales__c = 0,           YTD_NS_HI_Shares__c = 0,
                       QTD_NS_HI_Sales__c = 0,          QTD_NS_HI_Shares__c = 0,          MTD_NS_HI_Sales__c = 0,           MTD_NS_HI_Shares__c = 0,
                       PY_NS_HI_Sales__c = 0,           PY_NS_HI_Shares__c = 0,           Total_NS_Income_II_Sales__c = 0,  Total_NS_Income_II_Shares__c = 0,
                       YTD_NS_Income_II_Sales__c = 0,   YTD_NS_Income_II_Shares__c = 0,   QTD_NS_Income_II_Sales__c = 0,    QTD_NS_Income_II_Shares__c = 0,
                       MTD_NS_Income_II_Sales__c = 0,   MTD_NS_Income_II_Shares__c = 0,   PY_NS_Income_II_Sales__c = 0,     PY_NS_Income_II_Shares__c = 0,
                       Total_NS_RXR_Sales__c = 0,       Total_NS_RXR_Shares__c = 0,       YTD_NS_RXR_Sales__c = 0,          YTD_NS_RXR_Shares__c = 0,
                       QTD_NS_RXR_Sales__c = 0,         QTD_NS_RXR_Shares__c = 0,         MTD_NS_RXR_Sales__c = 0,          MTD_NS_RXR_Shares__c = 0,
                       PY_NS_RXR_Sales__c = 0,          PY_NS_RXR_Shares__c = 0,          Rollup_Trades__c = DateTime.now()
                   )
                            );
            }
            Map<String, SObjectField[]>
                ytd = new map<string, sobjectfield[]> {
                    //'3910' => new sobjectfield[] { account.YTD_NIOR_I_Sales__c , account.YTD_NIOR_I_Shares__c},
                    //'3911' => new sobjectfield[] { account.YTD_NS_Income_Sales__c , account.YTD_NS_Income_Shares__c },
                    '3912' => new sobjectfield[] { account.YTD_NS_HI_Sales__c , account.YTD_NS_HI_Shares__c },
                    '3915' => new sobjectfield[] { account.YTD_NS_Income_II_Sales__c , account.YTD_NS_Income_II_Shares__c },
                    '3960' => new sobjectfield[] { account.YTD_NS_RXR_Sales__c, account.YTD_NS_RXR_Shares__c}
                },
                qtd = new map<string, sobjectfield[]> {
                    //'3910' => new sobjectfield[] { account.QTD_NIOR_I_Sales__c , account.QTD_NIOR_I_Shares__c},
                    //'3911' => new sobjectfield[] { account.QTD_NS_Income_Sales__c , account.QTD_NS_Income_Shares__c },
                    '3912' => new sobjectfield[] { account.QTD_NS_HI_Sales__c , account.QTD_NS_HI_Shares__c },
                    '3915' => new sobjectfield[] { account.QTD_NS_Income_II_Sales__c , account.QTD_NS_Income_II_Shares__c },
                    '3960' => new sobjectfield[] { account.QTD_NS_RXR_Sales__c, account.QTD_NS_RXR_Shares__c}
                },
                mtd = new map<string, sobjectfield[]> {
                    //'3910' => new sobjectfield[] { account.MTD_NIOR_I_Sales__c , account.MTD_NIOR_I_Shares__c},
                    //'3911' => new sobjectfield[] { account.MTD_NS_Income_Sales__c , account.MTD_NS_Income_Shares__c },
                    '3912' => new sobjectfield[] { account.MTD_NS_HI_Sales__c , account.MTD_NS_HI_Shares__c },
                    '3915' => new sobjectfield[] { account.MTD_NS_Income_II_Sales__c , account.MTD_NS_Income_II_Shares__c },
                    '3960' => new sobjectfield[] { account.MTD_NS_RXR_Sales__c, account.MTD_NS_RXR_Shares__c}
                },
                py = new map<string, sobjectfield[]> {
                    //'3910' => new sobjectfield[] { account.PY_NIOR_I_Sales__c , account.PY_NIOR_I_Shares__c},
                    //'3911' => new sobjectfield[] { account.PY_NS_Income_Sales__c , account.PY_NS_Income_Shares__c },
                    '3912' => new sobjectfield[] { account.PY_NS_HI_Sales__c , account.PY_NS_HI_Shares__c },
                    '3915' => new sobjectfield[] { account.PY_NS_Income_II_Sales__c , account.PY_NS_Income_II_Shares__c },
                    '3960' => new sobjectfield[] { account.PY_NS_RXR_Sales__c, account.PY_NS_RXR_Shares__c}
                },
                total = new map<string, sobjectfield[]> {
                    //'3910' => new sobjectfield[] { account.Total_NIOR_I_Sales__c , account.Total_NIOR_I_Shares__c},
                    //'3911' => new sobjectfield[] { account.Total_NS_Income_Sales__c , account.Total_NS_Income_Shares__c },
                    '3912' => new sobjectfield[] { account.Total_NS_HI_Sales__c , account.Total_NS_HI_Shares__c },
                    '3915' => new sobjectfield[] { account.Total_NS_Income_II_Sales__c , account.Total_NS_Income_II_Shares__c },
                    '3960' => new sobjectfield[] { account.Total_NS_RXR_Sales__c, account.Total_NS_RXR_Shares__c}
                };
    
    // We make the select in a "for" so instead of selecting to many records at once hitting the heap size limit the for it will take only 200 records to work with at each iteration.
    for(Trades__c[] tradesList : [select Dollar_Amount_of_the_transaction__c, Fund_Number__c, Number_of_Shares_of_the_transaction__c, Resolved_Firm_Trading_ID__c, Resolved_Firm_Trading_IDs__c, Trade_Date__c from Trades__c where Resolved_Firm_Trading_ID__c in :accountIds and Fund_Number__c in (/**'3910', '3911',**/ '3912', '3915', '3960') and Dollar_Amount_of_the_transaction__c != null and Number_of_Shares_of_the_transaction__c != null and Trade_Date__c != null and Dollar_Amount_of_the_transaction__c >= 0 and Number_of_Shares_of_the_transaction__c >= 0 FOR UPDATE]){
        for(trades__c trade: tradesList) {
            
            if(date.today().year() == trade.trade_date__c.year()) {
                accounts.get(trade.Resolved_Firm_Trading_ID__c).put(ytd.get(trade.fund_number__c)[0], ((Decimal)accounts.get(trade.Resolved_Firm_Trading_ID__c).get(ytd.get(trade.fund_number__c)[0]))+trade.Dollar_Amount_of_The_Transaction__c);
                accounts.get(trade.Resolved_Firm_Trading_ID__c).put(ytd.get(trade.fund_number__c)[1], ((Decimal)accounts.get(trade.Resolved_Firm_Trading_ID__c).get(ytd.get(trade.fund_number__c)[1]))+trade.Number_of_Shares_of_the_transaction__c);
                //system.debug(ytd);
                //system.debug(LoggingLevel.DEBUG, + Limits.getCpuTime() + '/' + Limits.getLimitCpuTime());
                
                //( (date.ValueOf(date.today().month()).divide(3, 0) == date.ValueOf(trade.trade_date__c.month()).divide(3, 0)) )
                if((((date.today().month() - 1) / 3) + 1) == (((trade.Trade_Date__c.month() - 1) / 3) + 1))   {
                    accounts.get(trade.Resolved_Firm_Trading_ID__c).put(qtd.get(trade.fund_number__c)[0], ((Decimal)accounts.get(trade.Resolved_Firm_Trading_ID__c).get(qtd.get(trade.fund_number__c)[0]))+trade.Dollar_Amount_of_The_Transaction__c);
                    accounts.get(trade.Resolved_Firm_Trading_ID__c).put(qtd.get(trade.fund_number__c)[1], ((Decimal)accounts.get(trade.Resolved_Firm_Trading_ID__c).get(qtd.get(trade.fund_number__c)[1]))+trade.Number_of_Shares_of_the_transaction__c);
                    //system.debug(qtd);
                    //system.debug(LoggingLevel.DEBUG, + Limits.getCpuTime() + '/' + Limits.getLimitCpuTime());
                    
                    if(date.today().month()==trade.trade_date__c.month()) {
                        accounts.get(trade.Resolved_Firm_Trading_ID__c).put(mtd.get(trade.fund_number__c)[0], ((Decimal)accounts.get(trade.Resolved_Firm_Trading_ID__c).get(mtd.get(trade.fund_number__c)[0]))+trade.Dollar_Amount_of_The_Transaction__c);
                        accounts.get(trade.Resolved_Firm_Trading_ID__c).put(mtd.get(trade.fund_number__c)[1], ((Decimal)accounts.get(trade.Resolved_Firm_Trading_ID__c).get(mtd.get(trade.fund_number__c)[1]))+trade.Number_of_Shares_of_the_transaction__c);
                        //system.debug(mtd);
                        //system.debug(LoggingLevel.DEBUG, + Limits.getCpuTime() + '/' + Limits.getLimitCpuTime());
                    }
                }
            } 
            else if(date.today().year()-1==trade.trade_date__c.year()) {
                accounts.get(trade.Resolved_Firm_Trading_ID__c).put(py.get(trade.fund_number__c)[0], ((Decimal)accounts.get(trade.Resolved_Firm_Trading_ID__c).get(py.get(trade.fund_number__c)[0]))+trade.Dollar_Amount_of_The_Transaction__c);
                accounts.get(trade.Resolved_Firm_Trading_ID__c).put(py.get(trade.fund_number__c)[1], ((Decimal)accounts.get(trade.Resolved_Firm_Trading_ID__c).get(py.get(trade.fund_number__c)[1]))+trade.Number_of_Shares_of_the_transaction__c);
                //system.debug(py);
                //system.debug(LoggingLevel.DEBUG, + Limits.getCpuTime() + '/' + Limits.getLimitCpuTime());
            }
            accounts.get(trade.Resolved_Firm_Trading_ID__c).put(total.get(trade.fund_number__c)[0], ((Decimal)accounts.get(trade.Resolved_Firm_Trading_ID__c).get(total.get(trade.fund_number__c)[0]))+trade.Dollar_Amount_of_The_Transaction__c);
            accounts.get(trade.Resolved_Firm_Trading_ID__c).put(total.get(trade.fund_number__c)[1], ((Decimal)accounts.get(trade.Resolved_Firm_Trading_ID__c).get(total.get(trade.fund_number__c)[1]))+trade.Number_of_Shares_of_the_transaction__c);
            //system.debug(total);
            //system.debug(LoggingLevel.DEBUG, + Limits.getCpuTime() + '/' + Limits.getLimitCpuTime());
        }
            }
        }
        inprog = true;
        update accounts.values();
        inprog = false;
    }
}

Trigger:
trigger Account_RollupTrades on Account (after update) {
    if(Account_RollupTrades.inprog == false) {
        //set<ID> sID = new set<ID> (trigger.newMap.keySet());
        Account_RollupTrades.execute(trigger.newMap.keySet(), trigger.new);
    }
}

Trades Class
public class Trades_CascadeAccounts {
    public Trades__c[] tradesOldList { set; get; }
    public Trades__c[] tradesNewList { set; get; }
    public Map<Id, Trades__c> tradesOldListMap { set; get; }
    
    public Trades_CascadeAccounts(Trades__c[] tradesOldList, Trades__c[] tradesNewList) {
        this.tradesNewList = tradesNewList == null ? new Trades__c[0] : tradesNewList.clone();
        this.tradesOldList = tradesOldList == null ? new Trades__c[0] : tradesOldList.clone();
        this.tradesOldListMap = new Map<Id, Trades__c>(this.tradesOldList);
    }
    
    public void execute() {
        Set<Id> tradesAccountIds = new Set<Id> {};
            for(Trades__c tradesNew : tradesNewList) {
                Trades__c tradesOld = tradesOldListMap.containsKey(tradesNew.Id) ? tradesOldListMap.get(tradesNew.Id) : new Trades__c();
                tradesAccountIds.addAll(new Set<Id> { tradesOld.Resolved_Firm_Trading_ID__c, tradesNew.Resolved_Firm_Trading_ID__c });
            }
        tradesAccountIds.remove(null);
        
        Account[] accountList = new Account[0];
        for(Id accountId : tradesAccountIds) {
            accountList.add(new Account(Id=AccountId,Rollup_Trades__c=null));
        }
        update accountList;
        //System.debug('Total Number of script statements allowed in this apex code context: ' +  Limits.getLimitScriptStatements());  
    }
}

Trigger:
trigger Trades_CascadeAccounts on Trades__c (after delete, after insert, after undelete, after update) {
    Trades__c[] tradesOldList = trigger.IsDelete ? null : trigger.old;
    Trades__c[] tradesNewList = trigger.IsDelete ? trigger.old : trigger.new;
    new Trades_CascadeAccounts(tradesOldList, tradesNewList).execute();
}

 
simply buzzes 9simply buzzes 9
Awesom no doubt but there are alot of issues that i am facing on my site (https://trustedbrokers.com/uk/) you can check . but if you are an expert then could you please recommend me what should i do to optimize my site progress.