merge changes from the cap-gains2 branch:

-- delete of cap-gains splits now handled
-- gnc-events now generated at commit-edit, not willy-nilly
-- improved scrub docos


git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@9222 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Linas Vepstas 2003-09-03 13:02:37 +00:00
parent 7f89231a82
commit 91bf87ec53
4 changed files with 161 additions and 89 deletions

View File

@ -38,6 +38,24 @@
#include "gnc-engine.h"
/** The xaccGroupScrubLotsBalance() routine walks the
* account tree, and invokes xaccAccountScrubLots()
* and xaccAccountScrubDoubleBalance() on all accounts
* that are trading accounts.
* The xaccAccountTreeScrubLotsBalance() does the same.
* The xaccAccountScrubLotsBalance() will do the same,
* except that it won't descend down to the account
* children.
*
* Most GUI routines will want to use one of these
* xacc[*]ScrubLotsBalance() routines, instead of the
* component ScrubLots() and ScrubDoubleBalance() routines,
* since it usually makes sense to call these together.
*/
void xaccGroupScrubLotsBalance (AccountGroup *grp);
void xaccAccountScrubLotsBalance (Account *acc);
void xaccAccountTreeScrubLotsBalance (Account *acc);
/** The xaccAccountScrubLots() routine will walk over all of
* the splits in an account, and make sure that each belongs
* to a lot. Any splits that are not in a lot will be used
@ -78,14 +96,5 @@ void xaccAccountScrubDoubleBalance (Account *acc);
*/
void xaccLotScrubDoubleBalance (GNCLot *lot);
/** The xaccGroupScrubLotsBalance() routine walks the
* account tree, and invokes xaccAccountScrubLots()
* and xaccAccountScrubDoubleBalance() on all accounts
* that are trading accounts.
*/
void xaccGroupScrubLotsBalance (AccountGroup *grp);
void xaccAccountScrubLotsBalance (Account *acc);
void xaccAccountTreeScrubLotsBalance (Account *acc);
#endif /* XACC_SCRUB2_H */
/** @} */

View File

@ -52,6 +52,20 @@
#include "qofobject.h"
#include "qofqueryobject.h"
/*
* Design notes on event-generation: transaction-modified-events
* should not be generated until transacation commit or rollback
* time. They should not be generated as each field is tweaked.
* This for two reasons:
* 1) Most editing events make multiple changes to a trnasaction,
* which would generate a flurry of (needless) events, if they
* weren't saved up till the commit.
* 2) Technically, its incorrect to use transaction data
* until the transaction is commited. The GUI element that
* is changing the data can look at it, but all of the rest
* of the GUI should ignore the data until its commited.
*/
/*
* The "force_double_entry" flag determines how
* the splits in a transaction will be balanced.
@ -591,19 +605,25 @@ G_INLINE_FUNC void gen_event (Split *split);
G_INLINE_FUNC void gen_event (Split *split)
{
Account *account = split->acc;
Transaction *trans;
Transaction *trans = split->parent;
GNCLot *lot = split->lot;
if (account)
{
xaccGroupMarkNotSaved (account->parent);
gnc_engine_generate_event (&account->guid, GNC_ID_ACCOUNT, GNC_EVENT_MODIFY);
xaccGroupMarkNotSaved (account->parent);
gnc_engine_generate_event (&account->guid, GNC_ID_ACCOUNT, GNC_EVENT_MODIFY);
}
trans = split->parent;
if (trans)
{
gnc_engine_generate_event (&trans->guid, GNC_ID_TRANS, GNC_EVENT_MODIFY);
}
if (lot)
{
/* A change of value/amnt affects gains displat, etc. */
gnc_engine_generate_event (&lot->guid, GNC_ID_LOT, GNC_EVENT_MODIFY);
}
}
G_INLINE_FUNC void gen_event_trans (Transaction *trans);
@ -613,9 +633,19 @@ G_INLINE_FUNC void gen_event_trans (Transaction *trans)
for (node = trans->splits; node; node = node->next)
{
Account *account = ((Split *) (node->data)) -> acc;
Split *s = node->data;
Account *account = s->acc;
GNCLot *lot = s->lot;
if (account)
{
xaccGroupMarkNotSaved (account->parent);
gnc_engine_generate_event (&account->guid, GNC_ID_ACCOUNT, GNC_EVENT_MODIFY);
}
if (lot)
{
/* A change of transaction date might affect opening date of lot */
gnc_engine_generate_event (&lot->guid, GNC_ID_LOT, GNC_EVENT_MODIFY);
}
}
gnc_engine_generate_event (&trans->guid, GNC_ID_TRANS, GNC_EVENT_MODIFY);
@ -683,7 +713,7 @@ xaccSplitSetSlots_nc(Split *s, KvpFrame *frm)
s->kvp_data = frm;
gen_event (s);
/* gen_event (s); No! only in TransCommit() ! */
}
/********************************************************************\
@ -702,7 +732,7 @@ DxaccSplitSetSharePriceAndAmount (Split *s, double price, double amt)
SET_GAINS_VDIRTY(s);
mark_split (s);
gen_event (s);
/* gen_event (s); No! only in TransCommit() ! */
}
void
@ -718,7 +748,7 @@ xaccSplitSetSharePriceAndAmount (Split *s, gnc_numeric price,
SET_GAINS_VDIRTY(s);
mark_split (s);
gen_event (s);
/* gen_event (s); No! only in TransCommit() ! */
}
void
@ -741,7 +771,7 @@ xaccSplitSetSharePrice (Split *s, gnc_numeric price)
SET_GAINS_VDIRTY(s);
mark_split (s);
gen_event (s);
/* gen_event (s); No! only in TransCommit() ! */
}
void
@ -769,7 +799,7 @@ DxaccSplitSetShareAmount (Split *s, double damt)
SET_GAINS_VDIRTY(s);
mark_split (s);
gen_event (s);
/* gen_event (s); No! only in TransCommit() ! */
}
void
@ -785,7 +815,7 @@ DxaccSplitSetAmount (Split *s, double damt)
SET_GAINS_VDIRTY(s);
mark_split (s);
gen_event (s);
/* gen_event (s); No! only in TransCommit() ! */
}
void
@ -798,7 +828,7 @@ xaccSplitSetAmount (Split *s, gnc_numeric amt)
SET_GAINS_VDIRTY(s);
mark_split (s);
gen_event (s);
/* gen_event (s); No! only in TransCommit() ! */
}
void
@ -832,7 +862,7 @@ DxaccSplitSetValue (Split *s, double damt)
SET_GAINS_VDIRTY(s);
mark_split (s);
gen_event (s);
/* gen_event (s); No! only in TransCommit() ! */
}
void
@ -845,7 +875,7 @@ xaccSplitSetValue (Split *s, gnc_numeric amt)
SET_GAINS_VDIRTY(s);
mark_split (s);
gen_event (s);
/* gen_event (s); No! only in TransCommit() ! */
}
/********************************************************************\
@ -1323,7 +1353,7 @@ xaccTransSetSlots_nc (Transaction *t, KvpFrame *frm)
t->kvp_data = frm;
gen_event_trans (t);
/* gen_event_trans (t); No! only in TransCommit() ! */
}
/********************************************************************\
@ -1416,7 +1446,7 @@ xaccSplitSetBaseValue (Split *s, gnc_numeric value,
s->amount = value;
}
mark_split (s);
gen_event (s);
/* gen_event (s); No! only in TransCommit() ! */
return;
}
@ -1454,7 +1484,7 @@ xaccSplitSetBaseValue (Split *s, gnc_numeric value,
}
mark_split (s);
gen_event (s);
/* gen_event (s); No! only in TransCommit() ! */
}
gnc_numeric
@ -1772,7 +1802,7 @@ xaccTransSetCurrency (Transaction *trans, gnc_commodity *curr)
}
mark_trans (trans);
gen_event_trans (trans);
/* gen_event_trans (trans); No! only in TransCommit() ! */
}
/********************************************************************\
@ -1807,6 +1837,78 @@ xaccTransBeginEdit (Transaction *trans)
trans->orig = xaccDupeTransaction (trans);
}
/********************************************************************\
\********************************************************************/
void
xaccTransDestroy (Transaction *trans)
{
if (!trans) return;
check_open (trans);
if (xaccTransWarnReadOnly (trans)) return;
trans->do_free = TRUE;
}
static void
destroy_gains (Transaction *trans)
{
SplitList *node;
for (node = trans->splits; node; node = node->next)
{
Split *s = node->data;
if (GAINS_STATUS_UNKNOWN == s->gains) DetermineGainStatus(s);
if (s->gains_split && (GAINS_STATUS_GAINS & s->gains_split->gains))
{
Transaction *t = s->gains_split->parent;
xaccTransBeginEdit (t);
xaccTransDestroy (t);
xaccTransCommitEdit (t);
s->gains_split = NULL;
}
}
}
static void
do_destroy (Transaction *trans)
{
SplitList *node;
/* If there are capital-gains transactions associated with this,
* they need to be destroyed too. */
destroy_gains (trans);
/* Make a log in the journal before destruction. */
xaccTransWriteLog (trans, 'D');
gnc_engine_generate_event (&trans->guid, GNC_ID_TRANS, GNC_EVENT_DESTROY);
for (node = trans->splits; node; node = node->next)
{
Split *split = node->data;
mark_split (split);
xaccAccountRemoveSplit (split->acc, split);
xaccAccountRecomputeBalance (split->acc);
gen_event (split);
qof_entity_remove(split->book->entity_table, &split->guid);
xaccFreeSplit (split);
node->data = NULL;
}
g_list_free (trans->splits);
trans->splits = NULL;
qof_entity_remove(trans->book->entity_table, &trans->guid);
/* The actual free is done with the commit call, else its rolled back */
}
/********************************************************************\
\********************************************************************/
void
xaccTransCommitEdit (Transaction *trans)
{
@ -1922,12 +2024,10 @@ xaccTransCommitEdit (Transaction *trans)
}
/* ------------------------------------------------- */
if (!trans->splits || trans->do_free)
if (trans->do_free || !trans->splits)
{
PINFO ("delete trans at addr=%p", trans);
/* Make a log in the journal before destruction. */
xaccTransWriteLog (trans, 'D');
qof_entity_remove(trans->book->entity_table, &trans->guid);
do_destroy (trans);
xaccFreeTransaction (trans);
return;
}
@ -1949,6 +2049,7 @@ xaccTransCommitEdit (Transaction *trans)
/* Put back to zero. */
trans->editlevel--;
gen_event_trans (trans);
LEAVE ("trans addr=%p\n", trans);
}
@ -2156,6 +2257,7 @@ xaccTransRollbackEdit (Transaction *trans)
* out about it until this user tried to edit it.
*/
xaccTransDestroy (trans);
do_destroy (trans);
xaccFreeTransaction (trans);
/* push error back onto the stack */
@ -2225,48 +2327,6 @@ xaccTransWarnReadOnly (const Transaction *trans)
return FALSE;
}
/********************************************************************\
\********************************************************************/
void
xaccTransDestroy (Transaction *trans)
{
GList *node;
if (!trans) return;
check_open (trans);
if (xaccTransWarnReadOnly (trans))
return;
trans->do_free = TRUE;
xaccTransWriteLog (trans, 'D');
gnc_engine_generate_event (&trans->guid, GNC_ID_TRANS, GNC_EVENT_DESTROY);
for (node = trans->splits; node; node = node->next)
{
Split *split = node->data;
mark_split (split);
xaccAccountRemoveSplit (split->acc, split);
xaccAccountRecomputeBalance (split->acc);
gen_event (split);
qof_entity_remove(split->book->entity_table, &split->guid);
xaccFreeSplit (split);
node->data = NULL;
}
g_list_free (trans->splits);
trans->splits = NULL;
qof_entity_remove(trans->book->entity_table, &trans->guid);
/* the actual free is done with the commit call, else its rolled back */
/* xaccFreeTransaction (trans); don't do this here ... */
}
/********************************************************************\
* TransRemoveSplit is an engine private function and does not/should
* not cause any rebalancing to occur.
@ -2686,7 +2746,7 @@ xaccTransSetDateInternal(Transaction *trans, Timespec *dadate, Timespec val)
*dadate = val;
mark_trans(trans);
gen_event_trans (trans);
/* gen_event_trans (trans); No! only in TransCommit() ! */
/* Because the date has changed, we need to make sure that each of
* the splits is properly ordered in each of their accounts. We
@ -2791,7 +2851,7 @@ xaccTransSetNum (Transaction *trans, const char *xnum)
tmp = g_cache_insert(gnc_engine_get_string_cache(), (gpointer) xnum);
g_cache_remove(gnc_engine_get_string_cache(), trans->num);
trans->num = tmp;
gen_event_trans (trans);
/* gen_event_trans (trans); No! only in TransCommit() ! */
}
void
@ -2804,7 +2864,7 @@ xaccTransSetDescription (Transaction *trans, const char *desc)
tmp = g_cache_insert(gnc_engine_get_string_cache(), (gpointer) desc);
g_cache_remove(gnc_engine_get_string_cache(), trans->description);
trans->description = tmp;
gen_event_trans (trans);
/* gen_event_trans (trans); No! only in TransCommit() ! */
}
void
@ -2814,7 +2874,7 @@ xaccTransSetNotes (Transaction *trans, const char *notes)
check_open (trans);
kvp_frame_set_str (trans->kvp_data, trans_notes_str, notes);
gen_event_trans (trans);
/* gen_event_trans (trans); No! only in TransCommit() ! */
}
/********************************************************************\
@ -3074,7 +3134,7 @@ xaccSplitSetMemo (Split *split, const char *memo)
tmp = g_cache_insert(gnc_engine_get_string_cache(), (gpointer) memo);
g_cache_remove(gnc_engine_get_string_cache(), split->memo);
split->memo = tmp;
gen_event (split);
/* gen_event (split); No! only in TransCommit() ! */
}
void
@ -3087,7 +3147,7 @@ xaccSplitSetAction (Split *split, const char *actn)
tmp = g_cache_insert(gnc_engine_get_string_cache(), (gpointer) actn);
g_cache_remove(gnc_engine_get_string_cache(), split->action);
split->action = tmp;
gen_event (split);
/* gen_event (split); No! only in TransCommit() ! */
}
void
@ -3116,7 +3176,7 @@ xaccSplitSetReconcile (Split *split, char recn)
split->reconciled = recn;
mark_split (split);
xaccAccountRecomputeBalance (account);
gen_event (split);
/* gen_event (split); No! only in TransCommit() ! */
}
}
@ -3128,7 +3188,7 @@ xaccSplitSetDateReconciledSecs (Split *split, time_t secs)
split->date_reconciled.tv_sec = secs;
split->date_reconciled.tv_nsec = 0;
gen_event (split);
/* gen_event (split); No! only in TransCommit() ! */
}
void
@ -3138,7 +3198,7 @@ xaccSplitSetDateReconciledTS (Split *split, Timespec *ts)
check_open (split->parent);
split->date_reconciled = *ts;
gen_event (split);
/* gen_event (split); No! only in TransCommit() ! */
}
void
@ -3288,7 +3348,7 @@ xaccSplitMakeStockSplit(Split *s)
s->value = gnc_numeric_zero();
kvp_frame_set_str(s->kvp_data, "split-type", "stock-split");
mark_split(s);
gen_event (s);
/* gen_event (s); No! only in TransCommit() ! */
}
@ -3577,7 +3637,6 @@ xaccTransReverse (Transaction *trans)
g_return_if_fail(trans);
gnc_engine_suspend_events();
xaccTransBeginEdit(trans);
/* Reverse the values on each split. Clear per-split info. */
@ -3593,8 +3652,6 @@ xaccTransReverse (Transaction *trans)
}
xaccTransCommitEdit(trans);
gnc_engine_resume_events();
}
/********************************************************************\

View File

@ -81,9 +81,10 @@
#define GAINS_STATUS_CLEAN 0x0
#define GAINS_STATUS_GAINS 0x3
#define GAINS_STATUS_DATE_DIRTY 0x10
#define GAINS_STATUS_VALU_DIRTY 0x20
#define GAINS_STATUS_LOT_DIRTY 0x40
#define GAINS_STATUS_VDIRTY (GAINS_STATUS_VALU_DIRTY|GAINS_STATUS_LOT_DIRTY)
#define GAINS_STATUS_AMNT_DIRTY 0x20
#define GAINS_STATUS_VALU_DIRTY 0x40
#define GAINS_STATUS_LOT_DIRTY 0x80
#define GAINS_STATUS_VDIRTY (GAINS_STATUS_AMNT_DIRTY|GAINS_STATUS_VALU_DIRTY|GAINS_STATUS_LOT_DIRTY)
struct split_s
{

View File

@ -80,6 +80,7 @@ gnc_lot_new (QofBook *book)
lot = g_new (GNCLot, 1);
gnc_lot_init (lot, book);
gnc_engine_generate_event (&lot->guid, GNC_ID_LOT, GNC_EVENT_CREATE);
return lot;
}
@ -242,6 +243,7 @@ gnc_lot_add_split (GNCLot *lot, Split *split)
return;
}
if (lot == split->lot) return; /* handle not-uncommon no-op */
if (split->lot)
{
gnc_lot_remove_split (split->lot, split);
@ -252,6 +254,8 @@ gnc_lot_add_split (GNCLot *lot, Split *split)
/* for recomputation of is-closed */
lot->is_closed = -1;
gnc_engine_generate_event (&lot->guid, GNC_ID_LOT, GNC_EVENT_MODIFY);
}
void
@ -269,6 +273,7 @@ gnc_lot_remove_split (GNCLot *lot, Split *split)
xaccAccountRemoveLot (lot->account, lot);
lot->account = NULL;
}
gnc_engine_generate_event (&lot->guid, GNC_ID_LOT, GNC_EVENT_MODIFY);
}
/* ============================================================== */