On currency in credit card expense transactions – Part 2

On currency in credit card expense transactions – Part 2

In the previous blog On currency in credit card expense transactions – Part 1 we have explored a case where the credit card currency and the local accounting currency in D365FO did match. But what if the card is issued in a currency different from the accounting currency of the legal entity?

Case 2: credit card currency <> accounting currency

For example, Hungarian employees (the official currency of Hungary is the Forint, abbreviated as HUF) may be given credit cards billed in Euro, since they are surrounded by the Euro zone. If we follow the same logic as before, if such a credit card statement is expressed in EUR, then it must be posted in EUR into the AP subledger:
  • 01.06.2019 Paid a hotel in Bratislava 500 EUR (the credit card provider applied the cross rate of 1.00)
  • 04.06.2019 Posted in AP subledger as 500 EUR (the daily rate was 322 HUF/EUR)
  • 30.06.2019 The credit card balance of June was withdrawn by the bank from the employee’s daily account in HUF @323,39 = 161 695 HUF. This is not recorded in D365FO for personal credit cards.
  • 30.06.2019 An AP revaluation is performed in D365FO. The liability is now worth 161 450 HUF at the current exchange rate of 322,9 HUF/EUR
  • 01.07.2019 The employee is reimbursed in the local currency by the employer with 161 450 HUF @322,9 HUF/EUR.
As a result, the employee will suffer a loss of 245 HUF but have to arrange himself/herself, as the benefits of travelling with an Euro card should overweigh any potential losses from the imperfect execution in D365FO by far.

Case 3: credit card currency <> accounting currency <> local currency

What if the trip was not to Slovakia (EUR) but to the Czech Republic who refused to adopt the Euro and retained their own Czech koruna (CZK)? Now all 3 currencies in the transaction are different:
  • The legal entity Accounting currency = HUF
  • The transaction Local currency = CZK
  • The Credit card Currency = EUR
The equation is still the same, the credit card balance is posted as a Forex liability in EUR. In the General Ledger voucher / accounting distribution the cross rate CZK -> HUF is kind of triangulated through the Euro: CZK -> EUR -> HUF where CZK -> EUR is the rate applied by the credit card institution. With that in mind, let us summarize the different business cases with the 3rd being the most generic and sound:
Case 1 Case 2 Case 3
Credit card Currency CHF EUR EUR
CC “Local” currency THB EUR CZK
Accounting currency CHF HUF HUF
Expense line THB EUR CZK
Line itemizations THB EUR CZK
Acc. distribution THB EUR CZK*
GL voucher Dr THB – Cr THB** Dr EUR – Cr EUR Dr CZK – Cr CZK**
AP subledger CHF EUR EUR
(*) The accounting currency HUF equivalent i.e. ‘amount MST’ is evaluated through the rate EUR -> HUF (**) Note the currency mismatch between the AP and GL ledgers. This spoils the AP ledger account with transactions in foreign currencies and may potentially kick the subledgers off balance.

On currency in credit card expense transactions – Part 1

On currency in credit card expense transactions – Part 1


The Expense management module in D365FO comes with an interface to credit card providers. I addressed this topic in an old blog of mine: visa-vcf-plain-text-credit-card-statement-into-dynamics-ax-with-xslt. Imported credit card transactions end up in the [Unattached] Credit card transactions list, ready to be taken over by the employee into an expense report.

There used to be a lot of misunderstanding with regards to the different currency rates and amounts and their meaning. Moreover, for a decade the Dynamics system had been posting the liability in the merchant transaction currency, which led to the expense report being split by currency code on posting into the AP ledger. It was wrong in many ways until we fixed it in a tremendous collaboration effort with Microsoft Support in 2018.

Case 1: credit card currency = accounting currency

In the expense report line there is an obligatory Payment method associated with the credit card type. It mandates how the employee is reimbursed for this part of the expense report. Typically, the Payment method (Expense management > Setup > General > Payment methods) is configured with the Offset account type = Worker which creates a liability against the AP account (vendor) associated with the employee.

If this liability is expressed in a currency different from the accounting currency of the legal entity, it starts accumulating exchange rate difference. If the payment takes place in a different accounting period, the employee may be reimbursed too much or too little. Indeed, the credit card it typically bound to a bank account of the employee, and the exchange rate charged by the bank to the cardholder is very unlikely to be the same as the current corporate exchange rate maintained in D365FO. Ergo, the AP transaction should be expressed in the accounting currency.

Take a look at the below example, the employee visited Thailand:
Credit card transaction

  • The Local currency code is not what you would expect but the currency the merchant charged the transaction in, here the Thai baht. Internally it is called EXCHCODE_LOCALCURRENCY.
  • Amount in local currency is the transaction amount in baht
  • The Currency code is the currency the credit card issued in (a.k.a. EXCHCODE_CREDITCARDCURRENCY), typically the currency of the state where the cardholder lives (here: the Swiss Franc)
  • Transaction amount is the amount the credit card issuer will settle against the bank account backing the credit card, i.e. an amount in CHF to be withheld from the cardholder at the end of the month. Internally it is called AMOUNT_CREDITCARDCURRENCY.

The exchange rate between the “Local currency” and the “Currency” must not follow the standard exchange rate setting in D365FO, but it should be what the credit card institute provides on the account statement. Take the next example (Expense management > Periodic tasks > Credit card transactions):
Credit card transactions
The exchange rate was developing over the same time span as shown below:
01.01.2018 2,995 CHF for 100 THB
01.02.2018 2,975 CHF for 100 THB
01.03.2018 3,001 CHF for 100 THB

The exchange rate applied by the bank in February was 15,11 CHF/ 500 THB = 0,03022 CHF/THB = 3,022 CHF for 100 THB. Clearly, it was higher than the average to the disadvantage of the employee, right as expected of a greedy bank.

What will you see in Dynamics 365 for Finance and Operations (version 8.x+, all bugs fixed) upon attaching the imported credit card transactions to an expense report and posting the same?
Credit card transaction detailed

  • Expense report line currency: THB
  • Expense report line Transaction amount and currency: 77,67 CHF (!)
  • Expense report line Local amount: 2550
  • Accounting distribution currency and amount: 2550 THB
  • Expense report line Exchange rate: 3,046 CHF/100 THB, not editable (*)
  • GL Voucher transactions: Debit expense THB – Credit liability THB (**)
  • AP Subledger transaction: Credit liability CHF (!!)

(*) This is the unique exchange rate as charged by the credit card provider, and not the default legal entity exchange rate on the transaction date.

(**) The GL transaction currency does not match the subledger currency, as you can see. In theory, it is possible to have voucher transactions with the debit in one currency (THB) and a credit on another currency (CHF), as long as the equivalent in the local currency (CHF) matches and the voucher is in balance. However, it was not feasible for Microsoft to implement it in the subledger / accounting distribution programming model.

To be continued: Part 2


Get a cost center in D365FO

Get a cost center in D365FO

It is shocking to see over and over again functional consultants failing to create the Cost center dimension backed by the Organization units table (Organisation administration > Organisations > Operating units), choosing a custom dimension type instead and loosing the ability to specify an address, make a hierarchy of cost centers, specify a cost center manager etc.

This has also given a rise to excruciatingly dumb custom code snippets predating the dimension name CostCenter as if there were no British English or other languages.

With the proper setup and the proper coding this reduces to 3 essential lines:

static void main(Args _args)
DefaultDimensionView defaultDimensionView;
RefRecId testDefaultDimensionRecId =
(select firstonly DefaultDimension from ProdTable where ProdTable.ProdId == "P000173").DefaultDimension;
// Copy of the private method OMOperatingUnit::getDimensionViewId()
RefTableId getDimensionViewId(OMOperatingUnitType _omOperatingUnitType)
Dictionary dict = new Dictionary();
DictEnum dictEnum = new DictEnum(enumNum(OMOperatingUnitType));
return dict.tableName2Id(strFmt('DimAttribute%1', dictEnum.index2Symbol(_omOperatingUnitType)));

// Filter by the virtual backing entity table Id for cost centers
select defaultDimensionView
where defaultDimensionView.BackingEntityType == getDimensionViewId(OMOperatingUnitType::OMCostCenter)
&& defaultDimensionView.DefaultDimension == testDefaultDimensionRecId;