salesforceapex-codesalesforce-service-cloud

salesforce update trigger on serviceterritory object


I have below requirement and I'm new to SF development, need assistance if my approach is correct or not.

When any update happens on ServiceTerritory object, if the Time_Zone__c field of ServiceTerritory is not matching with User Object TimeZoneSidKey field, then update ServiceTerritory object Time_Zone__c field with User Object TimeZoneSidKey field.

  1. ServiceTerritory object : has Center_Instructor_Contact__c field tagged to ID field in Contact object.
  2. Contact object : has ID field and AccountId field
  3. User Object : has AccountId field
public static void afterUpdate(List<ServiceTerritory> serviceTerritories, Map<Id, ServiceTerritory> oldRecords) {

Set<Id> recIds = new Set<Id>();
        for (ServiceTerritory record : serviceTerritories) {
            recIds.add(record.Id);
        }

Set<Id> STMembers = new Set<Id>();
        for (ServiceTerritory member : [SELECT Id, Center_Instructor_Contact__c FROM ServiceTerritory WHERE Id IN :recIds]) {
            STMembers.add(member.Center_Instructor_Contact__c);
        }

//Contact object : has ID field and AccountId field

Set<Id> ContactIDs = new Set<Id>();
for (Contact Cnt : [SELECT AccountId FROM Contact WHERE Id IN :STMembers]) {
            ContactIDs.add(Cnt.AccountId);
        }

//User Object : has AccountId field
Set<Id> UserIDs = new Set<Id>();
for (User Cnt : [SELECT AccountId, TimeZoneSidKey FROM User WHERE AccountId IN :ContactIDs]) {
            UserIDs.add(Cnt.AccountId);
        }
}

and here how to compare and update ServiceTerritory object if the timezone is not matching between the objects.


Solution

  • Not many Salesforce instances will have access to "Field Service Lightning" which is where ServiceTerritory table is used. If you sign up for free Salesforce Developer Edition it probably won't exist there. So it's bit hard to understand the question and help. Plus if you wrote "User Object : has AccountId field" it sounds like you're using Experience Cloud (formerly known as communities), that narrows down the specialists even more.

    So it's Service Territory -> "up" to -> Contact -> "down" to (community) -> User?

    If you're using community users they'll have AccountId and ContactId in them, no need going via Account (and in fact you could get stupid results that way... What if not all contacts in account are community-enabled, what if they are but have different timezones...)

    Try something like that but you'll have to experiment a lot. And change your code to run "before update", you'll get save to database for free

    List<ServiceTerritory> serviceTerritories; // passed to your function
    
    Set<Id> contactIds = new Set<Id>();
    for (ServiceTerritory st : serviceTerritories) {
        contactIds.add(st.Center_Instructor_Contact__c);
    }
    System.debug(contactIds);
    
    // Grab all these Contacts and their community users (it's a related list so it'll be a subquery but really there will be at most one user
    Map<Id, Contact> contacts = new Map<Id, Contact>([SELECT Id,
            (SELECT TimezoneSidKey FROM Users)
        FROM Contact
        WHERE Id IN :contactIds AND Id IN (SELECT ContactId FROM User)]);
        
    // Loop again and check against "reference data"
    for (ServiceTerritory st : serviceTerritories) {
        if(contacts.containsKey(st.Center_Instructor_Contact__c)){
            Contact c = contacts.get(st.Center_Instructor_Contact__c);
            System.debug(c);
            System.debug('comparing ' + st.Time_Zone__c + ' and ' + c.Users);
            if(st.Time_Zone__c != c.Users[0].TimezoneSidKey){
                System.debug('fixing ' + st.Id);
                st.Time_Zone__c = c.Users[0].TimezoneSidKey;
            }
        }
    }