Add retrieval functions for price before the date given

Add a new function, gnc_pricedb_convert_balance_nearest_before_price_t64
that retrieves the balance using the last price dated before a
specified date like today for the preset value. This uses another new
function gnc_pricedb_get_nearest_before_price to do the retrieval.
This commit is contained in:
Robert Fewell
2021-04-21 14:32:40 +01:00
parent b54c30e03d
commit 05507008c5
3 changed files with 89 additions and 13 deletions

View File

@@ -3623,7 +3623,7 @@ xaccAccountConvertBalanceToCurrencyAsOfDate(const Account *acc, /* for book */
book = gnc_account_get_book (acc);
pdb = gnc_pricedb_get_db (book);
balance = gnc_pricedb_convert_balance_nearest_price_t64(
balance = gnc_pricedb_convert_balance_nearest_before_price_t64 (
pdb, balance, balance_currency, new_currency, date);
return balance;

View File

@@ -2516,7 +2516,7 @@ convert_price (const gnc_commodity *from, const gnc_commodity *to, PriceTuple tu
static gnc_numeric
indirect_price_conversion (GNCPriceDB *db, const gnc_commodity *from,
const gnc_commodity *to, time64 t)
const gnc_commodity *to, time64 t, gboolean before_date)
{
GList *from_prices = NULL, *to_prices = NULL;
PriceTuple tuple;
@@ -2531,6 +2531,12 @@ indirect_price_conversion (GNCPriceDB *db, const gnc_commodity *from,
if (from_prices)
to_prices = gnc_pricedb_lookup_latest_any_currency(db, to);
}
else if (before_date)
{
from_prices = gnc_pricedb_lookup_latest_before_any_currency_t64 (db, from, t);
if (from_prices)
to_prices = gnc_pricedb_lookup_latest_before_any_currency_t64 (db, to, t);
}
else
{
from_prices = gnc_pricedb_lookup_nearest_in_time_any_currency_t64 (db, from, t);
@@ -2550,7 +2556,7 @@ indirect_price_conversion (GNCPriceDB *db, const gnc_commodity *from,
static gnc_numeric
direct_price_conversion (GNCPriceDB *db, const gnc_commodity *from,
const gnc_commodity *to, time64 t)
const gnc_commodity *to, time64 t, gboolean before_date)
{
GNCPrice *price;
gnc_numeric retval = gnc_numeric_zero();
@@ -2559,6 +2565,8 @@ direct_price_conversion (GNCPriceDB *db, const gnc_commodity *from,
if (t == INT64_MAX)
price = gnc_pricedb_lookup_latest(db, from, to);
else if (before_date)
price = gnc_pricedb_lookup_latest_before_t64(db, (gnc_commodity*)from, (gnc_commodity*)to, t);
else
price = gnc_pricedb_lookup_nearest_in_time64(db, from, to, t);
@@ -2573,6 +2581,29 @@ direct_price_conversion (GNCPriceDB *db, const gnc_commodity *from,
return retval;
}
gnc_numeric
gnc_pricedb_get_nearest_before_price (GNCPriceDB *pdb,
const gnc_commodity *orig_currency,
const gnc_commodity *new_currency,
const time64 t)
{
gnc_numeric price;
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, TRUE);
/*
* 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, TRUE);
return gnc_numeric_reduce (price);
}
gnc_numeric
gnc_pricedb_get_nearest_price (GNCPriceDB *pdb,
const gnc_commodity *orig_currency,
@@ -2585,13 +2616,13 @@ gnc_pricedb_get_nearest_price (GNCPriceDB *pdb,
return gnc_numeric_create (1, 1);
/* Look for a direct price. */
price = direct_price_conversion (pdb, orig_currency, new_currency, t);
price = direct_price_conversion (pdb, orig_currency, new_currency, t, FALSE);
/*
* 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);
price = indirect_price_conversion (pdb, orig_currency, new_currency, t, FALSE);
return gnc_numeric_reduce (price);
}
@@ -2604,18 +2635,23 @@ gnc_pricedb_get_latest_price (GNCPriceDB *pdb,
return gnc_pricedb_get_nearest_price (pdb, orig_currency, new_currency, INT64_MAX);
}
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)
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,
gboolean before_date)
{
gnc_numeric price;
if (gnc_numeric_zero_p (amount))
return amount;
price = gnc_pricedb_get_nearest_price (pdb, orig_currency, new_currency, t);
if (before_date)
price = gnc_pricedb_get_nearest_before_price (pdb, orig_currency, new_currency, t);
else
price = gnc_pricedb_get_nearest_price (pdb, orig_currency, new_currency, t);
/* the price retrieved may be invalid. return zero. see 798015 */
if (gnc_numeric_check (price))
@@ -2636,7 +2672,7 @@ gnc_pricedb_convert_balance_latest_price (GNCPriceDB *pdb,
const gnc_commodity *new_currency)
{
return convert_amount_at_date
(pdb, balance, balance_currency, new_currency, INT64_MAX);
(pdb, balance, balance_currency, new_currency, INT64_MAX, FALSE);
}
gnc_numeric
@@ -2647,9 +2683,19 @@ gnc_pricedb_convert_balance_nearest_price_t64(GNCPriceDB *pdb,
time64 t)
{
return convert_amount_at_date
(pdb, balance, balance_currency, new_currency, t);
(pdb, balance, balance_currency, new_currency, t, FALSE);
}
gnc_numeric
gnc_pricedb_convert_balance_nearest_before_price_t64 (GNCPriceDB *pdb,
gnc_numeric balance,
const gnc_commodity *balance_currency,
const gnc_commodity *new_currency,
time64 t)
{
return convert_amount_at_date
(pdb, balance, balance_currency, new_currency, t, TRUE);
}
/* ==================================================================== */
/* gnc_pricedb_foreach_price infrastructure

View File

@@ -559,6 +559,19 @@ PriceList * gnc_pricedb_lookup_latest_before_any_currency_t64(GNCPriceDB *db,
const gnc_commodity *c,
time64 t);
/** @brief Retrieve the price one currency to another using the price
* nearest to before the given time.
* @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
* @param t The time to be used for for comparison
* @return A price, or gnc_numeric_zero if no price is available.
*/
gnc_numeric gnc_pricedb_get_nearest_before_price (GNCPriceDB *pdb,
const gnc_commodity *orig_currency,
const gnc_commodity *new_currency,
const time64 t);
/** @brief Retrieve the price one currency to another at specified date
* @param pdb The pricedb
@@ -610,6 +623,23 @@ gnc_pricedb_convert_balance_nearest_price_t64(GNCPriceDB *pdb,
const gnc_commodity *new_currency,
time64 t);
/** @brief Convert a balance from one currency to another using the price
* nearest to before 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 in which the last price before it should be used.
* @return A new balance or gnc_numeric_zero if no price is available.
*/
gnc_numeric
gnc_pricedb_convert_balance_nearest_before_price_t64 (GNCPriceDB *pdb,
gnc_numeric balance,
const gnc_commodity *balance_currency,
const gnc_commodity *new_currency,
time64 t);
typedef gboolean (*GncPriceForeachFunc)(GNCPrice *p, gpointer user_data);
/** @brief Call a GncPriceForeachFunction once for each price in db, until the