Is essentially that I'm going to hit limits and I know there are better ways to code this. If I'm correct, I'll have to store all current records into a map, then loop over that map X amount of times to check if it already exists?
This is a pretty good summary. Looking at your code, I think what you need to change is this.
for(Integer i = 0; i < 120; i++){
currentDate = Date.today();
firstDayOfCurrentMonth = currentDate.addMonths(i).toStartofMonth();
lastDayOfCurrentMonth = currentDate.addMonths(i + 1).toStartofMonth().addDays(-1);
Instead of going straight to the generation of the Accounting Periods, let's generate a Set
representing the key data points that define an already-existing Accounting Period. If that is the start date, for example, build a Set<Date>
, and populate it with all the values you generate for firstDayOfCurrentMonth
.
List<AcctSeed__Accounting_Period__c> checkAccountingPeriodAlreadyExist = [SELECT Id, AcctSeed__Start_Date__c, AcctSeed__End_Date__c FROM AcctSeed__Accounting_Period__c where AcctSeed__Start_Date__c = :firstDayOfCurrentMonth];
This query is the key limits problem. It needs to be run exactly once, outside the for
loop. If you generate a Set<Date> firstDaysOfMonths
as mentioned above, you could change the query to
List<AcctSeed__Accounting_Period__c> checkAccountingPeriodAlreadyExist = [SELECT Id, AcctSeed__Start_Date__c, AcctSeed__End_Date__c FROM AcctSeed__Accounting_Period__c where AcctSeed__Start_Date__c IN :firstDaysOfMonths];
Now we could, for fast O(1) access to determine if a given Accounting Period exists, convert this List
into a Map<Date, AcctSeed__Accounting_Period__c> apMap
, where the keys are the start dates, and then look at that Map while we iterate over the numbers 1 to 120 again to determine which records need to be created.
I actually think there's a faster way, though. Iterate over this list, and remove from the Set<DateSet<Date>
all those records you already found:
for (AcctSeed__Accounting_Period__c ap : checkAccountingPeriodAlreadyExist) {
firstDaysOfMonths.remove(ap.AcctSeed__Start_Date__c);
}
Then, lastly, you can iterate over the remaining start datesStart Dates that you generated in the first loop, build an Accounting Period for each one, and finally insert a single list of all the generated Accounting Periods.
If my thesis that the Start Date is unique was false, you can still follow something like this process; you'd just make changes to use a different field or combination of fields as your unique key, and the logic might be slightly more complex.