GnuCash  5.6-150-g038405b370+
gnc-euro.cpp
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 <map>
24 #include <optional>
25 
26 #include "gnc-euro.h"
27 #include "gnc-session.h"
28 
29 /* The rates are per EURO and are converted to GncNumeric */
30 static const std::map<std::string,double> gnc_euro_rates =
31 {
32  { "ATS", 13.7603 }, /* austrian schilling */
33  { "BEF", 40.3399 }, /* belgian franc */
34  { "CYP", .585274 }, /* cyprus pound */
35  { "DEM", 1.95583 }, /* german mark */
36  { "EEK", 15.6466 }, /* Estonian Kroon */
37  { "ESP", 166.386 }, /* spanish peseta */
38  { "EUR", 1.00000 }, /* euro */
39  { "FIM", 5.94573 }, /* finnmark */
40  { "FRF", 6.55957 }, /* french franc */
41  { "GRD", 340.750 }, /* greek drachma */
42  { "HRK", 7.53450 }, /* Croatian kuna */
43  { "IEP", .787564 }, /* irish pound */
44  { "ITL", 1936.27 }, /* italian lira */
45  { "LUF", 40.3399 }, /* luxembourg franc */
46  { "LVL", .702804 }, /* latvian lats */
47  { "MTL", .429300 }, /* maltese lira */
48  { "NLG", 2.20371 }, /* netherland gulden */
49  { "PTE", 200.482 }, /* portuguese escudo */
50  { "SIT", 239.640 }, /* slovenian tolar */
51  { "SKK", 30.1260 } /* slovak koruna */
52 };
53 
54 static std::optional<double>
55 get_euro_rate (const gnc_commodity * currency)
56 {
57  if (!currency || !gnc_commodity_is_iso(currency))
58  return {};
59 
60  auto it = gnc_euro_rates.find (gnc_commodity_get_mnemonic(currency));
61  if (it == gnc_euro_rates.end())
62  return {};
63 
64  return it->second;
65 }
66 
67 /* ------------------------------------------------------ */
68 
69 gboolean
70 gnc_is_euro_currency(const gnc_commodity * currency)
71 {
72  return get_euro_rate (currency).has_value();
73 }
74 
75 /* ------------------------------------------------------ */
76 
77 gnc_numeric
78 gnc_convert_to_euro(const gnc_commodity * currency, gnc_numeric value)
79 {
80  auto euro_rate = get_euro_rate (currency);
81  if (!euro_rate)
82  return gnc_numeric_zero();
83 
84  auto rate = double_to_gnc_numeric (*euro_rate, 100000, GNC_HOW_RND_ROUND_HALF_UP);
85 
86  /* round to 2 decimal places */
87  /* EC Regulation 1103/97 states we should use "Round half away from zero"
88  * See https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX%3A31997R1103&qid=1662917247821
89  */
90  return gnc_numeric_div (value, rate, 100, GNC_HOW_RND_ROUND_HALF_UP);
91 }
92 
93 /* ------------------------------------------------------ */
94 
95 gnc_numeric
96 gnc_convert_from_euro(const gnc_commodity * currency, gnc_numeric value)
97 {
98  auto euro_rate = get_euro_rate (currency);
99  if (!euro_rate)
100  return gnc_numeric_zero();
101 
102  auto rate = double_to_gnc_numeric (*euro_rate, 100000, GNC_HOW_RND_ROUND_HALF_UP);
103 
104  /* EC Regulation 1103/97 states we should use "Round half away from zero"
105  * See http://europa.eu/legislation_summaries/economic_and_monetary_affairs/institutional_and_economic_framework/l25025_en.htm */
106  return gnc_numeric_mul (value, rate, gnc_commodity_get_fraction (currency),
108 }
109 
110 /* ------------------------------------------------------ */
111 
112 gnc_numeric
113 gnc_euro_currency_get_rate (const gnc_commodity *currency)
114 {
115  auto euro_rate = get_euro_rate (currency);
116  if (!euro_rate)
117  return gnc_numeric_zero();
118 
120 }
121 
122 /* ------------------------------------------------------ */
123 
124 gnc_commodity *
125 gnc_get_euro (void)
126 {
127  QofBook* book = qof_session_get_book (gnc_get_current_session ());
128  gnc_commodity_table *table = gnc_commodity_table_get_table (book);
129 
130  return gnc_commodity_table_lookup (table, GNC_COMMODITY_NS_CURRENCY, "EUR");
131 }
gnc_commodity_table * gnc_commodity_table_get_table(QofBook *book)
Returns the commodity table associated with a book.
int gnc_commodity_get_fraction(const gnc_commodity *cm)
Retrieve the fraction for the specified commodity.
const char * gnc_commodity_get_mnemonic(const gnc_commodity *cm)
Retrieve the mnemonic for the specified commodity.
gnc_numeric double_to_gnc_numeric(double n, gint64 denom, gint how)
Convert a floating-point number to a gnc_numeric.
QofBook * qof_session_get_book(const QofSession *session)
Returns the QofBook of this session.
Definition: qofsession.cpp:574
gnc_numeric gnc_numeric_mul(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
Multiply a times b, returning the product.
gnc_numeric gnc_numeric_div(gnc_numeric x, gnc_numeric y, gint64 denom, gint how)
Division.
Round to the nearest integer, rounding away from zero when there are two equidistant nearest integers...
Definition: gnc-numeric.h:165
#define GNC_DENOM_AUTO
Values that can be passed as the &#39;denom&#39; argument.
Definition: gnc-numeric.h:245
gboolean gnc_commodity_is_iso(const gnc_commodity *cm)
Checks to see if the specified commodity is an ISO 4217 recognized currency.