Quantcast
Channel: Microsoft Dynamics 365 Community
Viewing all 10657 articles
Browse latest View live

URL Parameters And Values

$
0
0
The new Microsoft Dynamics AX runs in the browser and parts of the navigation through the UI are done via URL parameters. Since I wasn’t able to find a list of them in the official documentation...(read more)

Finding the Right Business IT Solution for Fast Track Growth

$
0
0
For Small & Midsize Enterprises (SMEs) getting to grips with your IT systems and business solutions when you are giving your all into getting your new venture off the ground can be a real challenge. It's a dilemma that faces thousands of businesses ...read more

Extension capabilities of AX 7 RTW – Security Duties

$
0
0
In my last post I covered the extension capabilities of Data entities. In this post, I will cover the extension capabilities of Security duties. There are many examples available of security duties extension...(read more)

High Level Overview of Microsoft Dynamics AX 2012 Licensing and Security Architecture

$
0
0
The most straight forward way to customize which actions a specific user may perform in Microsoft Dynamics AX 2012 R3 is by assigning multiple Security Roles to a user. Microsoft Dynamics AX 2012 R3 provides...(read more)

Extension capabilities of AX 7 RTW – Security Roles

$
0
0
In my last post I covered the extension capabilities of security duties. In this post, I will cover the extension capabilities of Security roles. There are many examples available of security roles extension...(read more)

Understanding Address Framework Technically

$
0
0
LogisticsPostalAddress (Address): This table stores the actual physical postal address.
Postal Address have 2 important fields ValidFrom, ValidTo. This means that there could be multiple entries.

LogisticsElectronicAddress (Contact): This table stores all the contacts. Contacts are of 2 types
·         Contacts linked directly to Customer/Vendor.
·         Contacts linked to a Postal Address.

In Microsoft Dynamics AX, you add postal and electronic address information to entities such as customer, vendor, or contact person by using the DirPartyPostalAddressView and DirPartyContactInfoView views.

Table
Description
DirPartyTable
Global address book. This will contain entries for all people and organizations 
you deal with, including customers, suppliers, employees, etc.
This information is maintained across the entire organization. NB the table structure often refers to address book entries as 'parties'. Generally other records (like customer, supplier, etc) will reference a record in this table by a field named Party.
LogisticsLocation
This is a single 'location' that can be attached to one or more address book entries. This is similar in principle to the old 'Address' table from Ax2009, that no longer exists - The main difference now being that the location header always points to an address book entry, whereas in 2009 the Address table could point to anything.

Note that this is not an address - Physical address details are stored in
LogisticsPostalAddress
LogisticsPostalAddress
A postal address, linked to a LogisticsLocation record via field Location.
LogisticsElectronicAddress
'Electronic' address details, such as email, phone, web address etc.

Each different type of address is represented as a separate record, delineated by 'Type'. This links to the location record.
DirPartyLocation
This table links entries in the LogisticsLocation table to an address book entry (DirPartyTable).
LogisticsLocationRole
This defines types of roles that an address are classified as, such as "Delivery", "Invoice", etc.
DirPartyLocationRole
Links a location role type (LogisticsLocationRole) and an address book entry (DirPartyTable)
DirPartyPostalAddressView (view)
This is a view that collates address book entries with their linked postal adresses



Simple job to understand the relation between DirPartyLocation and DirPartyTable. Creation of postal address and contact info is shown below:

static void AddressJob(Args _args)  // X++ job.
{

    // Declare variables: views.
    DirPartyContactInfoView contactInfo;
    DirPartyPostalAddressView postalAddress;

    // Declare variables: tables.
    ContactPerson contactperson;
    DirPartyTable partyTable = DirPartyTable::findByName("Contoso", DirPartyType::Organization);
    LogisticsPostalAddress logisticsPostalAddressInfo;

    // Declare variables: classes.
    ContactPersonEntity contactPersonEntity;
    LogisticsLocationEntity entity;

    // Declare variables: extended data types.
    Phone phone;

    // Declare variables: primitives.
    str firstName;
    str middleName;
    str lastName;
   
    // Create and populate the contact person.
    contactPersonEntity = ContactPersonEntity::construct(contactPerson);
    contactPersonEntity.parmFirstName('Contact');
    contactPersonEntity.parmMiddleName('M.');
    contactPersonEntity.parmLastName('Person');
    contactPersonEntity.parmAssistantName('AssistantName');
    contactPersonEntity.parmBillingInformation('Billing info');
    contactPersonEntity.parmCharacter('Character description');
    contactPersonEntity.parmComputerNetworkName('Computer network name');
    contactPersonEntity.parmContactForParty(partyTable.RecId);
    contactPersonEntity.parmContactMemo('Memo');
    contactPersonEntity.parmContactPersonId('CP61');
    contactPersonEntity.parmLoyalty('Loyalty');
    contactPersonEntity.parmMileage('Mileage');
    contactPersonEntity.parmOfficeLocation('Office location');
    contactPersonEntity.parmOutlookCategories('Outlook categories');
    contactPersonEntity.parmProfession('Profession');
    contactPersonEntity.parmSensitivity(smmSensitivity::Personal);
    contactPersonEntity.parmSpouse('Spouse');
    contactPersonEntity.parmTimeAvailableFrom(1000);
    contactPersonEntity.parmTimeAvailableTo(2000);
    contactPersonEntity.write();

    // Populate the postal address information by using the view.
    postalAddress.Street = 'One Microsoft Way';
    postalAddress.City = 'Redmond';
    postalAddress.State = 'WA';
    postalAddress.ZipCode = '98052';
    postalAddress.CountryRegionId = 'US';




    // Update the postal address information.
    contactPersonEntity.createOrUpdatePostalAddress(postalAddress);

    // Populate the contact information by using the view.
    contactInfo.Locator = '555-555-5555';
    contactInfo.Type = LogisticsElectronicAddressMethodType::Phone;
    contactInfo.IsPrimary = true;
    // Update the contact information.
    contactPersonEntity.createOrUpdateContactInfo(contactInfo);
   
    // Verify that the data was stored correctly.
    firstName = contactPersonEntity.parmFirstName();
    middleName = contactPersonEntity.parmMiddleName();
    lastName = contactPersonEntity.parmLastName();
   
    logisticsPostalAddressInfo = entity.getPostalAddress();
    phone = contactPersonEntity.getPrimaryElectronicAddressLocation().getPhone();

    info(firstName + " " + middleName + " " + LastName +
        " is located at " + logisticsPostalAddressInfo.StreetNumber +
        " " + logisticsPostalAddressInfo.Street + ", " +
        logisticsPostalAddressInfo.City + ", " +
        logisticsPostalAddressInfo.State + " " +
        logisticsPostalAddressInfo.ZipCode +
        ". They can be contacted at " + phone + ".");
}



Note:
Ø  LogisticsPostalAddressView consists of LogisticsPostalAddress and LogisticsLocation.
Ø  DirPartyPostalAddressView consists of LogisticsPostalAddressView and DirPartyLocation.
Ø  DirPartyLocation consists of Party and Location.


Retrieve Customer/Vendor address:

static void CustomerAddressBook (Args _args)
{
    CustTable               custTable;
    DirPartyTable           dirPartyTable;
    DirPartyLocation        partyLocation;
    LogisticsLocation       logisticsLocation;
    LogisticsPostalAddress  postalAddress;
    ;
    custTable       = custTable::find('Test1001'); // Customer account id
    dirPartyTable   = dirPartyTable::findRec(custTable.Party);
    while select partyLocation
        where   partyLocation.Party     == dirPartyTable.RecId
    {
        logisticsLocation = logisticsLocation::find(partyLocation.Location);       
        if(logisticsLocation.IsPostalAddress)
        {
            postalAddress = LogisticsPostalAddress::findByLocation(logisticsLocation.RecId);           
            info(strFmt("%1 - %2",
                logisticsLocation.Description,
                postalAddress.CountryRegionId));
        }       
    }
}

  


Get Email address:     
             
static void CustomerEmailAddresses(Args _args)
{
    CustTable                   custTable;
    DirPartyTable               dirPartyTable;
    DirPartyLocation            partyLocation;
    LogisticsLocation           logisticsLocation;
    LogisticsElectronicAddress  electronicAddress;
    ;
    custTable       = custTable::find('Test1001'); // Customer account id
    dirPartyTable   = dirPartyTable::findRec(custTable.Party);
    while select partyLocation
        where   partyLocation.Party     == dirPartyTable.RecId
    {
        logisticsLocation = logisticsLocation::find(partyLocation.Location);       
        while select electronicAddress
            where   electronicAddress.Location  == logisticsLocation.RecId
            &&      electronicAddress.Type      == LogisticsElectronicAddressMethodType::Email
        {           
            info(strFmt("%1",electronicAddress.Locator));
        }       
    }
}




Get Phone number from warehouses:

static void PhoneNumbersAttachedToWarehouse(Args _args)
{

    InventLocation                      inventLocation;
    LogisticsEntityPostalAddressView    postalAddressView;
    LogisticsElectronicAddress          elecAddress;
    LogisticsLocation                   contactLocation;
   
    inventLocation = inventLocation::find('NB');
   
    if(inventLocation)
    {
        while select postalAddressView 
            where   postalAddressView.Entity            == inventLocation.RecId
            &&      postalAddressView.EntityType        == LogisticsLocationEntityType::Warehouse
        {               
            while select elecAddress               
                where   elecAddress.Type                == LogisticsElectronicAddressMethodType::Phone
            join contactLocation                                   
                where   contactLocation.ParentLocation  == postalAddressView.Location
                &&      contactLocation.RecId           == elecAddress.Location
            {           
                info(elecAddress.Locator);  
            }                  
        }
    }

}



Here is the static method which I've written to make the life easier for the developer, to find the already existing combination of street, city, zip code, state, country etc.
If it finds the existing data in the tables then it will return the ‘LogisticsPostalAddress’buffer else it creates the new record in the LogisticsPostalAddresstable using the below logic.       

publicstatic LogisticsPostalAddress retrieveMatchingPostalAddress(
    Description                     _locationName,
    LogisticsAddressStreet          _street,
    LogisticsAddressCity            _city,
    LogisticsAddressCountyId        _county,
    LogisticsAddressZipCodeId       _zipCode,
    LogisticsAddressStateId         _state,
    LogisticsAddressCountryRegionId _countryRegionId,
    LogisticsPostalAddressRecId     _originalPostalAddress   = 0
    )
{
    LogisticsPostalAddress              ret;
    LogisticsPostalAddressEntity        postalAddressEntity = new LogisticsPostalAddressEntity();
    LogisticsPostalAddressView          postalAddressView;
    LogisticsPostalAddress              originalPostalAddress;
    LogisticsLocation                   originalLocation;
    boolean                             createAddress = false;

    if (_originalPostalAddress != 0)
    {
        originalPostalAddress   = LogisticsPostalAddress::findRecId(_originalPostalAddress);
        originalLocation        = LogisticsLocation::find(originalPostalAddress.Location);

        if (originalLocation.Description            == _locationName
        && originalPostalAddress.Street             == _street
        && originalPostalAddress.City               == _city
        && originalPostalAddress.ZipCode            == _zipCode
        && originalPostalAddress.State              == _state
        && originalPostalAddress.County             == _county
        && originalPostalAddress.CountryRegionId    == _countryRegionId)
        {
            ret = originalPostalAddress;
        }
        else
        {
            createAddress = true;
        }
    }
    else
    {
        createAddress = true;
    }

    if (createAddress)
    {
        postalAddressView.LocationName      = _locationName;
        postalAddressView.Street            = _street;
        postalAddressView.City              = _city;
        postalAddressView.ZipCode           = _zipCode;
        postalAddressView.State             = _state;
        postalAddressView.County            = _county;
        postalAddressView.CountryRegionId   = _countryRegionId;

        ret = postalAddressEntity.createPostalAddress(postalAddressView);
    }

    return ret;
}



UtilElements in AX 7

$
0
0

In older versions of Dynamics AX, you can get information about AX application objects (metadata) through system “tables” such as UtilElements. This doesn’t work anymore in AX 7. These tables still exist, but they don’t have any data, therefore you have to migrate to another solution.

AX 7 comes with a rich framework for metadata, implemented in several assemblies in namespace Microsoft.Dynamics.AX.Metadata. But it’s too complex for simple tasks – you can make it much simpler by using MetadataSupport class. For example, the following piece of code iterates through all form names:

var forms = Microsoft.Dynamics.Ax.Xpp.MetadataSupport::FormNames();
while(forms.MoveNext()){print forms.Current;
}

This is even easier than before!

Expect Deep-Dive Learning at AXUG Focus 2016

$
0
0
You may expect a very different AXUG Focus event in 2016 - one dedicated to deep-dive face-to-face workshops. The Dynamics AX User Group (AXUG) will hold the AXUG Focus 2016 event on June 7 and 8 in Schaumburg, Illinois. The event aims to ...read more

Accrual amount in Accrued purchases report when discount is applied

$
0
0

This is about the following report – Procurement and Sourcing / Reports / Status / Accrued purchases.

In AX2012 (companing with AX2009) we’ve made a performance improvement of the report by changing it’s datasource. But if you use discounts the report might show you a wrong value. Below you will find a way to resolve it.

Scenario. In case you apply a discount to a purchase order and then post a packing slip, the amount of the packign slip’s Purchase, accrual is the amount before discount (for example, 1000), but the report will show you the amounts after discount (for example, 900). So there’s a discrepancy between the report and the real posting.

Below is an illustration of the code that will resolve the issue, but the report may work a bit slower. The new code lines are marked in yellow.

\Classes\VendAccruedPurchasesDP_NA\processReport
/// <summary>
/// Processes the SQL Server Reporting Services report business logic.
/// </summary>
/// <remarks>
/// This method provides the ability to write the report business logic. This method will be called by
/// SQL Server Reporting Services (SSRS) at run time. The method should compute data and populate the
/// data tables that will be returned to SSRS.
/// </remarks>
[SysEntryPointAttribute(false)]
publicvoid
processReport()
{
    VendInvoiceTrans        vendInvoiceTrans, vendInvoiceTransNotExists;
    VendTable vendTable;
    InventTransOrigin      inventTransOrigin;
    InventTrans            inventTrans;
VendInvoicePackingSlipQuantityMatch     qtyMatched,     qtyMatchedNotExists;
VendAccruedPurchasesPartialInvoicedQty  partialInvoiced, partialInvoicedBeforeCutOff;
    this.getParametersFromContract();
    this.processReportQuery();

     if (physicalOnly)
    {
        this.buildPhysicalOnlyVendAccruedPurchases(true);
        this.buildPhysicalOnlyVendAccruedPurchases(false);
    }
    else
    {
        this.buildVendAccruedPurchases();
    }

    // Now that all rows exist for the report, do set-based
    // updates to fill in the remaining columns
     // Remove the product receipt records that don’t have invoices and are after the cut-off date
    delete_from vendAccruedPurchasesTmp_NA
        where vendAccruedPurchasesTmp_NA.DatePhysical > cutOffDate
        notexistsjoin qtyMatched where
            qtyMatched.PackingSlipSourceDocumentLine == vendAccruedPurchasesTmp_NA.PackingSlipSourceDocumentLine;
     // Remove the records that have product receipts and invoices that are after the cut-off date and don’t have
    // invoices that are prior to the cut-off date
    delete_from vendAccruedPurchasesTmp_NA
        where vendAccruedPurchasesTmp_NA.DatePhysical > cutOffDate
        existsjoin qtyMatched where
            qtyMatched.PackingSlipSourceDocumentLine == vendAccruedPurchasesTmp_NA.PackingSlipSourceDocumentLine
        join vendInvoiceTrans where
            vendInvoiceTrans.SourceDocumentLine == qtyMatched.InvoiceSourceDocumentLIne
            && vendInvoiceTrans.InvoiceDate > cutOffDate
        notexistsjoin qtyMatchedNotExists where
            qtyMatchedNotExists.PackingSlipSourceDocumentLine == vendAccruedPurchasesTmp_NA.PackingSlipSourceDocumentLine
        join SourceDocumentLine, InvoiceDate from vendInvoiceTransNotExists where
            vendInvoiceTransNotExists.SourceDocumentLine == qtyMatchedNotExists.InvoiceSourceDocumentLIne
            && vendInvoiceTransNotExists.InvoiceDate <= cutOffDate;
     // Summation of partial invoiced quantity cannot be done in the
    // original insert_recordset as it would change the cardinality of
    // the rows in the report. Similarly, it can’t be done in a simple
    // update_recordset because update_recordset does not support summation..
    // Instead, do an insert_recordset with a sum into a staging table,
    // and then update out of that staging table.
     // At this point partialInvoiced may still contain quantities for the fully invoiced records.
    // We will delete them from vendAccruedPurchasesTmp_NA in the next statement.
     insert_recordset partialInvoiced (PackingSlipSourceDocumentLine, PartiallyInvoicedQuantity)
        select PackingSlipSourceDocumentLine from vendAccruedPurchasesTmp_NA
            groupby vendAccruedPurchasesTmp_NA.PackingSlipSourceDocumentLine
            where vendAccruedPurchasesTmp_NA.DatePhysical <= cutOffDate
                    joinsum(Quantity) from qtyMatched where
                        qtyMatched.PackingSlipSourceDocumentLine == vendAccruedPurchasesTmp_NA.PackingSlipSourceDocumentLine
                    existsjoin vendInvoiceTrans where
                        vendInvoiceTrans.SourceDocumentLine == qtyMatched.InvoiceSourceDocumentLIne
                        && vendInvoiceTrans.InvoiceDate <= cutOffDate;
     // Remove those records that have already been fully invoiced (Qty = InvoicedQty)
    delete_from vendAccruedPurchasesTmp_NA
        existsjoin partialInvoiced where
            partialInvoiced.PackingSlipSourceDocumentLine == vendAccruedPurchasesTmp_NA.PackingSlipSourceDocumentLine
            && vendAccruedPurchasesTmp_NA.Qty == partialInvoiced.PartiallyInvoicedQuantity;
     // Grab and sum up records that are invoiced prior to the cut-off date, but were received after the cut-off date
    insert_recordset partialInvoicedBeforeCutOff (PackingSlipSourceDocumentLine, PartiallyInvoicedQuantity)
        select PackingSlipSourceDocumentLine from vendAccruedPurchasesTmp_NA
            groupby vendAccruedPurchasesTmp_NA.PackingSlipSourceDocumentLine
            where vendAccruedPurchasesTmp_NA.DatePhysical > cutOffDate
                    joinsum(Quantity) from qtyMatched where
                        qtyMatched.PackingSlipSourceDocumentLine == vendAccruedPurchasesTmp_NA.PackingSlipSourceDocumentLine
                    existsjoin vendInvoiceTrans where
                        vendInvoiceTrans.SourceDocumentLine == qtyMatched.InvoiceSourceDocumentLIne
                        && vendInvoiceTrans.InvoiceDate <= cutOffDate;

    // Date the invoice was posted
    update_recordset vendAccruedPurchasesTmp_NA setting
        DateFinancial    = vendInvoiceTrans.InvoiceDate,
        CostAmountPosted = (vendInvoiceTrans.LineAmountMST / vendInvoiceTrans.Qty) * vendAccruedPurchasesTmp_NA.Qty
        join qtyMatched
            where qtyMatched.PackingSlipSourceDocumentLine == vendAccruedPurchasesTmp_NA.PackingSlipSourceDocumentLine
        joinmaxOf(InvoiceDate), LineAmountMST, Qty from vendInvoiceTrans
            where vendInvoiceTrans.SourceDocumentLine == qtyMatched.InvoiceSourceDocumentLine;
     // Vendor name
    update_recordSet vendAccruedPurchasesTmp_NA setting
        VendName = dirPartyTable.Name
        join dirPartyTable
        existsjoin vendTable where
            vendTable.AccountNum == vendAccruedPurchasesTmp_NA.InvoiceAccount &&
            vendTable.Party == dirPartyTable.RecId;
     // Cost amount posted (has to be calculated *after* Qty is calculated for partial invoicing)
    update_recordSet vendAccruedPurchasesTmp_NA setting
        CostAmountPhysical = (vendAccruedPurchasesTmp_NA.ValueMST / vendAccruedPurchasesTmp_NA.ReceivedQuantity) * (vendAccruedPurchasesTmp_NA.ReceivedQuantity – partialInvoiced.PartiallyInvoicedQuantity),
        CostAmountPosted = 0,
        qty              = (vendAccruedPurchasesTmp_NA.ReceivedQuantity – partialInvoiced.PartiallyInvoicedQuantity),
        Voucher          =
        where vendAccruedPurchasesTmp_NA.ReceivedQuantity != 0
        join partialInvoiced where
            partialInvoiced.PackingSlipSourceDocumentLine == vendAccruedPurchasesTmp_NA.PackingSlipSourceDocumentLine;

    // Any packing slip that is prior to the cut-off date and has invoices that are only after the cut-off date should be updated.
    // If there are invoices prior the cut-off date, then this update does not apply.
    update_recordSet vendAccruedPurchasesTmp_NA setting
        CostAmountPosted = 0
        where vendAccruedPurchasesTmp_NA.ReceivedQuantity != 0
        join qtyMatched where
            qtyMatched.PackingSlipSourceDocumentLine == vendAccruedPurchasesTmp_NA.PackingSlipSourceDocumentLine
        join vendInvoiceTrans where
            vendInvoiceTrans.SourceDocumentLine == qtyMatched.InvoiceSourceDocumentLIne
            && vendInvoiceTrans.InvoiceDate > cutOffDate
        notExistsjoin partialInvoiced where
            partialInvoiced.PackingSlipSourceDocumentLine == vendAccruedPurchasesTmp_NA.PackingSlipSourceDocumentLine;
     // Any packing slip that is prior to the cut-off date and has invoices that are before the cut-off date should be updated.
    update_recordSet vendAccruedPurchasesTmp_NA setting
        DateFinancial    = dateNull()
        where vendAccruedPurchasesTmp_NA.ReceivedQuantity != 0
        join partialInvoiced where
            partialInvoiced.PackingSlipSourceDocumentLine == vendAccruedPurchasesTmp_NA.PackingSlipSourceDocumentLine;
     // Update Costs and quantities for packing slips that are after the cut-off, but invoices that are before the cut-off
    update_recordSet vendAccruedPurchasesTmp_NA setting
        CostAmountPhysical = (vendAccruedPurchasesTmp_NA.ValueMST / vendAccruedPurchasesTmp_NA.ReceivedQuantity) * partialInvoicedBeforeCutOff.PartiallyInvoicedQuantity,
        CostAmountPosted = (vendAccruedPurchasesTmp_NA.ValueMST / vendAccruedPurchasesTmp_NA.ReceivedQuantity) * partialInvoicedBeforeCutOff.PartiallyInvoicedQuantity,
        qty              = partialInvoicedBeforeCutOff.PartiallyInvoicedQuantity
        where vendAccruedPurchasesTmp_NA.ReceivedQuantity != 0
        join partialInvoicedBeforeCutOff where
            partialInvoicedBeforeCutOff.PackingSlipSourceDocumentLine == vendAccruedPurchasesTmp_NA.PackingSlipSourceDocumentLine;

    // Accrual (has to be calculated *after* CostAmountPosted is populated)
    update_recordSet vendAccruedPurchasesTmp_NA setting
        Accrual = vendAccruedPurchasesTmp_NA.CostAmountPhysical – vendAccruedPurchasesTmp_NA.CostAmountPosted
        where vendAccruedPurchasesTmp_NA.DatePhysical <= cutOffDate;

    update_recordSet vendAccruedPurchasesTmp_NA setting
        Accrual = 0– vendAccruedPurchasesTmp_NA.CostAmountPosted
        where vendAccruedPurchasesTmp_NA.DatePhysical > cutOffDate;
    ttsbegin;
    whileselect forUpdate vendAccruedPurchasesTmp_NAZ
    {
        select RecId from inventTransOrigin
            where inventTransOrigin.InventTransId == vendAccruedPurchasesTmp_NA.InventTransID
        join inventTrans
            where inventTrans.InventTransOrigin   == inventTransOrigin.RecId
            &&    inventTrans.VoucherPhysical     == vendAccruedPurchasesTmp_NA.VoucherPhysical;
          if (inventTrans.DatePhysical && inventTrans.DateFinancial)
        {
            if (inventTrans.DatePhysical < inventTrans.DateFinancial)
            {
                accrual = inventTrans.costAmountPhysExclStdAdjustment();
            }
            else
            {

if (inventTrans.DatePhysical > inventTrans.DateFinancial)
                {
                    accrual = -inventTrans.costAmountPhysExclStdAdjustment();
                }
                else
                {
                    accrual = -inventTrans.CostAmountPosted;
                }
            }
        }
        else
        {
            if (inventTrans.DatePhysical)
            {
                accrual =  inventTrans.costAmountPhysExclStdAdjustment();
            }
            if (inventTrans.DateFinancial)
            {
                accrual =  -inventTrans.CostAmountPosted;
            }
        }
        vendAccruedPurchasesTmp_NA.Accrual = accrual;
        vendAccruedPurchasesTmp_NA.update();
    }
    ttsCommit;
}

Disclaimer. The described code changes are for your information only. Microsoft only supports installation of the packaged hotfix, and we do not recommend that you attempt to implement similar changes manually.

Addin reports in Visual Studio for New Microsoft Dynamics AX RTW

$
0
0
I came across addin reports and statistics in AX 7. You can access this using Visual studio. Navigate to Dynamics AX menu -> Addins -> Data Entity report . This report looks like below: It has these...(read more)

Challenges for trading companies using the project module

$
0
0
Using the project management and accounting module in companies that are not primarily operating in the business project area but rather in trade or manufacturing can be beneficial due to the numerous...(read more)

Understanding TFS with AX 2012 (III)

$
0
0
So now some basic tasks with TFS and their approach in AX. Let's look at the way the deletes are handled and then the renames, using a simple example. Create three classes test1, test2 and test3. Add...(read more)

How to deploy a translated chart of accounts in a multiple country project

$
0
0

Enterprises may have subsidiaries in multi countries, in that scenario you can utilize the multi-language capabilities in Microsoft Dynamics AX. This enables translation of the client interface, including menus and data translation.

In this blog post I will focus on translation of the shared chart of account functionality, this enables translation of the client interface, including menus and data translation.

In my example a company has two subsidiaries, in one AX instance. The first legal entity is in the USA and the second in Italy.
The chart of accounts is identical across legal entities, and each legal entity is required to have the chart of account in their own language.

In a real life scenario, you must also consider specific regulations from each country that relate to a chart of accounts.

 

The following example will demonstrate how to use the multi-language functionality in Dynamics AX to fulfill the scenario presented above

In order to fulfill the above requirements and demonstrate it in a proper way;

  • Firstly, use the shared chart of accounts across legal entities (USD and Italy)
    The shared chart of account language is English.
  • Secondly, use the translation functionality in the chart of accounts.
    You can find more information at the following TechNet article: TechNet Text translation (form) [AX 2012]
  • I’ve added another user to set the language interface
    The below diagram illustrate the basic concept of the shared chart of accounts, the use of translation functionality, and user language.

I would consider numbering the steps going forward so they are easier to follow.

  1. Go to General ledger| Setup| Chart of Accounts| Chart of accounts
  2. Select the shared chart of accounts
  3. Select your main account (110110 is used in this example)
  4. Select the Translations button (You have this listed as Transactions)

5. In the Text translation form, select the language and add the translation text.

Text translation
6. Set Language in user options, go to Select File| Tool| Options. Then under General tab change language to IT (Italian)

User options
7. Changing the user options will result in menus being translated to Italian. To see this change, go to General Ledger| Journals| General journal. Create and post a general journal entry from the Italian interface. Note the account name shows in Italian.
GL

GL 2

8. The posted transaction details are shown in Italian as demonstrated below.

Posted transactions
9. The below example demonstrates how the translation looks on a Ledger Transaction report (General ledger| Reports| Transactions| Ledger transaction)

Ledger Transactions
10. The below example demonstrates the multi-language functionality with the Trial Balance list page.
(General ledger| Common| Trial balance)

Balance list

The account list page shows the account name in English. As mentioned in TechNet Text translation (form) [AX 2012]

You also can use this form to create translated text for a main account name and a custom financial dimension value. The translations that you create are displayed everywhere that a main account name or custom financial dimension value is displayed, except on the main account list and list pages.

Balance list 2

Import/Export data using composite entity in new Microsoft Dynamics AX RTW

$
0
0
In this post I will cover import-export data using the composite entities in new Microsoft Dynamics AX RTW. There are 12 composite entities available out of box. I will take example of Customer Payment...(read more)

File upload and download in AX 7

$
0
0

New Dynamics AX is a web application running in cloud, so how can users work with files in such an environment? The answer is: in the same way as with other web applications. If you know how to add and download attachments in your webmail client, you can do it in AX 7 as well.

And it’s not too difficult for developers either.

Let me demonstrate it on a simple form I’ve built.

FormLook

When you click the Upload button, a dialog opens where you can pick a file on your computer and upload it. It even shows progress of uploading.

Uploading

The whole upload is triggered by a single statement: File::GetFileFromUser(). You don’t have to deal with any details.

By default, the file is uploaded to a temporary blob storage and can be accessed through some ugly URL such as this:

Uploaded

If you click the download button, it will navigate to the URL and your browser will do the rest:

SaveFile

Code of Download button is again a one-liner: new Browser().navigate(fileUrl).

This is the complete code of the form, showing also how to get the URL of the uploaded file:

[Form]publicclass UploadDownloadForm extends FormRun
{str fileUrl;
 
    [Control("Button")]class UploadButton
    {publicvoid clicked(){
            FileUploadTemporaryStorageResult result = File::GetFileFromUser() as FileUploadTemporaryStorageResult;
            if(result && result.getUploadStatus()){
                fileUrl = result.getDownloadUrl();
                info(fileUrl);
            }}} 
    [Control("Button")]class DownloadButton
    {publicvoid clicked(){new Browser().navigate(fileUrl);
        }}}

Your files typically aren’t accessible by URL, because they’re in database or in a secured storage. But that’s not a problem. Just load the content of your file to a stream and pass it to File::SendFileToUser(). It will put the file to the temporary blob storage and navigate to the URL, therefore users can download the file in the same way as above.


Add the mobile client to the tools menu again

$
0
0
A while ago I posted How to add the mobile client emulator to the Tools menu in AX 2012 . One of my colleagues, Ievgen Miroshnikov, has pointed out that there’s a much simpler way of achieving...(read more)

El nuevo Microsoft Dynamics AX listo para desplegar

$
0
0
Aunque ya llevamos tiempo hablando sobre la última versión de Microsoft Dynamics AX (aka “El nuevo”, “AX 7” o “ Rainier “) no ha sido hasta esta semana durante la Microsoft...(read more)

The New Dynamics AX

$
0
0
Last week was a busy week with the release to web of the new Dynamics AX, Tech Conference and training over the weekend. It was good to catch up with some familiar faces and meet some new people. With...(read more)

Using the new menu search

$
0
0
The new menu search feature is a handy tool to avoid clicking in the navigation menu. I’m still getting use to having it, but it is becoming quite handy to avoid having to click multiple times if...(read more)

Enabling document handling

$
0
0
If you are starting to use the new Dynamics AX and looking to use the document handling then you might want to enable it under the user option. Here is a quick walk through The assumption here...(read more)
Viewing all 10657 articles
Browse latest View live


Latest Images