mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
compute cost basis correctly
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@1584 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
ec762df4a6
commit
2faa2d40b3
@ -34,6 +34,7 @@
|
||||
#include "GroupP.h"
|
||||
#include "date.h"
|
||||
#include "messages.h"
|
||||
#include "Queue.h"
|
||||
#include "Transaction.h"
|
||||
#include "TransactionP.h"
|
||||
#include "util.h"
|
||||
@ -203,7 +204,7 @@ void
|
||||
xaccAccountCommitEdit (Account *acc)
|
||||
{
|
||||
if (!acc) return;
|
||||
acc->changed = 1;
|
||||
acc->changed |= ACC_INVALIDATE_ALL;
|
||||
acc->open = 0;
|
||||
}
|
||||
|
||||
@ -263,7 +264,7 @@ disable for now till we figure out what the right thing is.
|
||||
*/
|
||||
|
||||
/* mark the account as having changed */
|
||||
acc -> changed = TRUE;
|
||||
acc -> changed |= ACC_INVALIDATE_ALL;
|
||||
|
||||
/* if this split belongs to another acount, remove it from
|
||||
* there first. We don't want to ever leave the system
|
||||
@ -357,7 +358,7 @@ xaccAccountRemoveSplit ( Account *acc, Split *split )
|
||||
CHECK (acc);
|
||||
|
||||
/* mark the account as having changed */
|
||||
acc -> changed = TRUE;
|
||||
acc -> changed |= ACC_INVALIDATE_ALL;
|
||||
|
||||
for( i=0,j=0; j<acc->numSplits; i++,j++ ) {
|
||||
acc->splits[i] = acc->splits[j];
|
||||
@ -416,7 +417,8 @@ xaccAccountRecomputeBalance( Account * acc )
|
||||
Split *split, *last_split = NULL;
|
||||
|
||||
if( NULL == acc ) return;
|
||||
if (FALSE == acc->changed) return;
|
||||
if (0x0 == (ACC_INVALID_BALN & acc->changed)) return;
|
||||
acc->changed &= ~ACC_INVALID_BALN;
|
||||
|
||||
split = acc->splits[0];
|
||||
while (split) {
|
||||
@ -453,7 +455,8 @@ xaccAccountRecomputeBalance( Account * acc )
|
||||
split -> cleared_balance = dcleared_balance;
|
||||
split -> reconciled_balance = dreconciled_balance;
|
||||
}
|
||||
split -> cost_basis = dbalance;
|
||||
/* invalidate the cost basis; this has to be computed with other routine */
|
||||
split -> cost_basis = 0.0;
|
||||
|
||||
last_split = split;
|
||||
i++;
|
||||
@ -479,6 +482,46 @@ xaccAccountRecomputeBalance( Account * acc )
|
||||
return;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
|
||||
void
|
||||
xaccAccountRecomputeCostBasis( Account * acc )
|
||||
{
|
||||
int i = 0;
|
||||
double amt = 0.0;
|
||||
Split *split = NULL;
|
||||
Queue *q;
|
||||
|
||||
if( NULL == acc ) return;
|
||||
if (0x0 == (ACC_INVALID_COSTB & acc->changed)) return;
|
||||
acc->changed &= ~ACC_INVALID_COSTB;
|
||||
|
||||
/* create the FIFO queue */
|
||||
q = xaccMallocQueue ();
|
||||
|
||||
/* loop over all splits in this account */
|
||||
split = acc->splits[0];
|
||||
while (split) {
|
||||
|
||||
/* positive amounts are a purchase, negative are a sale.
|
||||
* Use FIFO accounting: purchase to head, sale from tail. */
|
||||
amt = split->damount;
|
||||
if (0.0 < amt) {
|
||||
xaccQueuePushHead (q, split);
|
||||
} else
|
||||
if (0.0 > amt) {
|
||||
xaccQueuePopTailShares (q, amt);
|
||||
}
|
||||
split->cost_basis = xaccQueueGetValue (q);
|
||||
|
||||
i++;
|
||||
split = acc->splits[i];
|
||||
}
|
||||
|
||||
xaccFreeQueue (q);
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
* xaccCheckDateOrder *
|
||||
* check this split to see if the date is in correct order *
|
||||
|
@ -18,7 +18,7 @@
|
||||
/********************************************************************\
|
||||
* Account.h -- the Account data structure *
|
||||
* Copyright (C) 1997 Robin D. Clark *
|
||||
* Copyright (C) 1997, 1998 Linas Vepstas *
|
||||
* Copyright (C) 1997, 1998, 1999 Linas Vepstas *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU General Public License as *
|
||||
@ -129,8 +129,9 @@ struct _account {
|
||||
int numSplits; /* length of splits array below */
|
||||
Split **splits; /* ptr to array of ptrs to splits */
|
||||
|
||||
/* the "changed" flag helps the gui keep track of
|
||||
* changes to this account */
|
||||
/* The "changed" flag is used to invalidate cached values in this structure.
|
||||
* currently, the balances and the cost basis are cached.
|
||||
*/
|
||||
short changed;
|
||||
|
||||
/* the "open" flag indicates if the account has been
|
||||
@ -138,6 +139,11 @@ struct _account {
|
||||
short open;
|
||||
};
|
||||
|
||||
/* bitfields for the changed flag */
|
||||
#define ACC_INVALID_BALN 0x1
|
||||
#define ACC_INVALID_COSTB 0x2
|
||||
#define ACC_INVALIDATE_ALL 0x3
|
||||
|
||||
/* bitflields for the open flag */
|
||||
#define ACC_BEGIN_EDIT 0x1
|
||||
#define ACC_DEFER_REBALANCE 0x2
|
||||
@ -160,6 +166,12 @@ void xaccAccountRemoveSplit (Account *, Split *);
|
||||
void xaccAccountRecomputeBalance (Account *);
|
||||
void xaccAccountRecomputeBalances (Account **);
|
||||
|
||||
/*
|
||||
* recomputes the cost basis
|
||||
*/
|
||||
void xaccAccountRecomputeCostBasis (Account *);
|
||||
|
||||
|
||||
/** GLOBALS *********************************************************/
|
||||
|
||||
extern int next_free_unique_account_id;
|
||||
|
@ -203,7 +203,7 @@ xaccConfigGetForceDoubleEntry (void)
|
||||
|
||||
#define MARK_SPLIT(split) { \
|
||||
Account *acc = (Account *) ((split)->acc); \
|
||||
if (acc) acc->changed = 1; \
|
||||
if (acc) acc->changed |= ACC_INVALIDATE_ALL; \
|
||||
}
|
||||
|
||||
static void
|
||||
@ -308,6 +308,7 @@ double xaccSplitGetShareBalance (Split *s)
|
||||
double xaccSplitGetCostBasis (Split *s)
|
||||
{
|
||||
if (!s) return 0.0;
|
||||
xaccAccountRecomputeCostBasis (s->acc);
|
||||
return s->cost_basis;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user