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
Silpi roy 16Silpi roy 16 

Help with trigger code correction

Please help me in updating the trigger code ,
Requirement is If the record is first created based on created date then set the checkbox as true.

trigger updateForecastMassUIpdateFields on ForecastSchedule__c (before insert, before update) {

for (ForecastSchedule__c fs:trigger.new)
    {
        /*List<Period> p=[SELECT Number , FiscalYearSettings.Name  FROM Period WHERE Type = 'Month' AND StartDate <=: fs.date__c AND EndDate >=: fs.date__c];   
    
        for(Period p1:p)
        {
            fs.fiscal_period__c=p1.number + '-' + p1.FiscalYearSettings.Name;
        }
        for ( Case c1 : [select id, name from case where id in (<ids>) ])

        {

        }*/
        if(fs.IsBudget__c==true || fs.SourceType__c=='4 - Budget')  
        {
            if(fs.Budget_Quantity__c==0 || fs.Budget_Quantity__c==null)
            {
                fs.Budget_Unit_Price__c=fs.UnitPrice__c;
                fs.Budget_Quantity__c=fs.Quantity__c;
                fs.Budget_Revenue__c=fs.Revenue__c;
                fs.Budget_Revenue_in_EUR__c=fs.RevenueInEUR__c;
            }
            else
            {
                fs.UnitPrice__c=fs.Budget_Unit_Price__c;
                fs.Quantity__c=fs.Budget_Quantity__c;
                //fs.Revenue__c=fs.Budget_Revenue__c;
                //fs.RevenueInEUR__c=fs.Budget_Revenue_in_EUR__c;
            }
         List<ForecastSchedule__c> FSList=[Select Id,Name,FC_quantity__c,FC_Revenue__c,FC_Unit_Price__c,ERPProductNr__c,Opportunity__c, Product2__c from ForecastSchedule__c order by CreatedDate asc LIMIT 1 ];
        if(FSList.size()>0){
        fs.isPrimary__c=True;
        }
        Update fs;
    }

}

Please help
abhishek singh 497abhishek singh 497

Hello, silpi,

Can you please better explain your requirement with each and every step?

Thanks & Regards,
Abhishek Singh.
 
Silpi roy 16Silpi roy 16
Hi Abhishek,

The requirement is there is a custom checkbox Primary and I want to make it true if the record is first .
Suppose there are 3 forecast record in a single month so I need to display the first record of that month as primary.
Forecast has different sources like SO,Billing,Budget.

Thanks!!
abhishek singh 497abhishek singh 497
Hello Silpi,

In before event, we don't need any DML statements so just remove update statement from your code.
Let me know after removing the update statement, your code is not working fine.

Thanks & Regards,
Abhishek Singh.
Silpi roy 16Silpi roy 16
no
 
Andrew GAndrew G
I do enjoy when people say their Trigger doesn't work, but provide no indication of what the issue is.  Lets quickly touch on issues that I can see and you can refine where the actual problem is.

1.   You say that you need to set the first created Forecast Schedule as Primary, yet your test is that if the query returns something, set the primary field to True.  Surely if something exists, then the one being created now cannot be first.

2.  You say that you need the first one created for the current month.  Where is your filter for the current month?  Is there a flag or a field in the Forecast Schedule that indicates the current month?

3. I imagine in your environment, there may be lots of Forecast Schedules, How are they related to ..... ? Is the Forecast Schedule for an Account?  A Sales Person?  How are we limiting the Forecast schedules? or is there only ever one for the entire environment?  Your query would indicate that it is the latter.

4.  You have a SELECT statement within a FOR loop - a big No-No for bulkification.

5. You have a single record Update within a FOR loop - another No-No.  Add the individual record to a list and then update the list of records once (outside the loop).

6.  We are interrogating the Created date, so logic would indicate that I only need to do this on creation, therefore before insert.  And when we think a little deeper, if this is happening before insert, why are we then trying to do an Update on the records with during the before insert - hence remove the update record we mentioned in point 5.

So thats the bad news that I can see.
Here is a version that will address points 1,2,4,5 & 6.
trigger updateForecastMassUIpdateFields on ForecastSchedule__c (before insert) {

	//declare a list of ForecastSchedules that we will update
	List<ForecastSchedule__c> fsToUpdate = New List<ForecastSchedule__c>;

	//declare and set some values to help in the SOQL 
	Integer mnth = System.Today().Month();
	Integer yr = System.Today().Year();
	//since I am only going to do a count on the records returned i will only grab the Id
	//since I am only going to do a count on the records there is no need to LIMIT the query to 1
	//since I am only going to do a count on the records there is no need to Sort the result
	List<ForecastSchedule__c> FSList=[Select Id from ForecastSchedule__c where CALENDAR_MONTH(CreatedDate) = :mnth and CALENDAR_YEAR(CreatedDate) = :yr ];

    //now I have my list of forecast schedules, I can start my loop
	for (ForecastSchedule__c fs:trigger.new) {
		if(fs.IsBudget__c==true || fs.SourceType__c=='4 - Budget')  {
			if(fs.Budget_Quantity__c==0 || fs.Budget_Quantity__c==null){
				fs.Budget_Unit_Price__c=fs.UnitPrice__c;
				fs.Budget_Quantity__c=fs.Quantity__c;
				fs.Budget_Revenue__c=fs.Revenue__c;
				fs.Budget_Revenue_in_EUR__c=fs.RevenueInEUR__c;
			}
			else {
				fs.UnitPrice__c=fs.Budget_Unit_Price__c;
				fs.Quantity__c=fs.Budget_Quantity__c;
			}

			if(FSList.size() == 0){  //nothing is in the list for Forecasts created this month, so this must be first
				fs.isPrimary__c=True;
				fsToUpdate.add(fs);
			}
			// Update fs;  //we don't update single records - bulkification issue - would be multiple DML
		}
	}  //end loop 
    //if I was going to do an update, it would occur here, however, we are doing a before insert, so no update required, the environment will do it.
	// Update fsToUpdate;  //the loop is over, so just do ONE update the list of records 
} 

Note, that I have had to make a few assumptions about how your code needs to work.  

I should also mention that the better practice is to create a TriggerHandler class with all the methods and code, and that all the Trigger does is to invoke the relevant parts of that class.


best of luck
Andrew

 
Silpi roy 16Silpi roy 16
Hi Andrew G,

Thanks a lot for such an elaborate inspection.
Anwers for ypur queries:
2.yes i had a field as display month which will display the month.
3.Forecasts are related with opportunity.A single opportunity can have multiple Forecast
User-added image
For your reference I have attached the screenshot.

 
Andrew GAndrew G
Hi

Based on the limitation by opportunity, i would recommend using AggregrateResult Object.
Here is an example of using it in a batch class, but there is enough explanation to determine how to use it:
https://developer.salesforce.com/forums/ForumsMain?id=9062I000000g9FEQAY
And here is the SF help documents
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/langCon_apex_SOQL_agg_fns.htm

Your aggregate query would looks something like:
AggregateResult[] groupedResults = [SELECT OpportunityId, Count(Id) fsCount FROM ForecastSchedule__c WHERE CALENDAR_MONTH(CreatedDate) = :mnth AND CALENDAR_YEAR(CreatedDate) = :yr  AND opportunityID In :opptyIDSet GROUP BY OpportunityId];

Best of luck

Andrew G