Sunday, February 17, 2013

Default Descriptions

Quoting from MSDN,
“You can set up default text that is used to fill in the Description field for accounting entries that are posted automatically to the general ledger. Use the Default descriptions form to select the parameters or fields that are used to create the description text.”


Organization administration > Setup > Default descriptions.
In the Text field, enter the default description. You can type text in the field, or you can use one or more of the following free text variables:
·        %1 – Add the transaction date.
·        %2 – Add an identifier that corresponds to the document type that is being posted to the general ledger. For example, for transaction types that are related to invoices, the %2 variable adds the invoice number.
·        %3 – Add an identifier that is related to the document type that is being posted to the general ledger. For example, for transaction types that are related to invoices, the %3 variable adds the customer account number.
You can also define three more variables %4-%6, whose values differ from record to record. In case you are creating your own description (needs customization), you can define what values to come in these.

Behind the scenes
Class TransactionTxt drives this feature end to end. If you see the method txt(), the last line explains it all.  

return strfmt(txt, date2StrUsr(transDate, DateFlags::FormatAll), formLetterNum, voucherNum, key1, key2, key3);

In one of the customizations, I was required to populate description value on invoice transactions. I used a display method with below logic, the use of TransactionTxt class is self evident.



 

Saturday, February 16, 2013

Create a New Financial Dimension

AX 2012 supports unlimited number of Financial Dimensions. System entities like Projects, Customers, Customer groups etc can be made into Dimensions. Form opens at General ledger > Setup > Financial dimensions > Financial dimensions. One option is to create a user-defined financial dimension in the Use values from field by selecting < Custom dimension >. Another way it to customize AX to include your own dimensions.
For example, one requirement i got was to have Mode of Delivery as a Financial dimension.


So what needs to be done?

Luckily, only thing required is to create a view.

1. Create a view named DimAttributeModeOfDelivery. Why such a name, little later.
2. Define its datasource name as BackingEntity.
3. Define three fields on it namely, Key(RecId), Value(Code like Id) and Name


Whats going on here?
Form DimensionDetails's run method calls Class DimensionDetails.run() method which calls a method DimensionEnabledType::getSystemDefinedDimensions()


Next call is made to DimensionEnabledType::getSystemDefinedDimensionsServer()

Here the code loops through and if an entity is a view and matches proper naming conventions (prefix DimAttribute*), considers it "dimension enabled"


Multiple Designs in SSRS

Developers who have had their hands dirty playing with SSRS in 2012 must be well aware of the Report Data Provider framework. RDP is the new way AX wants you to make reports in SSRS. In a way, Microsoft wants to put all the business logic back in X++ and dissuade developers from using the Visual Studio data methods. In case, all this sounds greek to you, please browse MSDN. 

Few important concepts here: 
  • Temporary table – RDP class fills a temporary table with data that will be used by Reporting Services to display the report. 
  • Data Contract Class – defines the parameters in the report. 
  • Report Data Provider Class – processes business logic based on a query and parameters defined in the data contract class, and then returns the tables as a dataset for the report. 
  • Controller class – control the report execution and dialog forms. Report controllers can be used to modify report dialogs, validate report parameters and other validations necessary before report execution. 
  • UIBuilder class – enhance the dialog more. 

Today, I will touch upon a small but interesting topic related to this. One of the reports I was required to have two designs Summary/Detailed and based on the value in Summary checkbox in Dialog, decide at run-time which design to display. This logic resides in the Controller class, in method preRunModifyContract().

protected void preRunModifyContract()
{
    SalesMarginReportContract   dataContract = this.parmReportContract().parmRdpContract() as SalesMarginReportContract;

    if (dataContract.parmIsSummary())
    {
        this.parmReportContract().parmReportName(ssrsReportStr(SalesMarginReport, SummaryDesign));

    }
    else
    {
        this.parmReportContract().parmReportName(ssrsReportStr(SalesMarginReport, DetailedDesign));
    }

    super();
}

Up Down Sequence Logic

In one of the customizations, there was a requirement to allow users to move items up/down in BOMDesignerDetails Form. This form uses a Tree control, which displays a BOM and its items in a tree structure. A user should be able to resequence these items with Up and Down arrows. Sounds simple and it is, once you know how. There is a standard form EConDesigner which has this feature and I replicated the code for the two buttons. Code is in the clicked method of the buttons. Logic utilizes few standard Tree control methods like getSelection, getPrevSibling, getNextSibling, moveItem, selectItems. Below is a simpler description, our requirement was a little more complex requiring renumbering of LineNum as the sequence changes and simultaneous update to a Map, which stored the key, value pairs for each item. 



MoveUpButton
void clicked()
{
    int idx_mv = ModelTree.getSelection();
    int idx;
    ;

    if (idx_mv)
    {
        idx = ModelTree.getPrevSibling(idx_mv);
        if (idx)
        {
            idx_mv = ModelTree.moveItem(idx, ModelTree.getParent(idx_mv), idx_mv);
            ModelTree.selectItems(idx, idx);
        }
    }
}
MoveDownButton
void clicked()
{
    int idx_mv = ModelTree.getSelection();
    int idx;
    ;

    if (idx_mv)
    {
        idx = ModelTree.getNextSibling(idx_mv);
        if (idx)
        {
            idx_mv = ModelTree.moveItem(idx_mv, ModelTree.getParent(idx_mv), idx);
            ModelTree.selectItems(idx_mv, idx_mv);
        }
    }
}