mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Mike Alexander's patch to fix lot date calculation, and to include all
splits when computing capital gain's instead of just the opening lot. Scrub lots when scrubbing everything else. Some MacOs X fixes. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@13872 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
3cb46f0897
commit
4a5f6e30ca
1
AUTHORS
1
AUTHORS
@ -91,6 +91,7 @@ Other Contributors:
|
|||||||
----------------
|
----------------
|
||||||
(In alphabetical order)
|
(In alphabetical order)
|
||||||
|
|
||||||
|
Mike Alexander <mta@umich.edu> Cap gains, lot and MacOS fixes.
|
||||||
Andrew Arensburger <arensb@cfar.umd.edu> for FreeBSD & other patches
|
Andrew Arensburger <arensb@cfar.umd.edu> for FreeBSD & other patches
|
||||||
Matt Armstrong <matt_armstrong@bigfoot.com> for misc fixes
|
Matt Armstrong <matt_armstrong@bigfoot.com> for misc fixes
|
||||||
A. Alper Atici <alper_atici@yahoo.com> Turkish translation
|
A. Alper Atici <alper_atici@yahoo.com> Turkish translation
|
||||||
|
10
ChangeLog
10
ChangeLog
@ -1,5 +1,15 @@
|
|||||||
2006-04-28 David Hampton <hampton@employees.org>
|
2006-04-28 David Hampton <hampton@employees.org>
|
||||||
|
|
||||||
|
* src/gnome/window-reconcile.c:
|
||||||
|
* src/gnome/gnc-plugin-page-account-tree.c:
|
||||||
|
* src/engine/gnc-lot.[ch]:
|
||||||
|
* src/engine/Transaction.c:
|
||||||
|
* src/engine/Scrub2.c:
|
||||||
|
* src/engine/cap-gains.c: Mike Alexander's patch to fix lot date
|
||||||
|
calculation, and to include all splits when computing capital
|
||||||
|
gain's instead of just the opening lot. Scrub lots when scrubbing
|
||||||
|
everything else. Some MacOs X fixes.
|
||||||
|
|
||||||
* src/gnome/gnc-plugin-basic-commands.c: Finishing all pending
|
* src/gnome/gnc-plugin-basic-commands.c: Finishing all pending
|
||||||
transactions before new and open commands, not just save commands.
|
transactions before new and open commands, not just save commands.
|
||||||
Fixes #334090.
|
Fixes #334090.
|
||||||
|
@ -413,6 +413,7 @@ restart:
|
|||||||
Split *s = node->data;
|
Split *s = node->data;
|
||||||
if (xaccSplitGetLot (s) != lot) continue;
|
if (xaccSplitGetLot (s) != lot) continue;
|
||||||
if (s == split) continue;
|
if (s == split) continue;
|
||||||
|
if (s->inst.do_free) continue;
|
||||||
|
|
||||||
/* OK, this split is in the same lot (and thus same account)
|
/* OK, this split is in the same lot (and thus same account)
|
||||||
* as the indicated split. It must be a subsplit (although
|
* as the indicated split. It must be a subsplit (although
|
||||||
|
@ -1014,6 +1014,8 @@ xaccTransCommitEdit (Transaction *trans)
|
|||||||
*/
|
*/
|
||||||
if (!(trans->inst.do_free) && scrub_data &&
|
if (!(trans->inst.do_free) && scrub_data &&
|
||||||
!qof_book_shutting_down(xaccTransGetBook(trans))) {
|
!qof_book_shutting_down(xaccTransGetBook(trans))) {
|
||||||
|
/* If scrubbing gains recurses through here, don't call it again. */
|
||||||
|
scrub_data = 0;
|
||||||
/* The total value of the transaction should sum to zero.
|
/* The total value of the transaction should sum to zero.
|
||||||
* Call the trans scrub routine to fix it. Indirectly, this
|
* Call the trans scrub routine to fix it. Indirectly, this
|
||||||
* routine also performs a number of other transaction fixes too.
|
* routine also performs a number of other transaction fixes too.
|
||||||
@ -1021,6 +1023,8 @@ xaccTransCommitEdit (Transaction *trans)
|
|||||||
xaccTransScrubImbalance (trans, NULL, NULL);
|
xaccTransScrubImbalance (trans, NULL, NULL);
|
||||||
/* Get the cap gains into a consistent state as well. */
|
/* Get the cap gains into a consistent state as well. */
|
||||||
xaccTransScrubGains (trans, NULL);
|
xaccTransScrubGains (trans, NULL);
|
||||||
|
/* Allow scrubbing in transaction commit again */
|
||||||
|
scrub_data = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Record the time of last modification */
|
/* Record the time of last modification */
|
||||||
|
@ -86,6 +86,9 @@ xaccAccountHasTrades (Account *acc)
|
|||||||
|
|
||||||
if (!acc) return FALSE;
|
if (!acc) return FALSE;
|
||||||
|
|
||||||
|
if (xaccAccountIsPriced (acc))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
acc_comm = acc->commodity;
|
acc_comm = acc->commodity;
|
||||||
|
|
||||||
for (node=acc->splits; node; node=node->next)
|
for (node=acc->splits; node; node=node->next)
|
||||||
@ -158,7 +161,7 @@ finder_helper (GNCLot *lot, gpointer user_data)
|
|||||||
static inline GNCLot *
|
static inline GNCLot *
|
||||||
xaccAccountFindOpenLot (Account *acc, gnc_numeric sign,
|
xaccAccountFindOpenLot (Account *acc, gnc_numeric sign,
|
||||||
gnc_commodity *currency,
|
gnc_commodity *currency,
|
||||||
gint64 guess,
|
guint64 guess,
|
||||||
gboolean (*date_pred)(Timespec, Timespec))
|
gboolean (*date_pred)(Timespec, Timespec))
|
||||||
{
|
{
|
||||||
struct find_lot_s es;
|
struct find_lot_s es;
|
||||||
@ -184,7 +187,7 @@ xaccAccountFindEarliestOpenLot (Account *acc, gnc_numeric sign,
|
|||||||
ENTER (" sign=%" G_GINT64_FORMAT "/%" G_GINT64_FORMAT, sign.num, sign.denom);
|
ENTER (" sign=%" G_GINT64_FORMAT "/%" G_GINT64_FORMAT, sign.num, sign.denom);
|
||||||
|
|
||||||
lot = xaccAccountFindOpenLot (acc, sign, currency,
|
lot = xaccAccountFindOpenLot (acc, sign, currency,
|
||||||
G_GINT64_CONSTANT(2^31) * G_GINT64_CONSTANT(2^31), earliest_pred);
|
G_MAXUINT64, earliest_pred);
|
||||||
LEAVE ("found lot=%p %s baln=%s", lot, gnc_lot_get_title (lot),
|
LEAVE ("found lot=%p %s baln=%s", lot, gnc_lot_get_title (lot),
|
||||||
gnc_num_dbg_to_string(gnc_lot_get_balance(lot)));
|
gnc_num_dbg_to_string(gnc_lot_get_balance(lot)));
|
||||||
return lot;
|
return lot;
|
||||||
@ -199,8 +202,7 @@ xaccAccountFindLatestOpenLot (Account *acc, gnc_numeric sign,
|
|||||||
sign.num, sign.denom);
|
sign.num, sign.denom);
|
||||||
|
|
||||||
lot = xaccAccountFindOpenLot (acc, sign, currency,
|
lot = xaccAccountFindOpenLot (acc, sign, currency,
|
||||||
G_GINT64_CONSTANT(-2^31) * G_GINT64_CONSTANT(2^31),
|
0, latest_pred);
|
||||||
latest_pred);
|
|
||||||
LEAVE ("found lot=%p %s", lot, gnc_lot_get_title (lot));
|
LEAVE ("found lot=%p %s", lot, gnc_lot_get_title (lot));
|
||||||
return lot;
|
return lot;
|
||||||
}
|
}
|
||||||
@ -589,11 +591,16 @@ xaccSplitAssign (Split *split)
|
|||||||
|
|
||||||
if (!split) return FALSE;
|
if (!split) return FALSE;
|
||||||
|
|
||||||
ENTER ("(split=%p)", split);
|
/* If this split already belongs to a lot or the account doesn't
|
||||||
|
* have lots, we are done.
|
||||||
/* If this split already belongs to a lot, we are done. */
|
*/
|
||||||
if (split->lot) return FALSE;
|
if (split->lot) return FALSE;
|
||||||
acc = split->acc;
|
acc = split->acc;
|
||||||
|
if (!xaccAccountHasTrades (acc))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
ENTER ("(split=%p)", split);
|
||||||
|
|
||||||
pcy = acc->policy;
|
pcy = acc->policy;
|
||||||
xaccAccountBeginEdit (acc);
|
xaccAccountBeginEdit (acc);
|
||||||
|
|
||||||
@ -657,6 +664,7 @@ xaccSplitComputeCapGains(Split *split, Account *gain_acc)
|
|||||||
gnc_numeric value = zero;
|
gnc_numeric value = zero;
|
||||||
gnc_numeric frac;
|
gnc_numeric frac;
|
||||||
gnc_numeric opening_amount, opening_value;
|
gnc_numeric opening_amount, opening_value;
|
||||||
|
gnc_numeric lot_amount, lot_value;
|
||||||
gnc_commodity *opening_currency;
|
gnc_commodity *opening_currency;
|
||||||
|
|
||||||
if (!split) return;
|
if (!split) return;
|
||||||
@ -705,6 +713,12 @@ xaccSplitComputeCapGains(Split *split, Account *gain_acc)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (safe_strcmp ("stock-split", xaccSplitGetType (split)) == 0)
|
||||||
|
{
|
||||||
|
LEAVE ("Stock split split, returning.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (GAINS_STATUS_GAINS & split->gains)
|
if (GAINS_STATUS_GAINS & split->gains)
|
||||||
{
|
{
|
||||||
Split *s;
|
Split *s;
|
||||||
@ -826,19 +840,23 @@ xaccSplitComputeCapGains(Split *split, Account *gain_acc)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The cap gains is the difference between the value of the
|
/* The cap gains is the difference between the basis prior to the
|
||||||
* opening split, and the current split, pro-rated for an equal
|
* current split, and the current split, pro-rated for an equal
|
||||||
* amount of shares.
|
* amount of shares.
|
||||||
* i.e. purchase_price = opening_value / opening_amount
|
* i.e. purchase_price = lot_value / lot_amount
|
||||||
* cost_basis = purchase_price * current_amount
|
* cost_basis = purchase_price * current_split_amount
|
||||||
* cap_gain = current_value - cost_basis
|
* cap_gain = current_split_value - cost_basis
|
||||||
*/
|
*/
|
||||||
frac = gnc_numeric_div (split->amount, opening_amount,
|
gnc_lot_get_balance_before (lot, split, &lot_amount, &lot_value);
|
||||||
|
/* Fraction of the lot that this split represents: */
|
||||||
|
frac = gnc_numeric_div (split->amount, lot_amount,
|
||||||
GNC_DENOM_AUTO,
|
GNC_DENOM_AUTO,
|
||||||
GNC_HOW_DENOM_REDUCE);
|
GNC_HOW_DENOM_REDUCE);
|
||||||
value = gnc_numeric_mul (frac, opening_value,
|
/* Basis for this split: */
|
||||||
|
value = gnc_numeric_mul (frac, lot_value,
|
||||||
gnc_numeric_denom(opening_value),
|
gnc_numeric_denom(opening_value),
|
||||||
GNC_HOW_DENOM_EXACT|GNC_HOW_RND_ROUND);
|
GNC_HOW_DENOM_EXACT|GNC_HOW_RND_ROUND);
|
||||||
|
/* Capital gain for this split: */
|
||||||
value = gnc_numeric_sub (value, split->value,
|
value = gnc_numeric_sub (value, split->value,
|
||||||
GNC_DENOM_AUTO, GNC_HOW_DENOM_FIXED);
|
GNC_DENOM_AUTO, GNC_HOW_DENOM_FIXED);
|
||||||
PINFO ("Open amt=%s val=%s; split amt=%s val=%s; gains=%s\n",
|
PINFO ("Open amt=%s val=%s; split amt=%s val=%s; gains=%s\n",
|
||||||
@ -1124,7 +1142,10 @@ restart:
|
|||||||
{
|
{
|
||||||
gboolean altered = FALSE;
|
gboolean altered = FALSE;
|
||||||
split->gains |= ~GAINS_STATUS_ADIRTY;
|
split->gains |= ~GAINS_STATUS_ADIRTY;
|
||||||
if (split->lot) altered = xaccScrubLot (split->lot);
|
if (split->lot)
|
||||||
|
altered = xaccScrubLot (split->lot);
|
||||||
|
else
|
||||||
|
altered = xaccSplitAssign (split);
|
||||||
if (altered) goto restart;
|
if (altered) goto restart;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -225,6 +225,40 @@ gnc_lot_get_balance (GNCLot *lot)
|
|||||||
|
|
||||||
/* ============================================================= */
|
/* ============================================================= */
|
||||||
|
|
||||||
|
void
|
||||||
|
gnc_lot_get_balance_before (GNCLot *lot, Split *split,
|
||||||
|
gnc_numeric *amount, gnc_numeric *value)
|
||||||
|
{
|
||||||
|
GList *node;
|
||||||
|
gnc_numeric zero = gnc_numeric_zero();
|
||||||
|
gnc_numeric amt = zero;
|
||||||
|
gnc_numeric val = zero;
|
||||||
|
|
||||||
|
if (lot && lot->splits)
|
||||||
|
{
|
||||||
|
for (node = lot->splits; node; node = node->next)
|
||||||
|
{
|
||||||
|
Split *s = node->data;
|
||||||
|
Transaction *ta, *tb;
|
||||||
|
ta = xaccSplitGetParent (s);
|
||||||
|
tb = xaccSplitGetParent (split);
|
||||||
|
if ((ta == tb && s != split) ||
|
||||||
|
xaccTransOrder (ta, tb) < 0)
|
||||||
|
{
|
||||||
|
gnc_numeric tmpval = xaccSplitGetAmount (s);
|
||||||
|
amt = gnc_numeric_add_fixed (amt, tmpval);
|
||||||
|
tmpval = xaccSplitGetValue (s);
|
||||||
|
val = gnc_numeric_add_fixed (val, tmpval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*amount = amt;
|
||||||
|
*value = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================================= */
|
||||||
|
|
||||||
void
|
void
|
||||||
gnc_lot_add_split (GNCLot *lot, Split *split)
|
gnc_lot_add_split (GNCLot *lot, Split *split)
|
||||||
{
|
{
|
||||||
@ -294,7 +328,7 @@ gnc_lot_get_earliest_split (GNCLot *lot)
|
|||||||
Timespec ts;
|
Timespec ts;
|
||||||
Split *earliest = NULL;
|
Split *earliest = NULL;
|
||||||
|
|
||||||
ts.tv_sec = ((long long) LONG_MAX);
|
ts.tv_sec = ((long long) ULONG_MAX);
|
||||||
ts.tv_nsec = 0;
|
ts.tv_nsec = 0;
|
||||||
if (!lot) return NULL;
|
if (!lot) return NULL;
|
||||||
|
|
||||||
@ -323,7 +357,7 @@ gnc_lot_get_latest_split (GNCLot *lot)
|
|||||||
Timespec ts;
|
Timespec ts;
|
||||||
Split *latest = NULL;
|
Split *latest = NULL;
|
||||||
|
|
||||||
ts.tv_sec = -((long long) LONG_MAX);
|
ts.tv_sec = 0;
|
||||||
ts.tv_nsec = 0;
|
ts.tv_nsec = 0;
|
||||||
if (!lot) return NULL;
|
if (!lot) return NULL;
|
||||||
|
|
||||||
|
@ -97,6 +97,13 @@ Account * gnc_lot_get_account (GNCLot *);
|
|||||||
* of the account. */
|
* of the account. */
|
||||||
gnc_numeric gnc_lot_get_balance (GNCLot *);
|
gnc_numeric gnc_lot_get_balance (GNCLot *);
|
||||||
|
|
||||||
|
/** The gnc_lot_get_balance_before routines computes both the balance and
|
||||||
|
* value in the lot considering only splits in transactions prior to the
|
||||||
|
* one containing the given split or other splits in the same transaction.
|
||||||
|
* The first return value is the amount and the second is the value. */
|
||||||
|
void gnc_lot_get_balance_before (GNCLot *, Split *,
|
||||||
|
gnc_numeric *, gnc_numeric *);
|
||||||
|
|
||||||
/** The gnc_lot_is_closed() routine returns a boolean flag: is this
|
/** The gnc_lot_is_closed() routine returns a boolean flag: is this
|
||||||
* lot closed? A lot is closed if its balance is zero. This
|
* lot closed? A lot is closed if its balance is zero. This
|
||||||
* routine is faster than using gnc_lot_get_balance() because
|
* routine is faster than using gnc_lot_get_balance() because
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
#include "gnc-plugin-page-register.h"
|
#include "gnc-plugin-page-register.h"
|
||||||
|
|
||||||
#include "Scrub.h"
|
#include "Scrub.h"
|
||||||
|
#include "Scrub3.h"
|
||||||
#include "Transaction.h"
|
#include "Transaction.h"
|
||||||
#include "dialog-account.h"
|
#include "dialog-account.h"
|
||||||
#include "dialog-transfer.h"
|
#include "dialog-transfer.h"
|
||||||
@ -1198,6 +1199,8 @@ gnc_plugin_page_account_tree_cmd_scrub (GtkAction *action, GncPluginPageAccountT
|
|||||||
xaccAccountScrubOrphans (account);
|
xaccAccountScrubOrphans (account);
|
||||||
xaccAccountScrubImbalance (account);
|
xaccAccountScrubImbalance (account);
|
||||||
|
|
||||||
|
xaccAccountScrubLots (account);
|
||||||
|
|
||||||
gnc_resume_gui_refresh ();
|
gnc_resume_gui_refresh ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1213,6 +1216,8 @@ gnc_plugin_page_account_tree_cmd_scrub_sub (GtkAction *action, GncPluginPageAcco
|
|||||||
xaccAccountTreeScrubOrphans (account);
|
xaccAccountTreeScrubOrphans (account);
|
||||||
xaccAccountTreeScrubImbalance (account);
|
xaccAccountTreeScrubImbalance (account);
|
||||||
|
|
||||||
|
xaccAccountTreeScrubLots (account);
|
||||||
|
|
||||||
gnc_resume_gui_refresh ();
|
gnc_resume_gui_refresh ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1225,6 +1230,10 @@ gnc_plugin_page_account_tree_cmd_scrub_all (GtkAction *action, GncPluginPageAcco
|
|||||||
|
|
||||||
xaccGroupScrubOrphans (group);
|
xaccGroupScrubOrphans (group);
|
||||||
xaccGroupScrubImbalance (group);
|
xaccGroupScrubImbalance (group);
|
||||||
|
|
||||||
|
xaccGroupScrubLots (group);
|
||||||
|
|
||||||
|
gnc_resume_gui_refresh ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include <glib/gi18n.h>
|
#include <glib/gi18n.h>
|
||||||
|
|
||||||
#include "Scrub.h"
|
#include "Scrub.h"
|
||||||
|
#include "Scrub3.h"
|
||||||
#include "dialog-account.h"
|
#include "dialog-account.h"
|
||||||
#include "dialog-transfer.h"
|
#include "dialog-transfer.h"
|
||||||
#include "dialog-utils.h"
|
#include "dialog-utils.h"
|
||||||
@ -1229,6 +1230,8 @@ gnc_recn_scrub_cb(GtkAction *action, gpointer data)
|
|||||||
xaccAccountTreeScrubOrphans (account);
|
xaccAccountTreeScrubOrphans (account);
|
||||||
xaccAccountTreeScrubImbalance (account);
|
xaccAccountTreeScrubImbalance (account);
|
||||||
|
|
||||||
|
xaccAccountTreeScrubLots (account);
|
||||||
|
|
||||||
gnc_resume_gui_refresh ();
|
gnc_resume_gui_refresh ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user