diff --git a/libgnucash/engine/Scrub.c b/libgnucash/engine/Scrub.c index 3e4c972801..340cd3431f 100644 --- a/libgnucash/engine/Scrub.c +++ b/libgnucash/engine/Scrub.c @@ -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");