mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
conversion of FileIO to use splits
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@388 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
934ed5efa3
commit
612dad2706
562
src/FileIO.c
562
src/FileIO.c
@ -37,6 +37,8 @@
|
|||||||
* *
|
* *
|
||||||
* Version 4 of the file format adds account groups *
|
* Version 4 of the file format adds account groups *
|
||||||
* *
|
* *
|
||||||
|
* Version 5 of the file format adds splits *
|
||||||
|
* *
|
||||||
* *
|
* *
|
||||||
* the format of the data in the file: *
|
* the format of the data in the file: *
|
||||||
* file ::== token Group *
|
* file ::== token Group *
|
||||||
@ -44,9 +46,10 @@
|
|||||||
* Account ::== accID flags type accountName description *
|
* Account ::== accID flags type accountName description *
|
||||||
* notes numTran (Transaction)^numTrans *
|
* notes numTran (Transaction)^numTrans *
|
||||||
* numGroups (Group)^numGroups *
|
* numGroups (Group)^numGroups *
|
||||||
* Transaction ::== num date description memo catagory reconciled *
|
* Transaction ::== num date description credit_split *
|
||||||
* amount share_price *
|
* numSplits (Split)^numSplits *
|
||||||
* credit_account debit_account *
|
* Split ::== memo action reconciled *
|
||||||
|
* amount share_price account *
|
||||||
* token ::== int [the version of file format == VERSION] *
|
* token ::== int [the version of file format == VERSION] *
|
||||||
* numTrans ::== int *
|
* numTrans ::== int *
|
||||||
* numAccounts ::== int *
|
* numAccounts ::== int *
|
||||||
@ -62,12 +65,10 @@
|
|||||||
* description ::== String *
|
* description ::== String *
|
||||||
* memo ::== String *
|
* memo ::== String *
|
||||||
* action ::== String *
|
* action ::== String *
|
||||||
* catagory ::== int (obsolete) *
|
|
||||||
* reconciled ::== char *
|
* reconciled ::== char *
|
||||||
* amount ::== double *
|
* amount ::== double *
|
||||||
* share_price ::== double *
|
* share_price ::== double *
|
||||||
* credit_account ::= int *
|
* account ::= int *
|
||||||
* debit_account ::= int *
|
|
||||||
* String ::== size (char)^size *
|
* String ::== size (char)^size *
|
||||||
* size ::== int *
|
* size ::== int *
|
||||||
* Date ::== year month day *
|
* Date ::== year month day *
|
||||||
@ -107,12 +108,14 @@ static Account *springAccount (int acc_id);
|
|||||||
static AccountGroup *readGroup( int fd, Account *, int token );
|
static AccountGroup *readGroup( int fd, Account *, int token );
|
||||||
static Account *readAccount( int fd, AccountGroup *, int token );
|
static Account *readAccount( int fd, AccountGroup *, int token );
|
||||||
static Transaction *readTransaction( int fd, Account *, int token );
|
static Transaction *readTransaction( int fd, Account *, int token );
|
||||||
|
static Split *readSplit( int fd, int token );
|
||||||
static char *readString( int fd, int token );
|
static char *readString( int fd, int token );
|
||||||
static Date *readDate( int fd, int token );
|
static Date *readDate( int fd, int token );
|
||||||
|
|
||||||
static int writeGroup( int fd, AccountGroup *grp );
|
static int writeGroup( int fd, AccountGroup *grp );
|
||||||
static int writeAccount( int fd, Account *account );
|
static int writeAccount( int fd, Account *account );
|
||||||
static int writeTransaction( int fd, Transaction *trans );
|
static int writeTransaction( int fd, Transaction *trans );
|
||||||
|
static int writeSplit( int fd, Split *split);
|
||||||
static int writeString( int fd, char *str );
|
static int writeString( int fd, char *str );
|
||||||
static int writeDate( int fd, Date *date );
|
static int writeDate( int fd, Date *date );
|
||||||
|
|
||||||
@ -481,17 +484,18 @@ readTransaction( int fd, Account *acc, int token )
|
|||||||
{
|
{
|
||||||
int err=0;
|
int err=0;
|
||||||
int acc_id;
|
int acc_id;
|
||||||
|
int i;
|
||||||
Date *date;
|
Date *date;
|
||||||
int dummy_category;
|
int dummy_category;
|
||||||
|
int numSplits;
|
||||||
Transaction *trans = 0x0;
|
Transaction *trans = 0x0;
|
||||||
Split *split;
|
|
||||||
char *tmp;
|
char *tmp;
|
||||||
char recn;
|
char recn;
|
||||||
|
double num_shares = 0.0;
|
||||||
|
double share_price = 0.0;
|
||||||
|
|
||||||
/* create a transaction structure with at least one split */
|
/* create a transaction structure */
|
||||||
trans = mallocTransaction();
|
trans = mallocTransaction();
|
||||||
split = xaccMallocSplit();
|
|
||||||
xaccAppendSplit (trans, split);
|
|
||||||
|
|
||||||
ENTER ("readTransaction");
|
ENTER ("readTransaction");
|
||||||
|
|
||||||
@ -521,152 +525,309 @@ readTransaction( int fd, Account *acc, int token )
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* At version 5, most of the transaction stuff was
|
||||||
|
* moved to splits. Thus, vast majority of stuff below
|
||||||
|
* is skipped
|
||||||
|
*/
|
||||||
|
if (4 >= token) {
|
||||||
|
tmp = readString( fd, token );
|
||||||
|
if( NULL == tmp )
|
||||||
|
{
|
||||||
|
PERR ("Premature end of Transaction at memo");
|
||||||
|
freeTransaction(trans);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
xaccTransSetMemo (trans, tmp);
|
||||||
|
XtFree (tmp);
|
||||||
|
|
||||||
|
/* action first introduced in version 3 of the file format */
|
||||||
|
if (3 <= token) {
|
||||||
|
tmp = readString( fd, token );
|
||||||
|
if( tmp == NULL )
|
||||||
|
{
|
||||||
|
PERR ("Premature end of Transaction at action");
|
||||||
|
freeTransaction(trans);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
xaccTransSetAction (trans, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* category is now obsolete */
|
||||||
|
err = read( fd, &(dummy_category), sizeof(int) );
|
||||||
|
if( err != sizeof(int) )
|
||||||
|
{
|
||||||
|
PERR ("Premature end of Transaction at catagory");
|
||||||
|
freeTransaction(trans);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = read( fd, &recn, sizeof(char) );
|
||||||
|
if( err != sizeof(char) )
|
||||||
|
{
|
||||||
|
PERR ("Premature end of Transaction at reconciled");
|
||||||
|
freeTransaction(trans);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
xaccTransSetReconcile (trans, recn);
|
||||||
|
|
||||||
|
if( 1 >= token ) {
|
||||||
|
/* Note: this is for version 0 of file format only.
|
||||||
|
* What used to be reconciled, is now cleared... transactions
|
||||||
|
* aren't reconciled until you get your bank statement, and
|
||||||
|
* use the reconcile window to mark the transaction reconciled
|
||||||
|
*/
|
||||||
|
if( YREC == trans->credit_split.reconciled == YREC ) {
|
||||||
|
xaccTransSetReconcile (trans, CREC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* make sure the value of trans->reconciled is valid...
|
||||||
|
* I have to do this mainly for if I change what NREC and
|
||||||
|
* YREC are defined to be... this way it might loose all
|
||||||
|
* the reconciled data, but at least the field is valid */
|
||||||
|
if( (YREC != trans->credit_split.reconciled) &&
|
||||||
|
(FREC != trans->credit_split.reconciled) &&
|
||||||
|
(CREC != trans->credit_split.reconciled) ) {
|
||||||
|
xaccTransSetReconcile (trans, NREC);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Version 1 files stored the amount as an integer,
|
||||||
|
* with the amount recorded as pennies.
|
||||||
|
* Version 2 and above store the share amounts and
|
||||||
|
* prices as doubles. */
|
||||||
|
if (1 == token) {
|
||||||
|
int amount;
|
||||||
|
err = read( fd, &amount, sizeof(int) );
|
||||||
|
if( err != sizeof(int) )
|
||||||
|
{
|
||||||
|
PERR ("Premature end of Transaction at V1 amount");
|
||||||
|
freeTransaction(trans);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
XACC_FLIP_INT (amount);
|
||||||
|
num_shares = 0.01 * ((double) amount); /* file stores pennies */
|
||||||
|
trans->credit_split.damount = num_shares;
|
||||||
|
} else {
|
||||||
|
double damount;
|
||||||
|
|
||||||
|
/* first, read number of shares ... */
|
||||||
|
err = read( fd, &damount, sizeof(double) );
|
||||||
|
if( err != sizeof(double) )
|
||||||
|
{
|
||||||
|
PERR ("Premature end of Transaction at amount");
|
||||||
|
freeTransaction(trans);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
XACC_FLIP_DOUBLE (damount);
|
||||||
|
num_shares = damount;
|
||||||
|
trans->credit_split.damount = num_shares;
|
||||||
|
|
||||||
|
/* ... next read the share price ... */
|
||||||
|
err = read( fd, &damount, sizeof(double) );
|
||||||
|
if( err != sizeof(double) )
|
||||||
|
{
|
||||||
|
PERR ("Premature end of Transaction at share_price");
|
||||||
|
freeTransaction(trans);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
XACC_FLIP_DOUBLE (damount);
|
||||||
|
share_price = damount;
|
||||||
|
trans->credit_split.share_price = share_price;
|
||||||
|
}
|
||||||
|
|
||||||
|
INFO_2 ("readTransaction(): num_shares %f \n", num_shares);
|
||||||
|
|
||||||
|
/* Read the account numbers for double-entry */
|
||||||
|
/* These are first used in Version 2 of the file format */
|
||||||
|
if (1 < token) {
|
||||||
|
Account *peer_acc;
|
||||||
|
/* first, read the credit account number */
|
||||||
|
err = read( fd, &acc_id, sizeof(int) );
|
||||||
|
if( err != sizeof(int) )
|
||||||
|
{
|
||||||
|
PERR ("Premature end of Transaction at credit");
|
||||||
|
freeTransaction(trans);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
XACC_FLIP_INT (acc_id);
|
||||||
|
INFO_2 ("readTransaction(): credit %d\n", acc_id);
|
||||||
|
peer_acc = locateAccount (acc_id);
|
||||||
|
trans -> credit_split.acc = (struct _account *) peer_acc;
|
||||||
|
|
||||||
|
/* insert the split part of the transaction into
|
||||||
|
* the credited account */
|
||||||
|
if (peer_acc) xaccInsertSplit( peer_acc, &(trans->credit_split) );
|
||||||
|
|
||||||
|
/* next read the debit account number */
|
||||||
|
err = read( fd, &acc_id, sizeof(int) );
|
||||||
|
if( err != sizeof(int) )
|
||||||
|
{
|
||||||
|
PERR ("Premature end of Transaction at debit");
|
||||||
|
freeTransaction(trans);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
XACC_FLIP_INT (acc_id);
|
||||||
|
INFO_2 ("readTransaction(): debit %d\n", acc_id);
|
||||||
|
peer_acc = locateAccount (acc_id);
|
||||||
|
if (peer_acc) {
|
||||||
|
Split *split;
|
||||||
|
split = xaccMallocSplit ();
|
||||||
|
xaccAppendSplit (trans, split);
|
||||||
|
split -> acc = (struct _account *) peer_acc;
|
||||||
|
xaccInsertSplit (peer_acc, split);
|
||||||
|
split->damount = -num_shares;
|
||||||
|
split->share_price = share_price;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* Version 1 files did not do double-entry */
|
||||||
|
xaccInsertSplit( acc, &(trans->credit_split) );
|
||||||
|
}
|
||||||
|
} else { /* else, read version-5 files */
|
||||||
|
Split *split;
|
||||||
|
|
||||||
|
/* first, read the credit split, and copy it in place */
|
||||||
|
split = readSplit (fd, token);
|
||||||
|
xaccSplitSetMemo ( &(trans->credit_split), split->memo);
|
||||||
|
xaccSplitSetAction ( &(trans->credit_split), split->action);
|
||||||
|
xaccSplitSetReconcile ( &(trans->credit_split), split->reconciled);
|
||||||
|
trans->credit_split.damount = split->damount;
|
||||||
|
trans->credit_split.share_price = split->share_price;
|
||||||
|
trans->credit_split.acc = split->acc;
|
||||||
|
trans->credit_split.parent = trans;
|
||||||
|
|
||||||
|
/* then wire it into place */
|
||||||
|
xaccInsertSplit( ((Account *) (trans->credit_split.acc)), &(trans->credit_split) );
|
||||||
|
|
||||||
|
/* free the thing that the read returned */
|
||||||
|
split->acc = NULL;
|
||||||
|
split->parent = NULL;
|
||||||
|
xaccFreeSplit (split);
|
||||||
|
|
||||||
|
/* read number of splits */
|
||||||
|
err = read( fd, &(numSplits), sizeof(int) );
|
||||||
|
if( err != sizeof(int) )
|
||||||
|
{
|
||||||
|
PERR ("Premature end of Transaction at num-splits");
|
||||||
|
freeTransaction(trans);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
XACC_FLIP_INT (numSplits);
|
||||||
|
|
||||||
|
for (i=0; i<numSplits; i++) {
|
||||||
|
split = readSplit (fd, token);
|
||||||
|
split->parent = trans;
|
||||||
|
xaccAppendSplit( trans, split);
|
||||||
|
xaccInsertSplit( ((Account *) (split->acc)), split);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return trans;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************\
|
||||||
|
* readSplit *
|
||||||
|
* reads in the data for a split from the datafile *
|
||||||
|
* *
|
||||||
|
* Args: fd - the filedescriptor of the data file *
|
||||||
|
* token - the datafile version *
|
||||||
|
* Return: the transaction structure *
|
||||||
|
\********************************************************************/
|
||||||
|
|
||||||
|
static Split *
|
||||||
|
readSplit ( int fd, int token )
|
||||||
|
{
|
||||||
|
Account *peer_acc;
|
||||||
|
Split *split;
|
||||||
|
int err=0;
|
||||||
|
int acc_id;
|
||||||
|
char *tmp;
|
||||||
|
char recn;
|
||||||
|
double damount;
|
||||||
|
|
||||||
|
/* create a split structure */
|
||||||
|
split = xaccMallocSplit();
|
||||||
|
|
||||||
|
ENTER ("readSplit");
|
||||||
|
|
||||||
tmp = readString( fd, token );
|
tmp = readString( fd, token );
|
||||||
if( NULL == tmp )
|
if( NULL == tmp )
|
||||||
{
|
{
|
||||||
PERR ("Premature end of Transaction at memo");
|
PERR ("Premature end of Split at memo");
|
||||||
freeTransaction(trans);
|
xaccFreeSplit(split);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
xaccTransSetMemo (trans, tmp);
|
xaccSplitSetMemo (split, tmp);
|
||||||
XtFree (tmp);
|
XtFree (tmp);
|
||||||
|
|
||||||
/* action first introduced in version 3 of the file format */
|
tmp = readString( fd, token );
|
||||||
if (3 <= token) {
|
if( tmp == NULL )
|
||||||
trans->action = readString( fd, token );
|
|
||||||
if( trans->action == NULL )
|
|
||||||
{
|
|
||||||
PERR ("Premature end of Transaction at memo");
|
|
||||||
freeTransaction(trans);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* category is now obsolete */
|
|
||||||
err = read( fd, &(dummy_category), sizeof(int) );
|
|
||||||
if( err != sizeof(int) )
|
|
||||||
{
|
{
|
||||||
PERR ("Premature end of Transaction at catagory");
|
PERR ("Premature end of Split at action");
|
||||||
freeTransaction(trans);
|
xaccFreeSplit (split);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
xaccSplitSetAction (split, tmp);
|
||||||
|
|
||||||
err = read( fd, &recn, sizeof(char) );
|
err = read( fd, &recn, sizeof(char) );
|
||||||
if( err != sizeof(char) )
|
if( err != sizeof(char) )
|
||||||
{
|
{
|
||||||
PERR ("Premature end of Transaction at reconciled");
|
PERR ("Premature end of Split at reconciled");
|
||||||
freeTransaction(trans);
|
xaccFreeSplit (split);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
xaccTransSetReconcile (trans, recn);
|
xaccSplitSetReconcile (split, recn);
|
||||||
|
|
||||||
if( 1 >= token ) {
|
/* make sure the value of split->reconciled is valid...
|
||||||
/* Note: this is for version 0 of file format only.
|
* Do this mainly in case we change what NREC and
|
||||||
* What used to be reconciled, is now cleared... transactions
|
|
||||||
* aren't reconciled until you get your bank statement, and
|
|
||||||
* use the reconcile window to mark the transaction reconciled
|
|
||||||
*/
|
|
||||||
if( YREC == trans->credit_split.reconciled == YREC ) {
|
|
||||||
xaccTransSetReconcile (trans, CREC);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* make sure the value of trans->reconciled is valid...
|
|
||||||
* I have to do this mainly for if I change what NREC and
|
|
||||||
* YREC are defined to be... this way it might loose all
|
* YREC are defined to be... this way it might loose all
|
||||||
* the reconciled data, but at least the field is valid */
|
* the reconciled data, but at least the field is valid */
|
||||||
if( (YREC != trans->credit_split.reconciled) &&
|
if( (YREC != split->reconciled) &&
|
||||||
(CREC != trans->credit_split.reconciled) ) {
|
(FREC != split->reconciled) &&
|
||||||
xaccTransSetReconcile (trans, NREC);
|
(CREC != split->reconciled) ) {
|
||||||
|
xaccSplitSetReconcile (split, NREC);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Version 1 files stored the amount as an integer,
|
|
||||||
* with the amount recorded as pennies.
|
|
||||||
* Version 2 and above store the share amounts and
|
|
||||||
* prices as doubles. */
|
|
||||||
if (1 == token) {
|
|
||||||
int amount;
|
|
||||||
err = read( fd, &amount, sizeof(int) );
|
|
||||||
if( err != sizeof(int) )
|
|
||||||
{
|
|
||||||
PERR ("Premature end of Transaction at V1 amount");
|
|
||||||
freeTransaction(trans);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
XACC_FLIP_INT (amount);
|
|
||||||
split->damount = 0.01 * ((double) amount); /* file stores pennies */
|
|
||||||
} else {
|
|
||||||
double damount;
|
|
||||||
|
|
||||||
/* first, read number of shares ... */
|
/* first, read number of shares ... */
|
||||||
err = read( fd, &damount, sizeof(double) );
|
err = read( fd, &damount, sizeof(double) );
|
||||||
if( err != sizeof(double) )
|
if( err != sizeof(double) )
|
||||||
{
|
{
|
||||||
PERR ("Premature end of Transaction at amount");
|
PERR ("Premature end of Split at amount");
|
||||||
freeTransaction(trans);
|
xaccFreeSplit (split);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
XACC_FLIP_DOUBLE (damount);
|
XACC_FLIP_DOUBLE (damount);
|
||||||
split->damount = damount;
|
split -> damount = damount;
|
||||||
|
|
||||||
/* ... next read the share price ... */
|
/* ... next read the share price ... */
|
||||||
err = read( fd, &damount, sizeof(double) );
|
err = read( fd, &damount, sizeof(double) );
|
||||||
if( err != sizeof(double) )
|
if( err != sizeof(double) )
|
||||||
{
|
{
|
||||||
PERR ("Premature end of Transaction at share_price");
|
PERR ("Premature end of Split at share_price");
|
||||||
freeTransaction(trans);
|
xaccFreeSplit (split);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
XACC_FLIP_DOUBLE (damount);
|
XACC_FLIP_DOUBLE (damount);
|
||||||
split->share_price = damount;
|
split->share_price = damount;
|
||||||
}
|
|
||||||
|
|
||||||
INFO_2 ("readTransaction(): amount %f \n", trans->damount);
|
INFO_2 ("readSplit(): num_shares %f \n", damount);
|
||||||
|
|
||||||
/* Read the account numbers for double-entry */
|
/* Read the account number */
|
||||||
/* These are first used in Version 2 of the file format */
|
|
||||||
if (1 < token) {
|
|
||||||
Account *peer_acc;
|
|
||||||
/* first, read the credit account number */
|
|
||||||
err = read( fd, &acc_id, sizeof(int) );
|
|
||||||
if( err != sizeof(int) )
|
|
||||||
{
|
|
||||||
PERR ("Premature end of Transaction at credit");
|
|
||||||
freeTransaction(trans);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
XACC_FLIP_INT (acc_id);
|
|
||||||
INFO_2 ("readTransaction(): credit %d\n", acc_id);
|
|
||||||
peer_acc = locateAccount (acc_id);
|
|
||||||
trans -> credit_split.acc = (struct _account *) peer_acc;
|
|
||||||
|
|
||||||
/* insert the transaction into both the debit and
|
err = read( fd, &acc_id, sizeof(int) );
|
||||||
* the credit accounts; first the credit ... */
|
if( err != sizeof(int) )
|
||||||
if (peer_acc) insertTransaction( peer_acc, trans );
|
{
|
||||||
|
PERR ("Premature end of Split at account");
|
||||||
|
xaccFreeSplit (split);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
XACC_FLIP_INT (acc_id);
|
||||||
|
INFO_2 ("readSplit(): account id %d\n", acc_id);
|
||||||
|
peer_acc = locateAccount (acc_id);
|
||||||
|
split -> acc = (struct _account *) peer_acc;
|
||||||
|
|
||||||
/* next read the debit account number */
|
return split;
|
||||||
err = read( fd, &acc_id, sizeof(int) );
|
|
||||||
if( err != sizeof(int) )
|
|
||||||
{
|
|
||||||
PERR ("Premature end of Transaction at debit");
|
|
||||||
freeTransaction(trans);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
XACC_FLIP_INT (acc_id);
|
|
||||||
INFO_2 ("readTransaction(): debit %d\n", acc_id);
|
|
||||||
peer_acc = locateAccount (acc_id);
|
|
||||||
split -> acc = (struct _account *) peer_acc;
|
|
||||||
|
|
||||||
/* insert the transaction into both the debit and
|
|
||||||
* the credit accounts; next, the debit ... */
|
|
||||||
if (peer_acc) insertTransaction( peer_acc, trans );
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* Version 1 files did not do double-entry */
|
|
||||||
insertTransaction( acc, trans );
|
|
||||||
}
|
|
||||||
|
|
||||||
return trans;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************\
|
/********************************************************************\
|
||||||
@ -775,7 +936,9 @@ xaccResetWriteFlags (AccountGroup *grp)
|
|||||||
s = acc->splits[0];
|
s = acc->splits[0];
|
||||||
n=0;
|
n=0;
|
||||||
while (s) {
|
while (s) {
|
||||||
s -> write_flag = 0;
|
Transaction *trans;
|
||||||
|
trans = s->parent;
|
||||||
|
if (trans) trans -> write_flag = 0;
|
||||||
n++;
|
n++;
|
||||||
s = acc->splits[n];
|
s = acc->splits[n];
|
||||||
}
|
}
|
||||||
@ -880,6 +1043,7 @@ static int
|
|||||||
writeAccount( int fd, Account *acc )
|
writeAccount( int fd, Account *acc )
|
||||||
{
|
{
|
||||||
Transaction *trans;
|
Transaction *trans;
|
||||||
|
Split *s;
|
||||||
int err=0;
|
int err=0;
|
||||||
int i, numUnwrittenTrans, ntrans;
|
int i, numUnwrittenTrans, ntrans;
|
||||||
int acc_id;
|
int acc_id;
|
||||||
@ -918,13 +1082,24 @@ writeAccount( int fd, Account *acc )
|
|||||||
/* figure out numTrans -- it will be less than the total
|
/* figure out numTrans -- it will be less than the total
|
||||||
* number of transactions in this account, because some
|
* number of transactions in this account, because some
|
||||||
* of the double entry transactions will already have been
|
* of the double entry transactions will already have been
|
||||||
* written. */
|
* written. write_flag values are:
|
||||||
|
* 0 == uncounted, unwritten
|
||||||
|
* 1 == counted, unwritten
|
||||||
|
* 2 == written
|
||||||
|
*/
|
||||||
numUnwrittenTrans = 0;
|
numUnwrittenTrans = 0;
|
||||||
for( i=0; i<acc->numTrans; i++ ) {
|
i=0;
|
||||||
trans = getTransaction(acc,i);
|
s = acc->splits[i];
|
||||||
if (0 == trans->credit_split.write_flag) numUnwrittenTrans ++;
|
while (s) {
|
||||||
|
trans = s->parent;
|
||||||
|
if (0 == trans->write_flag) {
|
||||||
|
numUnwrittenTrans ++;
|
||||||
|
trans->write_flag = 1;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
s = acc->splits[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
ntrans = numUnwrittenTrans;
|
ntrans = numUnwrittenTrans;
|
||||||
XACC_FLIP_INT (ntrans);
|
XACC_FLIP_INT (ntrans);
|
||||||
err = write( fd, &ntrans, sizeof(int) );
|
err = write( fd, &ntrans, sizeof(int) );
|
||||||
@ -932,12 +1107,16 @@ writeAccount( int fd, Account *acc )
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
INFO_2 ("writeAccount(): will write %d trans\n", numUnwrittenTrans);
|
INFO_2 ("writeAccount(): will write %d trans\n", numUnwrittenTrans);
|
||||||
for( i=0; i<acc->numTrans; i++ ) {
|
i=0;
|
||||||
trans = getTransaction(acc,i);
|
s = acc->splits[i];
|
||||||
if (0 == trans->credit_split.write_flag) {
|
while (s) {
|
||||||
|
trans = s->parent;
|
||||||
|
if (1 == trans->write_flag) {
|
||||||
err = writeTransaction( fd, trans );
|
err = writeTransaction( fd, trans );
|
||||||
|
if (-1 == err) return err;
|
||||||
}
|
}
|
||||||
if( -1 == err ) return err;
|
i++;
|
||||||
|
s = acc->splits[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (acc->children) {
|
if (acc->children) {
|
||||||
@ -948,8 +1127,7 @@ writeAccount( int fd, Account *acc )
|
|||||||
|
|
||||||
XACC_FLIP_INT (numChildren);
|
XACC_FLIP_INT (numChildren);
|
||||||
err = write( fd, &numChildren, sizeof(int) );
|
err = write( fd, &numChildren, sizeof(int) );
|
||||||
if( err != sizeof(int) )
|
if( err != sizeof(int) ) return -1;
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (acc->children) {
|
if (acc->children) {
|
||||||
err = writeGroup (fd, acc->children);
|
err = writeGroup (fd, acc->children);
|
||||||
@ -963,89 +1141,113 @@ writeAccount( int fd, Account *acc )
|
|||||||
* saves the data for a transaction to the datafile *
|
* saves the data for a transaction to the datafile *
|
||||||
* *
|
* *
|
||||||
* Args: fd - the filedescriptor of the data file *
|
* Args: fd - the filedescriptor of the data file *
|
||||||
* acc - the account that the trans came from *
|
|
||||||
* trans - the transaction data to save *
|
* trans - the transaction data to save *
|
||||||
* Return: -1 on failure *
|
* Return: -1 on failure *
|
||||||
\********************************************************************/
|
\********************************************************************/
|
||||||
static int
|
static int
|
||||||
writeTransaction( int fd, Transaction *trans )
|
writeTransaction( int fd, Transaction *trans )
|
||||||
{
|
{
|
||||||
|
Split *s;
|
||||||
int err=0;
|
int err=0;
|
||||||
int tmp, acc_id;
|
int i=0;
|
||||||
double damount;
|
|
||||||
Account *xfer_acc;
|
|
||||||
|
|
||||||
ENTER ("writeTransaction");
|
ENTER ("writeTransaction");
|
||||||
/* If we've already written this transaction, don't write
|
/* If we've already written this transaction, don't write
|
||||||
* it again. That is, prevent double-entry transactions
|
* it again. That is, prevent double-entry transactions
|
||||||
* from being written twice
|
* from being written twice
|
||||||
*/
|
*/
|
||||||
if (trans->credit_split.write_flag) return 4;
|
if (2 == trans->write_flag) return 4;
|
||||||
trans->credit_split.write_flag = 1;
|
trans->write_flag = 2;
|
||||||
|
|
||||||
err = writeString( fd, trans->num );
|
err = writeString( fd, trans->num );
|
||||||
if( -1 == err )
|
if( -1 == err ) return err;
|
||||||
return err;
|
|
||||||
|
|
||||||
err = writeDate( fd, &(trans->date) );
|
err = writeDate( fd, &(trans->date) );
|
||||||
if( -1 == err )
|
if( -1 == err ) return err;
|
||||||
return err;
|
|
||||||
|
|
||||||
err = writeString( fd, trans->description );
|
err = writeString( fd, trans->description );
|
||||||
|
if( -1 == err ) return err;
|
||||||
|
|
||||||
|
err = writeSplit( fd, &(trans->credit_split) );
|
||||||
|
if( -1 == err ) return err;
|
||||||
|
|
||||||
|
/* count the number of splits */
|
||||||
|
i = 0;
|
||||||
|
s = trans->debit_splits[i];
|
||||||
|
while (s) {
|
||||||
|
i++;
|
||||||
|
s = trans->debit_splits[i];
|
||||||
|
}
|
||||||
|
XACC_FLIP_INT (i);
|
||||||
|
err = write( fd, &i, sizeof(int) );
|
||||||
|
if( err != sizeof(int) ) return -1;
|
||||||
|
|
||||||
|
/* now write the splits */
|
||||||
|
i = 0;
|
||||||
|
s = trans->debit_splits[i];
|
||||||
|
while (s) {
|
||||||
|
err = writeSplit (fd, s);
|
||||||
|
if( -1 == err ) return err;
|
||||||
|
i++;
|
||||||
|
s = trans->debit_splits[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************\
|
||||||
|
* writeSplit *
|
||||||
|
* saves the data for a split to the datafile *
|
||||||
|
* *
|
||||||
|
* Args: fd - the filedescriptor of the data file *
|
||||||
|
* split - the split data to save *
|
||||||
|
* Return: -1 on failure *
|
||||||
|
\********************************************************************/
|
||||||
|
static int
|
||||||
|
writeSplit ( int fd, Split *split )
|
||||||
|
{
|
||||||
|
int err=0;
|
||||||
|
int tmp, acc_id;
|
||||||
|
double damount;
|
||||||
|
Account *xfer_acc;
|
||||||
|
|
||||||
|
ENTER ("writeSplit");
|
||||||
|
|
||||||
|
err = writeString( fd, split->memo );
|
||||||
if( -1 == err )
|
if( -1 == err )
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
err = writeString( fd, trans->credit_split.memo );
|
err = writeString( fd, split->action );
|
||||||
if( -1 == err )
|
if( -1 == err )
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
err = writeString( fd, trans->action );
|
err = write( fd, &(split->reconciled), sizeof(char) );
|
||||||
if( -1 == err )
|
|
||||||
return err;
|
|
||||||
|
|
||||||
/* category is now obsolete */
|
|
||||||
tmp = 0;
|
|
||||||
XACC_FLIP_INT (tmp);
|
|
||||||
err = write( fd, &tmp, sizeof(int) );
|
|
||||||
if( err != sizeof(int) )
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
err = write( fd, &(trans->credit_split.reconciled), sizeof(char) );
|
|
||||||
if( err != sizeof(char) )
|
if( err != sizeof(char) )
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
damount = trans->damount;
|
damount = split->damount;
|
||||||
INFO_2 ("writeTransaction: amount=%f \n", damount);
|
INFO_2 ("writeSplit: amount=%f \n", damount);
|
||||||
XACC_FLIP_DOUBLE (damount);
|
XACC_FLIP_DOUBLE (damount);
|
||||||
err = write( fd, &damount, sizeof(double) );
|
err = write( fd, &damount, sizeof(double) );
|
||||||
if( err != sizeof(double) )
|
if( err != sizeof(double) )
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
damount = trans->share_price;
|
damount = split->share_price;
|
||||||
XACC_FLIP_DOUBLE (damount);
|
XACC_FLIP_DOUBLE (damount);
|
||||||
err = write( fd, &damount, sizeof(double) );
|
err = write( fd, &damount, sizeof(double) );
|
||||||
if( err != sizeof(double) )
|
if( err != sizeof(double) )
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* write the double-entry values */
|
/* write the credited/debted account */
|
||||||
xfer_acc = (Account *) (trans->credit_split.acc);
|
xfer_acc = (Account *) (split->acc);
|
||||||
acc_id = -1;
|
acc_id = -1;
|
||||||
if (xfer_acc) acc_id = xfer_acc -> id;
|
if (xfer_acc) acc_id = xfer_acc -> id;
|
||||||
INFO_2 ("writeTransaction: credit %d \n", acc_id);
|
INFO_2 ("writeSplit: credit %d \n", acc_id);
|
||||||
XACC_FLIP_INT (acc_id);
|
XACC_FLIP_INT (acc_id);
|
||||||
err = write( fd, &acc_id, sizeof(int) );
|
err = write( fd, &acc_id, sizeof(int) );
|
||||||
if( err != sizeof(int) )
|
if( err != sizeof(int) )
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
xfer_acc = (Account *) (trans->debit);
|
|
||||||
acc_id = -1;
|
|
||||||
if (xfer_acc) acc_id = xfer_acc -> id;
|
|
||||||
INFO_2 (" writeTransaction: debit %d \n", acc_id);
|
|
||||||
XACC_FLIP_INT (acc_id);
|
|
||||||
err = write( fd, &acc_id, sizeof(int) );
|
|
||||||
if( err != sizeof(int) )
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1421,9 +1421,8 @@ regSaveTransaction( RegWindow *regData, int position )
|
|||||||
String actn = NULL;
|
String actn = NULL;
|
||||||
DEBUG("MOD_ACTN\n");
|
DEBUG("MOD_ACTN\n");
|
||||||
/* ... the action ... */
|
/* ... the action ... */
|
||||||
XtFree( trans->action );
|
|
||||||
actn = XbaeMatrixGetCell(regData->reg,row+ACTN_CELL_R,ACTN_CELL_C);
|
actn = XbaeMatrixGetCell(regData->reg,row+ACTN_CELL_R,ACTN_CELL_C);
|
||||||
trans->action = XtNewString( actn );
|
xaccTransSetAction (trans, actn);
|
||||||
}
|
}
|
||||||
|
|
||||||
if( regData->changed & MOD_RECN )
|
if( regData->changed & MOD_RECN )
|
||||||
|
@ -164,24 +164,14 @@ initTransaction( Transaction * trans )
|
|||||||
{
|
{
|
||||||
|
|
||||||
/* fill in some sane defaults */
|
/* fill in some sane defaults */
|
||||||
trans->debit = 0x0;
|
|
||||||
|
|
||||||
trans->num = XtNewString("");
|
trans->num = XtNewString("");
|
||||||
trans->description = XtNewString("");
|
trans->description = XtNewString("");
|
||||||
trans->action = XtNewString("");
|
|
||||||
|
|
||||||
trans->debit_splits = (Split **) _malloc (sizeof (Split *));
|
trans->debit_splits = (Split **) _malloc (sizeof (Split *));
|
||||||
trans->debit_splits[0] = NULL;
|
trans->debit_splits[0] = NULL;
|
||||||
|
|
||||||
xaccInitSplit ( &(trans->credit_split));
|
xaccInitSplit ( &(trans->credit_split));
|
||||||
|
trans->credit_split->parent = trans;
|
||||||
trans->damount = 0.0;
|
|
||||||
trans->share_price = 1.0;
|
|
||||||
|
|
||||||
trans->credit_balance = 0.0;
|
|
||||||
trans->credit_cleared_balance = 0.0;
|
|
||||||
trans->debit_balance = 0.0;
|
|
||||||
trans->debit_cleared_balance = 0.0;
|
|
||||||
|
|
||||||
trans->date.year = 1900;
|
trans->date.year = 1900;
|
||||||
trans->date.month = 1;
|
trans->date.month = 1;
|
||||||
@ -219,19 +209,10 @@ implemented and tested.
|
|||||||
_free (trans->debit_splits);
|
_free (trans->debit_splits);
|
||||||
XtFree(trans->num);
|
XtFree(trans->num);
|
||||||
XtFree(trans->description);
|
XtFree(trans->description);
|
||||||
XtFree(trans->action);
|
|
||||||
|
|
||||||
/* just in case someone looks up freed memory ... */
|
/* just in case someone looks up freed memory ... */
|
||||||
trans->num = 0x0;
|
trans->num = 0x0;
|
||||||
trans->description = 0x0;
|
trans->description = 0x0;
|
||||||
trans->action = 0x0;
|
|
||||||
trans->damount = 0.0;
|
|
||||||
trans->share_price = 1.0;
|
|
||||||
|
|
||||||
trans->credit_balance = 0.0;
|
|
||||||
trans->credit_cleared_balance = 0.0;
|
|
||||||
trans->debit_balance = 0.0;
|
|
||||||
trans->debit_cleared_balance = 0.0;
|
|
||||||
|
|
||||||
trans->date.year = 1900;
|
trans->date.year = 1900;
|
||||||
trans->date.month = 1;
|
trans->date.month = 1;
|
||||||
@ -461,7 +442,6 @@ xaccTransSetDescription (Transaction *trans, char *desc)
|
|||||||
trans->description = XtNewString (desc);
|
trans->description = XtNewString (desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
xaccTransSetMemo (Transaction *trans, char *memo)
|
xaccTransSetMemo (Transaction *trans, char *memo)
|
||||||
{
|
{
|
||||||
@ -469,12 +449,41 @@ xaccTransSetMemo (Transaction *trans, char *memo)
|
|||||||
trans->credit_split.memo = XtNewString (memo);
|
trans->credit_split.memo = XtNewString (memo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xaccTransSetAction (Transaction *trans, char *actn)
|
||||||
|
{
|
||||||
|
if (trans->credit_split.action) XtFree (trans->credit_split.action);
|
||||||
|
trans->credit_split.action = XtNewString (actn);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
xaccTransSetReconcile (Transaction *trans, char recn)
|
xaccTransSetReconcile (Transaction *trans, char recn)
|
||||||
{
|
{
|
||||||
trans->credit_split.reconciled = recn;
|
trans->credit_split.reconciled = recn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/********************************************************************\
|
||||||
|
\********************************************************************/
|
||||||
|
|
||||||
|
void
|
||||||
|
xaccSplitSetMemo (Split *split, char *memo)
|
||||||
|
{
|
||||||
|
if (split->memo) XtFree (split->memo);
|
||||||
|
split->memo = XtNewString (memo);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xaccSplitSetAction (Split *split, char *actn)
|
||||||
|
{
|
||||||
|
if (split->action) XtFree (split->action);
|
||||||
|
split->action = XtNewString (actn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
xaccSplitSetReconcile (Split *split, char recn)
|
||||||
|
{
|
||||||
|
split->reconciled = recn;
|
||||||
|
}
|
||||||
|
|
||||||
/************************ END OF ************************************\
|
/************************ END OF ************************************\
|
||||||
\************************* FILE *************************************/
|
\************************* FILE *************************************/
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user