Apex Trigger Salesforce - salesforce

I need to use the look up field which relates Contact and Account object in Trigger. I have lookup field Account__c on the Contact, but I cannot get the related Account for that contact when I write something like
Map <Id,Account> acts = new Map<Id,Account>([Select Id,Name from Account where Id:=contact.Account__c]);
it should get all related accounts in to acts, but it does not work..
How can I get related Accounts?

Unless this is a special case you don't need to create a relationship between contact and account, there is already a standard one. you can query it like so
try {
Account parent = [SELECT Id, Name FROM Account WHERE Id = :contact.AccountId];
} catch(QueryException e) {
//list has no rows for assignment
//means the account with Id could not be found
}
For more information about the api names you should look at the wsdl
As an aside, you don't need to pass the results of this query to a map, any time you use Id = :idValue in a WHERE clause it is guaranteed that you will get exactly 0 or 1 result, and in the cause of 0 results a QueryException will be thrown.

Related

Didn't understand relationship 'LinkedEntityId' in field path

So I am generally able to query the relationships but I do not have the access to this object in object manager, so what should be the query to access accountId from ContentDocumentLink object when I know LinkedEntity is a case.
My Code:
List<ContentDocumentLink> case_file_links=
[
SELECT Id,ContentDocumentId,LinkedEntityId.AccountId,ShareType
FROM ContentDocumentLink
WHERE Id IN: case_file_link_Ids
];
Error:
SELECT Id,ContentDocumentId,LinkedEntityId.AccountId,ShareType
^
ERROR at Row:2:Column:45
Didn't understand relationship 'LinkedEntityId' in field path. If you..
LinkedEntityId is a weird mutant lookup to many tables, any table that supports File upload. Official name is "polymorphic lookup".
Maybe you worked with Tasks before, they have similar fields. WhatId can point to Account, Case, Opportunity plus many custom objects. and WhoId points to User/Contact/Lead.
So it's a lookup to "something". It's not guaranteed it's to Cases so at compile time SF can't just blindly accept AccountId. What if the field is not there.
You might have to use TYPEOF in SOQL.
SELECT Id, ContentDocumentId, ShareType,
TYPEOF LinkedEntity WHEN Case THEN CaseNumber, Subject, AccountId END
FROM ContentDocumentLink
WHERE Id IN ('06A7a000001VafmEAC', '06A7a000001VafnEAC')
Developer Console is too stupid to display it properly but workbench should manage
In Apex you'll need an instanceof to check and cast the LinkedEntity to right sObject... or use the generic sObj.get('AccountId') and if it's not there it'll return null?
If this sounds like too much hassle - you can always split it into 2 queries.
Query just SELECT Id, ContentDocumentId, LinkedEntityId, ShareType FROM ContentDocumentLink
Loop through results, collect LinkedEntityId into a helper Set<Id>.
Map<Id, Case> cases = new Map<Id, Case>([SELECT Id, AccountId FROM Case WHERE Id IN :mySet]);

Is there a way to assign a List to a field?

I know the question seems weird but hear me out...
Say I have a group of users called Managers.
List userList = [Manager1, Manager2,Manager3,...,ManagerN]
And I wanted to assign one of these managers to a record using a round robin which uses a modulus to determine the count.
integer count = 0;
integer userModulus = Math.round(Math.mod(Count, userList.size()));
count++;
Then use this value to return the index of the list like userList[userModulus] right?
Originally I planned to use custom metadata types to house the lists with the intent of managing these custom metadata lists by screen flow... but on implementation I don't see this being realistic.
Is there a way to store this list of users in a field, or some other kind of structure where it can be maintained by managers or other non-admin users?
There are code-free ways to do it, see https://help.salesforce.com/s/articleView?id=sf.essentials_round_robin_lead_assignment.htm&type=5
Or ready pieces of code you can get inspired with: https://gist.github.com/eskfung/f342b47ecc0849deb0cb
Many ways to achieve this. You could have a field on the User (picklist? checkbox? being assigned a special Role?) and then
List<User> users = [SELECT Id, Name
FROM User
WHERE IsActive = true AND UserRole.Name = 'Sales Manager'
ORDER BY Name];
Bit crude but should get the job done.
You could also add them to a public group or queue? Queues should be pretty close to normal owner assignment functionality anyway. And then you'd query all group/queue members. Queues are a type of group so it'd sit in same table: Group, GroupMember
SELECT Id, Name, Type
FROM Group
WHERE Type IN ('Regular', 'Queue')
SELECT Id, Name
FROM User
WHERE Id IN (SELECT UserOrGroupId FROM GroupMember WHERE Group.Name = 'MyGroup' AND Group.Type = 'Regular')
It's bit simple, it assumes people are directly assigned to the group. In reality groups/queues often consist of other groups, roles, roles+subordinates, not just manually assigned individuals... You'd need to keep querying the GroupMember records till you exhaust the tree.
Still, should be enough to get you started?

Data Category Visibility Issue

I am facing Data Category visibility related issue.
The scenario is i'm following -
I have One Community User which one is using for login into my community.
This User's role is Inheriting Visibility for Category Group from it's parant role and it's Visibility is No categories are visible to parent role and subordinates.
But This User's Permission set have Custom Visibility Permission is like -
All Category Group > child Category > sub child Category
for ex :
All Products > Computers > Laptops
And I am accessing lick bellow query from apex to display related article in community.
Select Id, Title, KnowledgeArticleId, Summary, CreatedDate, UrlName From KnowledgeArticleVersion WHERE Language = 'en_US' and PublishStatus='Online' WITH DATA CATEGORY Products at (Computers__c) limit 10 UPDATE VIEWSTAT
but I am not getting any articles.
getting error like --
Invalid data category name provided: Products. There is no data category matching the given developer name on the data category group: Computers__c
If anyone have solution for this please let me know.
Thank you,
Harsiddhi.
You probably have already figured this out by now, however you need to use the API name for your Group as well, i.e. 'Products' becomes 'Products__c'.
Should be something more like this:
Select Id, Title, KnowledgeArticleId, Summary, CreatedDate, UrlName From KnowledgeArticleVersion WHERE Language = 'en_US' and PublishStatus='Online' WITH DATA CATEGORY Products__c at (Computers__c)
Queries are not dependent on permission sets.
The error in the SOQL query can be looked upon at the query editor. Whenever there is a wrong API name in the query, there comes down an indication in the Query Editor under Developer Console that:
No such column 'field_name' on entity
Thus we can look back at the object fields and relationships and can ensure if the right API name is there.

How to query all task which are having relatedto(whatId) as Account or Contact

I am using an soql query to get tasks. My requirement is to get all tasks which are related account or contact object. Also few other fields inside Account or contact object whichever the object related. Is there a simple way instead of writing multiple queries.
Please provide more specific information next time. Generally speaking you can refer to a parent object by reference name followed with a dot. Here is an example
Select Account.Name, AccountId From Task Where Account.Name = 'John'
Here Account is the name of the reference (from task) and AccountId is the referencing field.
Your question is a little unclear. Are you looking for all TASKS related to any ACCOUNT or CONTACT or related to specific ACCOUNTS or CONTACTS?
If the former, try
SELECT Id, Subject,
FROM TASK
WHERE
What.Type = 'Account' OR
Who.Type = 'Contact'
if the latter, use the IN :list syntax already suggested by Moti. The What.Type is useful, as opposed to AccountId!=null, because it will not return TASKS associated with, for example, OPPORTUNITIES (if you want that behavior, use AccountId!=null and maybe drop the Who.Type if you associate all CONTACTS with OPPORTUNITIES, as it would be redundant).
In either case, your issue will be pulling specific data from CONTACT whos, as polymorphic fields only allow access to a limited number of fields. Can't seem to find that list right now. I don't believe old SOQL supports the kind of the syntax to do that in one query--that's why SOQL polymorphism made such a bang--though I could be wrong.
Now, if you have SOQL TYPEOF available to you, you should be able to do something more interesting like:
SELECT Id, Subject,
TYPEOF What
WHEN Account THEN AccountNumber
END,
TYPEOF Who
WHEN Contact THEN FirstName
END
FROM Task
WHERE
What.Type = 'Account' OR
Who.Type = 'Contact'
How about
select {column list] from task where parentid in (select id from account where ...) or parentid in (select id from contact where ...)
Alternatively, if you're inside Apex and already have the contact or account ids in a list (we'll use idList), you can use:
select {column list] from task where parentid in :idList

How can I reassign opportunities in Salesforce based on number of opportunities per account?

I have created a simple class and visual force page that displays a "group by". The output is perfect, it will display the number of opportunities a given account has:
lstAR = [ select Account.Name AccountName, AccountId, Count(CampaignID) CountResult from Opportunity where CampaignID != null group by Account.Name,AccountId having COUNT(CampaignID) > 0 LIMIT 500 ];
I would like to be able to say, if an account has more then 10 opportunities, then assign the opportunity to another account that has less then 10.
I used the following code to get the results in my visual force page:
public list<OppClass> getResults() {
list<OppClass> lstResult = new list<OppClass>();
for (AggregateResult ar: lstAR) {
oppClass objOppClass = new oppClass(ar);
lstResult.add(objOppClass);
}
return lstResult;
}
class oppClass {
public Integer CountResult { get;set; }
public String AccountName { get;set; }
public String AccountID { get;set; }
public oppClass(AggregateResult ar) {
//Note that ar returns objects as results, so you need type conversion here
CountResult = (Integer)ar.get('CountResult');
AccountName = (String)ar.get('AccountName');
AccountID = (String)ar.get('AccountID');
}
What would be the best approach to check the count greater then a given number and then assign an account with less then that given number the opportunities?
As I said, code wise I have a nice little controller and vf page that will display the account and count in a grid. Just not sure of a good approach to do the reassigning opportunity.
Thanks
Frank
I'm not sure why you'd be moving your opportunity to another account b/c typically the account is the organization/person buying the stuff?
But that said, ignoring the why and focusing on the how...
Trigger on the Opportunity, before insert
loop over trigger.new and count how many oppties you have per account (or owner) in that batch, put that into a map accountId to count [because you could be inserting 10 oppties for the same account!]. If ever your count is > 10 change the assignment using whatever assignment helper class you have.
Also populate set of accountIds.
Then run your aggregate for each account where Id in set of accountIds, you'll have to group by AccountId.
Loop over results, and update the map of accountId to count.
Then loop over trigger.new and for each oppty, look up in the map by accountId the count. If the count > 10 then do your assignment using your helper class.
And done.
Of course your assignment helper class is another issue to tackle - how do you know which account/user to assign the opportunity to, are you going to use queues, custom objects, custom settings to govern the rules, etc...
But the concept above should work...

Resources