Get only processes of certain name/id in SOQL? - salesforce

I have following SOQL query:
[SELECT p.ProcessInstance.TargetObjectId FROM ProcessInstanceWorkitem p WHERE p.ProcessInstance.Status = 'Pending' AND p.ProcessInstance.TargetObject.Type = 'Contact' AND ActorId =: uid LIMIT 1];
With this I am getting one process which can be of any type... But I want it to filter for either the process id or the process name. Like WHERE ProcessInstance.ProcessName = 'myName'. Is this somehow possible? I didn't find anything which represents the name of the approval process.

Related

Who to access field of nested relationship in soql where first relation is simple and next is polymorphic

I want to access custom field of Owner (User) fields where Owner is polymorphic relation it can be either User or Group.
I tried following query:
SELECT Id, Email, Name, Lead.TYPEOF Owner WHEN User THEN custom__c FROM CampaignMember WHERE CampaignId='xxxxxx'
Relationship stack is:
Lead > Owner (User,Group) > custom__c.
SELECT field1__c,
field2__c
FROM Lead
WHERE Owner.type = 'User'
AND CampaignID = 'xxxxxx'
EDIT:
Leaving my original answer in case it helps someone else.
I believe what you are looking for is this:
SELECT Id, Email, Name,
TYPEOF Lead.Owner
WHEN User THEN custom__c
END
FROM CampaignMember
WHERE Field != 'value'

Get Contact Emails of Currently Active Account as List

Given: A Salesforce user is viewing an account page.
Desired Output: All Emails of Contacts related to the Account currently viewed as a List object.
My code:
SELECT Email FROM Contact WHERE Id IN (SELECT ContactId FROM AccountContactRelation WHERE AccountId = ApexPages.CurrentPage.getParameters().get('id'))
This does not retrieve any results. When using a fixed number instead of ApexPages.CurrentPage.getParameters().get('id'), the Emails are correctly returned.
I'm sort of new to Apex. Could anyone point out what I am doing wrong?
To achieve the desired output you need to use SOQL variable injection.
You can do this by creating a variable first and then referencing the variable inside the SOQL using : and the variable name:
String theAccountId = ApexPages.CurrentPage.getParameters().get('id');
List<Contact> theContacts = [SELECT Email FROM Contact WHERE Id IN (SELECT ContactId FROM AccountContactRelation WHERE AccountId = :theAccountId)];
You can use a static query with a bind variable to retrieve the correct results.
Additionally, the Contact object contains an AccountId field of its own. Therefore, depending on your setup, you may be able to eliminate your subquery. You may also want to filter out Email fields that are empty, since Email is not a required field.
The complete result could look something like this:
String accountId = ApexPages.CurrentPage.getParameters().get('id');
List<Contact> accountContactsEmailList = [
SELECT
Email
FROM
Contact
WHERE
Email != ''
AND AccountId = :accountId
];
for (Contact contact : accountContactsEmailList) {
System.debug(contact.Email);
}

Look for records related to another related records within specific criteria

I am trying to created a set of records based on some criteria and i need to figure out the best way to do this.
I want to create a record for every object A and B that has an specific Account object. object A needs to have a status of "DONE", and B a status of "READY" in order to create the record (which will be an Object A with an "Active" status) the fields on the new Object A will copy from some of the Object A and B fields.
This is a process im not triggering from user action but a set of records i need to already dump in the database. I do have a sandbox to start working on and testing then rolling out.
Please let me know the easiest way to do this.
I appreciate the help!
You didn't provide enough info, we don't know how the relations look like. Are A and B related lists under Account? Are they independent or is there some link from one to another?
I'll write what I would do as a script (if needed you could make a batch job out of it or perhaps you'll be more comfortable with Data Loader, reports with cross filters, MS Excel and orgy of VLOOKUPs...)
To identify all "candidate" accounts you can try with this skeleton of a query
SELECT Id, Name
FROM Account
WHERE Id IN (SELECT Account__c FROM A__c WHERE Status__c = 'Done')
AND Id IN (SELECT Account__c FROM B__c WHERE Status__c = 'Ready')
LIMIT 10000
Now, the question about amounts of data. Will it return 10K (which is limit of records you can insert/update/modify in single transaction), if more - you might have to chunk it somehow... Maybe ORDER BY Id, record Id of last processed Account and in next iteration add AND Id > '001....'
Anyway, we got a "candidate", well, maybe he already has an Active A record, we wouldn't want to make a duplicate. And besides we need to pull some fields from B so they'd be copied across. So let's modify the query a bit, to add "subqueries" (think of them as related lists or LEFT INNER JOINs if that helps)
SELECT Id, Name,
(SELECT Id FROM As__r WHERE Status__c = 'Active' LIMIT 1),
(SELECT SomeField__c, SomeOtherField__c FROM Bs__r WHERE Status__c = 'Ready' LIMIT 1)
FROM Account
WHERE Id IN (SELECT Account__c FROM A__c WHERE Status__c = 'Done')
AND Id IN (SELECT Account__c FROM B__c WHERE Status__c = 'Ready')
LIMIT 10000
Nice. So now you need to loop through accounts, see if they contain that at least 1 active record (and if they do - skip). If they don't - create new one.
List<A__c> toInsert = new List<A__c>();
for(Account a : [SELECT...]){
if(a.As__r.isEmpty() && !a.Bs__r.isEmpty()){
toInsert.add(new A__c(
Account__c = a.Id,
Status__c = 'Active',
Foo__c = a.Bs__r[0].SomeField__c,
Bar__c = a.Bs__r[0].SomeOtherField__c + 7
));
}
}
insert toInsert;

No such column 'Owner' on entity 'Lead'

i am getting the following error
Error: Compile Error: No such column 'Owner' on entity 'Lead'. If you are attempting to use a custom field, be sure to append the '__c' after the custom field name. Please reference your WSDL or the describe call for the appropriate names. at line 8 column 17
trigger Lead_Assignment on Lead (after insert) {
List<Lead> le=trigger.new;
User us=le.get(0).CreatedBy;
List<User> u=[SELECT id from USER WHERE At_Work__c=true];
List<integer> ii=new List<Integer>();
for(User uu:u){
Integer xx= [SELECT count() from Lead WHERE Owner=:uu];
}
}
there is a field with name Owner in Lead Object why i am getting this error please help in solving this error.
I think you would be better off with a query similar to below:
Integer xx= [SELECT count() from Lead WHERE OwnerId=:uu.Id];
The Owner field on the lead object is actually a reference to the owner user object. Typically this gets populated if you do a query similar to below:
[SELECT id, Owner.Name, Owner.Email FROM Lead]
And to access the Owner fields you would access the lead object owner property:
Lead myLead = [SELECT Id, Owner.Name, Owner.Email FROM Lead limit 1];
System.debug(myLead.Owner.Email);
However, there is a larger issue here. It isn't best practice to query within a loop like this. You are better off using an aggregate query like:
AggregateResult[] results = [SELECT COUNT(ID), OwnerId FROM LEAD GROUP BY OwnerId WHERE OwnerId IN :listOfUserIds]

SalesForce: Query objects a user has read permission for

How can I Query all Accounts a given user has read permission for?
I tried the following but, returned the error "semi join sub selects can only query id fields, cannot use: 'RecordId'"
User u = new User();
Account[] account = [SELECT Name FROM Account a
WHERE Id IN
(
SELECT RecordId
FROM UserRecordAccess
WHERE RecordId = :a.Id
AND UserId = :u
AND HasReadAccess = true
)
];
The code is being executed as part of a scheduled batch job run as system so use of "with sharing" is not applicable.
Thanks
The salesforce documentation says that RecordID is a picklist field which seems odd. If it is a picklist field that might explain why it does not work in a subquery.
You could try building a set of RecordIDs first and then using this to filter the Account query.
Set<ID> sRecordIDs = [SELECT RecordID FROM UserRecordAccess WHERE UserId = :u AND HasReadAccess = True];
Account[] accs =[SELECT ID,Name FROM Account WHERE Id in :sRecordIDs];
This might fall over governor limits if the number of records in UserRecordAccess is high.
If you are only looking to do this for Account you could try this:
User u = new User();
list<Account> accs = [select Id, Name from Account where Id in (select AccountId from AccountShare where UserOrGroupId = :u.Id) or OwnerId = :u.Id];
That should give you all of the account records that the user has access to or owns. In the general case each sObject has its own 'Share' sObject that represents visibility against it, unless it is degenerate in some way (i.e. it is the detail in a master-detail).

Resources