|
|
|
|
@ -530,50 +530,6 @@ get_trading_split (Transaction *trans, Account *base,
|
|
|
|
|
return balance_split;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Find the trading split for a commodity, but don't create any splits
|
|
|
|
|
or accounts if they don't already exist. */
|
|
|
|
|
static Split *
|
|
|
|
|
find_trading_split (Transaction *trans, Account *root,
|
|
|
|
|
gnc_commodity *commodity)
|
|
|
|
|
{
|
|
|
|
|
Account *trading_account;
|
|
|
|
|
Account *ns_account;
|
|
|
|
|
Account *account;
|
|
|
|
|
|
|
|
|
|
if (!root)
|
|
|
|
|
{
|
|
|
|
|
root = gnc_book_get_root_account (xaccTransGetBook (trans));
|
|
|
|
|
if (NULL == root)
|
|
|
|
|
{
|
|
|
|
|
/* This can't occur, things should be in books */
|
|
|
|
|
PERR ("Bad data corruption, no root account in book");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
trading_account = gnc_account_lookup_by_name (root, _("Trading"));
|
|
|
|
|
if (!trading_account)
|
|
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ns_account = gnc_account_lookup_by_name (trading_account,
|
|
|
|
|
gnc_commodity_get_namespace(commodity));
|
|
|
|
|
if (!ns_account)
|
|
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
account = gnc_account_lookup_by_name (ns_account,
|
|
|
|
|
gnc_commodity_get_mnemonic(commodity));
|
|
|
|
|
if (!account)
|
|
|
|
|
{
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return xaccTransFindSplitByAccount(trans, account);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
add_balance_split (Transaction *trans, gnc_numeric imbalance,
|
|
|
|
|
Account *root, Account *account)
|
|
|
|
|
@ -631,71 +587,6 @@ gnc_transaction_balance_no_trading (Transaction *trans, Account *root,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
/** If there are existing trading splits, adjust the price or exchange
|
|
|
|
|
rate in each of them to agree with the non-trading splits for the
|
|
|
|
|
same commodity. If there are multiple non-trading splits for the
|
|
|
|
|
same commodity in the transaction this will use the exchange rate in
|
|
|
|
|
the last such split. This shouldn't happen, and if it does then there's
|
|
|
|
|
not much we can do about it anyway.
|
|
|
|
|
|
|
|
|
|
While we're at it, compute the value imbalance ignoring existing
|
|
|
|
|
trading splits. */
|
|
|
|
|
|
|
|
|
|
static gnc_numeric
|
|
|
|
|
gnc_transaction_adjust_trading_splits (Transaction* trans, Account *root)
|
|
|
|
|
{
|
|
|
|
|
GList* splits;
|
|
|
|
|
gnc_numeric imbalance = gnc_numeric_zero();
|
|
|
|
|
for (splits = trans->splits; splits; splits = splits->next)
|
|
|
|
|
{
|
|
|
|
|
Split *split = splits->data;
|
|
|
|
|
Split *balance_split = NULL;
|
|
|
|
|
gnc_numeric value, amount;
|
|
|
|
|
gnc_commodity *commodity, *txn_curr = xaccTransGetCurrency (trans);
|
|
|
|
|
|
|
|
|
|
if (! xaccTransStillHasSplit (trans, split)) continue;
|
|
|
|
|
|
|
|
|
|
commodity = xaccAccountGetCommodity (xaccSplitGetAccount(split));
|
|
|
|
|
if (!commodity)
|
|
|
|
|
{
|
|
|
|
|
PERR("Split has no commodity");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
balance_split = find_trading_split (trans, root, commodity);
|
|
|
|
|
|
|
|
|
|
if (balance_split != split)
|
|
|
|
|
/* this is not a trading split */
|
|
|
|
|
imbalance = gnc_numeric_add(imbalance, xaccSplitGetValue (split),
|
|
|
|
|
GNC_DENOM_AUTO, GNC_HOW_DENOM_EXACT);
|
|
|
|
|
|
|
|
|
|
/* Ignore splits where value or amount is zero */
|
|
|
|
|
value = xaccSplitGetValue (split);
|
|
|
|
|
amount = xaccSplitGetAmount (split);
|
|
|
|
|
if (gnc_numeric_zero_p(amount) || gnc_numeric_zero_p(value))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (balance_split && balance_split != split)
|
|
|
|
|
{
|
|
|
|
|
gnc_numeric convrate = gnc_numeric_div (amount, value,
|
|
|
|
|
GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
|
|
|
|
|
gnc_numeric old_value, new_value;
|
|
|
|
|
old_value = xaccSplitGetValue(balance_split);
|
|
|
|
|
new_value = gnc_numeric_div (xaccSplitGetAmount(balance_split),
|
|
|
|
|
convrate,
|
|
|
|
|
gnc_commodity_get_fraction(txn_curr),
|
|
|
|
|
GNC_HOW_RND_ROUND_HALF_UP);
|
|
|
|
|
if (! gnc_numeric_equal (old_value, new_value))
|
|
|
|
|
{
|
|
|
|
|
xaccTransBeginEdit (trans);
|
|
|
|
|
xaccSplitSetValue (balance_split, new_value);
|
|
|
|
|
xaccSplitScrub (balance_split);
|
|
|
|
|
xaccTransCommitEdit (trans);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return imbalance;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gnc_numeric
|
|
|
|
|
gnc_transaction_get_commodity_imbalance (Transaction *trans,
|
|
|
|
|
@ -719,6 +610,42 @@ gnc_transaction_get_commodity_imbalance (Transaction *trans,
|
|
|
|
|
return val_imbalance;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* GFunc wrapper for xaccSplitDestroy */
|
|
|
|
|
static void
|
|
|
|
|
destroy_split (void* ptr, void* data)
|
|
|
|
|
{
|
|
|
|
|
Split *split = GNC_SPLIT (ptr);
|
|
|
|
|
if (split)
|
|
|
|
|
xaccSplitDestroy (split);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Balancing transactions with trading accounts works best when
|
|
|
|
|
* starting with no trading splits.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
xaccTransClearTradingSplits (Transaction *trans)
|
|
|
|
|
{
|
|
|
|
|
GList *trading_splits = NULL;
|
|
|
|
|
|
|
|
|
|
for (GList* node = trans->splits; node; node = node->next)
|
|
|
|
|
{
|
|
|
|
|
Split* split = GNC_SPLIT(node->data);
|
|
|
|
|
Account* acc = NULL;
|
|
|
|
|
if (!split)
|
|
|
|
|
continue;
|
|
|
|
|
acc = xaccSplitGetAccount(split);
|
|
|
|
|
if (acc && xaccAccountGetType(acc) == ACCT_TYPE_TRADING)
|
|
|
|
|
trading_splits = g_list_prepend (trading_splits, node->data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!trading_splits)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
xaccTransBeginEdit (trans);
|
|
|
|
|
g_list_foreach (trading_splits, destroy_split, NULL);
|
|
|
|
|
xaccTransCommitEdit (trans);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
gnc_transaction_balance_trading (Transaction *trans, Account *root)
|
|
|
|
|
{
|
|
|
|
|
@ -859,8 +786,11 @@ xaccTransScrubImbalance (Transaction *trans, Account *root,
|
|
|
|
|
|
|
|
|
|
ENTER ("()");
|
|
|
|
|
|
|
|
|
|
/* Must look for orphan splits even if there is no imbalance. */
|
|
|
|
|
/* Must look for orphan splits and remove trading splits even if
|
|
|
|
|
* there is no imbalance and we're not using trading accounts.
|
|
|
|
|
*/
|
|
|
|
|
xaccTransScrubSplits (trans);
|
|
|
|
|
xaccTransClearTradingSplits (trans);
|
|
|
|
|
|
|
|
|
|
/* Return immediately if things are balanced. */
|
|
|
|
|
if (xaccTransIsBalanced (trans))
|
|
|
|
|
@ -876,9 +806,7 @@ xaccTransScrubImbalance (Transaction *trans, Account *root,
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
imbalance = gnc_transaction_adjust_trading_splits (trans, root);
|
|
|
|
|
|
|
|
|
|
/* Balance the value, ignoring existing trading splits */
|
|
|
|
|
imbalance = xaccTransGetImbalanceValue (trans);
|
|
|
|
|
if (! gnc_numeric_zero_p (imbalance))
|
|
|
|
|
{
|
|
|
|
|
PINFO ("Value unbalanced transaction");
|
|
|
|
|
|