mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
stock portfolio alpha-level fixes
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@17 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
2f0e6918aa
commit
4732ac577b
21
README
21
README
@ -39,16 +39,19 @@ sorry, no "make install" yet.
|
||||
|
||||
Status:
|
||||
-------
|
||||
As of version 0.9f:
|
||||
As of version 0.9g:
|
||||
---------------
|
||||
Mutual fund and Stock Portfolio handling
|
||||
is implemented, but is in alpha state: many features are
|
||||
missing, and others are broken. Transfers between funds and
|
||||
bank accounts are not properly supported. Also, tabbing between
|
||||
fields for mutual funds does not work correctly. One planned
|
||||
addition is an indication of the type of transaction (Buy,
|
||||
Cap Gain, Dividend Reinvest, etc.) But it is not clear when
|
||||
this will be added.
|
||||
Bare-bones Mutual Fund and Stock Portfolio handling
|
||||
is implemented.
|
||||
Working Features:
|
||||
-- transfers between bank account & fund work
|
||||
-- save to disk, restore from disk.
|
||||
|
||||
Bugs:
|
||||
-- tabbing between fields for mutual funds does not work correctly.
|
||||
|
||||
Planned additions:
|
||||
-- Indicate type of transaction (Buy, Cap Gain, Dividend Reinvest, etc.)
|
||||
|
||||
--------
|
||||
An alpha version of import from Quicken files is also present,
|
||||
|
@ -594,6 +594,7 @@ createCB( Widget mw, XtPointer cd, XtPointer cb )
|
||||
String name = XmTextGetString(accData->name);
|
||||
String desc = XmTextGetString(accData->desc);
|
||||
|
||||
#ifdef SHOULDNT_BE_BROKEN_ANYMORE
|
||||
{
|
||||
/* since portfolio & mutual not fully implemented, provide warning */
|
||||
int warn = 0;
|
||||
@ -615,6 +616,7 @@ Do you want to continue anyway?\n");
|
||||
if (!do_it_anyway) return;
|
||||
}
|
||||
}
|
||||
#endif /* SHOULDNT_BE_BROKEN_ANYMORE */
|
||||
|
||||
/* The account has to have a name! */
|
||||
if( strcmp( name, "" ) == 0 ) {
|
||||
|
115
src/Account.c
115
src/Account.c
@ -275,6 +275,18 @@ insertTransaction( Account *acc, Transaction *trans )
|
||||
\********************************************************************/
|
||||
|
||||
double xaccGetAmount (Account *acc, Transaction *trans)
|
||||
{
|
||||
double themount; /* amount */
|
||||
|
||||
themount = xaccGetShareAmount (acc, trans);
|
||||
themount *= trans->share_price;
|
||||
return themount;
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
|
||||
double xaccGetShareAmount (Account *acc, Transaction *trans)
|
||||
{
|
||||
double themount; /* amount */
|
||||
if (NULL == trans) return 0.0;
|
||||
@ -287,7 +299,7 @@ double xaccGetAmount (Account *acc, Transaction *trans)
|
||||
if ( trans->debit == ((struct _account *) acc) ) {
|
||||
themount = - (trans->damount);
|
||||
} else {
|
||||
printf ("Internal Error: xaccGetAmount: missing double entry \n");
|
||||
printf ("Internal Error: xaccGetShareAmount: missing double entry \n");
|
||||
printf ("this error should not occur. Please report the problem. \n");
|
||||
themount = 0.0; /* punt */
|
||||
}
|
||||
@ -297,7 +309,7 @@ double xaccGetAmount (Account *acc, Transaction *trans)
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
|
||||
void xaccSetAmount (Account *acc, Transaction *trans, double themount)
|
||||
void xaccSetShareAmount (Account *acc, Transaction *trans, double themount)
|
||||
{
|
||||
/* for a double-entry, determine if this is a credit or a debit */
|
||||
if ( trans->credit == ((struct _account *) acc) ) {
|
||||
@ -315,6 +327,17 @@ void xaccSetAmount (Account *acc, Transaction *trans, double themount)
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
|
||||
void xaccSetAmount (Account *acc, Transaction *trans, double themount)
|
||||
{
|
||||
if (0.0 < trans->share_price) {
|
||||
themount /= trans->share_price;
|
||||
xaccSetShareAmount (acc, trans, themount);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
\********************************************************************/
|
||||
|
||||
double xaccGetBalance (Account *acc, Transaction *trans)
|
||||
{
|
||||
double themount; /* amount */
|
||||
@ -379,11 +402,25 @@ double xaccGetShareBalance (Account *acc, Transaction *trans)
|
||||
* xaccRecomputeBalance *
|
||||
* recomputes the partial balances and the current balance for *
|
||||
* this account. *
|
||||
|
||||
The current balance is always the current share balance times the
|
||||
current share price. The share price for bank accounts is always 1.0,
|
||||
so, for bank acccounts, the current balance is always equal to the current
|
||||
share balance.
|
||||
*
|
||||
* The way the computation is done depends on whether the partial
|
||||
* balances are for a monetary account (bank, cash, etc.) or a
|
||||
* certificate account (stock portfolio, mutual fund). For bank
|
||||
* accounts, the invarient amount is the dollar amount. For share
|
||||
* accounts, the invarient amount is the number of shares. For
|
||||
* share accounts, the share price fluctuates, and the current
|
||||
* value of such an account is the number of shares times the current
|
||||
* share price.
|
||||
*
|
||||
* Part of the complexity of this computatation stems from the fact
|
||||
* xacc uses a double-entry system, meaning that one transaction
|
||||
* appears in two accounts: one account is debited, and the other
|
||||
* is credited. When the transaction represents a sale of shares,
|
||||
* or a purchase of shares, some care must be taken to compute
|
||||
* balances correctly. For a sale of shares, the stock account must
|
||||
* be debited in shares, but the bank account must be credited
|
||||
* in dollars. Thus, two different mechanisms must be used to
|
||||
* compute balances, depending on account type.
|
||||
* *
|
||||
* Args: account -- the account for which to recompute balances *
|
||||
* Return: void *
|
||||
@ -394,33 +431,67 @@ xaccRecomputeBalance( Account * acc )
|
||||
int i;
|
||||
double dbalance = 0.0;
|
||||
double dcleared_balance = 0.0;
|
||||
Transaction *trans;
|
||||
double share_balance = 0.0;
|
||||
double share_cleared_balance = 0.0;
|
||||
double amt = 0.0;
|
||||
Transaction *trans, *last_trans;
|
||||
Account *tracc;
|
||||
|
||||
if( NULL == acc ) return;
|
||||
|
||||
for( i=0; (trans=getTransaction(acc,i)) != NULL; i++ ) {
|
||||
dbalance += xaccGetAmount (acc, trans);
|
||||
|
||||
/* compute both dollar and share balances */
|
||||
amt = xaccGetShareAmount (acc, trans);
|
||||
share_balance += amt;
|
||||
dbalance += amt * (trans->share_price);
|
||||
|
||||
if( trans->reconciled != NREC ) {
|
||||
dcleared_balance += xaccGetAmount (acc, trans);
|
||||
share_cleared_balance += amt;
|
||||
dcleared_balance += amt * (trans->share_price);
|
||||
}
|
||||
|
||||
if (acc == (Account *) trans->credit) {
|
||||
trans -> credit_share_balance = dbalance;
|
||||
trans -> credit_share_cleared_balance = dcleared_balance;
|
||||
trans -> credit_balance = trans->share_price * dbalance;
|
||||
trans -> credit_cleared_balance = trans->share_price * dcleared_balance;
|
||||
tracc = (Account *) trans->credit;
|
||||
if (tracc == acc) {
|
||||
/* For bank accounts, the invarient subtotal is the dollar
|
||||
* amount. For stock accoounts, the invarient is the share amount */
|
||||
if ( (PORTFOLIO == tracc->type) || ( MUTUAL == tracc->type) ) {
|
||||
trans -> credit_share_balance = share_balance;
|
||||
trans -> credit_share_cleared_balance = share_cleared_balance;
|
||||
trans -> credit_balance = trans->share_price * share_balance;
|
||||
trans -> credit_cleared_balance = trans->share_price * share_cleared_balance;
|
||||
} else {
|
||||
trans -> credit_share_balance = dbalance;
|
||||
trans -> credit_share_cleared_balance = dcleared_balance;
|
||||
trans -> credit_balance = dbalance;
|
||||
trans -> credit_cleared_balance = dcleared_balance;
|
||||
}
|
||||
}
|
||||
if (acc == (Account *) trans->debit) {
|
||||
trans -> debit_share_balance = dbalance;
|
||||
trans -> debit_share_cleared_balance = dcleared_balance;
|
||||
trans -> debit_balance = trans->share_price * dbalance;
|
||||
trans -> debit_cleared_balance = trans->share_price * dcleared_balance;
|
||||
tracc = (Account *) trans->debit;
|
||||
if (tracc == acc) {
|
||||
if ( (PORTFOLIO == tracc->type) || ( MUTUAL == tracc->type) ) {
|
||||
trans -> debit_share_balance = share_balance;
|
||||
trans -> debit_share_cleared_balance = share_cleared_balance;
|
||||
trans -> debit_balance = trans->share_price * share_balance;
|
||||
trans -> debit_cleared_balance = trans->share_price * share_cleared_balance;
|
||||
} else {
|
||||
trans -> debit_share_balance = dbalance;
|
||||
trans -> debit_share_cleared_balance = dcleared_balance;
|
||||
trans -> debit_balance = dbalance;
|
||||
trans -> debit_cleared_balance = dcleared_balance;
|
||||
}
|
||||
}
|
||||
|
||||
last_trans = trans;
|
||||
}
|
||||
|
||||
acc -> balance = dbalance;
|
||||
acc -> cleared_balance = dcleared_balance;
|
||||
if ( (PORTFOLIO == acc->type) || ( MUTUAL == acc->type) ) {
|
||||
acc -> balance = share_balance * (last_trans->share_price);
|
||||
acc -> cleared_balance = share_cleared_balance * (last_trans->share_price);
|
||||
} else {
|
||||
acc -> balance = dbalance;
|
||||
acc -> cleared_balance = dcleared_balance;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ Boolean havePixels = False;
|
||||
void
|
||||
refreshMainWindow( void )
|
||||
{
|
||||
int i,j,nrows;
|
||||
int i,nrows;
|
||||
char buf[BUFSIZE];
|
||||
|
||||
XtVaGetValues( accountlist, XmNrows, &nrows, NULL );
|
||||
@ -91,14 +91,10 @@ refreshMainWindow( void )
|
||||
String rows[3];
|
||||
Transaction *trans=NULL;
|
||||
Account *acc = getAccount( data, i );
|
||||
double dbalance = 0.0;
|
||||
double share_balance = 0.0;
|
||||
double dbalance;
|
||||
|
||||
j=0;
|
||||
while( (trans = getTransaction(acc,j++)) != NULL ) {
|
||||
share_balance += xaccGetAmount (acc, trans);
|
||||
dbalance = share_balance * trans->share_price;
|
||||
}
|
||||
xaccRecomputeBalance (acc);
|
||||
dbalance = acc->balance;
|
||||
|
||||
if( 0.0 > dbalance )
|
||||
sprintf( buf,"-$%.2f\0", DABS(dbalance) );
|
||||
|
@ -238,20 +238,47 @@ regRefresh( RegWindow *regData )
|
||||
|
||||
newData[row+1][RECN_CELL_C] = XtNewString("");
|
||||
|
||||
themount = xaccGetAmount (acc, trans);
|
||||
|
||||
/* hack alert -- share amounts should have three digits */
|
||||
if( 0.0 > themount )
|
||||
/* ----------------------------------- */
|
||||
/* display depends on account type */
|
||||
switch(acc->type)
|
||||
{
|
||||
sprintf( buf, "%.2f ", -themount );
|
||||
newData[row][PAY_CELL_C] = XtNewString(buf);
|
||||
newData[row][DEP_CELL_C] = XtNewString("");
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf( buf, "%.2f ", themount );
|
||||
newData[row][PAY_CELL_C] = XtNewString("");
|
||||
newData[row][DEP_CELL_C] = XtNewString(buf);
|
||||
case BANK:
|
||||
case CASH:
|
||||
case ASSET:
|
||||
case CREDIT:
|
||||
case LIABILITY:
|
||||
themount = xaccGetAmount (acc, trans);
|
||||
if( 0.0 > themount )
|
||||
{
|
||||
sprintf( buf, "%.2f ", -themount );
|
||||
newData[row][PAY_CELL_C] = XtNewString(buf);
|
||||
newData[row][DEP_CELL_C] = XtNewString("");
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf( buf, "%.2f ", themount );
|
||||
newData[row][PAY_CELL_C] = XtNewString("");
|
||||
newData[row][DEP_CELL_C] = XtNewString(buf);
|
||||
}
|
||||
break;
|
||||
case PORTFOLIO:
|
||||
case MUTUAL:
|
||||
themount = xaccGetShareAmount (acc, trans);
|
||||
if( 0.0 > themount )
|
||||
{
|
||||
sprintf( buf, "%.3f ", -themount );
|
||||
newData[row][PAY_CELL_C] = XtNewString(buf);
|
||||
newData[row][DEP_CELL_C] = XtNewString("");
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf( buf, "%.3f ", themount );
|
||||
newData[row][PAY_CELL_C] = XtNewString("");
|
||||
newData[row][DEP_CELL_C] = XtNewString(buf);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf( stderr, "Ineternal Error: Account type: %d is unknown!\n", acc->type);
|
||||
}
|
||||
|
||||
newData[row+1][PAY_CELL_C] = XtNewString("");
|
||||
@ -277,13 +304,11 @@ regRefresh( RegWindow *regData )
|
||||
newData[row+1][PRIC_CELL_C] = XtNewString("");
|
||||
newData[row][SHRS_CELL_C] = XtNewString("");
|
||||
newData[row+1][SHRS_CELL_C] = XtNewString("");
|
||||
/*
|
||||
newData[row][ACTN_CELL_C] = XtNewString("");
|
||||
newData[row+1][ACTN_CELL_C] = XtNewString("");
|
||||
*/
|
||||
/* newData[row][ACTN_CELL_C] = XtNewString(""); */
|
||||
/* newData[row+1][ACTN_CELL_C] = XtNewString(""); */
|
||||
break;
|
||||
default:
|
||||
fprintf( stderr, "Ineternal Error: Account type: %d is unknown!\n", regData->acc->type);
|
||||
fprintf( stderr, "Ineternal Error: Account type: %d is unknown!\n", acc->type);
|
||||
}
|
||||
}
|
||||
|
||||
@ -384,9 +409,9 @@ regRecalculateBalance( RegWindow *regData )
|
||||
(PORTFOLIO == acc->type) )
|
||||
{
|
||||
#ifdef USE_NO_COLOR
|
||||
sprintf( buf, "%.2f ", share_balance );
|
||||
sprintf( buf, "%.3f ", share_balance );
|
||||
#else
|
||||
sprintf( buf, "%.2f ", DABS(share_balance) );
|
||||
sprintf( buf, "%.3f ", DABS(share_balance) );
|
||||
|
||||
/* Set the color of the text, depending on whether the
|
||||
* balance is negative or positive */
|
||||
@ -552,7 +577,7 @@ regSaveTransaction( RegWindow *regData, int position )
|
||||
sscanf( amount, "%f", &val );
|
||||
themount -= val;
|
||||
|
||||
xaccSetAmount (acc, trans, themount);
|
||||
xaccSetShareAmount (acc, trans, themount);
|
||||
|
||||
/* Reset so there is only one field filled */
|
||||
if( 0.0 > themount )
|
||||
@ -897,7 +922,7 @@ regWindow( Widget parent, Account *acc )
|
||||
case MUTUAL:
|
||||
acc -> colWidths[PRIC_CELL_C] = 8; /* price */
|
||||
acc -> colWidths[SHRS_CELL_C] = 8; /* share balance */
|
||||
/* acc -> colWidths[ACTN_CELL_C] = 6; /* action (category) */
|
||||
/* acc -> colWidths[ACTN_CELL_C] = 6; /* action (Buy/Sell)*/
|
||||
break;
|
||||
}
|
||||
|
||||
@ -953,7 +978,7 @@ regWindow( Widget parent, Account *acc )
|
||||
case MUTUAL:
|
||||
acc -> rows[0][PRIC_CELL_C] = "Price";
|
||||
acc -> rows[0][SHRS_CELL_C] = "Tot Shrs";
|
||||
/* acc -> rows[0][ACTN_CELL_C] = "Cat"; /* action */
|
||||
/* acc -> rows[0][ACTN_CELL_C] = "Action"; /* action */
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1251,22 +1276,24 @@ deleteCB( Widget mw, XtPointer cd, XtPointer cb )
|
||||
{
|
||||
RegWindow *regData = (RegWindow *)cd;
|
||||
Account *acc = regData->acc;
|
||||
Transaction *trans;
|
||||
|
||||
if( getTransaction(acc,regData->lastTrans) != NULL )
|
||||
trans = getTransaction (acc, regData->lastTrans );
|
||||
if( NULL != trans)
|
||||
{
|
||||
char *msg = "Are you sure you want\nto delete this transaction?";
|
||||
|
||||
if( verifyBox( toplevel, msg ) )
|
||||
{
|
||||
Transaction *trans;
|
||||
trans = getTransaction (acc, regData->lastTrans );
|
||||
Account * cred = (Account *) (trans->credit);
|
||||
Account * deb = (Account *) (trans->debit);
|
||||
|
||||
/* remove the transaction from both accounts */
|
||||
REMOVE_TRANS ((trans->credit), trans);
|
||||
REMOVE_TRANS ((trans->debit), trans);
|
||||
REMOVE_TRANS (cred, trans);
|
||||
REMOVE_TRANS (deb, trans);
|
||||
|
||||
RECALC_BALANCE ((trans->debit));
|
||||
RECALC_BALANCE ((trans->credit));
|
||||
RECALC_BALANCE (deb);
|
||||
RECALC_BALANCE (cred);
|
||||
|
||||
/* Delete the transaction */
|
||||
freeTransaction (trans);
|
||||
|
@ -108,6 +108,13 @@ dateCB( Widget mw, XtPointer cd, XtPointer cb )
|
||||
cbs->doit = False;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x0:
|
||||
/* if delete key (for example) is hit, then input string */
|
||||
/* will be an empty string. In such a case, allow the input */
|
||||
cbs->doit = True;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* only accept the input if it is a number */
|
||||
cbs->doit = isNum(input);
|
||||
|
Loading…
Reference in New Issue
Block a user