Tuesday, April 13, 2021

Sysoperations framework sample

UIBuilder class

/// <summary>
/// The <c>TransferOrderCreateProposalUIBuilder</c> The data contract for Transfer order creation.
/// </summary>
class TransferOrderCreateProposalUIBuilder extends SysOperationAutomaticUIBuilder
{
    DialogField                                 toDate;
    DialogField                                 timeFence;
    DialogField                                 fromSite;
    DialogField		                            fromWarehouse,toWarehouses;
    DialogField                                 proposalModel;
    DialogField                                 recalculateQuantities;
    DialogField                                 replaceCurrentProposals;
    

    SysLookupMultiSelectCtrl                    ctrlSources;
    
    /// <summary>
    /// 
    /// </summary>
    public void postBuild()
    {
        TransferOrderCreateProposalContract contract	= this.dataContractObject() as TransferOrderCreateProposalContract;

        toDate                       = this.bindInfo().getDialogField(contract, methodStr(TransferOrderCreateProposalContract, parmToDate));
        timeFence                    = this.bindInfo().getDialogField(contract, methodStr(TransferOrderCreateProposalContract, parmTimeFence));
        fromSite                     = this.bindInfo().getDialogField(contract, methodStr(TransferOrderCreateProposalContract, parmInventSiteId));
        fromWarehouse                = this.bindInfo().getDialogField(contract, methodStr(TransferOrderCreateProposalContract, parmInventLocationIdFrom));
        toWarehouses	             = this.bindInfo().getDialogField(contract, methodStr(TransferOrderCreateProposalContract, parmInventLocationIdTo));
        proposalModel	             = this.bindInfo().getDialogField(contract, methodStr(TransferOrderCreateProposalContract, parmProposalModel));
        recalculateQuantities        = this.bindInfo().getDialogField(contract, methodStr(TransferOrderCreateProposalContract, parmRecalculateQuantities));
        replaceCurrentProposals      = this.bindInfo().getDialogField(contract, methodStr(TransferOrderCreateProposalContract, parmReplaceCurrentProposal));
        
        replaceCurrentProposals.allowEdit(false);
        recalculateQuantities.visible(false);
        toWarehouses.lookupButton(FormLookupButton::Always);

        switch (this.controller().parmArgs().menuItemName())
        {
            case menuItemActionStr(TransferOrderCreateProposal):
                replaceCurrentProposals.value(true);
                recalculateQuantities.value(false);
                toDate.value(DateTimeUtil::getSystemDate(DateTimeUtil::getUserPreferredTimeZone()));
                break;
            case menuItemActionStr(TransferOrderEditProposal):
                TransferOrderProposal    transferOrderProposal = this.controller().parmArgs().record();

                fromSite.allowEdit(false);
                fromWarehouse.allowEdit(false);
                proposalModel.allowEdit(false);

                recalculateQuantities.value(false);
                replaceCurrentProposals.value(false);
                toDate.value(transferOrderProposal.ToDate);
                fromSite.value(transferOrderProposal.InventSiteIdFrom);
                timeFence.value(transferOrderProposal.timeFence);
                proposalModel.value(transferOrderProposal.ProposalModel);
                fromWarehouse.value(transferOrderProposal.InventLocationIdFrom);
                break;

            case menuItemActionStr(TransferOrderRecalculateQty):
                toDate.visible(false);
                fromSite.visible(false);
                fromWarehouse.visible(false);
                timeFence.visible(false);
                toWarehouses.visible(false);
                replaceCurrentProposals.visible(false);

                recalculateQuantities.value(true);
                replaceCurrentProposals.value(false);
                break;

            default:
                break;
        }
    }

    /// <summary>
    /// 
    /// </summary>
    public void postRun()
    {
        if ( this.controller().parmArgs().menuItemName() == menuItemActionStr(TransferOrderCreateProposal) )
        {
            this.WarehouseLookup(false);
        }
        else if ( this.controller().parmArgs().menuItemName() == menuItemActionStr(TransferOrderEditProposal) )
        {
            this.WarehouseLookup(true);
        }
    }

    /// <summary>
    /// Multi select lookup for warehouse
    /// </summary>
    /// <param name = "_preselectValues">true for preselect lookup values</param>
    public void WarehouseLookup(boolean _preselectValues)
    {
        Query		            query		    = new Query();
        QueryBuildDataSource    qbdsWarehouses  = query.addDataSource(tablenum(InventLocation));

        container selectedFields = [tableNum(InventLocation), fieldNum(InventLocation, InventLocationId)];

        qbdsWarehouses.fields().addField(fieldNum(InventLocation, InventLocationId));
        qbdsWarehouses.fields().addField(fieldNum(InventLocation, Name));

        ctrlSources = SysLookupMultiSelectCtrl::constructWithQuery(this.dialog().formRun(),
                                                                   toWarehouses.control(),
                                                                   query,
                                                                   true,
                                                                   selectedFields);
        if (_preselectValues)
        {
            TransferOrderProposal    transferOrderProposal, transferOrderProposalLoc = this.controller().parmArgs().record();
            InventLocation              inventLocation;

            container selectedRecIds;
            container selectedValues;

            while select InventLocationIdTo from transferOrderProposal group by InventLocationIdTo
                where transferOrderProposal.ProposalModel == transferOrderProposalLoc.ProposalModel
            {
                inventLocation = InventLocation::find(transferOrderProposal.InventLocationIdTo);

                selectedRecIds += inventLocation.RecId;
                selectedValues += inventLocation.InventLocationId;
            }

            ctrlSources.set([selectedRecIds, selectedValues]);
        }
    }

}

Service class

/// <summary>
/// The <c>TransferOrderCreationProposalService</c> is used to create Transfer order proposals
/// for planned orders.
/// </summary>
class TransferOrderCreateProposalService
{
    List                                    toWareHouse;
    Query                                   query;
    counter                                 timeFence, lineNum;
    boolean                                 replaceCurrentProposal;
    String20                                proposalModel;
    TransDate                               fromDate,toDate;
    InventTable                             inventTable;
    InventSiteId                            fromInventSite;
    InventLocationId                        fromWarehouse;
    Enumerator                              enumerator;
    TransferOrderCreateProposalContract  contract;

    /// <summary>
    /// Entry point for creating Transfer order propsal lines based on proposal model
    /// </summary>
    /// <param name = "_contract">TransferOrderCreateProposalContract passed from dialog</param>
    public void createTransferOrderProposal(TransferOrderCreateProposalContract _contract)
    {
        contract = _contract;
       
        this.initializeQuery();
        this.initializeParameters();
        
        ttsbegin;

        this.deleteTranferProposalsLines(proposalModel, replaceCurrentProposal);
        this.createTransferOrderProposalLines();

        ttscommit;
    }

    /// <summary>
    /// Method is used to delete the Transfer order propsal lines based on proposal model
    /// </summary>
    /// <param name = "_proposalModel">from dialog</param>
    /// <param name = "_replaceCurrentProposal">true if creating new transfer order proposal</param>
    public void deleteTranferProposalsLines(ProposalModelId _proposalModel, boolean _replaceCurrentProposal)
    {
        if (_replaceCurrentProposal)
        {
            TransferOrderProposal    transferOrderProposal;

            delete_from transferOrderProposal
                where transferOrderProposal.ProposalModel == _proposalModel;
        }
    }

    /// <summary>
    /// intilalize parameters
    /// </summary>
    public void initializeParameters()
    {
        toDate                  = contract.parmToDate();
        timeFence               = contract.parmTimeFence();

        fromDate                = contract.parmToDate() - timeFence;

        toWareHouse             = contract.parmInventLocationIdTo();
        fromWarehouse           = contract.parmInventLocationIdFrom();
        proposalModel           = contract.parmProposalModel();
        fromInventSite          = contract.parmInventSiteId();
        replaceCurrentProposal  = contract.parmReplaceCurrentProposal();
    }

    /// <summary>
    /// initialize query object
    /// </summary>
    public void initializeQuery()
    {
        query = contract.parmQuery();
    }

    /// <summary>
    /// Method is used to create the Transfer order propsal lines based on proposal model
    /// </summary>
    public void createTransferOrderProposalLines()
    {
        Real                        workingdays;
        InventLocation              inventLocation;
        InventQtyTotal              inventQty;
        RecordInsertList            transferOrderProposalInsertList = null;
        TransferOrderProposal    transferOrderProposal;

        QueryRun queryRun = new QueryRun(query);

        while (queryRun.next())
        {
            transferOrderProposalInsertList = new RecordInsertList(tablenum(TransferOrderProposal));

            inventTable =   queryRun.get(tablenum(InventTable));
            enumerator  =   toWareHouse.getEnumerator();

            try
            {         
                ttsbegin;

                while (enumerator.moveNext())
                {
                    if (!replaceCurrentProposal)
                    {
                        if (TransferOrderProposal::exist(inventTable.ItemId, enumerator.current(), proposalModel))
                        {
                            lineNum++;
                            continue;
                        }
                    }

                    transferOrderProposal.clear();

                    lineNum++;

                    transferOrderProposal.LineNum                   = lineNum;
                    transferOrderProposal.ItemId                    = inventTable.ItemId;
                    transferOrderProposal.ItemName                  = inventTable.itemName();
                    transferOrderProposal.ToDate                    = toDate;
                    transferOrderProposal.TimeFence                 = timeFence;
                    transferOrderProposal.InventSiteIdFrom          = fromInventSite;

                    inventLocation = InventLocation::find(fromWarehouse);

                    transferOrderProposal.InventLocationIdFrom      = inventLocation.InventLocationId;
                    transferOrderProposal.InventLocationIdFromName  = inventLocation.Name;
                    transferOrderProposal.InventSiteIdTo            = fromInventSite;

                    inventLocation = InventLocation::find(enumerator.current());

                    transferOrderProposal.InventLocationIdTo        = inventLocation.InventLocationId;
                    transferOrderProposal.InventLocationIdToName    = inventLocation.Name;
                    transferOrderProposal.ProposalModel             = proposalModel;
                    transferOrderProposal.CoverageGroup             = inventTable.ReqGroupId;
                    
                    transferOrderProposal.RefillAvailablePhysical   = this.getRefillItemAvailPhysicalBySiteAndWarehouse(transferOrderProposal.ItemId,
                                                                                                                        transferOrderProposal.InventSiteIdFrom,
                                                                                                                        transferOrderProposal.InventLocationIdFrom);
                    inventQty = 0;
                    inventQty = this.getItemTotalSalesBySiteAndWarehouse(transferOrderProposal.ItemId,
                                                                         transferOrderProposal.InventSiteIdFrom,
                                                                         transferOrderProposal.InventLocationIdFrom,
                                                                         fromDate,
                                                                         toDate);
                    workingdays = 0;
                    workingdays = this.getNumOfWorkingdays(transferOrderProposal.InventLocationIdFrom, fromDate, toDate);

                    transferOrderProposal.RefillSalesPerDay = workingdays ? inventQty / workingdays : 0;

                    transferOrderProposal.RefillCoverageDays = transferOrderProposal.RefillSalesPerDay ? transferOrderProposal.RefillAvailablePhysical / transferOrderProposal.RefillSalesPerDay : 0;

                    transferOrderProposal.DCAvailablePhysical   = this.getDCItemAvailPhysicalBySiteAndWarehouse(transferOrderProposal.ItemId,
                                                                                                                transferOrderProposal.InventSiteIdTo,
                                                                                                                transferOrderProposal.InventLocationIdTo);
                    inventQty = 0;
                    inventQty = this.getItemTotalSalesBySiteAndWarehouse(transferOrderProposal.ItemId,
                                                                         transferOrderProposal.InventSiteIdTo,
                                                                         transferOrderProposal.InventLocationIdTo,
                                                                         fromDate,
                                                                         toDate);
                    workingdays = 0;
                    workingdays = this.getNumOfWorkingdays(transferOrderProposal.InventLocationIdTo,fromDate, toDate);

                    transferOrderProposal.DCSalesPerDay = workingdays ? inventQty / workingdays : 0;

                    transferOrderProposal.DCCoverageDays = transferOrderProposal.DCSalesPerDay ? transferOrderProposal.DCAvailablePhysical / transferOrderProposal.DCSalesPerDay : 0;

                    transferOrderProposalInsertList.add(transferOrderProposal);
                }

                transferOrderProposalInsertList.insertDatabase();

                ttscommit;
                
            }
            catch(Exception::Error)
            {
                throw error( "@Planning:TransferOrderPropsalCreationError");
            }
            catch(Exception::Deadlock )
            {
                if(xSession::currentRetryCount() >= Planning_Constants::MaxOCCRetryCount)
                {
                    throw Exception::Deadlock;
                }
                else
                {
                    retry;
                }
            }
            catch(Exception::UpdateConflict)
            {
                if (appl.ttsLevel() == 0)
                {
                    if (xSession::currentRetryCount() >= Planning_Constants::MaxOCCRetryCount)
                    {
                        throw Exception::UpdateConflictNotRecovered;
                    }
                    else
                    {
                        retry;
                    }
                }
                else
                {
                    throw Exception::UpdateConflict;
                }
            }

            info(strFmt("@Planning:TransferOrderProposalCreationSuccess", lineNum, proposalModel));
        }
    }

    /// <summary>
    /// Calculate total sales between daterange for each item based on site and warehouse
    /// </summary>
    /// <param name = "_itemId"></param>
    /// <param name = "_inevntSiteId"></param>
    /// <param name = "_inventLocationId"></param>
    /// <returns></returns>
    public InventQtyTotal getItemTotalSalesBySiteAndWarehouse(ItemId _itemId, 
                                                              InventSiteId _inventSiteId,
                                                              InventLocationId _inventLocationId,
                                                              FromDate _fromDate,
                                                              ToDate _toDate)
    {
        InventDim           inventDim;
        InventTrans         inventTrans;
        InventTransOrigin   inventTransOrigin;


        select sum(Qty) from inventTrans
                where inventTrans.ItemId == _itemId
                    && inventTrans.DatePhysical >= _fromDate
                    && inventTrans.DatePhysical <= _toDate
                    exists join inventTransOrigin
                    where inventTransOrigin.RecId == inventTrans.InventTransOrigin
                        && inventTransOrigin.ReferenceCategory == InventTransType::Sales
                        exists join inventDim
                        where inventDim.inventDimId == inventTrans.inventDimId
                            && inventDim.InventSiteId == _inventSiteId
                            && inventDim.InventLocationId == _inventLocationId;

        return abs(inventTrans.Qty);
    }

    /// <summary>
    /// calculates number of working days based on warehouse or Legal entity base calender
    /// </summary>
    /// <param name = "_inventLocationId"></param>
    /// <returns></returns>
    public Real getNumOfWorkingdays(InventLocationId _inventLocationId, FromDate _fromDate, ToDate _toDate)
    {
        Real                workingdays;
        CalendarId          calenderId;
        WorkCalendarDate    WorkCalendarDate;

        if (InventLocation::find(_inventLocationId).ReqCalendarId)
        {
            calenderId = InventLocation::find(_inventLocationId).ReqCalendarId;
        }
        else
        {
            calenderId = CompanyInfo::find().ShippingCalendarId;
        }

        select count(RecId) from WorkCalendarDate
            where WorkCalendarDate.CalendarId       == calenderId
                && (WorkCalendarDate.TransDate      >= _fromDate
                && WorkCalendarDate.TransDate       <= _toDate)
                && WorkCalendarDate.WorkTimeControl == WorkTimeControl::Open;

        workingdays = any2Real(WorkCalendarDate.RecId);

        if (!calenderId)
        {
            Real noOfDays    = _toDate - _fromDate;

            //Formula for calculating working days if No base calender is present
            workingdays = (abs(noOfDays) / Planning_Constants::NumOfDaysInAWeek ) * Planning_Constants::MinWorkingDaysInAWeek;
        }
        
        return abs(workingdays);
    }

    /// <summary>
    /// Calculate avaialable physical inventory for each item based on site and warehouse
    /// </summary>
    /// <param name = "_itemId"></param>
    /// <param name = "_inevntSiteId"></param>
    /// <param name = "_inventLocationId"></param>
    /// <returns>Refill warehouse avail physical</returns>
    public InventQtyAvailPhysical getRefillItemAvailPhysicalBySiteAndWarehouse(ItemId _itemId, InventSiteId _inventSiteId, InventLocationId _inventLocationId)
    {
        InventDim       inventDim;
        InventDimParm   inventDimParm;
      
        inventDim = this.initInventDim(_inventSiteId, _inventLocationId);

        inventDimParm.initFromInventDim(inventDim);

        return abs(InventOnhand::newParameters(_itemId, inventDim, inventDimParm).availPhysical());
    }

    /// <summary>
    /// Calculate avaialable physical inventory for each item based on site and warehouse
    /// </summary>
    /// <param name = "_itemId"></param>
    /// <param name = "_inevntSiteId"></param>
    /// <param name = "_inventLocationId"></param>
    /// <returns>DC warehouse avail physical</returns>
    public InventQtyAvailPhysical getDCItemAvailPhysicalBySiteAndWarehouse(ItemId _itemId, InventSiteId _inventSiteId, InventLocationId _inventLocationId)
    {
        InventDim           inventDim;
        InventTrans         inventTrans;
        InventDimParm       inventDimParm;
        inventTransOrigin   InventTransOrigin;
        InventQty           totalAvailPhysical;
      
        inventDim = this.initInventDim(_inventSiteId, _inventLocationId);

        inventDimParm.initFromInventDim(inventDim);

        totalAvailPhysical = abs(InventOnhand::newParameters(_itemId, inventDim, inventDimParm).availPhysical());

        inventDim.clear();

        select sum(Qty) from inventTrans
                where inventTrans.ItemId == _itemId
                    && inventTrans.DatePhysical == dateNull()
                    && inventTrans.StatusIssue == StatusIssue::ReservPhysical
                    exists join inventTransOrigin
                    where inventTransOrigin.RecId == inventTrans.InventTransOrigin
                        && (inventTransOrigin.ReferenceCategory == InventTransType::TransferOrderShip
                            || inventTransOrigin.ReferenceCategory == InventTransType::TransferOrderReceive)
                            exists join inventDim
                            where inventDim.inventDimId   == inventTrans.inventDimId
                            && inventDim.InventSiteId     == _inventSiteId
                            && inventDim.InventLocationId == _inventLocationId;

        return totalAvailPhysical + abs(inventTrans.Qty);
    }

    /// <summary>
    /// Initilalize InevntDim by site and warehouse
    /// </summary>
    /// <param name = "_inevntSiteId">SiteId from proposal line</param>
    /// <param name = "_inventLocationId">LocationId from proposal line</param>
    /// <returns>InventDim buffer</returns>
    public InventDim initInventDim(InventSiteId _inevntSiteId, InventLocationId _inventLocationId)
    {
        InventDim inventDim;
      
        inventDim.InventSiteId      = _inevntSiteId;
        inventDim.InventLocationId  = _inventLocationId;

        inventDim = InventDim::findOrCreate(inventDim);
        
        return inventDim;
    }

    /// <summary>
    /// Recalculates and updates avail physical quanties
    /// </summary>
    /// <param name = "_contract">TransferOrderCreateProposalContract from dialog</param>
    public void recalculateQuanties(TransferOrderCreateProposalContract _contract)
    {
        TransferOrderProposal    transferOrderProposal;
        InventQtyTotal              inventQty;
        Real                        workingdays;

        while select forupdate transferOrderProposal
            where transferOrderProposal.ProposalModel == _contract.parmProposalModel()
        {
            try
            {
                ttsbegin;
                transferOrderProposal.RefillAvailablePhysical   = this.getRefillItemAvailPhysicalBySiteAndWarehouse(transferOrderProposal.ItemId,
                                                                                                                    transferOrderProposal.InventSiteIdFrom,
                                                                                                                    transferOrderProposal.InventLocationIdFrom);

                inventQty = 0;
                inventQty = this.getItemTotalSalesBySiteAndWarehouse(transferOrderProposal.ItemId,
                                                                     transferOrderProposal.InventSiteIdFrom,
                                                                     transferOrderProposal.InventLocationIdFrom,
                                                                     transferOrderProposal.ToDate - transferOrderProposal.TimeFence,
                                                                     transferOrderProposal.ToDate);
                workingdays = 0;
                workingdays = this.getNumOfWorkingdays(transferOrderProposal.InventLocationIdFrom, transferOrderProposal.ToDate - transferOrderProposal.TimeFence, transferOrderProposal.ToDate);

                transferOrderProposal.RefillCoverageDays = transferOrderProposal.RefillSalesPerDay ? transferOrderProposal.RefillAvailablePhysical / transferOrderProposal.RefillSalesPerDay : 0;

                transferOrderProposal.DCAvailablePhysical   = this.getDCItemAvailPhysicalBySiteAndWarehouse(transferOrderProposal.ItemId,
                                                                                                            transferOrderProposal.InventSiteIdTo,
                                                                                                            transferOrderProposal.InventLocationIdTo);
                inventQty = 0;
                inventQty = this.getItemTotalSalesBySiteAndWarehouse(transferOrderProposal.ItemId,
                                                                     transferOrderProposal.InventSiteIdTo,
                                                                     transferOrderProposal.InventLocationIdTo,
                                                                     transferOrderProposal.ToDate - transferOrderProposal.TimeFence,
                                                                     transferOrderProposal.ToDate);
                workingdays = 0;
                workingdays = this.getNumOfWorkingdays(transferOrderProposal.InventLocationIdFrom, transferOrderProposal.ToDate - transferOrderProposal.TimeFence, transferOrderProposal.ToDate);


                transferOrderProposal.DCCoverageDays = transferOrderProposal.DCSalesPerDay ? transferOrderProposal.DCAvailablePhysical / transferOrderProposal.DCSalesPerDay : 0;

                transferOrderProposal.update();

                ttscommit;
            }
            catch(Exception::Error)
            {
                throw error( "@Planning:TransferOrderPropsalCreationError");
            }
            catch(Exception::Deadlock )
            {
                if(xSession::currentRetryCount() >= Planning_Constants::MaxOCCRetryCount)
                {
                    throw Exception::Deadlock;
                }
                else
                {
                    retry;
                }
            }
            catch(Exception::UpdateConflict)
            {
                if (appl.ttsLevel() == 0)
                {
                    if (xSession::currentRetryCount() >= Planning_Constants::MaxOCCRetryCount)
                    {
                        throw Exception::UpdateConflictNotRecovered;
                    }
                    else
                    {
                        retry;
                    }
                }
                else
                {
                    throw Exception::UpdateConflict;
                }
            }
        }
    }

}

Controller class

/// <summary>
/// The controller for handling bulk Transfer order proposal creation.
/// </summary>
class TransferOrderCreateProposalController  extends SysOperationServiceController
{
    /// <summary>
    /// Constructs a new instance of the <c>TransferOrderCreateProposalController</c>.
    /// </summary>
    /// <param name = "_args">A set of arguments that is used for Transfer order proposal creation.</param>
    /// <returns>A new instance of the <c>TransferOrderCreateProposalController</c>.</returns>
    public static TransferOrderCreateProposalController construct(Args _args)
    {
        TransferOrderCreateProposalController  controller;

        switch (_args.menuItemName())
        {
            case menuItemActionStr(TransferOrderEditProposal):
            case menuItemActionStr(TransferOrderCreateProposal):
                controller = new TransferOrderCreateProposalController(classStr( TransferOrderCreateProposalService ),
                                                                          methodStr( TransferOrderCreateProposalService, createTransferOrderProposal ),
                                                                          SysOperationExecutionMode::Synchronous);
                break;

            case menuItemActionStr(TransferOrderRecalculateQty):
                controller = new TransferOrderCreateProposalController(classStr( TransferOrderCreateProposalService ),
                                                                          methodStr( TransferOrderCreateProposalService, recalculateQuanties ),
                                                                          SysOperationExecutionMode::Synchronous);
                break;

            default:
                break;
        }

        controller.parmArgs( _args );

        return controller;
    }

    public static void main(Args _args)
    {
        TransferOrderCreateProposalController  controller = TransferOrderCreateProposalController::construct( _args );

        controller.startOperation();
        
        //Only run if in Non batch mode
        if (controller.startResult == SysOperationStartResult::Started)
        {
            controller.RefreshCallingForm(_args);
        }
    }

    /// <summary>
    /// Refresh TransferOrderProposal from when not running in batch
    /// </summary>
    /// <param name = "_args"></param>
    private void RefreshCallingForm(args _args)
    {
        if (_args && _args.caller() && _args.caller() is formRun)
        {
            TransferOrderCreateProposalContract contract = this.getDataContractObject();

            FormStringControl proposalModel;

            FormRun callerFormRun = _args.caller() as formRun;

            proposalModel = callerFormRun.design().controlName(formControlStr(TransferOrderProposal, ProposalModel));

            proposalModel.Text(contract.parmProposalModel());
            proposalModel.modified();

            callerFormRun.dataSource(1).research(true);
            callerFormRun.dataSource(1).refresh();

            callerFormRun.dataSource(2).research(true);
            callerFormRun.dataSource(2).refresh();
        }
    }

    protected boolean canRunInNewSession()
    {
        return true;
    }

}

Contract class

/// <summary>
/// The data contract for Transfer order creation.
/// </summary>
[
    DataContract,
    SysOperationGroup("HistoricalHorizoGroup","@:HistoricalHorizon","1",FormArrangeMethod::Vertical),
    SysOperationGroup("ReplaceCurrentProposalGroup","@:ReplaceCurrentProposal","2",FormArrangeMethod::Vertical),
    SysOperationContractProcessing(classStr(TransferOrderCreateProposalUIBuilder))
]
public class TransferOrderCreateProposalContract implements SysOperationInitializable, SysOperationValidatable
{
    Query                   query;
    str                     packedQuery;
    TransDate               fromDate,toDate;
    NoYesId                 replaceCurrentProposal;
    NoYesId                 recalculateQuantities;

    InventSiteId            inventSiteId;
    InventLocationId        inventLocationIdFrom;
    Integer                 timeFence;
    ProposalModelId      proposalModel;

    List                    inventLocationIdTo;
    
    /// <summary>
    /// Indicates whether the contract is valid.
    /// </summary>
    /// <returns>
    /// A Boolean value that indicates whether the contract is valid.
    /// </returns>
    public boolean validate()
    {
        boolean isValid = true;        

        if (!proposalModel)
        {
            isValid = checkFailed(strFmt("@SYS135209", "@:ProposalModel"));
        }
        else if (!this.confirmReplaceCurrentProposal(proposalModel, replaceCurrentProposal) && !recalculateQuantities)
        {
            isValid = false;
        }

        if (!replaceCurrentProposal && !recalculateQuantities)
        {
            isValid = this.checkProposalExists();
        }

        return isValid;
    }

    /// <summary>
    /// check for transfer order proposals exists
    /// </summary>
    /// <returns>A Boolean value that indicates whether the contract is valid</returns>
    public boolean checkProposalExists()
    {
        Query                       queryVal;
        Counter                     lineNum;
        container                   results;
        Enumerator                  enumerator;
        InventTable                 inventTable;
        
        boolean                     isValid =  true;

        if (query == null && packedQuery)
        {
            queryVal = new Query( SysOperationHelper::base64Decode( packedQuery ) );
        }
        else
        {
            queryVal = query;
        }

        QueryRun queryRun   = new QueryRun(queryVal);

        while (queryRun.next())
        {
            inventTable =   queryRun.get(tablenum(InventTable));
            enumerator  =   inventLocationIdTo.getEnumerator();

            while (enumerator.moveNext())
            {
                if (TransferOrderProposal::exist(inventTable.ItemId, enumerator.current(), proposalModel))
                {
                    lineNum++;

                    results += strFmt("@:ProposalExistsValidation", inventTable.ItemId, enumerator.current());

                    if (lineNum >= 100)
                    {
                        break;
                    }
                }
            }
        }

        if (conLen(results) > 0)
        {
            warning(con2Str(results));

            DialogButton    diagBut;

            str strMessage  = "@:TransferOrderAddlinesConfirmation";
            str strTitle    = "@ApplicationPlatform:SystemNotificationTitle";

            diagBut = Box::okCancel(strMessage,
                                    DialogButton::Cancel, // Initial focus is on the Cancel button.
                                    strTitle);

            if (diagBut == DialogButton::Cancel)
            {
                isValid = false;
            }
            else
            {
                isValid = true;
            }
        }

        return isValid;
    }

    /// <summary>
    /// confirm from user to replace Marked/modifeied transfer order proposals
    /// </summary>
    /// <param name = "_proposalModel">user selected value</param>
    /// <param name = "_replaceCurrentProposal">true</param>
    /// <returns>A Boolean value that indicates whether the contract is valid </returns>
    public boolean confirmReplaceCurrentProposal(ProposalModelId _proposalModel, boolean _replaceCurrentProposal)
    {
        boolean ret = true;
        
        if(_proposalModel && _replaceCurrentProposal)
        {
            TransferOrderProposal    transferOrderProposal;

            select firstonly RecId from transferOrderProposal
                    where transferOrderProposal.ProposalModel   == _proposalModel
                        && (transferOrderProposal.AddToShipment == NoYes::Yes
                            || transferOrderProposal.CaseQty != 0);

            if (transferOrderProposal.RecId)
            {
                DialogButton    diagBut;

                str strMessage  = "@:PropsalReplaceConfirmationText";
                str strTitle    = "@ApplicationPlatform:SystemNotificationTitle";

                diagBut = Box::okCancel(strMessage,
                                        DialogButton::Cancel, // Initial focus is on the Cancel button.
                                        strTitle);

                if (diagBut == DialogButton::Cancel)
                {
                    ret = false;
                }
                else
                {
                    ret = true;
                }
            }
        }
        else
        {
            ret = true;
        }

        return ret;
    }

    /// <summary>
    /// Initailizes the default values to parameters.
    /// </summary>
    public void initialize()
    {
        query = new Query( queryStr( InventTableQuery ) );
    }

    /// <summary>
    /// load query from syslast value
    /// </summary>
    /// <param name = "_packedQuery"></param>
    /// <returns> packed query string</returns>
    [
         DataMember,
         AifQueryTypeAttribute('_packedQuery', queryStr( InventTableQuery ) )
    ]
    public str parmPackedQuery( str _packedQuery = packedQuery)
    {
        packedQuery = _packedQuery;

        return packedQuery;
    }

    /// <summary>
    /// Encode/decode the query and set or get
    /// </summary>
    /// <param name = "_query"></param>
    /// <returns>query object</returns>
    public Query parmQuery( Query _query = query )
    {
        if ( prmisDefault( _query ) && query == null )
        {
            query = new Query( SysOperationHelper::base64Decode( packedQuery ) );
        }
        else
        {
            packedQuery  = SysOperationHelper::base64Encode( _query.pack() );
            query = _query;
        }

        return query;
    }

    /// <summary>
    /// Method used to specify the data memmber attribute
    /// </summary>
    /// <param>
    /// <name>parmFromDate</name>is used to set and get the FromDate
    /// </param>
    [
         DataMember,
         SysOperationGroupMember("HistoricalHorizoGroup"),
         SysOperationDisplayOrder("1"),
         SysOperationLabelAttribute(literalstr("@:TransferProposalModel"))
    ]
    public ProposalModelId parmProposalModel( ProposalModelId _proposalModel = proposalModel )
    {
        proposalModel  =   _proposalModel;

        return proposalModel;
    }

    /// <summary>
    /// Method used to specify the data member attribute
    /// </summary>
    /// <param>
    /// <name>parmTimeFence</name>is used to set and get the historical time
    /// </param>
    [
         DataMember,
         SysOperationGroupMember("HistoricalHorizoGroup"),
         SysOperationDisplayOrder("2"),
         SysOperationLabelAttribute(literalstr("@SYS315566"))
    ]
    public Integer parmTimeFence(Integer _timeFence = timeFence  )
    {
        timeFence  =   _timeFence;

        return timeFence;
    }

    /// <summary>
    /// Method used to specify the data member attribute
    /// </summary>
    /// <param>
    /// <name>parmToDate</name>is used to set and get the ToDate
    /// </param>
    [
         DataMember,
         SysOperationGroupMember("HistoricalHorizoGroup"),
         SysOperationDisplayOrder("3"),
         SysOperationLabelAttribute(literalstr("@:ToDate"))
    ]
    public TransDate parmToDate( TransDate _toDate = toDate )
    {
        toDate  =   _toDate;

        return toDate;
    }

    /// <summary>
    /// Method used to specify the data member attribute
    /// </summary>
    /// <param>
    /// <name>parmReplaceCurrentProposal</name>is used to set and get the parameter value
    /// </param>
    [
         DataMember,
         SysOperationGroupMember("ReplaceCurrentProposalGroup"),
         SysOperationDisplayOrder("4"),  
         SysOperationLabelAttribute(literalstr("@:ReplaceCurrentProposal"))
    ]
    public NoYesId parmReplaceCurrentProposal( NoYesId _replaceCurrentProposal = replaceCurrentProposal )
    {
        replaceCurrentProposal  =   _replaceCurrentProposal;

        return replaceCurrentProposal;
    }

    /// <summary>
    /// Method used to specify the data memmber attribute
    /// </summary>
    /// <param>
    /// <name>parmToDate</name>is used to set and get the ToDate
    /// </param>
    [
         DataMember,
         SysOperationGroupMember("ReplaceCurrentProposalGroup"),
         SysOperationDisplayOrder("5"),
         SysOperationLabelAttribute(literalstr("@SYS106955"))
    ]
    public InventSiteId parmInventSiteId( InventSiteId _inventSiteId = inventSiteId )
    {
        inventSiteId  =   _inventSiteId;

        return inventSiteId;
    }

    /// <summary>
    /// Method used to specify the data memmber attribute
    /// </summary>
    /// <param>
    /// <name>parmToDate</name>is used to set and get the ToDate
    /// </param>
    [
         DataMember,
         SysOperationGroupMember("ReplaceCurrentProposalGroup"),
         SysOperationDisplayOrder("6"),
         SysOperationLabelAttribute(literalstr("@SYS25253"))
    ]
    public InventLocationId parmInventLocationIdFrom( InventLocationId _inventLocationIdFrom = inventLocationIdFrom )
    {
        inventLocationIdFrom  =   _inventLocationIdFrom;

        return inventLocationIdFrom;
    }

    /// <summary>
    /// Method used to specify the data memmber attribute
    /// </summary>
    /// <param>
    /// <name>parmToDate</name>is used to set and get the ToDate
    /// </param>
    [
         DataMember,
         SysOperationGroupMember("ReplaceCurrentProposalGroup"),
         SysOperationDisplayOrder("7"),
         SysOperationLabelAttribute(literalstr("@SYS8519")),
         AifCollectionType('return', Types::String)
    ]
    public List parmInventLocationIdTo( List _inventLocationIdTo = inventLocationIdTo )
    {
        inventLocationIdTo  =   _inventLocationIdTo;

        return inventLocationIdTo;
    }

    /// <summary>
    /// Method used to specify the data memmber attribute
    /// </summary>
    /// <param>
    /// <name>parmReplaceCurrentProposal</name>is used to set and get the parameter value
    /// </param>
    [
         DataMember,
         SysOperationGroupMember("ReplaceCurrentProposalGroup"),
         SysOperationDisplayOrder("8"),
         SysOperationLabelAttribute(literalstr("@SYS40695"))
    ]
    public NoYesId parmRecalculateQuantities( NoYesId _recalculateQuantities = recalculateQuantities )
    {
        recalculateQuantities  =   _recalculateQuantities;

        return recalculateQuantities;
    }

}

No comments:

Post a Comment

Table browser URL in D365FO

Critical Thinking icon icon by Icons8