[Gnucash-changes] r13611 - gnucash/trunk - Andrew Sackville-West's
changes to add the ability to lookup the
David Hampton
hampton at cvs.gnucash.org
Sun Mar 12 17:18:28 EST 2006
Author: hampton
Date: 2006-03-12 17:18:28 -0500 (Sun, 12 Mar 2006)
New Revision: 13611
Trac: http://svn.gnucash.org/trac/changeset/13611
Modified:
gnucash/trunk/ChangeLog
gnucash/trunk/src/engine/gnc-pricedb.c
gnucash/trunk/src/engine/gnc-pricedb.h
gnucash/trunk/src/engine/gw-engine-spec.scm
Log:
Andrew Sackville-West's changes to add the ability to lookup the
latest price before a specific date.
Modified: gnucash/trunk/ChangeLog
===================================================================
--- gnucash/trunk/ChangeLog 2006-03-12 21:54:04 UTC (rev 13610)
+++ gnucash/trunk/ChangeLog 2006-03-12 22:18:28 UTC (rev 13611)
@@ -1,5 +1,10 @@
2006-03-12 David Hampton <hampton at employees.org>
+ * src/engine/gnc-pricedb.[ch]:
+ * src/engine/gw-engine-spec.scm: Andrew Sackville-West's changes
+ to add the ability to lookup the latest price before a specific
+ date.
+
* src/register/register-gnome/gnucash-sheet.[ch]:
* src/register/ledger-core/split-register.[ch]:
* src/register/ledger-core/split-register-control.c:
Modified: gnucash/trunk/src/engine/gnc-pricedb.c
===================================================================
--- gnucash/trunk/src/engine/gnc-pricedb.c 2006-03-12 21:54:04 UTC (rev 13610)
+++ gnucash/trunk/src/engine/gnc-pricedb.c 2006-03-12 22:18:28 UTC (rev 13611)
@@ -1575,6 +1575,59 @@
return result;
}
+GNCPrice *
+gnc_pricedb_lookup_latest_before (GNCPriceDB *db,
+ gnc_commodity *c,
+ gnc_commodity *currency,
+ Timespec t)
+{
+ GList *price_list;
+ GNCPrice *current_price = NULL;
+ /* GNCPrice *next_price = NULL;
+ GNCPrice *result = NULL;*/
+ GList *item = NULL;
+ GHashTable *currency_hash;
+ QofBook *book;
+ QofBackend *be;
+ Timespec price_time;
+
+ if(!db || !c || !currency) return NULL;
+ ENTER ("db=%p commodity=%p currency=%p", db, c, currency);
+ book = qof_instance_get_book(&db->inst);
+ be = qof_book_get_backend(book);
+#ifdef GNUCASH_MAJOR_VERSION
+ if (be && be->price_lookup)
+ {
+ GNCPriceLookup pl;
+ pl.type = LOOKUP_LATEST_BEFORE;
+ pl.prdb = db;
+ pl.commodity = c;
+ pl.currency = currency;
+ pl.date = t;
+ (be->price_lookup) (be, &pl);
+ }
+#endif
+ currency_hash = g_hash_table_lookup(db->commodity_hash, c);
+ if(!currency_hash) { LEAVE ("no currency hash"); return NULL; }
+
+ price_list = g_hash_table_lookup(currency_hash, currency);
+ if(!price_list) { LEAVE ("no price list"); return NULL; }
+
+ item = price_list;
+ do
+ {
+ price_time = gnc_price_get_time (item->data);
+ if (timespec_cmp(&price_time, &t) <= 0)
+ current_price = item->data;
+ item = item->next;
+ }
+ while (timespec_cmp(&price_time, &t) > 0 && item);
+ gnc_price_ref(current_price);
+ LEAVE (" ");
+ return current_price;
+}
+
+
static void
lookup_nearest(gpointer key, gpointer val, gpointer user_data)
{
@@ -1628,6 +1681,38 @@
gnc_price_list_insert(return_list, result, FALSE);
}
+
+static void
+lookup_latest_before(gpointer key, gpointer val, gpointer user_data)
+{
+ //gnc_commodity *currency = (gnc_commodity *)key;
+ GList *price_list = (GList *)val;
+ GNCPrice *current_price = NULL;
+ /* GNCPrice *next_price = NULL;
+ GNCPrice *result = NULL;*/
+ GList *item = NULL;
+ GNCPriceLookupHelper *lookup_helper = (GNCPriceLookupHelper *)user_data;
+ GList **return_list = lookup_helper->return_list;
+ Timespec t = lookup_helper->time;
+ Timespec price_time;
+
+ if (price_list)
+ {
+ item = price_list;
+ do
+ {
+ price_time = gnc_price_get_time (item->data);
+ if (timespec_cmp(&price_time, &t) <= 0)
+ current_price = item->data;
+ item = item->next;
+ }
+ while (timespec_cmp(&price_time, &t) > 0 && item);
+ }
+
+ gnc_price_list_insert(return_list, current_price, FALSE);
+}
+
+
GList *
gnc_pricedb_lookup_nearest_in_time_any_currency(GNCPriceDB *db,
const gnc_commodity *c,
@@ -1671,6 +1756,49 @@
}
+GList *
+gnc_pricedb_lookup_latest_before_any_currency(GNCPriceDB *db,
+ gnc_commodity *c,
+ Timespec t)
+{
+ GList *result = NULL;
+ GHashTable *currency_hash;
+ GNCPriceLookupHelper lookup_helper;
+ QofBook *book;
+ QofBackend *be;
+
+ if(!db || !c) return NULL;
+ ENTER ("db=%p commodity=%p", db, c);
+ book = qof_instance_get_book(&db->inst);
+ be = qof_book_get_backend(book);
+#ifdef GNUCASH_MAJOR_VERSION
+ if (be && be->price_lookup)
+ {
+ GNCPriceLookup pl;
+ pl.type = LOOKUP_LATEST_BEFORE;
+ pl.prdb = db;
+ pl.commodity = c;
+ pl.currency = NULL; /* can the backend handle this??? */
+ pl.date = t;
+ (be->price_lookup) (be, &pl);
+ }
+#endif
+ currency_hash = g_hash_table_lookup(db->commodity_hash, c);
+ if(!currency_hash) { LEAVE (" no currency hash"); return NULL; }
+
+ lookup_helper.return_list = &result;
+ lookup_helper.time = t;
+ g_hash_table_foreach(currency_hash, lookup_latest_before, &lookup_helper);
+
+ if(!result) { LEAVE (" "); return NULL; }
+
+ result = g_list_sort(result, compare_prices_by_date);
+
+ LEAVE (" ");
+ return result;
+}
+
+
/*
* Convert a balance from one currency to another.
*/
@@ -1817,6 +1945,7 @@
balance = gnc_numeric_mul (balance, currency_price_value,
gnc_commodity_get_fraction (new_currency),
GNC_HOW_RND_ROUND);
+
balance = gnc_numeric_mul (balance, gnc_price_get_value (price),
gnc_commodity_get_fraction (new_currency),
GNC_HOW_RND_ROUND);
@@ -1826,6 +1955,85 @@
}
+gnc_numeric
+gnc_pricedb_convert_balance_latest_before(GNCPriceDB *pdb,
+ gnc_numeric balance,
+ gnc_commodity *balance_currency,
+ gnc_commodity *new_currency,
+ Timespec t)
+{
+ GNCPrice *price, *currency_price;
+ GList *price_list, *list_helper;
+ gnc_numeric currency_price_value;
+ gnc_commodity *intermediate_currency;
+
+ if (gnc_numeric_zero_p (balance) ||
+ gnc_commodity_equiv (balance_currency, new_currency))
+ return balance;
+
+ /* Look for a direct price. */
+ price = gnc_pricedb_lookup_latest_before (pdb, balance_currency, new_currency, t);
+
+ if (price) {
+ balance = gnc_numeric_mul (balance, gnc_price_get_value (price),
+ gnc_commodity_get_fraction (new_currency),
+ GNC_HOW_RND_ROUND);
+ gnc_price_unref (price);
+ return balance;
+ }
+
+ /*
+ * no direct price found, try if we find a price in another currency
+ * and convert in two stages
+ */
+ price_list = gnc_pricedb_lookup_latest_before_any_currency(pdb, balance_currency, t);
+ if (!price_list) {
+ balance = gnc_numeric_zero ();
+ return balance;
+ }
+
+ list_helper = price_list;
+ currency_price_value = gnc_numeric_zero();
+
+ do {
+ price = (GNCPrice *)(list_helper->data);
+
+ intermediate_currency = gnc_price_get_currency(price);
+ currency_price = gnc_pricedb_lookup_latest_before(pdb, intermediate_currency,
+ new_currency, t);
+ if(currency_price) {
+ currency_price_value = gnc_price_get_value(currency_price);
+ gnc_price_unref(currency_price);
+ } else {
+ currency_price = gnc_pricedb_lookup_nearest_in_time(pdb, new_currency,
+ intermediate_currency, t);
+ if (currency_price) {
+ /* here we need the reciprocal */
+ currency_price_value = gnc_numeric_div(gnc_numeric_create(1, 1),
+ gnc_price_get_value(currency_price),
+ gnc_commodity_get_fraction (new_currency),
+ GNC_HOW_RND_ROUND);
+ gnc_price_unref(currency_price);
+ }
+ }
+
+ list_helper = list_helper->next;
+ } while((list_helper != NULL) &&
+ (!gnc_numeric_zero_p(currency_price_value)));
+
+ balance = gnc_numeric_mul (balance, currency_price_value,
+ gnc_commodity_get_fraction (new_currency),
+ GNC_HOW_RND_ROUND);
+ balance = gnc_numeric_mul (balance, gnc_price_get_value (price),
+ gnc_commodity_get_fraction (new_currency),
+ GNC_HOW_RND_ROUND);
+
+ gnc_price_list_destroy(price_list);
+ return balance;
+}
+
+
+
/* ==================================================================== */
/* gnc_pricedb_foreach_price infrastructure
*/
Modified: gnucash/trunk/src/engine/gnc-pricedb.h
===================================================================
--- gnucash/trunk/src/engine/gnc-pricedb.h 2006-03-12 21:54:04 UTC (rev 13610)
+++ gnucash/trunk/src/engine/gnc-pricedb.h 2006-03-12 22:18:28 UTC (rev 13611)
@@ -348,7 +348,21 @@
GList * gnc_pricedb_lookup_nearest_in_time_any_currency(GNCPriceDB *db,
const gnc_commodity *c,
Timespec t);
+/** gnc_pricedb_lookup_latest_before - return the latest price for the given commodity
+ in the given currency up to and including time t. */
+GNCPrice * gnc_pricedb_lookup_latest_before(GNCPriceDB *db,
+ gnc_commodity *c,
+ gnc_commodity *currency,
+ Timespec t);
+/** gnc_pricedb_lookup_latest_before_any_currency - return recent prices that
+ match the given commodity up to and including time t in any available currency. Prices
+ will be returned as a GNCPrice list (see above). */
+GList * gnc_pricedb_lookup_latest_before_any_currency(GNCPriceDB *db,
+ gnc_commodity *c,
+ Timespec t);
+
+
/** gnc_pricedb_convert_balance_latest_price - Convert a balance
from one currency to another. */
gnc_numeric
@@ -366,6 +380,16 @@
const gnc_commodity *new_currency,
Timespec t);
+/** gnc_pricedb_convert_balance_latest_before - Convert a balance from one currency
+ to another using the lastest price prior to Timespec t. */
+gnc_numeric
+gnc_pricedb_convert_balance_latest_before(GNCPriceDB *pdb,
+ gnc_numeric balance,
+ gnc_commodity *balance_currency,
+ gnc_commodity *new_currency,
+ Timespec t);
+
+
/** gnc_pricedb_foreach_price - call f once for each price in db, until
and unless f returns FALSE. If stable_order is not FALSE, make
sure the ordering of the traversal is stable (i.e. the same order
Modified: gnucash/trunk/src/engine/gw-engine-spec.scm
===================================================================
--- gnucash/trunk/src/engine/gw-engine-spec.scm 2006-03-12 21:54:04 UTC (rev 13610)
+++ gnucash/trunk/src/engine/gw-engine-spec.scm 2006-03-12 22:18:28 UTC (rev 13611)
@@ -1300,7 +1300,28 @@
(<gnc:commodity*> commodity) (<gnc:time-pair> t))
"Returns the price(s) nearest to t in any currency available.")
+
(gw:wrap-function
+ws
+'gnc:pricedb-lookup-latest-before
+'<gnc:Price*>
+"gnc_pricedb_lookup_latest_before"
+'((<gnc:PriceDB*> db)
+ (<gnc:commodity*> commodity) (<gnc:commodity*> currency)
+ (<gnc:time-pair> t))
+"Returns the latest price quote <= t. Unref price when finished with it.")
+
+(gw:wrap-function
+ws
+'gnc:pricedb-lookup-latest-before-any-currency
+'(gw:glist-of <gnc:Price*> caller-owned)
+"gnc_pricedb_lookup_latest_before_any_currency"
+'((<gnc:PriceDB*> db)
+ (<gnc:commodity*> commodity) (<gnc:time-pair> t))
+"Returns the latest price quote(s) <= t in any currency available.")
+
+
+(gw:wrap-function
ws
'gnc:pricedb-get-prices
'(gw:glist-of <gnc:Price*> caller-owned)
@@ -1352,6 +1373,20 @@
"convert balance in commodity balance_commodity to new_currency using nearest price
to time t.")
+
+(gw:wrap-function
+ ws
+ 'gnc:pricedb-convert-balance-latest-before
+ '<gnc:numeric>
+ "gnc_pricedb_convert_balance_latest_before"
+ '((<gnc:PriceDB*> db)
+ (<gnc:numeric> balance)
+ (<gnc:commodity*> balance_commodity) (<gnc:commodity*> new_currency)
+ (<gnc:time-pair> t))
+ "convert balance in commodity balance_commodity to new_currency using latest price
+prior to time t.")
+
+
;;===========
;; QofSession
More information about the gnucash-changes
mailing list