SysOperationFramework with use of Query

 The SysOperation framework is very good and effective, but unforutnatly a bit complicated to get in to and do as you want. 

I had one case in which a simple table should be updated, the job was to be able to set in batch. Also it had to use a query so that the user could easily set up the ranges as he pleased.

Note that I will use the same query for updating the table which I mentioned. So the same query is used all the way through ending in using Quer::updateRecordset

For this you need:

  1. Data contract class
  2. Controller class
  3. Service class
  4. Simple query oject
  5. Action Menu item
  6. Main menu where to make the menu item available.




1. Data contract class

Note the simple query highlighted in bright yellow

[DataContractAttribute

    , SysOperationGroupAttribute('Parameters',  "Parameters", '1')]

internal final class CustAutoCancelUpdateDataContract

{

    str             packedQuery;

    MCRAutoCancel   autoCancel;


    public Query getQuery()

    {

        return new Query(SysOperationHelper::base64Decode(packedQuery));

    }


    [DataMemberAttribute,

         AifQueryTypeAttribute('_packedQuery', querystr(CustAutoCancelDeposit))]

    public str parmItemQuery(str _packedQuery = packedQuery)

    {

        packedQuery = _packedQuery;

        return packedQuery;

    }


    public void setQuery(Query _query)

    {

        packedQuery = SysOperationHelper::base64Encode(_query.pack());

    }


    [   DataMemberAttribute('Parameters'),

        SysOperationControlVisibilityAttribute(true),

        SysOperationLabelAttribute(literalStr("@MCR22943")),

        SysOperationGroupMemberAttribute('Parameters'),

        SysOperationDisplayOrderAttribute('1')

    ]


    public MCRAutoCancel parmMCRAutoCancel(MCRAutoCancel _autoCancel = autoCancel)

    {

        autoCancel = _autoCancel;


        return autoCancel;

    }


    public boolean validate()

    {

        boolean isValid = true;

        if(true)

        {

            //if you have any validations for the dialog, put them here

        }

        return isValid;

    }

}



2. Controller class


[SysOperationJournaledParametersAttribute(true)]//if you want it to be able to run in batch journal

internal final class CustAutoCancelUpdateController extends SysOperationServiceController implements BatchRetryable

{


    public static void main(Args _args)

    {

        CustAutoCancelUpdateController controller = CustAutoCancelUpdateController::construct();

        controller.parmArgs(_args);

        controller.startOperation();        

    }


    public ClassDescription defaultCaption()

    {

        return "@XXXX:CustSetAutoCancel";

    }


    [Hookable(false)]

    final boolean isRetryable()

    {

        return true;

    }


    public static CustAutoCancelUpdateController construct(SysOperationExecutionMode _executionMode = SysOperationExecutionMode::Synchronous)

    {

        CustAutoCancelUpdateController custAutoCancelUpdateController = new CustAutoCancelUpdateController();


        custAutoCancelUpdateController.parmExecutionMode(_executionMode);

        

        return custAutoCancelUpdateController;

    }


    public boolean canGoBatchJournal()

    {

        return true;

    }


    protected void new()

    {

        super(classStr(CustAutoCancelUpdateService), methodStr(CustAutoCancelUpdateService, setCustAutoCancel), SysOperationExecutionMode::Synchronous);

    }

}

Start write the next paragraph here


3. Service class

This takes the query provided from the dialog, here you can manipulate the query if needed. There is a discrepancy in logic regarding the datatypes, notice that I am updating a base enum field, those are stored as integers in the database, but we have to set up the field map to use String. If you try any other data type than String it will not work.

internal final class CustAutoCancelUpdateService

{

    public void setCustAutoCancel(CustAutoCancelUpdateDataContract _contract)

    {

        QueryRun    qr = new QueryRun(_contract.getQuery());

        Query       q = qr.query();


        Map fieldMapSet = new Map(Types::String, Types::String);

                

        fieldMapSet.insert(fieldStr(MCRCustTable, AutoCancel), _contract.parmMCRAutoCancel() == NoYes::Yes ? '1' : '0');


        ttsbegin;

        //only for main datasource can we use this

        Query::update_recordset(fieldMapSet, q, true,true, false);

        ttscommit;

    }

}



4. Simple Query object

I just made a simple query consiting of one table. Use in your data contract class.

5. Action menu item


Here we call the controller class and provide parameter to execute the service class method setCustAutoCancel.

To specify which code is to be executed fill these parmaeters:

- Object: [Name of controller class]
- Object type: Class
- Parameters: [Name of controller class].[Name of method to execute]





6. Menu, add action menu

Add your action menu item to a menu to run it, you can also run it by manipulating your URL

[D365FO URL]/?mi=Action:[Action menu item name]


Comments

Popular posts from this blog

Call a simple Logic app from X++

Retail Attributes on sales lines