3

I have 4 very similar code blocks in a trigger that deal with synchronizing record type changes from Opportunity to its children. The only difference between them is that they do work on different custom objects. Since the actual work they do is identical, it seems like I should be able to combine them using a generic object type but I'm a little fuzzy on how to do it (assuming I even should).

(Note: I'm interested in general best practice here, not how to refactor specific code. Links are acceptable!)

My repetitive code looks something like this:

trigger OpportunityTrigger on Opportunity (before insert, after insert, before update, after update, before delete, after delete) {
    if (Trigger.isAfter && Trigger.isUpdate) {
        // Get record type map
        List<String, Id> rtMap = OpportunityHelper.getRecordTypeMap();

        // Update lists
        List<Custom_Object1__c> obj1Updates = new List<Custom_Object1__c>();
        List<Custom_Object2__c> obj2Updates = new List<Custom_Object1__c>();

        // Get object 1 records
        List<Custom_Object1__c> obj1List = [
            SELECT
                Id,
                Opportunity__c,
                RecordTypeId
            FROM Custom_Object1__c
            WHERE Opportunity__c IN : Trigger.newMap.keyset()
        ];

        // Get object 2 records
        List<Custom_Object2__c> obj2List = [
            SELECT
                Id,
                Opportunity__c,
                RecordTypeId
            FROM Custom_Object2__c
            WHERE Opportunity__c IN : Trigger.newMap.keyset()
        ];

        // Map to opportunities
        Map<Id, List<Custom_Object1__c>> oppId2Obj1Map = OpportunityHelper.mapify(obj1List);
        Map<Id, List<Custom_Object2__c>> oppId2Obj2Map = OpportunityHelper.mapify(obj2List);

        for (Opportunity o : Trigger.new) {
            // Get record type of opportunity
            String rtOpportunity = OpportunityHelper.getRecordTypeName(o.RecordTypeId);

            // Get opportunity children
            List<Custom_Object1__c> obj1List = oppId2Obj1Map.get(o.Id);
            List<Custom_Object2__c> obj2List = oppId2Obj2Map.get(o.Id);

            // Sync up obj1 record types
            for (Custom_Object1__c obj1 : obj1List) {
                // Get record type names of child
                String rtObj1 = OpportunityHelper.getRecordTypeName(obj1.RecordTypeId);

                // If record types don't match, change the record type of obj1
                if (rtOpportunity <> rtObj1) {
                    obj1.RecordTypeId = rtMap.get(rtOpportunity);
                    obj1Updates.add(obj1);
                }
            }

            // Sync up obj2 record types
            for (Custom_Object2__c obj2 : obj2List) {
                // Get record type names of child
                String rtObj2 = OpportunityHelper.getRecordTypeName(obj2.RecordTypeId);

                // If record types don't match, change the record type of obj2
                if (rtOpportunity <> rtObj2) {
                    obj2.RecordTypeId = rtMap.get(rtOpportunity);
                    obj2Updates.add(obj2);
                }
            }
        }

        // Process record type changes
        if (obj1Updates.size() > 0) update obj1Updates;
        if (obj2Updates.size() > 0) update obj2Updates;
    }
}

So...is there some way I can use a generic object type to minimize my repetitive code here? Maybe a function prototype I can pass the object name into?

Something more like...

...

List<sObject> stuffToUpdate1 = newList<sObject>();
List<sObject> stuffToUpdate2 = newList<sObject>();

for (Opportunity o : Trigger.new) {
    stuffToUpdate1.add(syncRecordTypes('Custom_Object1__c', o));
    stuffToUpdate2.add(syncRecordTypes('Custom_Object2__c', o));
}

if (stuffToUpdate1.size() > 0) update stuffToUpdate1;
if (stuffToUpdate2.size() > 0) update stuffToUpdate2;

...

private static List<Object> syncRecordTypes(String sObjName, Opportunity opp) {
    // ???
}
6

You can use Sobject get and put method to your advantage. This allows you to dynamically refer and set fiels in any Salesforce Record .

I would go by adding all children in a Generic List, then iterate over it and assign new recordTypeId accordingly.

So my code will be like:

List<Sobject> genericChildList = new List<Sobject>();
genericChildList.addAll(oppId2Obj1Map.get(o.Id)); //add child 1
genericChildList.addAll(oppId2Obj2Map.get(o.Id)); //add child 2

String rtOpportunity = OpportunityHelper.getRecordTypeName(o.RecordTypeId);
for(Sobject child : genericChildList){

    if(OpportunityHelper.getRecordTypeName(child.get('RecordTypeId')) != rtOpportunity ){
        child.put('RecordTypeId',rtMap.get(rtOpportunity));
    }

}


update genericChildList;

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.