Remove trading splits instead of trying to adjust them.

This commit is contained in:
John Ralls
2021-05-11 14:42:21 -07:00
parent 4f030aac6e
commit da3c511b6c

View File

@@ -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");