Scenario: Our company needs to preserve old "Abandoned" cases (due to employee departure, etc) for tracking/metrics purposes, but also need to be able to "Transfer" the cases to a new employee.
To accomplish this, we have a value of "Abandoned" in Case status, a custom picklist field called
Abandoned_Reason__c
with a value of "Transferred" and a custom lookup relationship calledTransfer_To__c
which is a lookup to User. When we mark a case as Abandoned/Transferred and set a Transfer To user,before update
apex is executed.The Apex does a .clone() on the oldMap of each record (to get the values prior to being marked Abandoned/Transferred), and updates the Owner on the newly cloned record to match the owner specified in the
Transfer_To__c
field on the old record.
Requirement: I also want to update the Parent Case field on the original case, the one that is now marked as Abandoned. Since I am in the before update
context I can manipulate these records still since they are not committed yet.
Problem: Since the record(s) being cloned haven't been inserted yet, there are no Ids, so I can't populate the Parent Case field on the old record until after the newly cloned records are inserted. However, there is no link between the newly inserted clone(s) and their original(s), so, while I can loop through the casesToInsert
after inserting them to get their Id, I have no way right now to identify which newly cloned and inserted case matches to which originally abandoned case.
Thoughts: I've spent a decent amount of time considering different approaches to this. I could create a custom self-lookup on Case where I store the old Case Id, making the new record a child of the old record, and then loop through the newly cloned/inserted records to build a Map<Id,Id>
where the Key is the Old_Case_Id__c field, and the value is the Id of the current case.
I would then loop through the Trigger.new context again, and using my map I would identify the key/val pair and update the Parent Case field on the old record to the value in the map.
Question: Before I went down this road, I wanted to reach out to the Stack community to see if there is a simpler or more elegant approach to this. Is there a better way that I could clone a record and then make the newly cloned record a parent of its old self, without doing this roundabout circular lookup reference?
Method Code below for reference:
public static void cloneTransferCases(Map<Id,Case> oldMap,List<Case> newList){
System.debug('MM++++ oldMap: ' + oldMap.keySet());
System.debug('MM++++ oldMap Values: ' + oldMap.values());
System.debug('MM++++ newList: ' + newList);
List<Case> casesToInsert = new List<Case>();
for(Case cs : newList){
// check to see if this record has been processed already in this transaction
if(!processedAbandonCloneRecords.contains(cs.Id)){
if(cs.Status == 'Abandoned'){
if(cs.Abandoned_Reason__c == 'Transferred' && oldMap.get(cs.Id).Abandoned_Reason__c != 'Transferred'){
if(cs.Transfer_To__c != null && cs.ParentId == null){
// Create a temporary case using oldMap
// to get field values prior to Abandonment
Case tempCase = oldMap.get(cs.Id).clone();
// set owner of new case to match the Transfer To user
tempCase.OwnerId = cs.Transfer_To__c;
tempCase.ParentId = null;
casesToInsert.add(tempCase);
// mark this record as processed in this transaction
processedAbandonCloneRecords.add(cs.Id);
// if we are running tests, insert and update will
// occur in same transaction so we should actually
// not stop cascade
if(Test.isRunningTest()){
processedAbandonCloneRecords.remove(cs.Id);
}
}
}
}
}
}
if(!casesToInsert.isEmpty()){
insert casesToInsert;
}
}