mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
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:
parent
7f89231a82
commit
91bf87ec53
@ -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 */
|
||||
/** @} */
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
/********************************************************************\
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/* ============================================================== */
|
||||
|
Loading…
Reference in New Issue
Block a user