gnucash maint: Multiple changes pushed
Christopher Lam
clam at code.gnucash.org
Mon Oct 26 12:00:44 EDT 2020
Updated via https://github.com/Gnucash/gnucash/commit/92f27278 (commit)
via https://github.com/Gnucash/gnucash/commit/1a4f27f6 (commit)
via https://github.com/Gnucash/gnucash/commit/89c0baee (commit)
via https://github.com/Gnucash/gnucash/commit/4ff3355f (commit)
via https://github.com/Gnucash/gnucash/commit/e7165507 (commit)
via https://github.com/Gnucash/gnucash/commit/e833c8e1 (commit)
via https://github.com/Gnucash/gnucash/commit/2ecdd70e (commit)
via https://github.com/Gnucash/gnucash/commit/4d63eb92 (commit)
via https://github.com/Gnucash/gnucash/commit/26e7eada (commit)
from https://github.com/Gnucash/gnucash/commit/b675e17e (commit)
commit 92f272786219adee04b7ce96bb15abc864cbb15e
Merge: b675e17e4 1a4f27f6b
Author: Christopher Lam <christopher.lck at gmail.com>
Date: Mon Oct 26 23:57:39 2020 +0800
Merge branch 'maint-797982' into maint #802
commit 1a4f27f6b3b4d3ae2e9263396b32e684f434c96b
Author: Christopher Lam <christopher.lck at gmail.com>
Date: Wed Oct 21 22:45:06 2020 +0800
[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.
diff --git a/gnucash/report/html-utilities.scm b/gnucash/report/html-utilities.scm
index fb46b6a34..50629e01d 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 <html-table>.
(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)))
commit 89c0baee9b6f6ae6c7c74730f9920a61157adb93
Author: Christopher Lam <christopher.lck at gmail.com>
Date: Mon Oct 19 22:29:59 2020 +0800
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
diff --git a/gnucash/report/reports/standard/account-summary.scm b/gnucash/report/reports/standard/account-summary.scm
index 0ea163838..0ffb26641 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 dddc7dfdc..6c1c32d76 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 d50a7a0d7..03df94ece 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 2e2978b56..e12e22e7e 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 623f71998..2379e1885 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 ce13efc1c..4b47cb179 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 93988525d..ec9d8df4e 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 18b06f8ab..b305d70c5 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)
commit 4ff3355f02498308d4683906e2a23620b0b0414e
Author: Christopher Lam <christopher.lck at gmail.com>
Date: Tue Oct 20 21:55:55 2020 +0800
[html-style-info.scm] price-renderer does not convert to decimal
so that it may obey global pref decimal vs fraction
diff --git a/gnucash/report/html-style-info.scm b/gnucash/report/html-style-info.scm
index 20f34e640..0c58671ec 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))
commit e7165507c8497bfbcf7d3b107ca4e9ed2912a9d3
Author: Christopher Lam <christopher.lck at gmail.com>
Date: Tue Oct 20 10:03:48 2020 +0800
[commodity-utils.scm][api] gnc:html-make-rates-table with price-fn
better precision than gnc:html-make-exchangerates
diff --git a/gnucash/report/commodity-utilities.scm b/gnucash/report/commodity-utilities.scm
index c6c87efa2..e777a2a84 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 d536201e0..fb46b6a34 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 <html-table>. 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 7791d969e..8444da85c 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)
commit e833c8e1aa6f55341692d81c9d87aa0ad53b393b
Author: Christopher Lam <christopher.lck at gmail.com>
Date: Mon Oct 26 20:48:52 2020 +0800
[utest-gnc-pricedb.c] test: gnc_pricedb_get_[latest|nearest]_price
diff --git a/libgnucash/engine/test/utest-gnc-pricedb.c b/libgnucash/engine/test/utest-gnc-pricedb.c
index 0afeb86c1..daf34df4f 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);
commit 2ecdd70e2412dac95d6b65eece136e718797252f
Author: Christopher Lam <christopher.lck at gmail.com>
Date: Mon Oct 19 20:08:44 2020 +0800
[gnc-pricedb.c][api] pull out composite pricedb price retriever
* tries direct price retrieval from pricedb.
* if fails, tries intermediate currency.
diff --git a/libgnucash/engine/gnc-pricedb.c b/libgnucash/engine/gnc-pricedb.c
index 3b39788c1..481df22ad 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);
-
- /*
- * 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);
+ price = gnc_pricedb_get_nearest_price (pdb, 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 6a8301f3c..5010476c3 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
commit 4d63eb922f4ae3794315dad36c9dafc0e9f752e3
Author: Christopher Lam <christopher.lck at gmail.com>
Date: Mon Oct 19 10:47:50 2020 +0800
[gnc-pricedb.c] copy convert_amount to convert_price
diff --git a/libgnucash/engine/gnc-pricedb.c b/libgnucash/engine/gnc-pricedb.c
index 6887652d6..3b39788c1 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)
commit 26e7eada37efa2a3b91509483e17e9c9ba544ec6
Author: Christopher Lam <christopher.lck at gmail.com>
Date: Mon Oct 19 10:26:23 2020 +0800
[gnc-pricedb.c] refactor amount converters, use common code
diff --git a/libgnucash/engine/gnc-pricedb.c b/libgnucash/engine/gnc-pricedb.c
index 94075ac03..6887652d6 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);
}
Summary of changes:
gnucash/report/commodity-utilities.scm | 13 ++
gnucash/report/html-style-info.scm | 8 +-
gnucash/report/html-utilities.scm | 26 +++
gnucash/report/report.scm | 2 +
.../report/reports/standard/account-summary.scm | 5 +-
gnucash/report/reports/standard/balance-sheet.scm | 3 +-
.../reports/standard/budget-balance-sheet.scm | 6 +-
.../reports/standard/budget-income-statement.scm | 5 +-
gnucash/report/reports/standard/cash-flow.scm | 6 +-
.../report/reports/standard/equity-statement.scm | 12 +-
.../report/reports/standard/income-statement.scm | 6 +-
gnucash/report/reports/standard/trial-balance.scm | 5 +-
libgnucash/engine/gnc-pricedb.c | 215 +++++++++++----------
libgnucash/engine/gnc-pricedb.h | 18 ++
libgnucash/engine/test/utest-gnc-pricedb.c | 80 ++++++++
15 files changed, 280 insertions(+), 130 deletions(-)
More information about the gnucash-changes
mailing list