diff --git a/ChangeLog b/ChangeLog index 7fa4950eb8..2fe514c34b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2003-03-31 Herbert Thoma + + * src/engine/gnc-pricedb.c + * src/engine/gnc-pricedb.h: new function + gnc_pricedb_lookup_latest_any_currency, return any available + prices for given commodity regardless of currency + + * src/app-utils/gnc-ui-util.c: do a "two stage" price lookup in + gnc_ui_convert_balance_to_currency if no price for the commodity + is found in the requested currency, then look for prices in any + currency and for a exchange rate from the price currency to the + requested currency + + * src/gnome/gnc-split-reg.c: do currency conversion and show the + value in the status line of stock and mutual fund accounts + 2003-03-31 Derek Atkins * src/business/business-core/test/test-employee.c: fix the test diff --git a/src/app-utils/gnc-ui-util.c b/src/app-utils/gnc-ui-util.c index 04c7bdaf54..9faff53417 100644 --- a/src/app-utils/gnc-ui-util.c +++ b/src/app-utils/gnc-ui-util.c @@ -392,14 +392,70 @@ gnc_ui_convert_balance_to_currency(gnc_numeric balance, gnc_commodity *balance_c pdb = gnc_book_get_pricedb (book); price = gnc_pricedb_lookup_latest (pdb, balance_currency, currency); - if (!price) - return gnc_numeric_zero (); - balance = gnc_numeric_mul (balance, gnc_price_get_value (price), - gnc_commodity_get_fraction (currency), - GNC_RND_ROUND); + if (price) + { + balance = gnc_numeric_mul (balance, gnc_price_get_value (price), + gnc_commodity_get_fraction (currency), + GNC_RND_ROUND); + gnc_price_unref (price); + } + else + { + /* no direct price found, try if we find a price in another + currency and convert in two stages */ + GList *price_list = gnc_pricedb_lookup_latest_any_currency(pdb, balance_currency); + + if(price_list) + { + GList *list_helper = price_list; + gnc_numeric currency_price_value = gnc_numeric_zero(); + gnc_commodity *intermediate_currency; + GNCPrice *currency_price; - gnc_price_unref (price); + do + { + price = (GNCPrice *)(list_helper->data); + + intermediate_currency = gnc_price_get_currency(price); + currency_price = gnc_pricedb_lookup_latest(pdb, intermediate_currency, currency); + if(currency_price) + { + currency_price_value = gnc_price_get_value(currency_price); + gnc_price_unref(currency_price); + } + else + { + currency_price = gnc_pricedb_lookup_latest(pdb, currency, intermediate_currency); + 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 (currency), + GNC_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 (currency), + GNC_RND_ROUND); + balance = gnc_numeric_mul (balance, gnc_price_get_value (price), + gnc_commodity_get_fraction (currency), + GNC_RND_ROUND); + + gnc_price_list_destroy(price_list); + } + else + { + balance = gnc_numeric_zero (); + } + } return balance; } diff --git a/src/engine/gnc-pricedb.c b/src/engine/gnc-pricedb.c index 976aa7c5b9..890850c6a7 100644 --- a/src/engine/gnc-pricedb.c +++ b/src/engine/gnc-pricedb.c @@ -989,6 +989,44 @@ gnc_pricedb_lookup_latest(GNCPriceDB *db, return result; } +static void +lookup_latest(gpointer key, gpointer val, gpointer user_data) +{ + //gnc_commodity *currency = (gnc_commodity *)key; + GList *price_list = (GList *)val; + GList **return_list = (GList **)user_data; + + if(!price_list) return; + + /* the latest price ist the first in list */ + gnc_price_list_insert(return_list, price_list->data); +} + +GList * +gnc_pricedb_lookup_latest_any_currency(GNCPriceDB *db, + gnc_commodity *commodity) +{ + GList *result; + GHashTable *currency_hash; + + result = NULL; + + ENTER ("db=%p commodity=%p", db, commodity); + if(!db || !commodity) return NULL; + + currency_hash = g_hash_table_lookup(db->commodity_hash, commodity); + if(!currency_hash) return NULL; + + g_hash_table_foreach(currency_hash, lookup_latest, &result); + + if(!result) return NULL; + + result = g_list_sort(result, compare_prices_by_date); + + LEAVE(" "); + return result; +} + GList * gnc_pricedb_get_prices(GNCPriceDB *db, gnc_commodity *commodity, diff --git a/src/engine/gnc-pricedb.h b/src/engine/gnc-pricedb.h index 6a4d244479..b29eb9fce8 100644 --- a/src/engine/gnc-pricedb.h +++ b/src/engine/gnc-pricedb.h @@ -249,6 +249,12 @@ GNCPrice * gnc_pricedb_lookup_latest(GNCPriceDB *db, gnc_commodity *commodity, gnc_commodity *currency); +/** gnc_pricedb_lookup_latest_any_currency - find the most recent prices + for the given commodity in any available currency. Returns NULL on + failure. */ +GList *gnc_pricedb_lookup_latest_any_currency(GNCPriceDB *db, + gnc_commodity *commodity); + /** gnc_pricedb_get_prices - return all the prices for a given commodity in the given currency. Returns NULL on failure. The result is a GNCPrice list (see above). */ diff --git a/src/gnome/gnc-split-reg.c b/src/gnome/gnc-split-reg.c index e7f6271367..d2b0af4207 100644 --- a/src/gnome/gnc-split-reg.c +++ b/src/gnome/gnc-split-reg.c @@ -645,6 +645,29 @@ account_latest_price (Account *account) return gnc_pricedb_lookup_latest (pdb, commodity, currency); } +static GNCPrice * +account_latest_price_any_currency (Account *account) +{ + GNCBook *book; + GNCPriceDB *pdb; + gnc_commodity *commodity; + GList *price_list; + GNCPrice *result; + + commodity = xaccAccountGetCommodity (account); + + book = gnc_get_current_book (); + pdb = gnc_book_get_pricedb (book); + + price_list = gnc_pricedb_lookup_latest_any_currency (pdb, commodity); + + result = gnc_price_clone((GNCPrice *)(price_list->data), book); + + gnc_price_list_destroy(price_list); + + return result; +} + static void gsr_redraw_all_cb (GnucashRegister *g_reg, gpointer data) @@ -716,9 +739,45 @@ gsr_redraw_all_cb (GnucashRegister *g_reg, gpointer data) price = account_latest_price (leader); if (!price) { - gnc_set_label_color (gsr->value_label, gnc_numeric_zero ()); - gtk_label_set_text (GTK_LABEL (gsr->value_label), - _("")); + price = account_latest_price_any_currency (leader); + if(!price) + { + gnc_set_label_color (gsr->value_label, gnc_numeric_zero ()); + gtk_label_set_text (GTK_LABEL (gsr->value_label), + _("")); + } + else + { + gnc_commodity *currency = gnc_price_get_currency (price); + gnc_commodity *default_currency = gnc_default_currency (); + gnc_numeric currency_amount; + gnc_numeric default_currency_amount; + + print_info = gnc_commodity_print_info (currency, TRUE); + + amount = xaccAccountGetBalance (leader); + if (reverse) + amount = gnc_numeric_neg (amount); + + currency_amount = gnc_ui_convert_balance_to_currency(amount, commodity, currency); + + xaccSPrintAmount (string, currency_amount, print_info); + + default_currency_amount = gnc_ui_convert_balance_to_currency(amount, commodity, + default_currency); + if(!gnc_numeric_zero_p(default_currency_amount)) + { + strcat( string, " / " ); + print_info = gnc_commodity_print_info (default_currency, TRUE); + xaccSPrintAmount( string + strlen( string ), default_currency_amount, + print_info); + } + + gnc_set_label_color (gsr->value_label, amount); + gtk_label_set_text (GTK_LABEL (gsr->value_label), string); + + gnc_price_unref (price); + } } else {