Thursday, 28 May 2020

Cheque Report

If you want

[ExtensionOf(classStr(CustVendCheque))]
final class CustVendChequeCIT_Extension
{
    public ReportPosition          slipTop1;
    public ReportPosition          slipTop2;
    public ReportPosition          slipHeight;
    public Counter                 specTransLines;

    public AmountCur               totalDiscount;
    public AmountCur               totalAmount;
    public AmountCur               totalPaid;
    public AccountNum              vendAccount;
    public Name                    vendName;
    public int                     checkLines;   

    private str formatField(str _value, int _maxLength = 0, boolean _rightAlign = true)
    {
        str currentVal;
   
        currentVal = _value;
   
        if (_maxLength > 0)
        {
            if (_rightAlign)
            {
                currentVal = strRFix(currentVal, _maxLength);
            }
            else
            {
                currentVal = strLFix(currentVal, _maxLength);
            }
        }
   
        return currentVal;
    }

    public void output(CustVendPaym _custVendPaym)
    {
        // Trying to skip STD code execution by passing 'CustVendPaym' as blank
        //But CustVendPaym  is a ABSTRACT CLASS, so we are unable to re-initilize it to pass it as blank value
        //getting 'VendPaym' in buffer value so intilazed it and passed as parameter it seld
        VendPaym VendPaym = new VendPaym();
        //Getting 'Company not avaiable error', so we assigned curresnt compnay value to it
        VendPaym.ledgerJournalTrans().Company = curExt();

        next output(VendPaym);

        BankNegInstRecipientName    recipientName;
        VendTable                   vendTable;
        CustTable                   custTable;
        Counter                     endLines;
        Counter                     notesLines;
        Counter                     paymentNotesHeaderLinesPrinted;
        Counter                     i;

        LedgerJournalTrans ledgerJournalTrans = _custVendPaym.ledgerJournalTrans();
        BankAccountTable bankAccountTableCurrent;
        LogisticsLocationEntity location;
        LogisticsPostalAddress address;
        BankChequeNum slipChequeNum;
        List paymentNotesList;
        ListEnumerator le;

        str paymentNotesLine;
        ChequeSlipTxt slipText;

        boolean firstCheque = true;
        TmpChequePrintout   tmpChequePrintouttmp;
        chequetmp           ChequeTmp;
        delete_from ChequeTmp;
        delete_from tmpChequePrintouttmp;

        changecompany(ledgerJournalTrans.Company)
        {
            switch (ledgerJournalTrans.AccountType)
            {
                case LedgerJournalACType::Vend:
                    vendTable = VendTable::findByLedgerDimension(ledgerJournalTrans.parmLedgerDimension());

                    //Verify if the remittancelocation on the table is still active; if no remittancelocation exists or is invalid then default
                    ledgerJournalTrans.RemittanceLocation = this.setVendorOutputFieldsRemittanceLocation(ledgerJournalTrans, vendTable);

                    //get the vendors remit to address
                    location = this.setVendorOutputFieldsLocation(ledgerJournalTrans);
                    address = this.setVendorOutputFieldsAddress(location, address, ledgerJournalTrans);
                    ledgerJournalTrans.RemittanceAddress = address.RecId;
                    recipientName = this.setVendorOutputFieldsRecipientName(ledgerJournalTrans);
                    break;

                case LedgerJournalACType::Cust:
                    custTable = CustTable::findByLedgerDimension(ledgerJournalTrans.parmLedgerDimension());
                    address = this.setCustomerOutputFieldsAddress(custTable);
                    recipientName = this.setCustomerOutputFieldsRecipientName(address);
                    break;

                case LedgerJournalACType::Bank:
                    bankAccountTableCurrent = this.setBankAccountTableCurrentOutputFields(ledgerJournalTrans);
                    break;

                case LedgerJournalACType::Ledger:
                    this.initLedgerJournalTransLedger(ledgerJournalTrans);
                    break;

                default:
                    throw error(Error::wrongUseOfFunction(funcName()));
            }
        }

        BankAccountTable bankAccountTable = BankAccountTable::find(accountId);
        BankChequeLayout bankChequeLayout = BankChequeLayout::find(accountId);

        Currency currency = (bankChequeLayout.OtherCurrencies == NoYes::Yes ?
            Currency::find(ledgerJournalTrans.CurrencyCode) :
            Currency::find(bankAccountTable.CurrencyCode));

        AmountCur amountCur = ledgerJournalTrans.AmountCurDebit - ledgerJournalTrans.AmountCurCredit;

        if (TaxWithholdParameters_IN::checkTaxParameters())
        {
            AmountCur taxAmount;

            if (ledgerJournalTrans.OffsetLedgerDimension)
            {
                taxAmount = TaxWithholdUncommitted_IN::getActualTaxAmountForVoucher(ledgerJournalTrans.ledgerJournalTable().TableId, ledgerJournalTrans.ledgerJournalTable().RecId, ledgerJournalTrans.Voucher, false, '', ledgerjournalTrans.RecId);
            }
            else
            {
                taxAmount = TaxWithholdUncommitted_IN::getActualTaxAmountForVoucher(ledgerJournalTrans.ledgerJournalTable().TableId, ledgerJournalTrans.ledgerJournalTable().RecId, ledgerJournalTrans.Voucher, false);
            }

            ledgerJournalTrans.AmountCurDebit += taxAmount;
            amountCur += taxAmount;
        }

        if (TaxWithholdParameters_IN::checkTaxParameters() || TaxParameters::checkTaxParameters_IN())
        {
            AmountCur feeAmountTotal;
            VendPaymFee vendPaymFeeLoc;
            CustVendPaymJournalFee custVendPaymJournalFeeLoc;
            AmountCur feeAmount;

            while select FeeId, FeeValue from custVendPaymJournalFeeLoc
            where custVendPaymJournalFeeLoc.RefRecId == ledgerJournalTrans.RecId
            {
                select firstonly vendPaymFeeLoc
                where vendPaymFeeLoc.FeeId == custVendPaymJournalFeeLoc.FeeId
                    && (vendPaymFeeLoc.TaxWithholdFeeType_IN == TaxWithholdFeeType_IN::Interest
                        || vendPaymFeeLoc.TaxWithholdFeeType_IN == TaxWithholdFeeType_IN::Others);

                if (vendPaymFeeLoc)
                {
                    feeAmountTotal -= custVendPaymJournalFeeLoc.FeeValue;
                }
            }

            feeAmount = feeAmountTotal;
            //AmountCur feeAmount = this.calculatePaymentFee_IN(ledgerJournalTrans.RecId);
            amountCur += feeAmount;
            ledgerJournalTrans.AmountCurDebit -= feeAmount;
        }

        if (ledgerJournalTrans.BankNegInstRecipientName)
        {
            recipientName = ledgerJournalTrans.BankNegInstRecipientName;
        }

        if (!recipientName && (ledgerJournalTrans.AccountType == LedgerJournalACType::Vend || ledgerJournalTrans.AccountType == LedgerJournalACType::Cust))
        {
            recipientName = ledgerJournalTrans.LedgerDimensionName;
        }

        BankChequeTable::setChequeStatus(
            accountId,
            chequeNum,
            ChequeStatus::Payment,
            ledgerJournalTrans.TransDate,
            ledgerJournalTrans.Voucher,
            CustVendCheque::ledgerJournalACType2RecipientType(ledgerJournalTrans.AccountType),
            ledgerJournalTrans.Company,
            ledgerJournalTrans.parmAccount(),
            ledgerJournalTrans.CurrencyCode,
            amountCur,
            recipientName,
            ledgerJournalTrans.RemittanceAddress,
            ledgerJournalTrans.TableId,
            ledgerJournalTrans.RecId);

        BankChequeTable bankChequeTable = BankChequeTable::find(accountId, chequeNum);
        this.insertBankPaymentTrans(ledgerJournalTrans, _custVendPaym);

        Counter totalBankChequePaymTransLines = this.getInvoiceCount(bankChequeTable);

        CustVendChequeSlipTextCalculator slipTextCalculator = this.initCustVendChequeSlipTextCalculator(bankChequeLayout);

        Counter slipLines = slipTextCalculator.calculateSlipTextLines();

        Counter startLines = 0;
        Counter bankChequePaymTransLines = 0;

        if (slipLines < slipTextCalculator.getMinimumSlipLines(bankChequeLayout.ChequeFormType))
        {
            totalBankChequePaymTransLines = 0;

            if (this.shouldResetPaymentNotes(bankChequeLayout.ChequeFormType))
            {
                ledgerJournalTrans.PaymentNotes = '';
            }
        }

        CustVendPDCRegister custVendPDCRegister; 

        select firstonly MaturityDate from custVendPDCRegister
            where custVendPDCRegister.LedgerJournalTrans == ledgerJournalTrans.RecId;

        PDCMaturityDate maturityDate =  custVendPDCRegister.MaturityDate && CustVendPDCManager::allowPostDatedChecks(ledgerJournalTrans) ? custVendPDCRegister.MaturityDate : ledgerJournalTrans.TransDate;


        while (bankChequePaymTransLines < totalBankChequePaymTransLines || totalBankChequePaymTransLines == 0)
        {
            tmpChequePrintout.clear();
            this.initTmpChequePrintout(
                ledgerJournalTrans.AccountType,
                address,
                location,
                vendTable,
                custTable,
                bankAccountTableCurrent,
                ledgerJournalTrans.BankNegInstRecipientName,
                ledgerJournalTrans.RecId,
                bankChequeLayout.ChequeFormType,
                slipTextCalculator,
                true,
                true);

            if (firstCheque)
            {
                firstCheque = false;

                this.initBankDetails(
                    accountId,
                    bankChequeLayout,
                    bankAccountTable);

                this.setChequeAmount(
                    amountCur,
                    currency,
                    bankChequeLayout,
                    vendTable,
                    custTable);

                this.setSignatures(bankChequeLayout, amountCur);

                slipChequeNum = chequeNum;
            }
            else
            {
                this.setBlankCheque(ledgerJournalTrans);
                tmpChequePrintout.Void = NoYes::Yes;
                tmpChequePrintout.BankCopySignatureText = "@SYS53120";
                tmpChequePrintout.BankCopyCustomWatermark = "@SYS53120";
                tmpChequePrintout.AccountId = accountId;

                slipLines = this.adjustSlipTextLinesForAdditionalCheques(slipLines);
            }

            tmpChequePrintout.ChequeNum = chequeNum;
            tmpChequePrintout.TransDate = ledgerJournalTrans.TransDate;
            tmpChequePrintout.MaturityDate = maturityDate;

            if ((slipTextCalculator.getNumOfSlips() > 0 && bankChequeLayout.ChequeFormType != ChequeFormType::FRStyle)
                || (bankChequeLayout.UseGER == NoYes::Yes && bankChequeLayout.GERNumberOfSlipTxtLines > 0))
            {
                [slipText, bankChequePaymTransLines, endLines] = slipTextCalculator.fillSlipText(
                    bankChequeTable,
                    startLines,
                    slipLines,
                    totalBankChequePaymTransLines,
                    bankChequeLayout.ChequeFormType);

                tmpChequePrintout.SlipTxt = slipText;
                tmpChequePrintout.DiscountTaken = slipTextCalculator.totalDiscount;
                tmpChequePrintout.TotalPaid = slipTextCalculator.totalPaid;
                tmpChequePrintout.TotalAmount = slipTextCalculator.totalAmount;
                //Created and updated total fields in BankChequeTable, To fetch these vaules when running report from CHECKS.
                BankChequeTable bankChequeTableLoc = BankChequeTable::find(accountId, chequeNum);
                if(bankChequeTableLoc)
                {
                    ttsbegin;
                    bankChequeTableLoc.selectforupdate(true);
                    bankChequeTableLoc.TotalAmount     =   tmpChequePrintout.TotalAmount;
                    bankChequeTableLoc.TotalDiscount   =   tmpChequePrintout.DiscountTaken;
                    bankChequeTableLoc.TotalPaid       =   tmpChequePrintout.TotalPaid;
                    bankChequeTableLoc.update();
                    ttscommit;
                }

                if (this.shouldPrintPaymentNotes(ledgerJournalTrans, bankChequePaymTransLines, totalBankChequePaymTransLines))
                {
                    notesLines = this.notesLines(ledgerJournalTrans.PaymentNotes);

                    if (notesLines <= endLines - 1)
                    {
                        tmpChequePrintout.SlipTxt += this.formatSlipText(ledgerJournalTrans);
                        endLines -= notesLines;
                    }
                    else
                    {
                        if (endLines > 1)
                        {
                            tmpChequePrintout.SlipTxt += strRep('\n', endLines - 1);
                            endLines = 1;
                        }

                        this.insertTmpChequePrintout();
                        tmpChequePrintout.clear();

                        //Printing Payment notes but the payment notes won't fit on one check, spread it out to several checks
                        paymentNotesList = strSplit(ledgerJournalTrans.PaymentNotes, '\n');
                        notesLines = paymentNotesList.elements();
                        le = paymentNotesList.getEnumerator();

                        while (notesLines > 0)
                        {
                            endLines = slipLines;
                            this.initTmpChequePrintout(
                                ledgerJournalTrans.AccountType,
                                address,
                                location,
                                vendTable,
                                custTable,
                                bankAccountTableCurrent,
                                ledgerJournalTrans.BankNegInstRecipientName,
                                ledgerJournalTrans.ledgerJournalTable().RecId,
                                bankChequeLayout.ChequeFormType,
                                slipTextCalculator,
                                false,
                                false);

                            this.setBlankCheque(ledgerJournalTrans);

                            tmpChequePrintout.ChequeNum = chequeNum;
                            tmpChequePrintout.Void = NoYes::Yes;
                            tmpChequePrintout.BankCopySignatureText = "@SYS53120";
                            tmpChequePrintout.BankCopyCustomWatermark = "@SYS53120";
                            tmpChequePrintout.AccountId = accountId;
                            tmpChequePrintout.TransDate = ledgerJournalTrans.TransDate;

                            tmpChequePrintout.MaturityDate = maturityDate;

                            paymentNotesHeaderLinesPrinted = 0;

                            if (this.shouldUpdateSlipTextForChequePrinting(bankChequeLayout.ChequeFormType))
                            {
                                tmpChequePrintout.SlipTxt = strFmt('%1 %2\n\n', "@SYS22495", slipChequeNum);
                                paymentNotesHeaderLinesPrinted = 2;
                                endLines -= 2;
                            }

                            for (i = 0; i < slipLines - paymentNotesHeaderLinesPrinted; i++)
                            {
                                le.moveNext();
                                paymentNotesLine = le.current();

                                tmpChequePrintout.SlipTxt += paymentNotesLine;

                                if (endLines != 1)
                                {
                                    tmpChequePrintout.SlipTxt += '\n';
                                }

                                notesLines--;

                                endLines -= 1;

                                if (notesLines <= 0 || endLines == 0)
                                {
                                    break;
                                }
                            }

                            if (endLines > 1)
                            {
                                tmpChequePrintout.SlipTxt += strRep('\n', endLines - 1);
                                endLines = 1;
                            }

                            this.insertTmpChequePrintout();
                            tmpChequePrintout.SlipTxt = '';

                            if (notesLines <= 0)
                            {
                                return;
                            }
                        }
                    }

                    if (endLines > 1)
                    {
                        tmpChequePrintout.SlipTxt += strRep('\n', endLines - 1);
                        endLines = 1;
                    }
                }
                else
                {
                    if (endLines > 1)
                    {
                        tmpChequePrintout.SlipTxt += strRep('\n', endLines - 1);
                        endLines = 1;
                    }
                }
            }
            else
            {
                totalBankChequePaymTransLines = -1;
            }

            this.insertTmpChequePrintout();
            startLines = bankChequePaymTransLines;

            totalBankChequePaymTransLines = this.getRemainingTotalBankChequePaymentTransLines(totalBankChequePaymTransLines);
        }
    }

}

Thursday, 23 April 2020

Refreshing the caller form in d365

 public void close()
    {   
        next close();
        FormRun calledFomr = @this.localFormRun;
        Formdatasource  callingformdatasource = calledFomr.dataSource();
        callingformdatasource.refresh();
        callingformdatasource.reread();
        callingformdatasource.research(true);
    }

Sunday, 19 April 2020

AX7/D365/Operations: Data entities export data error

Error1


 Exception:

While exporting data from local VM of Dynamics 365 for Operations, you might get an error if the Azure storage emulator is not running.
Microsoft.WindowsAzure.Storage.StorageException: Unable to connect to the remote server —> System.Net.WebException: Unable to connect to the remote server —> System.Net.Sockets.SocketException: No connection could be made because the target machine actively refused it.

Resolution:

You can start the Azure storage emulator by following the steps below:
  1. On OneBox VM, run command prompt as administrator.
  2. Navigate to “C:\Program Files (x86)\Microsoft SDKs\Azure\Storage Emulator\”
  3. Run “AzureStorageEmulator.exe start”
This should resolve the issue reported above which surfaces while exporting data through data entities in Dynamics 365 for Operations.
Emulator

Thursday, 16 April 2020

Change Tracking For Entity Export

When we are trying to change track  the entity it is giving error like sql is not set to change tracking. Then we need to execute below code

AXDBECO - AX data base name

ALTER DATABASE AXDBECO
SET CHANGE_TRACKING = ON
(CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON)

Tuesday, 31 March 2020

squish up the address using expressions in ssrs

=Replace(First(Fields!CompanyAddress.Value, "SalesInvoiceHeaderFooterDS")+"  Phone:  "+First(Fields!CompanyPhone.Value, "SalesInvoiceHeaderFooterDS"), Chr(10), ", ")

Tuesday, 25 February 2020

Multi-Language Tips in SSRS

Multi-Language Tips in SSRS

In looking through the forums at Microsoft, I often see questions pertaining to the formats of dates, number and currency in a report.

In my latest gig with a multinational travel management company, I have had a lot of exposure to the multi-language/culture formatting.

I will cover multiple languages in a future blog, and today focus on the formatting of dates, numbers, and currency values.

To start with, Microsoft has a good page explaining each of the terms used by them to customize the user interface to the user’s regional setting:

http://www.microsoft.com/globaldev/getwr/steps/wrg_lclmdl.mspx


SSRS handles formatting the display of dates, numbers and currency by adding a property to a report and textbox: Language. This is misleading since it really does not change the language except on the verbose date formats. For example, changing a number from the US format: 1,234.56 to a French format: 1 234,56 really isn’t a language change, just a locale change, according to the link above.

The language property displays the locale description, and behind that, the locale code.
For example, the property displays English (United States), and the value behind that is en-US.

I found a good list of these locale codes here:

http://msdn2.microsoft.com/en-us/library/system.globalization.cultureinfo.aspx

I put these into a database table, so that I can use them as a parameter in my reports.

In the reports that I create, I have a dataset called Locales in which I call a stored procedure that returns the locale code and the description, sorted by description.

I then create a parameter called Locale. This is a String parameter that is setup to read available values from the Locales dataset, with the code as the value and the description as the label.

Depending on the report target audience, I set a non-queried default value, usually en-US.

In the report properties window (NOT the properties that show up when you select the menu items: Report, Properties. You have to click on the outlying yellowish area of the report designer and press F4), I set the language as an expression: =Parameters!Locale.Value

Now you should format all of the textboxes that contain dates, numbers and currencies.

You should use the standard formatting strings rather than hardcoding a format into the format property. For example, for a short date format, use d rather than d/M/yy, as this will always format the date d/M/yy no matter what you select for the language property.

Here are some standard formatting codes:

Date/Time: http://msdn2.microsoft.com/en-us/library/az4se3k1(VS.71).aspx
Numeric: http://msdn2.microsoft.com/en-us/library/dwhawy9k(VS.71).aspx

Note that some of the formatting strings are “InvariantCulture.” This means that they will not be affected by the language property.

NOTE: When changing locales on currency fields, all this does is change the formatting of the displayed number. It does NOT do any currency conversion. For this reason, I usually do not format currencies as currency, but as a N2 (Numeric, 2 decimal places) and then display the ISO currency code (USD, EUR, JPY, etc) to indicate which currency is being displayed. I also use a separate parameter to select the currency based on this ISO code. Since the ISO currency codes and the Microsoft locale list do not tie in any way, it makes it a lot more difficult to use the language properties to format currency changes.

The way parameters are displayed is controlled by the browser regional settings. There is no way in reporting services to control that. However, the regional settings on a browser should be set to the way the user likes to see the dates, numbers, etc, so you should not have to worry about this setting.

Well, that wraps up this tip. I hope that someone out there benefits from this. I have done a lot of research, as well as a lot of work on my own, to put this together. I use this extensively on existing reports and it works very well.

Sunday, 5 January 2020

Sysoperation Framework - Query

Contract:
[ DataContractAttribute]
class CheckContract implements SysOperationValidatable
{
NoYes checkProduct, checkProbity, checkTransport;
SalesTable salesTable;
str packedQuery;
[
DataMemberAttribute,
AifQueryTypeAttribute(‘_packedQuery’, ”)//queryStr(SalesTable))
]
public str parmPackedQuery(str _packedQuery = packedQuery)
{
packedQuery = _packedQuery;
return packedQuery;
}
public void initQuery()
{
Query newQuery;
QueryBuildDataSource qbds;
QueryBuildRange qbr;
newQuery = new Query(queryStr(SalesTable));
qbds = newQuery.dataSourceTable(tableNum(SalesTable));
qbr = qbds.addRange(fieldNum(SalesTable, SalesId));
if(this.parmSalesTable().SalesId)
{
qbr.value(this.parmSalesTable().SalesId);
qbr.status(1);//Lock query range
}
this.setQuery(newQuery);
}
public Query getQuery()
{
return
new Query(SysOperationHelper::base64Decode(packedQuery));
}
public void setQuery(Query _query)
{
packedQuery = SysOperationHelper::base64Encode(_query.pack());
}
[
DataMemberAttribute(‘CheckProduct’),
SysOperationLabelAttribute(‘Check product’),
SysOperationDisplayOrderAttribute(‘1’),
SysOperationHelpTextAttribute(literalStr(“If yes, product logic will be executed.”))
]
public NoYes parmCheckProduct(NoYes _checkProduct = checkProduct)
{
checkProduct = _checkProduct;
return checkProductCompilance;
}
[
DataMemberAttribute(‘checkProbity’),
SysOperationLabelAttribute(‘Check probity’),
SysOperationDisplayOrderAttribute(‘2’),
SysOperationHelpTextAttribute(literalStr(“If yes, probity logic will be executed.”))
]
public NoYes parmCheckProbity(NoYes _checkProbity = checkProbity)
{
checkProbity = _checkProbity;
return checkProbity;
}
[
DataMemberAttribute(‘CheckTransport’),
SysOperationLabelAttribute(‘Check transport’),
SysOperationDisplayOrderAttribute(‘3’),
SysOperationHelpTextAttribute(literalStr(“If yes, transportlogic will be executed.”))
]
public NoYes parmCheckTransport(NoYes _checkTransport = checkTransport)
{
checkTransport = _checkTransport;
return checkTransport;
}
public boolean validate()
{
boolean isValid = true;
return isValid;
}
[
DataMemberAttribute(‘SalesOrder’),
SysOperationControlVisibilityAttribute(false),
SysOperationDisplayOrderAttribute(‘4’),
SysOperationHelpTextAttribute(literalStr(“SalesOrder”))
]
public SalesTable parmSalesTable(SalesTable _salesTable = salesTable)
{
salesTable = _salesTable;
return salesTable;
}
}
Controller:
[SysOperationJournaledParametersAttribute(true)]
class checkController extends SysOperationServiceController
{
Common callerRecord;
void new()
{
super();
this.parmClassName(classStr(CheckService));
this.parmMethodName(methodStr(CheckService, process));
this.parmDialogCaption(‘check’);
}
public static void main(Args _args)
{
CheckContract contract;
CheckController controller;
controller = new CheckController();
controller.parmShowDialog(true);
contract = controller.getDataContractObject();
contract.parmSalesTable(SalesTable::findRecId(_args.record().RecId));
contract.initQuery();
controller.startOperation();
}
public LabelType parmDialogCaption(LabelType _dialogCaption = “”)
{
LabelType caption;
caption = “check”;
return caption;
}
private void initFromCaller()
{
SalesTable salesTable;
}
public boolean canGoBatch()
{
return true;
}
public Common parmCallerRecord(Common _callerRecord = callerRecord)
{
callerRecord = _callerRecord;
return callerRecord;
}
/// Refreshes the calling form data source.
protected void refreshCallerRecord()
{
FormDataSource callerDataSource;
if (this.parmCallerRecord() && this.parmCallerRecord().dataSource())
{
callerDataSource = this.parmCallerRecord().dataSource();
callerDataSource.research(true);
}
}
}
Service:
using System.Xml.Linq;
[SRSReportQueryAttribute(queryStr(SalesTable))]
class CheckService extends SysOperationServiceBase
{
static XElement generateXML(Name _jurisdictionId, ItemId _itemId, ItemId _itemIdBOM2, Description _attributeValue)
{
XElement XMLElement =  new XElement(“Check”,
new XElement(“Jurisdiction ID”, _jurisdictionId),
new XElement(“Item Id”, _itemId),
new XElement(“Item Id”, _itemIdBOM2),
new XElement(“Attribute value”,_attributeValue));
return XMLElement;
}
public void process(CheckContract _contract)
{
NoYes checkProduct, checkProbity, checkTransport;
SalesTable callerSalesTable, salesTable;
QueryRun queryRun;
checkProduct = _contract.parmCheckProduct();
checkProbity = _contract.parmCheckProbity();
checkTransport = _contract.parmCheckTransport();
callerSalesTable = _contract.parmSalesTable();
try
{
queryRun = new queryRun(_contract.getQuery());
while(queryRun.next())
{
salesTable = queryRun.get(tableNum(SalesTable));
//logic
}
}
catch (Exception::Error)
{
retry;
}
}

}