web
You’re offline. This is a read only version of the page.
close
Skip to main content

Notifications

Announcements

No record found.

Community site session details

Community site session details

Session Id :
Finance | Project Operations, Human Resources, ...
Answered

Multiple line approval for workflows

(0) ShareShare
ReportReport
Posted on by 343

Hi All,

I have a requirement to approve multiple workitems assigned to me.

There are many threads on this but no proper solution is available. 
please help.

Thanks,

Priya

I have the same question (0)
  • Suggested answer
    GirishS Profile Picture
    27,827 Moderator on at

    Hi Priya,

    You can do like below.

    For each workflow you will be having separate approval menu items. So you need to use switch case based on RefTableId field on WorkflowWorkItem table.

    WorkflowWorkItemTable workItem;
    
    while select * from workItem
        where workItem.UserId = cusrUserid()
    {
        //add a swith case statement to find out the workflow.
        switch(workItem.RefTableId)
        case tablenum(Table1):
        WorkflowWorkItemActionManager::dispatchWorkItemAction(workItem,"Approved",curUserId(),
                            WorkflowWorkItemActionType::Complete,menuItemActionStr(YourWorkflowApprovalMenuItem2),"WorkflowApproval");
                            break;
        
        case tablenum(Table1):
         WorkflowWorkItemActionManager::dispatchWorkItemAction(workItem,"Approved",curUserId(),
                            WorkflowWorkItemActionType::Complete,menuItemActionStr(YourWorkflowApprovalMenuItem2),"WorkflowApproval");
                            break;
    }

    Thanks,

    Girish S.

  • PriyaDutta Profile Picture
    343 on at

    Hi Girish,

    I found the below piece of code. Can you tell me where should I add the above code.

    internal final class MassTimeApproval
    {
        public static void actionItem(WorkflowWorkItemActionType action, WorkflowWorkItemTable _workitem, WorkflowComment _comment,MenuItemName _menuItem )
            
        {
               WorkflowWorkItemActionManager::dispatchWorkItemAction(_workitem,
                                                                            _comment,
                                                                            '',
                                                                            action,
                                                                            _menuItem,
                                                                            '');
            
        }
    
            public static WorkflowWorkitemTable getActiveWorkitemForRecord(Common _buffer)
        
        {
                WorkflowWorkitemTable           workitem;
                RecId                           refRecid = _buffer.RecId;
                TableId                         refTableId = _buffer.TableId;
            
                select workitem where workitem.RefRecId == refRecid && workitem.RefTableId == refTableId
                    && (workitem.Status == WorkflowWorkItemStatus::Pending || workitem.Status == WorkflowWorkItemStatus::Delegated);
            
                return workitem;
            
        }
    
            public static container getMenuItemForType(WorkflowWorkItemtable _workitem, WorkflowWorkItemActionType _type, UserId user)
        
        {
                #Workflow
            
                WorkflowElementTable            workflowElement;
                SysDictWorkflowElement          dictWorkflowElem;
            
                WorkflowConfigOutcome           workflowConfigOutcome;
                WorkflowWorkItemActionType      workItemActionType;
            
                Map                             actionList;
                MapEnumerator                   actionListEnum;
                Map                             outcomeList;
                MapEnumerator                   outcomeListEnum;
            
                SysDictMenu                     sysDictMenu;
            
                MenuItemName                    mi;
            //WorkflowWorkItemActionDelegate WorkflowWorkItemActionDelegate;
            
                container ret = ["",""];
                ;
                if (_workitem.Type != WorkflowWorkItemType::Recall)
            
            {
                        workflowElement = WorkflowElementTable::find(_workitem.ElementId);
                        if (workflowElement.RecId != 0)
                
                {
                                dictWorkflowElem = new SysDictWorkflowElement(workflowElement.ElementType, workflowElement.ElementName);
                    
                                if (_workitem.Type == WorkflowWorkItemType::RequestChange || _workitem.Type == WorkflowWorkItemType::Return)
                    
                    {
                                        //ADD RESUBMIT ITEMS
                                        mi = dictWorkflowElem.resubmitMenuItem();
                                        sysDictMenu = SysDictMenu::newMenuItem(mi,MenuItemType::Action);
                                        if (_type == WorkflowWorkItemActionType::Resubmit)
                        
                        {
                                                ret = [mi, sysDictMenu.label()];
                                                return ret;
                            
                        }
                        
                    }
                                else
                    
                    {
                        
                                        workflowConfigOutcome = workflowElement.getElementOutcomes();
                        
                                        actionList = workflowConfigOutcome.parmActionList();
                                        actionListEnum = actionList.getEnumerator();
                        
                                        outcomeList = workflowConfigOutcome.parmOutcomList();
                                        outcomeListEnum = outcomeList.getEnumerator();
                        
                                        while (outcomeListEnum.moveNext())
                        
                        {
                                                if (outcomeListEnum.currentValue() == NoYes::Yes)
                            
                            {
                                                        mi = dictWorkflowElem.actionMenuItem(outcomeListEnum.currentKey());
                                                        sysDictMenu = SysDictMenu::newMenuItem(mi,MenuItemType::Action);
                                                        workItemActionType = WorkflowWorkItemActionManager::findActionTypeForMenuItem(_workitem, mi);
                                                        if (workItemActionType == _type)
                                
                                {
                                                                if (sysDictMenu)
                                    
                                    {
                                                                        ret = [mi, sysDictMenu.label()];
                                                                        break;
                                        
                                    }
                                    
                                }
                                
                            }
                            
                        }
                        
                                        if (_type == WorkflowWorkItemActionType::Delegate)
                        
                        {
                                                while (actionListEnum.moveNext())
                            
                            {
                                                        // make sure action is enabled
                                                        if (actionListEnum.currentValue() == NoYes::Yes)
                                
                                {
                                                                if (actionListEnum.currentKey() == #WorkflowWorkItemActionDelegate)
                                    
                                    {
                                                                        // allow delegate if work item is not a final approver work item
                                                                        if (_workitem.Type != WorkflowWorkItemType::FinalApprover)
                                        
                                        {
                                                                                mi = dictWorkflowElem.delegateMenuItem();
                                                                                sysDictMenu = SysDictMenu::newMenuItem(mi,MenuItemType::Action);
                                                                                ret = [mi, sysDictMenu.label()];
                                            
                                        }
                                        
                                    }
                                    
                                }
                                
                            }
                            
                        }
                        
                    }
                    
                }
                
            }
                return ret;
            
        }
    
            public static void main(Args args)
        
        {
                FormDataSource                  ds = args.record().dataSource();
                Common                          record;
                WorkflowWorkItemTable           workitem;
                WorkflowComment                 comment;
                MenuItemName                    menuitem;
                str                             label;
                WorkflowWorkItemActionType      action;
                boolean                         commented;
                WorkflowWorkItemActionDialog    dialog;
                TSTimesheetTable                tsTimesheetTable;
            
            
                action = WorkflowWorkItemActionType::Complete;
            
                for(record = ds.getFirst(true) ? ds.getFirst(true) : ds.cursor(); record; record = ds.getNext())
            
            {
                        workitem = MassTimeApproval::getActiveWorkitemForRecord(record);
                        if (workitem)
                
                {
                    [menuitem,Label] = MassTimeApproval::getMenuItemForType(workitem, action , curUserId());
                                if (!commented)
                    
                    {
                                        dialog = WorkflowWorkItemActionDialog::construct(workitem, action, new MenuFunction(menuitem, MenuItemType::Action));
                                        dialog.run();
                                        if (dialog.parmIsClosedOK())
                        
                        {
                                                commented = true;
                                                comment = dialog.parmWorkflowComment();
                            
                        }
                                        else
                        
                        {
                                                break;
                            
                        }
                        
                    }
                                if (menuitem)
                    
                    {
                        MassTimeApproval::actionItem(action, workitem,comment,menuitem);
                                        tsTimesheetTable = TSTimesheetTable::findRecId(record.RecId);
                                        if(tsTimesheetTable)
                        
                        {
                                                SourceDocumentProcessorFacade::submitSourceDocumentImplementation(tsTimesheetTable, false, SourceDocumentAccountingStatus::Completed);
                            
                        }
                        
                    }
                                else
                    
                    {
                                        error(strFmt("No %1 action defined for item %2", action, record.caption()));
                        
                    }
                    
                }
                
            }
                ds.research();
                ds.refresh();
            
            
        }
    
    }

    Thanks,

    Priya

  • Verified answer
    GirishS Profile Picture
    27,827 Moderator on at

    On your code - Line number 174, you are getting the work item by calling the getActiveWorkitemForRecord. After that code just call the below piece of code.

    You know the Approval menu item for timesheet - Just mention the action menu item name itself - No need to write separate method to get the action approval menu item.

    WorkflowWorkItemActionManager::dispatchWorkItemAction(workItem,"Approved",curUserId(),
                            WorkflowWorkItemActionType::Complete,menuItemActionStr(YourWorkflowApprovalMenuItem2),"WorkflowApproval");
                            break;

    You can comment all the other codes after that.

    If not working properly, debug the code and find out on which line it gets failed.

    Thanks,

    Girish 

  • PriyaDutta Profile Picture
    343 on at

    Hi Girish,

    By approval menu item you mean the menu item button that is created in the form calling the action menu item “MassTimeApproval” ?

  • Suggested answer
    GirishS Profile Picture
    27,827 Moderator on at

    It's related to the workflow completed action menu item. While creating workflows action menu item will be created. You can find that in workflow types- property name will be CompletedEventHandler.

    If its a timesheet workflow then menu item name will be TSWorkflowEventHandler.

    Thanks,

    Girish S.

  • PriyaDutta Profile Picture
    343 on at

    Hi Girish,

    So should I create new workflow or can I use the standard workflow and the menu items already present. 

  • Verified answer
    GirishS Profile Picture
    27,827 Moderator on at

    No need to create new workflow - Use the standard workflow menu items.

    Thanks,

    Girish S.

  • PriyaDutta Profile Picture
    343 on at

    Hi Girish,

    Thanks for your help.

    I am able to now Approve and Reject multiple timesheets for review.

    But I am struggling with Delegation.

    I am getting below error on clicking 'Delegate'.

    pastedimage1678365162749v1.png

    Please find the below code .

    internal final class MassTimeDelegate
    {
        public static void main(Args args)
        
        {
           // FormDataSource                  ds = args.record().dataSource();
            FormDataSource                  ds = FormDataUtil::getFormDataSource( args.record());
            Common                          record;
            WorkflowWorkItemTable           workitem;
            //WorkflowComment                 comment;
            //MenuItemName                    menuitem;
            //str                             label;
            WorkflowWorkItemActionType      action;
          
            
            
            action = WorkflowWorkItemActionType::Delegate;
          
            
            for(record = ds.getFirst(true) ? ds.getFirst(true) : ds.cursor(); record; record = ds.getNext())
            
            {
                
    
                select * from workItem
                    where workItem.UserId == curUserid() && workItem.RecId == record.RecId;
               
               
    
                WorkflowWorkItemActionManager::dispatchWorkItemAction(workItem,'Delegated',curUserId(),
                           WorkflowWorkItemActionType::Delegate,menuItemActionStr(TSworkflowDelegate),'WorkflowApproval');
               
              
               
    
            }
            ds.research();
            ds.refresh();
    
            
        }

    On debugging I find error is being thrown after below statement

    pastedimage1678365417826v2.png

    Not sure what is the issue. When i am going to standard form "Work items assigned to me " I am able to delegate  work items.

    Please help.

    Thanks ,

    Priya

  • Verified answer
    GirishS Profile Picture
    27,827 Moderator on at

    From the error I think "curUserId" already has a work item assigned for the same workflow step. Check what is the value of _toUser and  _fromUser in the arguments of delegate method.

    Also open the WorkflowWorkItemTable and see whether the delegated user has already a work Item assigned.

    Thanks,

    Girish S.

  • PriyaDutta Profile Picture
    343 on at

    Hi Girish,

    I just checked that while passing user in below statement

     WorkflowWorkItemActionManager::dispatchWorkItemAction(workItem,'Delegated',curUserId(),
                           WorkflowWorkItemActionType::Delegate,menuItemActionStr(TSworkflowDelegate),'WorkflowApproval');
                           

    In standard , they are passing _toUser  value , whereas in my code current user is getting passed, due to which the both toUser and fromUser values are same.

    So,I have updated the code to fetch target user .

    WorkflowWorkItemActionDialog workflowWorkItemActionDialog;
    
                workflowWorkItemActionDialog = WorkflowWorkItemActionDialog::construct(workItem,
                                                                                   WorkflowWorkItemActionType::Delegate,
                    new MenuFunction(menuItemActionStr(TSworkflowDelegate),MenuItemType::Action),
                                                                                    'Action');
                workflowWorkItemActionDialog.run();
    
              
                if (workflowWorkItemActionDialog.parmIsClosedOK())
                    {
                        WorkflowWorkItemActionManager::dispatchWorkItemAction(workItem,'Delegated',workflowWorkItemActionDialog.parmTargetUser(),
                           WorkflowWorkItemActionType::Delegate,menuItemActionStr(TSworkflowDelegate),'WorkflowApproval');
               
                    }

    Its working fine now.

    Thanks for your help,

    Priya

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Responsible AI policies

As AI tools become more common, we’re introducing a Responsible AI Use…

Neeraj Kumar – Community Spotlight

We are honored to recognize Neeraj Kumar as our Community Spotlight honoree for…

Leaderboard > Finance | Project Operations, Human Resources, AX, GP, SL

#1
Martin Dráb Profile Picture

Martin Dráb 584 Most Valuable Professional

#2
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 499 Super User 2025 Season 2

#3
Sohaib Cheema Profile Picture

Sohaib Cheema 254 User Group Leader

Last 30 days Overall leaderboard

Product updates

Dynamics 365 release plans