From 0fc2f2048a5000f57c27f0894f0506f8d5ee4c65 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Sun, 5 Apr 1998 09:26:01 +0000 Subject: [PATCH] make sure that balances are automatically recomputed whenever needed git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@782 57a11ea4-9604-0410-9ed3-97b8803252fd --- src/engine/Account.c | 35 ++++++++++++++--------------------- src/engine/Account.h | 12 ++++++------ src/engine/AccountP.h | 23 +++++++++++++++++++++++ src/engine/Transaction.c | 34 ++++++++++++++++++++++++++-------- 4 files changed, 69 insertions(+), 35 deletions(-) diff --git a/src/engine/Account.c b/src/engine/Account.c index 9933c3dfc7..a329974468 100644 --- a/src/engine/Account.c +++ b/src/engine/Account.c @@ -103,9 +103,8 @@ xaccMallocAccount( void ) void xaccFreeAccount( Account *acc ) { - int i=0, j=0; - Split *s, *debit_s; - int dont_free_transaction = 0; + int i=0; + Split *s; if (NULL == acc) return; @@ -129,20 +128,7 @@ xaccFreeAccount( Account *acc ) i=0; s = acc->splits[0]; while (s) { - Transaction *trans = (Transaction *) s->parent; - - j=0; - debit_s = trans->splits[0]; - while (debit_s) { - if (debit_s->acc) { dont_free_transaction = 1; break; } - j++; - debit_s = trans->splits[j]; - } - - if (!dont_free_transaction) { - xaccFreeTransaction( trans ); - } - + xaccSplitDestroy (s); i++; s = acc->splits[i]; } @@ -233,6 +219,11 @@ xaccAccountInsertSplit ( Account *acc, Split *split ) acc -> changed = TRUE; if( acc->parent != NULL ) acc->parent->saved = FALSE; + /* if this split belongs to another acount, remove it from + * there first. We don't want to ever leave the system + * in an inconsistent state. + */ + if (split->acc) xaccAccountRemoveSplit (split->acc, split); split->acc = acc; oldsplits = acc->splits; @@ -273,6 +264,8 @@ xaccAccountInsertSplit ( Account *acc, Split *split ) acc->splits[acc->numSplits] = NULL; _free(oldsplits); + + xaccAccountRecomputeBalance (acc); } @@ -309,7 +302,7 @@ xaccAccountRemoveSplit ( Account *acc, Split *split ) /********************************************************************\ - * xaccRecomputeBalance * + * xaccAccountRecomputeBalance * * recomputes the partial balances and the current balance for * * this account. * * @@ -337,7 +330,7 @@ xaccAccountRemoveSplit ( Account *acc, Split *split ) \********************************************************************/ void -xaccRecomputeBalance( Account * acc ) +xaccAccountRecomputeBalance( Account * acc ) { int i = 0; double dbalance = 0.0; @@ -528,7 +521,7 @@ xaccIsAccountInList (Account * acc, Account **list) \********************************************************************/ void -xaccRecomputeBalances( Account **list ) +xaccAccountRecomputeBalances( Account **list ) { Account * acc; int nacc = 0; @@ -536,7 +529,7 @@ xaccRecomputeBalances( Account **list ) acc = list[0]; while (acc) { - xaccRecomputeBalance (acc); + xaccAccountRecomputeBalance (acc); nacc++; acc = list[nacc]; } diff --git a/src/engine/Account.h b/src/engine/Account.h index 7f6660b147..7d99c4398f 100644 --- a/src/engine/Account.h +++ b/src/engine/Account.h @@ -49,13 +49,13 @@ void xaccAccountCommitEdit (Account *); int xaccGetAccountID (Account *); +/* + * The xaccAccountInsertSplit() method will insert the indicated + * split into the indicated account. If the split already + * belongs to anothe account, it will be removed from that + * account first. + */ void xaccAccountInsertSplit (Account *, Split *); -void xaccAccountRemoveSplit (Account *, Split *); - -/* the following recompute the partial balances (stored with the transaction) - * and the total balance, for this account */ -void xaccRecomputeBalance (Account *); -void xaccRecomputeBalances (Account **); /* The xaccCheckDateOrder() surboutine checks to see if * a split is in proper sorted date order with respect diff --git a/src/engine/AccountP.h b/src/engine/AccountP.h index e49a7b5240..b2f8232380 100644 --- a/src/engine/AccountP.h +++ b/src/engine/AccountP.h @@ -6,6 +6,13 @@ * This is the *private* header for the account structure. * No one outside of the engine should ever include this file. * + * This header includes prototypes for "dangerous" functions. + * Invoking any of these functions potentially leave the account + * in an inconsistent state. If they are not used in the proper + * setting, they can leave the account structures in an inconsistent + * state. Thus, these methods should never be used outside of + * the engine, which is why they are "hidden" here. + * */ /********************************************************************\ @@ -74,4 +81,20 @@ struct _account { }; +/* The xaccAccountRemoveSplit() routine will remove the indicated split + * from the indicated account. Note that this will leave the split + * "dangling", i.e. unassigned to any account, and therefore will put + * the engine into an inconsistent state. After removing a split, + * it should be immediately destroyed, or it should be inserted into + * an account. + */ + +void xaccAccountRemoveSplit (Account *, Split *); + +/* the following recompute the partial balances (stored with the + * transaction) + * and the total balance, for this account */ +void xaccAccountRecomputeBalance (Account *); +void xaccAccountRecomputeBalances (Account **); + #endif /* __XACC_ACCOUNT_P_H__ */ diff --git a/src/engine/Transaction.c b/src/engine/Transaction.c index 2d0b1d9890..8e82a17765 100644 --- a/src/engine/Transaction.c +++ b/src/engine/Transaction.c @@ -136,6 +136,7 @@ MarkChanged (Transaction *trans) void xaccSplitDestroy (Split *split) { + Account *acc; Transaction *trans; int numsplits = 0; int ismember = 0; @@ -148,6 +149,7 @@ xaccSplitDestroy (Split *split) numsplits = 0; s = trans->splits[0]; while (s) { + MARK_SPLIT(s); if (s == split) ismember = 1; numsplits ++; s = trans->splits[numsplits]; @@ -158,20 +160,30 @@ xaccSplitDestroy (Split *split) * merely unlink & free the split. */ if (2 < numsplits) { + MARK_SPLIT (split); xaccTransRemoveSplit (trans, split); - xaccAccountRemoveSplit (split->acc, split); + acc = split->acc; + xaccAccountRemoveSplit (acc, split); + xaccAccountRecomputeBalance (acc); xaccFreeSplit (split); - xaccSplitRebalance (trans->splits[1]); + xaccSplitRebalance (trans->splits[0]); } else { /* if the transaction has only two splits, * remove both of them, and them destroy the * transaction. */ s = trans->splits[0]; - xaccAccountRemoveSplit (split->acc, s); + acc = s->acc; + MARK_SPLIT (s); + xaccAccountRemoveSplit (acc, s); + xaccAccountRecomputeBalance (acc); xaccFreeSplit (s); + s = trans->splits[1]; - xaccAccountRemoveSplit (split->acc, s); + acc = s->acc; + MARK_SPLIT (s); + xaccAccountRemoveSplit (acc, s); + xaccAccountRecomputeBalance (acc); xaccFreeSplit (s); xaccFreeTransaction (trans); } @@ -355,13 +367,17 @@ xaccTransDestroy (Transaction *trans) { int i; Split *split; + Account *acc; if (!trans) return; i=0; split = trans->splits[i]; while (split) { - xaccAccountRemoveSplit (split->acc, split); + MARK_SPLIT (split); + acc = split ->acc; + xaccAccountRemoveSplit (acc, split); + xaccAccountRecomputeBalance (acc); i++; split = trans->splits[i]; } @@ -437,6 +453,7 @@ xaccSplitRebalance (Split *split) */ s -> damount = - (value / (s->share_price)); MARK_SPLIT (s); + xaccAccountRecomputeBalance (s->acc); } else{ /* There are no destination splits !! @@ -461,9 +478,9 @@ xaccSplitRebalance (Split *split) /* insert the new split into the transaction and * the same account as the source split */ + MARK_SPLIT (s); xaccTransAppendSplit (trans, s); xaccAccountInsertSplit (split->acc, s); - MARK_SPLIT (s); } #endif @@ -486,6 +503,7 @@ xaccSplitRebalance (Split *split) s = trans->splits[0]; s -> damount = - (value / (s->share_price)); MARK_SPLIT (s); + xaccAccountRecomputeBalance (s->acc); } /* hack alert -- if the "force-double-entry" flag is set, @@ -713,10 +731,9 @@ xaccTransSetDate (Transaction *trans, int day, int mon, int year) i=0; split = trans->splits[i]; while (split) { - acc = (Account *) split->acc; + acc = split->acc; xaccAccountRemoveSplit (acc, split); xaccAccountInsertSplit (acc, split); - xaccRecomputeBalance (acc); i++; split = trans->splits[i]; @@ -874,6 +891,7 @@ xaccSplitSetReconcile (Split *split, char recn) { split->reconciled = recn; MARK_SPLIT (split); + xaccAccountRecomputeBalance (split->acc); } /********************************************************************\