Friday, April 30, 2021

Conversion from UTCDateTime to Date or Time in AX

Here is an example of correct conversion between UTCDateTime value and Date and Time value which is associated with user preferred time zone:
public static void testDateTimeConversion()
{
    utcDateTime dateTime;
    date dateInUserTimeZone;
    TimeOfDay timeInUserTimeZone;

    dateTime = DateTimeUtil::utcNow();

    dateInUserTimeZone = DateTimeUtil::date(DateTimeUtil::applyTimeZoneOffset(dateTime, DateTimeUtil::getUserPreferredTimeZone()));
    timeInUserTimeZone = DateTimeUtil::time(DateTimeUtil::applyTimeZoneOffset(dateTime, DateTimeUtil::getUserPreferredTimeZone()));

    dateTime = DateTimeUtil::newDateTime(dateInUserTimeZone, timeInUserTimeZone, DateTimeUtil::getUserPreferredTimeZone());
}

Monday, April 26, 2021

UserConnection in D365fo

Its used when we need to commit our transaction wehen standared code doesn't Commit.
example :SalesQuotationEditLinesForm_Sales_Send > checkSales() , COC and try to write 
custom insert or update operation here while validation is failed our transactions doesn't commit

static void KlForRecordInserted(Args _args)
{
    UserConnection userConnection;
    CustTable custTable;
    ;
   
    ttsbegin;
   
    userConnection = new userConnection();
   
    custTable.clear();
    custTable.initValue();
    custTable.AccountNum = "000020";
    custTable.Name = "My Test Customer";
    custTable.setConnection(userConnection); // set userconnection
    custTable.insert();
   
    throw error("An error that causes a rollback");
    ttscommit;
}

Saturday, April 24, 2021

Query with join with multiple data sources in AX (Inner join, not exists join)

    public void initializeQueryDS()
    {
        query = new Query();
        QueryBuildDataSource qbds;
        QueryBuildDataSource qbdsSessionLine;

        switch(routing)
        {
            case Routing::Sales:
                qbds = query.addDataSource(tableNum(SalesLine));

                qbdsSessionLine = qbds.addDataSource(tableNum(WorkbenchSessionLine));
                qbdsSessionLine.joinMode(JoinMode::NoExistsJoin);
                qbdsSessionLine.relations(true);
                qbdsSessionLine.fetchMode(QueryFetchMode::One2One);

                TblNum = tableNum(SalesLine);
                break;
            case Routing::Return:
                qbds = query.addDataSource(tableNum(SalesLine));
                TblNum = tableNum(SalesLine);
                break;
        }
    }

    public void initializeQueryRange()
    {
        if(inventLocationId != strMin())
        {  
            QueryBuildDataSource qbdsSalesLine,qbdsInventDim;

            qbdsSalesLine = query.dataSourceTable(tableNum(SalesLine));
            qbdsInventDim = qbdsSalesLine.addDataSource(tableNum(InventDim));
            qbdsInventDim.joinMode(JoinMode::InnerJoin);
            qbdsInventDim.relations(true);
            qbdsInventDim.fetchMode(QueryFetchMode::One2One);
            qbdsInventDim.addRange(fieldNum(InventDim, InventLocationId)).value(inventLocationId);
        }

        if(shipDate != dateNull())
        {
            QueryBuildDataSource qbds;

            qbds = query.dataSourceTable(tableNum(SalesLine));
            qbds.addRange(fieldNum(SalesLine, ShippingDateConfirmed)).value(SysQuery::value(shipDate));
        }

        if(dlvModeFrom.elements())
        {
            container   conMOD;
            Enumerator  enumerator  =   dlvModeFrom.getEnumerator();

            while (enumerator.moveNext())
            {
                conMOD += enumerator.current();
            }

            QueryBuildDataSource qbds;
            qbds = query.dataSourceTable(tableNum(SalesLine));

            qbds.addRange(fieldNum(SalesLine, DlvMode)).value(con2Str(conMOD));
        }

    }

    public WorkbenchSessionLine initFromCommon(Common _callerTable)
    {
        WorkbenchSessionLine line;

        switch (_callerTable.TableId)
        {
            case tableNum(SalesLine):
                line.RefRecId    = _callerTable.(fieldNum(SalesLine, RecId));
                line.RefTableId    = _callerTable.TableId;

                line.InventTransId    = _callerTable.(fieldNum(SalesLine, InventTransId));

                if(routing == Routing::Sales)
                {
                    line.ReferenceType = RefType::SalesOrder;
                }
                else if(routing == Routing::Return)
                {
                    line.ReferenceType = RefType::ReturnOrder;
                }
                break;

            default:
                break;
        }

        return line;
    }

    public void createWorkbenchSession(WorkbenchSessionContract _contract)
    {
        WorkbenchSessionTable header;
        WorkbenchSessionLine line;

        RecordInsertList lineRecordList = new RecordInsertList(tableNum(WorkbenchSessionLine), true, true, true, false, true, line);

        contract = _contract;
       
        this.initializeParameters();
        this.initializeQueryDS();
        this.initializeQueryRange();

        try
        {
            ttsbegin;

            NumberSeq numberSeq = NumberSeq::newGetNum(TMSParameters::numRefInternalSessionID());

            header.initValue();

            header.DynamicsInternalSessionID = numberSeq.num();

            numberSeq.used();

            header.SessionStatus = SessionStatus::Open;

            header.LE_ID = curExt();

            if (routing == Routing::Sales || routing == Routing::Return)
            {
                header.CombineOrders = true;
            }
           
            header.insert();

            queryRun = new QueryRun(query);

            while(queryRun.next())
            {
                Common common = queryRun.get(TblNum);

                line = this.initFromCommon(common);

                line.WorkbenchSessionTable = header.RecId;

                lineRecordList.add(line);
            }

            lineRecordList.insertDatabase();

            ttscommit;
            
            this.openWorkbenchSessionForm(header);
        }
        catch
        {

        }
    }

Sysoperations frameworks Tips and tricks in AX

    protected ClassDescription defaultCaption()
    {
        return "@CashManagement:CashFlowTimeSeriesInitializeControllerCaption";
    }

    public ClassDescription caption()
    {
        return this.defaultCaption();
    }

    /// <summary>
    /// Indicates if the class must run in batch or not.
    /// </summary>
    /// <returns>
    /// Always returns false.
    /// </returns>
    /// <remarks>
    /// This method must be in this class because it is called from the <c>dialogRunbase</c> class.
    /// </remarks>
    public boolean mustGoBatch()
    {
        return false;
    }

    /// <summary>
    /// Determines whether the job can be executed in batch.
    /// </summary>
    /// <returns>
    /// false if the job cannot be executed in batch; otherwise, true.
    /// </returns>
    public boolean canGoBatch()
    {
        return false;
    }

    /// <summary>
    /// Sets whether to show the batch tab or not.
    /// </summary>
    /// <param name = "_showBatchTab">Flag to identify whether to show the batch tab or not.</param>
    /// <returns>False for batch tab to be invisible</returns>
    public boolean showBatchTab(boolean _showBatchTab = showBatchTab)
    {
        return false;
    }
	
	public boolean showBatchRecurrenceButton(boolean _showBatchRecurrenceButton = showBatchRecurrenceButton)
    {
        return false;
    }

Thursday, April 22, 2021

How to get the number of elements in the list in AX

{ 
    List il = new List(Types::Integer); 
 
    il.addStart(1); 
    il.addStart(2); 
    il.addStart(3); 
    if (il.elements() != 3) 
    { 
        print "Something is wrong..."; 
    } 
}

Friday, April 16, 2021

Data entities method calling sequence in D365FO

 
EXPORT:
       Entity- postLoad()
       staging - insert()
       Entity- postLoad() - depends on records

IMPORT:
       staging - postLoad()
       Entity - postLoad()
       Entity - initValue()
       Entity - validateField() - depends on no of fields
       Entity - validateWrite()
       Entity - insert() / update()
       Entity - persistEntity()
       Entity - initializeEntityDataSource()
       Entity - mapEntityToDataSource()
       Entity - insertEntityDataSource() / updateEntityDataSource()
       Entity - mapDataSourceToEntity()
       staging - postLoad()

Tuesday, April 13, 2021

How to create a collapsible section in Blogger

Add CSS

Add a unique name for each new post eg: collapsible1 or collapsible2 etc
add at the start of the HTML code after <HTML> tag
<style>
.collapsible {
  background-color: #777;
  color: white;
  cursor: pointer;
  padding: 18px;
  border: none;
  text-align: left;
  outline: none;
  font-size: 15px;
}

.active, .collapsible:hover {
  background-color: #555;
}

.content1 {
  padding: 0 18px;
  display: none;
  overflow: hidden;
  background-color: #f1f1f1;
}
</style>

Apply CSS to div and Paragragh

add these classes in the paragrah and the div at the start of the tag
<p title="UIBuilder" class="collapsible">UIBuilder class</p>
<div class="content1"></div>

Javascript

add at the end of the HTML code before </HTML> tag
<script>
var coll = document.getElementsByClassName("collapsible");
var i;

for (i = 0; i < coll.length; i++) {
  coll[i].addEventListener("click", function() {
    this.classList.toggle("active");
    var content = this.nextElementSibling;
    if (content.style.display === "block") {
      content.style.display = "none";
    } else {
      content.style.display = "block";
    }
  });
}
</script>

How to use RecordInsertList in AX

/// <summary>
/// The <c>BankCheckStubDP</c> class declares the variables and tables that are required for the
/// <c>BankCheckStub</c> report.
/// </summary>
[
    SRSReportParameterAttribute(classStr(BankCheckStubContract))
]
public class BankCheckStubDP extends SRSReportDataProviderBase
{
    BankCheckStubTmp  BankCheckStubTmp;
    /// <summary>
    ///    Fetches the <c>BankCheckStubTmp</c> temporary table.
    /// </summary>
    /// <returns>
    ///    The <c>BankCheckStubTmp</c> temporary table.
    /// </returns>
    [
        SRSReportDataSetAttribute(tablestr(BankCheckStubTmp))
    ]
    public BankCheckStubTmp getBankCheckStubTmp()
    {
        select  BankCheckStubTmp;
    
        return  BankCheckStubTmp;
    }

    /// <summary>
    ///    Fetches the required data for the <c>BankCheckStub</c> report.
    /// </summary>
    public void processReport()
    {
        RecordInsertList            tmpTableRecordList;
        BankTrans             BankTrans;
        BankChequeTable             bankChequeTable;
        CompanyBankAccountId        curBankAccountIdGroup;
        BankChequeNum               curChequeNumGroup;
        int                         lineNumInCheck;
        RefRecId                    SSNType;
        HcmIdentificationNumber     BankSSN;
    
        BankCheckStubContract contract        = this.parmDataContract() as BankCheckStubContract;
        BankChequeNum               chequeNum       = contract.parmChequeNum();
        TransDate                   transDate       = contract.parmChequeDate();
        CompanyBankAccountId        bankAccountId   = contract.parmBankAccountId();
        ShowSSN                  showSSN         = contract.parmShowSSN();
    
        tmpTableRecordList = new RecordInsertList(tableNum(BankCheckStubTmp), true, true, true, false, true, BankCheckStubTmp);
    
        SSNType = BankAccountingParameters::find().SSNIdentificationType;
        if (!Global::hasTableAccess(tableNum(HcmPersonIdentificationNumber))
        ||  !Global::hasFieldAccess(tableNum(HcmPersonIdentificationNumber), fieldNum(HcmPersonIdentificationNumber, IdentificationNumber)))
        {
            showSSN = false;
        }
    
        while select BankTrans order by BankAccountId, BankChequeNum
            where (BankTrans.JournalEntryType == JournalEntryType::Refund
              ||   BankTrans.JournalEntryType == JournalEntryType::Stipend
              ||   BankTrans.JournalEntryType == JournalEntryType::SubsidiaryRefund)
              &&   BankTrans.SISPaymentType   == SISPaymentType::Check
              &&   BankTrans.BankChequeNum
              &&  (!chequeNum     || (chequeNum     && BankTrans.BankChequeNum  == chequeNum))
              &&  (!bankAccountId || (bankAccountId && BankTrans.BankAccountId  == bankAccountId))
            join TransDate from bankChequeTable
                where bankChequeTable.AccountID     == BankTrans.BankAccountId
                  &&  bankChequeTable.ChequeNum     == BankTrans.BankChequeNum
                  && (!transDate  || (transDate     && bankChequeTable.TransDate == transDate))
        {
            if (curBankAccountIdGroup != BankTrans.BankAccountId || curChequeNumGroup != BankTrans.BankChequeNum)
            {
                curBankAccountIdGroup = BankTrans.BankAccountId;
                curChequeNumGroup     = BankTrans.BankChequeNum;
                lineNumInCheck        = 1;
            }
    
            BankSSN  = "";
            if (showSSN)
            {
                BankSSN  = HcmPersonIdentificationNumber::findByPersonAndType(Bank::find(BankTrans.Bank).Person, SSNType).IdentificationNumber;
            }
    
            BankCheckStubTmp.BankAccountId   = BankTrans.BankAccountId;
            BankCheckStubTmp.ChequeNum       = BankTrans.BankChequeNum;
            BankCheckStubTmp.ChequeDate      = bankChequeTable.TransDate;
            BankCheckStubTmp.LineNum         = strFmt('%1', lineNumInCheck);
            BankCheckStubTmp.BankId       = strFmt('%1', BankTrans.BankIdInSIS);
            BankCheckStubTmp.BankName     = BankTrans.BankName();
            BankCheckStubTmp.BankSSN      = BankSSN;
            BankCheckStubTmp.FundSource      = FundSource::findByRecId(BankTrans.FundSource).Description;
            BankCheckStubTmp.Amount          = BankTrans.AmountCur;
    
            tmpTableRecordList.add(BankCheckStubTmp);
            lineNumInCheck++;
        }
    
        tmpTableRecordList.insertDatabase();
    }
}

How to create RunBaseBatch class in AX : Sample code

See the code

/// <summary>
///    The <c>LedgerJournalEntryPost</c> class creates and posts to general ledger transactions specified in
///    the <c>LedgerJournalEntryContract</c> contract class.
/// </summary>
class LedgerJournalEntryPost extends RunBaseBatch
{
    LedgerJournalEntryContract           ledgerJournalEntryContract;
    LedgerJournalEntryPostStatusContract ledgerJournalEntryPostStatusContract;
    Set                                     studentTransRecIdPostedSet;

    #IntegrationServiceFaults
    /// <summary>
    ///     Checks if the Ledger journal can be posted or not.
    /// </summary>
    /// <param name="_ledgerJournalTable">
    ///     Record of the <c>LedgerJournalTable</c> table to verify.
    /// </param>
    /// <returns>
    ///     True if Ledger journal can be posted; otherwise, false.
    /// </returns>
    protected boolean canPostLedgerJournal(LedgerJournalTable  _ledgerJournalTable)
    {
        LedgerJournalTrans  ledgerJournalTrans;
        VendPaymModeTable   vendPaymModeTable;
    
        select firstOnly RecId from ledgerJournalTrans
            where ledgerJournalTrans.JournalNum == _ledgerJournalTable.JournalNum;
    
        if (!ledgerJournalTrans.RecId)
        {
            return false;
        }
    
        if (_ledgerJournalTable.JournalType == LedgerJournalType::Payment)
        {
            select firstOnly RecId from ledgerJournalTrans
                where ledgerJournalTrans.JournalNum        == _ledgerJournalTable.JournalNum
                 &&   ledgerJournalTrans.AccountType       == LedgerJournalACType::Vend
                 &&   ledgerJournalTrans.OffsetAccountType == LedgerJournalACType::Bank
                 &&  (!ledgerJournalTrans.BankChequeNum
                 ||  ledgerJournalTrans.PaymentStatus      != CustVendPaymStatus::Sent)
            exists join vendPaymModeTable
                where vendPaymModeTable.PaymMode        == ledgerJournalTrans.PaymMode
                   && vendPaymModeTable.PaymentType     == PaymentType::Check;
    
            if(ledgerJournalTrans.RecId)
            {
                return false;
            }
        }
    
        return true;
    }

    /// <summary>
    ///     Creates a ledger journal for the specified ledger journal entry.
    /// </summary>
    /// <param name="_ledgerJourEntryLines">
    ///     List of <c>LedgerJournalEntryLineContract</c> contract classes.
    /// </param>
    /// <param name="_journalEntryType">
    ///     The type of the journal to create.
    /// </param>
    /// <returns>
    ///     Created <c>LedgerJournalTable</c> table.
    /// </returns>
    protected LedgerJournalTable createJournal(List                 _ledgerJourEntryLines,
                                               JournalEntryType  _journalEntryType)
    {
        LedgerJournalTable              ledgerJournalTable;
        LedgerJournalCreate          ledgerJournalCreate;
        LedgerJournalEntryContract   entryContract;
    
        entryContract = new LedgerJournalEntryContract();
        entryContract.parmLedgerJourEntryLines(_ledgerJourEntryLines);
    
        ledgerJournalCreate = LedgerJournalCreate::construct(entryContract, _journalEntryType);
        ledgerJournalCreate.run();
    
        ledgerJournalTable = ledgerJournalCreate.parmLedgerJournalTable();
    
        return  ledgerJournalTable;
    }

    /// <summary>
    ///     Finds or creates a ledger journal for the specified ledger journal entry.
    /// </summary>
    /// <param name="_ledgerJourEntryLines">
    ///     List of <c>LedgerJournalEntryLineContract</c> contract classes.
    /// </param>
    /// <param name="_journalEntryType">
    ///     The type of the journal entry.
    /// </param>
    /// <param name="_paymentType">
    ///     The payment type of the journal entry.
    /// </param>
    /// <returns>
    ///     Found or created <c>LedgerJournalTable</c> table.
    /// </returns>
    protected LedgerJournalTable findOrCreateJournal(List                 _ledgerJourEntryLines,
                                                     JournalEntryType  _journalEntryType,
                                                     SISPaymentType    _paymentType)
    {
        LedgerJournalTable  ledgerJournalTable;
    
        ledgerJournalTable = this.findRelatedJournal(_ledgerJourEntryLines, _journalEntryType, _paymentType);
    
        if (!ledgerJournalTable)
        {
            ledgerJournalTable = this.createJournal(_ledgerJourEntryLines, _journalEntryType);
        }
    
        return  ledgerJournalTable;
    }

    /// <summary>
    ///     Finds the ledger journal for the specified ledger journal entry.
    /// </summary>
    /// <param name="_ledgerJourEntryLines">
    ///     List of <c>LedgerJournalEntryLineContract</c> contract classes.
    /// </param>
    /// <param name="_journalEntryType">
    ///     The type of the journal entry.
    /// </param>
    /// <param name="_paymentType">
    ///     The payment type of the journal entry.
    /// </param>
    /// <returns>
    ///     Found <c>LedgerJournalTable</c> table.
    /// </returns>
    protected LedgerJournalTable findRelatedJournal(List                 _ledgerJourEntryLines,
                                                    JournalEntryType  _journalEntryType,
                                                    SISPaymentType    _paymentType)
    {
        LedgerJournalEntryLineContract   ledgerJournalEntryLineContract;
        ListEnumerator                      ledgerJourEntryLinesEnum;
        LedgerJournalTable                  ledgerJournalTable;
    
        if (StudentTrans::isBankChequeProcess(_journalEntryType, _paymentType))
        {
            ledgerJourEntryLinesEnum = _ledgerJourEntryLines.getEnumerator();
    
            while (ledgerJourEntryLinesEnum.moveNext())
            {
                ledgerJournalEntryLineContract = ledgerJourEntryLinesEnum.current();
    
                //if (ledgerJournalEntryLineContract.parmBankChequeNum())
                //{
                ledgerJournalTable = ledgerJournalTable.FindByStudentTransIdInSIS(ledgerJournalEntryLineContract.parmTransIdInSIS(),
                                                                                        ledgerJournalEntryLineContract.parmJournalEntryType());
                if (ledgerJournalTable)
                {
                    return  ledgerJournalTable;
                }
                //}
            }
        }
    
        return  ledgerJournalTable;
    }

    /// <summary>
    ///     Initializes the map of transaction types and transactions from
    ///     the <c>LedgerJournalEntryContract</c> contract class.
    /// </summary>
    /// <returns>
    ///     An instance of the map of transaction types and transactions.
    /// </returns>
    public Map getJournalEntryLinesMap()
    {
        List                              entryLineList;
        ListEnumerator                    ledgerJournalEntryLinesEnum;
        LedgerJournalEntryLineContract entryLineContract;
        container                         entryTypeKeyCon;
        int                               transGroupCounter;
        Map                               entryLinesMap = new Map(Types::Container, Types::Class);
    
        #define.TransGroupUniqueIdentifier("TransGroupUniqueIdentifier")
    
        ledgerJournalEntryLinesEnum     = ledgerJournalEntryContract.parmLedgerJourEntryLines().getEnumerator();
    
        while (ledgerJournalEntryLinesEnum.moveNext())
        {
            entryLineContract = ledgerJournalEntryLinesEnum.current();
    
            if (StudentTrans::isBankChequeProcess(entryLineContract.parmJournalEntryType(), entryLineContract.parmSISPaymentType())
             && entryLineContract.parmMasterChequeGroup())
            {
                entryTypeKeyCon = [entryLineContract.parmJournalEntryType(), entryLineContract.parmSISPaymentType(), entryLineContract.parmMasterChequeGroup()];
            }
            else
            {
                transGroupCounter++;
                entryTypeKeyCon = [entryLineContract.parmJournalEntryType(), entryLineContract.parmSISPaymentType(), strFmt("%1%2", #TransGroupUniqueIdentifier, transGroupCounter)];
            }
    
            if (!entryLinesMap.exists(entryTypeKeyCon))
            {
                entryLineList = new List(Types::Class);
                entryLineList.addEnd(entryLineContract);
    
                entryLinesMap.insert(entryTypeKeyCon, entryLineList);
            }
            else
            {
                entryLineList = entryLinesMap.lookup(entryTypeKeyCon);
                entryLineList.addEnd(entryLineContract);
    
                entryLinesMap.insert(entryTypeKeyCon, entryLineList);
            }
        }
    
        return entryLinesMap;
    }

    /// <summary>
    ///    Gets student transaction SIS Ids.
    /// </summary>
    /// <param name="_ledgerJourEntryLines">
    ///     List of <c>LedgerJournalEntryLineContract</c> contract classes.
    /// </param>
    /// <returns>
    ///     Container of student transaction SIS Ids.
    /// </returns>
    protected container getStudentTransIds(List _ledgerJourEntryLines)
    {
        LedgerJournalEntryLineContract   ledgerJournalEntryLineContract;
        container                           ret;
        ListEnumerator                      ledgerJournalEntryLinesEnum = _ledgerJourEntryLines.getEnumerator();
    
        while (ledgerJournalEntryLinesEnum.moveNext())
        {
            ledgerJournalEntryLineContract = ledgerJournalEntryLinesEnum.current();
    
            ret += ledgerJournalEntryLineContract.parmTransIdInSIS();
        }
    
        return  ret;
    }

    /// <summary>
    ///     Initializes <c>LedgerJournalEntryPostStatusContract</c> contract class.
    /// </summary>
    protected void initEntryPostStatusContract()
    {
        ledgerJournalEntryPostStatusContract = new LedgerJournalEntryPostStatusContract();
        ledgerJournalEntryPostStatusContract.parmPostedJournals(new List(Types::String));
        ledgerJournalEntryPostStatusContract.initializeMessages();
    }

    public static void markPostedTrans(Map _postedTransMap)
    {
        new SISIntegrationServiceAdapter().sendPostedStudentTrans(_postedTransMap);
    }

    public void new()
    {
        super();
    
        studentTransRecIdPostedSet = new Set(Types::Int64);
    }

    /// <summary>
    ///     Gets or sets the value of the <c>LedgerJournalEntryContract</c> class parameter.
    /// </summary>
    /// <param name="_ledgerJournalEntryContract">
    ///     The new value of the <c>LedgerJournalEntryContract</c> class parameter; optional.
    /// </param>
    /// <returns>
    ///     The current value of the <c>LedgerJournalEntryContract</c> class parameter.
    /// </returns>
    public LedgerJournalEntryContract parmLedgerJournalEntryContract(LedgerJournalEntryContract _ledgerJournalEntryContract = ledgerJournalEntryContract)
    {
        ledgerJournalEntryContract = _ledgerJournalEntryContract;
        return ledgerJournalEntryContract;
    }

    /// <summary>
    ///     Gets or sets the value of the <c>LedgerJournalEntryPostStatusContract</c> class parameter.
    /// </summary>
    /// <param name="_ledgerJournalEntryPostStatusContract">
    ///     The new value of the <c>LedgerJournalEntryPostStatusContract</c> class parameter; optional.
    /// </param>
    /// <returns>
    ///     The current value of the <c>LedgerJournalEntryPostStatusContract</c> class parameter.
    /// </returns>
    public LedgerJournalEntryPostStatusContract parmLedgerJournalEntryPostStatusContract(LedgerJournalEntryPostStatusContract _ledgerJournalEntryPostStatusContract = ledgerJournalEntryPostStatusContract)
    {
        ledgerJournalEntryPostStatusContract = _ledgerJournalEntryPostStatusContract;
        return  ledgerJournalEntryPostStatusContract;
    }

    /// <summary>
    ///     Gets or sets the value of the <c>studentTransRecIdPostedSet</c> parameter.
    /// </summary>
    /// <param name="_studentTransRecIdPostedSet">
    ///     The new value of the <c>studentTransRecIdPostedSet</c> parameter; optional.
    /// </param>
    /// <returns>
    ///     The current value of the <c>studentTransRecIdPostedSet</c> parameter.
    /// </returns>
    public Set parmStudentTransRecIdPostedSet(Set _studentTransRecIdPostedSet = studentTransRecIdPostedSet)
    {
        studentTransRecIdPostedSet = _studentTransRecIdPostedSet;
        return studentTransRecIdPostedSet;
    }

    /// <summary>
    ///     Posts the ledger journal.
    /// </summary>
    /// <param name="_ledgerJournalTable">
    ///     Ledger journal to post.
    /// </param>
    protected void postJournal(LedgerJournalTable   _ledgerJournalTable)
    {
        LedgerJournalCheckPost  ledgerJournalCheckPost;
        LedgerJournalTable      ledgerJournalTable;
    
        if (!_ledgerJournalTable)
        {
            throw error("@1401");
        }
    
        ledgerJournalCheckPost = LedgerJournalCheckPost::newLedgerJournalTable(_ledgerJournalTable, NoYes::Yes);
    
        if (this.canPostLedgerJournal(_ledgerJournalTable))
        {
            ledgerJournalCheckPost.parmSkipBlockedForManualEntryCheck(true);
            ledgerJournalCheckPost.runOperation();
        }
    
        ledgerJournalTable = ledgerJournalTable::find(_ledgerJournalTable.JournalNum);
    
        if (!ledgerJournalTable.Posted)
        {
            throw error("@1402");
        }
    }

    /// <summary>
    ///    Posts student transactions.
    /// </summary>
    /// <param name="_journalNum">
    ///     Ledger journal Id.
    /// </param>
    /// <param name="_ledgerJourEntryLines">
    ///     List of <c>LedgerJournalEntryLineContract</c> contract classes.
    /// </param>
    protected void postStudentTrans(LedgerJournalId   _journalNum,
                                    List              _ledgerJourEntryLines)
    {
        LedgerJournalEntryLineContract   ledgerJournalEntryLineContract;
        StudentTrans                     studentTrans;
        container                           mapKey;
        ListEnumerator                      ledgerJournalEntryLinesEnum = _ledgerJourEntryLines.getEnumerator();
        Map                                 transLedgerJournalIdMap     = new Map(Types::Container, Types::Class);
        Set                                 journalNumSet               = new Set(Types::String);
    
        journalNumSet.add(_journalNum);
    
        while (ledgerJournalEntryLinesEnum.moveNext())
        {
            ledgerJournalEntryLineContract = ledgerJournalEntryLinesEnum.current();
    
            mapKey = [ledgerJournalEntryLineContract.parmTransIdInSIS(), ledgerJournalEntryLineContract.parmJournalEntryType()];
    
            transLedgerJournalIdMap.insert(mapKey, journalNumSet);
    
            studentTrans        = StudentTrans::find(ledgerJournalEntryLineContract.parmTransIdInSIS(),
                                                        ledgerJournalEntryLineContract.parmJournalEntryType(),
                                                        true);
            studentTrans.Posted = true;
            if(studentTrans.SISPaymentType == SISPaymentType::Check)
                studentTrans.PendingChequeInSIS = false;
    
            if (!studentTrans.validateWrite())
            {
                throw error("@SYS18447");
            }
    
            studentTrans.updateSkipDatabaseLog(true);
    
            if (studentTrans.isValidForFundSourceTrans())
            {
                if (FundSourceTrans::findByStudentTrans(studentTrans.RecId))
                {
                    FundSourceTrans::updateExist(studentTrans);
                }
                else
                {
                    FundSourceTrans::create(studentTrans);
                }
            }
    
            if (StudentAccountingParameters::isCampusNexusMode())
            {
                LedgerJournalEntryPost::markPostedTrans(transLedgerJournalIdMap);
            }
    
            studentTransRecIdPostedSet.add(studentTrans.RecId);
        }
    }

    /// <summary>
    ///     Executes business logic of the class.
    /// </summary>
    public void run()
    {
        LedgerJournalTable      ledgerJournalTable;
        JournalEntryType     journalEntryType;
        SISPaymentType       paymentType;
        AifInfoLog              aifInfoLog;
        List                    ledgerJourEntryLines;
        Name                    groupName;
        boolean                 exceptionThrown;
        MapEnumerator           entryLinesMapEnum;
    
        this.initEntryPostStatusContract();
    
        entryLinesMapEnum = this.getJournalEntryLinesMap().getEnumerator();
    
        while (entryLinesMapEnum.moveNext())
        {
            [journalEntryType, paymentType, groupName]  = entryLinesMapEnum.currentKey();
            ledgerJourEntryLines                        = entryLinesMapEnum.currentValue();
            aifInfoLog                                  = new AifInfoLog();
    
            try
            {
                ttsBegin;
    
                this.validateLedgerJourEntryLines(ledgerJourEntryLines);
    
                ledgerJournalTable = this.findOrCreateJournal(ledgerJourEntryLines, journalEntryType, paymentType);
    
                this.postJournal(ledgerJournalTable);
                this.postStudentTrans(ledgerJournalTable.JournalNum, ledgerJourEntryLines);
    
                ttsCommit;
    
                if (ledgerJournalTable.Posted)
                {
                    ledgerJournalEntryPostStatusContract.parmPostedJournals().addEnd(ledgerJournalTable.JournalNum);
                }
            }
            catch (Exception::Error)
            {
                exceptionThrown = true;
                this.updateEntryPostStatus(aifInfoLog, LedgerJournalCreatePostStatus::Error, this.getStudentTransIds(ledgerJourEntryLines));
            }
            catch (Exception::CLRError)
            {
                exceptionThrown = true;
                error(AifUtil::getClrErrorMessage());
                this.updateEntryPostStatus(aifInfoLog, LedgerJournalCreatePostStatus::Error, this.getStudentTransIds(ledgerJourEntryLines));
            }
            catch
            {
                exceptionThrown = true;
                this.updateEntryPostStatus(aifInfoLog, LedgerJournalCreatePostStatus::Error, this.getStudentTransIds(ledgerJourEntryLines));
            }
        }
    
        if (!exceptionThrown && !ledgerJournalEntryPostStatusContract.parmPostedJournals().empty())
        {
            ledgerJournalEntryPostStatusContract.parmStatus(LedgerJournalCreatePostStatus::Posted);
        }
    }

    /// <summary>
    ///     Updates <c>LedgerJournalEntryPostStatusContract</c> contract class.
    /// </summary>
    /// <param name="_aifInfoLog">
    ///     An object of <c>AifInfoLog</c> class.
    /// </param>
    /// <param name="_postStatus">
    ///     Operation status.
    /// </param>
    /// <param name="_studentTransIdCon">
    ///     Container of student transaction SIS Ids.
    /// </param>
    protected void updateEntryPostStatus(AifInfoLog                         _aifInfoLog,
                                         LedgerJournalCreatePostStatus   _postStatus,
                                         container                          _studentTransIdCon)
    {
        SysInfologEnumerator infologEnum;
    
        if (!ledgerJournalEntryPostStatusContract)
        {
            this.initEntryPostStatusContract();
        }
    
        ledgerJournalEntryPostStatusContract.parmStatus(_postStatus);
    
        AifFault::fault(strFmt("@1403", "@141", con2str(_studentTransIdCon, ', ')), #LedgerJournalTableCreationFailed);
    
        infologEnum = SysInfologEnumerator::newData(_aifInfoLog.getInfoLogData());
    
        while (infologEnum.moveNext())
        {
            ledgerJournalEntryPostStatusContract.addMessage(IntegrationServiceProvider::trimLeadingTabs(infologEnum.currentMessage()));
        }
    }

    /// <summary>
    ///     Validates ledger journal entry lines.
    /// </summary>
    /// <param name="_ledgerJourEntryLines">
    ///     List of <c>LedgerJournalEntryLineContract</c> contract classes.
    /// </param>
    protected void validateLedgerJourEntryLines(List    _ledgerJourEntryLines)
    {
        LedgerJournalEntryLineContract ledgerJournalEntryLineContract;
        StudentTrans                   studentTrans;
        ListEnumerator                    ledgerJournalEntryLinesEnum = _ledgerJourEntryLines.getEnumerator();
    
        while (ledgerJournalEntryLinesEnum.moveNext())
        {
            ledgerJournalEntryLineContract = ledgerJournalEntryLinesEnum.current();
            studentTrans                    = StudentTrans::find(ledgerJournalEntryLineContract.parmTransIdInSIS(), ledgerJournalEntryLineContract.parmJournalEntryType());
    
            if (studentTrans.Posted)
            {
                throw error(strfmt("@1399", studentTrans.description()));
            }
    
            if (StudentTrans::isBankChequeProcess(studentTrans.JournalEntryType, studentTrans.SISPaymentType)
             && !studentTrans.BankChequeNum)
            {
                throw error(strFmt("@1400", studentTrans.description()));
            }
        }
    }

    /// <summary>
    ///     Creates a new instance of the <c>LedgerJournalEntryPost</c> class.
    /// </summary>
    /// <param name="_ledgerJournalEntryContract">
    ///     Value of the <c>LedgerJournalEntryContract</c> contract class.
    /// </param>
    /// <returns>
    ///    Created instance of the <c>LedgerJournalEntryPost</c> class.
    /// </returns>
    public static server LedgerJournalEntryPost construct(LedgerJournalEntryContract _ledgerJournalEntryContract)
    {
        LedgerJournalEntryPost   ledgerJournalEntryPost = new LedgerJournalEntryPost();
    
        ledgerJournalEntryPost.parmLedgerJournalEntryContract(_ledgerJournalEntryContract);
    
        return  ledgerJournalEntryPost;
    }

    /// <summary>
    ///     Creates an object of <c>LedgerJournalEntryContract</c> contract class.
    /// </summary>
    /// <param name="_studentTransRecIdPacked">
    ///     Packed set of <c>StudentTrans</c> record Ids.
    /// </param>
    /// <returns>
    ///     An object of <c>LedgerJournalEntryContract</c> contract class.
    /// </returns>
    public static server LedgerJournalEntryContract createJournalEntryContractList(container   _studentTransRecIdPacked)
    {
        StudentTrans                 studentTrans;
        StudentTrans                 studentTransMasterCheque;
        LedgerJournalEntryContract   ledgerJournalEntryContract  = new LedgerJournalEntryContract();
        Set                             masterChequeGroup           = new Set(Types::String);
        Set                             studentTransRecIdSet        = Set::create(_studentTransRecIdPacked);
        SetEnumerator                   se                          = studentTransRecIdSet.getEnumerator();
    
        ledgerJournalEntryContract.parmLedgerJourEntryLines(new List(Types::Class));
    
        while (se.moveNext())
        {
            studentTrans = StudentTrans::findRecId(se.current());
    
            if (studentTrans.MasterChequeGroup && !masterChequeGroup.in(studentTrans.MasterChequeGroup))
            {
                masterChequeGroup.add(studentTrans.MasterChequeGroup);
    
                while select studentTransMasterCheque
                    where studentTransMasterCheque.MasterChequeGroup == studentTrans.MasterChequeGroup
                {
                    ledgerJournalEntryContract.parmLedgerJourEntryLines().addEnd(studentTransMasterCheque.ledgerJournalEntryLineContract());
                }
            }
            else if (!studentTrans.MasterChequeGroup)
            {
                ledgerJournalEntryContract.parmLedgerJourEntryLines().addEnd(studentTrans.ledgerJournalEntryLineContract());
            }
        }
    
        return  ledgerJournalEntryContract;
    }

    /// <summary>
    ///     Performs transaction posting from user interface.
    /// </summary>
    /// <param name="_args">
    ///     Parameters object.
    /// </param>
    public static void main(Args _args)
    {
        LedgerJournalEntryPost   ledgerJournalEntryPost;
        StudentTrans             studentTrans;
        FormDataSource              ds;
        Set                         studentTransRecIdSet = new Set(Types::Int64);
    
        if (!_args || !_args.dataset())
        {
            throw Error(Error::wrongUseOfFunction(funcName()));
        }
    
        if (FormDataUtil::isFormDataSource(_args.record()))
        {
            ds              = FormDataUtil::getFormDataSource(_args.record());
            studentTrans    = ds.getFirst(true) ? ds.getFirst(true) : ds.cursor();
    
            while (studentTrans)
            {
                studentTransRecIdSet.add(studentTrans.RecId);
                studentTrans = ds.getNext();
            }
        }
        else
        {
            studentTrans = _args.record();
            studentTransRecIdSet.add(studentTrans.RecId);
        }
    
        ledgerJournalEntryPost = LedgerJournalEntryPost::newFromLedgerJournalEntryContract(LedgerJournalEntryPost::createJournalEntryContractList(studentTransRecIdSet.pack()));
        ledgerJournalEntryPost.runOperation();
    
        info(strFmt("@561", ledgerJournalEntryPost.parmStudentTransRecIdPostedSet().elements()));
    
        if (ds)
        {
            ds.research(true);
        }
    }

    /// <summary>
    ///     Creates a new instance of the <c>LedgerJournalEntryPost</c> class and initilizes its parameters.
    /// </summary>
    /// <param name="_ledgerJournalEntryContract">
    ///     Value of the <c>LedgerJournalEntryContract</c> contract class.
    /// </param>
    /// <returns>
    ///    Created instance of the <c>LedgerJournalEntryPost</c> class.
    /// </returns>
    public static server LedgerJournalEntryPost newFromLedgerJournalEntryContract(LedgerJournalEntryContract _ledgerJournalEntryContract)
    {
        LedgerJournalEntryPost ledgerJournalEntryPost = new LedgerJournalEntryPost();
    
        LedgerJournalEntryPost::validateLedgerJournalEntryContract(_ledgerJournalEntryContract);
    
        ledgerJournalEntryPost.parmLedgerJournalEntryContract(_ledgerJournalEntryContract);
    
        return ledgerJournalEntryPost;
    }

    /// <summary>
    ///     Validates the <c>LedgerJournalEntryContract</c> contract class.
    /// </summary>
    /// <param name="_ledgerJournalEntryContract">
    ///     An instance of the <c>LedgerJournalEntryContract</c> contract class.
    /// </param>
    public static void validateLedgerJournalEntryContract(LedgerJournalEntryContract _ledgerJournalEntryContract)
    {
        if (!_ledgerJournalEntryContract)
        {
            throw error(strFmt("@35", classStr(LedgerJournalEntryContract)));
        }
    
        if (!_ledgerJournalEntryContract.parmLedgerJourEntryLines()
         || _ledgerJournalEntryContract.parmLedgerJourEntryLines().empty())
        {
            throw error("@36");
        }
    }

    protected boolean canRunInNewSession()
    {
        return false;
    }

}

How to pass marked records from grid to sysoperations framework in AX

Controller class

/// <summary>
/// 
/// </summary>
class Sales_UpdateMoDSalesOrderController extends SysOperationServiceController
{
    public static Sales_UpdateMoDSalesOrderController construct(Args _args)
    {
        Sales_UpdateMoDSalesOrderController  controller = new Sales_UpdateMoDSalesOrderController(classStr( Sales_UpdateMoDSalesOrderService ),
                                                                                                        methodStr( Sales_UpdateMoDSalesOrderService, updateMoDSalesOrder ),
            SysOperationExecutionMode::Synchronous);

        controller.parmArgs( _args );

        return controller;
    }

    public static void main(Args _args)
    {
        Set                                     recordSet;
        SalesTable                              salesTable;
        MultiSelectionHelper                    multiselectionHelper;
        Sales_UpdateMoDSalesOrderContract    dataContract;
        Sales_UpdateMoDSalesOrderController  controller;

        controller = Sales_UpdateMoDSalesOrderController::construct( _args );

        // Get marked records from calling form
        if (_args && _args.caller() is FormRun)
        {
            recordSet = new Set(Types::Record);
            multiselectionHelper = MultiSelectionHelper::createFromCaller(_args.caller());
        
            salesTable = multiselectionHelper.getFirst();

            while (salesTable)
            {
                recordSet.add(salesTable);
            
                salesTable = multiselectionHelper.getNext();
            }
        }

        // Put records from calling datasource into dataContract
        dataContract = controller.getDataContractObject();

        if (dataContract is Sales_UpdateMoDSalesOrderContract)
        {
            dataContract.parmRecordCon(recordSet.pack());
        }

        controller.startOperation();
    }
}

Contract class

/// <summary>
/// The data contract for Intercompany update of Mode of delivery
/// </summary>
[
    DataContract,
    SysOperationGroup('GeneralGroup',"@SYS81043",'1',FormArrangeMethod::Vertical)
]
class Sales_UpdateMoDSalesOrderContract implements SysOperationInitializable, SysOperationValidatable
{
    UpsModeOfDelivery upsModeOfDelivery;
    container            recordCon;

    /// <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;
        return isValid;
    }

    /// <summary>
    /// Initailizes the default values to parameters.
    /// </summary>
    public void initialize()
    {
    }

    /// <summary>
    /// Method used to specify the data memmber attribute
    /// </summary>
    /// <param>
    /// <name>parmShipmentDate</name>is used to set and get the shipmentDate
    /// </param>
    [
         DataMember,
         SysOperationGroupMember('GeneralGroup'),
         SysOperationDisplayOrder('1'),
         SysOperationLabelAttribute(literalstr("@Warehouse:UpsModeOfDelivery"))
    ]
    public UpsModeOfDelivery parmUpsModeOfDelivery( UpsModeOfDelivery _upsModeOfDelivery = upsModeOfDelivery )
    {
        upsModeOfDelivery  =  _upsModeOfDelivery;

        return upsModeOfDelivery;
    }

    /// <summary>
    /// Method used to specify the data memmber attribute
    /// </summary>
    /// <param name = "_recordCon"></param>
    /// <returns></returns>
    [DataMemberAttribute, SysOperationControlVisibilityAttribute(false)]
    public container parmRecordCon(container _recordCon = recordCon)
    {
        recordCon = _recordCon;

        return recordCon;
    }

}

Service class

class Sales_UpdateMoDSalesOrderService
{
    /// <summary>
    /// Creates transfer order for from and to wareshouse combination
    /// </summary>
    /// <param name = "_contract">TransferOrderCreateContract from dialog</param>
    public void updateMoDSalesOrder(Sales_UpdateMoDSalesOrderContract _contract)
    {
        Set                     recordSet;
        Common                  record;
        SalesTable              salesTable;
        SetEnumerator           se;
        ModeOfDeliverySetup  smModeOfDeliverySetup;

        // Process records
        if (conLen(_contract.parmRecordCon()) > 0)
        {
            recordSet = Set::create(_contract.parmRecordCon());
            se = recordSet.getEnumerator();
            while (se.moveNext())
            {
                record = se.current();

                switch (record.TableId)
                {
                    case tableNum(SalesTable):
                        salesTable = record;
                        salesTable.DlvMode = _contract.parmUpsModeOfDelivery();

                        info(strFmt("%1 %2", salesTable.SalesId, salesTable.DlvMode));
                        break;

                    default:
                        break;
                }
            }
        }
    }

}

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;
    }

}

Table browser URL in D365FO

Critical Thinking icon icon by Icons8