Showing posts with label D365FO. Show all posts
Showing posts with label D365FO. Show all posts

Thursday, 2 September 2021

Get Company Currency in X++ / AX

Here is the one-line code to get company currency

static void  main(Args _args)
{
    info(CompanyInfo::standardCurrency());
    info(Ledger::accountingCurrency(CompanyInfo::current());
}

SQL In Operator in X++ / D365FO

Sometimes we need to select the records only if the field value is in a set of expected values. Microsoft Introduce In Operator in X++ in D365FO. Remember this can only be used for enum type fields

First, you need to assign containers with specified values. Here is sample code where the query selects only the records with status delivered, Sales, Invoice in where clause

Static void main(Args args)
{
SalesTable  salesTable;
container con = [SalesStatus::Delivered, SalesType::Sales,  SalesStatus::Invoiced];
 
select from salesTable
where salesTable.SalesStatus in con;
}

Tuesday, 31 August 2021

Get item Category hierarchy using X++ in Ax / D365FO

Here you can find the X++ code to get complete item Category hierarchy using X++ in Ax

Static void main(Args args)

ItemId itemId = "MT0001";
EcoResProductCategory EcoResProductCategory;
EcoResCategory EcoResCategory,EcoResCategoryNext;
EcoResCategoryId parentCategory;
List li = new List(Types::String);
ListEnumerator enumer;

select * from EcoResCategory
join RecId from EcoResProductCategory
where EcoResCategory.RecId == EcoResProductCategory.Category
&& EcoResProductCategory.Product == InventTable::find(itemId).Product;
parentCategory = EcoResCategory.ParentCategory;
li.addStart(EcoResCategory.Name);

while (parentCategory)
{
    select * from EcoResCategory
        where EcoResCategory.RecId == parentCategory;
    //&& EcoResCategory.ParentCategory != 0;
        parentCategory = EcoResCategory.ParentCategory;
        li.addStart(EcoResCategory.Name);
}

enumer = li.getEnumerator();

while (enumer.moveNext())
{
    info(enumer.current());
}
}

Find item attributes using X++ in Ax and D365FO

 static void GetAttribute(Args _args)

{

    inventTable                 InventTable;

    EcoResProductAttributeValue ecoResProductAttributeValue;

    EcoResAttribute             ecoResAttribute;

    EcoResValue                 ecoResValue;

    while select InventTable where InventTable.itemid == "0000001"

        join RecId from ecoResProductAttributeValue

        where ecoResProductAttributeValue.Product == InventTable.Product

            join Name from ecoResAttribute

            where ecoResProductAttributeValue.Attribute == ecoResAttribute.RecId

                join ecoResValue

                where ecoResValue.RecId == ecoResProductAttributeValue.Value

    {

        info(strFmt("%1 - %2 - %3", InventTable.ItemId, ecoResAttribute.Name, ecoResValue.value()));

    }

}

Sending Email using X++ / Sending Email in Ax / D365FO/ Ax 7

 Here is the complete class for sending email notifications in Ax and D365FO. Make sure the email template is already created

/// <summary>
/// Class can  be used for sending email
/// </summary>
class EmailNotification
{
    private  boolean isEmailSent(Map _mappings, str _recipientEmail, str _templateName)
    {
        boolean         isSucess;
        SysEmailTable   sysEmailTable;       
        sysEmailTable = sysEmailTable::find(_templateName);
        SysEmailMessageTable msg = SysEmailMessageTable::find(sysEmailTable.EmailId, sysEmailTable.DefaultLanguage);
        if (msg)
        {
            str messageBody = msg.Mail;
            messageBody = SysLabel::resolveLabels(messageBody, sysEmailTable.DefaultLanguage);
            messageBody = SysEmailMessage::stringExpand(messageBody, SysEmailTable::htmlEncodeParameters(_mappings));
            messageBody = strReplace(messageBody, '\n', '<br>');
            var builder = new SysMailerMessageBuilder()
                .setFrom(sysEmailTable.SenderAddr)
                .addTo(_recipientEmail)
                .setSubject(msg.Subject)
                .setBody(messageBody);
            var message = builder.getMessage();
            isSucess = SysMailerFactory::getNonInteractiveMailer().sendNonInteractive(message);
        }
        return isSucess;
    }
    /// <summary>
    /// Sending single emails
    /// </summary>
    /// <param name = "_sysEmailTable">SysEmailTable buffer</param>
    /// <param name = "_mappings">Map</param>
    /// <param name = "_recipient">Recipient detail</param>
    /// <param name = "_attachment">File attachement</param>
    /// <returns>True/false</returns>
    private  boolean sendSingleMail(SysEmailTable   _sysEmailTable,
                                Map                 _mappings,
                                str                 _recipient,
                                FilenameOpen        _attachment = '')
    {
        boolean     isSucess;
        try
        {
            SysEmailTable::sendMail(_sysEmailTable.EmailId,
                                _sysEmailTable.DefaultLanguage,
                                _recipient,
                                _mappings,
                                _attachment,
                                '' ,
                                true,
                                _sysEmailTable.SenderName,
                                true); 
            isSucess  = true;
        }
        catch(Exception::Error)
        {
            isSucess = false;
        }
        return isSucess;
    }
    /// <summary>
    /// Method used for sending email
    /// </summary>
    /// <param name = "_emailTemplate">Email template name</param>
    /// <param name = "_mappings">Map</param>
    /// <param name = "_recipient">Recipient detail</param>
    /// <param name = "_attachment">File attachement</param>
    /// <returns>True/false</returns>
    public Static boolean sendEmail(str         _emailTemplate,
                                Map             _mappings,
                                str             _recipient   = '',
                                FilenameOpen    _attachment  = '')
    {
        SysEmailTable           sysEmailTable;
        boolean                 isSucess;
        sysEmailTable           = SysEmailTable::find(_emailTemplate); 
        EmailNotification emailNotification   =   new EmailNotification();
        if (sysEmailTable)
        {
            isSucess = emailNotification.isEmailSent(_mappings, _recipient, _emailTemplate);
        }
        else
        {
            info(strFmt("Email Template Not Found"));
        }
        return isSucess;
    }
}

Get Worker Primary Position in valid date time in X++ / Worker Primary Position in Ax

Here is the X++ code to find  Worker Primary Position in given date time

public static HcmWorkerPrimaryPosition findByWorker(

    HcmWorkerRecId      _worker,

    utcdatetime         _validFrom = DateTimeUtil::utcNow(),

    utcdatetime         _validTo   = _validFrom,

    boolean             _forUpdate = false,

    ConcurrencyModel    _concurrencyModel = ConcurrencyModel::Auto)

    {

        HcmWorkerPrimaryPosition hcmWorkerPrimaryPosition;


        hcmWorkerPrimaryPosition.selectForUpdate(_forUpdate );

        if (_forUpdate && _concurrencyModel != ConcurrencyModel::Auto)

        {

            hcmWorkerPrimaryPosition.concurrencyModel(_concurrencyModel);

        }


        if (_worker)

        {

            if (prmisdefault(_validFrom) && prmisdefault(_validTo))

            {

                select firstonly hcmWorkerPrimaryPosition

                    where hcmWorkerPrimaryPosition.Worker == _worker;

            }

            else if (_validFrom == _validTo)

            {

                select firstonly ValidTimeState(_validFrom) hcmWorkerPrimaryPosition

                    where hcmWorkerPrimaryPosition.Worker == _worker;

            }

            else

            {

                select ValidTimeState(_validFrom, _validTo) hcmWorkerPrimaryPosition

                    where hcmWorkerPrimaryPosition.Worker == _worker;

            }

        }


        return hcmWorkerPrimaryPosition;

    }


current database name in Ax

There is a class available in AX SysSQLSystemInfo. Using this we can get the current database name

static void databse_name(Args _args)
{
    info(SysSQLSystemInfo::construct().getloginDatabase());
}

Creating Default Dimension using X++ / D365FO / AX-2012

X++ code to create default dimension in both D365FO and AX-2012

public class DefaultDimesnionHelper

{

    public static DimensionDefault createDefaultDimension(container conAttribute,container attributeValue)
    {
        DimensionAttributeValueSetStorage   valueSetStorage                     new DimensionAttributeValueSetStorage();
        DimensionDefault        result;
        DimensionAttribute      dimensionAttribute;
        DimensionAttributeValue dimensionAttributeValue;
        int                     i;
        
  
        container               conAttr = conAttribute;
        container               conValue = attributeValue;
        str                     dimValue;
  
        for (i = 1; i <= conLen(conAttr); i++)
        {
            dimensionAttribute = dimensionAttribute::findByName(conPeek(conAttr,i));
      
            if (dimensionAttribute.RecId == 0)
            {
                continue;
            }
      
            dimValue = conPeek(conValue,i);
      
            if (dimValue != "")
            {
                // The last parameter is "true". A dimensionAttributeValue record will be created if not found.
                dimensionAttributeValue =
                    dimensionAttributeValue::findByDimensionAttributeAndValue(dimensionAttribute,dimValue,false,true);
          
                // Add the dimensionAttibuteValue to the default dimension
                valueSetStorage.addItem(dimensionAttributeValue);
            }
        }
  
        result = valueSetStorage.save();
        return result;
    }
}

Get Employee Dimensions using X++

 X++ code to find employee dimension

static void employeeDim(Args _args)

    {
        HcmEmployment                         hcmEmployment;
        DimensionAttributeValueSetItem  setItem;
        DimensionAttributeValue              dimAttrValue;
        DimensionAttribute                      dimAttribute;
        ;

        dimAttribute    = DimensionAttribute::findByName('CostCenter');

        while select hcmEmployment
              join RecId, DisplayValue from setItem
              where setItem.DimensionAttributeValueSet ==
              hcmEmployment.DefaultDimension
              join dimAttrValue
              where dimAttrValue.RecId == setItem.DimensionAttributeValue &&
              dimAttrValue.DimensionAttribute == dimAttribute.RecId       &&
              dimAttrValue.IsDeleted == false
        {
            info(strFmt("Employee personnel number  = %1  %2 = %3 ",
           HcmWorker::find(hcmEmployment.Worker).PersonnelNumber,
           dimAttribute.Name, setItem.DisplayValue));
        }
    }

Get List of Tables using X++

 Here is the X++ code to find the complete list of tables in Ax 2012 and D365FO

public void getTableList()   

{
    SysDictTable sysDictTable;
    Dictionary dict = new Dictionary();
    DictTable dictTable;
    
    for (int i=1; i<=dict.tableCnt(); i++)
    {
        sysDictTable=new SysDictTable(dict.tableCnt2Id(i));
        }
}

Friday, 3 August 2018

Import and Export project with multiple objects using VS - D365FO / AX 7

Overview
In Visual Studio we have solution that contains multiple projects. These projects helps us to organize and manage the elements. Each project contain elements from only one model. In order to move elements from one environment to another in D365, It can be easily done by using project package file which contains list of the elements added in the project.

To transfer the elements first create a project in VS and add elements to the project and follow the steps.

Export a project
Exporting a project is quite simple. You need to Right-click it and select Export Project. Provide the name of the project file and click Save. Project file is created with extension .axpp.
















Import a project
Now, you can use this file to move the elements into any environment by just simply importing the project. 

Go to Visual Studio and click on Dynamics 365 -> Import Project. Now select the .axpp file you need to import. By default all the elements in the project are selected for import. After selecting the elements click OK. 



















NOTE: Project package file doesn’t only carries the elements but also contains the information about the model and the layer they belongs to. So during import if the model doesn’t exists Visual Studio creates the missing model automatically.

Friday, 27 July 2018

How to get multiple selected records in control level event handlers in D365FO / AX 7

Purpose:
The purpose of this document is to show how to get multiple selected records in form control event handlers. 

Development:
First of all create new event handler class HRPayrollPayStatementEventHandler and subscribe to form button OnClicked event handler.

/// <summary>
/// The <c>HRPayrollPayStatementEventHandler</c> class is the event handler class for managing PayrollPayStatement form events
/// </summary>
class HRPayrollPayStatementEventHandler
{
   

    /// <summary>
    /// Click event handler
    /// </summary>
    /// <param name="_sender">Form control buffer</param>
    /// <param name="_e"> Event args</param>
    [FormControlEventHandler(formControlStr(PayrollPayStatement, CustomButton), FormControlEventType::Clicked)]
    public static void SLD_CustomButton_OnClicked(FormControl _sender, FormControlEventArgs _e)
    {
        FormDataSource    PayrollPayStatement_DS = _sender.formRun().dataSource(formDataSourceStr(PayrollPayStatement, PayrollPayStatement));

        MultiSelectionHelper    selectionHelper = MultiSelectionHelper::construct();
        PayrollPayStatement     payStatement;

        selectionHelper.parmDataSource(PayrollPayStatement_DS);
        payStatement  = selectionHelper.getFirst();

        if (payStatement.RecId)
        {
            while (payStatement.RecId != 0)
            { 
                info (payStatement.DocumentNumber);

                payStatement = selectionHelper.getNext();
            }          
        }
    }
}

Run AX report using X++

       Args                     args;      ReportRun          report;     salesLineProductPartProd salesLineProductPartProdLocal;     ;     ...