Custom Workflow Development in Dynamics 365 Finance and Operations

Bayram ÇETİNBayram ÇETİN
5 min read

Microsoft Dynamics 365 Finance and Operations, işletmelerin süreçlerini daha verimli ve esnek bir şekilde yönetmelerine olanak tanıyan güçlü bir ERP çözümüdür. Standart iş akışları birçok işletmenin ihtiyaçlarını karşılayacak şekilde tasarlanmış olsa da, her şirketin kendine özgü süreçleri ve gereksinimleri olabilir. Bu noktada, Dynamics 365'te özel iş akışları geliştirmenin önemi devreye girer. Bu blog yazısında, Dynamics 365 Finance and Operations üzerinde özel iş akışları geliştirmenin adımlarını ve bu süreçte dikkat edilmesi gereken temel noktaları ayrıntılı bir şekilde inceleyeceğiz.


Öncelikle aşağıdaki gibi yeni bir enum açıyoruz. Kullandığım label'ları parantez içerisinde verdim.

  1. NotSubmitted (@SYS109900)

  2. Submitted (@SYS109901)

  3. Approved (@SYS109904)

  4. Rejected (@SYS118125)

  5. InReview (@Leave:InReview)

  6. Cancelled (@DataJobService:Canceled)

  7. ChangeRequest (@SYS109906)

İş akışının çalışmasını istediğimiz ilgili tabloya "WorkflowStatus" alanını ekliyoruz. Ayrıca "WorkflowGroup" adında bir field group oluşturuyoruz.

İlgili tabloya "CanSubmitToWorkflow" ve "UpdateWorkflowStatus" metotlarını ekliyoruz.

    public boolean canSubmitToWorkflow(str _workflowType = '')
    {
        boolean ret;
        ret = super(_workflowType);

        if(this.WorkflowStatus != ETGBudgetWorkflowStatus::NotSubmitted)
        {
            ret = false;
        }
        else
        {
            ret = true;
        }

        return ret;
    }

    public static void updateWorkflowStatus(RefRecId recId, ETGBudgetWorkflowStatus status)
    {
        ETGBudgetEntryTable etgBudgetEntryTable;

        ttsbegin;

        select firstonly forupdate etgBudgetEntryTable
            where etgBudgetEntryTable.RecId == recId;

        etgBudgetEntryTable.WorkflowStatus = status;
        etgBudgetEntryTable.update();

        ttscommit;
    }

“ETGBudgetEntryTableWFQuery” adında yeni bir Query oluşturun. İlgili tabloyu Query’ye ekleyin. Dynamic Fields özelliğini Yes yapın.

“ETGBudgetEntryTableWFCategory” isminde bir Workflow Category nesnesi açıyoruz. Module özelliğini ayarlamayı unutmayın.

Şimdi sıra, Workflow type ile birlikte ilgili nesneleri otomatik olarak oluşturmaya geldi.

“ETGBudgetEntryTableWFType” isminde bir Workflow type oluşturulması için Add diyoruz. Ardından stepleri takip etmemiz gerekiyor. İlgili Category, Query ve Display menu item nesnelerimizi listeden seçiyoruz.

Son adımda, otomatik olarak oluşacak nesneleri görüyoruz. Onay verdiğimizde, bu nesneler oluşturulacak ve projemize eklenecek.

Otomatik olarak oluşan nesnelerin Label ve Help text bilgilerini, aşağıda listelenen nesneler için sağlıyoruz.

  • ETGBudgetEntryTableWFTypeSubmitMenuItem (@CLITraceParser:TraceParser_SubmitButton)

  • ETGBudgetEntryTableWFTypeCancelMenuItem (@AssetLeasing:Cancel)


Aşağıdaki kodu Submit manager class'ına ekleyin.

/// <summary>
/// The ETGBudgetEntryTableWFTypeSubmitManager menu item action event handler.
/// </summary>
public class ETGBudgetEntryTableWFTypeSubmitManager 
{
    public static void main(Args args)
    {
        //  TODO:  Write code to execute once a work item is submitted.
        ETGBudgetEntryTable     customWorkflowTable;

        WorkflowComment         note;
        WorkflowSubmitDialog    workflowSubmitDialog;
        WorkflowCorrelationId   workflowCorrelationId;
        WorkflowTypeName        workflowTypeName = workFlowTypeStr(ETGBudgetEntryTableWFType);

        //Opens the submit to workflow dialog.
        workflowSubmitDialog =    WorkflowSubmitDialog::construct(args.caller().getActiveWorkflowConfiguration());
        workflowSubmitDialog.run();

        if (workflowSubmitDialog.parmIsClosedOK())
        {
            customWorkflowTable = args.record();

            // Get comments from the submit to workflow dialog.
            note = workflowSubmitDialog.parmWorkflowComment();

            try
            {
                ttsbegin;
                workflowCorrelationId = Workflow::activateFromWorkflowType(workflowTypeName, customWorkflowTable.RecId, note, NoYes::No);
                customWorkflowTable.WorkflowStatus = ETGBudgetWorkflowStatus::Submitted;
                customWorkflowTable.update();
                ttscommit;

                // Send an Infolog message.
                info("İş akışına gönderildi.");

            }
            catch (Exception::Error)
            {
                error("İş akışında hata");
            }

        }

        args.caller().updateWorkFlowControls();
    }

}

Aşağıdaki kodu event handler class'ına ekliyoruz.

/// <summary>
/// The ETGBudgetEntryTableWFTypeEventHandler workflow event handler.
/// </summary>
public class  ETGBudgetEntryTableWFTypeEventHandler implements WorkflowCanceledEventHandler,  
    WorkflowCompletedEventHandler,
    WorkflowStartedEventHandler
{
    public void started(WorkflowEventArgs _workflowEventArgs)
    {
        // TODO:  Write code to execute once the workflow is started.
        ETGBudgetEntryTable::updateWorkflowStatus(_workflowEventArgs.parmWorkflowContext().parmRecId(),ETGBudgetWorkflowStatus::Submitted);
    }

    public void canceled(WorkflowEventArgs _workflowEventArgs)
    {
        // TODO:  Write code to execute once the workflow is canceled.
        ETGBudgetEntryTable::updateWorkflowStatus(_workflowEventArgs.parmWorkflowContext().parmRecId(),ETGBudgetWorkflowStatus::Cancelled);
    }

    public void completed(WorkflowEventArgs _workflowEventArgs)
    {
        // TODO:  Write code to execute once the workflow is completed.
        ETGBudgetEntryTable::updateWorkflowStatus(_workflowEventArgs.parmWorkflowContext().parmRecId(), ETGBudgetWorkflowStatus::Approved);
    }

}

Formumuzda iş akışını etkinleştirmek için "Workflow enabled" özelliğini "Yes" olarak ayarlıyoruz. Ardından, "Workflow Data Source" ve "Workflow Type" özelliklerine ilgili nesnelerimizi atıyoruz.

Buraya kadar tüm adımları tamamladıktan sonra projemizi derleyip senkronize ediyoruz.


Şimdi sıra Workflow approval nesnesini eklemeye geldi. Yine yukarıda olduğu gibi yönergeleri takip edersek, nesneler otomatik olarak oluşacaktır.

Add dedikten sonra açılan pencereden Workflow document, Field group ve display menu item özelliklerini seçiyoruz.

Son adımda ise otomatik olarak oluşacak nesneleri görüyoruz. Onay verdiğimizde, bu nesneler oluşturulacak ve projemize eklenecek.

Aşağıdaki kodu workflow approval event handler class'ına ekleyelim.

/// <summary>
/// The ETGBudgetEntryTableWFApprovalEventHandler workflow outcome event handler.
/// </summary>
public final class ETGBudgetEntryTableWFApprovalEventHandler implements WorkflowElementCanceledEventHandler,
    WorkflowElemChangeRequestedEventHandler,
    WorkflowElementCompletedEventHandler,
    WorkflowElementReturnedEventHandler,
    WorkflowElementStartedEventHandler,
    WorkflowElementDeniedEventHandler,
    WorkflowWorkItemsCreatedEventHandler
{
    public void started(WorkflowElementEventArgs _workflowElementEventArgs)
    {
        // TODO:  Write code to execute once the workflow is started.
        ETGBudgetEntryTable::updateWorkflowStatus(_workflowElementEventArgs.parmWorkflowContext().parmRecId(), ETGBudgetWorkflowStatus::InReview);
    }

    public void canceled(WorkflowElementEventArgs _workflowElementEventArgs)
    {
        // TODO:  Write code to execute once the workflow is canceled.
        ETGBudgetEntryTable::updateWorkflowStatus(_workflowElementEventArgs.parmWorkflowContext().parmRecId(), ETGBudgetWorkflowStatus::Cancelled);
    }

    public void completed(WorkflowElementEventArgs _workflowElementEventArgs)
    {
        // TODO:  Write code to execute once the workflow is completed.
        ETGBudgetEntryTable::updateWorkflowStatus(_workflowElementEventArgs.parmWorkflowContext().parmRecId(), ETGBudgetWorkflowStatus::Approved);
    }

    public void denied(WorkflowElementEventArgs _workflowElementEventArgs)
    {
        // TODO:  Write code to execute once the workflow is denied.
        ETGBudgetEntryTable::updateWorkflowStatus(_workflowElementEventArgs.parmWorkflowContext().parmRecId(), ETGBudgetWorkflowStatus::Denied);
    }

    public void changeRequested(WorkflowElementEventArgs _workflowElementEventArgs)
    {
        // TODO:  Write code to execute once change is requested for the workflow.
        ETGBudgetEntryTable::updateWorkflowStatus(_workflowElementEventArgs.parmWorkflowContext().parmRecId(), ETGBudgetWorkflowStatus::ChangeRequest);
    }

    public void returned(WorkflowElementEventArgs _workflowElementEventArgs)
    {
        // TODO:  Write code to execute once the workflow is returned.
        ETGBudgetEntryTable::updateWorkflowStatus(_workflowElementEventArgs.parmWorkflowContext().parmRecId(), ETGBudgetWorkflowStatus::Denied);
    }

    public void created(WorkflowWorkItemsEventArgs _workflowWorkItemsEventArgs)
    {
        // TODO:  Write code to execute once work items are created.
        // Burada WorkflowStatus ile ilgili bir işlem yapmayın.
    }

}

Aşağıdaki nesnelerin Label ve Help text bilgilerini veriyoruz. Verdiğim label'ları parantez içinde paylaştım.

  • ETGBudgetEntryTableWFApprovalApprove (@ENG407)

  • ETGBudgetEntryTableWFApprovalDelegateMenuItem (@SYS105444)

  • ETGBudgetEntryTableWFApprovalReject (@AppTroubleshooting:CustomScriptReject)

  • ETGBudgetEntryTableWFApprovalRequestChange (@SYS105446)

  • ETGBudgetEntryTableWFApprovalResubmitMenuItem (Yeniden gönder)

Label'ları verdikten sonra sıra, Workflow Type nesnemize referans eklemeye geldi. Workflow Approval nesnemizi referans olarak veriyoruz.

Buraya gelmişken Workflow Type nesnemizin Label ve Help text bilgilerini de verelim.

Workflow approval nesnemizin Label ve Help text bilgilerini de verelim.

Label bilgilerini verdikten sonra, projemizi tekrardan derleyip senkronize ediyoruz.


Şimdi sıra arayüzde iş akışını yapılandırmaya geldi. İlgili modülünüzün Ayarlar yada Kurulum altında ki “İş akışları” ekranından, Yeni dedikten sonra bir diyalog açılır buradan kendi iş akışımıza tıklıyarak, kurulumları yapabiliriz.

İş akışları ekranından Yeni dedikten sonra bir diyalog açılır buradan kendi iş akışımıza tıklıyoruz.

Aşağıdaki gibi iş akışımızı yapılandırdıktan sonra iş akışlarının formumuz üzerinde aktif olduğunu görebiliriz. Bu yapılandırmayı iş analistleri yaptığı için detaylı olarak yazmıyorum.

Sonuç olarak formumuzda iş akışı aktif hale geldi.

Özel iş akışları geliştirerek Dynamics 365 Finance and Operations’ı işletmenizin ihtiyaçlarına göre uyarlamak, süreçlerinizi daha verimli hale getirir ve operasyonel esnekliği artırır. Bu adımlar sayesinde, iş akışlarınızı optimize edebilir ve Dynamics 365'in sunduğu güçlü araçlardan tam anlamıyla faydalanabilirsiniz.

0
Subscribe to my newsletter

Read articles from Bayram ÇETİN directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Bayram ÇETİN
Bayram ÇETİN

Senior Dynamics 365 Developer