Multi currency - what to store and when to convert? - database

I have read different Q&A on SO regarding multi currency but none of them are clear to me or do not provide enough details with regards to my use case.
Scenario:
Company Raddo has 3 branch locations, UK, France and USA. Raddo has base currency US dollars. Budgets are created in US dollars. Raddo stores supported curencies exchange rates in the database.
Employees in UK create purchase orders in GBP and in France create purchase orders in Euros.
Q1: What should be stored in Purchase Orders/Order items database table - Branch location currency and current exchange rate or converted amounts in base currency US dollars? Please keep in mind that exchange rate must be the one at the time of PO created.
Q2: What to convert and when, to be able to generate reports in US dollars/base currency?
Q3: what is the impact on the exising data if someone say after 2 years change the base currency from US dollars to AUS Australian dollar?
Q4: What is the best way to deal with multi currencies so application handles minimum amount of conversions?

Bear in mind that the answers you receive will be subjective. With that disclaimer out of the way, this is how I would go about setting up such a system.
TL;DR: Use a currency rates table to store currency rates for different currencies and dates when they are applicable. Store amounts in both the local currency and a calculated USD value.
A Currency Rates Table
Create a currency table (FX rates) of the form:
FX_RATES
--------
SOURCE_CURRENCY -- e.g. USD, GBP, EUR
TARGET_CURRENCY -- as above
EXCHANGE_RATE -- a suitable decimal field representing the conversion
VALID_FROM_DATE -- date range when the above exchange rate is valid
VALID_TO_DATE -- as above
The combination of the first 4 columns will represent a unique record.
It is recommended that whenever a record for a pair of currencies (USD -> GBP) is entered, the equivalent reverse record is also inserted (GBP -> USD), either with the true exchange rate (conversions one way might use a different rate than the other way), or with the inverse of the original record.
For a pair of currencies, successive rows must exhibit continuity of dates (i.e. for a pair of currencies, there should never be a date that does not fall between VALID_FROM_DATE and VALID_TO_DATE in exactly one row).
For convenience, also enter a single row ('USD', 'USD', 1, smallest_date, largest_date) with the smallest and largest dates supported by the databases. This makes it easier to handle cases when entries are made in the base currency itself.
You will need to determine a source of currency FX rates that feeds this table, as well as a frequency of updation. For example, your financial team might issue a weekly FX rates table (even if the values in the currency market changes daily).
A sample table would look like the following. Although it appears there are overlaps between the end date of one row and the start date of the next, the lookup operation checks for equality only on one column (i.e. >= VALID_FROM_DATE AND < VALID_TO_DATE)
SOURCE_CURRENCY TARGET_CURRENCY EXCHANGE_RATE VALID_FROM_DATE VALID_TO_DATE
--------------- --------------- ---------------------- --------------- --------------
GBP USD 1.250000 06-Mar-2017 13-Mar-2017
GBP USD 1.260000 13-Mar-2017 20-Mar-2017
GBP USD 1.240000 20-Mar-2017 27-Mar-2017
GBP USD 1.250000 27-Mar-2017 03-Apr-2017
USD GBP 0.800000 06-Mar-2017 13-Mar-2017
USD GBP 0.793651 13-Mar-2017 20-Mar-2017
USD GBP 0.806452 20-Mar-2017 27-Mar-2017
USD GBP 0.800000 27-Mar-2017 03-Apr-2017
USD USD 1.000000 01-Jan-1900 31-Dec-9999
Columns in PO Table
In the purchase orders table, keep the following fields:
PURCHASE_ORDERS
---------------
... other fields
PO_TXN_DATE -- Date for the PO that represents the financial transaction
ORDER_VALUE_LOC -- Decimal field with the order value in local currency
ORDER_CURRENCY_LOC -- The currency used for ORDER_VALUE_LOC (e.g. GBP/EUR)
ORDER_VALUE_USD -- The order value in USD (as this is the company's base currency)
... other fields
Populating the PO Columns
There will already be a process that populates the PO table, which will have to be extended to populate the following fields:
PO_TXN_DATE is the date of the financial transaction on the PO. Based on your business rules, this may or may not be the date the PO is created/raised.
ORDER_VALUE_LOC is the value of the transaction in the local currency.
ORDER_CURRENCY_LOC is the currency code for the local currency.
These three fields will be used to look up the FX rates table.
ORDER_VALUE_USD is populated by looking up the exchange rate in the FX_RATES table:
Populating ORDER_VALUE_USD is demonstrated by the following pseudo-code
ORDER_VALUE_USD = PURCHASE_ORDERS.ORDER_VALUE_LOC * FX_RATES.EXCHANGE_RATE
WHERE
FX_RATES.SOURCE_CURRENCY = PURCHASE_ORDERS.ORDER_CURRENCY_LOC
AND FX_RATES.TARGET_CURRENCY = 'USD'
AND PURCHASE_ORDERS.PO_TXN_DATE >= FX_RATES.VALID_FROM_DATE
AND PURCHASE_ORDERS.PO_TXN_DATE < FX_RATES.VALID_TO_DATE
Answers to OP's Questions
Q1: What should be stored in Purchase Orders/Order items database
table - Branch location currency and current exchange rate or
converted amounts in base currency US dollars? Please keep in mind
that exchange rate must be the one at the time of PO created.
As mentioned, within the purchase orders table store the local currency value, transaction date, local currency name; also calculate and store the value in the base currency (USD). The exchange rate can be looked up again if required, there's no need to redundantly store it here.
The USD value is stored here to allow easier aggregation in a single currency (e.g. to generate a report that shows total value of outstanding POs to send to the head office). If the need for such a use case is low, then there's no need to store the USD value, it can be calculated from the FX rates table for the times it is required. However, the following question implies that there will be a reasonable need for getting the value in the base currency (USD).
Q2: What to convert and when, to be able to generate reports in US
dollars/base currency?
By storing the values in both the base currency and USD, such reporting will be greatly simplified. This is the reason we take the one-time cost of calculating and storing the USD value, so it can be read many times.
Q3: What is the impact on the existing data if someone - say after 2
years - changes the base currency from US dollars to AUD Australian
dollar?
Technically, if such a change is expected, then don't name any database structures with USD, instead use something generic like BASE. :-)
If such a change is done, the finance division of the company will instruct you how to restate the financial data - e.g. should you recalculate the base values based on the prevailing FX rate at the time of the transaction, or just use a flat conversion factor? In any case, once this decision is given to you, you just need to enter the appropriate conversion factors into the FX_RATES table, and run a one-off process to repopulate the PURCHASE_ORDERS.ORDER_VALUE_BASE column. Apart from the FX rate, all the other information for this lookup is already present and unchanged in the PURCHASE_ORDERS table.
Q4: What is the best way to deal with multiple currencies so application
handles minimum amount of conversions?
This will again be driven by your business needs, it will not be a technical decision. If there is a need to frequently report on both the local currency as well as the base (USD) currency, it helps to store the relevant transaction values in both currencies. By calculating it once and storing it, you can benefit from accessing stored data thereafter.
Also, since you're not discarding any data, you can always recalculate the financials if required. Some scenarios where this might be required are:
A corporate decision is made that the base currency is calculated using the prevailing exchange rate at the time of the PO being raised, but the base (USD) currency is to be recalculated when the PO is closed or invoiced. In such a case, you'd use a different date to look up the FX_RATES table at the time of closing the PO.
If the pound suddenly tanks, and changes from 1 GBP = 1.25 USD to 1.5 GBP = 1 USD, you might be required to calculate the dollar impact of such a change. Then, you can get the difference between the stored value ORDER_VALUE_USD and a re-calculated value using today's exchange rate from the FX_RATES table, to determine the dollar impact of such a shift.
Q5: Can't the exchange rate at the time of transaction be stored in the
purchase orders table? This way, system wont need to look up the
exchange rate in FX rates table. (Asked via a follow-up comment)
The exchange rate can definitely be stored in the PO table, instead of the USD amount. There is nothing intrinsically "wrong" about storing exchange rates in the PO table, nor is there anything "right" about storing the USD amount instead.
Of course, that then will lead on to a question of - where do you get the exchange rate from in order to populate it into the PO table, if you don't store it in some lookup table in the first place. Bear in mind that in large/global corporations, FX rates will in all likelihood not be populated via the LOB application itself, it will be some external source, such as a FX rates team that determines FX rates to be used across the company. In such a case, storing the FX rates in a separate table is more convenient.
I've listed some of the benefits of different approaches below. You'd need to pick the one(s) you use based on your needs.
Benefit of Storing USD in the PO Table: Amounts in USD are directly available without needing any further calculation (i.e. no need to calculate ORDER_VALUE_LOC x EXCHANGE_RATE when running a report).
Benefit of a separate FX Rates table: FX rates are centrally stored in a single table, making it easier to update & review (remember large corporations might have a separate team fixing the FX rates for company-wide use), as well as validate (e.g. to check for continuity of FX rates - in the above example, it is trivially simple to check that there no gaps for FX rates by stringing together the valid from/to dates on successive rows). FX rates are not scattered around multiple tables.
Benefit of Storing FX Rate in the PO Table: No need for a separate FX_RATES table.
Of course, you could redundantly store additional information (trading off storage) to gain a benefit (for example, in the PO table you store the local currency amount, FX rate and USD amount, as well as keep a separate FX rates table. This allows you to easily print out PO documents that displays the local currency amount, and the FX rate used to convert it to the USD amount. At the same time, the FX rates table remains as an authoritative source of exchange rates).
Remember, the question - and its answers - are subjective, so there's no right nor wrong. Tailor all these recommendations to your requirements, and your company's standards.

Usually you use the currency of the country where the company has its base and pay its taxes. So you should convert the other currencies to US$ with valid exchange rate at the time of transaction.
Conversions takes place as soon as you get all the data.
The impact of changing currency is unknown as it can change multitude of things not only the currency.
I dont know what is the best way, but it seems logical to keep track of all the exchange rates whenever any transaction happens, so you can give appropriate data.

Related

How to calculate the tax free amount of sales, based on date fields?

i need your help for a task that i have undertaken and i face difficulties.
So, i have to calculate the NET amount of sales for some products, which were sold in different cities on different years and for this reason different tax rate is applied.
Specifically, i have a dimension table (Dim_Cities) which consists of the cities that the products can be sold.
i.e
Dim_Cities:
CityID, CityName, Area, District.
Dim_Cities:
1, "Athens", "Attiki", "Central Greece".
Also, i have a file/table which consists of the following information :
i.e
[SalesArea]
,[EffectiveFrom_2019]
,[EffectiveTo_2019]
,[VAT_2019]
,[EffectiveFrom_2018]
,[EffectiveTo_2018]
,[VAT_2018]
,[EffectiveFrom_2017]
,[EffectiveTo_2017]
,[VAT_2017]
,[EffectiveFrom_2016_Semester1]
,[EffectiveTo_2016_Semester1]
,[VAT_2016_Semester1]
,[EffectiveFrom_2016_Semester2]
,[EffectiveTo_2016_Semester2]
,[VAT_2016_Semester2]
i.e
"Athens", "2019-01-01", "2019-12-31", 0.24,
"2018-01-01", "2018-12-31", 0.24,
"2017-01-01", "2017-12-31", 0.17,
"2016-01-01", "2016-05-31", 0.16,
"2016-01-06", "2016-12-31", 0.24
And of course there is a fact table that holds all the information,
i.e
FactSales_ID, CityID, SaleAmount (with VAT), SaleDate_ID.
The question is how to compute for every city the "TAX-Free SalesAmount", that corresponds to each particular saledate? In other words, i think that i have to create a function that computes every time the NET amount, substracting in each case the corresponding tax rate, based on the date and city that it finds. Can anyone help me or guide me to achieve this please?
I'm not sure if you are asking how to query your data to produce this result or how to design your data warehouse to make this data available - but I'm hoping you are asking about how to design your data warehouse as this information should definitely be pre-calculated and held in your DW rather than being calculated every time anyone wants to report on the data.
One of the key points of building a DW is that all the complex business logic should be handled in the ETL (as much as possible) so that the actually reporting is simple; the only calculations in a reporting process are those that can't be pre-calculated.
If your CITY Dim is SCD2 (or could be made to be SCD2) then I would add the VAT rate as an attribute to that Dim - otherwise you could hold VAT Rate in a "worker" table.
When your ETL loads your Fact table you would use the VAT rate on the CITY Dim (or in the worker table) to calculate the Net and Gross amounts and hold both as measures in your fact table

Which one is the best database design for supporting multi-currency money values?

I want to know the best database design for storing multi-currency money values in database.
For example I have one Entity that has two money fields. These fields may have different currency types for each record.
Example:
Table A:
-------------
Id
Name
Amount1
Amount2
Sample records:
Id Name Amount1 Amount2
1 aaa 12$ 15£
2 bbb 30€ 17$
I cannot store values in one currency. For example I want to lend somebody money. I store its data in a table. The type of money can be different. When I lend someone 10€ I should take back 10€ and I cannot store all values in one currency like dollar.
I want to know what the best and more efficient design for storing these values in database is.
Should I store amount and currency sign in one column with string data type or it is better to define Money and Currency tables as separate tables for storing money values?
Or any other design?
Without commenting too much on the actual structure of your table (2 or more monies in a single table is OK, as long as they have business meaning—like subtotal, shippingFee and total), I'll focus on how to store them:
Storing the monies
You should store the amount in one column, and the currency code in another.
Currency
You'll typically deal with ISO 4217, which comes with 2 codes for each currency:
a 3-letter alpha code, such as EUR or USD
a 3-digit numeric code, such as 978 or 840
Which one you use is up to you. You can save one byte per record by using numeric codes. On the other hand, alpha codes are easier to read and remember for humans, and could make it easier to use custom currencies (crypto), that may have a de-facto standard alpha code but no numeric code.
Amount
Because currencies may have different numbers of decimal places (2 for EUR, USD etc., but 0 for JPY, 3 for TND...), I always advise to store amounts in minor currency units (cents) as an integer.
Your table would therefore look like:
amount INT NOT NULL,
currencyCode CHAR(3) NOT NULL
If you want to store 12.34 USD, you'll actually store (1234, 'USD').
Multiple amounts, single currency
If your table holds several monies that will always be in a single currency (like the subtotal/shippingFee/total example above), all 3 amounts can share a single currency code:
subtotal INT NOT NULL,
shippingFee INT NOT NULL,
total INT NOT NULL,
currencyCode CHAR(3) NOT NULL
In this case, you probably don't need separate subtotalCurrencyCode, shippingFeeCurrencyCode and totalCurrencyCode, although there are other business cases where amounts will be in different currencies. The decision is yours.
Retrieving the monies
Of course dealing with integer amounts is not very easy, so you'll need to use a money library that supports converting from/to minor amounts.
For example in PHP, you can use brick/money (disclaimer: I'm the author):
$money = Money::ofMinor(1234, 'USD');
$money->getAmount(); // 12.34
$money->getMinorAmount(); // 1234
Never ever store multiple values in the same column!!
The currecny and the amount need to be separated. Also, if you have column names with numbers then you most probably do something wrong. This is one way to do it:
table products
--------------
id
name
table prices
------------
id
product_id
amount
currency_id
table currencies
----------------
id
name
abbreviation_sign
Then to get the Dollar price of a product you can do
select pri.amount
from prices pri
join products prod on prod.id = pri.product_id
join currencies c on c.id = pri.currency_id
where prod.id = 123
and c.name = 'Dollar'
With proper indexes this is really fast to query.

DB Schema: Versioned price model vs invoice-related data

I am creating some db model for rental invoice generation.
The invoice consists of N booking time ranges.
Each booking belongs to a price model. A price model is a set of rules which determine a final price (base price + season price + quantity discout + ...).
That means the final price for the N bookings within an invoice can be a complex calculation, and of course I want to keep track of every aspect of the final price calculation for later review of an invoice.
The problem is, that a price model can change in the future. So upon invoice generation, there are two possibilities:
(a) Never change a price model. Just make it immutable by versioning it and refer to a concrete version from an invoice.
(b) Put all the price information, discounts and extras into the invoice. That would mean alot of data, as an invoice contains N bookings which may be partly in the range of a season price.
Basically, I would break down each booking into its days and for each day I would have N rows calculating the base price, discounts and extra fees.
Possible table model:
Invoice
id: int
InvoiceBooking # Each booking. One invoice has N bookings
id: int
invoiceId: int
(other data, e.g. guest information)
InvoiceBookingDay # Days of a booking. Each booking has N days
id: int
invoiceBookingId: id
date: date
InvoiceBookingDayPriceItem # Concrete discounts, etc. One days has many items
id: int
invoiceBookingDayId: int
price: decimal
title: string
My question is, which way should I prefer and why.
My considerations:
With solution (a), the invoice would be re-calculated using the price model information each time the data is viewed. I don't like this, as algorithms can change. It does not feel natural for the "read-only" nature of an invoice.
Also the version handling of price models is not a trivial task and the user needs to know about the version concept, which adds application complexity.
With solution (b), I generate a bunch of nested data and it adds alot of complexity to the schema.
Which way would you prefer? Am I missing something?
Thank you
There is a third option which I recommend. I call it temporal (time) versioning and the layout of the table is really quite simple. You don't describe your pricing data so I'll just show a simple example.
Table: DailyPricing
ID EffDate Price ...
A 01/01/2015 17.50 ...
B 01/01/2015 20.00 ...
C 01/01/2015 22.50 ...
B 01/01/2016 19.50 ...
C 07/01/2016 24.00 ...
This shows that all three price schedules (A, B and C just represent whatever method you use to distinguish between price levels) were given a price on Jan 1, 2015. On Jan 1, 2016, the price of plan B was reduced. In July, the price of plan C was increased.
To get the current price of a plan, the query is this:
select dp.Price
from DailyPricing dp
where dp.ID = 'A'
and dp.Effdate =(
select Max( dp2.EffDate )
from DailyPricing dp2
where dp2.ID = dp.ID
and dp2.EffDate >= :DateOfInterest);
The DateOfInterest variable would be loaded with the current date/time. This query returns the one price that is currently in effect. In this case, the price set Jan 1, 2015 as that has never changed since taking effect. If the search had been for plan B, the price set on Jan 1, 2016 would have been returned and for plan C, the price set on July 1, 2016. These are the latest prices set for each plan; that is, the current prices.
Such a query would more likely be in a join with probably the invoice table so you could perform the price calculation.
select ...
from Invoices i
join DailyPricing dp
on dp.ID = i.ID
and dp.Effdate =(
select Max( dp2.EffDate )
from DailyPricing dp2
where dp2.ID = dp.ID
and dp2.EffDate >= i.InvoiceDate )
where i.ID = 1234;
This is a little more complex than a simple query but you are asking for more complex data (or, rather, a more complex view of the data). However, this calculation is probably only executed once and the final price stored back in to the invoice data or elsewhere.
It would be calculated again only if the customer made some changes or you were going through an audit, rechecking the calculation for accuracy.
Notice something, however, that is subtle but very important. If the query above were being executed for an invoice that had just been created, the InvoiceDate would be the current date and the price returned would be the current price. If, however, the query was being run as a verification on an invoice that was two years old, the InvoiceDate would be two years ago and the price returned would be the price that was in effect two years ago.
In other words, the query to return current data and the query to return past data is the same query.
That is because current data and past data remain in the same table, differentiated only by the date the data takes effect. This, I think, is about the simplest solution to what you want to do.
How about A and B?
It's not best practice to re-calculate any component of an invoice, especially if the component was printed. An invoice and invoice details should be immutable, and you should be able to reproduce it without re-calculating.
If you ever have a problem with figuring out how you got to a certain amount, or if there is a bug in your program, you'll be glad you have the details, especially if the calculations are complex.
Also, it's a good idea to keep a history of your pricing models so you can validate how you got to a certain price. You can make this simple to your users. They don't have to see the history -- but you should record their changes in the history log.

Is there any way to get settlement figures in the local currency from Amazon MWS?

We're using 3 marketplaces - our local is UK, so we've got GBP figures for the payment settlement reports, but the other 2 are in EUR. I could do with at least knowing how much Amazon have paid us in GBP for the 2 EUR reports, but I can't see any way of doing that?
I'm open to the idea of using some other API to get Amazon's payout exchange rates on the date of the report or other ideas.
I realise that I can use an external currency exchange data source, but I want to know what Amazon's exchange rate is for paying out since they almost certainly won't match.
I have tried all 3 settlement reports: -
_GET_FLAT_FILE_PAYMENT_SETTLEMENT_DATA_
_GET_PAYMENT_SETTLEMENT_DATA_
_GET_ALT_FLAT_FILE_PAYMENT_SETTLEMENT_DATA_
All settlement information uses the currency of the corresponding marketplace: your Amazon.co.uk settlement will be in GBP, while an Amazon.de settlement will be in EUR. The conversion to another currency is not part of the settlement.
IIRC, it is the bank that actually converts it to GBP, not Amazon. Therefore, you will not find an Amazon API to find its conversion rate (or conversion fees for that matter).

Implementing a sales tax strategy for Invoices

Here in South Africa we have Value Added Tax (VAT) which is pretty much identical to Sales Tax and is currently fixed at 14%, but could change at any time.
I need to include VAT on invoices (which are immutable) consisting of several Invoice Lines. Each line references a Product with a Boolean property, IsTaxable, and almost all products are taxable.
I don't want to store pre-tax prices in the database, because that just makes it hard to read the real price that the customer is going to pay and everywhere I display those prices, I then have to remember to add tax. And when the VAT rate does change, for this particular business, it is undesirable for all prices to change automagically.
So I reckon a reverse tax calculation is the way to go and probably not uncommon. The invoice total is the sum of all invoice line totals, which includes any line discounts and should be tax-inclusive. Therefore the invoice total itself is tax-inclusive:
TaxTotal = InvoiceTotal / (1 + TaxRate),
where InvoiceTotal is tax-inclusive and TaxRate == 0.14
Since invoices cannot be changed once issued (they are immutable), should I:
Store a single Tax amount in my Invoices table that does not change? Or...
Store a tax amount for each invoice line and calculate the invoice tax total every time I display the invoice?
Option 2 seems safer from a DBA point-of-view since if an invoice is ever manually changed, then Tax will be calculated correctly, but if the invoice has already been issued, this still presents a problem of inconsistency. If I stick with option 1, then I cannot display tax for a single line item, but it makes managing the tax total and doing aggregate calculations easier, though it also presents inconsistency if ever changed.
I can't do both since that would be duplicating data.
Which is the right way to go? Or is a reverse tax calculation a really bad idea?
Store the pre tax value in the data base, you can also store the with tax value and use that for most use cases.
Th big problem I forsee is the rounding rules for VAT on invoices.These (at least in the UK) are really strict and there is no way for your reverse calculation to get this right.
Also you need to store the tax item by item as the VAT dragons will expect you to refund exactly the tax paid if an item is returned. You really need to get hold of the local sales tax rules before you start.
My experience is that you can get dragged over the coals if your calculations are out by as little as a penny, and, if you are audited you need to be able to show how you arrived at the VAT figure so not storing anything used in your calculations will catch you out.
I totally agree with James Anderson! In Germany the rules according VAT calculations are as strict as in the UK.
We have to accumulate the net value by VAT percentage (we have three types: 0, 7 and 19 percent) rounded by two digits. On this rounded value we have to calculcate VAT.
VAT has to be rounded by two digits and has to be showed at the invoice.
But nonetheless you can store prices including tax. It depends whether the net prices or the end prices stay unchanged when tax rises. In Germany usually B2B net prices stay unchanged but B2C end prices stay unchanged - it depends.
You can calculate it this way:
with cPriceIncludingVAT as (
select InvoiceNo, VATPercentage,
PriceIncludingVAT = cast(sum(amount * price) as decimal(12,2))
from InvoiceLines inner join VAT on VAT.VATID=InvoiceLines.VATID
group by InvoiceNo, VATPercentage
),
cVATcalculated as (
select InvoiceNo, VATPercentage, PriceIncludingVAT,
VAT = cast(PriceIncludingVAT * VATPercentage /
(1+VATPercentage) as decimal(12,2))
from cVATcalculated
)
select InvoiceNo, VATPercentage, PriceIncludingVAT, VAT,
NetPrice = PriceIncludingVAT - VAT
from cVATcalculated;
If you save this as a view you should be able to reprint a dynamically calculated VAT value exactly. When there is an accounting system you can (and should) export exactly the same data you printed.
Usually you should save values like these as field values within the database - but I understand if you'd like to have a more dynamic approach ...
The other answers are good, but as idevlop mentions, it's almost a certainty that at some time in the future, you'll start having different rates for different categories of products. Adding that capability up front will save you a ton of heartache later on. Been there, done that.

Resources