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 Answer 1

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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .