帐户中所有联系人角色分配给当前用户的Apex检索任务

时间:2018-08-10 15:56:55

标签: salesforce apex

我有一个Apex类,其目的是检索和删除用户刚刚调用的联系人角色(与帐户有关)上的过期任务。我需要对其进行修改,以便它可以查询该帐户上所有联系人角色上分配给用户的所有过期任务,但正在努力获取正确的查询。

这是有问题的代码的一部分,我认为最相关的部分:

/***************************************************
Brief Description: Deletes overdue Tasks or Events.
****************************************************/
public class DSDenali_DeleteOverDueActivities {

private static List<Task> followUpTasksToDelete = new List<Task>(); 
private static List<Event> followUpEventsToDelete = new List<Event>();
private static Map<Id, Set<String>> ownerOfActivities = new Map<Id, Set<String>>();

@InvocableMethod (label = 'DialSource Denali Delete Overdue Activities')
public static void gatherData(List<Data> requests)
{
    Map<Id, String> results = new Map<Id, String>();

    for (Data request : requests)
        results.put(request.contactRoleID, request.assignedTo);

    for (Id key : results.keySet())
    {
        Set<String> assignedToValues = parseAssignedTo(results.get(key));
        System.debug('assignedToValues: ' + assignedToValues);
        ownerOfActivities.put(key, assignedToValues);
        System.debug(ownerOfActivities);
    }

    queryAndFilterData();
    deleteOverdueActivities();
}

//Query for the Tasks and Events and filter the ones to delete
private static void queryAndFilterData()
{
    List<Contact_Role__c> contactRoles = [SELECT Id, 
                                                (SELECT Id, Owner.UserRole.Name, OwnerId FROM Tasks WHERE status != 'Completed' AND ActivityDate <= :system.TODAY() AND Type__c = 'Outbound Call'),
                                                (SELECT Id, Owner.UserRole.Name, OwnerId, Description FROM Events WHERE EndDateTime <= :system.NOW())
                                         FROM Contact_Role__c
                                         WHERE Id IN :ownerOfActivities.keySet()];

    for (Contact_Role__c contactRole : contactRoles)
    {
        for (Task currentTask : contactRole.Tasks)
        {
            if (ownerOfActivities.get(contactRole.Id).contains(currentTask.OwnerId))
            {
                if (currentTask.OwnerId != '0050B000006ET37' && currentTask.Owner.UserRole != NULL && Pattern.matches('.*Altair.*', currentTask.Owner.UserRole.Name))
                    followUpTasksToDelete.add(currentTask);

                else if (currentTask.OwnerId == '0050B000006ET37')
                    followUpTasksToDelete.add(currentTask);

                else 
                    continue; 
            }

            else if (ownerOfActivities.get(contactRole.Id).contains('ALL'))
            {
                if (currentTask.Owner.UserRole != NULL && Pattern.matches('.*Altair.*', currentTask.Owner.UserRole.Name))
                    followUpTasksToDelete.add(currentTask);

                else 
                    continue;
            }
        }

        for (Event currentEvent : contactRole.Events)
        {
            if (ownerOfActivities.get(contactRole.Id).contains(currentEvent.OwnerId) && currentEvent.Description == NULL)
            {
                if (currentEvent.OwnerId != '0050B000006ET37' && currentEvent.Owner.UserRole != NULL && Pattern.matches('.*Altair.*', currentEvent.Owner.UserRole.Name))
                    followUpEventsToDelete.add(currentEvent);

                else if (currentEvent.OwnerId == '0050B000006ET37')
                    followUpEventsToDelete.add(currentEvent);

                else 
                    continue; 
            }

            else if (ownerOfActivities.get(contactRole.Id).contains('ALL') && currentEvent.Description == NULL)
            {
                if (currentEvent.Owner.UserRole != NULL && Pattern.matches('.*Altair.*', currentEvent.Owner.UserRole.Name))
                    followUpEventsToDelete.add(currentEvent);

                else 
                    continue;
            }
        }
    }                                   
}

//Delete overdue Events/Tasks
private static void deleteOverdueActivities()
{
    try{
        delete followUpTasksToDelete;
    }

    catch (DmlException e){
        System.debug('The following error occured (DSDenali_DeleteOverDueActivities): ' + e);
    }

    try{
        delete followUpEventsToDelete;
    }

    catch (DmlException e){
        System.debug('The following error occured (DSDenali_DeleteOverDueActivities): ' + e);
    }
}

//Parse the CSVs of possible owners
private static Set<String> parseAssignedTo(String assignedTo)
{
    Set<String> assignedToValues = new Set<String>();
    assignedToValues.addAll(assignedTo.deleteWhitespace().split(','));
    return assignedToValues;
}

public class Data
{
    @InvocableVariable (required=true)
    public String assignedTo;

    @InvocableVariable (required=false)
    public Id contactRoleID; 
}
}

1 个答案:

答案 0 :(得分:0)

(在OP发布更多代码并要求查看代码后更新)

这不是坏代码,可以使用一些注释。考虑将其发布在https://codereview.stackexchange.com/(尽管与SF相关的帖子结尾不多)或https://salesforce.stackexchange.com

上发布

gatherData()

您的输入变量(经过一些解析)是Map<Id, Set<String>>,其中键是联系人角色的ID。用户(所有者)的那组字符串有点误导。您一眼便立即问自己为什么不能Set<Id>。只有在代码的深处,您才能看到“ All”显然是允许的值之一。这不是很好。我很想在这里提出两种方法,一种方法是合法的Map<Id, Set<Id>>,而另一种方法是简单的Set<Id>,如果您知道自己实际上在跳过第二个参数的话。

queryAndFilterData()

您只有一个查询,它不是循环的,很好。 我的技巧(从编辑之前开始)将对您不起作用(您实际上没有Account__c,但是在输入中称为anywere的字段中,您只有记录ID。如果您要检查/删除此帐户下角色的所有任务,最干净的方法可能是使用两个查询

// 1st the helper to collect all accounts...
Set<Id> allAccounts = new Map<Id, Account>([SELECT Id
FROM Account
WHERE Id IN (SELECT Account__c FROM Contact_Role__c WHERE Id IN :ownerOfActivities.keyset()]).keyset();

// then the outline of the main query would be bit like this
SELECT Id,
    (SELECT ... FROM Tasks WHERE ...),
    (SELECT ... FROM Events WHERE ...)
FROM Contact_Role__c
WHERE Account__c IN :allAccounts
    AND ...

我会检查可将多少过滤逻辑推入查询本身,而不是手动检查返回的每一行。我的意思是看看:

想象一下,我们要走一条简单的路线(忽略“所有”用户的概念),并且假设您还有另一个Set<Id> allUsers;变量(由所有数据中提到的所有ID组成)

对Tasks的查询可能变得简单

(SELECT Id
FROM Tasks
WHERE Status != 'Completed'
    AND ActivityDate <= TODAY 
    AND Type__c = 'Outbound Call'
    AND OwnerId IN :allUsers
    AND (OwnerId = '0050B000006ET37' OR Owner.UserRole.Name LIKE '%.Altair.%')
)

您仍然必须遍历它们,以验证是否真的可以删除每个对象(不足以匹配所有用户,它还必须检查该特定Contact_Role__c上的用户是否还可以,对吗?)像这样应该返回更少的行,并且不再有更多的正则表达式匹配...应该更快一些。

我不会为那个特殊所有者的ID设置魔法变量。理想情况下,还有其他描述该特殊用户的内容(角色?个人资料?用户记录上的自定义字段?个人资料中“作者Apex”的权限?)。至少将它移动到文件顶部的辅助Id变量中,这样就不会在整个位置复制粘贴了。并询问您的业务用户,如果那个人(默认任务所有者?一些集成帐户?)离开公司,会发生什么情况,因为大便会严重打击螺旋桨。

如果您对此版本的查询感到满意,那么“ ALL”版本会变得更加简单?没有“所有用户”,没有“魔术ID”和工作已完成?

(SELECT Id
FROM Tasks
WHERE Status != 'Completed'
    AND ActivityDate <= TODAY 
    AND Type__c = 'Outbound Call'
    Owner.UserRole.Name LIKE '%.Altair.%'
)

不要相信互联网上随机的人,他不知道您的业务流程,但是是的,还有一些改进的空间。进行彻底的测试:)

deleteOverdueActivities()

这不是很好的try-catch模式。您只需在调试日志中提出它,但会默默地吞下该错误。使它很难失败(让错误提示给用户),或进行一些适当的错误处理,例如在Helper Log__c对象中插入一些内容,或向管理员发送电子邮件/聊天记录...

parseAssignedTo() 不错。我希望当您将null传递给它时,它会爆炸得可怕。您可以通过在最后几行中标记所需的变量来保护自己,但我认为此注释仅适用于Flows。从其他Apex代码调用它的保护不够。