Pending Vendor Invoice Data Import Utility

Recently, I had to develop a data import utility as a part of one of the projects I was working on. One of the subparts of the data import utility is the Pending Vendor Invoices utility. The architecture of the data import utility is as follows:

  • Staging: Data is first import into staging table, where It can be viewed, validated or cleared by the user
  • Validate: Data can be validated in order to ensure the correctness of data
  • Import: Data in the staging tables are processed in the AX tables

I am sharing the Pending Vendor Invoice Import utility here.

Pending Vendor Invoice Import Utility UI:

Pending Vendor Invoice Import Utility UI

Pending Vendor Invoice Import Utility Staging Class:

Pending Vendor Invoice Import Utility Staging ClassPending Vendor Invoice Import Utility Validation Class:

Pending Vendor Invoice Import Utility Validation Class

Pending Vendor Invoice Import Utility Import Class:

Pending Vendor Invoice Import Utility Import Class

Code to Import:

private void ProcessData_Order()

{

SL_StagingPurchInvoice  stagingInvoice,stagingInvoiceCheck;

InventDimId inventDimId;

int         Purchcounter,counter,header;

int64       purchLineRowCount,QuantityLeft;

str         parmId,invoiceAccount,orderAccount,deliveryName;

TradeLineRefId  tableRefId;

 

try

{

header=0;

Purchcounter=0;

ttsBegin;

 

while select sum(Quantity),maxOf(FromDate),maxof(unitcost) from stagingInvoice

group by stagingInvoice.InvoiceNumber,stagingInvoice.PurchaseOrderNumber,stagingInvoice.Site,stagingInvoice.Warehouse,stagingInvoice.productnumber,stagingInvoice.Color,stagingInvoice.Size

where stagingInvoice.RecordStatus == SL_Status::Created

{

QuantityLeft = stagingInvoice.Quantity;

purchTable = PurchTable::find(stagingInvoice.PurchaseOrderNumber);

 

if (header == 0)

{

select recid from vendInvoiceInfoTable where vendInvoiceInfoTable.PurchId == purchTable.PurchId && vendInvoiceInfoTable.Num == stagingInvoice.InvoiceNumber;

if (!vendInvoiceInfoTable.recid)

{

vendInvoiceInfoTable.clear();

vendInvoiceInfoTable.initFromPurchTable(purchTable);

vendInvoiceInfoTable.DocumentOrigin         = DocumentOrigin::Manual;

vendInvoiceInfoTable.CurrencyCode           = purchTable.CurrencyCode;

vendInvoiceInfoTable.DeliveryName           = purchTable.DeliveryName;

vendInvoiceInfoTable.Num                    = stagingInvoice.InvoiceNumber ;

vendInvoiceInfoTable.PurchName              = purchTable.PurchName;

vendInvoiceInfoTable.VendInvoiceSaveStatus  = VendInvoiceSaveStatus::Pending;

vendInvoiceInfoTable.TransDate              = stagingInvoice.FromDate;

vendInvoiceInfoTable.FixedDueDate           = stagingInvoice.FromDate;

vendInvoiceInfoTable.DocumentDate           = stagingInvoice.FromDate;

vendInvoiceInfoTable.Hold                   = NoYes::Yes;

vendInvoiceInfoTable.insert();

header++;

}

}

inventDimId = this.getInventDim(stagingInvoice.Color, stagingInvoice.Size,stagingInvoice.Warehouse,stagingInvoice.Site);

select count(RecId) from purchline where purchLine.PurchId == purchTable.PurchId && purchLine.InventDimId == inventDimId && purchLine.ItemId == stagingInvoice.productnumber;

purchLineRowCount = purchline.RecId;

 

counter=0;

 

while select purchline where purchLine.PurchId == purchTable.PurchId && purchLine.InventDimId == inventDimId && purchLine.ItemId == stagingInvoice.productnumber

{

vendInvoiceInfoLine = VendInvoiceInfoLine::findByPurchLineRefRecId(purchline.RecId);

counter++;

if (!vendInvoiceInfoLine.RecId)

{

if (purchline.QtyOrdered != purchline.calcPendingQtyPurch())

{

vendInvoiceInfoLine.clear();

vendInvoiceInfoLine.initFromPurchLine(purchLine);

vendInvoiceInfoLine.DeliveryName    = vendInvoiceInfoTable.deliveryName;

vendInvoiceInfoLine.ParmId          = vendInvoiceInfoTable.parmId;

vendInvoiceInfoLine.TableRefId      = vendInvoiceInfoTable.tableRefId;

vendInvoiceInfoLine.CurrencyCode    = purchLine.CurrencyCode;

vendInvoiceInfoLine.DeliveryName    = purchLine.DeliveryName;

vendInvoiceInfoLine.LineNum         = purchLine.LineNumber;

vendInvoiceInfoLine.InvoiceAccount  = vendInvoiceInfoTable.invoiceAccount;

vendInvoiceInfoLine.InventDimId     = inventDimId;

vendInvoiceInfoLine.OrderAccount    = vendInvoiceInfoTable.orderAccount;

vendInvoiceInfoLine.ItemId          = purchline.ItemId;

vendInvoiceInfoLine.InventTransId   = purchline.InventTransId;

vendInvoiceInfoLine.DocumentOrigin  = DocumentOrigin::Manual;

vendInvoiceInfoLine.PurchPrice      = stagingInvoice.UnitCost;

vendInvoiceInfoLine.PurchLineRecId  = purchLine.RecId;

vendInvoiceInfoLine.OrigPurchId     = purchTable.PurchId;

 if (purchline.calcPendingQtyPurch() == 0)

{

if (QuantityLeft == purchline.QtyOrdered)

{

QuantityLeft                        = QuantityLeft – purchline.QtyOrdered – purchline.invoicedInTotal();

vendInvoiceInfoLine.ReceiveNow      = purchline.QtyOrdered – purchline.invoicedInTotal();

}

else if (QuantityLeft < purchline.QtyOrdered)

{

vendInvoiceInfoLine.ReceiveNow      = QuantityLeft;

QuantityLeft                        = QuantityLeft – purchline.QtyOrdered – purchline.invoicedInTotal();

 

}

else if (QuantityLeft > purchline.QtyOrdered)

{

if (counter == purchLineRowCount)

{

vendInvoiceInfoLine.ReceiveNow      = QuantityLeft + purchline.calcPendingQtyPurch();

 

}

else

{

vendInvoiceInfoLine.ReceiveNow      = purchline.QtyOrdered – purchline.invoicedInTotal();

QuantityLeft                        = QuantityLeft – purchline.QtyOrdered – purchline.invoicedInTotal();

}

}

}

else

{

if (QuantityLeft == purchline.QtyOrdered)

{

QuantityLeft                        = QuantityLeft – purchline.QtyOrdered – purchline.invoicedInTotal();

vendInvoiceInfoLine.ReceiveNow      = purchline.QtyOrdered – purchline.invoicedInTotal();

}

else if (QuantityLeft < purchline.QtyOrdered)

{

if (purchline.calcPendingQtyPurch() == 0)

{

vendInvoiceInfoLine.ReceiveNow      = QuantityLeft;

QuantityLeft = 0;

}

else if (purchline.calcPendingQtyPurch() >0)

{

vendInvoiceInfoLine.ReceiveNow  = purchline.QtyOrdered – purchline.calcPendingQtyPurch();

QuantityLeft =0;

}

}

else if (QuantityLeft > purchline.QtyOrdered)

{

if (counter == purchLineRowCount)

{

vendInvoiceInfoLine.ReceiveNow      = QuantityLeft+purchline.calcPendingQtyPurch();

 

}

else

{

vendInvoiceInfoLine.ReceiveNow      = purchline.QtyOrdered – purchline.invoicedInTotal();

QuantityLeft                        = QuantityLeft – purchline.QtyOrdered;

}

}

if (counter != purchLineRowCount && vendInvoiceInfoLine.ReceiveNow > purchline.QtyOrdered)

{

vendInvoiceInfoLine.ReceiveNow = purchline.QtyOrdered;

                               }

}

vendInvoiceInfoLine.LineAmount = stagingInvoice.UnitCost*vendInvoiceInfoLine.ReceiveNow;

vendInvoiceInfoLine.insert();

Purchcounter++;

if (QuantityLeft<=0) break;

}

}

}

}

while select forUpdate stagingInvoiceCheck where stagingInvoiceCheck.RecordStatus == SL_Status::Created

{

stagingInvoiceCheck.RecordStatus = SL_Status::Completed;

stagingInvoiceCheck.update();

}

ttsCommit;

}

catch(Exception::Error)

{

Purchcounter=0;

ttsBegin;

while select forUpdate stagingInvoiceCheck where stagingInvoiceCheck.RecordStatus == SL_Status::Created

{

stagingInvoiceCheck.RecordStatus = SL_Status::Completed;

stagingInvoiceCheck.update();

}

ttsCommit;

 

info(strFmt(‘%1′,Exception::Error));

ttsAbort;

}

info(strFmt(‘%1 Lines Processed Created’,Purchcounter));

}

 

 


Developing a form using Date Effective framework

Introduction:

In order to cater the scenarios where organizations need to keep track of or analyze data which keeps changing over time, Date effective framework was introduced in Microsoft Dynamics AX 2012.

One of the main requirements of an organization could be to keep track of an exchange rate.  What is the exchange rate today? What was the exchange rate on the day a particular invoice was posted? What was the exchange rate a month ago? In order to cater such needs of an organization, Date effective framework is used which provides ease and consistency for date effective scenarios.

Terminology:

Term Definition
Valid Time State Table A table that tracks the records over time using the fields ValidFrom and ValidTo
Valid Time State Key An Alternate key that enforces the valid time state semantics
Gap A condition in which a record can have a gap between its’ certain date ranges
Overlap A condition where a record has more than one occurrence
Current Record A record effective at the present time
Past Record A record effective in an earlier time
Future Record A record effective in a future time
Create New Time Period Creates a new time period updating the date effective table and closing the initial record
Effective Based When updating a valid time state table in Effective Based mode, if the record being updated is a current record, the record is updated in CreateNewTimePeriod mode. If the record being updated is a future record, the record is updated in Correction mode. If the record is a past record, the record cannot be updated. 

Tutorial – Developing a form using Date Effective fram

Introduction:

In order to cater the scenarios where organizations need to keep track of or analyze data which keeps changing over time, Date effective framework was introduced in Microsoft Dynamics AX 2012.

One of the main requirements of an organization could be to keep track of an exchange rate.  What is the exchange rate today? What was the exchange rate on the day a particular invoice was posted? What was the exchange rate a month ago? In order to cater such needs of an organization, Date effective framework is used which provides ease and consistency for date effective scenarios.

Terminology:

Term Definition
Valid Time State Table A table that tracks the records over time using the fields ValidFrom and ValidTo
Valid Time State Key An Alternate key that enforces the valid time state semantics
Gap A condition in which a record can have a gap between its’ certain date ranges
Overlap A condition where a record has more than one occurrence
Current Record A record effective at the present time
Past Record A record effective in an earlier time
Future Record A record effective in a future time
Create New Time Period Creates a new time period updating the date effective table and closing the initial record
Effective Based When updating a valid time state table in Effective Based mode, if the record being updated is a current record, the record is updated in CreateNewTimePeriod mode. If the record being updated is a future record, the record is updated in Correction mode. If the record is a past record, the record cannot be updated. 

Tutorial – Developing a form using Date Effective framework

Step 1:

Create a new form and add the date effective table SL_ExchangeRate in its data source. Select the CurrencyPairIdx in the index property of the form data srouce SL_ExchangeRate.

Creating a date effective form

Creating a date effective form

Step 2:

Add a grid in the design node of the form and set its data source to SL_ExchangeRate

Here is the data displayed in the form. It can be noticed that data which is effective as of date is only displayed in the form grid.

Date effective framework


Date effective framework – Retrieve Data using Query

Introduction:

In order to cater the scenarios where organizations need to keep track of or analyze data which keeps changing over time, Date effective framework was introduced in Microsoft Dynamics AX 2012.

One of the main requirements of an organization could be to keep track of an exchange rate.  What is the exchange rate today? What was the exchange rate on the day a particular invoice was posted? What was the exchange rate a month ago? In order to cater such needs of an organization, Date effective framework is used which provides ease and consistency for date effective scenarios.

Terminology:

Term Definition
Valid Time State Table A table that tracks the records over time using the fields ValidFrom and ValidTo
Valid Time State Key An Alternate key that enforces the valid time state semantics
Gap A condition in which a record can have a gap between its’ certain date ranges
Overlap A condition where a record has more than one occurrence
Current Record A record effective at the present time
Past Record A record effective in an earlier time
Future Record A record effective in a future time
Create New Time Period Creates a new time period updating the date effective table and closing the initial record
Effective Based When updating a valid time state table in Effective Based mode, if the record being updated is a current record, the record is updated in CreateNewTimePeriod mode. If the record being updated is a future record, the record is updated in Correction mode. If the record is a past record, the record cannot be updated. 

Tutorial – Retrieve Data using Query

Retrieving Data:

Current Get current exchange rate, as in today’s exchange rate
Specific Date Get exchange rate of a specific date such as yesterday’s exchange rate
Date Range Get exchange rate active within the specified date range e.g. valid from January and valid till March

Date Effective framework Methods:

Microsoft Dynamics Ax has introduced some methods in the Query API for the Date effective framework. The methods are mentioned below:

Query Description ValidTimeStateFieldType
Query::ValidTimeStateAsOfDate(Date)  Query records that are effective at the present Date  Date 
Query::ValidTimeStateDateRange(fromdate, todate)  Query records that are effective during the date range: fromdate and todate  Date 
Query::ValidTimeStateAsOfDatetime(DateTime)  Query records that are effective at the present Date and Time  UtcDateTime 
Query::ValidTimeStateDateTimeRange(fromDateTime, toDateTime)  Query records that are effective during  the Datime and Time range:fromdatetime and todatetime

 

UtcDateTime 

 

The following code sample is used to query the data that is effective on 1/1/2014:

static void ValidTimeStateAsOfDate (Args _args)

{

Query query;

QueryBuildDataSource queryBuildDataSource;

QueryRun queryRun;

Date currdate = 1\1\2014;

SL_ExchangeRate exchangeRate;

query = new Query();

queryBuildDataSource = query.addDataSource(tableName2id(“SL_ExchangeRate “));

query.ValidTimeStateAsOfDate(currdate);

queryRun = new QueryRun(query);

while (queryRun.next())

{

exchangeRate = queryRun.get(tableName2id(“SL_ExchangeRate “));

info(strFmt(“%1, %2, %3 %4″, ExchangeRate.CurrencyPair, ExchangeRate.exchangeRate, exchangeRate.ValidFrom, exchangeRate.ValidTo));

}

}

 

 

The following code samples is used to query the data that is effective during 2014-01-01T00:00:00 and 2014-01-31T00:00:00:

static void validTimeStateDateTimeRange (Args _args)

{

Query query;

QueryBuildDataSource queryBuildDataSource;

QueryRun queryRun;

UtcDateTime fromDateTime = 2014-01-01T00:00:00;

utcDateTime toDateTime = 2014-01-31T00:00:00;

SL_ExchangeRate exchangeRate;

query = new Query();

queryBuildDataSource = query.addDataSource(tableName2id(“SL_ExchangeRate “));

query. validTimeStateDateTimeRange (fromDateTime, toDateTime);

queryRun = new QueryRun(query);

while (queryRun.next())

{

exchangeRate = queryRun.get(tableName2id(“SL_ExchangeRate “));

info(strFmt(“%1, %2, %3 %4″, ExchangeRate.CurrencyPair, ExchangeRate.exchangeRate, exchangeRate.ValidFrom, exchangeRate.ValidTo));

}

}

This was the second part of the date effective tutorial. If you are interested in reading the first part of the date effective framework tutorial, please follow the link: 

http://thedynamicsblog.com/date-effective-framework-creating-a-new-table-with-a-valid-time-state-key/

The final and the last part of the date effective framework tutorial will be posted shortly.


Date effective framework – Creating a new table with a valid time state key

Introduction:

In order to cater the scenarios where organizations need to keep track of or analyze data which keeps changing over time, Date effective framework was introduced in Microsoft Dynamics AX 2012.
One of the main requirements of an organization could be to keep track of an exchange rate. What is the exchange rate today? What was the exchange rate on the day a particular invoice was posted? What was the exchange rate a month ago? In order to cater such needs of an organization, Date effective framework is used which provides ease and consistency for date effective scenarios.

Terminology:
Term Definition

  • Valid Time State Table A table that tracks the records over time using the fields ValidFrom and ValidTo
  • Valid Time State Key An Alternate key that enforces the valid time state semantics
  • Gap A condition in which a record can have a gap between its’ certain date ranges
  • Overlap A condition where a record has more than one occurrence
  • Current Record A record effective at the present time
  • Past Record A record effective in an earlier time
  • Future Record A record effective in a future time
  • Create New Time Period Creates a new time period updating the date effective table and closing the initial record
  • Effective Based When updating a valid time state table in Effective Based mode, if the record being updated is a current record, the record is updated in CreateNewTimePeriod mode. If the record being updated is a future record, the record is updated in Correction mode. If the record is a past record, the record cannot be updated.

Tutorial – Creating a new table with a valid time state key:
Step 1:
Create a table “SL_ExchangeRate”. In order to make the table date effective, it’s property ValidTimeStateFieldType needs to be set.
Date vs. UTCDateTime

  • Date Considers Date only. It can only cater one record per day
  • UtcDateTime Considers Date and Time. It can cater multiple records per day

For this tutorial, the ValidTimeStateFieldType will be set to Date.

Setting ValidTimeStateFieldType  to Date

Setting ValidTimeStateFieldType to Date

After setting the property to Date, it can be noticed that two fields ValidTo and ValidFrom are automatically added to the fields of the table.
Step 2:
The scenario requires the exchange rate to change over time. In order to do so, two fields will be added to the table.
• CurrencyPair (The currency pair value such as USD and PKR)
• Exchange Rate
After adding, the table will have these 4 fields:

Final look of the date effective table

Final look of the date effective table

Step 3:
An Alternate key index “CurrencyPairIdx” needs to be created. The index will contain the field Validfrom and another field which is date effective. In this case, the currencypair is date effective, as its value keeps changing over time. The properties of the Index should be as follows:

Properties of index of date effective table

Properties of index of date effective table

Here, it can be noticed that ValidTimeStateMode property has been set to NoGap. The property can be set to two values:
Gap Gap is allowed in a date range
No Gap No Gap is allowed in a date range. If the exchange rate for a particular currency pair is valid from January and the next exchange rate value is valid from March, then the exchange rate value valid from January will be valid till February.

Outcome:
After setting up the table, let’s add few records in the table and analyze the outcome.

Adding records in date effective table

Adding records in date effective table

Let’s see what happens when another exchange rate is added for the Currency pair # 2.

By clicking on Yes, the Date effective framework automatically sets the ValidTo value for the first date range of the currency Pair # 2.

Adding another exchange rate in our date effective table

Adding another exchange rate in our date effective table

This was the first part of the date effective  framework. I will be posting the next tutorial of the date effective framework tomorrow! Happy Knowledge sharing :)


Microsoft Dynamics AX Job – Eliminate Duplicate Barcode issue

I wrote a job that eliminated the duplicates barcode issue in AX 2012. The job goes through the list of the barcodes, finds duplicated barcodes and adds a D and a counter value at their beginning.  Duplicated barcodes, which are renamed after running this job, can always be found easily by getting a list of the barcodes starting with the letter “D”.

I am sharing the code here:

static void EliminateDuplicateBarcodes(Args _args)
{
    InventItemBarcode inventItemBarcode,inventItemBarcode1;
    int counter;

    counter=1;

    while select itemBarCode,RecId from inventItemBarcode where inventItemBarcode.itemBarCode != ''
    {
        while select forUpdate itemBarCode,recid from inventItemBarcode1
            where inventItemBarcode1.itemBarCode == inventItemBarcode.itemBarCode
                && inventItemBarcode1.RecId != inventItemBarcode.RecId
        {
            ttsBegin;
            inventItemBarcode1.itemBarCode = strFmt("D%1-%2",counter,inventItemBarcode1.itemBarCode);
            inventItemBarcode1.update();
            ttsCommit;

            counter++;
        }

    }

}

Happy Coding :)


Developing SSRS Report Using RDP in Microsoft Dynamics AX 2012

Today I am sharing, how to develop a RDP reports. I will be elaborating the process step by step, so that it is very easy for you to follow the steps and develop your own report.

Step 1: Create a Temp Table SSRS_VendTableTmp

Create a new table and set its table type to InMemory or TempDB. Add the following fields from the vendtable in your table.

  • Vendor Account
  • Address
  • County
  • State
  • Country
  • Telephone
  • Fax
  • Email
  • Telex Number

Step 2: Create a Query SSRS_VendTable

Create a new query and add vendtable in its Data source. Your Query should look like this:

SSRS1

 

Step 3: Create a Data Contract Class SSRS_VendTableDC

The Data contract class defines the parameters in your report. Your Data contract class will have the following methods.

Class Declaration

class SSRS_VendTableDC
{
AccountNum accountNum;
}

Parm Methods – Add as many as you want

[DataMemberAttribute("AccountNum")]
public AccountNum parmAccountNum(AccountNum _accountNum = accountNum)
{
accountNum = _accountNum;
return accountNum;
}

Step 4: Create a Report Data Provider Class SSRS_VendTableRDP

Your RDP class should have the following methods:

 

1.	[ SRSReportQueryAttribute (querystr(SSRS_VendTable)),
SRSReportParameterAttribute(classstr(SSRS_VendTableDC))
]
class SSRS_VendTableRDP extends SRSReportDataProviderBase
{
SSRS_VendTableTmp vendTableTmp;
}

2.	[SRSReportDataSetAttribute("Tmp_SRCustTable")]
public tmpSR_CustTable getTmpSR_CustTable()
{
select * from tmpSR_CustTable;
return tmpSR_CustTable;
}
3.	[SysEntryPointAttribute(false)]
public void processReport()
{
QueryRun queryRun;
Query query;
VendTable vendTable;
SSRS_VendTableDC vendTableDC;
AccountNum accountNum;
QueryBuildDataSource queryBuildDataSource;
QueryBuildRange queryBuildRange;
query = this.parmQuery();
vendTableDC = this.parmDataContract() as SRSRDPCustTableContractClass;
accountNum = vendTableDC.parmAccountNum();
// Add parameters to the query.
queryBuildDataSource = query.dataSourceTable(tablenum(VendTable));
if(accountNum)
{
queryBuildRange = queryBuildDataSource.findRange(fieldnum(VendTable, AccountNum));
if (!queryBuildRange)
{
queryBuildRange = queryBuildDataSource.addRange(fieldnum(VendTable, AccountNum));
}

if(!queryBuildRange.value())
queryBuildRange.value(accountNum);
}
queryRun = new QueryRun(query);
while(queryRun.next())
{
vendTable = queryRun.get(tableNum(VendTable));
this.insertTmpTable(VendTable);
}
}

Step 5: Create Report in Visual Studio

  1. Open Visual studio.
  2. Open a new Project.
  3. Select Microsoft Dynamics AX in the installed templates.
  4. Select report model.
  5. Name your report.
  6.  Click Ok.

SSRS2

Step 6: Setup Report

First of all, add a report in your project. Refer to the below pasted picture.

You can rename your report to VendTableReport.

SSRS3

Once you have added the report, right click on the dataset and add a dataset. Right click on your newly added Dataset and select “Properties”. Select “Report Data provider” in the Data Source Type.

SSRS4

Click on the button provided against the query property and select your RDP class.

SSRS5

Now add AutoDesign in your report. You can add an autodesign by right clicking on the designs or you can drag your  VendTableDataset on the designs node.

Select a Layout template in the properties of your AutoDesign

SSRS6

Select a Style template in the properties of your VendTableDatasetDesign node.

SSRS7

Step 7: Add report to AX AOT

The setup is completed. We need to view the report now. In order to do so, build the report by right clicking on your solution. After successful building of the report, deploy the report and add it to AOT.

SSRS8

Step 8: Create an Output Menu item for your report

In order to view the report in Dynamics AX, add an output menu item. Select SRRS Report in Report Type. Select your report in Object and report design in ReportDesign. Once you have setup the menu item, save it and open it. Here is the final report:

SSRS9


Trade Agreement Data Import Utility

Recently, I had to develop a data import utility as a part of one of the projects I was working on. One of the subparts of the data import utility is the trade agreement import utility. The architecture of the data import utility is as follows:

  • Staging: Data is first import into staging table, where It can be viewed, validated or cleared by the user
  • Validate: Data can be validated in order to ensure the correctness of data
  • Import: Data in the staging tables are processed in the AX tables

I am sharing the Trade Agreement Import utility here.

Trade Agreement Import Utility UI:

TradeAgreementImportUI

Staging Class:

TradeAgreementImportStaging Class

Validation Class:

TradeAgreementImportValidation Class

Import Class:

TradeAgreementImportImport Class

Code to Import Trade Agreements:

public void insertPriceDiscAdmTrans(PriceDiscJournalNum _journalNum)
{
    try
    {
        Counter=0;
        ttsBegin;
        
        while select * from tradeAgreement where tradeAgreement.RecordStatus == SL_Status::Created //Only Process Data in staging tables (Status = Created)
        {

            PriceDiscAdmTrans.clear();
            PriceDiscAdmTrans.JournalNum        = _journalNum;
            PriceDiscAdmTrans.AccountCode       =  this.getAccountCode('All');
            PriceDiscAdmTrans.relation          = this.getRelation('PriceSales');
            PriceDiscAdmTrans.Amount            = tradeAgreement.Calculated;
            PriceDiscAdmTrans.Currency          = 'PKR';
            PriceDiscAdmTrans.FromDate          = tradeAgreement.FromDate;
            PriceDiscAdmTrans.Module            = ModuleInventCustVend::Vend;

            ecoResProductMaster = EcoResProductMaster::find(EcoResProduct::findByDisplayProductNumber(tradeAgreement.Item).RecId);
            ecoResDistinctProductVariant.DisplayProductNumber = EcoResProductNumberBuilderVariant::buildFromProductNumberAndDimensions
            (
                ecoResProductMaster.productNumber(),
                EcoResProductVariantDimValue::getDimensionValuesContainer('', tradeAgreement.Size, tradeAgreement.Color, '')
            );
            ecoResProduct = EcoResProduct::findByDisplayProductNumber(ecoResDistinctProductVariant.DisplayProductNumber);
            
            if (ecoResProduct.recid) //Check If Product exist
            {

                if (tradeAgreement.FindNext == 'yes')
                {
                    PriceDiscAdmTrans.SearchAgain = NoYes::Yes;
                }
                else
                {
                    PriceDiscAdmTrans.SearchAgain = NoYes::No;
                }

                PriceDiscAdmTrans.ItemCode      = TableGroupAll::Table;

                if (PriceDiscAdmTrans.ItemCode == TableGroupAll::Table)
                {
                    PriceDiscAdmTrans.ItemRelation = tradeAgreement.Item;


                    if (PriceDiscAdmTrans.ItemRelation != '')
                    {
                        PriceDiscAdmTrans.UnitId = this.getUnitId(PriceDiscAdmTrans.ItemRelation); //Get Product Unit
                    }
                    else
                    {
                        throw error('Item does not exist');
                    }
                }
               
                if (tradeAgreement.Size == '' && tradeAgreement.Color == '') //For Product
                {

                    PriceDiscAdmTrans.InventDimId = 'AllBlank'; // default dimension
                }
                else //For Product Master
                {
                    PriceDiscAdmTrans.InventDimId = this.getInventdim(tradeAgreement.Size, tradeAgreement.Color);
                }
                
                PriceDiscAdmTrans.FromDate = tradeAgreement.FromDate;

                PriceDiscAdmTrans.insert();
                
                //Change Record Status from staged (Created) to processed (Completed)
                ttsBegin;
                select forUpdate tradeAgreementCompleted where tradeAgreementCompleted.recid == tradeAgreement.recid;
                tradeAgreementCompleted.recordStatus = SL_Status::Completed;
                Counter++;
                tradeAgreementCompleted.update();
                ttsCommit;
            }
            else
            {
                throw error(strFmt('Item %1 :Color or Size does not exist',tradeAgreement.Item));
            }

        }
        ttsCommit;
    }
    //rever log in case of any error
    catch(Exception::Error)
    {
        //Change record status from staged (created) to error
        ttsBegin;
        select forUpdate tradeAgreementCompleted where tradeAgreementCompleted.recid == tradeAgreement.recid;
        tradeAgreementCompleted.recordStatus = SL_Status::Error;
        Counter=0;
        tradeAgreementCompleted.update();
        ttsCommit;

        
        ttsAbort;
        info(strFmt('%1',Exception::Error));
    }
    
    //Display the number of records processed
    info(strFmt('%1 TradeAgreements Created',Counter));

First Windows 8 App for Microsoft Dynamics AX 2012

Microsoft Windows 8 App development team have been working really hard over the last weeks. As a result, they were able to launch three Microsoft Dynamics AX 2012 apps in the Windows store.

These Windows 8 apps have been designed to work with Dynamics AX 2012, however, right now they cannot be connected to a Dynamics AX system. The developers are working over this feature and are hopeful that they will bring some progress regarding this feature in the upcoming months.

The first app, released for the Dynamics AX 2012 is “Approval”. The app, basically, manages approvals with the Dynamics AX 2012 Approvals app in conjunction with Microsoft Dynamics AX 2012. The app user can view a list of the items which need review, view the recent actions taken, track the presence of the coworkers and get insights.

 

Windows 8 App "Approvals" for Dynamics AX 2012


Division of Modules in Microsoft Dynamics AX 2012

A few modules in the Microsoft Dynamics AX 2009 have been divided into sub-modules in Microsoft Dynamics AX 2012. The modules in Microsoft Dynamics AX 2009 and their division into the sub-modules in Microsoft Dynamics AX 2012 are listed below:

AX 2009 Module AX 2012 Module
Bank Cash and Bank Management
Accounts Payable Accounts Payable

Procurement and Sourcing

 

Accounts receivable Accounts receivable

Sales and Marketing

 

General Ledger General Ledger

Fixed Assets

 

Inventory Management Product Information

Inventory and Warehouse management

 

Production Production Control

 

Expense Management Travel and Expense management

 

Project Project management and Accounting

Compliance and Internal Control

 

 


Microsoft Dynamics AX Architecture

Microsoft Dynamics is a unique and powerful solution which contains efficient and flexible functional and development features. The Microsoft Dynamics is a three tier Architecture.

The three tier architecture is defined as:
Database: For the purpose of storing data
Server: Responsible for running the application business logic
Client: Allows user to access data from the database and run the business logic on the server

If we map this three tier architecture onto Microsoft AX, the components can be defined as:
Database (SQL Server Database): Microsoft Dynamics AX application uses data and data model stored in the SQL Server Database.
Server (Application Object Server –AOS): The AOS runs the business logic of the application.
Client (User Interface): The end user accesses the application through the user Interface which is the Microsoft Dynamics rich client or Enterprise Portal

Mircosoft Dynamics AX three-tier Architecture

SQL Server Databases:
Microsoft Dynamics AX Database: The Database is an online transaction processing database which stores the business data, metadata and the application code in tables and models.
Business Intelligence Database: SSRS and SSAS Databases are involved

Application Object Server:
As mentioned above, the AOS executes the business logic and perform many other tasks such as running X++ Job, managing sessions and enforcing security etc.

Client:
Microsoft Dynamics AX Client: It is the primary client which is used to access the functionality of the application. It is developed in the MorphX environment and it is a rich client.
Enterprise Portal: Part of the application that is displayed and accessed through a web browser

 

Some of the other components which are an essential part of the Microsoft Dynamics AX architecture are:
• Internet Information Server
• Microsoft Office
• The .NET Business Connector
• SharePoint
• Help Server
• Web Services

 
I hope this post helped you in getting a basic understanding of the architecture of Microsoft Dynamics AX. Keep visiting the blog to get more information about Microsoft Dynamics AX functionality and its development environment.


Pages:12