function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Raghavendra ARaghavendra A 

SOQL Query Help

Hi All,

I need your help wiht a SOQL query. In a visualforce page, I need to show in a Visualforce page all the Approval Process Item that is assigned to a logged in user. I am trying to build a SOQL query for this, but finding it much more challenging than regular SOQL queries. Challenge is that I want to provide a link to the Record that is part of the Approval Process.

Could someone help me with a SOQL query that pulls all Approval items peding for the logged in user. Or even help me with the right direction.

Thanks,
Raghu
Best Answer chosen by Raghavendra A
Roy LuoRoy Luo
Try something like this:
 
List<ProcessInstanceWorkitem> workItems = Test.isRunningTest()? 
          [SELECT ProcessInstance.TargetObjectId FROM ProcessInstanceWorkitem WHERE IsDeleted=false]
          :[SELECT ProcessInstance.TargetObjectId FROM ProcessInstanceWorkitem WHERE ActorId =:UserInfo.getUserId() AND IsDeleted=false];

Set<Id> myObjIds = new Set<Id>();
String keyPrefix = YourCustomObject__c.sObjectType.getDescribe().keyPrefix;
for(ProcessInstanceWorkitem piw : workItems)
        {
            if(!String.valueOf(piw.ProcessInstance.TargetObjectId).startsWith(keyPrefix)) continue;
            myObjIds.add(piw.ProcessInstance.TargetObjectId);
            workitemLookup.put(piw.ProcessInstance.TargetObjectId, piw);
        }

Then use myObjIds to query your custom object and do the data binding in your VF. 

Note: Test.isRunningTest() will come in handy for unit test since in unit test it takes lots of effort to setup the approval processes.

Hope this helpes.

All Answers

Roy LuoRoy Luo
Try something like this:
 
List<ProcessInstanceWorkitem> workItems = Test.isRunningTest()? 
          [SELECT ProcessInstance.TargetObjectId FROM ProcessInstanceWorkitem WHERE IsDeleted=false]
          :[SELECT ProcessInstance.TargetObjectId FROM ProcessInstanceWorkitem WHERE ActorId =:UserInfo.getUserId() AND IsDeleted=false];

Set<Id> myObjIds = new Set<Id>();
String keyPrefix = YourCustomObject__c.sObjectType.getDescribe().keyPrefix;
for(ProcessInstanceWorkitem piw : workItems)
        {
            if(!String.valueOf(piw.ProcessInstance.TargetObjectId).startsWith(keyPrefix)) continue;
            myObjIds.add(piw.ProcessInstance.TargetObjectId);
            workitemLookup.put(piw.ProcessInstance.TargetObjectId, piw);
        }

Then use myObjIds to query your custom object and do the data binding in your VF. 

Note: Test.isRunningTest() will come in handy for unit test since in unit test it takes lots of effort to setup the approval processes.

Hope this helpes.
This was selected as the best answer
BalajiRanganathanBalajiRanganathan
try this SOQL
SELECT CreatedById,ActorId,CreatedDate,IsDeleted,OriginalActorId,ProcessInstanceId,Id,SystemModstamp FROM ProcessInstanceWorkitem where actorid = : actorid
Raghavendra ARaghavendra A
Thanks, Roy! I have a coupld of questions:
  • Could you please eloborate this: use myObjIds to query your custom object and do the data binding in your VF.
  • Using Test.isRunningTest(), you meant to say if we use this we do not have to set up approval process in Test classes? Just using this in the actual class will suffice?
Thanks a lot for your help again!
Roy LuoRoy Luo
In your controller you would have
 
public List<YourObject> ObjItems {get;set;}
ObjItems = [SELECT Id, Name ... FROM YourObject__c WHERE Id IN :myObjIds];

Then in the VF, 
<apex:pageBlockTable value="{!ObjItems}" var="a" id="tblResults">
    <apex:column headerValue='Name' >
        <apex:outputLink value="yourbaseUrl/{!a.Id}">{!a.Name}</apex:outputLink>                       
    </apex:column>
 </apex:pageBlockTable>
I just use Test.isRunningTest() to skip the process of setting up approval actor, plainly for code coverage, since the approval actor assignment is not in the controller scope anyway.