diff --git a/src/engine/Scrub.c b/src/engine/Scrub.c index 1bfc46e9b8..b24fab4cc9 100644 --- a/src/engine/Scrub.c +++ b/src/engine/Scrub.c @@ -407,10 +407,8 @@ xaccTransScrubImbalance (Transaction *trans, AccountGroup *root, ENTER ("()"); - /* Must look or orphan splits even if there is no imbalance. */ - xaccTransBeginEdit(trans); + /* Must look for orphan splits even if there is no imbalance. */ xaccTransScrubSplits (trans); - xaccTransCommitEdit(trans); /* If the transaction is balanced, nothing more to do */ imbalance = xaccTransGetImbalance (trans); diff --git a/src/engine/Transaction.c b/src/engine/Transaction.c index dff27ffb13..1b1098832d 100644 --- a/src/engine/Transaction.c +++ b/src/engine/Transaction.c @@ -1841,16 +1841,102 @@ xaccTransScrubSplits (Transaction *trans) if (!trans) return; + xaccTransBeginEdit(trans); /* The split scrub expects the transaction to have a currency! */ currency = xaccTransGetCurrency (trans); if (!currency) PERR ("Transaction doesn't have a currency!"); FOR_EACH_SPLIT(trans, xaccSplitScrub(s)); + xaccTransCommitEdit(trans); +} + +/* ============================================================== */ +/** The xaccTransScrubGainsDate() routine is used to keep the posted date + * of gains splits in sync with the posted date of the transaction + * that caused the gains. + * + * The posted date is kept in sync using a lazy-evaluation scheme. + * If xaccTransactionSetDatePosted() is called, the date change is + * accepted, and the split is marked date-dirty. If the posted date + * is queried for (using GetDatePosted()), then the transaction is + * evaluated. If it's a gains-transaction, then its date is copied + * from the source transaction that created the gains. + */ + +static void +xaccTransScrubGainsDate (Transaction *trans) +{ + SplitList *node; + Timespec ts = {0,0}; +//restart_search: + for (node = trans->splits; node; node=node->next) { + Split *s = node->data; + + if (!xaccTransStillHasSplit(trans, s)) continue; + xaccSplitDetermineGainStatus(s); + + if ((GAINS_STATUS_GAINS & s->gains) && + s->gains_split && + ((s->gains_split->gains & GAINS_STATUS_DATE_DIRTY) || + (s->gains & GAINS_STATUS_DATE_DIRTY))) + { + Transaction *source_trans = s->gains_split->parent; + ts = source_trans->date_posted; + s->gains &= ~GAINS_STATUS_DATE_DIRTY; + s->gains_split->gains &= ~GAINS_STATUS_DATE_DIRTY; + + xaccTransSetDatePostedTS(trans, &ts); + FOR_EACH_SPLIT(trans, s->gains &= ~GAINS_STATUS_DATE_DIRTY); + //goto restart_search; + } + } +} + +/* ============================================================== */ + +void +xaccTransScrubGains (Transaction *trans, Account *gain_acc) +{ + SplitList *node; + + ENTER("(trans=%p)", trans); + /* Lock down posted date, its to be synced to the posted date + * for the source of the cap gains. */ + xaccTransScrubGainsDate(trans); + + /* Fix up the split amount */ +restart: + for (node = trans->splits; node; node = node->next) { + Split *s = node->data; + + if (!xaccTransStillHasSplit(trans, s)) continue; + + xaccSplitDetermineGainStatus(s); + if (s->gains & GAINS_STATUS_ADIRTY) { + gboolean altered = FALSE; + s->gains &= ~GAINS_STATUS_ADIRTY; + if (s->lot) + altered = xaccScrubLot(s->lot); + else + altered = xaccSplitAssign(s); + if (altered) goto restart; + } + } + + /* Fix up gains split value */ + FOR_EACH_SPLIT(trans, + if ((s->gains & GAINS_STATUS_VDIRTY) || + (s->gains_split && + (s->gains_split->gains & GAINS_STATUS_VDIRTY))) + xaccSplitComputeCapGains(s, gain_acc); + ); + + LEAVE("(trans=%p)", trans); } Split * -xaccTransFindSplitByAccount(Transaction *trans, Account *acc) +xaccTransFindSplitByAccount(const Transaction *trans, const Account *acc) { if (!trans || !acc) return NULL; FOR_EACH_SPLIT(trans, if (xaccSplitGetAccount(s) == acc) return s); diff --git a/src/engine/Transaction.h b/src/engine/Transaction.h index 5223ffb731..58e2906e5a 100644 --- a/src/engine/Transaction.h +++ b/src/engine/Transaction.h @@ -194,7 +194,18 @@ gboolean xaccTransIsOpen (const Transaction *trans); Transaction * xaccTransLookup (const GUID *guid, QofBook *book); #define xaccTransLookupDirect(g,b) xaccTransLookup(&(g),b) -Split * xaccTransFindSplitByAccount(Transaction *trans, Account *acc); +Split * xaccTransFindSplitByAccount(const Transaction *trans, + const Account *acc); + +/** The xaccTransScrubGains() routine performs a number of cleanup + * functions on the indicated transaction, with the end-goal of + * setting up a consistent set of gains/losses for all the splits + * in the transaction. This includes making sure that the lot + * assignments of all the splits are good, and that the lots + * balance appropriately. + */ +void xaccTransScrubGains (Transaction *trans, Account *gain_acc); + /** \warning XXX FIXME * gnc_book_count_transactions is a utility function, diff --git a/src/engine/cap-gains.c b/src/engine/cap-gains.c index 08f98789a6..db9fe1a85a 100644 --- a/src/engine/cap-gains.c +++ b/src/engine/cap-gains.c @@ -647,8 +647,9 @@ xaccSplitGetCapGainsSplit (const Split *split) gains_guid = kvp_value_get_guid (val); if (!gains_guid) return NULL; - /* Both splits will be in the same collection, so seearch there. */ - gains_split = (Split*) qof_collection_lookup_entity (split->inst.entity.collection, gains_guid); + /* Both splits will be in the same collection, so search there. */ + gains_split = (Split*) qof_collection_lookup_entity ( + split->inst.entity.collection, gains_guid); PINFO ("split=%p has gains-split=%p", split, gains_split); return gains_split; } @@ -703,7 +704,7 @@ xaccSplitComputeCapGains(Split *split, Account *gain_acc) kvp_frame_get_string (gnc_lot_get_slots (lot), "/title")); /* Make sure the status flags and pointers are initialized */ - if (GAINS_STATUS_UNKNOWN == split->gains) xaccSplitDetermineGainStatus(split); + xaccSplitDetermineGainStatus(split); /* Not possible to have gains if the transaction currency and * account commodity are identical. */ @@ -1092,106 +1093,4 @@ xaccLotComputeCapGains (GNCLot *lot, Account *gain_acc) LEAVE("(lot=%p)", lot); } -/* ============================================================== */ -/** The xaccScrubGainsDate() routine is used to keep the posted date - * of gains splis in sync with the posted date of the transaction - * that caused the gains. - * - * The posted date is kept in sync using a lazy-evaluation scheme. - * If xaccTransactionSetDatePosted() is called, the date change is - * accepted, and the split is marked date-dirty. If the posted date - * is queried for (using GetDatePosted()), then the transaction is - * evaluated. If its a gains-transaction, then it's date is copied - * from the source transaction that created the gains. - */ - -static void -xaccScrubGainsDate (Transaction *trans) -{ - SplitList *node; - Timespec ts = {0,0}; - gboolean do_set; -restart_search: - do_set = FALSE; - for (node = trans->splits; node; node=node->next) - { - Split *s = node->data; - if (GAINS_STATUS_UNKNOWN == s->gains) xaccSplitDetermineGainStatus(s); - - if ((GAINS_STATUS_GAINS & s->gains) && - s->gains_split && - ((s->gains_split->gains & GAINS_STATUS_DATE_DIRTY) || - (s->gains & GAINS_STATUS_DATE_DIRTY))) - { - Transaction *source_trans = s->gains_split->parent; - ts = source_trans->date_posted; - do_set = TRUE; - s->gains &= ~GAINS_STATUS_DATE_DIRTY; - s->gains_split->gains &= ~GAINS_STATUS_DATE_DIRTY; - break; - } - } - - if (do_set) - { - xaccTransBeginEdit (trans); - xaccTransSetDatePostedTS(trans, &ts); - xaccTransCommitEdit (trans); - for (node = trans->splits; node; node=node->next) - { - Split *s = node->data; - s->gains &= ~GAINS_STATUS_DATE_DIRTY; - } - goto restart_search; - } -} - -/* ============================================================== */ - -void -xaccTransScrubGains (Transaction *trans, Account *gain_acc) -{ - SplitList *node; - - ENTER("(trans=%p)", trans); - /* Lock down posted date, its to be synced to the posted date - * for the source of the cap gains. */ - xaccScrubGainsDate(trans); - - /* Fix up the split amount */ -restart: - for (node=trans->splits; node; node=node->next) - { - Split *split = node->data; - - if (GAINS_STATUS_UNKNOWN == split->gains) - { - xaccSplitDetermineGainStatus(split); - } - if (split->gains & GAINS_STATUS_ADIRTY) - { - gboolean altered = FALSE; - split->gains |= ~GAINS_STATUS_ADIRTY; - if (split->lot) - altered = xaccScrubLot (split->lot); - else - altered = xaccSplitAssign (split); - if (altered) goto restart; - } - } - - /* Fix up gains split value */ - for (node=trans->splits; node; node=node->next) - { - Split *split = node->data; - if ((split->gains & GAINS_STATUS_VDIRTY) || - (split->gains_split && - (split->gains_split->gains & GAINS_STATUS_VDIRTY))) - { - xaccSplitComputeCapGains (split, gain_acc); - } - } - LEAVE("(trans=%p)", trans); -} - /* =========================== END OF FILE ======================= */ diff --git a/src/engine/cap-gains.h b/src/engine/cap-gains.h index 38df7464ff..f5e1f5a6d8 100644 --- a/src/engine/cap-gains.h +++ b/src/engine/cap-gains.h @@ -202,15 +202,6 @@ gboolean xaccSplitAssign (Split *split); */ Split * xaccSplitAssignToLot (Split *split, GNCLot *lot); -/** The xaccTransScrubGains() routine performs a number of cleanup - * functions on the indicated transaction, with the end-goal of - * setting up a consistent set of gains/losses for all the splits - * in the transaction. This includes making sure that the lot - * assignments of all the splits are good, and that the lots - * balance appropriately. - */ -void xaccTransScrubGains (Transaction *trans, Account *gain_acc); - /** The xaccSplitComputeCapGains() routine computes the cap gains * or losses for the indicated split. The gains are placed into * the 'gains_acct'. If the gains_acct is NULL, then the appropriate