Search your query

Wednesday, July 12, 2017

Display methods in AX Extension Table (Dynamics 365)

Display methods in AX Extension Table (Dynamics 365)


Steps:

1. Create a class and set a name like <"TableName" and "_" and "Extension" > (Example: PurchTable_Extension)

2. Class should be a static class  and public access specifier.

3. Add this attribute  [SysClientCacheDataMethodAttribute(true)] for each display method header.

4. Display method should be a static method and public access specifier.

5. Only one parameter that should be that particular table name.

6. Go to that particular form, Create one field and set the datasource property as the above mentioned table and in datamethod property, Type like ClassName::MethodName.
(Ex: HcmWorker_Extension::dispWorkerPositionTitle)

Example X++ Code: 

//This method is used to find the Position title of current worker.//

public static class HcmWorker_Extension
{
    // BP deviation documented
    [SysClientCacheDataMethodAttribute(true)]
    public static display HcmTitleId dispWorkerPositionTitle(HcmWorker _this)
    {
        HcmPositionWorkerAssignment workerAssignment;
        HcmPosition hcmPosition;
        HcmPositionDetail hcmPositionDetail;

        select firstonly worker, Position from workerAssignment
            where workerAssignment.Worker == _this.RecId
            join recid from hcmPosition
            where hcmPosition.RecId == workerAssignment.Position
            join Title, Position from hcmPositionDetail
            where hcmPositionDetail.Position == hcmPosition.RecId;

        return HcmTitle::find(hcmPositionDetail.Title).TitleId;
    }
}


Fetch CostCenter, Department Dimensions based on Worker's Position


// Fetch CostCenter, Department Dimensions based on Worker's Position //

     public static Name workerPositionCostCenter(HcmWorker _this)
    {
        HcmPositionWorkerAssignment     workerAssignment;
        HcmPosition                     hcmPosition;
        HcmPositionDefaultDimension     hcmPositionDefaultDimension;
        DimensionAttributeValueSet      dimensionAttributeValueSet;
        DimensionAttributeValueSetItem  dimensionAttributeValueSetItem;
        OMOperatingUnit                 omOperatingUnit;

        select firstonly worker, Position from workerAssignment
            where workerAssignment.Worker == _this.RecId
            join recid from hcmPosition
            where hcmPosition.RecId == workerAssignment.Position;

        select firstonly DefaultDimension from hcmPositionDefaultDimension
            where hcmPositionDefaultDimension.Position == hcmPosition.RecId

            join RecId from dimensionAttributeValueSet
                where dimensionAttributeValueSet.RecId ==          
                hcmPositionDefaultDimension.DefaultDimension

                join DimensionAttributeValueSet, DisplayValue from dimensionAttributeValueSetItem
                    where dimensionAttributeValueSetItem.DimensionAttributeValueSet ==
                             dimensionAttributeValueSet.RecId

                    join Name from omOperatingUnit
                        where  omOperatingUnit.OMOperatingUnitNumber ==
                              dimensionAttributeValueSetItem.DisplayValue
                            && omOperatingUnit.OMOperatingUnitType   ==
                                          OMOperatingUnitType::OMCostCenter; // You can change Operating Unit Type based on your requirement.

        return omOperatingUnit.Name;
    }

Friday, May 26, 2017

X++ code to attach the text file from local system directory and send an email.

class EmailTextFile
{      
   
    /// <summary>
    /// Attach the text file from local system directory and send an email using X++.
    /// </summary>
    /// <param name = "_args">The specified arguments.</param>

    public static void main(Args _args)
    {    
        EmailTextFile emailTextFile = new EmailTextFile();
       
        emailTextFile .sendMail();
    }
 
    private void sendMail()
    {
        SysMailerMessageBuilder     sysMailBuilder = new SysMailerMessageBuilder();
        SysMailerSMTP               smtp           = new SysMailerSMTP();
        System.IO.StreamReader      reader         = new System.IO.StreamReader(@"C:\test.txt");
        System.Byte[]               byte           = reader.CurrentEncoding.GetBytes(reader.ReadToEnd());
        System.IO.Stream            stream         = new System.IO.MemoryStream(byte);

        sysMailBuilder.setSubject("Regarding - sending mail");
        sysMailBuilder.setFrom("XXX@yyy.com");
        sysMailBuilder.addTo("yyy@zzz.com");
        sysMailBuilder.addAttachment(stream,'text file');
        smtp.sendNonInteractive(sysMailBuilder.getMessage());          
     
    }

}

Create and Save the text file in specific local directory

class CreateAndSaveTextFile
{      
   
    /// <summary>
    /// Create and Save the text file in specific local directory.
    /// </summary>
    /// <param name = "_args">The specified arguments.</param>
    public static void main(Args _args)
    {    
        CreateAndSaveTextFile createAndSaveTextFile= new CreateAndSaveTextFile ();

        createAndSaveTextFile.generateFile();      
    }

    private void generateFile()
    {
        System.IO.StreamWriter sw;
        InteropPermission perm = new InteropPermission(InteropKind::ClrInterop);
       
        try
        {
            perm.assert();

            sw = new System.IO.StreamWriter(@"C:\test.txt"); // specify the local file path for new file.
            sw.WriteLine('line 1');
            sw.WriteLine('line2');
            sw.Dispose();

            CodeAccessPermission::revertAssert();
         
        }
        catch
        {
            error("Error");
        }
    }
}

Friday, April 21, 2017

X++ Code to access Private / Protected methods and variables of AX class from Class extension (Get the table buffer value when extending the class).

Using System.Reflection;

We will not be able to access private / protected data member and methods of classes when you are going to create extension for them.

But there might be a situation to access those variables / methods from extension class. Reflection would be used in such this scenario.

Create an eventhandler extension class for VersioningPurchaseOrder -> and cosume PostConfirm method.

Using System.Reflection;

class VersioningPurchaseOrderEventHandlers
{
    /// <summary>
    /// accessing VersioningPurchaseOrder -> post_confirm method.
    /// </summary>
    /// <param name="args"></param>

    [PostHandlerFor(classStr(VersioningPurchaseOrder), methodStr(VersioningPurchaseOrder, confirm))]
    public static void VersioningPurchaseOrder_Post_confirm(XppPrePostArgs args)
    {
        VersioningPurchaseOrder   versioningPO;
        PurchTable                       purchTable;

        versioningPO = args.getThis();

        var bindFlags = BindingFlags::Instance | BindingFlags::NonPublic;

        var field = versioningPO.GetType().GetField("PurchTable", bindFlags);

        purchTable = field.getValue(versioningPO);

        if(purchTable)
        {
            info(purchTable.PurchId);
        }
    }

}

// We can also call / invoke the private / protected method(s) this VersioningPurchaseOrder class.

var bindFlags = BindingFlags::Instance | BindingFlags::NonPublic;

var createVersionMethod = versioningPO.GetType().GetMethod(methodStr(VersioningPurchaseOrder, createNewVersion), bindFlags);

if(createVersionMethod)
{
      createVersionMethod.Invoke(versioningPO , new System.Object[0]());
}