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

Price Conversion - based on units

public SalesQuoteUOMPrice TotalConversionUnit(UnitOfMeasureSymbol _fromunit,UnitOfMeasureSymbol _tounit,SalesOrderedQty _qty,ItemId _itemid)
{
    SalesQuoteUOMPrice  totalConversionUnit;
    Qty         convertQty;
    UnitOfMeasureConverter_Product  unitConverter   = UnitOfMeasureConverter_Product::construct();

    unitConverter.parmProduct(InventTable::find(_itemid).Product);
    unitConverter.parmFromUnitOfMeasure(UnitOfMeasure::unitOfMeasureIdBySymbol(_fromunit));
    unitConverter.parmToUnitOfMeasure(UnitOfMeasure::unitOfMeasureIdBySymbol(_tounit));
    unitConverter.parmRoundAbsoluteValue(NoYes::Yes);
    unitConverter.parmApplyRounding(NoYes::Yes);

    return unitConverter.convertValue(1);

}

Monday 10 August 2015

Preview Pane creation for LP - Issues

Steps to Create Form Part as Preview Pane :
1.       Create a form , which need to appear as Preview pane. Set Form design properties : Style – Formpart, ViewEditMode – View , Width – Column Width.
2.       Create a Form Part  - Parts >> FormPart >> New
Set Name, Caption,Form – New Form created 1st step.
3.       Create a new menu item of Display Type. Set properties – Name, Label, Object type – FormPart ( Assign the form part created in 2nd step).
4.       Now go to the LP where you need to create a preview pane .
Drag and drop the menu item create in 3rd step in to Parts object of the form.
Set PartLocation – PreviewPane , DataSource – main datasource of the form, DatasourceRelation – SelfLink ( If new form datasource and LP datasource are same, else mention the relation. ), IsLinked – Auto.

We can create Preview Pane using Info part - but with Info part, i got the issue like I have a group field with Note field . When the field have multiple lines,  getting scroll bars, and the field is not extending the total form. 
I tried to set the Repeating property of the Group ( Yes)  - this make the fields in the Group to get Grid View. 

Issue : with setting Yes , for any child record selected, it is getting Note field value for all the records , instead of specific related record. Hence this is can be resolved, only by setting Width of Group which have Note field as - Column width. This can be only possible by R & D in net as creating a Form Part instead of Info Part.

Friday 7 August 2015

Arrival Create Journal From Arrival Overview and Posting

Functional Process:

To Get Lines in to Arrival Overview - we need to Create Purchase order.

Create Arrival journal(s) from Arrival overview form

1.       User navigates to Stock management / Periodic / Arrival overview
2.       On Arrival overview form,
a.       On Setup tab user sets new ‘Arrival journal per purchase order’ checkbox to ‘yes’
b.       On Overview tab user adjusts range as needed, and selects ‘Update’
3.       On same Arrival overview form, in Receipts section lines are displayed based on previously defined filter criteria ( set – Days Back : 2000 if you want data – click update)
4.       User selects lines (mark them in column ‘Select for arrival’), and calls function ‘Start arrival’
5.       AX prompts user about Arrival journal(s) being created

Register Delivered items on Arrival journal, and post journal

1.       User navigates to Stock management / Journals / Item arrival
2.       Item arrival form opened, user selects journal, and click on ‘Lines’ button.
3.       Journal lines form opened, providing information about:
4.       Click ‘Post’
5.       Posting dialog box displayed. If the user posts an arrival journal with discrepanc

Technical Overview :

Create Arrival journal(s) from Arrival overview form

>>\Forms\WMSArrivalOverview\Designs\Design\[Tab:Tab]\[TabPage:OverviewTabPage]\[Group:ExpectedReceipts]\[Group:OverviewGroup]\[ActionPane:ActionPane]\[ActionPaneTab:ActionPaneTab]\[ButtonGroup:ButtonGroup]\Button:StartArrivalButton\Methods\clicked

>> Classes\ WMSArrivalStart::startArrival

>> Classes\ WMSArrivalStart\run

wmsArrivalCreateJournal.createWMSJournalTrans(wmsArrivalDetailTmpLocal);  - Journal is created by looping all the selected lines in Lines grid.

>>Classes\WMSArrivalCreateJournal\ createWMSJournalTrans
Line no : 34  - Creates journal header
if (!wmsJournalTable.RecId)
    {
        this.createWMSJournalFromTmp(_wmsArrivalDetailTmp);
    }

Line no  : 52 – Create Journal Lines.

numberOfLines += this.createWMSJournalTransFromTmp(_wmsArrivalDetailTmp);

Post Item Arrival Journal : 

Classes \ WmsJournalCheckPostReception\run
Classes \ WMSJournalCheckPost\main
Classes\ JournalCheckPost\postjournal
 Some Learnings about Classes \JournalCheckPost :
Classes\JournalCheckPost\runEnd – then itself Journal status is updated as posted.
Classes \ WmsJournalCheckPostReception\run  - After Super() – We can make any process that should be done after posting …( Method can be overrided, as it do not exist).
X++ code to create a Item Arrival Journal :

Classes \ WmsJournalCheckPostReception\run   - Get Journal Id through
this.parmJournalId()

Requirements / Modifications :

Create Arrival journal(s) from Arrival overview form

Need to Create separate journals for different Orders
Customization required :
while select wmsArrivalDetailTmpLocal
        where wmsArrivalDetailTmpLocal.Selected   == NoYes::Yes
        &&    wmsArrivalDetailTmpLocal.InventQty  >  0
    {
        find    =   conFind(con,wmsArrivalDetailTmpLocal.InventTransRefId);
        if (!find)
        {
            con = conIns(con,i,wmsArrivalDetailTmpLocal.InventTransRefId);
            i++;
        }
    }
Get all different order ids and loop it by setting Invent TransRefId as range
while select wmsArrivalDetailTmpLocal
            where wmsArrivalDetailTmpLocal.Selected   == NoYes::Yes  // Existing
            &&    wmsArrivalDetailTmpLocal.InventQty  >  0
            && wmsArrivalDetailTmpLocal.InventTransRefId    ==  refrenceId // Add this line as range

Post Item Arrival Journal : 

Need to add new parameter on the post , Based on that we need to create new journal on some validated conditions

In post Dialog Add one more parameter along with Transfer all posting errors to a new journal :

Customization :

1)       Need to add Parm method
2)       Show this field only for Arrival posting : Classes\JournalCheckPost\dialog
wmsjournaltable =   WMSJournalTable::find(journalId);
        if(wmsjournaltable.journalType  ==  WMSJournalType::Reception)
            dialogTransferRemainingQty  = dialog.addField(extendedTypeStr(StockJournalTransferRemainingQuantity));


3)       Need to add the field in Macro – to maintain the value in cache -modify in Unpack and Classdeclaration ( If any error, just remove cache and usage data).
4)       Set parm method in Classes\JournalCheckPost\getFromDialog

Create a new Item Arrival Journal Through code : 

private void CreateArrivalJournal(JournalId _journalId)//JournalTransList _journalTransList)
{
        WMSJournalTable         fromJournalTable,toJournalTable;
        WMSJournalTrans         fromJournalTrans,toJournalTrans;
        str                     journalNum,journalName;
        int                     lineNum = 1;
        NumberSeq               numberSeq;
        WMSJournalName          wmsJournalName;
    ;
        if(this.chkRemaingQtyPerJournal(_journalId))
    {
        select * from fromJournalTable
            where fromJournalTable.journalId    ==  _journalId;

        numberSeq = NumberSeq::newGetNum(WMSParameters::numRefWMSJournalId());
        journalName = WMSParameters::find().receptionJournalNameId;
        journalNum = numberSeq.num();
        wmsJournalName = WMSJournalName::find(journalName);
        ttsbegin;
        toJournalTable.initFromWMSJournalName(wmsJournalName);

        toJournalTable.JournalNameId        =   journalName;
        toJournalTable.JournalId            =   journalNum;
        toJournalTable.journalType          =   WMSJournalType::Reception;

        toJournalTable.inventDimId = InventDim::inventDimIdBlank();
        toJournalTable.insert();
        while select fromJournalTrans
            where fromJournalTrans.journalId    ==  _journalId
        {
            //Condition whether to insert or not the lines
            {
                    toJournalTrans.clear();
                    toJournalTrans.initFromWMSJournalTable(toJournalTable);
                    toJournalTrans.JournalId                =   journalNum;
                    toJournalTrans.LineNum                  =   lineNum;
                    toJournalTrans.TransDate                =   today();
                    toJournalTrans.ItemId                   =   fromJournalTrans.ItemId;
                    toJournalTrans.Qty                      =   fromJournalTrans.StockExpectedQuantity - fromJournalTrans.qty;
                    toJournalTrans.InventDimId              =   fromJournalTrans.InventDimId;
                    toJournalTrans.vendAccount              =  fromJournalTrans.vendAccount;
                    toJournalTrans.inventTransType          =   fromJournalTrans.inventTransType;
                    toJournalTrans.inventTransRefId         =   fromJournalTrans.inventTransRefId;
                    toJournalTrans.inventTransId            =   fromJournalTrans.inventTransId;
                    toJournalTrans.checkPickingLocation     =   NoYes::No;
                    toJournalTrans.createQuarantineOrder    =   NoYes::No;
                    toJournalTrans.inventDimId              =   fromJournalTrans.InventDimId;
                    toJournalTrans.StockExpectedQuantity    =   fromJournalTrans.qty;
                    toJournalTrans.insert();
                    lineNum++;
            }
        }
    ttscommit;       
         info(strFmt("@SYS58788", journalNum));
    }

}