SQL Server:货币转换,执行计算和显示结果

时间:2013-09-25 15:39:40

标签: sql-server

SQL Server 2008

我的任务是设计对现有系统的修改。在用户界面上,我们需要允许从用户的货币类型输入货币值。将转换后的金额存储为美元。对存储的美元进行计算并将计算结果存储为美元。以配置的货币显示回当前用户。

主要问题摘要 如果用户输入EUR(例如)值,我们会将其转换为USD并将值存储在数据库(db)中,并将ID与用于计算的转换率相关联。当存储到数据库时,我们必须存储大约8个小数位,以便在从美元转换回来时准确地返回到欧元的原始输入金额,用于显示目的。 另一个用户可以登录配置为以美元显示金额,他们会看到什么?我们可能会将数据存储到数据库中的小数点后8位,但是我们是否可以将数据/地板/ ceil下降到分数? 如果我们只在UI和报告中显示低至货币分数的金额,那么我们将在某些时候平衡问题,特别是当显示为美元或转换为原始货币以外的货币时。

详细说明 我在设想保存价值的规模方面遇到了问题。目前我们只存储到两位小数,即使我们使用的是Money数据类型。如有必要,我们将从Money更改为Decimal(16,9)左右。 此外,我在构思如何向用户显示数据时遇到问题,因为我们现在只在UI中显示分数和报告。

我预见在将BACK从USD转换为用户的货币类型后显示预期值的问题。这一切都归结为我们在后端存储的内容,以及我们如何发布/ ceil / round。

我们会将所有值存储为基础货币,即美元。对输入的值执行计算,并从结果中创建和存储其他数据。

系统允许用户设置EUR等,并且金额将以该货币和格式显示在用户界面中。用户将无法输入小于该货币的最低面额的值。

回顾: 用户输入欧元金额。系统以美元存储。模块以美元价值运行,并以美元价值创建其他数据并存储结果。在稍后的时间/日期,用户可以返回系统,拉取记录,查看欧元的原始金额,并查看现在转换为欧元的其他计算金额。我们的报告和用户界面仅显示分数值。

将计算出的美元金额转换为其他货币,除了四舍五入到该货币的分数外,还可能导致显示的值出现平衡问题。

In the example below: 'a' is entered by user, 'b' is a look-up in the system, 'c' - 'd' - 'e' are all calculated and stored in database.

     a EUR * b conversion rate = c USD (value floored)
    c USD * <formula> = d result USD (value floored)
    USD - d result USD = e result USD

Balance formula:
USD = e result USD + d result USD

If a user enters 120.00 EUR, we get:
120.00 EUR * 1.330879 = 159.70548000 USD
159.70548000 USD * 0.89 =  142.1378772000 USD
159.70548000 USD - 142.1378772000 USD = 17.5676028000 USD
Balance:
159.70548000 USD  = 17.5676028000 USD + 142.1378772000 USD 

Showing back as EUR:
a: 159.70548000 USD * (1/1.330879 ) = 120 EUR
d: 142.1378772000 USD * (1/1.330879 ) = 106.8000000000000000 EUR
e: 17.5676028000 USD * (1/1.330879 ) = 13.2000000000000000 EUR
Balance:
120 EUR = 13.2000000000000000 EUR + 106.8000000000000000 EUR

If a user enters 120.00 EUR, and we floor our results, we get:
120.00 EUR * 1.330879 = 159.70 USD (value floored)
159.70 USD * 0.89 =  142.13 USD (value floored)
159.70 USD - 142.13 USD = 17.57 USD
Balance:
159.70 USD  = 17.57 USD + 142.13 USD 

Showing back as EUR:
a: 159.70 USD * (1/1.330879 ) = 119.99588242 EUR
d: 142.13 USD * (1/1.330879 ) = 106.79408120 EUR
e: 17.57 USD * (1/1.330879 ) = 13.20180122 EUR
Balance:
119.99588242 EUR = 13.20180122 EUR + 106.79408120 EUR
If we had floored the currency conversion: 119.99 EUR = 13.20 EUR + 106.79 EUR
Should be showing 120.00 EUR since that was what was originally entered by the user.

Showing back as EUR (and rounding):
a: 159.70 USD * (1/1.330879 ) = 120.00 EUR (Rounded)
d: 142.13 USD * (1/1.330879 ) = 106.79 EUR (Rounded)
e: 17.57 USD * (1/1.330879 ) = 13.20 EUR (Rounded)
Balance:
120.00 EUR <> 13.20 EUR + 106.79 EUR (actually equals 199.99)
Off by 1 cent.

1 个答案:

答案 0 :(得分:0)

我认为这会对我有用:

对于UI中用户可以输入值的每个位置,我需要以下内容: 1. ReportedValue存储在DB中,下降到货币类型的分数。 2. BaseValue,存储到基本货币类型的分数。 3. CurrencyConversionKey,具有原始货币类型,货币乘数,目标货币类型和转换生效日期的行的PK。

拥有这三个值后,我总能在UI中显示回原始输入金额的用户。或者,如果其他用户(具有不同的已配置货币类型)在UI中提取记录,则将原始输入金额转换为不同的货币类型。 我可以继续像我们目前那样进行所有内部计算(这将在BaseValue上),这将使所有计算保持在分数,并自动处理业务逻辑的任何舍入问题。