Разработка собственного рабочего процесса для журнала инвентаризации (Counting journal)

Category: Статьи Post Date: 22.06.2020

В этом блоге вы узнаете, как разработать собственный рабочий процесс (Workflow), который не входит в комплект поставки D365 for Finance. Для этого я создам рабочий процесс для утверждения журналов инвентаризации (Управление запасами >> Журналы >> Учет номенклатур>>Инвентаризация), потому что в системе нет такого процесса для модуля управления запасами. Ниже приведены шаги, которые необходимо выполнить.
Шаги:

  1. Создать базовое перечисление для статуса документа
    2. Создать расширение таблицы и добавление перечисления в таблицу.
    3. Добавить поле статуса документа в расширение формы
    4. Создать
    Query для рабочего процесса
    5. Создать категорию рабочего процесса
    6. Создать тип рабочего процесса
    7. Добавить методы
    can submit workflow и updateworkflow в расширение класса таблицы.
    8. Обновить класс
    submitmanager
    9. Обновить класс
    EventHandler
    10. Создать одобрение рабочего процесса
    11. Добавить элемент в тип рабочего процесса
    12. Добавить форму настройки рабочего процесса в модуль управления запасами.


Сейчас мы выполним все шаги детально:

 

1.        Создать базовое перечисление для статуса документа

Убедитесь, что вы создали решение и проект, а также назначили вашу модель для проекта. Теперь добавьте новый элемент и выберите Base Enum. Добавьте базовое перечисление и назовите его CFS_InventoryCountingWorkflow

2.        Создать расширение таблицы и добавление перечисления в таблицу

Мы создаем рабочий процесс для управления запасами, поэтому нам нужно создать расширение для таблицы InventoryJournalTable и перетащить созданное базовое перечисление на него, дабы создать новое поле с типом Enum.

3.        Добавить поле статуса документа в расширение формы

Теперь нам нужно создать расширение формы InventJournalCount и добавить созданное поле на форму, перетащив его из источника данных в элемент управления формы и назначив ему значение LabelId.

4.        Создать запрос

Добавьте новый запрос к проекту и назовите его CFS_InventoryCountingWorkflow, затем добавьте в него таблицу InventJournalTable и установите свойства следующим образом:

Я текстовый блок. Нажмите кнопку редактирования, чтобы изменить этот текст. Разнообразный и богатый опыт постоянный количественный рост и сфера нашей активности требуют от нас анализа позиций.

5.        Создать категорию рабочего процесса

Теперь мы добавим категорию рабочего процесса в проект и назовем ее CFS_InventJournalCounting, установив свойства следующим образом

6.        Создать тип рабочего процесса

После добавления категории рабочего процесса нам пора добавить тип рабочего процесса. Давайте назовем его CFS_InventoryJournalCounting и установим свойства следующим образом.
Это позволит нам создать новые элементы, такие как классы и пункты меню для выполнения всех действий рабочего процесса.

7.        Добавить методы can submit workflow и updateworkflow в расширение класса таблиц.

Чтобы добавить метод в таблицу, нам нужно создать расширение класса таблицы, для этого добавим новый класс и назовем его InventJournalTable_CFSExtension, а также добавим методы updateWorkflow и canSubmitWorkflow. Вы можете использовать следующий код

Extensionof(tableStr(InventJournalTable))]

final class InventJournalTable_Extension

{

public boolean canSubmitToWorkflow(str _workflowType)

{

boolean ret = next cansubmitToWorkflow(_workflowType);

 

ret = this.CFS_InventoryCountingWorkflow == CFS_InventoryCountingWorkflow::Draft;

 

return ret;

}

public static void updateWorkflowStatus(RecId _documentRecId, CFS_InventoryCountingWorkflow _status)

{

ttsbegin;

 

InventJournalTable document;

 

update_recordset document

setting CFS_InventoryCountingWorkflow = _status

where document.RecId == _documentRecId;

 

ttscommit;

}

}

8.        Обновить класс submitmanager

Убедитесь, что у вас аналогичное имя для класса-менеджера, если нет, то переименуйте его следующим образом и добавьте к нему следующий код:

public class CFS_InventoryJournalCountingSubmitManager

{

    private InventJournalTable document;

    private WorkflowVersionTable versionTable;

    private WorkflowComment comment;

    private WorkflowWorkItemTable workItem;

    private SysUserId userId;

    private boolean isSubmission;

    private WorkflowTypeName workflowType;

    public static void main(Args args)

   {

          //  TODO:  Write code to execute once a work item is submitted.

        if (args.record().TableId != tableNum(InventJournalTable))

        {

            throw error(‘Error attempting to submit document’);

        }

        InventJournalTable document = args.record();

        FormRun caller = args.caller() as FormRun;

        boolean isSubmission = args.parmEnum();

        MenuItemName menuItem = args.menuItemName();

        CFS_InventoryJournalCountingSubmitManager manager = CFS_InventoryJournalCountingSubmitManager::construct();

        manager.init(document, isSubmission, caller.getActiveWorkflowConfiguration(), caller.getActiveWorkflowWorkItem());

        if (manager.openSubmitDialog(menuItem))

        {

            manager.performSubmit(menuItem);

        }

        caller.updateWorkflowControls();

   }

    /// <summary>

    /// Construct method

    /// </summary>

    /// <returns>new instance of submission manager</returns>

    public static CFS_InventoryJournalCountingSubmitManager construct()

    {

        return new CFS_InventoryJournalCountingSubmitManager();

    }

    /// <summary>

    /// parameter method for document

    /// </summary>

    /// <param name = “_document”>new document value</param>

    /// <returns>current document</returns>

    public Inventjournaltable parmDocument(Inventjournaltable _document = document)

    {

        document = _document;

        return document;

    }

    /// <summary>

    /// parameter method for version

    /// </summary>

    /// <param name = “_versionTable”>new version table value</param>

    /// <returns>current version table</returns>

    public WorkflowVersionTable parmVersionTable(WorkflowVersionTable _versionTable = versionTable)

    {

        versionTable = _versionTable;

        return versionTable;

    }

    /// <summary>

    /// parameter method for comment

    /// </summary>

    /// <param name = “_comment”>new comment value</param>

    /// <returns>current comment value</returns>

    public WorkflowComment parmComment(WorkflowComment _comment = comment)

    {

        comment = _comment;

        return comment;

    }

    /// <summary>

    /// parameter method for work item

    /// </summary>

    /// <param name = “_workItem”>new work item value</param>

    /// <returns>current work item value</returns>

    public WorkflowWorkItemTable parmWorkItem(WorkflowWorkItemTable _workItem = workItem)

    {

        workItem = _workItem;

        return workItem;

    }

    /// <summary>

    /// parameter method for user

    /// </summary>

    /// <param name = “_userId”>new user value</param>

    /// <returns>current user value</returns>

    public SysUserId parmUserId(SysUserId _userId = userId)

    {

        userId = _userId;

        return userId;

    }

    /// <summary>

    /// parameter method for isSubmission flag

    /// </summary>

    /// <param name = “_isSubmission”>flag value</param>

    /// <returns>current flag value</returns>

    public boolean parmIsSubmission(boolean _isSubmission = isSubmission)

    {

        isSubmission = _isSubmission;

        return isSubmission;

    }

    /// <summary>

    /// parameter method for workflow type

    /// </summary>

    /// <param name = “_workflowType”>new workflow type value</param>

    /// <returns>current workflow type</returns>

    public WorkflowTypeName parmWorkflowType(WorkflowTypeName _workflowType = workflowType)

    {

        workflowType = _workflowType;

        return workflowType;

    }

    /// <summary>

    /// Opens the submit dialog and returns result

    /// </summary>

    /// <returns>true if dialog closed okay</returns>

    protected boolean openSubmitDialog(MenuItemName _menuItemName)

    {

        if (isSubmission)

        {

            return this.openSubmitDialogSubmit();

        }

        else

        {

            return this.openSubmitDialogResubmit(_menuItemName);

        }

    }

    /// <summary>

    /// Open submission dialog

    /// </summary>

    /// <returns>true if dialog closed okay</returns>

    private boolean openSubmitDialogSubmit()

    {

        WorkflowSubmitDialog submitDialog = WorkflowSubmitDialog::construct(this.parmVersionTable());

        submitDialog.run();

        this.parmComment(submitDialog.parmWorkflowComment());

        return submitDialog.parmIsClosedOK();

    }

    /// <summary>

    /// Open resubmit dialog

    /// </summary>

    /// <returns>true if dialog closed okay</returns>

    private boolean openSubmitDialogResubmit(MenuItemName _menuItemName)

    {

        WorkflowWorkItemActionDialog actionDialog = WorkflowWorkItemActionDialog::construct(workItem, WorkflowWorkItemActionType::Resubmit, new MenuFunction(_menuItemName, MenuItemType::Action));

        actionDialog.run();

        this.parmComment(actionDialog.parmWorkflowComment());

        this.parmUserId(actionDialog.parmTargetUser());

        return actionDialog.parmIsClosedOK();

    }

    /// <summary>

    /// initializes manager

    /// </summary>

    /// <param name = “_document”>document</param>

    /// <param name = “_menuItem”>calling menu item</param>

    /// <param name = “_versionTable”>workflow version</param>

    /// <param name = “_workItem”>workflow item</param>

    protected void init(InventJournalTable _document, boolean _isSubmission, WorkflowVersionTable _versionTable, WorkflowWorkitemTable _workItem)

    {

        this.parmDocument(_document);

        this.parmIsSubmission(_isSubmission);

        this.parmVersionTable(_versionTable);

        this.parmWorkItem(_workItem);

        this.parmWorkflowType(this.parmVersionTable().WorkflowTable().TemplateName);

    }

    /// <summary>

    /// perform workflow submission

    /// </summary>

    protected void performSubmit(MenuItemName _menuItemName)

    {

        if (isSubmission)

        {

            this.performSubmitSubmit();

        }

        else

        {

            this.performSubmitResubmit(_menuItemName);

        }

    }

    /// <summary>

    /// perform workflow submit

    /// </summary>

    private void performSubmitSubmit()

    {

        if (this.parmWorkflowType() && document.CFS_InventoryCountingWorkflow == CFS_InventoryCountingWorkflow::Draft)

        {

            Workflow::activateFromWorkflowType(workflowType, document.RecId, comment, NoYes::No);

            InventJournalTable::updateWorkflowStatus(document.RecId, CFS_InventoryCountingWorkflow::Submitted);

        }

    }

/// <summary>

/// perform workflow resubmit

/// </summary>

private void performSubmitResubmit(MenuItemName _menuItemName)

{

if (this.parmWorkItem())

{

WorkflowWorkItemActionManager::dispatchWorkItemAction(workItem, comment, userId, WorkflowWorkItemActionType::Resubmit, _menuItemName);

InventJournalTable::updateWorkflowStatus(document.RecId, CFS_InventoryCountingWorkflow::Submitted);

}

}

}

Поскольку мы добавляем код для повторной отправки только здесь, нам нужно изменить свойство пункта меню resubmit action menu на значение CFS_InventoryJournalCountingSubmitManager, и после этого вы можете удалить данный класс, т.к. мы используем класс-менеджер для повторной отправки документов.

9.        Обновить класс EventHandler

Добавьте следующий код в класс обработчика событий и назовите его CFS_InventoryJournalCountingEventHandler

public class  CFS_InventoryJournalCountingEventHandler implements WorkflowCanceledEventHandler

WorkflowCompletedEventHandler,

WorkflowStartedEventHandler

{

public void started(WorkflowEventArgs _workflowEventArgs)

{

RecId documentRecId = _workflowEventArgs.parmWorkflowContext().parmRecId();

InventJournalTable::updateWorkflowStatus(documentRecId, CFS_InventoryCountingWorkflow::Submitted);

// TODO:  Write code to execute once the workflow is started.

}

public void canceled(WorkflowEventArgs _workflowEventArgs)

{

RecId documentRecId = _workflowEventArgs.parmWorkflowContext().parmRecId();

InventJournalTable::updateWorkflowStatus(documentRecId, CFS_InventoryCountingWorkflow::Rejected);

// TODO:  Write code to execute once the workflow is canceled.

}

public void completed(WorkflowEventArgs _workflowEventArgs)

{

RecId documentRecId = _workflowEventArgs.parmWorkflowContext().parmRecId();

InventJournalTable::updateWorkflowStatus(documentRecId, CFS_InventoryCountingWorkflow::Approved);

// TODO:  Write code to execute once the workflow is completed.

}

}

10.    Создание утверждения рабочего процесса

Добавьте элемент Workflow Approval и назовите его CFS_InventoryJournalCountingApproval. Он также добавит новые элементы и установит свойства следующим образом.

Теперь нам нужно добавить фрагмент кода в обработчики событий утверждения рабочего процесса , а также задать имя как CFS_InventoryJournalCountingApprovalEventHandler

public final class CFS_InventoryJournalCountingApprovalEventHandler implements WorkflowElementCanceledEventHandler,

WorkflowElemChangeRequestedEventHandler,

WorkflowElementCompletedEventHandler,

WorkflowElementReturnedEventHandler,

WorkflowElementStartedEventHandler,

WorkflowElementDeniedEventHandler,

WorkflowWorkItemsCreatedEventHandler

{

public void started(WorkflowElementEventArgs _workflowElementEventArgs)

{

// TODO:  Write code to execute once the workflow is started.

}

public void canceled(WorkflowElementEventArgs _workflowElementEventArgs)

{

RecId documentRecId = _workflowElementEventArgs.parmWorkflowContext().parmRecId();

InventJournalTable::updateWorkflowStatus(documentRecId, CFS_InventoryCountingWorkflow::Rejected);

}

// TODO:  Write code to execute once the workflow is canceled.

 

public void completed(WorkflowElementEventArgs _workflowElementEventArgs)

{

RecId documentRecId = _workflowElementEventArgs.parmWorkflowContext().parmRecId();

InventJournalTable::updateWorkflowStatus(documentRecId, CFS_InventoryCountingWorkflow::Rejected);

}

// TODO:  Write code to execute once the workflow is completed.

 

public void denied(WorkflowElementEventArgs _workflowElementEventArgs)

{

// TODO:  Write code to execute once the workflow is denied.

}

public void changeRequested(WorkflowElementEventArgs _workflowElementEventArgs)

{

// TODO:  Write code to execute once change is requested for the workflow.

}

public void returned(WorkflowElementEventArgs _workflowElementEventArgs)

{

RecId documentRecId = _workflowElementEventArgs.parmWorkflowContext().parmRecId();

InventJournalTable::updateWorkflowStatus(documentRecId, CFS_InventoryCountingWorkflow::Rejected);

// TODO:  Write code to execute once the workflow is returned.

}

public void created(WorkflowWorkItemsEventArgs _workflowWorkItemsEventArgs)

{

// TODO:  Write code to execute once work items are created.

}

}

11.    Добавить элемент в тип рабочего процесса

После создания утверждения нам нужно прикрепить этот элемент к типам рабочего процесса, для этого мы добавим новый элемент к существующим типам и установим свойства следующим образом.

12.    Теперь добавьте форму настройки рабочего процесса в модуль управления запасами.

Поскольку в управлении запасами нет формы рабочего процесса, нам нужно выполнить определенные шаги, которые вы можете найти по этой ссылке, и у вас будет все готово для настройки рабочего процесса одобрения журналов инвентаризации. Эту процедуру также можно использовать для разработки других пользовательских рабочих процессов.

Подписывайтесь на канал @d365neti в Telegram

Подписаться

Добавить комментарий