diff --git a/src/engine/Scrub2.c b/src/engine/Scrub2.c index b1031f3232..a9d36b600f 100644 --- a/src/engine/Scrub2.c +++ b/src/engine/Scrub2.c @@ -116,9 +116,6 @@ xaccLotScrubDoubleBalance (GNCLot *lot) if (!lot) return; - /* We examine only closed lots */ - if (FALSE == gnc_lot_is_closed (lot)) return; - ENTER ("lot=%s", kvp_frame_get_string (gnc_lot_get_slots (lot), "/title")); for (snode = lot->splits; snode; snode=snode->next) @@ -127,6 +124,9 @@ xaccLotScrubDoubleBalance (GNCLot *lot) xaccSplitComputeCapGains (s, NULL); } + /* We double-check only closed lots */ + if (FALSE == gnc_lot_is_closed (lot)) return; + for (snode = lot->splits; snode; snode=snode->next) { Split *s = snode->data; diff --git a/src/engine/cap-gains.c b/src/engine/cap-gains.c index 929b3b4807..1b5064439d 100644 --- a/src/engine/cap-gains.c +++ b/src/engine/cap-gains.c @@ -500,7 +500,11 @@ xaccSplitComputeCapGains(Split *split, Account *gain_acc) if (!lot) return; currency = split->parent->common_currency; - ENTER ("lot=%s", kvp_frame_get_string (gnc_lot_get_slots (lot), "/title")); + ENTER ("split=%p lot=%s", split, + kvp_frame_get_string (gnc_lot_get_slots (lot), "/title")); + + /* Make sure this isn't a cap-gains split itself; ignore these. */ + if (gnc_numeric_zero_p (split->amount)) return; opening_split = gnc_lot_get_earliest_split(lot); if (split == opening_split) @@ -508,7 +512,10 @@ xaccSplitComputeCapGains(Split *split, Account *gain_acc) /* Check to make sure this split doesn't have a cap-gain * transaction associated with it. If it does, that's * wrong, and we ruthlessly destroy it. + * XXX Don't do this, it leads to infinite loops. + * We need to scrub out errors like this elsewhere! */ +#if MOVE_THIS_ELSEWHERE if (xaccSplitGetCapGainsSplit (split)) { Split *gains_split = xaccSplitGetCapGainsSplit(split); @@ -519,6 +526,7 @@ xaccSplitComputeCapGains(Split *split, Account *gain_acc) xaccTransDestroy (trans); xaccTransCommitEdit (trans); } +#endif return; } @@ -564,7 +572,7 @@ xaccSplitComputeCapGains(Split *split, Account *gain_acc) value = gnc_numeric_div (value, opening_split->amount, gnc_numeric_denom(opening_split->value), GNC_DENOM_EXACT); - value = gnc_numeric_add (value, split->value, + value = gnc_numeric_sub (value, split->value, GNC_DENOM_AUTO, GNC_DENOM_LCD); PINFO ("Open amt=%s val=%s; split amt=%s val=%s; gains=%s\n", gnc_numeric_to_string (opening_split->amount), @@ -672,4 +680,18 @@ xaccSplitComputeCapGains(Split *split, Account *gain_acc) LEAVE ("lot=%s", kvp_frame_get_string (gnc_lot_get_slots (lot), "/title")); } +/* ============================================================== */ + +gnc_numeric +xaccSplitGetCapGains(Split * split) +{ + if (!split) return gnc_numeric_zero(); + split = xaccSplitGetCapGainsSplit (split); + if (!split) return gnc_numeric_zero(); + + /* XXX Do *not! recomp gains every time; use a 'dirty' flag instead */ + xaccSplitComputeCapGains (split, NULL); + return split->value; +} + /* =========================== END OF FILE ======================= */ diff --git a/src/engine/cap-gains.h b/src/engine/cap-gains.h index 9da95ceee4..0c24af64a5 100644 --- a/src/engine/cap-gains.h +++ b/src/engine/cap-gains.h @@ -45,6 +45,19 @@ #include "gnc-engine.h" +/** The xaccSplitGetCapGains() method returns the value of + * capital gains (if any) associated with the indicated + * split. In order for there to be any capital gains, + * several things must hold true about this split: + * (1) It must have been involved in trading (for aexample, + * by belonging to a stock or trading account) + * (2) It must have been assigned to a lot. + * (3) It cannot be the opening split of a lot; that + * is, it must be a matching sale of an earlier purchase + * (or vice versa). + */ +gnc_numeric xaccSplitGetCapGains(Split *); + /** The xaccAccountHasTrades() method checks to see if the * indicated account is used in the trading of commodities. * A 'trading' account will contain transactions whose