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:
Linas Vepstas 1999-01-08 07:22:42 +00:00
parent ec762df4a6
commit 2faa2d40b3
3 changed files with 65 additions and 9 deletions

View File

@ -34,6 +34,7 @@
#include "GroupP.h" #include "GroupP.h"
#include "date.h" #include "date.h"
#include "messages.h" #include "messages.h"
#include "Queue.h"
#include "Transaction.h" #include "Transaction.h"
#include "TransactionP.h" #include "TransactionP.h"
#include "util.h" #include "util.h"
@ -203,7 +204,7 @@ void
xaccAccountCommitEdit (Account *acc) xaccAccountCommitEdit (Account *acc)
{ {
if (!acc) return; if (!acc) return;
acc->changed = 1; acc->changed |= ACC_INVALIDATE_ALL;
acc->open = 0; 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 */ /* mark the account as having changed */
acc -> changed = TRUE; acc -> changed |= ACC_INVALIDATE_ALL;
/* if this split belongs to another acount, remove it from /* if this split belongs to another acount, remove it from
* there first. We don't want to ever leave the system * there first. We don't want to ever leave the system
@ -357,7 +358,7 @@ xaccAccountRemoveSplit ( Account *acc, Split *split )
CHECK (acc); CHECK (acc);
/* mark the account as having changed */ /* mark the account as having changed */
acc -> changed = TRUE; acc -> changed |= ACC_INVALIDATE_ALL;
for( i=0,j=0; j<acc->numSplits; i++,j++ ) { for( i=0,j=0; j<acc->numSplits; i++,j++ ) {
acc->splits[i] = acc->splits[j]; acc->splits[i] = acc->splits[j];
@ -416,7 +417,8 @@ xaccAccountRecomputeBalance( Account * acc )
Split *split, *last_split = NULL; Split *split, *last_split = NULL;
if( NULL == acc ) return; 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]; split = acc->splits[0];
while (split) { while (split) {
@ -453,7 +455,8 @@ xaccAccountRecomputeBalance( Account * acc )
split -> cleared_balance = dcleared_balance; split -> cleared_balance = dcleared_balance;
split -> reconciled_balance = dreconciled_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; last_split = split;
i++; i++;
@ -479,6 +482,46 @@ xaccAccountRecomputeBalance( Account * acc )
return; 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 * * xaccCheckDateOrder *
* check this split to see if the date is in correct order * * check this split to see if the date is in correct order *

View File

@ -18,7 +18,7 @@
/********************************************************************\ /********************************************************************\
* Account.h -- the Account data structure * * Account.h -- the Account data structure *
* Copyright (C) 1997 Robin D. Clark * * 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 * * This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as * * 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 */ int numSplits; /* length of splits array below */
Split **splits; /* ptr to array of ptrs to splits */ Split **splits; /* ptr to array of ptrs to splits */
/* the "changed" flag helps the gui keep track of /* The "changed" flag is used to invalidate cached values in this structure.
* changes to this account */ * currently, the balances and the cost basis are cached.
*/
short changed; short changed;
/* the "open" flag indicates if the account has been /* the "open" flag indicates if the account has been
@ -138,6 +139,11 @@ struct _account {
short open; 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 */ /* bitflields for the open flag */
#define ACC_BEGIN_EDIT 0x1 #define ACC_BEGIN_EDIT 0x1
#define ACC_DEFER_REBALANCE 0x2 #define ACC_DEFER_REBALANCE 0x2
@ -160,6 +166,12 @@ void xaccAccountRemoveSplit (Account *, Split *);
void xaccAccountRecomputeBalance (Account *); void xaccAccountRecomputeBalance (Account *);
void xaccAccountRecomputeBalances (Account **); void xaccAccountRecomputeBalances (Account **);
/*
* recomputes the cost basis
*/
void xaccAccountRecomputeCostBasis (Account *);
/** GLOBALS *********************************************************/ /** GLOBALS *********************************************************/
extern int next_free_unique_account_id; extern int next_free_unique_account_id;

View File

@ -203,7 +203,7 @@ xaccConfigGetForceDoubleEntry (void)
#define MARK_SPLIT(split) { \ #define MARK_SPLIT(split) { \
Account *acc = (Account *) ((split)->acc); \ Account *acc = (Account *) ((split)->acc); \
if (acc) acc->changed = 1; \ if (acc) acc->changed |= ACC_INVALIDATE_ALL; \
} }
static void static void
@ -308,6 +308,7 @@ double xaccSplitGetShareBalance (Split *s)
double xaccSplitGetCostBasis (Split *s) double xaccSplitGetCostBasis (Split *s)
{ {
if (!s) return 0.0; if (!s) return 0.0;
xaccAccountRecomputeCostBasis (s->acc);
return s->cost_basis; return s->cost_basis;
} }