ZuloOne
English
Sign in
Menu

💱 Exchange differences

Updated

How a sale under a contract in a foreign currency, or a purchase from a supplier who bills in one, is owed, paid and carried in the books. The debt is in the counterparty's currency. The general ledger, tax, revenue and stock value are in the legal entity's own currency. The gap between the two is the exchange difference: realised at payment, unrealised at period end.

← Business wiki

How the process works#

Sales realization "Released" ──► Receivable: Amount (contract currency) + AmountFunc (entity currency)
         rate on the invoice date           Dr receivables / Cr revenue, at that rate
            │
Customer payment "Paid" ──► settles Amount, takes AmountFunc off at its carrying value
         rate on the payment date           Dr cash at the payment rate, Cr receivables at carrying,
            │                               the gap → exchange gain or loss (realised)
Receivable revaluation "Posted" ──► moves AmountFunc to open amount × period-end rate
         rate on the last day               the gap → exchange gain or loss (unrealised)
  • The currency comes from the contract. The Currency field of the SalesContract dictionary record decides it. The invoice, its credit and debit notes, returns and payments all follow their contract. A contract in the legal entity's own currency works exactly as before: the rate is 1, and nothing below produces a difference.
  • Each document stamps its rate. The rate is the contract currency's rate to the entity currency on the document date, taken from Exchange rates. It is written on the document as Exchange rate, so the document remembers the rate it was posted at, not today's.
  • The debt has two sides. The Receivable register keeps Amount in the contract's currency (what the customer is asked to pay) and AmountFunc in the entity's currency (what the debt is carried at in the books).
  • A payment settles the average. The register has no open items: debt is one balance per customer and contract. A payment of part of it takes off the same share of AmountFunc, and that share is the line's Carrying amount. The part of a payment above the open debt is an advance and is carried at the payment's own rate.
  • A revaluation moves only the entity-currency side. It is a document of its own, ReceivableRevaluation. Fill revaluation lists every open foreign-currency slice of one legal entity at the rate on the document date. Post revaluation books the differences. Cancel revaluation takes them back. The revalued carrying amount stays: it is not reversed next period, and the next payment's difference is measured against it. Realised and unrealised therefore add up to the whole difference.

A credit note, debit note and return use the rate of the invoice they correct. Tax was recognised at that rate, so it is reversed at that rate.

Purchases#

The purchase side mirrors the sale, with three differences:

  • The currency comes from the supplier contract. A payable is kept in the Currency of the document's SupplierContract; a document without a contract, or a contract with no currency, takes the Currency of the Supplier card; empty means the buyer legal entity's own currency. One supplier may hold contracts in several currencies at once — a hryvnia and a dollar contract of the same vendor, as in 1C — and each is owed, paid and revalued in its own currency.
  • The stock is valued at the receipt's rate. A receipt in 100 EUR at 40 enters stock at 4000 in InventoryValue and the cost lots, so cost of sales later is in the entity's currency. A supplier invoice difference is booked at the rate on the supplier's invoice date.
  • The signs are mirrored. A payable is a liability: when the rate rises, the entity owes more, so a payment or a revaluation at a higher rate is an exchange loss. PayableRevaluation (Purchasing → Documents → Payable revaluations) works like the receivable one.

Settings#

Exchange rates#

Where: model Common → dictionary ExchangeRate. Ribbon → Common → Dictionaries → Exchange rates.

Each row is one currency's Rate to base in a date window (Effective from / Effective to). The base currency is the one whose rate is 1. A rate between two currencies is computed through the base, so you enter one number per currency, not one per pair.

Value What changes
A window covers the document date The document stamps the rate and posts
No window covers the date (foreign currency) The invoice is not released, and the payment is not posted. The refusal names the date the rate is missing for
The contract currency is the entity's own No rate is needed; the rate is 1

Default: no rows. A single-currency stand needs none.

Example. The entity's currency has rate 1. EUR has 40 from 1 to 15 June and 42 from 16 to 25 June. An invoice dated 10 June stamps 40; a payment dated 20 June stamps 42.

Reporting in another currency#

The books do not store a third currency. A document form, a print layout or a turnover that must show the same amounts in dollars (or any other currency you keep rates for) converts on the day of the report through ICurrencyRateService.ConvertMoneyAsync. The order card already prints the contract currency's Symbol next to the total; it does not convert.

Value What changes
A window covers the report date for both currencies The amount is converted, rounded to Amount scale, and shown with the target Symbol (or Code if Symbol is empty)
No window on that date Nothing is converted. The caller leaves the cell empty or refuses the report
The source is already the target The amount is unchanged; no rate row is required

Where: the same Exchange rates dictionary. There is no extra setting named "reporting currency".

Default: no conversion. Totals stay in the contract currency (the card) or in the legal entity's currency (AmountFunc on the register).

Example. Books are hryvnia. 100 EUR of June invoices sit in AmountFunc as 4000. On 30 June EUR is 42 and USD is 40 (both to the base). Convert 4000 UAH → USD on that day: 4000 / 40 = 100 USD. Convert the 100 EUR themselves on 30 June: 100 × 42 / 40 = 105 USD. Those are two different questions — "as in the books, in dollars" versus "what the euros are worth today". Pick one per report. Do not add a euro invoice to a dollar invoice and then convert the sum.

Supplier currency#

Where: model Purchasing → dictionary SupplierContract, field Currency; and extension Supplier.Purchasing on the Supplier dictionary, field Currency (on the supplier card). The contract's wins; the card's fills a contract saved without one and covers documents with no contract.

Value What changes
A currency other than the buyer entity's Receipts, supplier invoices, returns and payments under this contract stamp a rate and carry the payable in two currencies
(empty) or the entity's own currency Rate 1, everything posts as before

Default: empty.

Example. Supplier «Rexon» bills in USD (card). Its contract «Seal Odesa» is in UAH. A receipt of 3 × 10 under «Seal Odesa» owes 30 UAH at rate 1; a receipt of 2 × 50 under the USD contract owes 100 USD, carried at 4000 at rate 40. A revaluation on 30 June at 41 revalues only the USD contract: +100.

Amount in words#

Where: model Common → dictionary Currency → group Amount in words on the currency card. The order summary (the document-totals card) spells the total out with these words.

Field What it holds Example, Ukrainian
WordsUnitOne / WordsUnitFew / WordsUnitMany the unit after 1 (21, 31…), after 2–4 (22–24…), after 5+ and 11–14 гривня / гривні / гривень
WordsUnitGender Masculine, Feminine or Neuter: decides одна/один/одне and дві/два before the unit Feminine
WordsMinorOne / WordsMinorFew / WordsMinorMany the hundredth, same three forms копійка / копійки / копійок
WordsMinorGender gender of the hundredth Feminine

The six word fields are translatable: each language keeps its own words, and the card shows the words of the language you are working in. English and Arabic use only the «one» and «many» forms. A field left empty keeps the built-in word, which exists for UAH, RUB, USD, EUR, SAR and AED. A currency with neither prints the hundredths as a fraction: одна тисяча вісім 63/100.

Example. A total of 1,008.63 UAH reads одна тисяча вісім гривень 63 копійки in Ukrainian and одна тысяча восемь гривен 63 копейки in Russian. 1.00 EUR reads одне євро 00 центів: euro is neuter.

Which currency. The card takes the document's own Currency. A document without one — a sales order — takes its contract's currency, then its legal entity's, then CommonSettings.DefaultCurrency.

Exchange gain and loss accounts#

Where: model Accounting → dictionary AccountingSettings → group Exchange differences, fields Exchange gain account and Exchange loss account. Ribbon → Accounting → Settings → Accounting settings.

Value What changes
A postable account The difference is booked to it: a gain as Cr gain, a loss as Dr loss
(empty) The payment posts as before FX (Dr cash / Cr receivables at what came in), and the difference stays in the receivables account. A revaluation moves the register but books nothing

Default: empty. The same pair serves realised and unrealised differences.

Revalue on period close#

Where: the same group, Revalue on period close.

Value What changes
On Closing a fiscal period (its Status set to anything but Open) first posts a ReceivableRevaluation and a PayableRevaluation dated the period's last day for every legal entity with foreign-currency debt. If one cannot be posted — a rate is missing on that day — the period stays open and the refusal names the currency and the date. Closing again after reopening revalues nothing twice: the difference is already booked
Off Revaluation is a document you create and post yourself

Default: off.

Example. 100 EUR open at 4000; the rate on 30 June is 41. Closing June with the setting on posts a receivable revaluation of +100 dated 30 June before the period closes. Without a rate on 30 June, June stays open.

Example with numbers#

The entity keeps its books in its own currency (rate 1). The contract is in EUR. Rates: 40 until 15 June, 42 from 16 to 25 June, 41 from 26 to 30 June.

Step Document Amount (EUR) AmountFunc Ledger
10 June Invoice 100 EUR, rate 40 100 4000 Dr receivables 4000 / Cr revenue 4000
20 June Payment 60 EUR, rate 42 40 1600 Dr cash 2520 / Cr receivables 2400 / Cr exchange gain 120
30 June Revaluation, rate 41 40 1640 Dr receivables 40 / Cr exchange gain 40
30 June Payment 40 EUR, rate 41 0 0 Dr cash 1640 / Cr receivables 1640

The payment on 20 June settles 60 of 100 EUR, so it takes off 60% of 4000 = 2400, not 60 × 40 at today's guess. The last payment books no difference: the revaluation had already carried the debt at 41. The customer paid 4160 in total for a sale recognised at 4000, and the 160 of gain splits 120 realised and 40 unrealised.

What is posted#

Document Transition Register Ledger
SalesRealization → Released Receivable Amount +, AmountFunc + at the invoice rate; Revenue at the invoice rate Dr receivables / Cr revenue at the invoice rate; output tax on the converted base
SalesCreditNote, SalesDebitNote → Posted Receivable tax part, both sides, at the invoice's rate tax reversal or addition on the converted base
SalesReturn → Posted Receivable and Revenue minus, at the invoice's rate Dr revenue / Cr receivables, converted
CustomerPayment → Paid Receivable Amount − line amount, AmountFunc − Carrying amount Dr cash (amount × payment rate) / Cr receivables (carrying) / the gap to gain or loss
ReceivableRevaluation → Posted Receivable AmountFunc ± difference gains: Dr receivables / Cr gain; losses: Dr loss / Cr receivables, as two sums
PurchaseOrder → Received Payable Amount +, AmountFunc + at the receipt rate; InventoryValue and cost lots at that rate Dr inventory / Cr payables, converted; input tax on the converted base
VendorPayment → Paid Payable Amount − line amount, AmountFunc − Carrying amount Dr payables (carrying) / Cr cash (amount × payment rate) / the gap: owed more than paid → Cr gain, paid more → Dr loss
PayableRevaluation → Posted Payable AmountFunc ± difference a rise: Dr loss / Cr payables; a fall: Dr payables / Cr gain

Boundaries and edge cases#

  • No rate, no posting. A foreign-currency invoice or payment without a rate window on its date is refused, and the message names the date.
  • A contract may use a currency other than the seller's. The invoice, notes, returns and payments follow the contract currency, not the legal entity's.
  • Revaluation reads the balance on its own date. The open amount and its carrying value are summed from the movements dated on or before the revaluation date. You can fill June's revaluation in July: July's invoices and payments do not enter it. If a July payment was posted before the June revaluation, it settled the debt at the unrevalued value; the July revaluation then removes what remains, and the total over the two months is still exact. A payment is likewise measured against the debt as it stood on the payment date.
  • The currency is fixed while debt is open. A contract's Currency or a supplier's Currency cannot change while the contract or supplier owes or is owed anything; the refusal names the open amount. Close the debt first (pay, or issue a credit note), then change the currency. This is also why there is no "debt from before FX": a currency can only be set on a clean slice.
  • Payables are kept per legal entity and contract. Payable carries the legal entity and the supplier contract of each document, so a supplier billed by two of your entities, or under contracts in two currencies, is revalued and paid per entity and contract, each in its own currency.
  • An advance carries at the payment rate. If an invoice is later set against that advance, a small entity-currency residual can remain on a slice whose Amount is zero. The next revaluation clears it.
  • Gains and losses are not netted in a revaluation: a loss on one customer does not hide behind a gain on another.

What's not there yet#

  • A payment settles the average carrying value of the contract slice, not a particular invoice. There is no open-item matching.
  • The register totals tab does not pick a reporting currency. A form, print layout or report script that needs one calls ConvertMoneyAsync on a slice that is already one currency (Amount of one contract, or AmountFunc).

Same topic for other readers: User · Developer

Where next#

Was this page helpful?