Merge branch 'big-prices'

This commit is contained in:
John Ralls 2015-10-29 15:37:18 -07:00
commit f82717496a
26 changed files with 2570 additions and 1205 deletions

View File

@ -1122,9 +1122,6 @@ create_each_transaction_helper(Transaction *template_txn, void *user_data)
price = gnc_pricedb_lookup_latest(price_db, first_cmdty, split_cmdty);
if (price == NULL)
{
price = gnc_pricedb_lookup_latest(price_db, split_cmdty, first_cmdty);
if (price == NULL)
{
GString *err = g_string_new("");
g_string_printf(err, "could not find pricedb entry for commodity-pair (%s, %s).",
gnc_commodity_get_mnemonic(first_cmdty),
@ -1135,7 +1132,9 @@ create_each_transaction_helper(Transaction *template_txn, void *user_data)
}
else
{
exchange = gnc_numeric_invert(gnc_price_get_value(price));
if (gnc_commodity_equiv(first_cmdty,
gnc_price_get_commodity(price)))
exchange = gnc_numeric_invert(gnc_price_get_value(price));
exchange = gnc_numeric_convert(exchange, 1000,
GNC_HOW_RND_ROUND_HALF_UP);
}

View File

@ -185,6 +185,8 @@ gnc_ui_account_get_balance_as_of_date (Account *account,
time64 date,
gboolean include_children)
{
QofBook *book = gnc_account_get_book (account);
GNCPriceDB *pdb = gnc_pricedb_get_db (book);
gnc_numeric balance;
gnc_commodity *currency;
@ -209,8 +211,10 @@ gnc_ui_account_get_balance_as_of_date (Account *account,
child = node->data;
child_currency = xaccAccountGetCommodity (child);
child_balance = xaccAccountGetBalanceAsOfDate (child, date);
child_balance = xaccAccountConvertBalanceToCurrency (child,
child_balance, child_currency, currency);
child_balance =
gnc_pricedb_convert_balance_latest_price (pdb, child_balance,
child_currency,
currency);
balance = gnc_numeric_add_fixed (balance, child_balance);
}
@ -316,4 +320,3 @@ gnc_ui_owner_get_print_report_balance (GncOwner *owner,
print_info = gnc_commodity_print_info (report_commodity, TRUE);
return g_strdup (xaccPrintAmount (balance, print_info));
}

View File

@ -203,7 +203,7 @@ write_price( GNCPrice* p, gpointer data )
g_return_val_if_fail( p != NULL, FALSE );
g_return_val_if_fail( data != NULL, FALSE );
if ( s->is_ok && gnc_price_get_source(p) != PRICE_SOURCE_INVOICE)
if ( s->is_ok && gnc_price_get_source(p) != PRICE_SOURCE_TEMP)
{
s->is_ok = save_price( s->be, QOF_INSTANCE(p) );
}

View File

@ -898,7 +898,7 @@ gnc_invoice_post(InvoiceWindow *iw, struct post_invoice_params *post_params)
gnc_price_set_commodity (convprice, account_currency);
gnc_price_set_currency (convprice, gncInvoiceGetCurrency (invoice));
gnc_price_set_time (convprice, postdate);
gnc_price_set_source (convprice, PRICE_SOURCE_INVOICE);
gnc_price_set_source (convprice, PRICE_SOURCE_TEMP);
gnc_price_set_typestr (convprice, PRICE_TYPE_LAST);
gnc_price_set_value (convprice, exch_rate);
gncInvoiceAddPrice(invoice, convprice);

View File

@ -382,7 +382,7 @@ KvpValue* qof_book_get_option (QofBook *book, GSList *key_path);
SET_ENUM("PRICE-SOURCE-XFER-DLG-VAL");
SET_ENUM("PRICE-SOURCE-SPLIT-REG");
SET_ENUM("PRICE-SOURCE-STOCK-SPLIT");
SET_ENUM("PRICE-SOURCE-INVOICE");
SET_ENUM("PRICE-SOURCE-TEMP");
SET_ENUM("PRICE-SOURCE-INVALID");
#undef SET_ENUM

View File

@ -81,6 +81,7 @@ typedef enum
typedef struct gnc_price_lookup_helper_s
{
GList **return_list;
gnc_commodity *key;
Timespec time;
} GNCPriceLookupHelper;

File diff suppressed because it is too large Load Diff

View File

@ -169,7 +169,8 @@ typedef enum
PRICE_SOURCE_SPLIT_REG, // "user:split-register"
PRICE_SOURCE_STOCK_SPLIT, // "user:stock-split"
PRICE_SOURCE_INVOICE, // "user:invoice-post"
PRICE_SOURCE_INVALID,
PRICE_SOURCE_TEMP, // "temporary"
PRICE_SOURCE_INVALID, // "invalid"
} PriceSource;
#define PRICE_TYPE_LAST "last"
@ -188,6 +189,17 @@ GNCPrice *gnc_price_create(QofBook *book);
content-wise duplicate of the given price, p. The returned clone
will have a reference count of 1. */
GNCPrice *gnc_price_clone(GNCPrice* p, QofBook *book);
/** Return a newly-allocated price that's the inverse of the given price, p.
*
* Inverse means that the commodity and currency are swapped and the value is
* the numeric inverse of the original's. The source is set to PRICE_SOURCE_TEMP
* to prevent it being saved in the pricedb.
* @param p The price to invert
* @return a new price, with a ref-count of 1. Don't forget to unref it!
*/
GNCPrice *gnc_price_invert(GNCPrice *p);
/** @} */
/* ------------------ */
@ -310,142 +322,281 @@ gboolean gnc_price_list_equal(PriceList *prices1, PriceList *prices2);
/** Data type */
typedef struct gnc_price_db_s GNCPriceDB;
/** return the pricedb associated with the book */
/*@ dependent @*/
/** @brief Return the pricedb associated with the book
* @param book The QofBook holding the pricedb
* @return The GNCPriceDB associated with the book.
*/
GNCPriceDB * gnc_pricedb_get_db(QofBook *book);
/** @brief Return the pricedb via the Book's collection.
* @param col The QofCollection holding the pricedb
* @return The GNCPriceDB in the QofCollection
*/
GNCPriceDB * gnc_collection_get_pricedb(QofCollection *col);
/** gnc_pricedb_destroy - destroy the given pricedb and unref all of
the prices it contains. This may not deallocate all of those
prices. Other code may still be holding references to them. */
/** @brief Destroy the given pricedb and unref all of the prices it contains.
*
* This may not deallocate all of those prices. Other code may still be holding
* references to them.
* @param db The pricedb to destroy.
*/
void gnc_pricedb_destroy(GNCPriceDB *db);
/** Used for editing the pricedb en-mass */
/** @brief Begin an edit. */
void gnc_pricedb_begin_edit (GNCPriceDB *);
/** @brief Commit an edit. */
void gnc_pricedb_commit_edit (GNCPriceDB *);
/** Indicate whether or not the database is in the middle of a bulk
* update. Setting this flag will disable checks for duplicate
* entries. */
/** @brief Set flag to indicate whether duplication checks should be performed.
*
* Normally used at load time to speed up loading the pricedb.
* @param db The pricedb
* @param bulk_update TRUE to disable duplication checks, FALSE to enable them.
*/
void gnc_pricedb_set_bulk_update(GNCPriceDB *db, gboolean bulk_update);
/** gnc_pricedb_add_price - add a price to the pricedb, you may drop
your reference to the price (i.e. call unref) after this
succeeds, whenever you're finished with the price. */
/** @brief Add a price to the pricedb.
*
* You may drop your reference to the price (i.e. call unref) after this
* succeeds, whenever you're finished with the price.
* @param db The pricedb
* @param p The GNCPrice to add.
* @return TRUE if the price was added, FALSE otherwise.
*/
gboolean gnc_pricedb_add_price(GNCPriceDB *db, GNCPrice *p);
/** gnc_pricedb_remove_price - removes the given price, p, from the
pricedb. Returns TRUE if successful, FALSE otherwise. */
/** @brief Remove a price from the pricedb and unref the price.
* @param db The Pricedb
* @param p The price to remove.
*/
gboolean gnc_pricedb_remove_price(GNCPriceDB *db, GNCPrice *p);
/** @brief Remove and unref prices older than a certain time.
* @param db The pricedb
* @param cutoff The time before which prices should be deleted.
* @param delete_user Whether user-created (i.e. not Finance::Quote) prices
* should be deleted.
* @param delete_last Whether a price should be deleted if it's the only
* remaining price for its commodity.
*/
gboolean gnc_pricedb_remove_old_prices(GNCPriceDB *db, Timespec cutoff,
const gboolean delete_user, gboolean delete_last);
const gboolean delete_user,
gboolean delete_last);
/** gnc_pricedb_lookup_latest - find the most recent price for the
given commodity in the given currency. Returns NULL on
failure. */
/** @brief Find the most recent price between the two commodities.
*
* The returned GNCPrice may be in either direction so check to ensure that its
* value is correctly applied.
* @param db The pricedb
* @param commodity The first commodity
* @param currency The second commodity
* @return A GNCPrice or NULL if no price exists.
*/
GNCPrice * gnc_pricedb_lookup_latest(GNCPriceDB *db,
const gnc_commodity *commodity,
const gnc_commodity *currency);
/** gnc_pricedb_lookup_latest_any_currency - find the most recent prices
for the given commodity in any available currency. Prices will be
returned as a GNCPrice list (see above). */
/** @brief Find the most recent price between a commodity and all other
* commodities
*
* The returned GNCPrices may be in either direction so check to ensure that
* their values are correctly applied.
* @param db The pricedb
* @param commodity The commodity for which to obtain prices
* @return A PriceList of prices found, or NULL if none found.
*/
PriceList * gnc_pricedb_lookup_latest_any_currency(GNCPriceDB *db,
const gnc_commodity *commodity);
/** gnc_pricedb_has_prices - return an indication of whether or not
there are any prices for a given commodity in the given currency.
Returns TRUE if there are prices, FALSE otherwise. */
/** @brief Report wether the pricedb contains prices for one commodity in
* another.
*
* Does *not* check the reverse direction.
* @param db The pricedb to check
* @param commodity The commodity to check for the existence of prices
* @param currency The commodity in which prices are sought. If NULL reports all
* commodities.
* @return TRUE if matching prices are found, FALSE otherwise.
*/
gboolean gnc_pricedb_has_prices(GNCPriceDB *db,
const gnc_commodity *commodity,
const gnc_commodity *currency);
/** 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). */
/** @brief Return all the prices for a given commodity in another.
*
* Does *not* retrieve reverse prices, i.e. prices of the second commodity in
* the first.
* @param db The pricedb from which to retrieve prices.
* @param commodity The commodity for which prices should be retrieved.
* @param currency The commodity in which prices should be quoted. If NULL, all
* prices in any commodity are included.
* @return A PriceList of matching prices or NULL if none were found.
*/
PriceList * gnc_pricedb_get_prices(GNCPriceDB *db,
const gnc_commodity *commodity,
const gnc_commodity *currency);
/** gnc_pricedb_lookup_at_time - return all prices that match the given
commodity, currency, and timespec. Prices will be returned as a
GNCPrice list (see above). */
PriceList * gnc_pricedb_lookup_at_time(GNCPriceDB *db,
/** @brief Find the price between two commodities at a timespec.
*
* The returned GNCPrice may be in either direction so check to ensure that its
* value is correctly applied.
* @param db The pricedb
* @param commodity The first commodity
* @param currency The second commodity
* @param t The timespec at which to retrieve the price.
* @return A GNCPrice or NULL if none matches.
*/
/* NOT USED */
GNCPrice * gnc_pricedb_lookup_at_time(GNCPriceDB *db,
const gnc_commodity *commodity,
const gnc_commodity *currency,
Timespec t);
/** gnc_pricedb_lookup_day - return the price that matchex the given
commodity, currency, and timespec which is on the same day.
If no prices are on that day, returns a null value. */
/** @brief Return the price between the two commodities on the indicated
* day. Note that the notion of day might be distorted by changes in timezone.
*
* The returned GNCPrice may be in either direction so check to ensure that its
* value is correctly applied.
* @param db The pricedb
* @param commodity The first commodity
* @param currency The second commodity
* @param t A time. The price returned will be in the same day as this time
* according to the local timezone.
* @return A GNCPrice or NULL on failure.
*/
GNCPrice * gnc_pricedb_lookup_day(GNCPriceDB *db,
const gnc_commodity *commodity,
const gnc_commodity *currency,
Timespec t);
/** gnc_pricedb_lookup_nearest_in_time - return the price for the given
commodity in the given currency nearest to the given time t. */
/** @brief Return the price between the two commoditiesz nearest to the given
* time.
*
* The returned GNCPrice may be in either direction so check to ensure that its
* value is correctly applied.
* @param db The pricedb
* @param c The first commodity
* @param currency The second commodity
* @param t The time nearest to which the returned price should be.
* @return A GNCPrice or NULL if no prices exist between the two commodities.
*/
GNCPrice * gnc_pricedb_lookup_nearest_in_time(GNCPriceDB *db,
const gnc_commodity *c,
const gnc_commodity *currency,
Timespec t);
/** gnc_pricedb_lookup_nearest_in_time_any_currency - return all prices that
match the given commodity and timespec in any available currency. Prices
will be returned as a GNCPrice list (see above). */
/** @brief Return the price nearest in time to that given between the given
* commodity and every other.
*
* The returned GNCPrices may be in either direction so check to ensure that
* their values are correctly applied.
*
* @param db, The pricedb
* @param c, The commodity for which prices should be obtained.
* @param t, The time nearest to which the prices should be obtained.
* @return A PriceList of prices for each commodity pair found or NULL if none
* are.
*/
PriceList * 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. */
/** @brief Return the latest price between the given commodities before the
* given time.
*
* The returned GNCPrice may be in either direction so check to ensure that its
* value is correctly applied.
* @param db The pricedb
* @param c The first commodity
* @param currency The second commodity
* @param t The time before which to find the price
* @return A GNCPrice or NULL if no prices are found before t.
*/
/* NOT USED, but see bug 743753 */
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). */
/** @brief Return the latest price between the given commodity and any other
* before the given time.
*
* The returned GNCPrice may be in either direction so check to ensure that its
* value is correctly applied.
* @param db The pricedb
* @param c The commodity
* @param t The time before which to find prices
* @return A PriceList of prices for each commodity found or NULL if none are.
*/
/* NOT USED, but see bug 743753 */
PriceList * gnc_pricedb_lookup_latest_before_any_currency(GNCPriceDB *db,
gnc_commodity *c,
Timespec t);
const gnc_commodity *c,
Timespec t);
/** gnc_pricedb_convert_balance_latest_price - Convert a balance
from one currency to another. */
/** @brief Convert a balance from one currency to another using the most recent
* price between the two.
* @param pdb The pricedb
* @param balance The balance to be converted
* @param balance_currency The commodity in which the balance is currently
* expressed
* @param new_currency The commodity to which the balance should be converted
* @return A new balance or gnc_numeric_zero if no price is available.
*/
gnc_numeric
gnc_pricedb_convert_balance_latest_price(GNCPriceDB *pdb,
gnc_numeric balance,
const gnc_commodity *balance_currency,
const gnc_commodity *new_currency);
gnc_numeric balance,
const gnc_commodity *balance_currency,
const gnc_commodity *new_currency);
/** gnc_pricedb_convert_balance_nearest_price - Convert a balance
from one currency to another. */
/** @brief Convert a balance from one currency to another using the price
* nearest to the given time.
* @param pdb The pricedb
* @param balance The balance to be converted
* @param balance_currency The commodity in which the balance is currently
* expressed
* @param new_currency The commodity to which the balance should be converted
* @param t The time nearest to which price should be used.
* @return A new balance or gnc_numeric_zero if no price is available.
*/
gnc_numeric
gnc_pricedb_convert_balance_nearest_price(GNCPriceDB *pdb,
gnc_numeric balance,
const gnc_commodity *balance_currency,
const gnc_commodity *new_currency,
Timespec t);
gnc_numeric balance,
const gnc_commodity *balance_currency,
const 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
every time given the same db contents -- stable traversals may be
less efficient). */
typedef gboolean (*GncPriceForeachFunc)(GNCPrice *p, gpointer user_data);
/** @brief Call a GncPriceForeachFunction once for each price in db, until the
* function returns FALSE.
*
* If stable_order is not FALSE, make sure the ordering of the traversal is
* stable (i.e. the same order every time given the same db contents -- stable
* traversals may be less efficient).
* @param db The pricedb
* @param f The function to call
* @param user_data A data to pass to each invocation of f
* @param stable_order Ensure that the traversal is performed in the same order
* each time.
* @return TRUE if all calls to f succeeded (unstable) or if the order of
* processing was the same as the previous invocation (stable), FALSE otherwise.
*/
gboolean gnc_pricedb_foreach_price(GNCPriceDB *db,
gboolean (*f)(GNCPrice *p,
gpointer user_data),
GncPriceForeachFunc f,
gpointer user_data,
gboolean stable_order);
/* The following two convenience functions are used to test the xml backend */
/** gnc_pricedb_get_num_prices - return the number of prices
in the database. */
/** @brief Return the number of prices in the database.
*
* For XML Backend Testing
*/
guint gnc_pricedb_get_num_prices(GNCPriceDB *db);
/** gnc_pricedb_equal - test equality of two pricedbs */
/** @brief Test equality of two pricedbs
*
* For XML Backend Testing */
gboolean gnc_pricedb_equal (GNCPriceDB *db1, GNCPriceDB *db2);
/** @name Internal/Debugging

View File

@ -114,6 +114,7 @@ test_engine_SOURCES = \
utest-Entry.c \
utest-Invoice.c \
test-engine-kvp-properties.c \
utest-gnc-pricedb.c \
dummy.cpp
test_engine_LDADD = \

View File

@ -129,7 +129,7 @@ teardown (Fixture *fixture, gconstpointer pData)
*/
QofBook *book = qof_instance_get_book (QOF_INSTANCE (fixture->acct));
test_destroy (fixture->acct);
test_destroy (book);
qof_book_destroy (book);
}
static void

View File

@ -33,6 +33,7 @@ extern void test_suite_gncInvoice();
extern void test_suite_transaction();
extern void test_suite_split();
extern void test_suite_engine_kvp_properties (void);
extern void test_suite_gnc_pricedb();
int
main (int argc,
@ -53,6 +54,7 @@ main (int argc,
test_suite_transaction();
test_suite_split();
test_suite_engine_kvp_properties ();
test_suite_gnc_pricedb();
return g_test_run( );
}

File diff suppressed because it is too large Load Diff

View File

@ -263,34 +263,18 @@ lookup_price(PriceReq *pr, PriceDate pd)
case SAME_DAY:
prc = gnc_pricedb_lookup_day (pr->pricedb, pr->from,
pr->to, pr->ts);
if (!prc)
{
prc = gnc_pricedb_lookup_day (pr->pricedb, pr->to,
pr->from, pr->ts);
pr->reverse = TRUE;
}
break;
break;
case NEAREST:
prc = gnc_pricedb_lookup_nearest_in_time (pr->pricedb, pr->from,
pr->to, pr->ts);
if (!prc)
{
prc = gnc_pricedb_lookup_nearest_in_time (pr->pricedb, pr->to,
pr->from, pr->ts);
pr->reverse = TRUE;
}
break;
break;
case LATEST:
prc = gnc_pricedb_lookup_latest (pr->pricedb, pr->from, pr->to);
if (!prc)
{
prc = gnc_pricedb_lookup_latest (pr->pricedb, pr->to, pr->from);
pr->reverse = TRUE;
}
break;
}
if (pr->reverse)
if (gnc_commodity_equiv(gnc_price_get_currency(prc), pr->from))
{
pr->reverse = TRUE;
PINFO("Found reverse price: 1 %s = %f %s",
gnc_commodity_get_mnemonic(pr->to),
gnc_numeric_to_double(gnc_price_get_value(prc)),
@ -1567,20 +1551,6 @@ create_transaction(XferDialog *xferData, Timespec *ts,
xferData->transaction_cb(trans, xferData->transaction_user_data);
}
static void
swap_amount (gnc_commodity **from, gnc_commodity **to, gnc_numeric *value,
gnc_numeric *from_amt, gnc_numeric *to_amt)
{
gnc_commodity *tmp = *from;
gnc_numeric *tmp_amt = from_amt;
*from = *to;
*to = tmp;
from_amt = to_amt;
to_amt = tmp_amt;
*value = gnc_numeric_invert (*value);
*value = round_price(*from, *to, *value);
}
static gnc_numeric
swap_commodities(gnc_commodity **from, gnc_commodity **to, gnc_numeric value)
{
@ -1609,12 +1579,6 @@ create_price(XferDialog *xferData, Timespec ts)
return;
value = gnc_amount_edit_get_amount(GNC_AMOUNT_EDIT(xferData->price_edit));
/* Try to be consistent about how quotes are installed. */
if (from == gnc_default_currency() ||
((to != gnc_default_currency()) &&
(strcmp (gnc_commodity_get_mnemonic(from),
gnc_commodity_get_mnemonic(to)) < 0)))
swap_amount (&from, &to, &value, &from_amt, &to_amt);
/* Normally we want to store currency rates such that the rate > 1 and commodity
* prices in terms of a currency regardless of value. However, if we already

View File

@ -90,38 +90,16 @@ static gnc_numeric
gtu_sr_get_rate_from_db (gnc_commodity *from, gnc_commodity *to)
{
GNCPrice *prc;
gnc_numeric rate_split;
gboolean have_rate = FALSE;
QofBook *book = gnc_get_current_book ();
/* Do we have a rate allready */
prc = gnc_pricedb_lookup_latest (gnc_pricedb_get_db (book), from, to);
if (prc)
{
rate_split = gnc_price_get_value (prc);
gnc_price_unref (prc);
have_rate = TRUE;
}
/* Lets try reversing the commodities */
if (!have_rate)
{
prc = gnc_pricedb_lookup_latest (gnc_pricedb_get_db (book), to, from);
if (prc)
{
rate_split = gnc_numeric_div (gnc_numeric_create (100, 100), gnc_price_get_value (prc),
GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
if (!prc)
return gnc_numeric_create (100, 100);
gnc_price_unref (prc);
have_rate = TRUE;
}
}
/* No rate, set to 1/1 */
if (!have_rate)
rate_split = gnc_numeric_create (100, 100);
return rate_split;
if (gnc_commodity_equiv(from, gnc_price_get_currency(prc)))
return gnc_numeric_invert(gnc_price_get_value(prc));
return gnc_price_get_value(prc);
}

View File

@ -148,20 +148,23 @@ gnc_ui_accounts_recurse (Account *parent, GList **currency_list,
for (node = children; node; node = g_list_next(node))
{
Account *account = node->data;
QofBook *book = gnc_account_get_book (account);
GNCPriceDB *pricedb = gnc_pricedb_get_db (book);
gnc_commodity *to_curr = options.default_currency;
account_type = xaccAccountGetType(account);
account_currency = xaccAccountGetCommodity(account);
if (options.grand_total)
grand_total_accum = gnc_ui_get_currency_accumulator(currency_list,
options.default_currency,
to_curr,
TOTAL_GRAND_TOTAL);
if (!gnc_commodity_is_currency(account_currency))
{
non_currency = TRUE;
non_curr_accum = gnc_ui_get_currency_accumulator(currency_list,
options.default_currency,
to_curr,
TOTAL_NON_CURR_TOTAL);
}
@ -186,9 +189,10 @@ gnc_ui_accounts_recurse (Account *parent, GList **currency_list,
end_amount = xaccAccountGetBalanceAsOfDate(account, options.end_date);
timespecFromTime64(&end_timespec, options.end_date);
end_amount_default_currency =
xaccAccountConvertBalanceToCurrencyAsOfDate
(account, end_amount, account_currency, options.default_currency,
timespecToTime64(timespecCanonicalDayTime(end_timespec)));
gnc_pricedb_convert_balance_nearest_price (pricedb, end_amount,
account_currency,
to_curr,
end_timespec);
if (!non_currency || options.non_currency)
{
@ -202,7 +206,7 @@ gnc_ui_accounts_recurse (Account *parent, GList **currency_list,
{
non_curr_accum->assets =
gnc_numeric_add (non_curr_accum->assets, end_amount_default_currency,
gnc_commodity_get_fraction (options.default_currency),
gnc_commodity_get_fraction (to_curr),
GNC_HOW_RND_ROUND_HALF_UP);
}
@ -210,7 +214,7 @@ gnc_ui_accounts_recurse (Account *parent, GList **currency_list,
{
grand_total_accum->assets =
gnc_numeric_add (grand_total_accum->assets, end_amount_default_currency,
gnc_commodity_get_fraction (options.default_currency),
gnc_commodity_get_fraction (to_curr),
GNC_HOW_RND_ROUND_HALF_UP);
}
@ -221,15 +225,18 @@ gnc_ui_accounts_recurse (Account *parent, GList **currency_list,
start_amount = xaccAccountGetBalanceAsOfDate(account, options.start_date);
timespecFromTime64(&start_timespec, options.start_date);
start_amount_default_currency =
xaccAccountConvertBalanceToCurrencyAsOfDate
(account, start_amount, account_currency, options.default_currency,
timespecToTime64(timespecCanonicalDayTime(start_timespec)));
gnc_pricedb_convert_balance_nearest_price (pricedb,
start_amount,
account_currency,
to_curr,
start_timespec);
end_amount = xaccAccountGetBalanceAsOfDate(account, options.end_date);
timespecFromTime64(&end_timespec, options.end_date);
end_amount_default_currency =
xaccAccountConvertBalanceToCurrencyAsOfDate
(account, end_amount, account_currency, options.default_currency,
timespecToTime64(timespecCanonicalDayTime(end_timespec)));
gnc_pricedb_convert_balance_nearest_price (pricedb, end_amount,
account_currency,
to_curr,
end_timespec);
if (!non_currency || options.non_currency)
{
@ -247,11 +254,11 @@ gnc_ui_accounts_recurse (Account *parent, GList **currency_list,
{
non_curr_accum->profits =
gnc_numeric_add (non_curr_accum->profits, start_amount_default_currency,
gnc_commodity_get_fraction (options.default_currency),
gnc_commodity_get_fraction (to_curr),
GNC_HOW_RND_ROUND_HALF_UP);
non_curr_accum->profits =
gnc_numeric_sub (non_curr_accum->profits, end_amount_default_currency,
gnc_commodity_get_fraction (options.default_currency),
gnc_commodity_get_fraction (to_curr),
GNC_HOW_RND_ROUND_HALF_UP);
}
@ -260,12 +267,12 @@ gnc_ui_accounts_recurse (Account *parent, GList **currency_list,
grand_total_accum->profits =
gnc_numeric_add (grand_total_accum->profits,
start_amount_default_currency,
gnc_commodity_get_fraction (options.default_currency),
gnc_commodity_get_fraction (to_curr),
GNC_HOW_RND_ROUND_HALF_UP);
grand_total_accum->profits =
gnc_numeric_sub (grand_total_accum->profits,
end_amount_default_currency,
gnc_commodity_get_fraction (options.default_currency),
gnc_commodity_get_fraction (to_curr),
GNC_HOW_RND_ROUND_HALF_UP);
}
@ -568,4 +575,3 @@ gnc_main_window_summary_new (void)
return retval->hbox;
}

View File

@ -231,7 +231,10 @@ refresh_details_page (StockSplitInfo *info)
if (prices)
{
/* Use the first existing price */
currency = gnc_price_get_currency(prices->data);
if (gnc_commodity_equiv (commodity, gnc_price_get_currency(prices->data)))
currency = gnc_price_get_commodity(prices->data);
else
currency = gnc_price_get_currency(prices->data);
}
else
{

View File

@ -347,7 +347,11 @@ pedit_commodity_changed_cb (GtkComboBox *cbwe, gpointer data)
(pedit_dialog->price_db, commodity);
if (price_list)
{
currency = gnc_price_get_currency((GNCPrice *)price_list->data);
GNCPrice * price = (GNCPrice*)price_list->data;
if (gnc_commodity_equiv(commodity, gnc_price_get_currency(price)))
currency = gnc_price_get_commodity((GNCPrice *)price);
else
currency = gnc_price_get_currency((GNCPrice *)price);
if (currency)
gnc_currency_edit_set_currency

View File

@ -495,49 +495,6 @@ gsr_update_summary_label( GtkWidget *label,
gtk_label_set_text( GTK_LABEL(label), string );
}
static GNCPrice *
account_latest_price (Account *account)
{
QofBook *book;
GNCPriceDB *pdb;
gnc_commodity *commodity;
gnc_commodity *currency;
if (!account) return NULL;
commodity = xaccAccountGetCommodity (account);
currency = gnc_default_currency ();
book = gnc_account_get_book (account);
pdb = gnc_pricedb_get_db (book);
return gnc_pricedb_lookup_latest (pdb, commodity, currency);
}
static GNCPrice *
account_latest_price_any_currency (Account *account)
{
QofBook *book;
GNCPriceDB *pdb;
gnc_commodity *commodity;
GList *price_list;
GNCPrice *result;
if (!account) return NULL;
commodity = xaccAccountGetCommodity (account);
book = gnc_account_get_book (account);
pdb = gnc_pricedb_get_db (book);
price_list = gnc_pricedb_lookup_latest_any_currency (pdb, commodity);
if (!price_list) return NULL;
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)
@ -546,7 +503,6 @@ gsr_redraw_all_cb (GnucashRegister *g_reg, gpointer data)
gnc_commodity * commodity;
GNCPrintAmountInfo print_info;
gnc_numeric amount;
char string[256];
Account *leader;
gboolean reverse;
gboolean euro;
@ -583,18 +539,18 @@ gsr_redraw_all_cb (GnucashRegister *g_reg, gpointer data)
gsr_update_summary_label( gsr->projectedminimum_label,
xaccAccountGetProjectedMinimumBalance,
leader, print_info, commodity, reverse, euro );
if (gsr->shares_label == NULL && gsr->value_label == NULL)
return;
amount = xaccAccountGetBalance( leader );
if (reverse)
amount = gnc_numeric_neg( amount );
/* Print the summary share amount */
/* Print the summary share amount */
if (gsr->shares_label != NULL)
{
char string[256];
print_info = gnc_account_print_info( leader, TRUE );
amount = xaccAccountGetBalance( leader );
if (reverse)
amount = gnc_numeric_neg( amount );
xaccSPrintAmount( string, amount, print_info );
gnc_set_label_color( gsr->shares_label, amount );
gtk_label_set_text( GTK_LABEL(gsr->shares_label), string );
}
@ -602,86 +558,18 @@ gsr_redraw_all_cb (GnucashRegister *g_reg, gpointer data)
/* Print the summary share value */
if (gsr->value_label != NULL)
{
GNCPrice *price;
char string[256];
QofBook *book = gnc_account_get_book (leader);
GNCPriceDB *pricedb = gnc_pricedb_get_db (book);
gnc_commodity *currency = gnc_default_currency ();
gnc_numeric currency_value =
gnc_pricedb_convert_balance_latest_price(pricedb, amount,
commodity, currency);
print_info = gnc_commodity_print_info (currency, TRUE);
xaccSPrintAmount (string, amount, print_info);
gnc_set_label_color (gsr->value_label, amount);
gtk_label_set_text (GTK_LABEL (gsr->value_label), string);
amount = xaccAccountGetBalance (leader);
if (reverse) amount = gnc_numeric_neg (amount);
price = account_latest_price (leader);
if (!price)
{
/* If the balance is zero, then print zero. */
if (gnc_numeric_equal(amount, gnc_numeric_zero()))
{
gnc_commodity *currency = gnc_default_currency ();
print_info = gnc_commodity_print_info (currency, TRUE);
amount = gnc_numeric_zero ();
xaccSPrintAmount (string, amount, print_info);
gnc_set_label_color (gsr->value_label, amount);
gtk_label_set_text (GTK_LABEL (gsr->value_label), string);
}
else
{
/* else try to do a double-price-conversion :-( */
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),
_("<No information>"));
}
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);
currency_amount =
xaccAccountConvertBalanceToCurrency(leader, amount,
commodity, currency);
xaccSPrintAmount (string, currency_amount, print_info);
default_currency_amount =
xaccAccountConvertBalanceToCurrency(leader, 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
{
gnc_commodity *currency = gnc_price_get_currency (price);
print_info = gnc_commodity_print_info (currency, TRUE);
amount = gnc_numeric_mul (amount, gnc_price_get_value (price),
gnc_commodity_get_fraction (currency),
GNC_HOW_RND_ROUND_HALF_UP);
xaccSPrintAmount (string, 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);
}
}
}

View File

@ -495,49 +495,6 @@ gsr2_update_summary_label (GtkWidget *label,
gtk_label_set_text( GTK_LABEL(label), string );
}
static GNCPrice *
account_latest_price (Account *account)
{
QofBook *book;
GNCPriceDB *pdb;
gnc_commodity *commodity;
gnc_commodity *currency;
if (!account) return NULL;
commodity = xaccAccountGetCommodity (account);
currency = gnc_default_currency ();
book = gnc_account_get_book (account);
pdb = gnc_pricedb_get_db (book);
return gnc_pricedb_lookup_latest (pdb, commodity, currency);
}
static GNCPrice *
account_latest_price_any_currency (Account *account)
{
QofBook *book;
GNCPriceDB *pdb;
gnc_commodity *commodity;
GList *price_list;
GNCPrice *result;
if (!account) return NULL;
commodity = xaccAccountGetCommodity (account);
book = gnc_account_get_book (account);
pdb = gnc_pricedb_get_db (book);
price_list = gnc_pricedb_lookup_latest_any_currency (pdb, commodity);
if (!price_list) return NULL;
result = gnc_price_clone ((GNCPrice *)(price_list->data), book);
gnc_price_list_destroy (price_list);
return result;
}
static
void
gsr2_redraw_all_cb (GncTreeViewSplitReg *view, gpointer user_data)
@ -546,7 +503,6 @@ gsr2_redraw_all_cb (GncTreeViewSplitReg *view, gpointer user_data)
gnc_commodity * commodity;
GNCPrintAmountInfo print_info;
gnc_numeric amount;
char string[256];
Account *leader;
gboolean reverse;
gboolean euro;
@ -584,17 +540,12 @@ gsr2_redraw_all_cb (GncTreeViewSplitReg *view, gpointer user_data)
xaccAccountGetProjectedMinimumBalance,
leader, print_info, commodity, reverse, euro );
/* Print the summary share amount */
/* Print the summary share amount */
if (gsr->shares_label != NULL)
{
char string[256];
print_info = gnc_account_print_info( leader, TRUE );
amount = xaccAccountGetBalance( leader );
if (reverse)
amount = gnc_numeric_neg( amount );
xaccSPrintAmount( string, amount, print_info );
gnc_set_label_color( gsr->shares_label, amount );
gtk_label_set_text( GTK_LABEL(gsr->shares_label), string );
}
@ -602,89 +553,23 @@ gsr2_redraw_all_cb (GncTreeViewSplitReg *view, gpointer user_data)
/* Print the summary share value */
if (gsr->value_label != NULL)
{
GNCPrice *price;
char string[256];
QofBook *book = gnc_account_get_book (leader);
GNCPriceDB *pricedb = gnc_pricedb_get_db (book);
gnc_commodity *commodity = xaccAccountGetCommodity (leader);
gnc_commodity *currency = gnc_default_currency ();
gnc_numeric currency_value =
gnc_pricedb_convert_balance_latest_price(pricedb, amount,
commodity, currency);
print_info = gnc_commodity_print_info (currency, TRUE);
xaccSPrintAmount (string, amount, print_info);
gnc_set_label_color (gsr->value_label, amount);
gtk_label_set_text (GTK_LABEL (gsr->value_label), string);
amount = xaccAccountGetBalance (leader);
if (reverse) amount = gnc_numeric_neg (amount);
price = account_latest_price (leader);
if (!price)
{
/* If the balance is zero, then print zero. */
if (gnc_numeric_equal(amount, gnc_numeric_zero()))
{
gnc_commodity *currency = gnc_default_currency ();
print_info = gnc_commodity_print_info (currency, TRUE);
amount = gnc_numeric_zero ();
xaccSPrintAmount (string, amount, print_info);
gnc_set_label_color (gsr->value_label, amount);
gtk_label_set_text (GTK_LABEL (gsr->value_label), string);
}
else
{
/* else try to do a double-price-conversion :-( */
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),
_("<No information>"));
}
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);
currency_amount =
xaccAccountConvertBalanceToCurrency(leader, amount,
commodity, currency);
xaccSPrintAmount (string, currency_amount, print_info);
default_currency_amount =
xaccAccountConvertBalanceToCurrency(leader, 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
{
gnc_commodity *currency = gnc_price_get_currency (price);
print_info = gnc_commodity_print_info (currency, TRUE);
amount = gnc_numeric_mul (amount, gnc_price_get_value (price),
gnc_commodity_get_fraction (currency),
GNC_HOW_RND_ROUND_HALF_UP);
xaccSPrintAmount (string, 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);
}
}
}
static void
gnc_split_reg2_ld_destroy (GNCLedgerDisplay2 *ledger)
{

View File

@ -166,6 +166,15 @@ if ($exchange eq "currency") {
while ($#ARGV >= 0) {
my $to = shift;
my $result = $q->currency($from, $to);
unless (defined($result) && $result >= 1) {
my $inv_res = $q->currency($to, $from);
if (defined($inv_res)) {
my $tmp = $to;
$to = $from;
$from = $tmp;
$result = $inv_res;
}
}
if (defined($result)) {
printf "1 $from = $result $to\n";
} else {

View File

@ -350,6 +350,19 @@ while(<>) {
last unless $to_currency;
my $price = $quoter->currency($from_currency, $to_currency);
my $inv_price = undef;
#Sometimes price quotes are available in only one direction, and if the
#direction we asked for results in a quote < 1 we want the other direction
#if it's available to get more significant digits.
unless (defined($price) && $price > 1) {
$inv_price = $quoter->currency($to_currency, $from_currency);
if (defined($inv_price)) {
my $tmp = $to_currency;
$to_currency = $from_currency;
$from_currency = $tmp;
$price = $inv_price;
}
}
$quote_data{$from_currency, "success"} = defined($price);
$quote_data{$from_currency, "symbol"} = $from_currency;

View File

@ -2067,15 +2067,9 @@ record_price (SplitRegister *reg, Account *account, gnc_numeric value,
return;
gnc_date_cell_get_date ((DateCell*)cell, &ts);
price = gnc_pricedb_lookup_day (pricedb, comm, curr, ts);
if (!price)
{
price = gnc_pricedb_lookup_day (pricedb, curr, comm, ts);
if (price)
/* It might be better to raise an error here: We shouldn't be creating
* currency->commodity prices.
*/
if (gnc_commodity_equiv (comm, gnc_price_get_currency (price)))
swap = TRUE;
}
if (price)
{
price_value = gnc_price_get_value(price);

View File

@ -724,12 +724,15 @@
(begin ;; do so
(set! missing-pricedb-entry? #f)
(set! pricedb-lookup-price
(gnc-pricedb-lookup-nearest-in-time
(let ((price (gnc-pricedb-lookup-nearest-in-time
pricedb
account-commodity
USD-currency
(timespecCanonicalDayTime
lookup-date)))
lookup-date))))
(if (gnc-commodity-equiv account-commodity (gnc-price-get-currency price))
(set! price (gnc-price-invert price)))
price))
(set! pricedb-lookup-price-value
(gnc-price-get-value
pricedb-lookup-price))

View File

@ -359,7 +359,9 @@
(for-each
(lambda (p)
(if (gnc-commodity-equiv currency (gnc-price-get-currency p))
(set! price p)))
(set! price p))
(if (gnc-commodity-equiv currency (gnc-price-get-commodity p))
(set! price (gnc-price-invert p))))
price-list)
(gnc-price-ref price)
(gnc-price-list-destroy price-list)
@ -1047,7 +1049,7 @@
(sum-total-gain (gnc-numeric-zero))
(sum-total-ugain (gnc-numeric-zero))
(sum-total-brokerage (gnc-numeric-zero))
(sum-total-totalreturn (gnc-numeric-zero)))
(sum-total-totalreturn (gnc-numeric-zero))) ;;end of let
;;begin building lists for which columns to display
(if show-symbol

View File

@ -219,7 +219,13 @@
(gnc-pricedb-lookup-latest-any-currency
pricedb foreign))
(fn (if (and price (> (length price) 0))
(let ((v (gnc-price-get-value (car price))))
(let* ((the_price
(if (gnc-commodity-equiv
foreign
(gnc-price-get-commodity (car price)))
(car price)
(gnc-price-invert (car price))))
(v (gnc-price-get-value the_price)))
(gnc-price-ref (car price))
(cons (car price) v))
(cons #f (gnc-numeric-zero)))))
@ -231,7 +237,13 @@
(gnc-pricedb-lookup-nearest-in-time-any-currency
pricedb foreign (timespecCanonicalDayTime date)))
(fn (if (and price (> (length price) 0))
(let ((v (gnc-price-get-value (car price))))
(let* ((the_price
(if (gnc-commodity-equiv
foreign
(gnc-price-get-commodity (car price)))
(car price)
(gnc-price-invert (car price))))
(v (gnc-price-get-value (car price))))
(gnc-price-ref (car price))
(cons (car price) v))
(cons #f (gnc-numeric-zero)))))

View File

@ -375,7 +375,15 @@
(saved-price #f)
(commodity-str (gnc-commodity-get-printname commodity))
)
(if (equal? (gnc-commodity-get-printname currency) commodity-str)
(let* ((symbol (assq-ref quote-data 'symbol))
(other-curr
(and commodity-table
(string? symbol)
(gnc-commodity-table-lookup commodity-table "ISO4217"
(string-upcase symbol)))))
(set! commodity other-curr))
)
(or-map (lambda (price-sym)
(let ((p (assq-ref quote-data price-sym)))
(if p
@ -412,31 +420,36 @@
commodity currency
gnc-time))
(if (not (null? saved-price))
(if (> (gnc-price-get-source saved-price) PRICE-SOURCE-FQ)
(begin
(gnc-price-begin-edit saved-price)
(gnc-price-set-time saved-price gnc-time)
(gnc-price-set-source saved-price PRICE-SOURCE-FQ)
(gnc-price-set-typestr saved-price price-type)
(gnc-price-set-value saved-price price)
(gnc-price-commit-edit saved-price)
(begin
(if (gnc-commodity-equiv (gnc-price-get-currency saved-price)
commodity)
(set! price (gnc-numeric-invert price)))
(if (> (gnc-price-get-source saved-price) PRICE-SOURCE-FQ)
(begin
(gnc-price-begin-edit saved-price)
(gnc-price-set-time saved-price gnc-time)
(gnc-price-set-source saved-price PRICE-SOURCE-FQ)
(gnc-price-set-typestr saved-price price-type)
(gnc-price-set-value saved-price price)
(gnc-price-commit-edit saved-price)
#f)
#f)
#f)
(let ((gnc-price (gnc-price-create book)))
(if (not gnc-price)
(string-append
currency-str ":" (gnc-commodity-get-mnemonic commodity))
(begin
(gnc-price-begin-edit gnc-price)
(gnc-price-set-commodity gnc-price commodity)
(gnc-price-set-currency gnc-price currency)
(gnc-price-set-time gnc-price gnc-time)
(gnc-price-set-source gnc-price PRICE-SOURCE-FQ)
(gnc-price-set-typestr gnc-price price-type)
(gnc-price-set-value gnc-price price)
(gnc-price-commit-edit gnc-price)
gnc-price)))))
)))
(let ((gnc-price (gnc-price-create book)))
(if (not gnc-price)
(string-append
currency-str ":" (gnc-commodity-get-mnemonic commodity))
(begin
(gnc-price-begin-edit gnc-price)
(gnc-price-set-commodity gnc-price commodity)
(gnc-price-set-currency gnc-price currency)
(gnc-price-set-time gnc-price gnc-time)
(gnc-price-set-source gnc-price PRICE-SOURCE-FQ)
(gnc-price-set-typestr gnc-price price-type)
(gnc-price-set-value gnc-price price)
(gnc-price-commit-edit gnc-price)
gnc-price)))))
))
))
(define (book-add-prices! book prices)
(let ((pricedb (gnc-pricedb-get-db book)))