From c7263cb8a757b60f1b5e4292445c3e83e3cf5f38 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Thu, 4 Dec 1997 08:15:13 +0000 Subject: [PATCH] solve a date-ordering related bug git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@266 57a11ea4-9604-0410-9ed3-97b8803252fd --- src/Account.c | 10 +++--- src/Transaction.c | 81 +++++++++++++++++++++++++++++++++++++++++++---- src/date.c | 7 ++++ 3 files changed, 86 insertions(+), 12 deletions(-) diff --git a/src/Account.c b/src/Account.c index 6ebeb0c903..e915a5f31f 100644 --- a/src/Account.c +++ b/src/Account.c @@ -29,6 +29,7 @@ #include "Data.h" #include "date.h" #include "main.h" +#include "Transaction.h" #include "util.h" int next_free_unique_account_id = 0; @@ -264,7 +265,6 @@ insertTransaction( Account *acc, Transaction *trans ) { int position=-1; int i,j; - Date *dj,*dt; int inserted = False; Transaction **oldTrans; @@ -319,7 +319,6 @@ insertTransaction( Account *acc, Transaction *trans ) * the new transaction before the first transaction of the same * or later date. The !inserted bit is a bit of a kludge to * make sure we only insert the new transaction once! */ - dt = &(trans->date); for( i=0,j=0; inumTrans; i++,j++ ) { /* if we didn't do this, and we needed to insert into the @@ -333,8 +332,7 @@ insertTransaction( Account *acc, Transaction *trans ) } else { - dj = &(oldTrans[j]->date); - if( (datecmp(dj,dt) > 0) && !inserted ) + if( (xaccTransOrder (&(oldTrans[j]),&trans) > 0) && !inserted ) { position = i; acc->transaction[i] = trans; @@ -642,10 +640,10 @@ xaccCheckDateOrder (Account * acc, Transaction *trans ) /* figure out if the transactions are out of order */ if (NULL != prevTrans) { - if( datecmp(&(prevTrans->date),&(trans->date))>0 ) outOfOrder = True; + if( xaccTransOrder (&prevTrans, &trans) >0 ) outOfOrder = True; } if (NULL != nextTrans) { - if( datecmp(&(trans->date),&(nextTrans->date))>0 ) outOfOrder = True; + if( xaccTransOrder (&trans, &nextTrans) >0 ) outOfOrder = True; } /* take care of re-ordering, if necessary */ diff --git a/src/Transaction.c b/src/Transaction.c index a77a7246a1..25ab240c82 100644 --- a/src/Transaction.c +++ b/src/Transaction.c @@ -126,7 +126,20 @@ freeTransaction( Transaction *trans ) * * returns a negative value if transaction a is dated earlier than b, * returns a positive value if transaction a is dated later than b, - * returns zero if both transactions are on the same date. + * + * This function tries very hard to uniquely order all transactions. + * If two transactions occur on the same date, then thier "num" fields + * are compared. If the num fileds are identical, then the description + * fileds are compared. If these are identical, then the memo fileds + * are compared. Hopefully, there will not be any transactions that + * occur on the same day that have all three of these values identical. + * + * Note that being able to establish this kind of absolute order is + * important for some of the ledger display functions. In particular, + * grep for "running_balance" in the code, and see the notes there. + * + * Yes, this kindof code dependency is ugly, but the alternatives seem + * ugly too. * \********************************************************************/ @@ -136,19 +149,75 @@ xaccTransOrder (Transaction **ta, Transaction **tb) int retval; char *da, *db; - retval = datecmp (&((*ta)->date), &((*tb)->date)); + if ( (*ta) && !(*tb) ) return -1; + if ( !(*ta) && (*tb) ) return +1; + if ( !(*ta) && !(*tb) ) return 0; /* if dates differ, return */ + retval = datecmp (&((*ta)->date), &((*tb)->date)); if (retval) return retval; + /* otherwise, sort on transaction strings */ + da = (*ta)->num; + db = (*tb)->num; + if (da && db) { + retval = strcmp (da, db); + /* if strings differ, return */ + if (retval) return retval; + } else + if (!da && db) { + return -1; + } else + if (da && !db) { + return +1; + } + /* otherwise, sort on transaction strings */ da = (*ta)->description; db = (*tb)->description; - if (!da) return -1; - if (!db) return +1; + if (da && db) { + retval = strcmp (da, db); + /* if strings differ, return */ + if (retval) return retval; + } else + if (!da && db) { + return -1; + } else + if (da && !db) { + return +1; + } - retval = strcmp (da, db); - return retval; + /* otherwise, sort on transaction strings */ + da = (*ta)->memo; + db = (*tb)->memo; + if (da && db) { + retval = strcmp (da, db); + /* if strings differ, return */ + if (retval) return retval; + } else + if (!da && db) { + return -1; + } else + if (da && !db) { + return +1; + } + + /* otherwise, sort on transaction strings */ + da = (*ta)->action; + db = (*tb)->action; + if (da && db) { + retval = strcmp (da, db); + /* if strings differ, return */ + if (retval) return retval; + } else + if (!da && db) { + return -1; + } else + if (da && !db) { + return +1; + } + + return 0; } /********************************************************************\ diff --git a/src/date.c b/src/date.c index 851f788dd4..6f510b1d31 100644 --- a/src/date.c +++ b/src/date.c @@ -159,6 +159,10 @@ daysInMonth( int month ) /********************************************************************\ * datecmp * * compares date1 and date2 * + * If you tink you need this function, you probably don't. * + * You should probably use xaccTransOrder instead. Some * + * if the algorithms used here depend on the superior ordering * + * that xaccTransOrder provides. * * * * Args: date1 - the first date to look at * * date2 - the second date in the comparison * @@ -184,3 +188,6 @@ datecmp( Date *date1, Date *date2 ) return 1; } } + +/********************** END OF FILE *********************************\ +\********************************************************************/