How to create multiple workitems without using LCM OOTB workflow

We have a custom wf which displays a form and lets end-user set owner of any selected entitlement. but before it is sent to OOTB Entitlement Update wf it goes via 2 or 3 level approval depending upon configuration set.

Till now we allowed only one entitlement in the form to be submitted. But now we want to expand this to 3 entitlements. which means on the form there will be 3 drop-downs to select 3 different entitlements, for which the selected owner will be the same for all 3. currently for this use case user has to submit 3 different requests.

So how can we do it our current wf. I am attaching the Approval step we have currently which is called immediately after the form is submitted and it contains the OwnerScript as well.

We want 3 different approvals altogether for 3 entitlements which will be selected. if any workitem is rejected it should not impact the other 2 workitems in progress.

  <Step icon="Message" name="Confirm" posX="332" posY="209">
    <Approval mode="serial" name="Update-Group-Approval-Form" return="identityName,PrimaryGroupOwner,SecondaryGroupOwner,Level1Owner,approvalType,GroupDN,requester,launcher,applicationName,selectentitlement,userComments,groupDisplayName,selectSystemOwner,ssOwner" send="identityName,PrimaryGroupOwner,SecondaryGroupOwner,Level1Owner,approvalType,GroupDN,requester,launcher,applicationName,selectentitlement,userComments,selectSystemOwner,ssOwner">
      <AfterScript>
        <Source>


          import sailpoint.server.Auditor;
          import sailpoint.object.AuditEvent;
          import sailpoint.object.Identity;
          import sailpoint.object.ManagedAttribute;
          import sailpoint.object.WorkItem;

          log.warn(item.toXml());
          String string1 =null;
          String string2 =null;
          String string3 =null;
          String string4 =null;
          String target = null;
          String completer = null;
          String attributeValue = null;



          if(WorkItem.State.Finished.equals(item.getState()))
          {
            log.warn("=======This is inside approve condition========");
            completer = item.getCompleter();  
            log.warn("The completer is: "+completer);

            workflow.put("completer",completer);
            log.warn("=======Yeah this is approved========");

          }
          else if (WorkItem.State.Rejected.equals(item.getState()))
          {
            log.warn("=======This is inside reject condition========");

            log.warn("=======This is item.xml========");
            log.warn(item.toXml());
            completer = item.getCompleter();  
            log.warn("The completer is: "+completer);

            workflow.put("completer",completer);
            log.warn("=======Yeah this is rejected========");

          }
          else 
          {
            log.warn("=======This is inside expire condition========");
            log.warn("=======Yeah this is expired========");
          }

          context.commitTransaction();

          log.warn("===========This is afterscript section ending.============");

        </Source>
      </AfterScript>
      <Arg name="forceClassicApprovalUI" value="true"/>
      <Arg name="SystemOwner" value="script:resolveDisplayName(ssOwner)"/>
      <Arg name="requester" value="ref:requester"/>
      <Arg name="approvalScheme" value="ref:approvalScheme"/>
      <Arg name="workItemType" value="Form"/>
      <Arg name="workItemDescription">
        <Script>
          <Source>import sailpoint.object.ManagedAttribute;

            if(selectentitlement!=null &amp;&amp; selectentitlement!=void)
            {
              log.warn("check2 " + selectentitlement);
              ManagedAttribute ma=context.getObjectById(ManagedAttribute.class,selectentitlement);
              String displayName = ma.getDisplayableName();
              return "Group Automation Request for "+displayName;
            }
            else
            {
            	return null;
            }
          </Source>
        </Script>
      </Arg>
      <Arg name="workItemForm" value="string:Update-Group-Approval-Form"/>
      <Arg name="identityName" value="ref:identityName"/>
      <Arg name="userFormWorkItemDescription" value="script:return &quot;Update Group Request by &quot;+launcher;"/>
      <Arg name="groupDisplayName">
        <Script>
          <Source>import sailpoint.object.ManagedAttribute;



            if(selectentitlement!=null &amp;&amp; selectentitlement!=void)
            {

              ManagedAttribute ma=context.getObjectById(ManagedAttribute.class,selectentitlement);

              return ma.getDisplayableName();
              }
            else
            {
              return null;
            }
          </Source>
        </Script>
      </Arg>
      <Arg name="PrimaryGroupOwner" value="ref:PrimaryGroupOwner"/>
      <Arg name="Level1Owner" value="ref:Level1Owner"/>
      <Arg name="approvalType" value="ref:approvalType"/>
      <Arg name="SecondaryGroupOwner" value="ref:SecondaryGroupOwner"/>
      <Arg name="GroupDN" value="ref:GroupDN"/>
      <Arg name="userComments" value="ref:userComments"/>
      <Arg name="applicationName" value="ref:applicationName"/>
      <Arg name="target" value="ref:GroupDN"/>
      <Arg name="ccToAddress" value="ref:requesteeEmail"/>
      <Arg name="ssOwner" value="ref:ssOwner"/>
      <OwnerScript>
        <Source>

          import java.util.Arrays;

          import java.util.List;

          import sailpoint.tools.Util;
          import sailpoint.object.Identity;


          List ownerAsList = new ArrayList();
          log.warn("The Launcher is check3 : " + launcher);
          Identity identityObject = context.getObjectByName(Identity.class, launcher); 
          Identity auditorObject = context.getObjectByName(Identity.class, "Compliance-Management"); 

          String manager = identityObject.getManager().getName();
          String auditor = auditorObject.getName();
          log.warn("the manager is : "+manager);
          log.warn("the system owner is : "+ssOwner);

          if(manager.equalsIgnoreCase(ssOwner))
          {
          	ownerAsList = Arrays.asList(manager,auditor);
          }
          else
          {
          	ownerAsList = Arrays.asList(manager,ssOwner,auditor);

          }

          return ownerAsList;

        </Source>
      </OwnerScript>
      <WorkItemConfig escalationStyle="both" hoursBetweenReminders="48" hoursTillEscalation="48" maxReminders="2">
        <EscalationEmailTemplateRef>
          <Reference class="sailpoint.object.EmailTemplate" id="" name="Work Item Escalation"/>
        </EscalationEmailTemplateRef>
        <EscalationRuleRef>
          <Reference class="sailpoint.object.Rule" id="" name="Group-Management-Expire-Rule"/>
        </EscalationRuleRef>
        <NotificationEmailTemplateRef>
          <Reference class="sailpoint.object.EmailTemplate" id="" name="Group-Management-Initial-EmailTemplate"/>
        </NotificationEmailTemplateRef>
        <ReminderEmailTemplateRef>
          <Reference class="sailpoint.object.EmailTemplate" id="" name="Group-Management-Reminder-EmailTemplate"/>
        </ReminderEmailTemplateRef>
      </WorkItemConfig>
    </Approval>
    <Description>Present user with a confirmation form before creating the group.</Description>
    <Transition to="Create Workgroup" when="script:approved"/>
    <Transition to="Expired Notification">
      <Script>
        <Source>log.warn("the approval state is: "+lastApprovalState);
          if(lastApprovalState.equals("Expired"))
          {

          return true;
          }</Source>
      </Script>
    </Transition>
    <Transition to="Rejected Notification"/>
  </Step>

@aakashpandita So, do you need to create three different approval flow? You can read the data selected by the user and you can iterate over them to generate three different approval item, Please give it a try.

In case you need help with the code/logic, please share the form and workflow artefacts used in this module.

exactly that is what i want to know, where do i iterate and how ? will it be in any step previous to step or where exactly?
can you provide me a high level code snippet for this. it would be really helpful.

@aakashpandita You need to do it in your workflow after you get the input in the form.

You need to move your approval generation steps to a different workflow and in your parent workflow you need to create a loop, where you pass one entitlement at a time.

If you share your form and workflow artefacts, i can try to modify and share it back to you. (If it works, you can also share it over chat as well).