You need to sign in to do that
Don't have an account?
KCali12
Using map to insert records with unique field combinations
I've never used a map in an Apex class before, but I think this scenario requires one, and I need help.
I have a custom object called Time_Allocation__c with the following fields:
With my batch Apex, which is querying all Time_Allocation__c records where the Time_Sheet_Allocated_Hrs__c field is null, I need to do the following:
After putting the values I want in the map, how do pick out the values to create the individual Time_Sheet_Allocated_Hrs__c records that I want to insert? Again, I only want one record for each Time_Sheet_c/Unit_Subunit__c combination, so I also need to figure out how to avoid creating duplicates.
Do I need a map of a map to do this? If so, what syntax do I use?
Thanks for any guidance you can offer.
I have a custom object called Time_Allocation__c with the following fields:
- Unit_Subunit__c (Formula field - string)
- Time_Sheet_Allocated_Hrs__c (Lookup to to Time_Sheet_Allocated_Hrs__c object)
- Time_Sheet__c (Lookup to Time_Sheet__c object)
With my batch Apex, which is querying all Time_Allocation__c records where the Time_Sheet_Allocated_Hrs__c field is null, I need to do the following:
- Create one Time_Sheet_Allocated_Hrs record for each Time_Sheet__c/Unit_Subunit__c combination.
- Populate the Time_Allocation__c record with the appropriate Time_Sheet_Allocated_Hrs__c lookup field (based on the appropriate Time_Sheet_c/Unit_Subunit__c combo.
global class TSAllocatedHrsBatch implements Database.Batchable<sObject>{ global Database.QueryLocator start(Database.BatchableContext bc){ return Database.getQueryLocator( [SELECT Id, Time_Sheet_Allocated_Hrs__c, Time_Sheet__c, Unit_Subunit__c from Time_Allocation__c where Type__c = 'Program Time' AND Time_Sheet_Allocated_Hrs__c = null order by Time_Sheet__c]); } global void execute(Database.BatchableContext bc, List<Time_Allocation__c> batchList){ Set<Id>taIds = new Set<Id>(); Set<String>UnitSubList = new Set<String>(); Set<Id>TimeSheetIds = new Set<Id>(); for (Time_Allocation__c ta : batchList){ taIds.add(ta.Id); UnitSubList.add(ta.Unit_Subunit__c); TimeSheetIds.add(ta.Time_Sheet__c); Map<Id,String> tsAllHrsMap = new Map<Id, String>(); tsAllHrsMap.put(ta.Time_Sheet__c, ta.Unit_Subunit__c); } //Now what? List<Time_Sheet_Allocated_Hrs__c> tsAllHrsListInsert = new List<Time_Sheet_Allocated_Hrs__c>(); insert tsAllHrsListInsert; } global void finish(Database.BatchableContext bc) { } }
After putting the values I want in the map, how do pick out the values to create the individual Time_Sheet_Allocated_Hrs__c records that I want to insert? Again, I only want one record for each Time_Sheet_c/Unit_Subunit__c combination, so I also need to figure out how to avoid creating duplicates.
Do I need a map of a map to do this? If so, what syntax do I use?
Thanks for any guidance you can offer.
you are on the write track, but with the Map use a key that is Time_sheet_Id and Unit_Subunit.
The last post in this thread has some code which should point you in the right direction.
https://developer.salesforce.com/forums/ForumsMain?id=9062I000000Xy3iQAC
What I am assuming is that each Time_Allocation__c record is unique based on Time Sheet and Unit Subunit.
However, using Maps in this way may not exclude duplication of Time_Sheet_Allocated_Hrs records based on Timesheet and UnitSubunit as it would not check for duplicates across different batch runs for the code.
Also, your code here would actually clear the map on each loop and at the end of the loop you would have just one record in the map. In this instance, you would have the Map declared outside the loop. Also, if we consider the behaviours of Map, that Map would only have one record per timesheet, as the timesheet would be the unique key and a second entry with the same timesheet would overwrite the value in the map.
Consider 3 Time_Allocation__c records with values
Timesheet 1 + Subunit A
Timesheet 2 + Subunit B
Timesheet 1 + Subunit C
Since "timesheet #" is the unique key, the Map (even if declared outside the loop), would contain two entries.
Timesheet 2 , Subunit B
Timesheet 1, Subunit C (since the value of Subunit A would have been overwritten due to the same key).
I hope the above proves helpful
Reagards
Andrew
Unfortunately, the Time_Allocation__c record is NOT unique based on Time Sheet and Unit_Subunit. Per time sheet, I will usually have 10 time allocations for that time sheet/unit_subunit combo, essentially one for each day in the pay period.
I have a flow that, upon edit of a Time_Allocation__c record where the Time_Sheet_Allocated_Hrs__c lookup field is null, will query if a Time Sheet Allocated Hrs with that unique Time Sheet/Unit_Subunit combination exists ... and if it doesn't, it will create one and relate ... if it does, it will just simply relate that record to my Time Allocation. That totally works on an individual basis, but it does not work, obviously, when a bunch of time allocation records are edited or inserted at once. Even if I trigger that flow in a batch class with a size of 10, for example, I am getting duplicate Time Sheet Allocated Hrs records for each Time Sheet/UnitSubunit combination. If I can't figure out how to write a proper Apex class to make this happen, I have a thought to trigger that flow in a batch class with a size of 1 and run it over night, but I know that's a really bad way to do this. :)
Hi KCali
Here is what i think your data diagram looks like: (pardon it's crudeness).
And the process:
For a given Timesheet (TS), which I assume is a reflection of a fortnight's (FN) work (possbily for a given employee) , there can be 1 or more Timesheet Allocation Hours (TSAH) and 1 or more Timesheet Allocations (TA).
A TSAH has a field to indicate a SubUnit (which i interpret to be a Type of work e.g Admin, Development, Design) This is used so that the fortnight TS you can break down Admin work versus Dev Work.
A user will create a TA in which they select only the TS (potentially their own) and the Subunit (e.g Development). On save, you want to populate the TSAH field, by either creating a new record or finding an existing record.
I am assuming this model as you will roll up the summary of hours into the TS and the TSAH for payroll and reporting purposes (respectively).
If the above is correct, with exception to some of my wording in my previous post, the logic in that post should work.
here is the Psuedo code which i think should solve the issue.
Noting the above, I would look to build some methods to handle the repetitive stuff, like building the Map and you could also do one for the assigning of TSAH to TAs (pass the List and the Map to the method)
Regards
Andrew