Skip to main content

Notifications

Announcements

No record found.

Finance | Project Operations, Human Resources, ...
Answered

Multiple line approval for workflows

Posted on by 303

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

  • GirishS Profile Picture
    GirishS 27,832 Super User 2024 Season 1 on at
    RE: Multiple line approval for workflows

    Please mark the helpful answers as verified, so others can make use of this thread.

    Thanks,

    Girish S.

  • PriyaDutta Profile Picture
    PriyaDutta 303 on at
    RE: Multiple line approval for workflows

    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

  • Verified answer
    GirishS Profile Picture
    GirishS 27,832 Super User 2024 Season 1 on at
    RE: Multiple line approval for workflows

    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
    PriyaDutta 303 on at
    RE: Multiple line approval for workflows

    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
    GirishS 27,832 Super User 2024 Season 1 on at
    RE: Multiple line approval for workflows

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

    Thanks,

    Girish S.

  • PriyaDutta Profile Picture
    PriyaDutta 303 on at
    RE: Multiple line approval for workflows

    Hi Girish,

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

  • Suggested answer
    GirishS Profile Picture
    GirishS 27,832 Super User 2024 Season 1 on at
    RE: Multiple line approval for workflows

    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
    PriyaDutta 303 on at
    RE: Multiple line approval for workflows

    Hi Girish,

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

  • Verified answer
    GirishS Profile Picture
    GirishS 27,832 Super User 2024 Season 1 on at
    RE: Multiple line approval for workflows

    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
    PriyaDutta 303 on at
    RE: Multiple line approval for workflows

    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

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

December Spotlight Star - Muhammad Affan

Congratulations to a top community star!

Top 10 leaders for November!

Congratulations to our November super stars!

Tips for Writing Effective Suggested Answers

Best practices for providing successful forum answers ✍️

Leaderboard

#1
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 291,280 Super User 2024 Season 2

#2
Martin Dráb Profile Picture

Martin Dráb 230,235 Most Valuable Professional

#3
nmaenpaa Profile Picture

nmaenpaa 101,156

Leaderboard

Product updates

Dynamics 365 release plans