多种货币 - 存储什么以及何时转换?

Multi currency - what to store and when to convert?

我已经阅读了关于多货币的不同问答,但是 none 我很清楚,或者没有提供足够的关于我的用例的细节。

场景:

Raddo 公司有 3 个分支机构,英国、法国和美国。拉多的基础货币是美元。预算以美元创建。 Raddo 在数据库中存储支持的货币汇率。

英国的员工以英镑创建采购订单,法国的员工以欧元创建采购订单。

Q1:采购 Orders/Order 项目数据库中应存储什么 table - 分支机构所在地货币和当前汇率或以基础货币美元换算的金额?请记住,汇率必须是创建 PO 时的汇率。

问题 2:要转换什么以及何时能够以美国 dollars/base 货币生成报告?

Q3:如果有人说2年后将基础货币从美元改为AUS澳元,对现有数据有什么影响?

问题 4:处理多种货币以使应用程序处理最少转换量的最佳方式是什么?

通常您使用公司所在国家/地区的货币并纳税。因此,您应将其他货币以交易时的有效汇率兑换成美元。 一旦您获得所有数据,就会发生转换。 改变货币的影响是未知的,因为它不仅可以改变货币,还可以改变很多东西。 我不知道什么是最好的方法,但是在任何交易发生时跟踪所有汇率似乎是合乎逻辑的,因此您可以提供适当的数据。

请记住,您收到的答案是主观的。排除该免责声明后,这就是我将如何建立这样一个系统。

TL;DR:使用货币汇率 table 来存储适用的不同货币和日期的汇率。以当地货币和计算的美元价值存储金额。


A 货币汇率 Table

创建货币 table(外汇汇率)的形式:

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 
  • 前 4 列的组合将代表一条唯一记录。
  • 建议每当输入一对货币(美元 -> 英镑)的记录时,也插入等效的反向记录(英镑 -> 美元),或者使用真实汇率(单向转换)可能使用与其他方式不同的比率),或者与原始记录相反。
  • 对于一对货币,连续的行必须表现出日期的连续性(即对于一对货币,永远不应该有一个日期不恰好落在 VALID_FROM_DATEVALID_TO_DATE 之间一排)。
  • 为方便起见,还输入一行 ('USD', 'USD', 1, smallest_date, largest_date),其中包含数据库支持的最小和最大日期。这使得以基础货币本身进行输入的情况更容易处理。
  • 您将需要确定支持此 table 的货币汇率来源以及更新频率。例如,您的财务团队可能会发布每周 外汇汇率table(即使货币市场的价值每天都在变化)。

示例 table 如下所示。尽管一行的结束日期和下一行的开始日期之间似乎存在重叠,但查找操作仅检查一列是否相等(即 >= 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 

PO 中的列 Table

在采购订单 table 中,保留以下字段:

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 

填充 PO 列

已经有一个填充采购订单的流程 table,必须扩展该流程以填充以下字段:

  • PO_TXN_DATE 是采购订单上的财务交易日期。根据您的业务规则,这可能是采购订单 created/raised 的日期,也可能不是。
  • ORDER_VALUE_LOC 是以当地货币计算的交易价值。
  • ORDER_CURRENCY_LOC 是当地货币的货币代码。
  • 这三个字段将用于查找外汇汇率table。
  • ORDER_VALUE_USD 通过在 FX_RATES table 中查找汇率来填充:

填充 ORDER_VALUE_USD 由以下伪代码

演示
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 

OP 问题的答案

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.

如前所述,在采购订单中table存储本地货币值、交易日期、本地货币名称;还以基础货币 (USD) 计算和存储价值。汇率可以根据需要再次查询,这里不用多存。

此处存储美元价值,以便更轻松地以单一货币汇总(例如,生成显示未结采购订单总价值的报告以发送至总部)。如果对这种用例的需求很低,则无需存储美元价值,可以根据需要的时间从外汇汇率 table 计算出来。但是,以下问题暗示有合理的需要以基础货币 (USD) 获取价值。

Q2: What to convert and when, to be able to generate reports in US dollars/base currency?

通过以基础货币和美元存储值,此类报告将大大简化。这就是为什么我们将计算和存储美元价值的一次性成本,所以它可以多次读取。

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?

从技术上讲,如果预期会发生这样的更改,则不要使用 USD 命名任何数据库结构,而是使用类似 BASE 的通用名称。 :-)

如果进行了此类更改,公司的财务部门将指导您如何重述财务数据 - 例如您应该根据交易时的现行外汇汇率重新计算基准值,还是只使用统一的换算系数?在任何情况下,一旦给你这个决定,你只需要在 FX_RATES table 中输入适当的转换因子,并且 运行 一个一次性的过程来重新填充 PURCHASE_ORDERS.ORDER_VALUE_BASE 列。除了 FX 汇率之外,此查找的所有其他信息都已存在且未更改 PURCHASE_ORDERS table。

Q4: What is the best way to deal with multiple currencies so application handles minimum amount of conversions?

这将再次由您的业务需求驱动,而不是技术决定。如果需要经常报告本地货币和基础 (USD) 货币,则有助于以两种货币存储相关交易价值。通过计算一次并存储它,您可以从之后访问存储的数据中受益。

此外,由于您没有丢弃任何数据,因此您可以随时根据需要重新计算财务数据。可能需要这样做的一些场景是:

  • 公司决定使用发出 PO 时的现行汇率计算基础货币,但在关闭 PO 或开具发票时将重新计算基础 (USD) 货币。在这种情况下,您将在关闭 PO 时使用不同的日期来查找 FX_RATES table。
  • 如果英镑突然下跌,从 1 英镑 = 1.25 美元变为 1.5 英镑 = 1 美元,您可能需要计算这种变化对美元的影响。然后,您可以从 FX_RATES table 中获取存储值 ORDER_VALUE_USD 和使用今天的汇率重新计算的值之间的差异,以确定这种转变对美元的影响。

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)

汇率绝对可以存储在PO table中,而不是美元金额。在 PO table 中存储汇率本质上 "wrong" 没有任何意义,也没有任何关于存储美元金额的 "right" 。

当然,这将导致一个问题 - 如果您不将其存储在某些查找中,您从哪里获得汇率以便将其填充到 PO table table 第一名。请记住,在 large/global 公司中,外汇汇率很可能不会通过 LOB 应用程序本身填充,它将是一些外部来源,例如确定整个公司使用的外汇汇率的外汇汇率团队.在这种情况下,将外汇汇率存储在单独的 table 中会更方便。

我在下面列出了不同方法的一些好处。您需要根据需要选择您使用的那个。

  • 在 PO 中存储美元的好处 Table:无需任何进一步计算即可直接获得美元金额(即无需计算 ORDER_VALUE_LOC x EXCHANGE_RATE当 运行 报告时)。
  • 单独外汇汇率的好处table:外汇汇率集中存储在一个 table 中,使其更易于更新和查看(请记住,大公司可能有一个单独的团队来确定公司范围内使用的外汇汇率),以及验证(例如检查外汇汇率的连续性 - 在上面例如,通过将连续行中的有效 from/to 日期串在一起 来检查外汇汇率是否存在差距非常简单)。外汇汇率并没有分散在多个 table 周围。
  • 在 PO 中存储外汇汇率的好处 Table:不需要单独的 FX_RATES table。

当然,您可以冗余存储额外信息(权衡存储)以获得收益(例如,在 PO table 中您存储本地货币金额、外汇汇率和美元金额,以及保持单独的外汇汇率 table。这使您可以轻松打印出显示当地货币金额的 PO 文档,以及用于将其转换为美元金额的外汇汇率。同时,外汇汇率 table 仍然是汇率的权威来源)。

请记住,问题及其答案是主观的,因此没有对错之分。根据您的要求和您公司的标准定制所有这些建议。