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
bpolbpol 

Concatenating onto the Master object from select Details objects

I am trying to create a field on a master object that is a concatenation of a field on a detail object when certain things are true.

 

In this particular case, "Student__c" is the master object and "Student_Call_Logs__c" is the detail object.  I'd like to pull the notes & dates field from the call log when the call is of a particular type... and stick this info into 1 field that would look like

 

"date -- note

 date -- note

 date -- note"

 

So far I have...

 

 

trigger CountRelatedCallLogs on Student_Call_Log__c (after insert, after update) { //define parameters //Student__c is the master object; Student_Call_Logs__c is the detail object String sid = null, note = null, techlogs = null, temp_note = null, temp_date = null; Integer i = null, counter=null; Set<Id> techlogids = new set<Id>(); techlogs = ''; counter = 0; Student_Call_Log__c [] scl = Trigger.new; sid = scl[0].Related_Student__c; Student_Call_Log__c [] relatedCLogs =[select id from Student_Call_Log__c where Related_Student__c = :sid and Call_Type__c = 'Avanza Tech Support' order by Call_Date_Time__c DESC]; for (Student_Call_Log__c cl : relatedCLogs) { temp_note = relatedCLogs[counter].Note__c; temp_date = relatedCLogs[counter].Call_Date__c techlogs = techlogs + temp_date + ' -- ' + temp_note + '\n'; counter = counter+1; }

 

So, I seem to be stuck in that I can't put the info into one 1 field AND I don't know how to pull the date and stick that into a text field.

 

Thanks!

 

 

Best Answer chosen by Admin (Salesforce Developers) 
bpolbpol

For me, this seems a bit too complex.  So here's what I came up with... that works!

 

 

// Establish the specific student Student_Call_Log__c [] scl = Trigger.new; sid = scl[0].Related_Student__c; // Establish the related call logs to that student Student_Call_Log__c [] relatedCLogs =[select id, Note__c, Call_Date_Time__c, Call_Type__c, Call_Results__c from Student_Call_Log__c where Related_Student__c = :sid order by Call_Date_Time__c DESC]; // Loop for all of the call logs related to the student // Create a field that adds the related fields to it on each loop for (Student_Call_Log__c cl : relatedCLogs) { techlogs = techlogs + String.valueOf(relatedCLogs[counter].Call_Date_Time__c) + ' -- ' + String.valueOf(relatedCLogs[counter].Call_Type__c) + ' -- ' + String.valueOf(relatedCLogs[counter].Call_Results__c) + ' -- ' + String.valueOf(relatedCLogs[counter].Note__c) + '\n'; counter = counter+1; } // Update the Student record with the new info s[0].tech_support_logs__c = techlogs; update s [0];

 

 

 

 

 

All Answers

CloudDevCloudDev

There's a number of ways to do this, the solution outline below is just one approach,, 

 

 

Part I

 

Create a Set of the Student Ids from the trigger. Then fire a single SOQL that queries back all log records where the Student id is in the set.

 

Set<Id> studentIds = new Set<Id>();

for (StudentLog sl : Trigger.new) {

    studentIds.add(sly.StudentId); // Sets hold unique values so no uniqueness check needed.

}

 

Map<Id, StudentLog> mapLog = new Map<Id, StudentLog>([select Id, [fields…] from StudentLog where StudentId in :studentIds]);

 

Enumerate the mapLog collection and build another map (mapStudentLog) that holds the Id of the Student against a list of the associated call logs.

 

Part II

 

Enumerate mapStudentLog, for each student in the map, create a Student object instance and set the Id, loop through the list of call logs and build your concatenated fields as single String variables, then set the summary fields on the student instance using those String vars. Finally add each Student instance to a List collection, say listUpdatedStudents.

 

Part III

 

call SaveResult[] res = Database.update(listUpdatedStudents);

 

BTW -adding a date to a text field shouldn't be more complex than String.valueof(myDate)..

 

Oh, and don't forget the after delete case..

bpolbpol

For me, this seems a bit too complex.  So here's what I came up with... that works!

 

 

// Establish the specific student Student_Call_Log__c [] scl = Trigger.new; sid = scl[0].Related_Student__c; // Establish the related call logs to that student Student_Call_Log__c [] relatedCLogs =[select id, Note__c, Call_Date_Time__c, Call_Type__c, Call_Results__c from Student_Call_Log__c where Related_Student__c = :sid order by Call_Date_Time__c DESC]; // Loop for all of the call logs related to the student // Create a field that adds the related fields to it on each loop for (Student_Call_Log__c cl : relatedCLogs) { techlogs = techlogs + String.valueOf(relatedCLogs[counter].Call_Date_Time__c) + ' -- ' + String.valueOf(relatedCLogs[counter].Call_Type__c) + ' -- ' + String.valueOf(relatedCLogs[counter].Call_Results__c) + ' -- ' + String.valueOf(relatedCLogs[counter].Note__c) + '\n'; counter = counter+1; } // Update the Student record with the new info s[0].tech_support_logs__c = techlogs; update s [0];

 

 

 

 

 

This was selected as the best answer
CloudDevCloudDev
If you can guarantee that bulk inserts/updates will only ever affect one Student parent record then yes simple is best. From a best practice point of view, it's always better to code to support all scenarios regardless of their likelihood.
JJJenkinsJJJenkins

Hi - 

 

Can you expand a bit on part II and the paragraph above it?  I am trying to do something similar and I'm getting stuck.

 

I want to concatenate a user look up field for all related records on one object to its parent account.  And we will be using the mass import function so I wanted to use this functionality vs the one marked as correct.

 

Thanks,

trigger MultiAssignPO on Assigned_To__c (before update) {
   //set of ids to be populated with unique ids from related Assigned To record
   Set<Id> PoIds = new Set<Id>();
   for (Assigned_To__c AsToObj : Trigger.new)
       {
           PoIds.add(AsToObj.Assigned_To__r.Full_Name__c);
       }
   
   //map of Assigned to records where PO is in set above
   Map<Id, Assigned_To__c> mapAsTo = new Map<Id, Assigned_To__c>([SELECT Id, Assigned_To__r.Full_Name__c, Purchase_Order__c
                                                                  FROM Assigned_To__c
                                                                  WHERE Purchase_Order__c in :PoIds]);
                                                                  
   Map<Id, Purchase_Order__c> mapPOs = new Map<Id, Purchase_Order__c> ([SELECT Id, Assigned_To_Multi__c
                                                                        FROM Purchase_Order__c
                                                                        WHERE Id in :PoIds]);
                                                                        
   list<id> PosToUpdate = new list<id>();