mirror of
https://github.com/Gnucash/gnucash.git
synced 2024-11-26 02:40:43 -06:00
Merge branch 'scrub-optimize' into stable
This commit is contained in:
commit
ccc75cfc88
@ -53,6 +53,8 @@
|
||||
#include "gnc-commodity.h"
|
||||
#include "qofinstance-p.h"
|
||||
#include "gnc-session.h"
|
||||
#include "qofquery.h"
|
||||
#include "Query.h"
|
||||
|
||||
#undef G_LOG_DOMAIN
|
||||
#define G_LOG_DOMAIN "gnc.engine.scrub"
|
||||
@ -89,47 +91,43 @@ gnc_get_ongoing_scrub (void)
|
||||
|
||||
/* ================================================================ */
|
||||
|
||||
void
|
||||
xaccAccountTreeScrubOrphans (Account *acc, QofPercentageFunc percentagefunc)
|
||||
static GList*
|
||||
get_all_transactions (Account *account, bool descendants)
|
||||
{
|
||||
if (!acc) return;
|
||||
|
||||
if (abort_now)
|
||||
(percentagefunc)(NULL, -1.0);
|
||||
|
||||
scrub_depth ++;
|
||||
xaccAccountScrubOrphans (acc, percentagefunc);
|
||||
gnc_account_foreach_descendant(acc,
|
||||
(AccountCb)xaccAccountScrubOrphans, percentagefunc);
|
||||
scrub_depth--;
|
||||
GList *accounts = descendants ? gnc_account_get_descendants (account) : NULL;
|
||||
accounts = g_list_prepend (accounts, account);
|
||||
QofQuery *q = qof_query_create_for (GNC_ID_TRANS);
|
||||
QofBook *book = qof_session_get_book (gnc_get_current_session ());
|
||||
qof_query_set_book (q, book);
|
||||
xaccQueryAddAccountMatch (q, accounts, QOF_GUID_MATCH_ANY, QOF_QUERY_AND);
|
||||
GList *transactions = g_list_copy (qof_query_run (q));
|
||||
qof_query_destroy (q);
|
||||
return transactions;
|
||||
}
|
||||
|
||||
/* ================================================================ */
|
||||
|
||||
static void
|
||||
TransScrubOrphansFast (Transaction *trans, Account *root)
|
||||
{
|
||||
GList *node;
|
||||
gchar *accname;
|
||||
g_return_if_fail (trans && trans->common_currency && root);
|
||||
|
||||
if (!trans) return;
|
||||
g_return_if_fail (root);
|
||||
g_return_if_fail (trans->common_currency);
|
||||
|
||||
for (node = trans->splits; node; node = node->next)
|
||||
for (GList *node = trans->splits; node; node = node->next)
|
||||
{
|
||||
Split *split = node->data;
|
||||
Account *orph;
|
||||
if (abort_now) break;
|
||||
|
||||
if (split->acc) continue;
|
||||
|
||||
DEBUG ("Found an orphan\n");
|
||||
|
||||
accname = g_strconcat (_("Orphan"), "-",
|
||||
gnc_commodity_get_mnemonic (trans->common_currency),
|
||||
NULL);
|
||||
orph = xaccScrubUtilityGetOrMakeAccount (root, trans->common_currency,
|
||||
accname, ACCT_TYPE_BANK,
|
||||
FALSE, TRUE);
|
||||
gchar *accname = g_strconcat
|
||||
(_("Orphan"), "-", gnc_commodity_get_mnemonic (trans->common_currency),
|
||||
NULL);
|
||||
|
||||
Account *orph = xaccScrubUtilityGetOrMakeAccount
|
||||
(root, trans->common_currency, accname, ACCT_TYPE_BANK, false, true);
|
||||
|
||||
g_free (accname);
|
||||
if (!orph) continue;
|
||||
|
||||
@ -137,43 +135,47 @@ TransScrubOrphansFast (Transaction *trans, Account *root)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
xaccAccountScrubOrphans (Account *acc, QofPercentageFunc percentagefunc)
|
||||
static void
|
||||
AccountScrubOrphans (Account *acc, bool descendants, QofPercentageFunc percentagefunc)
|
||||
{
|
||||
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;
|
||||
scrub_depth++;
|
||||
|
||||
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);
|
||||
GList *transactions = get_all_transactions (acc, descendants);
|
||||
gint total_trans = g_list_length (transactions);
|
||||
const char *message = _( "Looking for orphans in transaction: %u of %u");
|
||||
guint current_trans = 0;
|
||||
|
||||
for (node = splits; node; node = node->next)
|
||||
for (GList *node = transactions; node; current_trans++, node = node->next)
|
||||
{
|
||||
Split *split = node->data;
|
||||
if (current_split % 10 == 0)
|
||||
Transaction *trans = node->data;
|
||||
if (current_trans % 10 == 0)
|
||||
{
|
||||
char *progress_msg = g_strdup_printf (message, str, current_split, total_splits);
|
||||
(percentagefunc)(progress_msg, (100 * current_split) / total_splits);
|
||||
char *progress_msg = g_strdup_printf (message, current_trans, total_trans);
|
||||
(percentagefunc)(progress_msg, (100 * current_trans) / total_trans);
|
||||
g_free (progress_msg);
|
||||
if (abort_now) break;
|
||||
}
|
||||
|
||||
TransScrubOrphansFast (xaccSplitGetParent (split),
|
||||
gnc_account_get_root (acc));
|
||||
current_split++;
|
||||
TransScrubOrphansFast (trans, gnc_account_get_root (acc));
|
||||
}
|
||||
(percentagefunc)(NULL, -1.0);
|
||||
scrub_depth--;
|
||||
|
||||
g_list_free (transactions);
|
||||
}
|
||||
|
||||
void
|
||||
xaccAccountScrubOrphans (Account *acc, QofPercentageFunc percentagefunc)
|
||||
{
|
||||
AccountScrubOrphans (acc, false, percentagefunc);
|
||||
}
|
||||
|
||||
void
|
||||
xaccAccountTreeScrubOrphans (Account *acc, QofPercentageFunc percentagefunc)
|
||||
{
|
||||
AccountScrubOrphans (acc, true, percentagefunc);
|
||||
}
|
||||
|
||||
void
|
||||
xaccTransScrubOrphans (Transaction *trans)
|
||||
@ -350,6 +352,49 @@ split_scrub_or_dry_run (Split *split, bool dry_run)
|
||||
|
||||
/* ================================================================ */
|
||||
|
||||
|
||||
static void
|
||||
AccountScrubImbalance (Account *acc, bool descendants,
|
||||
QofPercentageFunc percentagefunc)
|
||||
{
|
||||
const char *message = _( "Looking for imbalances in transaction date %s: %u of %u");
|
||||
|
||||
if (!acc) return;
|
||||
|
||||
QofBook *book = qof_session_get_book (gnc_get_current_session ());
|
||||
Account *root = gnc_book_get_root_account (book);
|
||||
GList *transactions = get_all_transactions (acc, descendants);
|
||||
guint count = g_list_length (transactions), curr_trans = 0;
|
||||
|
||||
scrub_depth++;
|
||||
for (GList *node = transactions; node; node = node->next, curr_trans++)
|
||||
{
|
||||
Transaction *trans = node->data;
|
||||
if (abort_now) break;
|
||||
|
||||
PINFO("Start processing transaction %d of %d", curr_trans + 1, count);
|
||||
|
||||
if (curr_trans % 10 == 0)
|
||||
{
|
||||
char *date = qof_print_date (xaccTransGetDate (trans));
|
||||
char *progress_msg = g_strdup_printf (message, date, curr_trans, count);
|
||||
(percentagefunc)(progress_msg, (100 * curr_trans) / count);
|
||||
g_free (progress_msg);
|
||||
g_free (date);
|
||||
}
|
||||
|
||||
TransScrubOrphansFast (trans, root);
|
||||
xaccTransScrubCurrency(trans);
|
||||
xaccTransScrubImbalance (trans, root, NULL);
|
||||
|
||||
PINFO("Finished processing transaction %d of %d", curr_trans + 1, count);
|
||||
}
|
||||
(percentagefunc)(NULL, -1.0);
|
||||
scrub_depth--;
|
||||
|
||||
g_list_free (transactions);
|
||||
}
|
||||
|
||||
void
|
||||
xaccTransScrubSplits (Transaction *trans)
|
||||
{
|
||||
@ -391,75 +436,13 @@ xaccSplitScrub (Split *split)
|
||||
void
|
||||
xaccAccountTreeScrubImbalance (Account *acc, QofPercentageFunc percentagefunc)
|
||||
{
|
||||
if (!acc) return;
|
||||
|
||||
if (abort_now)
|
||||
(percentagefunc)(NULL, -1.0);
|
||||
|
||||
scrub_depth++;
|
||||
xaccAccountScrubImbalance (acc, percentagefunc);
|
||||
gnc_account_foreach_descendant(acc,
|
||||
(AccountCb)xaccAccountScrubImbalance, percentagefunc);
|
||||
scrub_depth--;
|
||||
AccountScrubImbalance (acc, true, percentagefunc);
|
||||
}
|
||||
|
||||
void
|
||||
xaccAccountScrubImbalance (Account *acc, QofPercentageFunc percentagefunc)
|
||||
{
|
||||
GList *node, *splits;
|
||||
const char *str;
|
||||
const char *message = _( "Looking for imbalances in account %s: %u of %u");
|
||||
gint split_count = 0, curr_split_no = 0;
|
||||
|
||||
if (!acc) return;
|
||||
/* If it's a trading account and an imbalanced transaction is
|
||||
* found the trading splits will be replaced, invalidating the
|
||||
* split list in mid-traversal, see
|
||||
* https://bugs.gnucash.org/show_bug.cgi?id=798346. Also the
|
||||
* transactions will get scrubbed at least twice from their "real"
|
||||
* accounts anyway so doing so from the trading accounts is wasted
|
||||
* effort.
|
||||
*/
|
||||
if (xaccAccountGetType(acc) == ACCT_TYPE_TRADING)
|
||||
return;
|
||||
|
||||
scrub_depth++;
|
||||
|
||||
str = xaccAccountGetName(acc);
|
||||
str = str ? str : "(null)";
|
||||
PINFO ("Looking for imbalances in account %s\n", str);
|
||||
|
||||
splits = xaccAccountGetSplitList(acc);
|
||||
split_count = g_list_length (splits);
|
||||
for (node = splits; node; node = node->next)
|
||||
{
|
||||
Split *split = node->data;
|
||||
Transaction *trans = xaccSplitGetParent(split);
|
||||
if (abort_now) break;
|
||||
|
||||
PINFO("Start processing split %d of %d",
|
||||
curr_split_no + 1, split_count);
|
||||
|
||||
if (curr_split_no % 10 == 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));
|
||||
|
||||
xaccTransScrubCurrency(trans);
|
||||
|
||||
xaccTransScrubImbalance (trans, gnc_account_get_root (acc), NULL);
|
||||
|
||||
PINFO("Finished processing split %d of %d",
|
||||
curr_split_no + 1, split_count);
|
||||
curr_split_no++;
|
||||
}
|
||||
(percentagefunc)(NULL, -1.0);
|
||||
scrub_depth--;
|
||||
AccountScrubImbalance (acc, false, percentagefunc);
|
||||
}
|
||||
|
||||
static Split *
|
||||
|
Loading…
Reference in New Issue
Block a user