Thursday, 3 December 2015

How to add Attachments button on a new form


Step 1. Open your form in AOT and Go to from Design node.

Step 2. Add new button group under ActivePanTab.

Step 3. Add new command button under this new button group.

clip_image001

Step 4. Set following properties of this button

clip_image002

Now you need to do one functional setup for this new customization

Step 5: Open below from
 Organization administration/SetUp-> Document Management -> Active Document Table 

Step 6: Add your table details here and click on Always enable.

clip_image003

Step 7: So its done now.
Open your form and click on Attachment button , below form must open.

clip_image006

Sunday, 29 November 2015

Ware house Phone number

static void warehousetelephonenumber(Args _args)
{
    str                                 Warehouse;
    LogisticsElectronicAddress          LogisticsElectronicAddress;
    LogisticsLocation                   LogisticsLocation;
    InventLocationLogisticsLocation     InventLocationLogisticsLocation;
    InventLocation                      InventLocation;
    ;
    Warehouse   = "11";
    InventLocation = InventLocation::find(Warehouse);
    Select firstOnly InventLocationLogisticsLocation
        where InventLocationLogisticsLocation.InventLocation    == InventLocation.RecId;
    if (InventLocationLogisticsLocation)
    {
        select firstOnly LogisticsLocation
            where LogisticsLocation.ParentLocation      == InventLocationLogisticsLocation.Location
            && LogisticsLocation.IsPostalAddress        == NoYes::No;
        if (LogisticsLocation)
        {
            Select firstOnly LogisticsElectronicAddress
                where LogisticsElectronicAddress.Location    == LogisticsLocation.RecId;
            if (LogisticsElectronicAddress)
            {
                info(strFmt("%1",   LogisticsElectronicAddress.Locator));          
            }
        }
    } 
}

===============================================================

logisticsElectronicAddressLocator getElectronicAddressByType(LogisticsElectronicAddressMethodType _type)
{
    InventLocationLogisticsLocation     InventLocLogLocation;
    LogisticsLocation                   logisticsLocation;
    logisticsLocation                   contactInfoLogLoc;
    LogisticsElectronicAddress          logisticsElectronicAddress;
    LogisticsPostalAddress              logisticsPostalAddress;
    ;
    while select firstOnly * from logisticsLocation
            where logisticsLocation.IsPostalAddress     == NoYes::Yes
        exists join InventLocLogLocation
            where InventLocLogLocation.Location         == logisticsLocation.RecId
               && InventLocLogLocation.InventLocation   == this.RecId
               && InventLocLogLocation.IsPrimary        == NoYes::Yes
        exists join LogisticsPostalAddress
            where LogisticsPostalAddress.Location       == logisticsLocation.RecId
               && logisticsPostalAddress.ValidFrom      <= DateTimeUtil::utcNow()
               && logisticsPostalAddress.ValidTo        >  DateTimeUtil::utcNow()
        exists join contactInfoLogLoc
            where contactInfoLogLoc.ParentLocation      == logisticsLocation.RecId
        exists join LogisticsElectronicAddress
            where LogisticsElectronicAddress.Location   == contactInfoLogLoc.RecId
               && logisticsElectronicAddress.Type       == _type
    {
        return logisticsElectronicAddress.Locator;
    }

    return '';
}

Thursday, 26 November 2015

How to add a method for the click event of a button placed on action pane of a List Page

Setting the DisplayTarget property of the button to the value "Client" will hide the button if used from Enterprise Portal and will enable you to override the clicked method. If you not plan to use the list page in EP then go ahead.
Otherwise you will have to put your code in the target form init or class main method.

Wednesday, 25 November 2015

Automatic PO Confirmation and Packingslip

static void PostPOPackingSlip(Args _args)
{
        PurchFormLetter  purchFormLetter;
        PurchTable       purchTable;
    purchTable  = purchTable::find('000048');
    if (purchTable.DocumentState != VersioningDocumentState::Confirmed)
                {
                    purchFormLetter = PurchFormLetter::construct(DocumentStatus::PurchaseOrder);
                    purchFormLetter.update(purchTable, "def1");
                }

                purchTable.reread();

                if (purchTable.DocumentState == VersioningDocumentState::Confirmed)
                {
                    purchFormLetter = PurchFormLetter::construct(DocumentStatus::PackingSlip);
                    purchFormLetter.update(purchTable,"123",systemDateGet(), PurchUpdate::All, AccountOrder::None,false,false);

                }

info("jobcompleted");

}

Thursday, 19 November 2015

AutomaticSOPackingSlip

static void AutomaticSOPackingSlip(Args _args)
{
    SalesTable  salestbl;
    SalesLine                   salesline;
    SalesFormLetter_PickingList salesFormLetter;

    salestbl    =   SalesTable::find('000184');
    while select salesline  where salesline.SalesId ==  salestbl.SalesId
    {
        salesline.selectForUpdate(true);
         ttsBegin;
            salesline.SalesDeliverNow   =   salesline.QtyOrdered;
            salesline.update();
            ttsCommit;

    }
    salesFormLetter = SalesFormLetter_PickingList::newPickingList();
    salesFormLetter.transDate(systemDateGet());

    salesFormLetter.update(salestbl,
                            systemdateget(),
                            SalesUpdate::All,
                            AccountOrder::None,
                            NoYes::No,
                            NoYes::No);

}

Wednesday, 18 November 2015

Get the String values from String separated by Delimiter


Requirement : To separate values from String with Pipe Delimited Values.

static void ValueFromStringSepdeli(Args _args)
{
    citInboundLineData x;
    container c;
    SalesShippingDate shipdate;
    int i;

    x= "SOPack"+"|"+"SO1"+"|"+"PR1"+"|"+"item1"+"|"+"10"+"|"+"25/5/2015"+"|"+"tn1";
    c = str2con(x,"|");
    //conview(c);
     for (i=1; i <= conLen(c); i++)
    {
        info (strFmt("container value %1 is %2", i, conPeek(c, i)));
    }
    shipdate    =   str2Date(conPeek(c,6),123);
    info(strFmt("%1",shipdate));
}

static void Job9(Args _args)
{
    citInboundLineData x;
    container c,toc;
    SalesShippingDate shipdate;
    int i;
     x= "SOPack"+","+"000185"+","+"PR1"+","+"T0004"+","+"10"+","+"12/31/2015"+","+"tn1";
    //toc =   con2Str(x, "|");
    toc = str2con(x,",");
    x = con2str(toc,"|");
    info(x);
    c=  str2con(x,"|");
    conview(c);
 
}

Monday, 16 November 2015

AX 2009 Reports

http://www.slideshare.net/magive249/report-microsoft-dynamics-ax

Through Report Wizard :
http://blog.rahulsharma.in/2009/12/reporting-capabilities-of-ms-dynamics_14.html

A requirement of Creating report , with Grouping / then get top 10 Highest Amount value sorting in Descending.

This is done by using Temp tables - Insert - filter values in to temp, the process to get it sort and insert.  Then send only 10 records through fetch method on to the report.

Use Programmable Section:

I got the requirement to Get details and below get the total Amounts  section .  Total amount section ( should be run only for the 10 Highest Amount Value , this all can be done in Fetch method.








public boolean fetch()
{
    boolean ret     =   false;
    q = qrun.query();

// Loop all the Query and in to Details temp table .
    while(qrun.next())
    {
        purchlineRec    =   qrun.get(tablenum(Purchline));
        inventtblRec    =   qrun.get(tablenum(InventTable));

        this.RelInventTbl(purchlineRec);
        table.ItemId        =   purchlineRec.ItemId;
        table.ItemName      =   purchlineRec.itemName();
        table.PODate        =   PurchTable::find(table.PurchId).createdDate;
        table.PurchId       =   purchlineRec.PurchId;
        table.QtyOrdered    =   purchlineRec.QtyOrdered;
        table.PurchPrice    =   purchlineRec.PurchPrice;
        table.DeliveryDate  =   purchlineRec.DeliveryDate;
        table.LineAmount    =   purchlineRec.LineAmount;
        table.VendName      =   VendTable::find(purchlineRec.VendAccount,false).Name;
        table.insert();
    }
// Insert – only one record per Item in to total temp table – Insert in to Table with Total Sum Amount etc ( fields required in Total Section)

   while select table
    {
        instbl = null;
       select instbl    where instbl.ItemId ==  table.ItemId;
       if(!instbl)
       {
        select sum(LineAmount),sum(QtyOrdered)from tablegrp where tablegrp.itemid == table.itemid;
        instbl.ItemId       =   table.ItemId;
        instbl.TotLineAmt   =   tablegrp.LineAmount;
        instbl.TotPurchQty    =   tablegrp.QtyOrdered;
        instbl.insert();
        }
    }
// Looping total Temp table , order by TotLine Amt – and get detail transactions for Details Temp table  
   while select * from instbl order by TotLineAmt desc where instbl.ItemId  != ""
   {
        while select * from table
            where table.ItemId  ==  instbl.ItemId
            {
                TotLineamt          =   instbl.TotLineAmt;
                TotPurchQty       =   instbl.TotPurchQty;

                //ttscommit;
                if(i <10)
                 element.send(table);
                else
                    break;

            }
            if(i >9)
                break;
             if (TotLineamt)
                {
                    element.execute(1); // Calling Programmable section only at required Part.

                }
              i++;

   }
    ret =   true;
    return ret;
}

Monday, 5 October 2015

how number sequence is generated using format in ax 2012 - through code

job GetnextNumseq()
{
     NumberSeq num;
     num = NumberSeq::newGetNum(CustParameters::numRefCustAccount());
    info(strfmt("%1",num.num));
}


Get Next number generated using format using X++ :
 int             purchreceiptcounter;
 PurchId         purchtblcounter;

//Find the Purch Id - from table.

 purchfind   =   purchTable.PurchId+ strRem(PurchParameters::find(false).LandedFreightTemplate,"#")+"*"; // Remove all '#' in format and add to Purch id.

// Get no. of Purchase orders created - PO1FFE*

            select count(RecId) from Purchtabletmp where Purchtabletmp.PurchId like purchfind;

            purchtblcounter=   int642int(Purchtabletmp .RecId); // Gets no.of records already inserted in table ...

            Purchtableins .PurchId   =   purchTable.PurchId+

// Which gets next numbersequence based on format

 NumberSeq::numInsertFormat(purchreceiptcounter+1,PurchParameters::find(false).Template);

//PurchParameters::find(false).Template) - Gets the format Value given - FFE##

Requirment :
PO1  ,

Next number sequence should be PO1FFE01 , if FFE## - Format

PO1FFE01
PO1FFE02
PO1FFE03
PO1FFE04
....

Suppose we have already PO1FFE02 in Purch table.  Now purchtbl counter - 2 , then Counter+1 value is passed to  "NumberSeq::numInsertFormat()" to get next number to insert in to table.


Wednesday, 30 September 2015

How to add Filter functionality to Display method in dynamics AX

Normally filters will work only in table fields but we can't do filters to display method.

This below code will work for filters to display method also.

Step 1:
Go to the form design right click on particular control properties Auto Declaration No to Yes.



Step 2:
Override the context() method on the display method .

public void context()
{
    int             selectedMenu;
    formrun         fr;
    Args            ag;
    Name            strtext;
    querybuilddataSource qb1;
    queryrun    qr;
    query       q;
    PopupMenu menu = new PopupMenu(element.hWnd());
    int a = menu.insertItem('Filter By Field');
    int b = menu.insertItem('Filter By Selection');
    int c = menu.insertItem('Remove Filter');
    ;
q   = ItemControl_ds.query();
qb1 = q.dataSourceTable(tablenum(ItemControl));
qb1 = qb1.addDataSource(TableNum(SalesTable));
qb1.addLink(FieldNum(ItemControl,PO),FieldNum(SalesTable,PurchOrderFormNum));  

selectedMenu = menu.draw();
    switch (selectedMenu)
    {
    case -1: //Filter by field
            break;
    case a:
            ag = new args('SysformSearch');
            fr = new formrun(ag);
            fr.run();
            fr.wait();
//Reading User entered value for filter process
            strtext = fr.design().controlName('FindEdit').valueStr();
            if(strtext)
            {
//Creating a query for filter
                
                qb1.addRange(FieldNum(SalesTable,SearchName)).value(strtext);
                ItemControl_ds.query(Q);
                ItemControl_ds.executeQuery();
            }
            break;

    case b:                                      // Filter By Selection
           
            qb1.addRange(FieldNum(SalesTable,SearchName)).value(ProjName.valueStr());
            ItemControl_ds.query(Q);
            ItemControl_ds.executeQuery();
            break;

    case c :                                      // Remove Filter
            q   = new Query();
            qb1 = q.addDataSource(tablenum(ItemControl));
            qb1.clearLinks();
            qb1.clearRanges();
            ItemControl_ds.query(Q);
            ItemControl_ds.removeFilter();
            break;

    Default:
            break;
    }

}
After adding the above code we are getting menus like 



Monday, 28 September 2015

Cube

A cube is defined by its measures and dimensions. 
A measure is a column in a table/ view that contains quantifiable data, usually numeric that can be aggregated
- like total no. of items sold/ profit/ revenue. A cube contains 1 or more measure.

Attributes are fields on table/ view .Dimensions are group of attributes.

The cube we create will allow us to analyze the data in Table format .


Prerequisites
  • Dynamics AX 2012
  • Dynamics AX 2012 Analysis Services
  • SQL Server 2012
Once you have identified the tables and views which contain the relevant data for your BI report, you can begin creating perspectives (cubes) in the AOT. Let’s suppose we have to develop a sales report for which the following tables/views contain the relevant data:
CUSTTRANSTOTALSALES view
CUSTTABLECUBE view
CUSTPAYMMODETABLE table

Creating Cube

Follow these steps to create a new perspective in the AOT:    Perspective Node
1. Expand Data Dictionary/Perspectives node
2. Create a new perspective and give it a suitable name
3. Set the USAGE property to OLAP
4. Drag the relevant tables and views

Defining Measures and Dimensions

Next step is to define measures and dimensions. Expand CUSTTRANSTOTALSALES view and set the field properties in the AOT as follows:
Untitled
Repeat the above step to specify measures and dimensions for other tables/views in your perspective as per your report requirements.

Generate Project

Click Tools > Business Intelligence (BI) tools > SQL Server Analysis Services project wizard. Create a new project and give a suitable name as shown below:
Untitled
On the next screen, select your newly created perspective:
Untitled
The next couple of screens offer optional features which include adding financial, date dimensions, language selection and currency conversion. The wizard will generate the project:
Untitled
Its up to you whether you save the project on disk or in the AOT.

Deploy cube

Next, the wizard will prompt you to choose the partitions to deploy the cube in if multiple partitions exist in the database environment. You can either to choose to process the cube using this wizard by ticking the checkbox or process the cube later in the SQL Server Management Studio.

Below screen - you can find based on no. of partitions of your DB . 
Go to >> System Administrator >> Setup >> Business intelligence>> Analysis servers >> Analysis server 
based on no. of records ( Partition keys) we get the same no.of records here.
Untitled

Process cube

Open SQL Server Management Studio, connect to Analysis Services. In the Object Explorer, you should be seeing now your newly created cube:
Right click your cube and click Process. Make sure the user has sufficient rights to process the cube otherwise you would have to provide Impersonation information in the Security settings of the database properties of your cube. The wizard will successfully process the cube.
Untitled
This ends the process of creating cubes! Now you can make MDX queries, build reports on top of your cubes. One such report that I created using SQL Server 2012 Power View plugin looks like below in the role center:
Untitled

Wednesday, 9 September 2015

Check access rights for menu item and call through code

public void jumpRef()
{
    MenuFunction    menuFunction;
    ;

    menuFunction = new MenuFunction(menuitemdisplaystr(smmProcessSalesDefinition), MenuItemType::Display);

    // Check access rights
    if (!menuFunction || !menuFunction.checkAccessRights())
    {
        // Access rights are not sufficient to use this function.
        throw error("@SYS81158");
    }

    menuFunction.run();
}

Tuesday, 1 September 2015

WorkFlow Automated Task

I have got the Workflow task of creating 4 Approvals based on amounts.

For Ex:  SalesTable Total Amount ( Get all line amounts total)

If   Sales Total Amount < 1000  - Get one approval
      Sales Total Amount < 2500  - Get 2 approval
      Sales Total Amount >25000 - 50000  - Get 3 approvals
      Sales Total Amount >50000  - Get 4 approvals

I created one approval Task and configured in Workflow, by creating conditional approval using same Approval class. The issue is with the code of Approval Complete Event - Changed the table Workflow field to approval.

Issue :  Even the amount is 2600, which needs 3 approvals, but when it pass through first approval the Table workflow field is getting Approved through code.

Resolved :  The issue is resolved by creating Automated Task event, And written below code in  "Executed " method .

public void execute(WorkflowElementEventArgs _workflowElementEventArgs)
{
    SalesTable  salesTable;
    WorkflowTrackingStatusTable workflowTrackingStatusTable;
    salesTable = SalesTable::findRecId(_workflowElementEventArgs.parmWorkflowContext().parmRecId());
    if(salesTable)
    {
        //workflowTrackingStatusTable = WorkflowTrackingStatusTable::findByCorrelation(_workflowElementEventArgs.parmWorkflowContext().parmWorkflowCorrelationId());
       // if(workflowTrackingStatusTable.TrackingStatus == WorkflowTrackingStatus::Completed)
        {
            ttsBegin;
            salesTable.selectForUpdate(true);
            salesTable.SalesCreditNoterWorkFlowStatus = SalesReturnOrderWorkFlowStatus::Approved;
            salesTable.update();
            ttsCommit;
        }
    }
    info("automated task is executed");
}

Configured the Automated Task  in Workflow before End...

So The flow comes from any of the approval needs to go from Automated Task and the workflow gets approved

Below code to get Total Line amount for a sales order :
    SalesTotals salesTotals;
    SalesTable salestblUpd;
    salestblUpd  =   SalesTable::find(Custinvoicejour.SalesId);
    if(salestblUpd)
    {
        salesTotals = SalesTotals::construct(salestblUpd, SalesUpdate::All);
        salesTotals.calc();
        salestblUpd.selectForUpdate(true);
        ttsBegin;
        salestblUpd.SalesCreditLineTotalAmount  =  salesTotals.totalAmount();
        salestblUpd.update();
        ttsCommit;
    }

Wednesday, 26 August 2015

Info

1. If you want to Open the corresponding Form/Table when you click the Id the message contain

info(strFmt("@SYS58788", journalNum),"",SysInfoAction_TableField::newBuffer(WMSJournalTable::find(journalNum)));

Tuesday, 18 August 2015

Exchange Rate in Ax 2012


Four pieces of information are necessary to perform a currency calculation in Microsoft Dynamics AX 2012: 1) From currency 2) To currency 3)Date 4) Exchange rate type 

=>Get Exchange Rate Currency Factor for two Currencies :
DD\Tables\ExchangeRateCurrencyPair\ExchangeRateDisplayFactor.

=> Calculate the accounting currency amount from a transaction currency
CurrencyExchangeHelper currencyExchangeHelper;
 TransDate transactionDate;
CurrencyCode transactionCurrency = 'CAD';
 AmountCur amountToConvert = 100.50;
boolean shouldRoundResult = true;
 AmountMst result;
currencyExchangeHelper = CurrencyExchangeHelper::newExchangeDate( Ledger::current(),transactionDate);

result = currencyExchangeHelper.calculateTransactionToAccounting( transactionCurrency, amountToConvert, shouldRoundResult);

=> Calculate the transaction currency amount from an accounting currency

CurrencyExchangeHelper currencyExchangeHelper;
 TransDate transactionDate;
CurrencyCode transactionCurrency = 'CAD';
 AmountMst amountToConvert = 100.50;
boolean shouldRoundResult = true;
AmountCur result;

currencyExchangeHelper = CurrencyExchangeHelper::newExchangeDate( Ledger::primaryLedger(CompanyInfo::findDataArea(‘TST’).RecId), transactionDate);


result = currencyExchangeHelper.calculateAccountingToTransaction( transactionCurrency, amountToConvert, shouldRoundResult);

=> Calculate using Exchange rates that have been provided
CurrencyExchangeHelper currencyExchangeHelper;
TransDate transactionDate;
 CurrencyCode transactionCurrency = 'CAD';
AmountMst result;
 currencyExchangeHelper = CurrencyExchangeHelper::newExchangeDate( Ledger::current(), transactionDate);

currencyExchangeHelper.parmExchangeRate1(1.234);
currencyExchangeHelper.parmExchangeRate2(2.54321);


result = currencyExchangeHelper.calculateTransactionToAccounting( transactionCurrency, 543.34, true);

=> Calculate by overriding the default exchange rate type from the ledger

Calculating an exchange rate by overriding the default exchange rate type would be useful when it is necessary to use a different set of exchange rates for a calculation scenario. Examples might include budget processing or consolidations.

CurrencyExchangeHelper currencyExchangeHelper;
TransDate transactionDate;
CurrencyCode transactionCurrency = 'CAD';
AmountMst result;
currencyExchangeHelper = CurrencyExchangeHelper::newExchangeDate( Ledger::current(), transactionDate);
currencyExchangeHelper.parmExchangeRateType( ExchangeRateType::findByName('SpecialRateType').RecId);


result = currencyExchangeHelper.calculateTransactionToAccounting( transactionCurrency, 200.75, true);

=> Calculate outside the context of ledger

Calculating an exchange rate by overriding the default exchange rate type would be useful when it is necessary to use a different set of exchange rates for a calculation scenario. Examples might include budget processing or consolidations.

CurrencyExchangeHelper currencyExchangeHelper;
TransDate transactionDate;
CurrencyCode fromCurrency = 'CAD';
CurrencyCode toCurrency = 'USD';
AmountCur result;
currencyExchangeHelper = CurrencyExchangeHelper::construct(); currencyExchangeHelper.parmExchangeDate(transactionDate); currencyExchangeHelper.parmExchangeRateType( ExchangeRateType::findByName('SpecialRateType').RecId);


result = currencyExchangeHelper.calculateCurrencyToCurrency( fromCurrency, toCurrency, 123.45, true);


Code for Exchange rates in AX 2012 :
currency::find(CurrencyCode).findExchRate(today());
in Dynamic ax 2009 following code is for Dynamic AX 2012

    static ExchRate exchRateFind(CurrencyCode _currencyCode = '')
{
    ExchangeRateType    ExchangeRateType;
   // ExchangeRate        ExchangeRate;
    ExchangeRateCurrencyPair    ExchangeRateCurrencyPair;
    ExchRate    ret;
    ExchangeRateHelper exchangeRateHelper;
    TransDate transactiondate;
    CurrencyExchangeRate exchangeRate1;
    CurrencyExchangeRate exchangeRate;
    ;
    exchangeRateHelper = ExchangeRateHelper::newExchangeDate(Ledger::current(),
_currencyCode, systemDateGet());

    exchangeRate1 = exchangeRateHelper.getExchangeRate1();
    exchangeRate = exchangeRateHelper.displayStoredExchangeRate(exchangeRate1);

//Ledger::find(Ledger::current()).DefaultExchangeRateType
    return exchangeRate;
}
There is a new class by name CurrencyExchangeHelper that has been introduced in AX 2012 to support this.In Microsoft Dynamics AX 2012, the currency and exchange rate framework has been enhanced to share information across multiple legal entities.
This class will help you to do some calculations between currencies. Some important methods to use:
calculateTransactionToAccounting
Example : This method will convert the transaction currency in to accounting currency defined in ledger Table.
static void SR_CEH_Example1(Args _args)
{
    CurrencyExchangeHelper currencyExchangeHelper;
    CurrencyCode transCurrency = ‘EUR’;
    AmountCur amountCur = 500.00;
    AmountMst amountMST;
   
    currencyExchangeHelper = CurrencyExchangeHelper::newExchangeDate(Ledger::current(), systemDateGet());
    amountMST = currencyExchangeHelper.calculateTransactionToAccounting(transCurrency, amountCur ,true);
    info(strFmt(‘%1’,amountMST));
}

Result :
image
calculateAccountingToTransaction
This method calculates the transaction currency amount from an accounting currency given.
static void SR_CEH_Example2(Args _args)
{
    CurrencyExchangeHelper currencyExchangeHelper;
    CurrencyCode transCurrency = ‘EUR’;
    AmountCur amountCur;
    AmountMst amountMST = 500.00;
   
    currencyExchangeHelper = CurrencyExchangeHelper::newExchangeDate(Ledger::primaryLedger(CompanyInfo::findDataArea("DUM").RecId), systemDateGet());
    amountCur = currencyExchangeHelper.calculateAccountingToTransaction(transCurrency, amountMST ,true);
    info(strFmt(‘%1’,amountcur));
}
Result :
image
While searching through, I found that there are  parmExchangeRate1 and parmExchangeRate2  methods that to calculate based on the exchange rates that have been provided. Please refer to the below example which calculates the misc charges [markup amount] based on the exchange rates defined.


Class Name : Markup >> calcMarkupAmount
image

How to Find Exchange rate in AX 2012 :

ExchangeRateHelper    exchangeRatehelper;
TransDate    transdate;
CurrencyCode  transactioncurrency = 'CAD';
CurrencyExchangeRate  excRate1,excRate2;

;
transdate  = mkdate(21,2,2012);

exchangeRatehelper = ExchangeRateHelper::newExchangeDate(Ledger::current(),transactionCurrency,transdate);
excRate1    = exchangeRateHelper.getExchangeRate1();
excRate2    = exchangeRateHelper.getExchangeRate2(0;
INFO(NUM2STR(exchangeRate1,2,2,1,1));