如何在 D365FO 的现有量查询中增加字段和数据源(Add the new field or datasource in Inventory On hand form using X++ in D365FO)

我们需要为类 InventDimCtrl_Frm_OnHand 创建一个扩展,以使用方法 modifiedQueryBasedOnDatasourceName 来实现这种Inventory On hand定制。

通过这种方式,我们可以在网格中添加带有过滤选项的新字段。(不使用显示方法)。根据需求,我们可以在表单中添加来自现有数据源以及新数据源的字段。

[ExtensionOf(classStr(InventDimCtrl_Frm_OnHand))]
final class InventDimCtrl_Frm_OnHandClass_Extension
{
    public void modifyQueryBasedOnDatasourceName(
                                                Query _inventSum_DS_Query,
                                                str _inventSum_DS_Name,
                                                FormDataSource _inventDim_DS)
    {
        Query query;
        QueryBuildDataSource qbds;
        QueryBuildDataSource qbdsInventOnHandItemListView;
        QueryBuildDataSource qbdsInventTable;
        Counter loop;
        boolean qbdsExists;
        next modifyQueryBasedOnDatasourceName(_inventSum_DS_Query, _inventSum_DS_Name, _inventDim_DS);
         
        query =   _inventSum_DS_Query;
     
        qbdsInventTable = query.dataSourceTable(tableNum(InventTable));
     
        if (qbdsInventTable)
        {
            qbdsInventTable.addGroupByField(fieldNum(InventTable, BinLocation));
            qbdsInventTable.addGroupByField(fieldNum(InventTable, ItemStatus));
            qbdsInventTable.addGroupByField(fieldNum(InventTable, PackQtyString));
            qbdsInventTable.addGroupByField(fieldNum(InventTable, PartNumber));
            qbdsInventTable.addGroupByField(fieldNum(InventTable, PromotionApplicable));
            qbdsInventTable.addGroupByField(fieldNum(InventTable, PurchaseMultiple));
            qbdsInventTable.addGroupByField(fieldNum(InventTable, ManufacturerCode));
     
            for (loop = 1; loop <= _inventSum_DS_Query.dataSourceCount(); loop++)
            {
                qbds =   _inventSum_DS_Query.dataSourceNo(loop);
     
                if (qbds.table() == tableNum(InventOnHandItemListView))
                {
                    qbdsExists = true;
                    break;
                }
            }
     
            if (!qbdsExists)
            {
                qbdsInventOnHandItemListView = query.dataSourceTable(tableNum(InventTable)).addDataSource(tableNum(InventOnHandItemListView));
                qbdsInventOnHandItemListView.addLink(fieldNum(InventOnHandItemListView, ItemId), fieldNum(InventTable, ItemId));
                qbdsInventOnHandItemListView.joinMode(JoinMode::InnerJoin);
     
                qbdsInventOnHandItemListView.addRange(fieldNum(InventOnHandItemListView, LanguageId)).value(queryValue(new xInfo().language()));
            }
            else
            {
                qbdsInventOnHandItemListView = query.dataSourceTable(tableNum(InventOnHandItemListView));
                    qbdsInventOnHandItemListView.addRange(fieldNum(InventOnHandItemListView, LanguageId)).value(queryValue(new xInfo().language()));
            }
     
            qbdsInventOnHandItemListView.addGroupByField(fieldNum(InventOnHandItemListView, ManufacturerName));
            qbdsInventOnHandItemListView.addGroupByField(fieldNum(InventOnHandItemListView, VendorID));
            qbdsInventOnHandItemListView.addGroupByField(fieldNum(InventOnHandItemListView, VendorName));
            qbdsInventOnHandItemListView.addGroupByField(fieldNum(InventOnHandItemListView, CoverageGroup));
            qbdsInventOnHandItemListView.addGroupByField(fieldNum(InventOnHandItemListView, ProductType));
            qbdsInventOnHandItemListView.addGroupByField(fieldNum(InventOnHandItemListView, ItemName));
            qbdsInventOnHandItemListView.addGroupByField(fieldNum(InventOnHandItemListView, ItemDescription));
            qbdsInventOnHandItemListView.addGroupByField(fieldNum(InventOnHandItemListView, SearchName));
            qbdsInventOnHandItemListView.addGroupByField(fieldNum(InventOnHandItemListView, ProductDimensionGroup));
            qbdsInventOnHandItemListView.addGroupByField(fieldNum(InventOnHandItemListView, StorageDimensionGroup));
            qbdsInventOnHandItemListView.addGroupByField(fieldNum(InventOnHandItemListView, TrackingDimensionGroup));
            qbdsInventOnHandItemListView.addGroupByField(fieldNum(InventOnHandItemListView, ItemModelGroupID));
            qbdsInventOnHandItemListView.addGroupByField(fieldNum(InventOnHandItemListView, BasePurchasePrice));
            qbdsInventOnHandItemListView.addGroupByField(fieldNum(InventOnHandItemListView, BaseSalesPrice));
            qbdsInventOnHandItemListView.addGroupByField(fieldNum(InventOnHandItemListView, BaseCostPrice));
            qbdsInventOnHandItemListView.addGroupByField(fieldNum(InventOnHandItemListView, InventUnit));
            qbdsInventOnHandItemListView.addGroupByField(fieldNum(InventOnHandItemListView, SalesUnit));
            qbdsInventOnHandItemListView.addGroupByField(fieldNum(InventOnHandItemListView, PurchUnit));
            qbdsInventOnHandItemListView.addGroupByField(fieldNum(InventOnHandItemListView, ItemGroupId));
            qbdsInventOnHandItemListView.addGroupByField(fieldNum(InventOnHandItemListView, ProductSubType));
        }
    }
}

| Tagged 

如何在D365FO使用视图在窗体上显示某一个财务维度(Financial dimensions)

在这篇文章中,我们将了解如何使用视图将财务维度(Financial dimensions)显示为表单网格中的字段,该视图将使用计算列直接从表中检索信息。这是一种快速获取信息以将其显示在列表中的方法,并且能够使用控件按维度值进行筛选。

解决方案:

如何做:

步骤 1:创建视图

我们创建一个新的视图 ( FTDDimensionSetView ),使用 DimensionAttributeValueSet 作为数据源,并添加 RecId 作为视图字段。请注意,此 RecId 将是  表中我们想要显示维度的DefaultDimension字段(本例中为CustTrans  ),这就是为什么我在视图中也将其命名为 DefaultDimension。

步骤 2:创建计算列方法

我们将对要添加到视图中的每个维度值使用一个静态方法。标准 DimensionSetEntity 实体需要对其进行概括,并且仅使用一个复杂的方法,在配置好所有维度后,使用插件加载所有维度,这些维度会自动创建,因为每个实现都有不同的维度……在我们的例子中,我们不需要额外的复杂性,因为我们已经知道并拥有我们想要显示的维度。保持简单!

这里有 3 种方法(我决定将逻辑放在一种通用方法中,所以有 4 种)。

public class FTDDimensionSetView extends common
{
    private static str getSQLStringForDimension(DimensionRefFieldName _dimensionName)
    {
        DimensionAttribute dimensionAttribute = DimensionAttribute::findByName(_dimensionName);
 
        return dimensionAttribute.DimensionValueColumnName;
    }
 
    private static str getDepartment()
    {
        return FTDDimensionSetView::getSQLStringForDimension(FTDDimensionUtils::Department);
    }
 
    private static str getCostCenter()
    {
        return FTDDimensionSetView::getSQLStringForDimension(FTDDimensionUtils::CostCenter);
    }
 
    private static str getRetailChannel()
    {
        return FTDDimensionSetView::getSQLStringForDimension(FTDDimensionUtils::RetailChannel);
    }
 
}

在这些方法中,我们将从配置它们的表 DimensionAttribute 中获取 SQL 中的列名称(对 VS 隐藏)。(FTDDimensionUtils 类中的值只是该表的名称字段的值)。

步骤 3:创建字符串计算列

现在,我们创建 3 个新的计算列,并使用属性View 方法将它们与上面创建的适当方法关联 。

如果在同步我们的视图之后,我们转到 SQL 并查看它的设计,它可以帮助我们直观地了解 计算列 实际上是什么:

步骤 4:从 CustTrans 添加新关系

现在,我们必须添加从 CustTrans  视图的关系。如果您想将财务维度添加到任何其他表格中,则只需重复执行此步骤和步骤 5(将其添加到表单)。因此,正如所有良好的发展一样,我们创建了一个非常有用、简单且可重复使用的代码片段!

第 5 步:在表单中使用它

将新视图作为新的相关数据源添加到表单,将字段添加到网格…

瞧! 请注意,我们可以通过它们进行筛选!需求匹配,客户满意

我希望这篇文章能够对你,匆忙的开发人员有所帮助,就像我之前知道它就会对我有所帮助一样。

Tax is regulated on purchase ID xxx. Purchase orders cannot be rearranged when individual purchase orders are tax regulated.

The reason why you get this error message is because you made the tax adjustment first at the individual invoice Level. Later on then you consolidated (rearranged) two or more invoices(PO partially invoiced) and AX says that it does not like that.

To get this fixed try the following:

1) Open the invoice for which you made the tax adjustment and set the tax amount back to what AX originally calculated

2) Rearrange, that is consolidate, the invoices

3) Before posting the rearranged invoices adjust the sales tax by opening the sales tax form at the vendor invoice Header or PO invoice posting.

4) Post your invoices.

如何D365FO使用视图使Display方法可以被过滤(How to create a filter on display method using view in D365FO)

基于Display的方法的表单字段不可过滤,但在某些情况下,客户希望这些字段可过滤(Filter on display method)。有两种方法可以使显示字段可过滤,我们将在本博客中仅解释最佳方法(使用最佳实践)。

在我们的案例中,供应商名称字段是一个基于Display方法的字段,并且不可过滤。

1.创建一个视图:

– metadata: 我们需要获取将替换显示字段的字段以及将用于与表单数据源创建关系的字段的表。(在我们的例子中是 VendTable 和 DirPartyTable)

– fields: 将替换显示字段的字段和我们将用于与表单数据源创建关系的字段。(在我们的例子中是 Name 和 AccountNum)

视图

2.在 FormDatasource(我们的案例 PurchLine)表上,我们需要添加一个与我们创建的 VendTableName 视图的新关系。

添加与视图的新关系

3. 在我们的表单上添加视图 VendTableName 作为数据源,并在 VendTableName FormDatasouce 属性上与主数据源(PurchLine)创建连接。

添加视图 VendTableName 作为数据源
create a join with the primary datasource

4. 最后一步是在表单网格上添加我们想要的视图数据字段。

输出结果:

| Tagged 

如何在D365FO工作流中使用审核编辑功能(how to use approval editable in d365fo workflow)

在Dynamics 365 F&O工作流开发过程中,配置采购订单工作流时,有两个审批元素可供使用,一个是“审批采购订单”,另一个是“可编辑的审批采购订单”(下文也将对其进行突出显示)。我的问题是关于第二个元素的开发,即“可编辑的审批采购订单”。根据我的测试,如果在配置过程中将此元素关联起来,系统将允许审批人编辑采购订单,然后在之后进行审批操作。

3515.editable-WF.png

可编辑的审批仅允许审批人编辑所选记录(他们正在审批的)。您可以按照以下步骤实现相同的功能:

  • 复制工作流审批工件并相应地更改其名称(例如,在我的情况下为“CaseDetailBaseApprovalEdit”),并将其与简单审批一起添加到支持的元素中。
  • 在表中创建一个方法(例如,我的情况下的“editAllowed()”)。
public boolean editAllowed()
{
    WorkflowElementTable workflowElementTable;
    WorkflowWorkItemTable workflowWorkItemTable;
 
    select * from workflowWorkItemTable
        where   workflowWorkItemTable.RefRecId      == this.RecId
            &&  workflowWorkItemTable.Status        == WorkflowWorkItemStatus::Pending
            &&  workflowWorkItemTable.UserId        == curUserId()
            &&  workflowWorkItemTable.CompanyId     == this.DataAreaId;
 
    select * from workflowElementTable
        where workflowElementTable.ElementId == workflowWorkItemTable.ElementId;
 
    return workflowElementTable.ElementName == workflowApprovalStr(CaseDetailBaseApprovalEdit)
        ||  this.CaseWFStatus == CaseWFStatus::Draft;
}
  • 覆盖表单数据源的 active() 方法(在我的情况下,我创建了 OOTB 表单数据源的 CoC)。
public int active()
{
   FormRun formRun = this.formRun() as FormRun;
   FormDataSource ds = formRun.dataSource();
   CaseDetailBase table = ds.cursor();
 
   boolean allowEdit = table.editAllowed();
 
   ds.allowEdit(allowEdit);
 
   if(allowEdit)
   {
       formRun.design().viewEditMode(ViewEditMode::Edit);
   }
   else
   {
       formRun.design().viewEditMode(ViewEditMode::View);
   }
 
   return next active();
}

如何在D365FO 中使用 Num2Str(因为每次使用的时候都会忘记)

参数 :

number :要转换为字符串的实数。

  • character:文本中所需的最少字符数。
  • decimals: 所需的小数位数。
  • separator1 : 小数分隔符
  • separator2:A 千分号分隔符

seperator1 参数的可能枚举值为:点(.),逗号 (,)

seperator2 参数的可能值为:无,点(.),逗号(,),空格( )

使用

static void Job_Num2Str(Args _args) 
{ 
    real realNum = 12345.1294567890123456777; // 19 decimals places. ; 
    info(Num2Str(realNum,0,16,1,3)); // 16 decimal places 
    info(Num2Str(realNum,0,17,1,3)); // 17 decimal places }
}

输出

12 345.1294567890123457
12 345.13

 

| Tagged 

如何在D365FO导入Excel文件(How to import EXCEL using X++ in D365 FO)

开始之前的准备

  • 命名空间
  • 参考包(reference packages)
Using System.IO;
Using OfficeOpenXml;
Using OfficeOpenXml.ExcelPackage;
Using OfficeOpenXml.ExcelRange;

除了基本的包,我们还需要参考包:Directory

How to Import Records from Excel Using X++ Code in D365FO

第一部分代码

在这部分代码中,创建了一个导入对话框,在这里我们可以选择需要导入的文件,文件上传之后会被存储在临时的空间中

How to Import Records from Excel Using X++ Code in D365FO

第二部分代码

在这部分代码中,我们从导入的Excel中获取数据

How to Import Records from Excel Using X++ Code in D365FO

完整的代码

Using System.IO;
Using OfficeOpenXml;
Using OfficeOpenXml.ExcelPackage;
Using OfficeOpenXml.ExcelRange;
class RunnableClass1
{
    /// <summary>
    /// Runs the class with the specified arguments.
    /// </summary>
    /// <param name = "_args">The specified arguments.</param>
    public static void main(Args _args)
    {
        /*---------part 1 ------------------*/
        System.IO.Stream stream;
        ExcelSpreadsheetName sheet;
        FileUploadBuild fileUpload,fileUploadBuild;
        DialogGroup dialogUploadGroup;
        FormBuildControl formBuildControl;
        Dialog dialog=new Dialog("Excel Import Example");
        dialogUploadGroup=dialog.addGroup("@SYS54759");
        formBuildControl=dialog.formBuildDesign().control(dialogUploadGroup.name());
        fileUploadBuild=formBuildControl.addControlEx(classStr(fileUpload),"UploadExcel");
        fileUploadBuild.style(FileUploadStyle::MinimalWithFilename);
        fileUploadBuild.fileTypesAccepted(".xlsx");
        if(dialog.run() && dialog.closedOk())
        {
            FileUpload fileUploadControl=dialog.formRun().control(dialog.formRun().controlId("Upload"));
            FileUploadTemporaryStorageResult
            fileUploadResult=file::GetFileFromUser(classStr(FileUploadTemporaryStorageStrategy));
            //fileUploadResult=fileUploadControl.getFileUploadResult();
            /*------------------part 1 end---------------------*/
            /*------------------part 2---------------------*/
            if(fileUploadResult!= null && fileUploadResult.getUploadStatus())
            {
                stream=fileUploadResult.openResult();
                using(ExcelPackage  package= new ExcelPackage(stream))
                {
                    int rowCount, iterator;
                    package.Load(stream);
                    ExcelWorksheet worksheet= package.get_workbook().get_worksheets().get_Item(1);
                    OfficeOpenXml.ExcelRange range=worksheet.Cells;              
                    rowCount = worksheet.Dimension.End.Row - worksheet.Dimension.Start.Row + 1;
                    for(iterator=2;iterator<=rowCount;iterator++)
                    {
                        Info(range.get_Item(iterator,1).Value);
                        Info(range.get_Item(iterator,2).Value);
                        Info(range.get_Item(iterator,3).Value);
                    }
                }
            }
            /*------------------part 2 end---------------------*/
        }
        else
        {
            Error("error occured.");
        }
    }
}

导入

运行上面的Job之后,系统会弹出导入对话框,然后选择下面的文件。

How to Import Records from Excel Using X++ Code in D365FO
How to Import Records from Excel Using X++ Code in D365FO
How to Import Records from Excel Using X++ Code in D365FO

以下是点击“OK”之后的结果:

How to Import Records from Excel Using X++ Code in D365FO

关于Excel导出功能,请参考一下链接:

如何在D365FO导出Excel文件(How to export to EXCEL using X++ in D365 FO)

步骤

创建一个Job

Create and Export excel files in d365 using xpp d365snippets

添加以下代码

class RunnableClass2
{
    public static void main(Args _args)
    {
        CustTable custTable;
        DocuFileSaveResult saveResult =
    DocuFileSave::promptForSaveLocation("@ApplicationPlatform:OfficeDefaultWorkbookFileName","xlsx", null, "excel create and export");
        if (saveResult&& saveResult.parmAction() != DocuFileSaveAction::Cancel)
        {
            saveResult.parmOpenParameters('web=1');
            saveResult.parmOpenInNewWindow(false);
            System.IO.Stream
      workbookStream = new System.IO.MemoryStream();
            System.IO.MemoryStream
      memoryStream = new System.IO.MemoryStream();
            using(var package = new OfficeOpenXml.ExcelPackage(memoryStream))
            {
                var worksheets = package.get_Workbook().get_Worksheets();
                var worksheet = worksheets.Add("Sheet1");
                var cells = worksheet.get_Cells();
                var currentRow=1 ;
                /*-------HEADER PART -------*/
                var cell = cells.get_Item(currentRow,1);
                cell.set_Value("Customer Name");
                cell=null;
                cell = cells.get_Item(currentRow,2);
                cell.set_Value("Customer Address");
                /*-------HEADER PART END-------*/
                /*-------RECORD 1-------*/
                currentRow=2;
                cell= cells.get_Item(currentRow, 1);
                cell.set_Value("ABCD Trading");
                cell= null;
                cell= cells.get_Item(currentRow, 2);
                cell.set_Value("ABCD Complex, P.O Box :xxxxxx, XYZ Street");
                /*-------RECORD 1 END-------*/
                /*-------RECORD 2-------*/
                currentRow=3;
                cell= cells.get_Item(currentRow, 1);
                cell.set_Value("XYZ Trading");
                cell = null;
                cell = cells.get_Item(currentRow, 2);
                cell.set_Value("XYZ Complex, P.O Box :xxxxxx, ABC Street");
                /*-------RECORD 2 END-------*/
                package.Save();
            }
            memoryStream.Seek(0,System.IO.SeekOrigin::Begin);
            //Download the file.
            DocuFileSave::processSaveResult(memoryStream,saveResult);
        }
    }
}

把这个Job设置为启动项,运行它后我们可以看到以下界面:

Create and Export excel files in d365 using xpp d365snippets2

点击下载按钮,Excel就会被导出到下载文件夹里面

Create and Export excel files in d365 using xpp d365snippets2

关于Excel导出功能,请参考一下链接:

为D365 Devbox 的Windows虚拟机设置静态IP

Hyper-V的虚拟机默认使用Default Switch虚拟网卡来连接宿主机的网络,好处是不需要自己单独配置网络,直接切换选择使用就可以。但倘若是物理机使用mstsc远程连接到当前的虚拟机里,默认的Default Switch虚拟网卡就不能很好的满足我们的需求了,毕竟那玩意儿ip重启就变……

Hyper-v 设置

简单说明

  • Default Switch :Hyper-V默认使用的网络
  • E0 :手动创建的虚拟内部网络

虚拟机内访问互联网的网络由Default Switch虚拟网卡提供。而E0虚拟网卡则通过设置任意的静态IP(非本地回环等一些特殊的ip地址),对宿主机提供内网服务。

1.错误方式

为了实现目的,曾经试过修改虚拟机里的网卡为静态IP,但结果嘛:重启还是关机,又或者变更网络后,默认的 Default Switch 网卡会dhcp获取与设置的静态ip不一致,导致虚拟机内部无法连接到互联网。

后来很长一段时间里,一直使用的是新建内部网络来设置静态IP供mstsc使用。但是有个问题,若虚拟机需要连接到互联网,这时候需要共享宿主机的网络到内部网络里,而且似乎只能选择一个内部网络共享?最伤的还是,有时候宿主机开机后,Windows11 6月份的补丁很容易导致无法连接网络,所以每次只能卸载6月份更新的内容,要不然就是取消共享网络,改用回默认网卡,很是不便利。

2.正确方式

某天点着Hyper-V的设置,突然想起可以给虚拟机设置多网卡啊,这样问题不就得到解决了?

确实如此:使用 Default Switch 虚拟网卡来访问互联网,而自建的 E0 虚拟网卡用来设置静态IP,供同宿主机连接访问使用。

这样的好处是:和Hyper-V对应的物理机平常连接互联网的速度一样。虚拟机内部访问互联网的网络由Hyper-V自带的 Default Switch 虚拟网卡来提供,虚拟机与宿主机直接的网络连接由 E0 虚拟网卡提供,两者互不冲突(前提是你ip不能设置为一样的)。而通过共享、桥接、将Default Switch 网卡设置为静态IP的等方式,多多少少需要等待一会儿才能访问互联网,而且很有可能还会出现连接失败、受限制的问题,这并不方便。

2.1 新建内部网络

设置,虚拟交换机管理器,添加一个内部网络,名称随意。为了方便记录,博主这里用的是 E0 。

2.2 使用内部网络

找到对应的虚拟机,设置,添加网络硬件,选择上面创建好的 E0 网卡,下方网络加入。

2.3 设置静态IP(虚拟机)

虚拟机里找到网络适配器,找到创建好的 E0 虚拟内部网卡,将其ipv4信息“任意”填写一下。注意,这里不能使用本地回环等一些特殊的IP地址。比如:可以填写我们常见的 192.168.x.x ,后面两段就随意了。

宿主机配置

端口转发

将一个RDP服务(远程桌面协议)转发到任意端口,将进来的流量从3340端口转发到标准的RDP端口3389,使用上面分配的IP地址

netsh interface portproxy add v4tov4 listenport=3340 listenaddress=192.168.1.2connectaddress=192.168.168.168 connectport=3389

查看系统中的所有转发规则是否生效:

netsh interface portproxy show all

删掉一个特定的端口转发规则:

netsh interface portproxy delete v4tov4 listenaddress=192.168.1.2 listenport=3340

远程连接

如果需要访问到该虚拟机,直接远程宿主机的IP地址和对应的端口号就行了。

Code upgrade snippets from AX2009 to AX2012 and D365FO

InventDimSearch

In Microsoft Dynamics AX 2009, the InventDimSearch class was used to get information about the
inventory dimension setup. This class has been deleted and several new classes have been
implemented to make it possible to get information about the dimension setup.

In order to determine whether a dimension for a specific field is active in Microsoft Dynamics AX 2009,
the following code could be used:

InventDimSearch inventDimSearch = new InventDimSearch();
InventDimGroupId dimGroupId = InventTable::find(ItemId). DimGroupId;
;
if (inventDimSearch.findActive(dimGroupId,fieldNum(InventDim,wmsPalletId)))
{
    info(strFmt("The palletId dimension is active for dimension group %1",dimGroupId));
}

In Microsoft Dynamics AX 2012 & D365FO, this can be achieved by the following code:

InventTable inventTable;
InventDimGroupSetup inventDimGroupSetup;
InventDimGroupFieldSetup inventDimGroupFieldSetup;
 
inventDimGroupSetup = InventDimGroupSetup::newInventTable(inventTable);
inventDimGroupFieldSetup =
inventDimGroupSetup.getFieldSetup(fieldNum(InventDim,WMSPalletId));
 
if (inventDimGroupFieldSetup.isActive())
{
    info(strFmt("The palletId dimension is active for dimension group
    %1",inventDimGroupSetup.getStorageDimensionGroup()));));
}

EmplTable

In Microsoft Dynamics AX 2009

In Microsoft Dynamics AX 2012 & D365FO , we have HcmWorkerHelper class which gives much information about worker such as department, primary position, current legal entity and so on.

HcmWorkerRecId   hcmWorkerRecId =  HcmWorker::userId2Worker(curUserId());
HcmPositionRecId hcmPositionRecId = HcmWorkerHelper::getPrimaryPosition(hcmWorkerRecId);
 
HcmWorker currentWorker = HcmWorker::find(HcmWorkerLookup::currentWorker());
OMOperatingUnit department = HcmWorkerHelper::getPrimaryDepartment(currentWorker.RecId);
 
HcmWorker currentWorker = HcmWorker::find(HcmWorkerLookup::currentWorker());
CompanyInfo legalEntity = HcmWorkerHelper::getLegalEntity(currentWorker.RecId);

Unit converter

In Microsoft Dynamics AX 2009

UnitConvert::qty(Qty,FromUnitId,ToUnitId,ItemId);
Unit::decimals()

In Microsoft Dynamics AX 2012 & D365FO

UnitOfMeasureConverter::convert(_salesQty,  
               UnitOfMeasure::unitOfMeasureIdBySymbol(_inventUnit),  
               UnitOfMeasure::unitOfMeasureIdBySymbol(_salesUnit),  
               NoYes::Yes,  
               InventTable::itemProduct(_itemId),  
               NoYes::Yes);  
UnitOfMeasure::unitOfMeasureDecimalPrecision(UnitOfMeasure::unitOfMeasureIdBySymbol(unitID));

CompanyInfo

In Microsoft Dynamics AX 2009

CompanyInfo::standardCurrency()
CompanyInfo::find().CurrencyCode

In Microsoft Dynamics AX 2012 & D365FO

Ledger::accountingCurrency(CompanyInfo::current())

Currency

In Microsoft Dynamics AX 2009

Currency::amountCur2MST(*)
Currency::Amount()
Currency::exchRate(*)
Currency::exchRateSecond(*)

In Microsoft Dynamics AX 2012 & D365FO

CurrencyExchangeHelper::amountCur2MST(*)
CurrencyExchangeHelper::amount(*);
ExchangeRateHelper::exchRate(*)
ExchangeRateHelper::exchRateSecond()
| Tagged