Entitlement Access Request Creating Multiple Work Items

We are in the process of making entitlements for one of our applications requestable through IIQ. We are currently seeing an issue in our QA environment where sometimes IIQ is creating more than 1 work item for the request and sending additional email for each work item created. While we can reproduce the issue, we can not figure out why this is happening. We are only seeing the issue for the first level approver (manager). It doesn’t matter if if the approval workflow is the same for all entitlements being requested. Looking at the log files from our 1st level override rule, when this does happen, the manager is listed as the approver 2 times in the log for each entitlement like IIQ is processing the rule twice for each entitlement.

Screen shot of the emails for two work items created for same access request. All 4 of the entitlements have the same approval workflow.

Update on this - We are still seeing issue, but it does not happen all the time. We did notice that when we look at the Work Items that are created, one is created for ‘Manager or Service Owner Approval’, the second one is created for ‘1st Level Entitlement Business Approvers Approval’. In our entitlement properties, we have manager listed as 1st level Business Approver. Is there a way to not have the initial work item for ‘Manager or Service Owner Approval’ created?

You can dynamically skip the Manager approval level by creating an Extended Rule and setting the rule name in the Application’s “Omit or Override Manager Approval Rule”. The rule should return a Map with a key named “ApprovalRequired”=false in order to skip that approval level. For example:

Map result = new HashMap();
result.put(“ApprovalRequired”,“FALSE”);
return result;

Thanks @paulo_urcid!

We are currently testing entitlement requests where we removed manager from the 1st level business approver and it seems to be working the way we want. It still goes to manager for approval first and then goes to our 2nd level business approver if specified. If we run into an issue with it this way, we will look at your suggestion.

Hi Michael @mer21

Could you please share email template which you have created above, we are facing some issues while trying to get workitem details into emails.

Many Thanks.
T

In case you don’t get a response from the OP (this is a very old post), here are a couple of helpful references:
https://community.sailpoint.com/t5/Technical-White-Papers/Email-Template-Usage-and-Customization/ta-p/78164
https://community.sailpoint.com/t5/Technical-White-Papers/Email-Template-Arguments/ta-p/73115

The 2nd is especially useful for advanced activities as it covers how to get a SailPointContext instance instantiated in the template’s evaluation for more advanced data lookups.

1 Like

@Tgavhane

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE EmailTemplate PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<EmailTemplate name="EmailTemplate-FrameworkApproval">
  <Body>

    #set($ctx = $spTools.class.forName("sailpoint.api.SailPointFactory").getMethod("getFactory", null).invoke(null,null).getCurrentContext())
    #set($launcherIdentity = $ctx.getObjectByName($spTools.class.forName("sailpoint.object.Identity"),$launcher))
    #set($requesteeIdentity = $ctx.getObjectByName($spTools.class.forName("sailpoint.object.Identity"),$identityName))
    #set($ownerIdentity = $ctx.getObjectByName($spTools.class.forName("sailpoint.object.Identity"),$item.owner.name))
    #set($reqType = $workflow.requestType)
    #set($accessReqNumber = $item.getIdentityRequestId())
    #set($accReq = $ctx.getObjectByName($spTools.class.forName("sailpoint.object.IdentityRequest"),$item.getIdentityRequestId()))
    #set($requestItems = $accReq.getItems())

    #if ( $requestItems ) 
    #set($comments = $requestItems[0].getAttribute("requesterComments"))
    #end
    #set($ruleObj = $ctx.getObjectByName($spTools.class.forName("sailpoint.object.Rule"), "Rule-Framework-Header-Footer-StyleSheet")) 
    #set($ruleArgs = { 
    "keyEmailTemplate"  : "styleSheet"
    }) 
    #set($styleSheet = $ctx.runRule($ruleObj, $ruleArgs))
    #if( $ruleObj )
    $ctx.decache($ruleObj)
    #end
    #set($ruleObj = $ctx.getObjectByName($spTools.class.forName("sailpoint.object.Rule"), "Rule-Framework-Header-Footer-StyleSheet")) 
    #set($ruleArgs = { 
    "keyEmailTemplate"  : "headerTemplate"
    }) 
    #set($headerTemplate = $ctx.runRule($ruleObj, $ruleArgs))
    #if( $ruleObj )
    $ctx.decache($ruleObj)
    #end
    #set($ruleObj = $ctx.getObjectByName($spTools.class.forName("sailpoint.object.Rule"), "Rule-Framework-Header-Footer-StyleSheet")) 
    #set($ruleArgs = { 
    "keyEmailTemplate"  : "footerTemplate"
    }) 
    #set($footerTemplate = $ctx.runRule($ruleObj, $ruleArgs))
    #if( $ruleObj )
    $ctx.decache($ruleObj)
    #end
    #set($ruleObj = $ctx.getObjectByName($spTools.class.forName("sailpoint.object.Rule"), "Rule-Server-Root-Path")) 
    #set($ruleArgs = {})
    #set($rootPath = $ctx.runRule($ruleObj, $ruleArgs))
    #if( $ruleObj )
    $ctx.decache($ruleObj)
    #end 
    &lt;html>
    &lt;head>
    &lt;meta charset="UTF-8">	    
    #if( $styleSheet )
    $styleSheet
    #end    
    &lt;/head>	      
    &lt;body>
    #if( $headerTemplate )
    $headerTemplate
    #end 
    &lt;br/>    
    #if($ownerIdentity.getDisplayName()) 
    Dear $ownerIdentity.getDisplayName(),&lt;br/>
    #elseif($ownerIdentity.getFirstname())
    Dear $ownerIdentity.getFirstname(),&lt;br/>
    #else
    Dear $ownerIdentity.getName(),&lt;br/>
    #end
	&lt;p>
            Please review and provide your access decision.
    &lt;/p>
    Request Number:  $accessReqNumber&lt;br/>
    Request For Identity ID:  &lt;strong>$identityName&lt;/strong>&lt;br/>
    Request For User:  &lt;strong>$identityDisplayName&lt;/strong>&lt;br/>
    Requestee Business Area: &lt;strong>$!requesteeIdentity.getAttribute("businessArea")&lt;/strong>&lt;br/>
    Comments:&lt;br/>
    #if ( $requestItems )
    &lt;strong>$!requestItems[0].getAttribute("requesterComments")&lt;/strong>&lt;br/>
    #end
    &lt;br/>
    Request:&lt;br/>
    #if ( $approvalSet.items )
    #foreach ($approvalItem in $approvalSet.items)
    #if ( $approvalItem.displayValue )
    &lt;strong>$!approvalItem.operation $approvalItem.displayValue&lt;/strong>&lt;br/>
    #elseif ($approvalItem.value &amp;&amp; $approvalItem.name &amp;&amp; $approvalItem.application)
    #set($ruleObj = $ctx.getObjectByName($spTools.class.forName("sailpoint.object.Rule"), "Rule-Framework-ManagedAttribute-GetDisplayValue")) 
    #set($ruleArgs = { 
    "attrName"  : $approvalItem.name, 
    "attrValue" : $approvalItem.value,
    "attrApp"   : $approvalItem.application 
    })
    #set($attrDisplayValue = $ctx.runRule($ruleObj, $ruleArgs))
    #if( $ruleObj )
    $ctx.decache($ruleObj)
    #end
    &lt;strong>$!approvalItem.operation $attrDisplayValue&lt;/strong>&lt;br/>
    #elseif ($approvalItem.value.class.name == "java.util.List" || $approvalItem.value.class.name == "java.util.ArrayList")
    &lt;strong>$!approvalItem.operation $approvalItem.value.get(0)&lt;/strong>&lt;br/>
    #elseif($approvalItem.value)
    &lt;strong>$!approvalItem.operation  $approvalItem.value&lt;/strong>&lt;br/>
    #elseif($approvalItem.application)
    &lt;strong>$!approvalItem.operation  Account on $approvalItem.application&lt;/strong>&lt;br/>
    #end
    #end
    &lt;/ul>
    #end
    #if ($dynamicAppContent)
    &lt;table>
    #foreach( $key in $dynamicAppContent.keySet() )
    &lt;tr>&lt;td>$key&lt;/td>&lt;td>$dynamicAppContent.get($key)&lt;/td>&lt;/tr>
    #end
    &lt;/table>&lt;br/>
    #end
    &lt;p>
            Use the following link to access and complete your review in IIQ. If you have trouble opening the link, make sure you try connecting to the VPN first before contacting support. &lt;a href="$rootPath/workitem/workItem.jsf?id=$workItem.id">$rootPath/workitem/workItem.jsf?id=$workItem.id &lt;/a>
    &lt;/p>
    #if( $footerTemplate )
    $footerTemplate
    #end
    #if( $launcherIdentity )
    $ctx.decache($launcherIdentity)
    #end
    #if( $requesteeIdentity )
    $ctx.decache($requesteeIdentity)
    #end
    #if( $ownerIdentity )
    $ctx.decache($ownerIdentity)
    #end
    &lt;/body>
    &lt;/html>

  </Body>
  <Description>
    Email Template for notifying approvers when they need to approve a request
    made through LCM.
    Note that in addition to the declared arguments, all workflow variables,
    Step arguments, and Approval arguments defined in the Workflow are
    also available.
  </Description>
  <Signature>
    <Inputs>
      <Argument name="workflow" type="Workflow">
        <Description>The Workflow object being executed.</Description>
      </Argument>
      <Argument name="item" type="WorkItem">
        <Description>The WorkItem representing the review.</Description>
      </Argument>
      <Argument name="approvalSet" type="ApprovalSet">
        <Description>The ApprovalSet object contained in the work item.</Description>
      </Argument>
      <Argument name="launcher" type="string">
        <Description>The name of the Identity that launched the workflow.</Description>
      </Argument>
      <Argument name="identityName" type="string">
        <Description>The name of the Identity that is being changed.</Description>
      </Argument>
      <Argument name="identityDisplayName" type="string">
        <Description>The display name of the Identity that is being changed. </Description>
      </Argument>
    </Inputs>
  </Signature>
  <Subject>Action Required: Request Awaiting Approval</Subject>
</EmailTemplate>

@mer21 @brian_weigel Thanks a lot that was really helpfull. cheers

1 Like

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.