mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
merge in changes originally done in the mono-split branch
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@1064 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
f80203fc25
commit
a6c5c7cfea
@ -94,6 +94,7 @@
|
|||||||
#include "messages.h"
|
#include "messages.h"
|
||||||
#include "Transaction.h"
|
#include "Transaction.h"
|
||||||
#include "TransactionP.h"
|
#include "TransactionP.h"
|
||||||
|
#include "TransLog.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#define PERMS 0666
|
#define PERMS 0666
|
||||||
@ -242,6 +243,8 @@ xaccReadAccountGroup( char *datafile )
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* disable logging during load; otherwise its just a mess */
|
||||||
|
xaccLogDisable();
|
||||||
holder = xaccMallocAccountGroup();
|
holder = xaccMallocAccountGroup();
|
||||||
grp = readGroup (fd, NULL, token);
|
grp = readGroup (fd, NULL, token);
|
||||||
|
|
||||||
@ -267,6 +270,7 @@ xaccReadAccountGroup( char *datafile )
|
|||||||
|
|
||||||
maingrp = NULL;
|
maingrp = NULL;
|
||||||
|
|
||||||
|
xaccLogEnable();
|
||||||
close(fd);
|
close(fd);
|
||||||
return grp;
|
return grp;
|
||||||
}
|
}
|
||||||
@ -396,6 +400,20 @@ readAccount( int fd, AccountGroup *grp, int token )
|
|||||||
printf (" expected %d got %d transactions \n",numTrans,i);
|
printf (" expected %d got %d transactions \n",numTrans,i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#ifdef DELINT_BLANK_SPLITS_HACK
|
||||||
|
/* This is a dangerous hack, as it can destroy real data. */
|
||||||
|
{
|
||||||
|
int j=0;
|
||||||
|
Split *s = trans->splits[0];
|
||||||
|
while (s) {
|
||||||
|
if (DEQ(0.0,s->damount) && DEQ (1.0,s->share_price)) {
|
||||||
|
xaccTransRemoveSplit (trans, s);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
j++; s=trans->splits[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* DELINT_BLANK_SPLITS_HACK */
|
||||||
}
|
}
|
||||||
|
|
||||||
springAccount (acc->id);
|
springAccount (acc->id);
|
||||||
@ -558,6 +576,13 @@ readTransaction( int fd, Account *acc, int token )
|
|||||||
if (4 >= token)
|
if (4 >= token)
|
||||||
{
|
{
|
||||||
Split * s;
|
Split * s;
|
||||||
|
|
||||||
|
/* The code below really wants to assume that there are a pair
|
||||||
|
* of splits in every transaction, so make it so.
|
||||||
|
*/
|
||||||
|
s = xaccMallocSplit ();
|
||||||
|
xaccTransAppendSplit (trans, s);
|
||||||
|
|
||||||
tmp = readString( fd, token );
|
tmp = readString( fd, token );
|
||||||
if( NULL == tmp )
|
if( NULL == tmp )
|
||||||
{
|
{
|
||||||
@ -569,7 +594,8 @@ readTransaction( int fd, Account *acc, int token )
|
|||||||
free (tmp);
|
free (tmp);
|
||||||
|
|
||||||
/* action first introduced in version 3 of the file format */
|
/* action first introduced in version 3 of the file format */
|
||||||
if (3 <= token) {
|
if (3 <= token)
|
||||||
|
{
|
||||||
tmp = readString( fd, token );
|
tmp = readString( fd, token );
|
||||||
if( NULL == tmp )
|
if( NULL == tmp )
|
||||||
{
|
{
|
||||||
@ -741,8 +767,8 @@ readTransaction( int fd, Account *acc, int token )
|
|||||||
XACC_FLIP_INT (numSplits);
|
XACC_FLIP_INT (numSplits);
|
||||||
for (i=0; i<numSplits; i++) {
|
for (i=0; i<numSplits; i++) {
|
||||||
split = readSplit (fd, token);
|
split = readSplit (fd, token);
|
||||||
if (2 > i+offset) {
|
if (0 == i+offset) {
|
||||||
/* the first two splits have been malloced. just replace them */
|
/* the first split has been malloced. just replace it */
|
||||||
xaccFreeSplit (trans->splits[i+offset]);
|
xaccFreeSplit (trans->splits[i+offset]);
|
||||||
trans->splits[i+offset] = split;
|
trans->splits[i+offset] = split;
|
||||||
split->parent = trans;
|
split->parent = trans;
|
||||||
|
@ -35,14 +35,60 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The logfiles are useful for tracing, journalling.
|
* The logfiles are useful for tracing, journalling, error recovery.
|
||||||
* Note that the current support for journalling is at best
|
* Note that the current support for journalling is at best
|
||||||
* embryonic, at worst, sets the wrong expectations.
|
* embryonic, at worst, is dangerous by setting the wrong expectations.
|
||||||
*/
|
*/
|
||||||
int gen_logs = 1;
|
|
||||||
FILE * trans_log = 0x0;
|
|
||||||
FILE * split_log = 0x0;
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some design philosphy that I think would be good to keep in mind:
|
||||||
|
* (0) Simplicity and foolproofness are the over-riding design points.
|
||||||
|
* This is supposed to be a fail-safe safety net. We don't want
|
||||||
|
* our safety net to fail because of some whiz-bang shenanigans.
|
||||||
|
*
|
||||||
|
* (1) Try to keep the code simple. Want to make it simple and obvious
|
||||||
|
* that we are recording everything that we need to record.
|
||||||
|
*
|
||||||
|
* (2) Keep the printed format human readable, for the same reasons.
|
||||||
|
* (2.a) Keep the format, simple, flat, more or less unstructured,
|
||||||
|
* record oriented. This will help parsing by perl scripts.
|
||||||
|
* No, using a perl script to analyze a file that's supposed to be human
|
||||||
|
* readable is not a contradication in terms -- that's exactly the point.
|
||||||
|
* (2.b) Use tabs as a human freindly field separator; its also a character
|
||||||
|
* that does not (should not) appear naturally anywhere in the data,
|
||||||
|
* as it serves no formatting purpose in the current GUI design.
|
||||||
|
* (hack alert -- this is not currently tested for or enforced,
|
||||||
|
* so this is a very unsafe assumption. Maybe urlencoding should
|
||||||
|
* be used.)
|
||||||
|
* (2.c) Don't print redundant information in a single record. This would
|
||||||
|
* just confuse any potential user of this file.
|
||||||
|
* (2.d) Saving space, being compact is not a priority, I don't think.
|
||||||
|
*
|
||||||
|
* (3) There are no compatibility requirements from release to release.
|
||||||
|
* Sounds OK to me to change the format of the output when needed.
|
||||||
|
*
|
||||||
|
* (-) print transaction start and end delimiters
|
||||||
|
* (-) print a unique transaction id as a handy label for anyone
|
||||||
|
* who actually examines these logs.
|
||||||
|
* The C address pointer to the transaction struct should be fine,
|
||||||
|
* as it is simple and unique until the transaction is deleted ...
|
||||||
|
* and we log deletions, so that's OK. Just note that the id
|
||||||
|
* for a deleted transaction might be recycled.
|
||||||
|
* (-) print the current timestamp, so that if it is known that a bug
|
||||||
|
* occurred at a certain time, it can be located.
|
||||||
|
* (-) hack alert -- something better than just the account name
|
||||||
|
* is needed for identifying the account.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
static int gen_logs = 1;
|
||||||
|
static FILE * trans_log = 0x0;
|
||||||
|
|
||||||
|
/********************************************************************\
|
||||||
|
\********************************************************************/
|
||||||
|
|
||||||
|
void xaccLogDisable (void) { gen_logs = 0; }
|
||||||
|
void xaccLogEnable (void) { gen_logs = 1; }
|
||||||
|
|
||||||
/********************************************************************\
|
/********************************************************************\
|
||||||
\********************************************************************/
|
\********************************************************************/
|
||||||
@ -50,41 +96,29 @@ FILE * split_log = 0x0;
|
|||||||
void
|
void
|
||||||
xaccOpenLog (void)
|
xaccOpenLog (void)
|
||||||
{
|
{
|
||||||
|
char filename[1000];
|
||||||
char * timestamp;
|
char * timestamp;
|
||||||
|
|
||||||
if (!gen_logs) return;
|
if (!gen_logs) return;
|
||||||
if (trans_log && split_log) return;
|
if (trans_log) return;
|
||||||
|
|
||||||
/* tag each filename with a timestamp */
|
/* tag each filename with a timestamp */
|
||||||
timestamp = xaccDateUtilGetStampNow ();
|
timestamp = xaccDateUtilGetStampNow ();
|
||||||
|
|
||||||
if (!trans_log) {
|
strcpy (filename, "translog.");
|
||||||
char filename[1000];
|
strcat (filename, timestamp);
|
||||||
|
strcat (filename, ".log");
|
||||||
|
|
||||||
strcpy (filename, "translog.");
|
trans_log = fopen (filename, "a");
|
||||||
strcat (filename, timestamp);
|
|
||||||
strcat (filename, ".log");
|
|
||||||
|
|
||||||
trans_log = fopen (filename, "a");
|
/* use tab-separated fields */
|
||||||
|
fprintf (trans_log, "mod id time_now " \
|
||||||
|
"date_entered date_posted " \
|
||||||
|
"num description " \
|
||||||
|
"account memo action reconciled " \
|
||||||
|
"amount price date_reconciled\n");
|
||||||
|
fprintf (trans_log, "-----------------\n");
|
||||||
|
|
||||||
/* use tab-separated fields, to be /rdb compatible */
|
|
||||||
fprintf (trans_log, "num description\n");
|
|
||||||
fprintf (trans_log, "-----------------\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!split_log) {
|
|
||||||
char filename[1000];
|
|
||||||
|
|
||||||
strcpy (filename, "splitlog.");
|
|
||||||
strcat (filename, timestamp);
|
|
||||||
strcat (filename, ".log");
|
|
||||||
|
|
||||||
split_log = fopen (filename, "a");
|
|
||||||
|
|
||||||
/* use tab-separated fields, to be /rdb compatible */
|
|
||||||
fprintf (split_log, "num memo action reconciled amount price\n");
|
|
||||||
fprintf (split_log, "-----------------\n");
|
|
||||||
}
|
|
||||||
free (timestamp);
|
free (timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,34 +126,56 @@ xaccOpenLog (void)
|
|||||||
\********************************************************************/
|
\********************************************************************/
|
||||||
|
|
||||||
void
|
void
|
||||||
xaccTransWriteLog (Transaction *trans)
|
xaccTransWriteLog (Transaction *trans, char flag)
|
||||||
{
|
{
|
||||||
Split *split;
|
Split *split;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
char *dnow, *dent, *dpost, *drecn;
|
||||||
|
|
||||||
if (!gen_logs) return;
|
if (!gen_logs) return;
|
||||||
if (!trans_log || !split_log) return;
|
if (!trans_log) return;
|
||||||
|
|
||||||
/* use tab-separated fields, to be /rdb compatible */
|
dnow = xaccDateUtilGetStampNow ();
|
||||||
fprintf (trans_log, "%s %s\n", trans->num, trans->description);
|
dent = xaccDateUtilGetStamp (trans->date_entered.tv_sec);
|
||||||
|
dpost = xaccDateUtilGetStamp (trans->date_posted.tv_sec);
|
||||||
|
|
||||||
|
fprintf (trans_log, "===== START\n");
|
||||||
|
|
||||||
split = trans->splits[0];
|
split = trans->splits[0];
|
||||||
while (split) {
|
while (split) {
|
||||||
fprintf (split_log, "%s %s %s %c %10.6f %10.6f\n",
|
char * accname = "";
|
||||||
trans->num,
|
if (split->acc) accname = split->acc->description;
|
||||||
|
drecn = xaccDateUtilGetStamp (split->date_reconciled.tv_sec);
|
||||||
|
|
||||||
|
/* use tab-separated fields */
|
||||||
|
fprintf (trans_log, "%c %p %s %s %s %s %s " \
|
||||||
|
"%s %s %s %c %10.6f %10.6f %s\n",
|
||||||
|
flag,
|
||||||
|
trans,
|
||||||
|
dnow,
|
||||||
|
dent,
|
||||||
|
dpost,
|
||||||
|
trans->num,
|
||||||
|
trans->description,
|
||||||
|
accname,
|
||||||
split->memo,
|
split->memo,
|
||||||
split->action,
|
split->action,
|
||||||
split->reconciled,
|
split->reconciled,
|
||||||
split->damount,
|
split->damount,
|
||||||
split->share_price
|
split->share_price,
|
||||||
|
drecn
|
||||||
);
|
);
|
||||||
|
free (drecn);
|
||||||
i++;
|
i++;
|
||||||
split = trans->splits[i];
|
split = trans->splits[i];
|
||||||
}
|
}
|
||||||
|
fprintf (trans_log, "===== END\n");
|
||||||
|
free (dnow);
|
||||||
|
free (dent);
|
||||||
|
free (dpost);
|
||||||
|
|
||||||
/* get data out to the disk */
|
/* get data out to the disk */
|
||||||
fflush (trans_log);
|
fflush (trans_log);
|
||||||
fflush (split_log);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************\
|
/********************************************************************\
|
||||||
@ -127,6 +183,8 @@ xaccTransWriteLog (Transaction *trans)
|
|||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* open_memstream seems to give various distros fits
|
/* open_memstream seems to give various distros fits
|
||||||
|
* this has resulted in warfare on the mailing list.
|
||||||
|
* I think the truce called required changing this to asprintf
|
||||||
* this code is not currently used ... so its ifdef out
|
* this code is not currently used ... so its ifdef out
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -27,7 +27,9 @@
|
|||||||
#include "Transaction.h"
|
#include "Transaction.h"
|
||||||
|
|
||||||
void xaccOpenLog (void);
|
void xaccOpenLog (void);
|
||||||
void xaccTransWriteLog (Transaction *);
|
void xaccTransWriteLog (Transaction *, char);
|
||||||
|
void xaccLogEnable (void);
|
||||||
|
void xaccLogDisable (void);
|
||||||
|
|
||||||
/* returned strings will have been allocated with malloc, free with free() */
|
/* returned strings will have been allocated with malloc, free with free() */
|
||||||
char *xaccSplitAsString(Split *s, const char prefix[]);
|
char *xaccSplitAsString(Split *s, const char prefix[]);
|
||||||
|
@ -39,12 +39,21 @@
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the "force_double_entry" flag has a non-zero value,
|
* If the "force_double_entry" flag determines how
|
||||||
* then all transactions will be *forced* to balance.
|
* the splits in a transaction will be balanced.
|
||||||
* This will be forced even if it requires a new split
|
*
|
||||||
* to be created.
|
* The following values have significance:
|
||||||
|
* 0 -- anything goes
|
||||||
|
* 1 -- The sum of all splits in a transaction will be'
|
||||||
|
* forced to be zero, even if this requires the
|
||||||
|
* creation of additonal splits. Note that a split
|
||||||
|
* whose value is zero (e.g. a stock price) can exist
|
||||||
|
* by itself. Otherwise, all splits must come in at
|
||||||
|
* least pairs.
|
||||||
|
* 2 -- splits without oparents will be forced into a
|
||||||
|
* lost & found account. (Not implemented)
|
||||||
*/
|
*/
|
||||||
int force_double_entry = 0;
|
int force_double_entry = 1;
|
||||||
|
|
||||||
/********************************************************************\
|
/********************************************************************\
|
||||||
* Because I can't use C++ for this project, doesn't mean that I *
|
* Because I can't use C++ for this project, doesn't mean that I *
|
||||||
@ -190,11 +199,13 @@ printf ("SplitDestroy(): trans=%p, %d'th split=%p\n", trans, numsplits, s);
|
|||||||
xaccAccountRecomputeBalance (acc);
|
xaccAccountRecomputeBalance (acc);
|
||||||
|
|
||||||
s = trans->splits[1];
|
s = trans->splits[1];
|
||||||
acc = s->acc;
|
if (s) {
|
||||||
MARK_SPLIT (s);
|
acc = s->acc;
|
||||||
xaccAccountRemoveSplit (acc, s);
|
MARK_SPLIT (s);
|
||||||
xaccAccountRecomputeBalance (acc);
|
xaccAccountRemoveSplit (acc, s);
|
||||||
xaccFreeTransaction (trans);
|
xaccAccountRecomputeBalance (acc);
|
||||||
|
xaccFreeTransaction (trans);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,16 +312,13 @@ xaccInitTransaction( Transaction * trans )
|
|||||||
|
|
||||||
trans->splits = (Split **) _malloc (3* sizeof (Split *));
|
trans->splits = (Split **) _malloc (3* sizeof (Split *));
|
||||||
|
|
||||||
/* create a pair of splits */
|
/* create a single split only. As soon as the balance becomes
|
||||||
|
* non-zero, additional splits will get created.
|
||||||
|
*/
|
||||||
split = xaccMallocSplit ();
|
split = xaccMallocSplit ();
|
||||||
split->parent = trans;
|
split->parent = trans;
|
||||||
trans->splits[0] = split;
|
trans->splits[0] = split;
|
||||||
|
trans->splits[1] = NULL;
|
||||||
split = xaccMallocSplit ();
|
|
||||||
split->parent = trans;
|
|
||||||
trans->splits[1] = split;
|
|
||||||
|
|
||||||
trans->splits[2] = NULL;
|
|
||||||
|
|
||||||
trans->date_entered.tv_sec = 0;
|
trans->date_entered.tv_sec = 0;
|
||||||
trans->date_entered.tv_nsec = 0;
|
trans->date_entered.tv_nsec = 0;
|
||||||
@ -376,31 +384,11 @@ xaccFreeTransaction( Transaction *trans )
|
|||||||
/********************************************************************\
|
/********************************************************************\
|
||||||
\********************************************************************/
|
\********************************************************************/
|
||||||
|
|
||||||
void
|
/* hack alert -- the algorithm used in this rebalance routine
|
||||||
xaccTransDestroy (Transaction *trans)
|
* is less than intuitive, and could use some write-up.
|
||||||
{
|
* Maybe it does indeed do the right thing, but that is
|
||||||
int i;
|
* not at all obvious.
|
||||||
Split *split;
|
*/
|
||||||
Account *acc;
|
|
||||||
|
|
||||||
if (!trans) return;
|
|
||||||
|
|
||||||
i=0;
|
|
||||||
split = trans->splits[i];
|
|
||||||
while (split) {
|
|
||||||
MARK_SPLIT (split);
|
|
||||||
acc = split ->acc;
|
|
||||||
xaccAccountRemoveSplit (acc, split);
|
|
||||||
xaccAccountRecomputeBalance (acc);
|
|
||||||
i++;
|
|
||||||
split = trans->splits[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
xaccFreeTransaction (trans);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************************************************\
|
|
||||||
\********************************************************************/
|
|
||||||
|
|
||||||
void
|
void
|
||||||
xaccTransRebalance (Transaction * trans)
|
xaccTransRebalance (Transaction * trans)
|
||||||
@ -459,7 +447,7 @@ xaccSplitRebalance (Split *split)
|
|||||||
MARK_SPLIT (s);
|
MARK_SPLIT (s);
|
||||||
xaccAccountRecomputeBalance (s->acc);
|
xaccAccountRecomputeBalance (s->acc);
|
||||||
|
|
||||||
} else{
|
} else {
|
||||||
/* There are no destination splits !!
|
/* There are no destination splits !!
|
||||||
* Either this is allowed, in which case
|
* Either this is allowed, in which case
|
||||||
* we just blow it off, or its forbidden,
|
* we just blow it off, or its forbidden,
|
||||||
@ -467,27 +455,25 @@ xaccSplitRebalance (Split *split)
|
|||||||
* to be created.
|
* to be created.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* hack alert -- I think this is broken */
|
|
||||||
#ifdef HACK_ALERT
|
|
||||||
if (force_double_entry) {
|
if (force_double_entry) {
|
||||||
value = split->share_price * split->damount;
|
if (! (DEQ (0.0, split->damount))) {
|
||||||
|
value = split->share_price * split->damount;
|
||||||
/* malloc a new split, mirror it to the source split */
|
|
||||||
s = xaccMallocSplit ();
|
/* malloc a new split, mirror it to the source split */
|
||||||
s->damount = -value;
|
s = xaccMallocSplit ();
|
||||||
free (s->memo);
|
s->damount = -value;
|
||||||
s->memo = strdup (split->memo);
|
free (s->memo);
|
||||||
free (s->action);
|
s->memo = strdup (split->memo);
|
||||||
s->action = strdup (split->action);
|
free (s->action);
|
||||||
|
s->action = strdup (split->action);
|
||||||
/* insert the new split into the transaction and
|
|
||||||
* the same account as the source split */
|
/* insert the new split into the transaction and
|
||||||
MARK_SPLIT (s);
|
* the same account as the source split */
|
||||||
xaccTransAppendSplit (trans, s);
|
MARK_SPLIT (s);
|
||||||
xaccAccountInsertSplit (split->acc, s);
|
xaccTransAppendSplit (trans, s);
|
||||||
|
xaccAccountInsertSplit (split->acc, s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
@ -537,6 +523,7 @@ xaccTransBeginEdit (Transaction *trans)
|
|||||||
assert (trans);
|
assert (trans);
|
||||||
trans->open = 1;
|
trans->open = 1;
|
||||||
xaccOpenLog ();
|
xaccOpenLog ();
|
||||||
|
xaccTransWriteLog (trans, 'B');
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -574,7 +561,35 @@ xaccTransCommitEdit (Transaction *trans)
|
|||||||
}
|
}
|
||||||
|
|
||||||
trans->open = 0;
|
trans->open = 0;
|
||||||
xaccTransWriteLog (trans);
|
xaccTransWriteLog (trans, 'C');
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************\
|
||||||
|
\********************************************************************/
|
||||||
|
|
||||||
|
void
|
||||||
|
xaccTransDestroy (Transaction *trans)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
Split *split;
|
||||||
|
Account *acc;
|
||||||
|
|
||||||
|
if (!trans) return;
|
||||||
|
CHECK_OPEN (trans);
|
||||||
|
xaccTransWriteLog (trans, 'D');
|
||||||
|
|
||||||
|
i=0;
|
||||||
|
split = trans->splits[i];
|
||||||
|
while (split) {
|
||||||
|
MARK_SPLIT (split);
|
||||||
|
acc = split ->acc;
|
||||||
|
xaccAccountRemoveSplit (acc, split);
|
||||||
|
xaccAccountRecomputeBalance (acc);
|
||||||
|
i++;
|
||||||
|
split = trans->splits[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
xaccFreeTransaction (trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************\
|
/********************************************************************\
|
||||||
@ -619,8 +634,11 @@ xaccTransAppendSplit (Transaction *trans, Split *split)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************\
|
/********************************************************************\
|
||||||
|
* TransRemoveSplit is an engine private function and does not/should
|
||||||
|
* not cause any rebalancing to occur.
|
||||||
\********************************************************************/
|
\********************************************************************/
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
xaccTransRemoveSplit (Transaction *trans, Split *split)
|
xaccTransRemoveSplit (Transaction *trans, Split *split)
|
||||||
{
|
{
|
||||||
@ -895,30 +913,32 @@ xaccTransSetDescription (Transaction *trans, const char *desc)
|
|||||||
|
|
||||||
#define SET_TRANS_FIELD(trans,field,value) \
|
#define SET_TRANS_FIELD(trans,field,value) \
|
||||||
{ \
|
{ \
|
||||||
|
char * tmp; \
|
||||||
if (!trans) return; \
|
if (!trans) return; \
|
||||||
CHECK_OPEN (trans); \
|
CHECK_OPEN (trans); \
|
||||||
\
|
\
|
||||||
/* the engine *must* always be internally consistent */ \
|
/* the engine *must* always be internally consistent */ \
|
||||||
assert (trans->splits); \
|
assert (trans->splits); \
|
||||||
|
assert (trans->splits[0]); \
|
||||||
\
|
\
|
||||||
|
/* there must be two splits if value of one non-zero */ \
|
||||||
if (force_double_entry) { \
|
if (force_double_entry) { \
|
||||||
assert (trans->splits[0]); \
|
if (! (DEQ (0.0, trans->splits[0]->damount))) { \
|
||||||
assert (trans->splits[1]); \
|
assert (trans->splits[1]); \
|
||||||
|
} \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
if (0x0 != trans->splits[0]) { \
|
tmp = strdup (value); \
|
||||||
char * tmp = strdup (value); \
|
free (trans->splits[0]->field); \
|
||||||
free (trans->splits[0]->field); \
|
trans->splits[0]->field = tmp; \
|
||||||
trans->splits[0]->field = tmp; \
|
MARK_SPLIT (trans->splits[0]); \
|
||||||
MARK_SPLIT (trans->splits[0]); \
|
\
|
||||||
\
|
/* If there are just two splits, then keep them in sync. */ \
|
||||||
/* if there are just two splits, then keep them in sync. */\
|
if (0x0 != trans->splits[1]) { \
|
||||||
if (0x0 != trans->splits[1]) { \
|
if (0x0 == trans->splits[2]) { \
|
||||||
if (0x0 == trans->splits[2]) { \
|
free (trans->splits[1]->field); \
|
||||||
free (trans->splits[1]->field); \
|
trans->splits[1]->field = strdup (tmp); \
|
||||||
trans->splits[1]->field = strdup (tmp); \
|
MARK_SPLIT (trans->splits[1]); \
|
||||||
MARK_SPLIT (trans->splits[1]); \
|
|
||||||
} \
|
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
@ -941,6 +961,9 @@ xaccTransSetAction (Transaction *trans, const char *actn)
|
|||||||
Split *
|
Split *
|
||||||
xaccTransGetSplit (Transaction *trans, int i)
|
xaccTransGetSplit (Transaction *trans, int i)
|
||||||
{
|
{
|
||||||
|
if (!trans) return NULL;
|
||||||
|
if (0 > i) return NULL;
|
||||||
|
/* hack alert - should check if i > sizeof array */
|
||||||
if (trans->splits) {
|
if (trans->splits) {
|
||||||
return (trans->splits[i]);
|
return (trans->splits[i]);
|
||||||
}
|
}
|
||||||
@ -950,18 +973,21 @@ xaccTransGetSplit (Transaction *trans, int i)
|
|||||||
char *
|
char *
|
||||||
xaccTransGetNum (Transaction *trans)
|
xaccTransGetNum (Transaction *trans)
|
||||||
{
|
{
|
||||||
|
if (!trans) return NULL;
|
||||||
return (trans->num);
|
return (trans->num);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
xaccTransGetDescription (Transaction *trans)
|
xaccTransGetDescription (Transaction *trans)
|
||||||
{
|
{
|
||||||
|
if (!trans) return NULL;
|
||||||
return (trans->description);
|
return (trans->description);
|
||||||
}
|
}
|
||||||
|
|
||||||
time_t
|
time_t
|
||||||
xaccTransGetDate (Transaction *trans)
|
xaccTransGetDate (Transaction *trans)
|
||||||
{
|
{
|
||||||
|
if (!trans) return 0;
|
||||||
return (trans->date_posted.tv_sec);
|
return (trans->date_posted.tv_sec);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -977,7 +1003,9 @@ xaccTransCountSplits (Transaction *trans)
|
|||||||
void
|
void
|
||||||
xaccSplitSetMemo (Split *split, const char *memo)
|
xaccSplitSetMemo (Split *split, const char *memo)
|
||||||
{
|
{
|
||||||
char * tmp = strdup (memo);
|
char * tmp;
|
||||||
|
if (!split) return;
|
||||||
|
tmp = strdup (memo);
|
||||||
if (split->memo) free (split->memo);
|
if (split->memo) free (split->memo);
|
||||||
split->memo = tmp;
|
split->memo = tmp;
|
||||||
MARK_SPLIT (split);
|
MARK_SPLIT (split);
|
||||||
@ -986,7 +1014,9 @@ xaccSplitSetMemo (Split *split, const char *memo)
|
|||||||
void
|
void
|
||||||
xaccSplitSetAction (Split *split, const char *actn)
|
xaccSplitSetAction (Split *split, const char *actn)
|
||||||
{
|
{
|
||||||
char * tmp = strdup (actn);
|
char * tmp;
|
||||||
|
if (!split) return;
|
||||||
|
tmp = strdup (actn);
|
||||||
if (split->action) free (split->action);
|
if (split->action) free (split->action);
|
||||||
split->action = tmp;
|
split->action = tmp;
|
||||||
MARK_SPLIT (split);
|
MARK_SPLIT (split);
|
||||||
@ -995,6 +1025,7 @@ xaccSplitSetAction (Split *split, const char *actn)
|
|||||||
void
|
void
|
||||||
xaccSplitSetReconcile (Split *split, char recn)
|
xaccSplitSetReconcile (Split *split, char recn)
|
||||||
{
|
{
|
||||||
|
if (!split) return;
|
||||||
split->reconciled = recn;
|
split->reconciled = recn;
|
||||||
MARK_SPLIT (split);
|
MARK_SPLIT (split);
|
||||||
xaccAccountRecomputeBalance (split->acc);
|
xaccAccountRecomputeBalance (split->acc);
|
||||||
|
@ -131,7 +131,7 @@ void xaccFreeSplit (Split *); /* frees memory */
|
|||||||
|
|
||||||
/* The xaccTransRemoveSplit() routine will remove the indicated
|
/* The xaccTransRemoveSplit() routine will remove the indicated
|
||||||
* split from the transaction. It will *NOT* otherwise
|
* split from the transaction. It will *NOT* otherwise
|
||||||
* readjust balances, modify accounts, etc.
|
* re-adjust balances, modify accounts, etc.
|
||||||
*/
|
*/
|
||||||
void xaccTransRemoveSplit (Transaction*, Split *);
|
void xaccTransRemoveSplit (Transaction*, Split *);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user