SQL Server 2008
私は、既存のシステムの変更を設計する任務を負っています。ユーザー インターフェイスでは、ユーザーの通貨タイプから通貨値を入力できるようにする必要があります。変換された金額を USD で保存します。保存された USD で計算を行い、計算結果を USD で保存します。設定された通貨で現在のユーザーに表示します。
主な問題のまとめ ユーザーが値を EUR で入力した場合 (たとえば)、それを USD に変換し、その値をデータベース (db) に、計算に使用された換算レートにリンクされた ID と共に保存します。データベースに保存するときは、表示目的で USD から元に戻すときに EUR で入力された元の金額に正確に戻すために、小数点以下約 8 桁を保存する必要があります。米ドルで金額を表示するように構成されている別のユーザーがログインすると、何が表示されますか? DB にデータを小数点以下 8 桁まで格納している可能性がありますが、丸め/床/天井でセントに切り下げますか? UI とレポートの両方で通貨のセントまでの金額のみを表示すると、特に表示が米ドルである場合や、元の通貨以外の通貨に変換する場合に、ある時点でバランスの問題が発生します。
詳細な説明 値を保存するスケールを考えるのに問題があります。Money データ型を使用しているにもかかわらず、現在は小数点以下 2 桁までしか保存されません。必要に応じて、Money から Decimal(16,9) などに変更します。さらに、現在は UI とレポートでセントまでしか表示されないため、データをユーザーに表示する方法を考えるのに問題があります。
USD からユーザーの通貨タイプに BACK を変換した後、期待値を表示する際に問題が発生することが予想されます。すべては、バックエンドに何を保存するか、どのようにフロア/天井/ラウンドするかにかかっています。
すべての値を基本通貨である USD で保存します。入力された値に対して計算が実行され、その結果から他のデータが作成および保存されます。
このシステムでは、ユーザーが EUR などを設定できるようになり、金額はその通貨と形式でユーザー インターフェイスに表示されます。ユーザーは、その通貨の最低額面よりも小さい値を入力できません。
要約: ユーザーはユーロで金額を入力します。米ドルでのシステム ストア。モジュールは USD 値で実行され、USD 値で他のデータを作成し、結果を保存します。後日、ユーザーはシステムに戻ってレコードを取得し、元の金額を EUR で表示し、その他の計算された金額が EUR に換算されたことを確認できます。当社のレポートとユーザー インターフェースには、セントまでの値しか表示されません。
計算された USD の金額を別の通貨に換算すると、その通貨のセントに四捨五入するだけでなく、表示される値全体でバランスの問題が発生する可能性があります。
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.