mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Some extract-function refactors to xaccTransScrubImbalance.
This commit is contained in:
parent
734ecce36d
commit
61973a8302
@ -527,50 +527,23 @@ add_balance_split (Transaction *trans, gnc_numeric imbalance,
|
||||
xaccTransCommitEdit (trans);
|
||||
}
|
||||
|
||||
void
|
||||
xaccTransScrubImbalance (Transaction *trans, Account *root,
|
||||
/* Balance a transaction without trading accounts. */
|
||||
static void
|
||||
gnc_transaction_balance_no_trading (Transaction *trans, Account *root,
|
||||
Account *account)
|
||||
{
|
||||
const gnc_commodity *currency;
|
||||
|
||||
if (!trans) return;
|
||||
|
||||
ENTER ("()");
|
||||
|
||||
/* Must look for orphan splits even if there is no imbalance. */
|
||||
xaccTransScrubSplits (trans);
|
||||
|
||||
/* Return immediately if things are balanced. */
|
||||
if (xaccTransIsBalanced (trans))
|
||||
{
|
||||
LEAVE ("transaction is balanced");
|
||||
return;
|
||||
}
|
||||
|
||||
currency = xaccTransGetCurrency (trans);
|
||||
|
||||
if (! xaccTransUseTradingAccounts (trans))
|
||||
{
|
||||
gnc_numeric imbalance;
|
||||
gnc_numeric imbalance = xaccTransGetImbalanceValue (trans);
|
||||
|
||||
/* Make the value sum to zero */
|
||||
imbalance = xaccTransGetImbalanceValue (trans);
|
||||
if (! gnc_numeric_zero_p (imbalance))
|
||||
{
|
||||
PINFO ("Value unbalanced transaction");
|
||||
|
||||
add_balance_split (trans, imbalance, root, account);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MonetaryList *imbal_list;
|
||||
MonetaryList *imbalance_commod;
|
||||
GList *splits;
|
||||
gnc_numeric imbalance;
|
||||
Split *balance_split = NULL;
|
||||
|
||||
/* If there are existing trading splits, adjust the price or exchange
|
||||
}
|
||||
/** 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
|
||||
@ -580,13 +553,17 @@ xaccTransScrubImbalance (Transaction *trans, Account *root,
|
||||
While we're at it, compute the value imbalance ignoring existing
|
||||
trading splits. */
|
||||
|
||||
imbalance = gnc_numeric_zero();
|
||||
|
||||
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;
|
||||
gnc_commodity *commodity, *txn_curr = xaccTransGetCurrency (trans);
|
||||
|
||||
if (! xaccTransStillHasSplit (trans, split)) continue;
|
||||
|
||||
@ -618,7 +595,7 @@ xaccTransScrubImbalance (Transaction *trans, Account *root,
|
||||
old_value = xaccSplitGetValue(balance_split);
|
||||
new_value = gnc_numeric_div (xaccSplitGetAmount(balance_split),
|
||||
convrate,
|
||||
gnc_commodity_get_fraction(currency),
|
||||
gnc_commodity_get_fraction(txn_curr),
|
||||
GNC_HOW_RND_ROUND_HALF_UP);
|
||||
if (! gnc_numeric_equal (old_value, new_value))
|
||||
{
|
||||
@ -629,14 +606,37 @@ xaccTransScrubImbalance (Transaction *trans, Account *root,
|
||||
}
|
||||
}
|
||||
}
|
||||
return imbalance;
|
||||
}
|
||||
|
||||
/* Balance the value, ignoring existing trading splits */
|
||||
if (! gnc_numeric_zero_p (imbalance))
|
||||
static gnc_numeric
|
||||
gnc_transaction_get_commodity_imbalance (Transaction *trans,
|
||||
gnc_commodity *commodity)
|
||||
{
|
||||
/* Find the value imbalance in this commodity */
|
||||
gnc_numeric val_imbalance = gnc_numeric_zero();
|
||||
GList *splits = NULL;
|
||||
for (splits = trans->splits; splits; splits = splits->next)
|
||||
{
|
||||
PINFO ("Value unbalanced transaction");
|
||||
|
||||
add_balance_split (trans, imbalance, root, account);
|
||||
Split *split = splits->data;
|
||||
gnc_commodity *split_commodity =
|
||||
xaccAccountGetCommodity(xaccSplitGetAccount(split));
|
||||
if (xaccTransStillHasSplit (trans, split) &&
|
||||
gnc_commodity_equal (commodity, split_commodity))
|
||||
val_imbalance = gnc_numeric_add (val_imbalance,
|
||||
xaccSplitGetValue (split),
|
||||
GNC_DENOM_AUTO,
|
||||
GNC_HOW_DENOM_EXACT);
|
||||
}
|
||||
return val_imbalance;
|
||||
}
|
||||
|
||||
static void
|
||||
gnc_transaction_balance_trading (Transaction *trans, Account *root)
|
||||
{
|
||||
MonetaryList *imbal_list;
|
||||
MonetaryList *imbalance_commod;
|
||||
Split *balance_split = NULL;
|
||||
|
||||
/* If the transaction is balanced, nothing more to do */
|
||||
imbal_list = xaccTransGetImbalance (trans);
|
||||
@ -655,7 +655,8 @@ xaccTransScrubImbalance (Transaction *trans, Account *root,
|
||||
gnc_commodity *commodity;
|
||||
gnc_numeric old_amount, new_amount;
|
||||
gnc_numeric old_value, new_value, val_imbalance;
|
||||
GList *splits;
|
||||
Account *account = NULL;
|
||||
const gnc_commodity *txn_curr = xaccTransGetCurrency (trans);
|
||||
|
||||
commodity = gnc_monetary_commodity (*imbal_mon);
|
||||
|
||||
@ -670,19 +671,9 @@ xaccTransScrubImbalance (Transaction *trans, Account *root,
|
||||
|
||||
account = xaccSplitGetAccount(balance_split);
|
||||
|
||||
if (! gnc_commodity_equal (currency, commodity))
|
||||
if (! gnc_commodity_equal (txn_curr, commodity))
|
||||
{
|
||||
/* Find the value imbalance in this commodity */
|
||||
val_imbalance = gnc_numeric_zero();
|
||||
for (splits = trans->splits; splits; splits = splits->next)
|
||||
{
|
||||
Split *split = splits->data;
|
||||
if (xaccTransStillHasSplit (trans, split) &&
|
||||
gnc_commodity_equal (commodity,
|
||||
xaccAccountGetCommodity(xaccSplitGetAccount(split))))
|
||||
val_imbalance = gnc_numeric_add (val_imbalance, xaccSplitGetValue (split),
|
||||
GNC_DENOM_AUTO, GNC_HOW_DENOM_EXACT);
|
||||
}
|
||||
gnc_transaction_get_commodity_imbalance (trans, commodity);
|
||||
}
|
||||
|
||||
xaccTransBeginEdit (trans);
|
||||
@ -694,7 +685,7 @@ xaccTransScrubImbalance (Transaction *trans, Account *root,
|
||||
|
||||
xaccSplitSetAmount (balance_split, new_amount);
|
||||
|
||||
if (gnc_commodity_equal (currency, commodity))
|
||||
if (gnc_commodity_equal (txn_curr, commodity))
|
||||
{
|
||||
/* Imbalance commodity is the transaction currency, value in the
|
||||
split must be the same as the amount */
|
||||
@ -704,7 +695,7 @@ xaccTransScrubImbalance (Transaction *trans, Account *root,
|
||||
{
|
||||
old_value = xaccSplitGetValue (balance_split);
|
||||
new_value = gnc_numeric_sub (old_value, val_imbalance,
|
||||
gnc_commodity_get_fraction(currency),
|
||||
gnc_commodity_get_fraction(txn_curr),
|
||||
GNC_HOW_RND_ROUND_HALF_UP);
|
||||
|
||||
xaccSplitSetValue (balance_split, new_value);
|
||||
@ -715,16 +706,19 @@ xaccTransScrubImbalance (Transaction *trans, Account *root,
|
||||
}
|
||||
|
||||
gnc_monetary_list_free(imbal_list);
|
||||
}
|
||||
|
||||
if (!gnc_numeric_zero_p(xaccTransGetImbalanceValue(trans)))
|
||||
{
|
||||
/* This is probably because there are splits with zero amount
|
||||
and non-zero value. These are usually realized gain/loss
|
||||
splits. Add a reversing split for each of them to balance
|
||||
the value. */
|
||||
|
||||
/** Balance the transaction by adding more trading splits. This shouldn't
|
||||
* ordinarily be necessary.
|
||||
* @param trans the transaction to balance
|
||||
* @param root the root account
|
||||
*/
|
||||
static void
|
||||
gnc_transaction_balance_trading_more_splits (Transaction *trans, Account *root)
|
||||
{
|
||||
/* Copy the split list so we don't see the splits we're adding */
|
||||
GList *splits_dup = g_list_copy(trans->splits);
|
||||
GList *splits_dup = g_list_copy(trans->splits), *splits = NULL;
|
||||
const gnc_commodity *txn_curr = xaccTransGetCurrency (trans);
|
||||
for (splits = splits_dup; splits; splits = splits->next)
|
||||
{
|
||||
Split *split = splits->data;
|
||||
@ -734,6 +728,8 @@ xaccTransScrubImbalance (Transaction *trans, Account *root,
|
||||
{
|
||||
gnc_commodity *commodity;
|
||||
gnc_numeric old_value, new_value;
|
||||
Split *balance_split;
|
||||
Account *account = NULL;
|
||||
|
||||
commodity = xaccAccountGetCommodity(xaccSplitGetAccount(split));
|
||||
if (!commodity)
|
||||
@ -745,7 +741,6 @@ xaccTransScrubImbalance (Transaction *trans, Account *root,
|
||||
if (!balance_split)
|
||||
{
|
||||
/* Error already logged */
|
||||
gnc_monetary_list_free(imbal_list);
|
||||
LEAVE("");
|
||||
return;
|
||||
}
|
||||
@ -755,7 +750,7 @@ xaccTransScrubImbalance (Transaction *trans, Account *root,
|
||||
|
||||
old_value = xaccSplitGetValue (balance_split);
|
||||
new_value = gnc_numeric_sub (old_value, xaccSplitGetValue(split),
|
||||
gnc_commodity_get_fraction(currency),
|
||||
gnc_commodity_get_fraction(txn_curr),
|
||||
GNC_HOW_RND_ROUND_HALF_UP);
|
||||
xaccSplitSetValue (balance_split, new_value);
|
||||
|
||||
@ -768,12 +763,66 @@ xaccTransScrubImbalance (Transaction *trans, Account *root,
|
||||
}
|
||||
|
||||
g_list_free(splits_dup);
|
||||
}
|
||||
|
||||
/** Correct transaction imbalances.
|
||||
* @param trans The Transaction
|
||||
* @param root The (hidden) root account, for the book default currency.
|
||||
* @param account The account whose currency in which to balance.
|
||||
*/
|
||||
|
||||
void
|
||||
xaccTransScrubImbalance (Transaction *trans, Account *root,
|
||||
Account *account)
|
||||
{
|
||||
gnc_numeric imbalance;
|
||||
|
||||
if (!trans) return;
|
||||
|
||||
ENTER ("()");
|
||||
|
||||
/* Must look for orphan splits even if there is no imbalance. */
|
||||
xaccTransScrubSplits (trans);
|
||||
|
||||
/* Return immediately if things are balanced. */
|
||||
if (xaccTransIsBalanced (trans))
|
||||
{
|
||||
LEAVE ("transaction is balanced");
|
||||
return;
|
||||
}
|
||||
|
||||
if (! xaccTransUseTradingAccounts (trans))
|
||||
{
|
||||
gnc_transaction_balance_no_trading (trans, root, account);
|
||||
LEAVE ("transaction balanced, no trading accounts");
|
||||
return;
|
||||
}
|
||||
|
||||
imbalance = gnc_transaction_adjust_trading_splits (trans, root);
|
||||
|
||||
/* Balance the value, ignoring existing trading splits */
|
||||
if (! gnc_numeric_zero_p (imbalance))
|
||||
{
|
||||
PINFO ("Value unbalanced transaction");
|
||||
|
||||
add_balance_split (trans, imbalance, root, account);
|
||||
}
|
||||
|
||||
gnc_transaction_balance_trading (trans, root);
|
||||
if (gnc_numeric_zero_p(xaccTransGetImbalanceValue(trans)))
|
||||
{
|
||||
LEAVE ("()");
|
||||
return;
|
||||
}
|
||||
/* If the transaction is still not balanced, it's probably because there
|
||||
are splits with zero amount and non-zero value. These are usually
|
||||
realized gain/loss splits. Add a reversing split for each of them to
|
||||
balance the value. */
|
||||
|
||||
gnc_transaction_balance_trading_more_splits (trans, root);
|
||||
if (!gnc_numeric_zero_p(xaccTransGetImbalanceValue(trans)))
|
||||
PERR("Balancing currencies unbalanced value");
|
||||
}
|
||||
}
|
||||
LEAVE ("()");
|
||||
|
||||
}
|
||||
|
||||
/* ================================================================ */
|
||||
|
Loading…
Reference in New Issue
Block a user