Multi-select In batch job and execution the record with validation Runbase Batch

/// <summary>

/// Batch job to update production order physical cost amounts rounded.

/// Supports multi-select of Production Orders via SysLookupMultiSelectCtrl.

/// </summary>

class ProdOrderCostRoundingUpdateBatch extends RunBaseBatch implements BatchRetryable

{

    container                   ProdID;

    SysLookupMultiSelectCtrl    prodIDMultiSelect;

    FormBuildStringControl      prodIDCtrl;

    DialogField                 ProdIDField;


    #define.CurrentVersion(1)

    #localMacro.CurrentList

        ProdID

    #endmacro


    /// <summary>

    /// Constructs and returns the dialog form for this batch job.

    /// </summary>

    /// <returns>The constructed dialog.</returns>

    public Object dialog()

    {

        DialogRunbase       dialog;

        DialogGroup         dialogGroup;

        FormBuildControl    formBuildControl;


       


        dialog = super();

        dialog.allowUpdateOnSelectCtrl(true);


        dialogGroup      = dialog.addGroup();

        formBuildControl = dialog.formBuildDesign().control(dialogGroup.formBuildGroup().id());


        prodIDCtrl = formBuildControl.addControl(FormControlType::String, identifierstr(ProdId));

        prodIDCtrl.label("Production order number");



        return dialog;

    }


    /// <summary>

    /// Validates the dialog inputs before execution.

    /// </summary>

    /// <param name="_calledFrom">The object that called the validation.</param>

    /// <returns>True if validation passes; otherwise, false.</returns>

    public boolean validate(Object _calledFrom = null)

    {

        boolean isValid = super(_calledFrom);

        int     i;


        for (i = 1; i <= conLen(ProdID); i++)

        {

            if (conPeek(ProdID, i) == "")

            {

                warning("Please select a Production Order.");

                isValid = false;

            }

        }


        return isValid;

    }


    /// <summary>

    /// Builds the lookup control for multi-select production order selection.

    /// </summary>

    /// <param name="dialog">The dialog form instance.</param>

    public void dialogPostRun(DialogRunbase dialog)

    {

        FormRun                 formRun;

        FormStringControl       fsCtrlProdid;

        Query                   q;

        QueryBuildDataSource    qbds;


        q    = new Query();

        qbds = q.addDataSource(tablenum(ProdTable));


        qbds.addSelectionField(fieldNum(ProdTable, ProdId));

        qbds.addSelectionField(fieldNum(ProdTable, Name));


        super(dialog);


        formRun = dialog.dialogForm().formRun();


        if (formRun)

        {

            fsCtrlProdid       = formRun.design().control(prodIDCtrl.id());

            prodIDMultiSelect  = SysLookupMultiSelectCtrl::constructWithQuery(formRun, fsCtrlProdid, q);


            prodIDMultiSelect.set([this.prodTableRecIdsToIDs(ProdID), ProdID]);

        }

    }


    /// <summary>

    /// Gets values from dialog fields and updates the variables.

    /// </summary>

    /// <returns>True if values successfully retrieved.</returns>

    public boolean getFromDialog()

    {

        boolean ret = super();


        ProdID       = this.prodTableRecIdsToIDs(prodIDMultiSelect.get());

        return ret;

    }


    /// <summary>

    /// Packs values for persistence.

    /// </summary>

    /// <returns>The packed container.</returns>

    public container pack()

    {

       

        return  [#CurrentVersion, #CurrentList];   //conNull();

    }


    /// <summary>

    /// Unpacks values when restoring the class.

    /// </summary>

    /// <param name="packedClass">The packed container.</param>

    /// <returns>True if unpacked successfully; otherwise, false.</returns>

    public boolean unpack(container packedClass)

    {

        Version version = RunBase::getVersion(packedClass);


        switch (version)

        {

            case #CurrentVersion:

                [version, #CurrentList] = packedClass;

                break;

            default:

                return false;

        }


        return true;

    }


    /// <summary>

    /// Constructs and returns a new instance of this batch class.

    /// </summary>

    /// <returns>A new instance of TestBatchJob.</returns>

    public static ProdOrderCostRoundingUpdateBatch construct()

    {

        return new ProdOrderCostRoundingUpdateBatch();

    }


    /// <summary>

    /// Provides a description for the batch job.

    /// </summary>

    /// <returns>The description string.</returns>

    client server static ClassDescription description()

    {

        return "Update Production order physical cost amount rounded";

    }


    /// <summary>

    /// Entry point for the batch job when run from a menu item or code.

    /// </summary>

    /// <param name="_args">The optional Args parameter.</param>

    public static void main(Args _args)

    {

        ProdOrderCostRoundingUpdateBatch batch = ProdOrderCostRoundingUpdateBatch::construct();


        if (batch.prompt())

        {

            batch.run();

        }

    }


    /// <summary>

    /// Converts a container of production table RecIds into their ProdId string values.

    /// </summary>

    /// <param name="_warehouseRecIds">Container of RecIds.</param>

    /// <returns>Container of corresponding ProdIds.</returns>

    public container prodTableRecIdsToIDs(container _warehouseRecIds)

    {

        ProdTable   prodTable;

        RecId       prodIDrecid;

        container   prodTableRecIds;

        int         i;


        prodTableRecIds = conNull();


        for (i = 1; i <= conLen(_warehouseRecIds); i++)

        {

            prodIDrecid = conPeek(_warehouseRecIds, i);


            select firstOnly ProdId from prodTable

                where prodTable.RecId == prodIDrecid;


            prodTableRecIds += [prodTable.ProdId];

        }


        return prodTableRecIds;

    }


    /// <summary>

    /// Indicates if this batch task is retryable in case of  exceptions.

    /// </summary>

    /// <returns>True if retryable; otherwise, false.</returns>

    [Hookable(false)]

    final boolean isRetryable()

    {

        return true;

    }


    /// <summary>

    /// Determines whether or not to allow saving the values entered by the user in the dialog.

    /// </summary>

    /// <returns>

    ///     true if saving the values is allowed; otherwise, false.

    /// </returns>

    public boolean allowSaveLast()

    {

        return false;

    }


    public void run()

    {

        #OCCRetryCount


        try

        {

            ttsbegin;

            this.runGenerationProcess();

            ttscommit;

        }

        catch (Exception::Deadlock)

        {

            retry;

        }

        catch (Exception::UpdateConflict)

        {

            if (appl.ttsLevel() == 0)

            {

                if (xSession::currentRetryCount() >= #RetryNum)

                {

                    throw Exception::UpdateConflictNotRecovered;

                }

                else

                {

                    retry;

                }

            }

            else

            {

                throw Exception::UpdateConflict;

            }

        }

    }


    /// <summary>

    /// Executes the processing logic for each selected production order.

    /// </summary>

    public void runGenerationProcess()

    {

        Query                   query = new Query();

        QueryBuildDataSource    qbdsProdTable;

        int                     i;

        int                     recordCount = 0;


        qbdsProdTable = query.addDataSource(tableNum(ProdTable));


        for (i = conLen(ProdID); i > 0; i--)

        {

            ProdId getProdid = conPeek(ProdID, i);

            qbdsProdTable.addRange(fieldNum(ProdTable, ProdId)).value(queryValue(getProdid));

        }


        QueryRun queryRun = new QueryRun(query);


        while (queryRun.next())

        {

            ProdTable prodTable = queryRun.get(tableNum(ProdTable));


            if (prodTable)

            {

                ttsbegin;


                

                /*

                while select forUpdate inventTrans

                    join inventTransOrigin

                        where inventTrans.inventTransOrigin == inventTransOrigin.RecId

                            && inventTransOrigin.ReferenceId == prodTable.ProdId

                            && (inventTransOrigin.ReferenceCategory == InventTransType::Production

                                || inventTransOrigin.ReferenceCategory == InventTransType::ProdLine)

                {

                    inventTrans.CostAmountPhysical = decRound(inventTrans.CostAmountPhysical, 2);

                    inventTrans.update();

                }


                while select forUpdate prodRouteTrans

                    where prodRouteTrans.TransRefId == prodTable.ProdId

                        && prodRouteTrans.TransRefType == ProdTransRefType::Production

                {

                    prodRouteTrans.Amount = decRound(prodRouteTrans.Amount, 2);

                    prodRouteTrans.update();

                }

                */


                info(strFmt("Production order %1 physical cost amount has been rounded.", prodTable.ProdId));


                recordCount++;


                ttscommit;

            }

        }

        info(strFmt("Total number of record process  %1 ", recordCount));

    }


}

Comments

Popular posts from this blog

Customization on Sales invoice Report in D365 F&O

46) D365 FO: SHAREPOINT FILE UPLOAD USING X++

75) COC - Create a coc of the table modified method