|
|
|
|
@ -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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|