gnucash maint: Multiple changes pushed
Geert Janssens
gjanssens at code.gnucash.org
Sat Nov 12 05:07:29 EST 2016
Updated via https://github.com/Gnucash/gnucash/commit/ecb43e7d (commit)
via https://github.com/Gnucash/gnucash/commit/5b832c7f (commit)
via https://github.com/Gnucash/gnucash/commit/96c22f54 (commit)
via https://github.com/Gnucash/gnucash/commit/254b4fbc (commit)
via https://github.com/Gnucash/gnucash/commit/a9c624bf (commit)
via https://github.com/Gnucash/gnucash/commit/396117ee (commit)
via https://github.com/Gnucash/gnucash/commit/d52f44a8 (commit)
via https://github.com/Gnucash/gnucash/commit/0bcd3030 (commit)
via https://github.com/Gnucash/gnucash/commit/673888de (commit)
from https://github.com/Gnucash/gnucash/commit/32c4d145 (commit)
commit ecb43e7d72941c32bc7bee3d3698029bfd643080
Author: Geert Janssens <janssens-geert at telenet.be>
Date: Sat Nov 12 10:30:31 2016 +0100
Bug 770364 - Sign of Value in Lots in Account window seems inconsistent
Two parts to this bug:
1. never reverse signs in the free splits list. Sign reversals don't
make sense there.
2. Sign reversal only makes sense for capital gains, not for business
transactions. So only to the sign dance for non-business lots in the
list of splits in the selected lot.
diff --git a/src/gnome/dialog-lot-viewer.c b/src/gnome/dialog-lot-viewer.c
index a4c64e4..2d6e2b5 100644
--- a/src/gnome/dialog-lot-viewer.c
+++ b/src/gnome/dialog-lot-viewer.c
@@ -485,8 +485,12 @@ gnc_split_viewer_fill (GNCLotViewer *lv, GtkListStore *store, SplitList *split_l
{
SplitList *node;
GtkTreeIter iter;
-
+ gboolean is_business_lot = FALSE;
gnc_numeric baln = gnc_numeric_zero();
+
+ if (lv->selected_lot)
+ is_business_lot = xaccAccountIsAPARType (xaccAccountGetType (gnc_lot_get_account (lv->selected_lot)));
+
gtk_list_store_clear (lv->split_in_lot_store);
for (node = split_list; node; node = node->next)
{
@@ -501,8 +505,7 @@ gnc_split_viewer_fill (GNCLotViewer *lv, GtkListStore *store, SplitList *split_l
gnc_numeric amnt, valu, gains;
/* Do not show gains splits, however do show empty business splits */
- if (!xaccAccountIsAPARType (xaccAccountGetType (xaccSplitGetAccount (split)))
- && gnc_numeric_zero_p (xaccSplitGetAmount(split))) continue;
+ if (!is_business_lot && gnc_numeric_zero_p (xaccSplitGetAmount(split))) continue;
gtk_list_store_append(store, &iter);
@@ -522,13 +525,13 @@ gnc_split_viewer_fill (GNCLotViewer *lv, GtkListStore *store, SplitList *split_l
gnc_account_print_info (lv->account, TRUE));
gtk_list_store_set (store, &iter, SPLIT_COL_AMOUNT, amtbuff, -1);
- /* Value. Invert the sign on the first, opening entry. */
+ /* Value.
+ * For non-business accounts which are part of a lot,
+ * invert the sign on the first. */
currency = xaccTransGetCurrency (trans);
valu = xaccSplitGetValue (split);
- if (node != split_list)
- {
- valu = gnc_numeric_neg (valu);
- }
+ if (lv->selected_lot && !is_business_lot && (node != split_list))
+ valu = gnc_numeric_neg (valu);
xaccSPrintAmount (valbuff, valu,
gnc_commodity_print_info (currency, TRUE));
gtk_list_store_set (store, &iter, SPLIT_COL_VALUE, valbuff, -1);
commit 5b832c7f9bec7e65077c139262e09070ada3e664
Author: Geert Janssens <janssens-geert at telenet.be>
Date: Sat Nov 12 09:22:09 2016 +0100
Use G_MAXINT64 instead of 0 to indicate an invalid date
diff --git a/src/gnome/dialog-lot-viewer.c b/src/gnome/dialog-lot-viewer.c
index 141da29..a4c64e4 100644
--- a/src/gnome/dialog-lot-viewer.c
+++ b/src/gnome/dialog-lot-viewer.c
@@ -393,7 +393,7 @@ gnc_lot_viewer_fill (GNCLotViewer *lv)
}
else
{
- gtk_list_store_set(store, &iter, LOT_COL_CLOSE, 0LL, -1);
+ gtk_list_store_set(store, &iter, LOT_COL_CLOSE, G_MAXINT64, -1);
}
/* Title */
@@ -800,7 +800,7 @@ static void print_date (GtkTreeViewColumn *tree_column,
doc_date_time = (time64) g_value_get_int64 (&value);
g_value_unset (&value);
- if (doc_date_time) /* assumes 0 represents an invalid date/time */
+ if (doc_date_time != G_MAXINT64) /* assumes INT64_MAX represents an invalid date/time */
{
g_free (doc_date_str);
doc_date_str = qof_print_date (doc_date_time);
commit 96c22f54a38420c7c3d2e981711e685edc63675c
Author: Geert Janssens <janssens-geert at telenet.be>
Date: Fri Nov 11 21:32:30 2016 +0100
Show empty business splits in lot viewer
diff --git a/src/gnome/dialog-lot-viewer.c b/src/gnome/dialog-lot-viewer.c
index 0bc919d..141da29 100644
--- a/src/gnome/dialog-lot-viewer.c
+++ b/src/gnome/dialog-lot-viewer.c
@@ -500,8 +500,9 @@ gnc_split_viewer_fill (GNCLotViewer *lv, GtkListStore *store, SplitList *split_l
time64 date = xaccTransGetDate (trans);
gnc_numeric amnt, valu, gains;
- /* Do not show gains splits */
- if (gnc_numeric_zero_p (xaccSplitGetAmount(split))) continue;
+ /* Do not show gains splits, however do show empty business splits */
+ if (!xaccAccountIsAPARType (xaccAccountGetType (xaccSplitGetAccount (split)))
+ && gnc_numeric_zero_p (xaccSplitGetAmount(split))) continue;
gtk_list_store_append(store, &iter);
commit 254b4fbc2fcdf697096fe7fd6aed6c97618472a0
Author: Geert Janssens <janssens-geert at telenet.be>
Date: Fri Nov 11 20:58:52 2016 +0100
Check more splits while running check & repair on business accounts
In addition, speed up the process a bit by already deleting empty splits as soon as they're encountered
diff --git a/src/engine/ScrubBusiness.c b/src/engine/ScrubBusiness.c
index 5212b5b..aa48ea3 100644
--- a/src/engine/ScrubBusiness.c
+++ b/src/engine/ScrubBusiness.c
@@ -200,7 +200,6 @@ scrub_start:
if (!sl_split)
continue; // next scrub lot split
- // Only lot link transactions need to be scrubbed
ll_txn = xaccSplitGetParent (sl_split);
if (!ll_txn)
@@ -212,9 +211,19 @@ scrub_start:
continue;
}
- if (xaccTransGetTxnType (ll_txn) != TXN_TYPE_LINK)
+ // Don't scrub invoice type transactions
+ if (xaccTransGetTxnType (ll_txn) == TXN_TYPE_INVOICE)
continue; // next scrub lot split
+ // Empty splits can be removed immediately
+ if (gnc_numeric_zero_p (xaccSplitGetValue (sl_split)) ||
+ gnc_numeric_zero_p(xaccSplitGetValue (sl_split)))
+ {
+ xaccSplitDestroy (sl_split);
+ modified = TRUE;
+ goto scrub_start;
+ }
+
// Iterate over all splits in the lot link transaction
for (lts_iter = xaccTransGetSplitList (ll_txn); lts_iter; lts_iter = lts_iter->next)
{
@@ -229,20 +238,22 @@ scrub_start:
if (sl_split == ll_txn_split)
continue; // next lot link transaction split
+ // Skip empty other splits. They'll be scrubbed in the outer for loop later
+ if (gnc_numeric_zero_p (xaccSplitGetValue (ll_txn_split)) ||
+ gnc_numeric_zero_p(xaccSplitGetValue (ll_txn_split)))
+ continue;
+
// Only splits of opposite signed values can be scrubbed
if (gnc_numeric_positive_p (xaccSplitGetValue (sl_split)) ==
gnc_numeric_positive_p (xaccSplitGetValue (ll_txn_split)))
continue; // next lot link transaction split
- // Find linked lot via split
+ // We can only scrub if the other split is in a lot as well
+ // Link transactions always have their other split in another lot
+ // however ordinary payment transactions may not
remote_lot = xaccSplitGetLot (ll_txn_split);
if (!remote_lot)
- {
- // This is unexpected - write a warning message and skip this split
- PWARN("Encountered a Lot Link transaction with a split that's not in any lot. "
- "This is unexpected! Skipping split %p from transaction %p.", ll_txn_split, ll_txn);
continue;
- }
sl_is_doc_lot = (gncInvoiceGetInvoiceFromLot (scrub_lot) != NULL);
rl_is_doc_lot = (gncInvoiceGetInvoiceFromLot (remote_lot) != NULL);
@@ -550,10 +561,16 @@ gncScrubBusinessSplit (Split *split)
*/
else if (gnc_numeric_zero_p (xaccSplitGetAmount(split)) && !gncInvoiceGetInvoiceFromTxn (txn))
{
+ GNCLot *lot = xaccSplitGetLot (split);
time64 pdate = xaccTransGetDate (txn);
gchar *pdatestr = gnc_ctime (&pdate);
PINFO ("Destroying empty split %p from transaction %s (%s)", split, pdatestr, xaccTransGetDescription(txn));
xaccSplitDestroy (split);
+
+ // Also delete the lot containing this split if it was the last split in that lot
+ if (lot && (gnc_lot_count_splits (lot) == 0))
+ gnc_lot_destroy (lot);
+
deleted_split = TRUE;
}
commit a9c624bfad7d98cd95a39788b399914eea01ea7c
Author: Geert Janssens <janssens-geert at telenet.be>
Date: Fri Nov 11 14:03:13 2016 +0100
Business check & repair - correct lot invoice state
There have been situations where a lot refered to an invoice while
it doesn't actually contain splits for that invoice (any more).
The new code corrects this by removing the invoice reference from the lot.
Also if the lot and its splits don't agree on the invoice they belong to
set the lot invoice to whatever the splits indicate.
diff --git a/src/engine/ScrubBusiness.c b/src/engine/ScrubBusiness.c
index 8ce5667..5212b5b 100644
--- a/src/engine/ScrubBusiness.c
+++ b/src/engine/ScrubBusiness.c
@@ -37,6 +37,7 @@
#include "policy-p.h"
#include "Account.h"
#include "gncInvoice.h"
+#include "gncInvoiceP.h"
#include "Scrub2.h"
#include "ScrubBusiness.h"
#include "Transaction.h"
@@ -46,6 +47,41 @@
static QofLogModule log_module = G_LOG_DOMAIN;
+static void
+gncScrubInvoiceState (GNCLot *lot)
+{
+ SplitList *ls_iter = NULL;
+ Transaction *txn = NULL; // ll_txn = "Lot Link Transaction"
+ GncInvoice *invoice = NULL;
+ GncInvoice *lot_invoice = gncInvoiceGetInvoiceFromLot (lot);
+
+ for (ls_iter = gnc_lot_get_split_list (lot); ls_iter; ls_iter = ls_iter->next)
+ {
+ Split *split = ls_iter->data;
+ Transaction *txn = NULL; // ll_txn = "Lot Link Transaction"
+
+ if (!split)
+ continue; // next scrub lot split
+
+ txn = xaccSplitGetParent (split);
+ invoice = gncInvoiceGetInvoiceFromTxn (txn);
+ if (invoice)
+ break;
+
+ }
+
+ if (invoice != lot_invoice)
+ {
+ PINFO("Correcting lot invoice associaton. Old invoice: %p, new invoice %p", lot_invoice, invoice);
+ gncInvoiceDetachFromLot(lot);
+
+ if (invoice)
+ gncInvoiceAttachToLot (invoice, lot);
+ else
+ gncOwnerAttachToLot (gncInvoiceGetOwner(lot_invoice), lot);
+ }
+}
+
// A helper function that takes two splits. If the splits are of opposite sign
// it reduces the biggest split to have the same value (but with opposite sign)
// of the smaller split.
@@ -214,7 +250,7 @@ scrub_start:
// Depending on the type of lots we're comparing, we need different actions
// - Two document lots (an invoice and a credit note):
// Special treatment - look for all document lots linked via ll_txn
- // and update the memo to be of more use to the uses.
+ // and update the memo to be of more use to the users.
// - Two payment lots:
// (Part of) the link will be eliminated and instead (part of)
// one payment will be added to the other lot to keep the balance.
@@ -424,6 +460,13 @@ gncScrubBusinessLot (GNCLot *lot)
if (acc)
xaccAccountBeginEdit(acc);
+ /* Check invoice link consistency
+ * A lot should have both or neither of:
+ * - one split from an invoice transaction
+ * - an invoice-guid set
+ */
+ gncScrubInvoiceState (lot);
+
// Scrub lot links.
// They should only remain when two document lots are linked together
xaccScrubMergeLotSubSplits (lot, FALSE);
diff --git a/src/engine/gncInvoice.c b/src/engine/gncInvoice.c
index 9b6c33f..222553f 100644
--- a/src/engine/gncInvoice.c
+++ b/src/engine/gncInvoice.c
@@ -1130,7 +1130,7 @@ qofInvoiceSetJob (GncInvoice *invoice, GncJob *job)
invoice->job = job;
}
-static void
+void
gncInvoiceDetachFromLot (GNCLot *lot)
{
KvpFrame *kvp;
@@ -1143,7 +1143,7 @@ gncInvoiceDetachFromLot (GNCLot *lot)
gnc_lot_commit_edit (lot);
}
-static void
+void
gncInvoiceAttachToLot (GncInvoice *invoice, GNCLot *lot)
{
KvpFrame *kvp;
@@ -1182,7 +1182,7 @@ GncInvoice * gncInvoiceGetInvoiceFromLot (GNCLot *lot)
return gncInvoiceLookup(book, guid);
}
-static void
+void
gncInvoiceAttachToTxn (GncInvoice *invoice, Transaction *txn)
{
KvpFrame *kvp;
diff --git a/src/engine/gncInvoiceP.h b/src/engine/gncInvoiceP.h
index 537dc2e..5b4942a 100644
--- a/src/engine/gncInvoiceP.h
+++ b/src/engine/gncInvoiceP.h
@@ -41,5 +41,9 @@ void gncInvoiceSetPostedTxn (GncInvoice *invoice, Transaction *txn);
void gncInvoiceSetPostedLot (GncInvoice *invoice, GNCLot *lot);
//void gncInvoiceSetPaidTxn (GncInvoice *invoice, Transaction *txn);
+void gncInvoiceAttachToLot (GncInvoice *invoice, GNCLot *lot);
+void gncInvoiceDetachFromLot (GNCLot *lot);
+void gncInvoiceAttachToTxn (GncInvoice *invoice, Transaction *txn);
+
#define gncInvoiceSetGUID(I,G) qof_instance_set_guid(QOF_INSTANCE(I),(G))
#endif /* GNC_INVOICEP_H_ */
commit 396117eec9514f20916df858c9477857e6c92b9a
Author: Geert Janssens <janssens-geert at telenet.be>
Date: Wed Nov 9 18:44:21 2016 +0100
Various small improvements to check & repair on business accounts
- don't attempt to merge splits that belong to an invoice transaction. These splits are managed by the business code.
- lot link cleanup can leave empty splits, remove these as well
diff --git a/src/engine/Scrub2.c b/src/engine/Scrub2.c
index 10ee3f8..e6a60af 100644
--- a/src/engine/Scrub2.c
+++ b/src/engine/Scrub2.c
@@ -43,6 +43,7 @@
#include "ScrubP.h"
#include "cap-gains.h"
#include "gnc-engine.h"
+#include "gncInvoice.h"
#include "gnc-lot.h"
#include "policy-p.h"
@@ -355,6 +356,11 @@ xaccScrubMergeSubSplits (Split *split, gboolean strict)
if (strict && (FALSE == is_subsplit (split))) return FALSE;
txn = split->parent;
+
+ // Don't mess with splits from an invoice transaction
+ // Those are the responsibility of the business code
+ if (gncInvoiceGetInvoiceFromTxn (txn)) return FALSE;
+
lot = xaccSplitGetLot (split);
ENTER ("(Lot=%s)", gnc_lot_get_title(lot));
@@ -366,6 +372,10 @@ restart:
if (s == split) continue;
if (qof_instance_get_destroying(s)) continue;
+ // Don't mess with splits from an invoice transaction
+ // Those are the responsibility of the business code
+ if (gncInvoiceGetInvoiceFromTxn (s->parent)) return FALSE;
+
if (strict)
{
/* OK, this split is in the same lot (and thus same account)
@@ -386,9 +396,13 @@ restart:
rc = TRUE;
goto restart;
}
- if (gnc_numeric_zero_p (split->amount))
+ if (rc && gnc_numeric_zero_p (split->amount))
{
+ time64 pdate = xaccTransGetDate (txn);
+ gchar *pdatestr = gnc_ctime (&pdate);
PWARN ("Result of merge has zero amt!");
+ PWARN ("Transaction details - posted date %s - description %s", pdatestr, xaccTransGetDescription(txn));
+ g_free (pdatestr);
}
LEAVE (" splits merged=%d", rc);
return rc;
diff --git a/src/engine/ScrubBusiness.c b/src/engine/ScrubBusiness.c
index cd69468..8ce5667 100644
--- a/src/engine/ScrubBusiness.c
+++ b/src/engine/ScrubBusiness.c
@@ -462,13 +462,14 @@ gncScrubBusinessLot (GNCLot *lot)
return splits_deleted;
}
-void
+gboolean
gncScrubBusinessSplit (Split *split)
{
const gchar *memo = _("Please delete this transaction. Explanation at http://wiki.gnucash.org/wiki/Business_Features_Issues#Double_Posting");
Transaction *txn;
+ gboolean deleted_split = FALSE;
- if (!split) return;
+ if (!split) return FALSE;
ENTER ("(split=%p)", split);
txn = xaccSplitGetParent (split);
@@ -500,10 +501,23 @@ gncScrubBusinessSplit (Split *split)
txn_date);
g_free (txn_date);
}
+ /* Next delete any empty splits that aren't part of an invoice transaction
+ * Such splits may be the result of scrubbing the business lots, which can
+ * merge splits together while reducing superfluous lot links
+ */
+ else if (gnc_numeric_zero_p (xaccSplitGetAmount(split)) && !gncInvoiceGetInvoiceFromTxn (txn))
+ {
+ time64 pdate = xaccTransGetDate (txn);
+ gchar *pdatestr = gnc_ctime (&pdate);
+ PINFO ("Destroying empty split %p from transaction %s (%s)", split, pdatestr, xaccTransGetDescription(txn));
+ xaccSplitDestroy (split);
+ deleted_split = TRUE;
+ }
}
LEAVE ("(split=%p)", split);
+ return deleted_split;
}
/* ============================================================== */
@@ -563,7 +577,7 @@ gncScrubBusinessAccountSplits (Account *acc, QofPercentageFunc percentagefunc)
{
SplitList *splits, *node;
gint split_count = 0;
- gint curr_split_no = 0;
+ gint curr_split_no;
const gchar *str;
const char *message = _( "Checking business splits in account %s: %u of %u");
@@ -577,6 +591,8 @@ gncScrubBusinessAccountSplits (Account *acc, QofPercentageFunc percentagefunc)
PINFO ("Cleaning up superfluous lot links in account %s \n", str);
xaccAccountBeginEdit(acc);
+restart:
+ curr_split_no = 0;
splits = xaccAccountGetSplitList(acc);
split_count = g_list_length (splits);
for (node = splits; node; node = node->next)
@@ -594,7 +610,10 @@ gncScrubBusinessAccountSplits (Account *acc, QofPercentageFunc percentagefunc)
}
if (split)
- gncScrubBusinessSplit (split);
+ // If gncScrubBusinessSplit returns true, a split was deleted and hence
+ // The account split list has become invalid, so we need to start over
+ if (gncScrubBusinessSplit (split))
+ goto restart;
PINFO("Finished processing split %d of %d",
curr_split_no + 1, split_count);
diff --git a/src/engine/ScrubBusiness.h b/src/engine/ScrubBusiness.h
index e4be74f..0cfce50 100644
--- a/src/engine/ScrubBusiness.h
+++ b/src/engine/ScrubBusiness.h
@@ -57,7 +57,9 @@ gboolean gncScrubBusinessLot (GNCLot *lot);
/** The gncScrubBusinessSplit() function will fix all issues found with
* the given split.
*
- * Currently this function only does one thing: check if the split is
+ * Current checks are:
+ *
+ * * check if the split is
* part of a transaction that was generated as the result of a doubly
* posted invoice/bill/credit note. Refer to
* https://bugzilla.gnome.org/show_bug.cgi?id=754209 to learn how this
@@ -66,8 +68,11 @@ gboolean gncScrubBusinessLot (GNCLot *lot);
* a warning is written to the trace file. Considering the user may
* already have added a correcting transaction we leave it up to the user
* to decide whether to also delete the transaction or not.
+ *
+ * * remove empty splits, on condition they aren't part of an invoice transaction.
+ * In this case the function returns true so the caller knows a split was removed.
*/
-void gncScrubBusinessSplit (Split *split);
+gboolean gncScrubBusinessSplit (Split *split);
/** The gncScrubBusinessAccountLots() function will call
* gncScrubBusinessLot() on each lot in the given account.
commit d52f44a8c7055a1c91477abacfae5130de9cf569
Author: Geert Janssens <janssens-geert at telenet.be>
Date: Sun Nov 6 17:11:30 2016 +0100
When juggling business splits while scrubbing set both value and amount
With only value there were several warnings in the log file during scrubbing
diff --git a/src/engine/gncOwner.c b/src/engine/gncOwner.c
index c55dd5c..e8e6295 100644
--- a/src/engine/gncOwner.c
+++ b/src/engine/gncOwner.c
@@ -971,10 +971,12 @@ gncOwnerReduceSplitTo (Split *split, gnc_numeric target_value)
rem_val = gnc_numeric_sub (split_val, target_value, GNC_DENOM_AUTO, GNC_HOW_DENOM_LCD); // note: values are of opposite sign
rem_split = xaccMallocSplit (xaccSplitGetBook (split));
xaccSplitCopyOnto (split, rem_split);
+ xaccSplitSetAmount (rem_split, rem_val);
xaccSplitSetValue (rem_split, rem_val);
txn = xaccSplitGetParent (split);
xaccTransBeginEdit (txn);
+ xaccSplitSetAmount (split, target_value);
xaccSplitSetValue (split, target_value);
xaccSplitSetParent (rem_split, txn);
xaccTransCommitEdit (txn);
commit 0bcd30301e8ae747bff8bea53a19a432a0ed9d5e
Author: Geert Janssens <janssens-geert at telenet.be>
Date: Sun Nov 6 17:10:30 2016 +0100
Update progress bar while running Check & Repair
Not complete - should still be added for check & repair invoked from a split register
diff --git a/src/engine/Scrub.c b/src/engine/Scrub.c
index 4146f9b..8588656 100644
--- a/src/engine/Scrub.c
+++ b/src/engine/Scrub.c
@@ -59,13 +59,13 @@ static QofLogModule log_module = G_LOG_DOMAIN;
/* ================================================================ */
void
-xaccAccountTreeScrubOrphans (Account *acc)
+xaccAccountTreeScrubOrphans (Account *acc, QofPercentageFunc percentagefunc)
{
if (!acc) return;
- xaccAccountScrubOrphans (acc);
+ xaccAccountScrubOrphans (acc, percentagefunc);
gnc_account_foreach_descendant(acc,
- (AccountCb)xaccAccountScrubOrphans, NULL);
+ (AccountCb)xaccAccountScrubOrphans, percentagefunc);
}
static void
@@ -99,24 +99,38 @@ TransScrubOrphansFast (Transaction *trans, Account *root)
}
void
-xaccAccountScrubOrphans (Account *acc)
+xaccAccountScrubOrphans (Account *acc, QofPercentageFunc percentagefunc)
{
- GList *node;
+ GList *node, *splits;
const char *str;
+ const char *message = _( "Looking for orphans in account %s: %u of %u");
+ guint total_splits = 0;
+ guint current_split = 0;
if (!acc) return;
str = xaccAccountGetName (acc);
str = str ? str : "(null)";
PINFO ("Looking for orphans in account %s \n", str);
+ splits = xaccAccountGetSplitList(acc);
+ total_splits = g_list_length (splits);
- for (node = xaccAccountGetSplitList(acc); node; node = node->next)
+ for (node = splits; node; node = node->next)
{
Split *split = node->data;
+ if (current_split % 100 == 0)
+ {
+ char *progress_msg = g_strdup_printf (message, str, current_split, total_splits);
+ (percentagefunc)(progress_msg, (100 * current_split) / total_splits);
+ g_free (progress_msg);
+ }
+
TransScrubOrphansFast (xaccSplitGetParent (split),
gnc_account_get_root (acc));
+ current_split++;
}
+ (percentagefunc)(NULL, -1.0);
}
@@ -273,25 +287,26 @@ xaccSplitScrub (Split *split)
/* ================================================================ */
void
-xaccAccountTreeScrubImbalance (Account *acc)
+xaccAccountTreeScrubImbalance (Account *acc, QofPercentageFunc percentagefunc)
{
- xaccAccountScrubImbalance (acc);
+ xaccAccountScrubImbalance (acc, percentagefunc);
gnc_account_foreach_descendant(acc,
- (AccountCb)xaccAccountScrubImbalance, NULL);
+ (AccountCb)xaccAccountScrubImbalance, percentagefunc);
}
void
-xaccAccountScrubImbalance (Account *acc)
+xaccAccountScrubImbalance (Account *acc, QofPercentageFunc percentagefunc)
{
GList *node, *splits;
const char *str;
- gint split_count = 0, curr_split_no = 1;
+ const char *message = _( "Looking for imbalances in account %s: %u of %u");
+ gint split_count = 0, curr_split_no = 0;
if (!acc) return;
str = xaccAccountGetName(acc);
str = str ? str : "(null)";
- PINFO ("Looking for imbalance in account %s \n", str);
+ PINFO ("Looking for imbalances in account %s \n", str);
splits = xaccAccountGetSplitList(acc);
split_count = g_list_length (splits);
@@ -301,16 +316,28 @@ xaccAccountScrubImbalance (Account *acc)
Transaction *trans = xaccSplitGetParent(split);
PINFO("Start processing split %d of %d",
- curr_split_no, split_count);
+ curr_split_no + 1, split_count);
+
+ if (curr_split_no % 100 == 0)
+ {
+ char *progress_msg = g_strdup_printf (message, str, curr_split_no, split_count);
+ (percentagefunc)(progress_msg, (100 * curr_split_no) / split_count);
+ g_free (progress_msg);
+ }
+
+ TransScrubOrphansFast (xaccSplitGetParent (split),
+ gnc_account_get_root (acc));
+ (percentagefunc)(NULL, 0.0);
xaccTransScrubCurrency(trans);
xaccTransScrubImbalance (trans, gnc_account_get_root (acc), NULL);
PINFO("Finished processing split %d of %d",
- curr_split_no, split_count);
+ curr_split_no + 1, split_count);
curr_split_no++;
}
+ (percentagefunc)(NULL, -1.0);
}
static Split *
diff --git a/src/engine/Scrub.h b/src/engine/Scrub.h
index efdad1b..d57fadf 100644
--- a/src/engine/Scrub.h
+++ b/src/engine/Scrub.h
@@ -77,12 +77,12 @@ void xaccTransScrubOrphans (Transaction *trans);
/** The xaccAccountScrubOrphans() method performs this scrub only for the
* indicated account, and not for any of its children.
*/
-void xaccAccountScrubOrphans (Account *acc);
+void xaccAccountScrubOrphans (Account *acc, QofPercentageFunc percentagefunc);
/** The xaccAccountTreeScrubOrphans() method performs this scrub for the
* indicated account and its children.
*/
-void xaccAccountTreeScrubOrphans (Account *acc);
+void xaccAccountTreeScrubOrphans (Account *acc, QofPercentageFunc percentagefunc);
/** The xaccSplitScrub method ensures that if this split has the same
* commodity and currency, then it will have the same amount and value.
@@ -108,8 +108,8 @@ void xaccAccountTreeScrubSplits (Account *account);
*/
void xaccTransScrubImbalance (Transaction *trans, Account *root,
Account *parent);
-void xaccAccountScrubImbalance (Account *acc);
-void xaccAccountTreeScrubImbalance (Account *acc);
+void xaccAccountScrubImbalance (Account *acc, QofPercentageFunc percentagefunc);
+void xaccAccountTreeScrubImbalance (Account *acc, QofPercentageFunc percentagefunc);
/** The xaccTransScrubCurrency method fixes transactions without a
* common_currency by looking for the most commonly used currency
diff --git a/src/engine/ScrubBusiness.c b/src/engine/ScrubBusiness.c
index f93619b..cd69468 100644
--- a/src/engine/ScrubBusiness.c
+++ b/src/engine/ScrubBusiness.c
@@ -509,12 +509,13 @@ gncScrubBusinessSplit (Split *split)
/* ============================================================== */
void
-gncScrubBusinessAccountLots (Account *acc)
+gncScrubBusinessAccountLots (Account *acc, QofPercentageFunc percentagefunc)
{
LotList *lots, *node;
gint lot_count = 0;
- gint curr_lot_no = 1;
+ gint curr_lot_no = 0;
const gchar *str;
+ const char *message = _( "Checking business lots in account %s: %u of %u");
if (!acc) return;
if (FALSE == xaccAccountIsAPARType (xaccAccountGetType (acc))) return;
@@ -533,29 +534,38 @@ gncScrubBusinessAccountLots (Account *acc)
GNCLot *lot = node->data;
PINFO("Start processing lot %d of %d",
- curr_lot_no, lot_count);
+ curr_lot_no + 1, lot_count);
+
+ if (curr_lot_no % 100 == 0)
+ {
+ char *progress_msg = g_strdup_printf (message, str, curr_lot_no, lot_count);
+ (percentagefunc)(progress_msg, (100 * curr_lot_no) / lot_count);
+ g_free (progress_msg);
+ }
if (lot)
gncScrubBusinessLot (lot);
PINFO("Finished processing lot %d of %d",
- curr_lot_no, lot_count);
+ curr_lot_no + 1, lot_count);
curr_lot_no++;
}
g_list_free(lots);
xaccAccountCommitEdit(acc);
+ (percentagefunc)(NULL, -1.0);
LEAVE ("(acc=%s)", str);
}
/* ============================================================== */
void
-gncScrubBusinessAccountSplits (Account *acc)
+gncScrubBusinessAccountSplits (Account *acc, QofPercentageFunc percentagefunc)
{
SplitList *splits, *node;
gint split_count = 0;
- gint curr_split_no = 1;
+ gint curr_split_no = 0;
const gchar *str;
+ const char *message = _( "Checking business splits in account %s: %u of %u");
if (!acc) return;
if (FALSE == xaccAccountIsAPARType (xaccAccountGetType (acc))) return;
@@ -574,29 +584,37 @@ gncScrubBusinessAccountSplits (Account *acc)
Split *split = node->data;
PINFO("Start processing split %d of %d",
- curr_split_no, split_count);
+ curr_split_no + 1, split_count);
+
+ if (curr_split_no % 100 == 0)
+ {
+ char *progress_msg = g_strdup_printf (message, str, curr_split_no, split_count);
+ (percentagefunc)(progress_msg, (100 * curr_split_no) / split_count);
+ g_free (progress_msg);
+ }
if (split)
gncScrubBusinessSplit (split);
PINFO("Finished processing split %d of %d",
- curr_split_no, split_count);
+ curr_split_no + 1, split_count);
curr_split_no++;
}
xaccAccountCommitEdit(acc);
+ (percentagefunc)(NULL, -1.0);
LEAVE ("(acc=%s)", str);
}
/* ============================================================== */
void
-gncScrubBusinessAccount (Account *acc)
+gncScrubBusinessAccount (Account *acc, QofPercentageFunc percentagefunc)
{
if (!acc) return;
if (FALSE == xaccAccountIsAPARType (xaccAccountGetType (acc))) return;
- gncScrubBusinessAccountLots (acc);
- gncScrubBusinessAccountSplits (acc);
+ gncScrubBusinessAccountLots (acc, percentagefunc);
+ gncScrubBusinessAccountSplits (acc, percentagefunc);
}
/* ============================================================== */
@@ -605,16 +623,16 @@ static void
lot_scrub_cb (Account *acc, gpointer data)
{
if (FALSE == xaccAccountIsAPARType (xaccAccountGetType (acc))) return;
- gncScrubBusinessAccount (acc);
+ gncScrubBusinessAccount (acc, data);
}
void
-gncScrubBusinessAccountTree (Account *acc)
+gncScrubBusinessAccountTree (Account *acc, QofPercentageFunc percentagefunc)
{
if (!acc) return;
- gnc_account_foreach_descendant(acc, lot_scrub_cb, NULL);
- gncScrubBusinessAccount (acc);
+ gnc_account_foreach_descendant(acc, lot_scrub_cb, percentagefunc);
+ gncScrubBusinessAccount (acc, percentagefunc);
}
/* ========================== END OF FILE ========================= */
diff --git a/src/engine/ScrubBusiness.h b/src/engine/ScrubBusiness.h
index cbf31d5..e4be74f 100644
--- a/src/engine/ScrubBusiness.h
+++ b/src/engine/ScrubBusiness.h
@@ -76,12 +76,12 @@ void gncScrubBusinessSplit (Split *split);
* lot structure of every lot of a business account is in good
* order.
*/
-void gncScrubBusinessAccountLots (Account *acc);
+void gncScrubBusinessAccountLots (Account *acc, QofPercentageFunc percentagefunc);
/** The gncScrubBusinessAccountSplits() function will call
* gncScrubBusinessSplit() on each split in the given account.
*/
-void gncScrubBusinessAccountSplits (Account *acc);
+void gncScrubBusinessAccountSplits (Account *acc, QofPercentageFunc percentagefunc);
/** The gncScrubBusinessAccount() function will call
* all scrub functions relevant for a given account
@@ -91,13 +91,13 @@ void gncScrubBusinessAccountSplits (Account *acc);
* This routine is the primary routine for fixing all
* (known) issues in a business account.
*/
-void gncScrubBusinessAccount (Account *acc);
+void gncScrubBusinessAccount (Account *acc, QofPercentageFunc percentagefunc);
/** The gncScrubBusinessAccountTreeLots() function will call
* gncScrubBusinessAccount() on the given account
* and its sub accounts.
*/
-void gncScrubBusinessAccountTree (Account *acc);
+void gncScrubBusinessAccountTree (Account *acc, QofPercentageFunc percentagefunc);
/** @} */
#endif /* GNC_SCRUBBUSINESS_H */
diff --git a/src/gnome/dialog-lot-viewer.c b/src/gnome/dialog-lot-viewer.c
index b5e44b3..0bc919d 100644
--- a/src/gnome/dialog-lot-viewer.c
+++ b/src/gnome/dialog-lot-viewer.c
@@ -48,6 +48,7 @@
#include "gnc-component-manager.h"
#include "gnc-prefs.h"
#include "gnc-ui-util.h"
+#include "gnc-window.h"
#include "misc-gnome-utils.h"
#include "tree-view-utils.h"
@@ -762,7 +763,7 @@ lv_response_cb (GtkDialog *dialog, gint response, gpointer data)
case RESPONSE_SCRUB_ACCOUNT:
gnc_suspend_gui_refresh ();
if (xaccAccountIsAPARType (xaccAccountGetType(lv->account)))
- gncScrubBusinessAccountLots (lv->account);
+ gncScrubBusinessAccountLots (lv->account, gnc_window_show_progress);
else
xaccAccountScrubLots (lv->account);
gnc_resume_gui_refresh ();
diff --git a/src/gnome/gnc-plugin-page-account-tree.c b/src/gnome/gnc-plugin-page-account-tree.c
index 7864e57..ce67bd6 100644
--- a/src/gnome/gnc-plugin-page-account-tree.c
+++ b/src/gnome/gnc-plugin-page-account-tree.c
@@ -63,6 +63,7 @@
#include "gnc-tree-model-account-types.h"
#include "gnc-ui.h"
#include "gnc-ui-util.h"
+#include "gnc-window.h"
#include "dialog-lot-viewer.h"
#include "window-reconcile.h"
#include "window-autoclear.h"
@@ -1561,19 +1562,23 @@ static void
gnc_plugin_page_account_tree_cmd_scrub (GtkAction *action, GncPluginPageAccountTree *page)
{
Account *account = gnc_plugin_page_account_tree_get_current_account (page);
+ GncWindow *window;
g_return_if_fail (account != NULL);
gnc_suspend_gui_refresh ();
- xaccAccountScrubOrphans (account);
- xaccAccountScrubImbalance (account);
+ window = GNC_WINDOW(GNC_PLUGIN_PAGE (page)->window);
+ gnc_window_set_progressbar_window (window);
+
+ xaccAccountScrubOrphans (account, gnc_window_show_progress);
+ xaccAccountScrubImbalance (account, gnc_window_show_progress);
// XXX: Lots/capital gains scrubbing is disabled
if (g_getenv("GNC_AUTO_SCRUB_LOTS") != NULL)
xaccAccountScrubLots(account);
- gncScrubBusinessAccount(account);
+ gncScrubBusinessAccount(account, gnc_window_show_progress);
gnc_resume_gui_refresh ();
@@ -1583,19 +1588,23 @@ static void
gnc_plugin_page_account_tree_cmd_scrub_sub (GtkAction *action, GncPluginPageAccountTree *page)
{
Account *account = gnc_plugin_page_account_tree_get_current_account (page);
+ GncWindow *window;
g_return_if_fail (account != NULL);
gnc_suspend_gui_refresh ();
- xaccAccountTreeScrubOrphans (account);
- xaccAccountTreeScrubImbalance (account);
+ window = GNC_WINDOW(GNC_PLUGIN_PAGE (page)->window);
+ gnc_window_set_progressbar_window (window);
+
+ xaccAccountTreeScrubOrphans (account, gnc_window_show_progress);
+ xaccAccountTreeScrubImbalance (account, gnc_window_show_progress);
// XXX: Lots/capital gains scrubbing is disabled
if (g_getenv("GNC_AUTO_SCRUB_LOTS") != NULL)
xaccAccountTreeScrubLots(account);
- gncScrubBusinessAccountTree(account);
+ gncScrubBusinessAccountTree(account, gnc_window_show_progress);
gnc_resume_gui_refresh ();
}
@@ -1604,16 +1613,20 @@ static void
gnc_plugin_page_account_tree_cmd_scrub_all (GtkAction *action, GncPluginPageAccountTree *page)
{
Account *root = gnc_get_current_root_account ();
+ GncWindow *window;
gnc_suspend_gui_refresh ();
- xaccAccountTreeScrubOrphans (root);
- xaccAccountTreeScrubImbalance (root);
+ window = GNC_WINDOW(GNC_PLUGIN_PAGE (page)->window);
+ gnc_window_set_progressbar_window (window);
+
+ xaccAccountTreeScrubOrphans (root, gnc_window_show_progress);
+ xaccAccountTreeScrubImbalance (root, gnc_window_show_progress);
// XXX: Lots/capital gains scrubbing is disabled
if (g_getenv("GNC_AUTO_SCRUB_LOTS") != NULL)
xaccAccountTreeScrubLots(root);
- gncScrubBusinessAccountTree(root);
+ gncScrubBusinessAccountTree(root, gnc_window_show_progress);
gnc_resume_gui_refresh ();
}
diff --git a/src/gnome/gnc-plugin-page-register.c b/src/gnome/gnc-plugin-page-register.c
index 88b03a5..0585617 100644
--- a/src/gnome/gnc-plugin-page-register.c
+++ b/src/gnome/gnc-plugin-page-register.c
@@ -3792,8 +3792,10 @@ gnc_plugin_page_register_cmd_scrub_all (GtkAction *action,
GncPluginPageRegisterPrivate *priv;
Query *query;
Account *root;
+ GncWindow *window;
GList *node, *splits;
- gint split_count = 0, curr_split_no = 1;
+ gint split_count = 0, curr_split_no = 0;
+ const char *message = _( "Checking splits in current register: %u of %u");
g_return_if_fail(GNC_IS_PLUGIN_PAGE_REGISTER(plugin_page));
@@ -3808,6 +3810,9 @@ gnc_plugin_page_register_cmd_scrub_all (GtkAction *action,
}
gnc_suspend_gui_refresh();
+ window = GNC_WINDOW(GNC_PLUGIN_PAGE (plugin_page)->window);
+ gnc_window_set_progressbar_window (window);
+
root = gnc_get_current_root_account();
splits = qof_query_run(query);
@@ -3818,9 +3823,17 @@ gnc_plugin_page_register_cmd_scrub_all (GtkAction *action,
Split *split = node->data;
Transaction *trans = xaccSplitGetParent(split);
+ if (!split) continue;
PINFO("Start processing split %d of %d",
- curr_split_no, split_count);
+ curr_split_no + 1, split_count);
+
+ if (curr_split_no % 100 == 0)
+ {
+ char *progress_msg = g_strdup_printf (message, curr_split_no, split_count);
+ gnc_window_show_progress (progress_msg, (100 * curr_split_no) / split_count);
+ g_free (progress_msg);
+ }
xaccTransScrubOrphans(trans);
xaccTransScrubImbalance(trans, root, NULL);
@@ -3833,10 +3846,11 @@ gnc_plugin_page_register_cmd_scrub_all (GtkAction *action,
}
PINFO("Finished processing split %d of %d",
- curr_split_no, split_count);
+ curr_split_no + 1, split_count);
curr_split_no++;
}
+ gnc_window_show_progress (NULL, -1.0);
gnc_resume_gui_refresh();
LEAVE(" ");
}
diff --git a/src/gnome/window-reconcile.c b/src/gnome/window-reconcile.c
index 6813161..c1fb12b 100644
--- a/src/gnome/window-reconcile.c
+++ b/src/gnome/window-reconcile.c
@@ -54,6 +54,7 @@
#include "gnc-prefs.h"
#include "gnc-ui.h"
#include "gnc-ui-balances.h"
+#include "gnc-window.h"
#include "guile-util.h"
#include "reconcile-view.h"
#include "window-reconcile.h"
@@ -1407,8 +1408,8 @@ gnc_recn_scrub_cb(GtkAction *action, gpointer data)
gnc_suspend_gui_refresh ();
- xaccAccountTreeScrubOrphans (account);
- xaccAccountTreeScrubImbalance (account);
+ xaccAccountTreeScrubOrphans (account, gnc_window_show_progress);
+ xaccAccountTreeScrubImbalance (account, gnc_window_show_progress);
// XXX: Lots are disabled.
if (g_getenv("GNC_AUTO_SCRUB_LOTS") != NULL)
diff --git a/src/gnome/window-reconcile2.c b/src/gnome/window-reconcile2.c
index 4409b37..bcb121f 100644
--- a/src/gnome/window-reconcile2.c
+++ b/src/gnome/window-reconcile2.c
@@ -54,6 +54,7 @@
#include "gnc-prefs.h"
#include "gnc-ui.h"
#include "gnc-ui-balances.h"
+#include "gnc-window.h"
#include "guile-util.h"
#include "reconcile-view.h"
#include "window-reconcile2.h"
@@ -1370,8 +1371,8 @@ gnc_recn_scrub_cb (GtkAction *action, gpointer data)
gnc_suspend_gui_refresh ();
- xaccAccountTreeScrubOrphans (account);
- xaccAccountTreeScrubImbalance (account);
+ xaccAccountTreeScrubOrphans (account, gnc_window_show_progress);
+ xaccAccountTreeScrubImbalance (account, gnc_window_show_progress);
// XXX: Lots are disabled.
if (g_getenv("GNC_AUTO_SCRUB_LOTS") != NULL)
commit 673888dee7c972d2ed8470ccc28c466162910a6d
Author: Geert Janssens <janssens-geert at telenet.be>
Date: Wed Nov 9 18:41:05 2016 +0100
Remove lot from account while deleting the lot
There was no way the account was informed about the lot being deleted.
This was resulting into invalid lot lists in an account while scrubbing.
Which would bomb at later stages like when re-running check & repair or
opening the lot viewer. Also saving would report a number of critical messages
about invalid objects, but these didn't result in a segfault.
diff --git a/src/engine/gnc-lot.c b/src/engine/gnc-lot.c
index ce780c4..3afb296 100644
--- a/src/engine/gnc-lot.c
+++ b/src/engine/gnc-lot.c
@@ -227,6 +227,9 @@ gnc_lot_free(GNCLot* lot)
}
g_list_free (priv->splits);
+ if (priv->account)
+ xaccAccountRemoveLot (priv->account, lot);
+
priv->account = NULL;
priv->is_closed = TRUE;
/* qof_instance_release (&lot->inst); */
Summary of changes:
src/engine/Scrub.c | 55 ++++++++---
src/engine/Scrub.h | 8 +-
src/engine/Scrub2.c | 16 +++-
src/engine/ScrubBusiness.c | 151 +++++++++++++++++++++++++------
src/engine/ScrubBusiness.h | 17 ++--
src/engine/gnc-lot.c | 3 +
src/engine/gncInvoice.c | 6 +-
src/engine/gncInvoiceP.h | 4 +
src/engine/gncOwner.c | 2 +
src/gnome/dialog-lot-viewer.c | 27 +++---
src/gnome/gnc-plugin-page-account-tree.c | 31 +++++--
src/gnome/gnc-plugin-page-register.c | 20 +++-
src/gnome/window-reconcile.c | 5 +-
src/gnome/window-reconcile2.c | 5 +-
14 files changed, 268 insertions(+), 82 deletions(-)
More information about the gnucash-changes
mailing list