2

I'm writing a class to implement Support.EmailTemplateSelector.

To retrieve the correct email template, I'm querying a Custom Metadata Type Smart_Template_Loader_Conf__mdt, retrieving an EmailTemplate DeveloperName from field Template_Name__c based on the Case RecordTypeId, Status, Reason and either the UserId (ideally) or User's ProfileId.

I want to configure the Metadata so that an Email Template can be retrieved if there is a match for all of the above fields and also, to allow for the following scenarios:

  • Case Status or Case Reason is null or doesn't match a value in the Custom Metadata table, in which case, query for 'Unknown' in place of the field value
  • No template is returned when user's UserName is referenced in the query
  • No template is returned when user's ProfileName is referenced in the query
  • Two or more records with matching Case field / User values exist in the table (so more than one template name is retrieved)

Obviously that's a lot of permutations to manage.

I have:

global class USmartTemplateLoader implements Support.EmailTemplateSelector {

    String userName;
    Id profileId;
    Map<Id, Schema.RecordTypeInfo> rts = new Map<Id, Schema.RecordTypeInfo>();
    String rtName;
    String caseStatus;
    String caseReason;
    Smart_Template_Loader_Conf__mdt conf;
    List<Smart_Template_Loader_Conf__mdt> confs;
    String profileName;
    EmailTemplate et;

    global USmartTemplateLoader() {
    }

    global Id getDefaultEmailTemplateId(Id caseId) {

        Case c = [SELECT RecordTypeId, Status, Reason
                    FROM Case 
                   WHERE Id = :caseId];

        userName = userInfo.getUserName();
        profileId = userInfo.getProfileId();
        rts = Case.SObjectType.getDescribe().getRecordTypeInfosById();
        rtName = rts.get(c.RecordTypeId).getName();
        caseStatus = c.Status;
        caseReason = c.Reason;

        if (caseStatus == null) {
            caseStatus = 'Unknown';
        }
        if (caseReason == null) {
            caseReason = 'Unknown';
        }

And then I need to query the Metadata Type so I could use

       confs = [SELECT Id, Template_Name__c
                  FROM Smart_Template_Loader_Conf__mdt
                 WHERE Username__c = :userName AND Record_Type_Name__c = :rtName AND Case_Status__c = :c.Status AND Case_Reason__c = :c.Reason];

        if (!confs.isEmpty()) {
            if (confs.size() > 1) {
                for(Smart_Template_Loader_Conf__mdt cnf : confs) {
                    // lack of template should prompt user complaint but addError not used, to enable user to still compose email
                    system.debug('USmartTemplateLoader: more than one template returned, metadata record Id: ' + cnf.Id);
                }
            }
            else {
                conf = confs[0];
                system.debug('USmartTemplateLoader: got template: ' + conf.Template_Name__c);
            }
        }

        if (conf == null &&
            caseStatus != 'Unknown') {

            confs = [SELECT Id, Template_Name__c
                       FROM Smart_Template_Loader_Conf__mdt
                      WHERE Username__c = :userName AND Record_Type_Name__c = :rtName AND Case_Status__c = 'Unknown' AND Case_Reason__c = :c.Reason];

            if (!confs.isEmpty()) {
                // process results, as above
            }
        }

        if (conf == null &&
            caseReason != 'Unknown') {
                // repeat query & process results, as above
        }

        // repeat above setting Case Status & Reason to 'Unknown'

        // repeat all of the above, using ProfileName instead of UserName

The number of queries isn't an issue, as querying Metadata doesn't count towards SOQL limits. But there must be a better way to manage this process. Should I retrieve every permutation in one query -

   confs = [SELECT Id, Template_Name__c
              FROM Smart_Template_Loader_Conf__mdt
             WHERE (Username__c = :userName AND Record_Type_Name__c = :rtName AND Case_Status__c = :c.Status AND Case_Reason__c = :c.Reason)
                OR (Username__c = :userName AND Record_Type_Name__c = :rtName AND Case_Status__c = 'Unknown' AND Case_Reason__c = :c.Reason)
                OR (Username__c = :userName AND Record_Type_Name__c = :rtName AND Case_Status__c = :c.Status AND Case_Reason__c = 'Unknown')
                OR (Username__c = :userName AND Record_Type_Name__c = :rtName AND Case_Status__c = 'Unknown' AND Case_Reason__c = 'Unknown')
                OR (Profile_Name__c = :profileName AND Record_Type_Name__c = :rtName AND Case_Status__c = :c.Status AND Case_Reason__c = :c.Reason)
                // etc];

if so what's the best way for me to process the results to find the 'best' result (the one that found a template using as many of the original record's values as possible)?

Or should I take another approach?

1

I would use a Optimized query like this and then process the result.

list<Smart_Template_Loader_Conf__mdt> retrievedTemplateList = [Select Id, Template_Name__c
                                                                 from Smart_Template_Loader_Conf__mdt
                                                                where Record_Type_Name__c = :rtName AND
                                                                      (Username__c = :UserInfo.getUserId() OR Profile_Name__c = :userInfo.getProfileId()) AND
                                                                      Case_Status__c IN (:c.Status, 'Unknown') AND
                                                                      Case_Reason__c IN (:c.Reason, 'Unknown')];

//From here, check the list size and retrieved record values and assign the
  templates accordingly (by using your "if" logic to check case reason and  
  case status). 
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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