How to call workflow during account deletion?

I have created one custom quicklink for deletion of account based on selected application. How can I call workflow when I am click on delete button and after that It will call approval process for deletion.

Manually we are deleting account from manage Access → manage Accounts ->select account → delete. Once we delete account it is going for approval.

So, I want same step for my custom quicklink. Once I will click on delete button from my form after selecting account based on application it will delete and follow approval process.

what will be the LCM process I need to call in my step?
How can I add this workflow ?

You can have a step in your custom quicklink workflow that you are using to present form. The workflow step should create a provisioning plan to delete the account on selected application. You can then call the LCM provisioning workflow in next step passing the plan you created as a input.

If you can post the quicklink workflow here I can provide details with some sample

To call a workflow from quicklink you may have to modify the quicklink action in the quicklink object to workflow and under the attributes initialize the name of the workflow under entry key value "workflowName"

<QuickLink action="workflow" category="quicklink category goes here" messageKey="quicklink message key goes here" name=”Quicklink name goes here ">
<Attributes>
<Map>
<entry key="workflowName" value=" workflow name goes here"/>
</Map>
</Attributes>
<Description>workflow description here</Description>
</QuickLink>

quickLink:

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Workflow PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Workflow created="1746428134679" explicitTransitions="true" handler="sailpoint.api.StandardWorkflowHandler" id="0ac13988961e13a081969f3a85174ca3" libraries="Identity" modified="1746704916592" name="TEF_Search_Users_Test" type="IdentityLifecycle">
  <Variable input="true" name="launcher"/>
  <Variable name="identityModel"/>
  <Variable initializer="true" name="transient"/>
  <Step icon="Start" name="Start" posX="82" posY="126">
    <Transition to="Initialize identityModel"/>
  </Step>
  <Step action="call:getIdentityModel" name="Initialize identityModel" posX="242" posY="126" resultVariable="identityModel">
    <Arg name="identityName" value="ref:identityName"/>
    <Arg name="expandLinks" value="script:return true;"/>
    <Description>Initialize the data for the identity that we are disabling.</Description>
    <Transition to="Initial Form"/>
  </Step>
  <Step icon="Default" name="Initial Form" posX="375" posY="127">
    <Approval name="ApplicationForm" owner="ref:launcher" return="identityModel">
      <Arg name="workItemFormBasePath" value="identityModel"/>
      <Form name="ApplicationForm">
        <Attributes>
          <Map>
            <entry key="hideIncompleteFields">
              <value>
                <Boolean></Boolean>
              </value>
            </entry>
            <entry key="includeHiddenFields">
              <value>
                <Boolean></Boolean>
              </value>
            </entry>
            <entry key="isWizard">
              <value>
                <Boolean></Boolean>
              </value>
            </entry>
            <entry key="pageTitle" value="ApplicationForm"/>
          </Map>
        </Attributes>
        <Description>User Selection Form</Description>
        <Section name="Section 1">
          <Field displayName="Search Application" dynamic="true" name="application" postBack="true" type="string">
            <AllowedValuesDefinition>
              <Value>
                <List>
                  <String>PCA - INFRA - Azure SGRSSS Non-PROD Tenant</String>
                </List>
              </Value>
            </AllowedValuesDefinition>
          </Field>
          <Field displayName="Input(ID,Email,FirstName,LastName)" dynamic="true" name="searchedUser" postBack="true" type="String">
            <AllowedValuesDefinition>
              <Script>
                <Source>




                  String appName = form.getField("application").getValue();
                  /* log.error("applicationName==>"+applicationName);
                  return applicationName; */

                  import sailpoint.object.Identity;
                  import sailpoint.object.Link;
                  import sailpoint.object.Filter;
                  import sailpoint.object.QueryOptions;
                  import sailpoint.object.Application;
                  import sailpoint.api.SailPointContext;
                  import sailpoint.tools.Util;

                  String appName = form.getField("application").getValue();  // Assumes field is named "application"

                  Application app = context.getObjectByName(Application.class, appName);
                  if (app == null) {
                  log.error("Could not find an Application named: " + appName);
                  return "Application not found: " + appName;
                  }

                  QueryOptions qo = new QueryOptions();
                  qo.addFilter(Filter.eq("application", app));

                  Iterator&lt;Link> it = context.search(Link.class, qo);

                  ArrayList&lt;String> info = new ArrayList&lt;String>();

                  while (it.hasNext()) {
                  Link link = it.next();
                  Identity id = link.getIdentity();
                  //String appName2 = link.getApplication().getName();
                  //   String acctName = link.getNativeIdentity();
                  String appAccountName=id.getName();   

                  info.add(appAccountName);
                  }

                  Util.flushIterator(it);

                  // Optionally return a string, or build an HTML table for display
                  // return info.toString();  // Or format as needed
                  return info;


                </Source>
              </Script>
            </AllowedValuesDefinition>
          </Field>
        </Section>
        <Button action="next" label="Next" parameter="userAction" value="next"/>
      </Form>
    </Approval>
    <Transition to="User Info Page"/>
  </Step>
  <Step icon="Default" name="User Info Page" posX="502" posY="126">
    <Approval name="User Details Form" owner="ref:launcher" return="identityModel,tableData" send="identityModel,tableData">
      <Form name="User Details Form">
        <Attributes>
          <Map>
            <entry key="hideIncompleteFields">
              <value>
                <Boolean></Boolean>
              </value>
            </entry>
            <entry key="includeHiddenFields">
              <value>
                <Boolean></Boolean>
              </value>
            </entry>
            <entry key="pageTitle" value="User Details Form"/>
          </Map>
        </Attributes>
        <Description>Second Form</Description>
        <Section name="Section 12" type="text">
          <Field displayName="User Info Page" filterString="htmlRender" name="tableData" type="text">
            <Attributes>
              <Map>
                <entry key="contentIsEscaped" value="true"/>
              </Map>
            </Attributes>
            <Script>
              <Source> import sailpoint.object.Filter;
                import sailpoint.object.IdentityEntitlement;
                import sailpoint.object.Link;
                import sailpoint.object.QueryOptions;
                import sailpoint.object.ManagedAttribute;
                import sailpoint.object.Application;
                import sailpoint.tools.GeneralException;
                import sailpoint.tools.Util;
                import sailpoint.object.Bundle;
                import sailpoint.object.Identity;
                import org.apache.commons.logging.Log;
                import org.apache.commons.logging.LogFactory;


                String mainStr="";


                System.out.println("identityModel:::::"+identityModel);
                String SearchValue = (String)identityModel.get("searchedUser");
                System.out.println("SearchValue:::"+SearchValue);
                // Define the attributes to return




                // Filter.like("FirstName", "%" + searchTerm + "%"),      

                QueryOptions qo = new QueryOptions();
                Filter f1 = Filter.eq("name", SearchValue);
                Filter f2 = Filter.like("firstname", SearchValue,Filter.MatchMode.START);
                Filter f3 = Filter.like("lastname", SearchValue,Filter.MatchMode.START);
                Filter f4 = Filter.eq("email", SearchValue);

                qo.add(Filter.or(f1,f2,f3,f4));


                List&lt;Identity> identities = context.getObjects(Identity.class, qo);

                //  System.out.println(">>>>>>>>>>>>>>>"+ identities);









                if (identities != null &amp;&amp; !identities.isEmpty()) {

                for (Identity identity : identities) {
                System.out.println("Inside for:::::"+identity);
                String identityAttributes = identity.getFirstname();
                //  System.out.println("identityAttributes::"+identityAttributes);

                String AppName = (String)identityModel.get("application");

                mainStr = "&lt;table border=\"1\" cellpadding=\"3\" cellspacing=\"3\" width=\"100%\" style=\"word-break:break-all;\">\n" +
                "  &lt;tr>\n" +
                "  &lt;th>FirstName&lt;/th>\n"+
                "  &lt;th>LastName&lt;/th>\n"+
                "  &lt;th>Email&lt;/th>\n"+
                "  &lt;th>PRUID&lt;/th>\n" +
                "  &lt;th>AppName&lt;/th>\n" +
                "  &lt;/tr>\n";

                mainStr += 
                "&lt;tr>\n"+ "&lt;td>"+ identity.getFirstname()+ "&lt;/td>\n"+
                "&lt;td>" + identity.getLastname() + "&lt;/td>\n"+
                "&lt;td>" + identity.getEmail()+"&lt;/td>\n"+
                "&lt;td>" + identity.getName()+"&lt;/td>\n"+
                "&lt;td>" + AppName +"&lt;/td>\n"+
                "&lt;/tr>\n";


                }
                }else{
                mainStr = "&lt;table border=\"1\" cellpadding=\"3\" cellspacing=\"3\" width=\"100%\" style=\"word-break:break-all;\">\n" +
                "  &lt;tr>\n" +
                "  &lt;p>&lt;/p>\n" +
                "  &lt;p>Data Not Found&lt;/p>\n" +

                "  &lt;/tr>\n";



                System.out.println("inside else");


                }



                log.debug("Execution Completed for Row Data:");
                log.error("Execution Completed for Row Data:");
                return mainStr;



              </Source>
            </Script>
          </Field>
        </Section>
        <Button action="cancel" label="Cancel" parameter="userAction" skipValidation="true" value="cancel"/>
        <Button action="next" label="Delete"/>
      </Form>
    </Approval>
    <Transition to="Build Plan"/>
  </Step>
  <Step icon="Task" name="Build Plan" posX="584" posY="502" resultVariable="plan">
    <Script>
      <Source> 
         

        import sailpoint.object.*;
        import sailpoint.api.ProvisioningPlan;
        import sailpoint.object.ProvisioningPlan.AccountRequest;
        import sailpoint.object.ProvisioningPlan.ObjectOperation;

        String identityName = identityModel.get("searchedUser");
        String appName = identityModel.get("application");

        Identity identity = context.getObjectByName(Identity.class, identityName);
        if (identity == null) {
        throw new GeneralException("Identity not found: " + identityName);
        }

        List&lt;Link> links = identity.getLinks();
        String nativeIdentity = null;

        for (Link link : links) {
        if (link.getApplicationName().equals(appName)) {
        nativeIdentity = link.getNativeIdentity();
        break;
        }
        }

        if (nativeIdentity == null) {
        throw new GeneralException("No account found on app: " + appName);
        }

        AccountRequest acctReq = new AccountRequest();
        acctReq.setApplication(appName);
        acctReq.setNativeIdentity(nativeIdentity);
        acctReq.setOp(ObjectOperation.Delete);

        ProvisioningPlan plan = new ProvisioningPlan();
        plan.setIdentity(identity);
        plan.add(acctReq);

        return plan;

        </Source>
    </Script>
    <Transition to="Provision"/>
  </Step>
  <Step icon="Task" name="Provision" posX="645" posY="111">
    <Arg name="adminUtilityAccess" value="ref:adminUtilityAccess"/>
    <Arg name="participantNumber" value="ref:participantNumber"/>
    <Arg name="identityEmailTemplate"/>
    <Arg name="formTemplate"/>
    <Arg name="enableRetryRequest"/>
    <Arg name="securityOfficerElectronicSignature"/>
    <Arg name="fallbackApprover" value="string:spadmin"/>
    <Arg name="endOnManualWorkItems"/>
    <Arg name="userEmailTemplate" value="ref:userEmailTemplate"/>
    <Arg name="policiesToCheck" value="ref:policiesToCheck"/>
    <Arg name="project"/>
    <Arg name="workItemComments"/>
    <Arg name="identityRequestId"/>
    <Arg name="approvalSplitPoint"/>
    <Arg name="source" value="ref:source"/>
    <Arg name="identityDisplayName" value="ref:participantNumber"/>
    <Arg name="foregroundProvisioning" value="ref:foregroundProvisioning"/>
    <Arg name="ownerElectronicSignature"/>
    <Arg name="batchRequestItemId"/>
    <Arg name="saveUnmanagedPlan_WithProjectArgument"/>
    <Arg name="splitPlans"/>
    <Arg name="doRefresh" value="ref:doRefresh"/>
    <Arg name="approverElectronicSignature" value="ref:approverElectronicSignature"/>
    <Arg name="plan" value="ref:plan"/>
    <Arg name="flow" value="ref:flow"/>
    <Arg name="identityElectronicSignature"/>
    <Arg name="identityName" value="ref:participantNumber"/>
    <Arg name="approvalSet"/>
    <Arg name="violationReviewDecision"/>
    <Arg name="filterRejects"/>
    <Arg name="splitProvisioning"/>
    <Arg name="saveUnmanagedPlan"/>
    <Arg name="splitProjects"/>
    <Arg name="noTriggers"/>
    <Arg name="requireCommentsForDenial"/>
    <Arg name="requesterEmailTemplate"/>
    <Arg name="approvalEmailTemplate" value="ref:approvalEmailTemplate"/>
    <Arg name="ticketManagementApplication" value="ref:ticketManagementApplication"/>
    <Arg name="securityOfficerName" value="ref:securityOfficerName"/>
    <Arg name="approvingIdentities" value="string:spadmin"/>
    <Arg name="managerEmailTemplate" value="ref:managerEmailTemplate"/>
    <Arg name="ticketId"/>
    <Arg name="approvalScheme" value="string:spadmin"/>
    <Arg name="allowRequestsWithViolations"/>
    <Arg name="workItemPriority" value="ref:workItemPriority"/>
    <Arg name="managerElectronicSignature"/>
    <Arg name="requireViolationReviewComments"/>
    <Arg name="splitApprovalSet"/>
    <Arg name="approvalMode" value="ref:approvalMode"/>
    <Arg name="trace" value="ref:trace"/>
    <Arg name="recompile"/>
    <Arg name="endOnProvisioningForms"/>
    <Arg name="splitWorkItemComments"/>
    <Arg name="requireCommentsForApproval"/>
    <Arg name="notificationScheme" value="ref:notificationScheme"/>
    <Arg name="manualActionsEmailTemplate"/>
    <Arg name="policyViolations"/>
    <Arg name="policyScheme" value="ref:policyScheme"/>
    <Arg name="setPreviousApprovalDecisions"/>
    <Arg name="approvalForm"/>
    <Arg name="optimisticProvisioning" value="ref:optimisticProvisioning"/>
    <Arg name="securityOfficerEmailTemplate" value="ref:securityOfficerEmailTemplate"/>
    <WorkflowRef>
      <Reference class="sailpoint.object.Workflow" id="8a2329c64013a36c014013a4c40c024d" name="LCM Provisioning"/>
    </WorkflowRef>
    <Transition to="end"/>
  </Step>
  <Step icon="Stop" name="end" posX="646" posY="217"/>
</Workflow>


Can anyone help on this to trigger workflow, after clicking on delete button from second from it is not working?

Did you update the quicklink action in the quicklink object?

I have already added.

There were couple of issues with your workflow code which I fixed and it should work fine. You can compare the code to find what changed but it was mainly 2 things. Your import statement for ProvisioningPlan was corrected and you were using participantNumber variable in Provision step which needed to be mapped to identityName. You can try to use the attached XML
TEF_Search_Users_Test.xml (14.0 KB)