From 26e7eada37efa2a3b91509483e17e9c9ba544ec6 Mon Sep 17 00:00:00 2001 From: Christopher Lam Date: Mon, 19 Oct 2020 10:26:23 +0800 Subject: [PATCH 1/8] [gnc-pricedb.c] refactor amount converters, use common code --- libgnucash/engine/gnc-pricedb.c | 66 +++++++++++++++------------------ 1 file changed, 30 insertions(+), 36 deletions(-) diff --git a/libgnucash/engine/gnc-pricedb.c b/libgnucash/engine/gnc-pricedb.c index 94075ac03a..6887652d66 100644 --- a/libgnucash/engine/gnc-pricedb.c +++ b/libgnucash/engine/gnc-pricedb.c @@ -2581,34 +2581,44 @@ indirect_balance_conversion (GNCPriceDB *db, gnc_numeric bal, return zero; } - -/* - * Convert a balance from one currency to another. - */ -gnc_numeric -gnc_pricedb_convert_balance_latest_price(GNCPriceDB *pdb, - gnc_numeric balance, - const gnc_commodity *balance_currency, - const gnc_commodity *new_currency) +static gnc_numeric convert_amount_at_date (GNCPriceDB *pdb, + gnc_numeric amount, + const gnc_commodity *orig_currency, + const gnc_commodity *new_currency, + const time64 t) { gnc_numeric new_value; - if (gnc_numeric_zero_p (balance) || - gnc_commodity_equiv (balance_currency, new_currency)) - return balance; + if (gnc_numeric_zero_p (amount) || + gnc_commodity_equiv (orig_currency, new_currency)) + return amount; /* Look for a direct price. */ - new_value = direct_balance_conversion(pdb, balance, balance_currency, - new_currency, INT64_MAX); - if (!gnc_numeric_zero_p(new_value)) - return new_value; + new_value = direct_balance_conversion + (pdb, amount, orig_currency, new_currency, t); /* * no direct price found, try if we find a price in another currency * and convert in two stages */ - return indirect_balance_conversion(pdb, balance, balance_currency, - new_currency, INT64_MAX); + if (gnc_numeric_zero_p (new_value)) + new_value = indirect_balance_conversion + (pdb, amount, orig_currency, new_currency, t); + + return new_value; +} + +/* + * Convert a balance from one currency to another. + */ +gnc_numeric +gnc_pricedb_convert_balance_latest_price (GNCPriceDB *pdb, + gnc_numeric balance, + const gnc_commodity *balance_currency, + const gnc_commodity *new_currency) +{ + return convert_amount_at_date + (pdb, balance, balance_currency, new_currency, INT64_MAX); } gnc_numeric @@ -2618,24 +2628,8 @@ gnc_pricedb_convert_balance_nearest_price_t64(GNCPriceDB *pdb, const gnc_commodity *new_currency, time64 t) { - gnc_numeric new_value; - - if (gnc_numeric_zero_p (balance) || - gnc_commodity_equiv (balance_currency, new_currency)) - return balance; - - /* Look for a direct price. */ - new_value = direct_balance_conversion(pdb, balance, balance_currency, - new_currency, t); - if (!gnc_numeric_zero_p(new_value)) - return new_value; - - /* - * no direct price found, try if we find a price in another currency - * and convert in two stages - */ - return indirect_balance_conversion(pdb, balance, balance_currency, - new_currency, t); + return convert_amount_at_date + (pdb, balance, balance_currency, new_currency, t); } From 4d63eb922f4ae3794315dad36c9dafc0e9f752e3 Mon Sep 17 00:00:00 2001 From: Christopher Lam Date: Mon, 19 Oct 2020 10:47:50 +0800 Subject: [PATCH 2/8] [gnc-pricedb.c] copy convert_amount to convert_price --- libgnucash/engine/gnc-pricedb.c | 88 +++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/libgnucash/engine/gnc-pricedb.c b/libgnucash/engine/gnc-pricedb.c index 6887652d66..3b39788c17 100644 --- a/libgnucash/engine/gnc-pricedb.c +++ b/libgnucash/engine/gnc-pricedb.c @@ -2513,6 +2513,94 @@ extract_common_prices (PriceList *from_prices, PriceList *to_prices, return retval; } + +static gnc_numeric +convert_price (const gnc_commodity *from, const gnc_commodity *to, PriceTuple tuple) +{ + gnc_commodity *from_com = gnc_price_get_commodity (tuple.from); + gnc_commodity *from_cur = gnc_price_get_currency (tuple.from); + gnc_commodity *to_com = gnc_price_get_commodity (tuple.to); + gnc_commodity *to_cur = gnc_price_get_currency (tuple.to); + gnc_numeric from_val = gnc_price_get_value (tuple.from); + gnc_numeric to_val = gnc_price_get_value (tuple.to); + gnc_numeric price; + int no_round = GNC_HOW_DENOM_EXACT | GNC_HOW_RND_NEVER; + + price = gnc_numeric_div (to_val, from_val, GNC_DENOM_AUTO, no_round); + + if (from_cur == from && to_cur == to) + return price; + + if (from_com == from && to_com == to) + return gnc_numeric_invert (price); + + price = gnc_numeric_mul (from_val, to_val, GNC_DENOM_AUTO, no_round); + + if (from_cur == from) + return gnc_numeric_invert (price); + + return price; +} + +static gnc_numeric +indirect_price_conversion (GNCPriceDB *db, const gnc_commodity *from, + const gnc_commodity *to, time64 t) +{ + GList *from_prices = NULL, *to_prices = NULL; + PriceTuple tuple; + gnc_numeric zero = gnc_numeric_zero(); + if (!from || !to) + return zero; + if (t == INT64_MAX) + { + from_prices = gnc_pricedb_lookup_latest_any_currency(db, from); + /* "to" is often the book currency which may have lots of prices, + so avoid getting them if they aren't needed. */ + if (from_prices) + to_prices = gnc_pricedb_lookup_latest_any_currency(db, to); + } + else + { + from_prices = gnc_pricedb_lookup_nearest_in_time_any_currency_t64 (db, from, t); + if (from_prices) + to_prices = gnc_pricedb_lookup_nearest_in_time_any_currency_t64 (db, to, t); + } + if (!from_prices || !to_prices) + return zero; + tuple = extract_common_prices (from_prices, to_prices, from, to); + gnc_price_list_destroy (from_prices); + gnc_price_list_destroy (to_prices); + if (tuple.from) + return convert_price (from, to, tuple); + return zero; +} + + +static gnc_numeric +direct_price_conversion (GNCPriceDB *db, const gnc_commodity *from, + const gnc_commodity *to, time64 t) +{ + GNCPrice *price; + gnc_numeric retval = gnc_numeric_zero(); + + if (!from || !to) return retval; + + if (t == INT64_MAX) + price = gnc_pricedb_lookup_latest(db, from, to); + else + price = gnc_pricedb_lookup_nearest_in_time64(db, from, to, t); + + if (!price) return retval; + + retval = gnc_price_get_value (price); + + if (gnc_price_get_commodity (price) != from) + retval = gnc_numeric_invert (retval); + + gnc_price_unref (price); + return retval; +} + static gnc_numeric convert_balance(gnc_numeric bal, const gnc_commodity *from, const gnc_commodity *to, PriceTuple tuple) From 2ecdd70e2412dac95d6b65eece136e718797252f Mon Sep 17 00:00:00 2001 From: Christopher Lam Date: Mon, 19 Oct 2020 20:08:44 +0800 Subject: [PATCH 3/8] [gnc-pricedb.c][api] pull out composite pricedb price retriever * tries direct price retrieval from pricedb. * if fails, tries intermediate currency. --- libgnucash/engine/gnc-pricedb.c | 135 +++++++------------------------- libgnucash/engine/gnc-pricedb.h | 18 +++++ 2 files changed, 48 insertions(+), 105 deletions(-) diff --git a/libgnucash/engine/gnc-pricedb.c b/libgnucash/engine/gnc-pricedb.c index 3b39788c17..481df22adc 100644 --- a/libgnucash/engine/gnc-pricedb.c +++ b/libgnucash/engine/gnc-pricedb.c @@ -2435,35 +2435,6 @@ gnc_pricedb_lookup_latest_before_t64 (GNCPriceDB *db, return current_price; } -static gnc_numeric -direct_balance_conversion (GNCPriceDB *db, gnc_numeric bal, - const gnc_commodity *from, const gnc_commodity *to, - time64 t) -{ - GNCPrice *price; - gnc_numeric retval = gnc_numeric_zero(); - if (from == NULL || to == NULL) - return retval; - if (gnc_numeric_zero_p(bal)) - return retval; - if (t != INT64_MAX) - price = gnc_pricedb_lookup_nearest_in_time64(db, from, to, t); - else - price = gnc_pricedb_lookup_latest(db, from, to); - if (price == NULL) - return retval; - if (gnc_price_get_commodity(price) == from) - retval = gnc_numeric_mul (bal, gnc_price_get_value (price), - gnc_commodity_get_fraction (to), - GNC_HOW_RND_ROUND); - else - retval = gnc_numeric_div (bal, gnc_price_get_value (price), - gnc_commodity_get_fraction (to), - GNC_HOW_RND_ROUND); - gnc_price_unref (price); - return retval; - -} typedef struct { @@ -2601,72 +2572,35 @@ direct_price_conversion (GNCPriceDB *db, const gnc_commodity *from, return retval; } -static gnc_numeric -convert_balance(gnc_numeric bal, const gnc_commodity *from, - const gnc_commodity *to, PriceTuple tuple) +gnc_numeric +gnc_pricedb_get_nearest_price (GNCPriceDB *pdb, + const gnc_commodity *orig_currency, + const gnc_commodity *new_currency, + const time64 t) { - gnc_commodity *from_com = gnc_price_get_commodity(tuple.from); - gnc_commodity *from_cur = gnc_price_get_currency(tuple.from); - gnc_commodity *to_com = gnc_price_get_commodity(tuple.to); - gnc_commodity *to_cur = gnc_price_get_currency(tuple.to); - gnc_numeric from_val = gnc_price_get_value(tuple.from); - gnc_numeric to_val = gnc_price_get_value(tuple.to); - int fraction = gnc_commodity_get_fraction(to); + gnc_numeric price; - int no_round = GNC_HOW_DENOM_EXACT | GNC_HOW_RND_NEVER; - if (from_cur == from && to_cur == to) - return gnc_numeric_div(gnc_numeric_mul(bal, to_val, GNC_DENOM_AUTO, - no_round), - from_val, fraction, GNC_HOW_RND_ROUND); - if (from_com == from && to_com == to) - return gnc_numeric_div(gnc_numeric_mul(bal, from_val, GNC_DENOM_AUTO, - no_round), - to_val, fraction, GNC_HOW_RND_ROUND); - if (from_cur == from) - return gnc_numeric_div(bal, gnc_numeric_mul(from_val, to_val, - GNC_DENOM_AUTO, no_round), - fraction, GNC_HOW_RND_ROUND); - return gnc_numeric_mul(bal, gnc_numeric_mul(from_val, to_val, - GNC_DENOM_AUTO, no_round), - fraction, GNC_HOW_RND_ROUND); + if (gnc_commodity_equiv (orig_currency, new_currency)) + return gnc_numeric_create (1, 1); + /* Look for a direct price. */ + price = direct_price_conversion (pdb, orig_currency, new_currency, t); + + /* + * no direct price found, try find a price in another currency + */ + if (gnc_numeric_zero_p (price)) + price = indirect_price_conversion (pdb, orig_currency, new_currency, t); + + return gnc_numeric_reduce (price); } -static gnc_numeric -indirect_balance_conversion (GNCPriceDB *db, gnc_numeric bal, - const gnc_commodity *from, const gnc_commodity *to, - time64 t ) + +gnc_numeric +gnc_pricedb_get_latest_price (GNCPriceDB *pdb, + const gnc_commodity *orig_currency, + const gnc_commodity *new_currency) { - GList *from_prices = NULL, *to_prices = NULL; - PriceTuple tuple; - gnc_numeric zero = gnc_numeric_zero(); - if (from == NULL || to == NULL) - return zero; - if (gnc_numeric_zero_p(bal)) - return zero; - if (t == INT64_MAX) - { - from_prices = gnc_pricedb_lookup_latest_any_currency(db, from); - /* "to" is often the book currency which may have lots of prices, - so avoid getting them if they aren't needed. */ - if (from_prices) - to_prices = gnc_pricedb_lookup_latest_any_currency(db, to); - } - else - { - from_prices = gnc_pricedb_lookup_nearest_in_time_any_currency_t64(db, - from, t); - if (from_prices) - to_prices = gnc_pricedb_lookup_nearest_in_time_any_currency_t64(db, - to, t); - } - if (from_prices == NULL || to_prices == NULL) - return zero; - tuple = extract_common_prices(from_prices, to_prices, from, to); - gnc_price_list_destroy(from_prices); - gnc_price_list_destroy(to_prices); - if (tuple.from) - return convert_balance(bal, from, to, tuple); - return zero; + return gnc_pricedb_get_nearest_price (pdb, orig_currency, new_currency, INT64_MAX); } static gnc_numeric convert_amount_at_date (GNCPriceDB *pdb, @@ -2675,25 +2609,16 @@ static gnc_numeric convert_amount_at_date (GNCPriceDB *pdb, const gnc_commodity *new_currency, const time64 t) { - gnc_numeric new_value; + gnc_numeric price; - if (gnc_numeric_zero_p (amount) || - gnc_commodity_equiv (orig_currency, new_currency)) + if (gnc_numeric_zero_p (amount)) return amount; - /* Look for a direct price. */ - new_value = direct_balance_conversion - (pdb, amount, orig_currency, new_currency, t); + price = gnc_pricedb_get_nearest_price (pdb, orig_currency, new_currency, t); - /* - * no direct price found, try if we find a price in another currency - * and convert in two stages - */ - if (gnc_numeric_zero_p (new_value)) - new_value = indirect_balance_conversion - (pdb, amount, orig_currency, new_currency, t); - - return new_value; + return gnc_numeric_mul + (amount, price, gnc_commodity_get_fraction (new_currency), + GNC_HOW_DENOM_EXACT | GNC_HOW_RND_ROUND); } /* diff --git a/libgnucash/engine/gnc-pricedb.h b/libgnucash/engine/gnc-pricedb.h index 6a8301f3c0..5010476c3e 100644 --- a/libgnucash/engine/gnc-pricedb.h +++ b/libgnucash/engine/gnc-pricedb.h @@ -559,6 +559,24 @@ PriceList * gnc_pricedb_lookup_latest_before_any_currency_t64(GNCPriceDB *db, time64 t); +/** @brief Retrieve the price one currency to another at specified date + * @param pdb The pricedb + * @param orig_currency The commodity in which the balance is currently + * expressed + * @param new_currency The commodity to which the balance should be converted + * @return A price, or gnc_numeric_zero if no price is available. + */ + +gnc_numeric gnc_pricedb_get_nearest_price (GNCPriceDB *pdb, + const gnc_commodity *orig_currency, + const gnc_commodity *new_currency, + const time64 t); + +gnc_numeric gnc_pricedb_get_latest_price (GNCPriceDB *pdb, + const gnc_commodity *orig_currency, + const gnc_commodity *new_currency); + + /** @brief Convert a balance from one currency to another using the most recent * price between the two. * @param pdb The pricedb From e833c8e1aa6f55341692d81c9d87aa0ad53b393b Mon Sep 17 00:00:00 2001 From: Christopher Lam Date: Mon, 26 Oct 2020 20:48:52 +0800 Subject: [PATCH 4/8] [utest-gnc-pricedb.c] test: gnc_pricedb_get_[latest|nearest]_price --- libgnucash/engine/test/utest-gnc-pricedb.c | 80 ++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/libgnucash/engine/test/utest-gnc-pricedb.c b/libgnucash/engine/test/utest-gnc-pricedb.c index 0afeb86c1f..daf34df4f4 100644 --- a/libgnucash/engine/test/utest-gnc-pricedb.c +++ b/libgnucash/engine/test/utest-gnc-pricedb.c @@ -1248,6 +1248,84 @@ test_gnc_pricedb_convert_balance_nearest_price_t64 (PriceDBFixture *fixture, gco g_assert_cmpint(result.denom, ==, 100); } + +static void +test_gnc_pricedb_get_latest_price (PriceDBFixture *fixture, gconstpointer pData) +{ + gnc_numeric result; + + result = gnc_pricedb_get_latest_price (fixture->pricedb, + fixture->com->usd, + fixture->com->aud); + g_assert_cmpint(result.num, ==, 3587); + g_assert_cmpint(result.denom, ==, 3125); + + result = gnc_pricedb_get_latest_price (fixture->pricedb, + fixture->com->usd, + fixture->com->gbp); + g_assert_cmpint(result.num, ==, 50000); + g_assert_cmpint(result.denom, ==, 78829); + + result = gnc_pricedb_get_latest_price (fixture->pricedb, + fixture->com->usd, + fixture->com->eur); + g_assert_cmpint(result.num, ==, 63418); + g_assert_cmpint(result.denom, ==, 78829); + + result = gnc_pricedb_get_latest_price (fixture->pricedb, + fixture->com->gbp, + fixture->com->dkk); + g_assert_cmpint(result.num, ==, 47194370497); + g_assert_cmpint(result.denom, ==, 5000000000); + + result = gnc_pricedb_get_latest_price (fixture->pricedb, + fixture->com->amzn, + fixture->com->aud); + g_assert_cmpint(result.num, ==, 111738637); + g_assert_cmpint(result.denom, ==, 312500); +} + +static void +test_gnc_pricedb_get_nearest_price (PriceDBFixture *fixture, gconstpointer pData) +{ + time64 t = gnc_dmy2time64(15, 8, 2011); + gnc_numeric result; + + result = gnc_pricedb_get_nearest_price (fixture->pricedb, + fixture->com->usd, + fixture->com->aud, t); + g_assert_cmpint(result.num, ==, 1250); + g_assert_cmpint(result.denom, ==, 1331); + + result = gnc_pricedb_get_nearest_price (fixture->pricedb, + fixture->com->usd, + fixture->com->gbp, + t); + g_assert_cmpint(result.num, ==, 100000); + g_assert_cmpint(result.denom, ==, 161643); + + result = gnc_pricedb_get_nearest_price (fixture->pricedb, + fixture->com->usd, + fixture->com->eur, + t); + g_assert_cmpint(result.num, ==, 37763); + g_assert_cmpint(result.denom, ==, 53881); + + result = gnc_pricedb_get_nearest_price (fixture->pricedb, + fixture->com->gbp, + fixture->com->dkk, + t); + g_assert_cmpint(result.num, ==, 84450223707); + g_assert_cmpint(result.denom, ==, 10000000000); + + result = gnc_pricedb_get_nearest_price (fixture->pricedb, + fixture->com->amzn, + fixture->com->aud, + t); + g_assert_cmpint(result.num, ==, 278150); + g_assert_cmpint(result.denom, ==, 1331); +} + /* pricedb_foreach_pricelist static void pricedb_foreach_pricelist(gpointer key, gpointer val, gpointer user_data)// Local: 0:1:0 @@ -1504,6 +1582,8 @@ test_suite_gnc_pricedb (void) // GNC_TEST_ADD (suitename, "indirect balance conversion", Fixture, NULL, setup, test_indirect_balance_conversion, teardown); GNC_TEST_ADD (suitename, "gnc pricedb convert balance latest price", PriceDBFixture, NULL, setup, test_gnc_pricedb_convert_balance_latest_price, teardown); GNC_TEST_ADD (suitename, "gnc pricedb convert balance nearest price", PriceDBFixture, NULL, setup, test_gnc_pricedb_convert_balance_nearest_price_t64, teardown); + GNC_TEST_ADD (suitename, "gnc pricedb get latest price", PriceDBFixture, NULL, setup, test_gnc_pricedb_get_latest_price, teardown); + GNC_TEST_ADD (suitename, "gnc pricedb get nearest price", PriceDBFixture, NULL, setup, test_gnc_pricedb_get_nearest_price, teardown); // GNC_TEST_ADD (suitename, "pricedb foreach pricelist", Fixture, NULL, setup, test_pricedb_foreach_pricelist, teardown); // GNC_TEST_ADD (suitename, "pricedb foreach currencies hash", Fixture, NULL, setup, test_pricedb_foreach_currencies_hash, teardown); // GNC_TEST_ADD (suitename, "unstable price traversal", Fixture, NULL, setup, test_unstable_price_traversal, teardown); From e7165507c8497bfbcf7d3b107ca4e9ed2912a9d3 Mon Sep 17 00:00:00 2001 From: Christopher Lam Date: Tue, 20 Oct 2020 10:03:48 +0800 Subject: [PATCH 5/8] [commodity-utils.scm][api] gnc:html-make-rates-table with price-fn better precision than gnc:html-make-exchangerates --- gnucash/report/commodity-utilities.scm | 13 +++++++++++++ gnucash/report/html-utilities.scm | 24 ++++++++++++++++++++++++ gnucash/report/report.scm | 2 ++ 3 files changed, 39 insertions(+) diff --git a/gnucash/report/commodity-utilities.scm b/gnucash/report/commodity-utilities.scm index c6c87efa2d..e777a2a842 100644 --- a/gnucash/report/commodity-utilities.scm +++ b/gnucash/report/commodity-utilities.scm @@ -21,6 +21,7 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (use-modules (ice-9 match)) +(use-modules (srfi srfi-26)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Functions to get splits with interesting data from accounts. @@ -764,6 +765,18 @@ (gnc:exchange-by-pricedb-nearest foreign domestic to-date-tp)))))) +(define (gnc:case-price-fn source target-curr date) + (define pdb (gnc-pricedb-get-db (gnc-get-current-book))) + (case source + ((pricedb-nearest) (cut gnc-pricedb-get-nearest-price pdb <> target-curr date)) + ((pricedb-latest) (cut gnc-pricedb-get-latest-price pdb <> target-curr)) + (else + (lambda (commodity) + (let* ((exchange-fn (gnc:case-exchange-fn source target-curr date)) + (foreign-mon (gnc:make-gnc-monetary commodity 1)) + (domestic-mon (exchange-fn foreign-mon target-curr))) + (gnc:gnc-monetary-amount domestic-mon)))))) + ;; Return a ready-to-use function. Which one to use is determined by ;; the value of 'source-option', whose possible values are set in ;; gnc:options-add-price-source!. diff --git a/gnucash/report/html-utilities.scm b/gnucash/report/html-utilities.scm index d536201e06..fb46b6a34f 100644 --- a/gnucash/report/html-utilities.scm +++ b/gnucash/report/html-utilities.scm @@ -228,6 +228,30 @@ (G_ "Exchange rates")))))) table)) +;; Create a html-table of all prices. The report-currency is +;; 'currency', The prices are given through the function 'price-fn' +;; and the 'accounts' determine which commodities to show. Returns a +;; html-object, a . price-fn is easily obtained from +;; gnc:case-price-fn +(define (gnc:html-make-rates-table currency price-fn accounts) + (define (cell c) (gnc:make-html-table-cell/markup "number-cell" c)) + (define table (gnc:make-html-table)) + (let lp ((comm-list (gnc:accounts-get-commodities accounts currency)) (entries 0)) + (match comm-list + (() + (unless (zero? entries) + (gnc:html-table-set-col-headers! + table (list (gnc:make-html-table-header-cell/size + 1 2 (if (= entries 1) (G_ "Exchange rate") + (G_ "Exchange rates")))))) + table) + ((comm . rest) + (gnc:html-table-append-row! + table + (list (cell (gnc:make-gnc-monetary comm 1)) + (cell (gnc:default-price-renderer currency (price-fn comm))))) + (lp rest (1+ entries)))))) + (define (gnc:html-make-generic-budget-warning report-title-string) (gnc:html-make-generic-simple-warning diff --git a/gnucash/report/report.scm b/gnucash/report/report.scm index 7791d969e3..8444da85c0 100644 --- a/gnucash/report/report.scm +++ b/gnucash/report/report.scm @@ -58,6 +58,7 @@ (export gnc:exchange-by-pricealist-nearest) (export gnc:case-exchange-fn) (export gnc:case-exchange-time-fn) +(export gnc:case-price-fn) (export gnc:sum-collector-commodity) ;; options-utilities.scm @@ -104,6 +105,7 @@ (export gnc:assign-colors) (export gnc:html-table-append-ruler!) (export gnc:html-make-exchangerates) +(export gnc:html-make-rates-table) (export gnc:html-render-options-changed) (export gnc:html-make-generic-warning) (export gnc:html-make-no-account-warning) From 4ff3355f02498308d4683906e2a23620b0b0414e Mon Sep 17 00:00:00 2001 From: Christopher Lam Date: Tue, 20 Oct 2020 21:55:55 +0800 Subject: [PATCH 6/8] [html-style-info.scm] price-renderer does not convert to decimal so that it may obey global pref decimal vs fraction --- gnucash/report/html-style-info.scm | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/gnucash/report/html-style-info.scm b/gnucash/report/html-style-info.scm index 20f34e640e..0c58671ece 100644 --- a/gnucash/report/html-style-info.scm +++ b/gnucash/report/html-style-info.scm @@ -167,12 +167,8 @@ (xaccPrintAmount datum (gnc-default-print-info #f))) ;; renders a price to target currency -(define (gnc:default-price-renderer currency amount) - (xaccPrintAmount - (gnc-numeric-convert - amount (min 10000 (* 100 (gnc-commodity-get-fraction currency))) - GNC-HOW-RND-ROUND) - (gnc-price-print-info currency #t))) +(define (gnc:default-price-renderer currency price) + (xaccPrintAmount price (gnc-price-print-info currency #t))) (define (gnc:default-html-gnc-monetary-renderer datum params) (let* ((comm (gnc:gnc-monetary-commodity datum)) From 89c0baee9b6f6ae6c7c74730f9920a61157adb93 Mon Sep 17 00:00:00 2001 From: Christopher Lam Date: Mon, 19 Oct 2020 22:29:59 +0800 Subject: [PATCH 7/8] Bug 797982 - exchange rates' decimal places use gnc:html-make-rates-table instead of gnc:html-make-exchangerates to show effective exchange rate or price used --- gnucash/report/reports/standard/account-summary.scm | 5 +++-- gnucash/report/reports/standard/balance-sheet.scm | 3 ++- .../report/reports/standard/budget-balance-sheet.scm | 6 +++--- .../reports/standard/budget-income-statement.scm | 5 +++-- gnucash/report/reports/standard/cash-flow.scm | 6 ++++-- gnucash/report/reports/standard/equity-statement.scm | 12 +++++++----- gnucash/report/reports/standard/income-statement.scm | 6 +++--- gnucash/report/reports/standard/trial-balance.scm | 5 +++-- 8 files changed, 28 insertions(+), 20 deletions(-) diff --git a/gnucash/report/reports/standard/account-summary.scm b/gnucash/report/reports/standard/account-summary.scm index 0ea163838e..0ffb26641e 100644 --- a/gnucash/report/reports/standard/account-summary.scm +++ b/gnucash/report/reports/standard/account-summary.scm @@ -315,6 +315,7 @@ (gnc:get-current-account-tree-depth) depth-limit)) ;; exchange rates calculation parameters + (price-fn (gnc:case-price-fn price-source report-commodity to-date)) (exchange-fn (gnc:case-exchange-fn price-source report-commodity to-date))) (gnc:html-document-set-title! @@ -441,8 +442,8 @@ ;; add currency information (when show-rates? (gnc:html-document-add-object! - doc (gnc:html-make-exchangerates - report-commodity exchange-fn + doc (gnc:html-make-rates-table + report-commodity price-fn (gnc:accounts-and-all-descendants accounts)))))) (gnc:report-finished) diff --git a/gnucash/report/reports/standard/balance-sheet.scm b/gnucash/report/reports/standard/balance-sheet.scm index dddc7dfdcd..6c1c32d769 100644 --- a/gnucash/report/reports/standard/balance-sheet.scm +++ b/gnucash/report/reports/standard/balance-sheet.scm @@ -343,6 +343,7 @@ (tree-depth (if (eq? depth-limit 'all) (gnc:get-current-account-tree-depth) depth-limit)) + (price-fn (gnc:case-price-fn price-source report-commodity reportdate)) ;; exchange rates calculation parameters (exchange-fn (gnc:case-exchange-fn price-source report-commodity reportdate))) @@ -550,7 +551,7 @@ (gnc:report-percent-done 90) (when show-rates? (gnc:html-document-add-object! - doc (gnc:html-make-exchangerates report-commodity exchange-fn accounts))) + doc (gnc:html-make-rates-table report-commodity price-fn accounts))) (gnc:report-percent-done 100))) diff --git a/gnucash/report/reports/standard/budget-balance-sheet.scm b/gnucash/report/reports/standard/budget-balance-sheet.scm index d50a7a0d75..03df94ecee 100644 --- a/gnucash/report/reports/standard/budget-balance-sheet.scm +++ b/gnucash/report/reports/standard/budget-balance-sheet.scm @@ -355,7 +355,8 @@ ;; exchange rates calculation parameters (exchange-fn (gnc:case-exchange-fn price-source report-commodity date-t64)) - ) + + (price-fn (gnc:case-price-fn price-source report-commodity date-t64))) (define (add-subtotal-line table pos-label neg-label signed-balance) (let* ((neg? (and signed-balance neg-label @@ -808,8 +809,7 @@ (if show-rates? (gnc:html-document-add-object! doc ;;(gnc:html-markup-p) - (gnc:html-make-exchangerates - report-commodity exchange-fn accounts))) + (gnc:html-make-rates-table report-commodity price-fn accounts))) (gnc:report-percent-done 100))))) (gnc:report-finished) diff --git a/gnucash/report/reports/standard/budget-income-statement.scm b/gnucash/report/reports/standard/budget-income-statement.scm index 2e2978b56f..e12e22e7ef 100644 --- a/gnucash/report/reports/standard/budget-income-statement.scm +++ b/gnucash/report/reports/standard/budget-income-statement.scm @@ -401,7 +401,8 @@ ;; exchange rates calculation parameters (exchange-fn (gnc:case-exchange-fn price-source report-commodity date-t64)) - ) + + (price-fn (gnc:case-price-fn price-source report-commodity date-t64))) (define (add-subtotal-line table pos-label neg-label signed-balance) (let* ((neg? (and signed-balance neg-label @@ -595,7 +596,7 @@ (gnc:report-percent-done 90) (when show-rates? (gnc:html-document-add-object! - doc (gnc:html-make-exchangerates report-commodity exchange-fn accounts))) + doc (gnc:html-make-rates-table report-commodity price-fn accounts))) (gnc:report-percent-done 100)))) (gnc:report-finished) diff --git a/gnucash/report/reports/standard/cash-flow.scm b/gnucash/report/reports/standard/cash-flow.scm index 623f71998a..2379e1885d 100644 --- a/gnucash/report/reports/standard/cash-flow.scm +++ b/gnucash/report/reports/standard/cash-flow.scm @@ -149,6 +149,8 @@ (exchange-fn (gnc:case-exchange-fn price-source report-currency to-date-t64)) + (price-fn (gnc:case-price-fn price-source report-currency to-date-t64)) + (doc (gnc:make-html-document)) (table (gnc:make-html-table)) @@ -321,8 +323,8 @@ (if show-rates? (gnc:html-document-add-object! doc ;;(gnc:html-markup-p - (gnc:html-make-exchangerates - report-currency exchange-fn accounts)))))) + (gnc:html-make-rates-table + report-currency price-fn accounts)))))) ;; error condition: no accounts specified diff --git a/gnucash/report/reports/standard/equity-statement.scm b/gnucash/report/reports/standard/equity-statement.scm index ce13efc1c6..4b47cb1792 100644 --- a/gnucash/report/reports/standard/equity-statement.scm +++ b/gnucash/report/reports/standard/equity-statement.scm @@ -280,7 +280,9 @@ (end-exchange-fn (gnc:case-exchange-fn price-source report-commodity end-date)) - ) + + (start-price-fn (gnc:case-price-fn price-source report-commodity start-date)) + (end-price-fn (gnc:case-price-fn price-source report-commodity end-date))) (define (unrealized-gains-at-date book-balance exchange-fn date) (define cost-fn @@ -496,10 +498,10 @@ (headers (list (qof-print-date start-date-printable) (qof-print-date end-date))) - (then (gnc:html-make-exchangerates - report-commodity start-exchange-fn accounts)) - (now (gnc:html-make-exchangerates - report-commodity end-exchange-fn accounts))) + (then (gnc:html-make-rates-table + report-commodity start-price-fn accounts)) + (now (gnc:html-make-rates-table + report-commodity end-price-fn accounts))) (gnc:html-table-set-col-headers! curr-tbl headers) (gnc:html-table-set-style! curr-tbl "table" 'attribute '("border" "1")) diff --git a/gnucash/report/reports/standard/income-statement.scm b/gnucash/report/reports/standard/income-statement.scm index 93988525d0..ec9d8df4e0 100644 --- a/gnucash/report/reports/standard/income-statement.scm +++ b/gnucash/report/reports/standard/income-statement.scm @@ -382,7 +382,7 @@ ;; exchange rates calculation parameters (exchange-fn (gnc:case-exchange-fn price-source report-commodity end-date)) - ) + (price-fn (gnc:case-price-fn price-source report-commodity end-date))) ;; Wrapper to call gnc:html-table-add-labeled-amount-line! ;; with the proper arguments. @@ -561,8 +561,8 @@ (gnc:report-percent-done 90) (when show-rates? (gnc:html-document-add-object! - doc (gnc:html-make-exchangerates - report-commodity exchange-fn accounts))) + doc (gnc:html-make-rates-table + report-commodity price-fn accounts))) (gnc:report-percent-done 100))) (gnc:report-finished) diff --git a/gnucash/report/reports/standard/trial-balance.scm b/gnucash/report/reports/standard/trial-balance.scm index 18b06f8ab6..b305d70c5a 100644 --- a/gnucash/report/reports/standard/trial-balance.scm +++ b/gnucash/report/reports/standard/trial-balance.scm @@ -401,6 +401,7 @@ ;; exchange rates calculation parameters (exchange-fn (gnc:case-exchange-fn price-source report-commodity end-date)) + (price-fn (gnc:case-price-fn price-source report-commodity end-date)) (period-for (string-append " " (G_ "for Period")))) (gnc:html-document-set-title! @@ -894,8 +895,8 @@ (if show-rates? (gnc:html-document-add-object! doc - (gnc:html-make-exchangerates - report-commodity exchange-fn accounts))) + (gnc:html-make-rates-table + report-commodity price-fn accounts))) (gnc:report-percent-done 100))) (gnc:report-finished) From 1a4f27f6b3b4d3ae2e9263396b32e684f434c96b Mon Sep 17 00:00:00 2001 From: Christopher Lam Date: Wed, 21 Oct 2020 22:45:06 +0800 Subject: [PATCH 8/8] [html-utilities.scm] deprecate gnc:html-make-exchangerates Because old exchange rates function used exchange-fn which converts 1 commodity into domestic currency; new exchange rates uses price-fn which queries the gnc_numeric pricedb entry directly. --- gnucash/report/html-utilities.scm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gnucash/report/html-utilities.scm b/gnucash/report/html-utilities.scm index fb46b6a34f..50629e01d6 100644 --- a/gnucash/report/html-utilities.scm +++ b/gnucash/report/html-utilities.scm @@ -207,6 +207,8 @@ ;; function 'exchange-fn' and the 'accounts' determine which ;; commodities to show. Returns a html-object, a . (define (gnc:html-make-exchangerates common-commodity exchange-fn accounts) + (issue-deprecation-warning + "gnc:html-make-exchangerates is deprecated. use gnc:html-make-rates-table instead.") (let ((comm-list (gnc:accounts-get-commodities accounts common-commodity)) (markup (lambda (c) (gnc:make-html-table-cell/markup "number-cell" c))) (table (gnc:make-html-table)))