Line data Source code
1 : /********************************************************************\
2 : * gnc-euro.c -- utilities for EURO currency *
3 : * *
4 : * Copyright (C) 2000 Herbert Thoma *
5 : * *
6 : * This program is free software; you can redistribute it and/or *
7 : * modify it under the terms of the GNU General Public License as *
8 : * published by the Free Software Foundation; either version 2 of *
9 : * the License, or (at your option) any later version. *
10 : * *
11 : * This program is distributed in the hope that it will be useful, *
12 : * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 : * GNU General Public License for more details. *
15 : * *
16 : * You should have received a copy of the GNU General Public License*
17 : * along with this program; if not, write to the Free Software *
18 : * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
19 : * *
20 : \********************************************************************/
21 :
22 : #include <string>
23 : #include <boost/container/flat_map.hpp>
24 : #include <optional>
25 :
26 : #include "gnc-euro.h"
27 : #include "gnc-session.h"
28 : #include <gnc-numeric.hpp>
29 : #include <gnc-rational-rounding.hpp>
30 :
31 : /* The rates are per EURO and are denoted in GncNumeric */
32 : static const boost::container::flat_map <std::string, GncNumeric> gnc_euro_rates =
33 : {
34 : { "ATS", {137603, 10000} }, /* austrian schilling */
35 : { "BEF", {403399, 10000} }, /* belgian franc */
36 : { "BGN", {195583, 100000} }, /* Bulgarian lev */
37 : { "CYP", {585274, 1000000} }, /* cyprus pound */
38 : { "DEM", {195583, 100000} }, /* german mark */
39 : { "EEK", {156466, 10000} }, /* Estonian Kroon */
40 : { "ESP", {166386, 1000} }, /* spanish peseta */
41 : { "EUR", { 1, 1} }, /* euro */
42 : { "FIM", {594573, 100000} }, /* finnmark */
43 : { "FRF", {655957, 100000} }, /* french franc */
44 : { "GRD", {340750, 1000} }, /* greek drachma */
45 : { "HRK", {753450, 100000} }, /* Croatian kuna */
46 : { "IEP", {787564, 1000000} }, /* irish pound */
47 : { "ITL", {193627, 100} }, /* italian lira */
48 : { "LUF", {403399, 10000} }, /* luxembourg franc */
49 : { "LVL", {702804, 1000000} }, /* latvian lats */
50 : { "MTL", {429300, 1000000} }, /* maltese lira */
51 : { "NLG", {220371, 100000} }, /* netherland gulden */
52 : { "PTE", {200482, 1000} }, /* portuguese escudo */
53 : { "SIT", {239640, 1000} }, /* slovenian tolar */
54 : { "SKK", {301260, 10000} } /* slovak koruna */
55 : };
56 :
57 : static std::optional<GncNumeric>
58 7469 : get_euro_rate (const gnc_commodity * currency)
59 : {
60 7469 : if (!currency || !gnc_commodity_is_iso(currency))
61 0 : return {};
62 :
63 7469 : auto it = gnc_euro_rates.find (gnc_commodity_get_mnemonic(currency));
64 7469 : if (it == gnc_euro_rates.end())
65 7414 : return {};
66 :
67 55 : return it->second;
68 : }
69 :
70 : /* ------------------------------------------------------ */
71 :
72 : gboolean
73 7428 : gnc_is_euro_currency(const gnc_commodity * currency)
74 : {
75 7428 : return get_euro_rate (currency).has_value();
76 : }
77 :
78 : /* ------------------------------------------------------ */
79 :
80 : gnc_numeric
81 11 : gnc_convert_to_euro(const gnc_commodity * currency, gnc_numeric value)
82 : {
83 11 : auto euro_rate = get_euro_rate (currency);
84 11 : if (!euro_rate)
85 0 : return gnc_numeric_zero();
86 :
87 : /* round to 2 decimal places */
88 : /* EC Regulation 1103/97 states we should use "Round half away from zero"
89 : * See https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX%3A31997R1103&qid=1662917247821
90 : */
91 11 : return (value / *euro_rate).convert<RoundType::half_up>(100);
92 : }
93 :
94 : /* ------------------------------------------------------ */
95 :
96 : gnc_numeric
97 10 : gnc_convert_from_euro(const gnc_commodity * currency, gnc_numeric value)
98 : {
99 10 : auto euro_rate = get_euro_rate (currency);
100 10 : if (!euro_rate)
101 0 : return gnc_numeric_zero();
102 :
103 : /* EC Regulation 1103/97 states we should use "Round half away from zero"
104 : * See http://europa.eu/legislation_summaries/economic_and_monetary_affairs/institutional_and_economic_framework/l25025_en.htm */
105 10 : return (value * *euro_rate).convert<RoundType::half_up>(gnc_commodity_get_fraction (currency));
106 : }
107 :
108 : /* ------------------------------------------------------ */
109 :
110 : gnc_numeric
111 20 : gnc_euro_currency_get_rate (const gnc_commodity *currency)
112 : {
113 20 : auto euro_rate = get_euro_rate (currency);
114 20 : if (!euro_rate)
115 0 : return gnc_numeric_zero();
116 :
117 20 : return static_cast<gnc_numeric>(*euro_rate);
118 : }
119 :
120 : /* ------------------------------------------------------ */
121 :
122 : gnc_commodity *
123 0 : gnc_get_euro (void)
124 : {
125 0 : QofBook* book = qof_session_get_book (gnc_get_current_session ());
126 0 : gnc_commodity_table *table = gnc_commodity_table_get_table (book);
127 :
128 0 : return gnc_commodity_table_lookup (table, GNC_COMMODITY_NS_CURRENCY, "EUR");
129 : }
|