42 #include <glib/gi18n.h>
51 #include "TransactionP.h"
55 #define G_LOG_DOMAIN "gnc.engine.scrub"
78 g_return_if_fail (root);
80 for (node = trans->splits; node; node = node->next)
82 Split *split = node->data;
85 if (split->acc)
continue;
87 DEBUG (
"Found an orphan \n");
89 accname = g_strconcat (_(
"Orphan"),
"-",
92 orph = xaccScrubUtilityGetOrMakeAccount (root, trans->common_currency,
97 xaccSplitSetAccount(split, orph);
110 str = str ? str :
"(null)";
111 PINFO (
"Looking for orphans in account %s \n", str);
115 Split *split = node->data;
132 for (node = trans->splits; node; node = node->next)
134 Split *split = node->data;
148 PINFO (
"Free Floating Transaction!");
150 root = gnc_book_get_root_account (book);
151 TransScrubOrphansFast (trans, root);
157 xaccAccountTreeScrubSplits (
Account *account)
159 if (!account)
return;
161 xaccAccountScrubSplits (account);
163 (AccountCb)xaccAccountScrubSplits, NULL);
167 xaccAccountScrubSplits (
Account *account)
185 ENTER (
"(split=%p)", split);
211 PINFO (
"Free Floating Transaction!");
212 LEAVE (
"no account");
220 value = gnc_numeric_zero();
227 amount = gnc_numeric_zero();
243 LEAVE (
"(split=%p) inequiv currency", split);
252 LEAVE(
"(split=%p) different values", split);
260 PINFO (
"Adjusted split with mismatched values, desc=\"%s\" memo=\"%s\""
261 " old amount %s %s, new amount %s",
262 trans->description, split->memo,
270 LEAVE (
"(split=%p)", split);
276 xaccAccountTreeScrubImbalance (
Account *acc)
278 xaccAccountScrubImbalance (acc);
280 (AccountCb)xaccAccountScrubImbalance, NULL);
284 xaccAccountScrubImbalance (
Account *acc)
292 str = str ? str :
"(null)";
293 PINFO (
"Looking for imbalance in account %s \n", str);
297 Split *split = node->data;
310 Split *balance_split;
322 PERR (
"Bad data corruption, no root account in book");
326 accname = g_strconcat (_(
"Imbalance"),
"-",
328 account = xaccScrubUtilityGetOrMakeAccount (root, commodity,
333 PERR (
"Can't get balancing account");
338 balance_split = xaccTransFindSplitByAccount(trans, account);
346 xaccSplitSetParent(balance_split, trans);
347 xaccSplitSetAccount(balance_split, account);
351 return balance_split;
360 Split *balance_split;
372 PERR (
"Bad data corruption, no root account in book");
384 if (! default_currency)
386 default_currency = commodity;
389 trading_account = xaccScrubUtilityGetOrMakeAccount (root,
393 if (!trading_account)
395 PERR (
"Can't get trading account");
399 ns_account = xaccScrubUtilityGetOrMakeAccount (trading_account,
405 PERR (
"Can't get namespace account");
409 account = xaccScrubUtilityGetOrMakeAccount (ns_account, commodity,
414 PERR (
"Can't get commodity account");
419 balance_split = xaccTransFindSplitByAccount(trans, account);
427 xaccSplitSetParent(balance_split, trans);
428 xaccSplitSetAccount(balance_split, account);
432 return balance_split;
451 PERR (
"Bad data corruption, no root account in book");
457 if (!trading_account)
476 return xaccTransFindSplitByAccount(trans, account);
485 Split *balance_split;
488 balance_split = get_balance_split(trans, root, account, currency);
536 LEAVE (
"transaction is balanced");
550 PINFO (
"Value unbalanced transaction");
552 add_balance_split (trans, imbalance, root, account);
557 MonetaryList *imbal_list;
558 MonetaryList *imbalance_commod;
561 Split *balance_split = NULL;
573 imbalance = gnc_numeric_zero();
575 for (splits = trans->splits; splits; splits = splits->next)
577 Split *split = splits->data;
581 if (! xaccTransStillHasSplit (trans, split))
continue;
586 PERR(
"Split has no commodity");
590 balance_split = find_trading_split (trans, root, commodity);
592 if (balance_split != split)
603 if (balance_split && balance_split != split)
626 PINFO (
"Value unbalanced transaction");
628 add_balance_split (trans, imbalance, root, account);
635 LEAVE(
"transaction is balanced");
639 PINFO (
"Currency unbalanced transaction");
641 for (imbalance_commod = imbal_list; imbalance_commod;
642 imbalance_commod = imbalance_commod->next)
650 commodity = gnc_monetary_commodity (*imbal_mon);
652 balance_split = get_trading_split(trans, root, commodity);
666 val_imbalance = gnc_numeric_zero();
667 for (splits = trans->splits; splits; splits = splits->next)
669 Split *split = splits->data;
670 if (xaccTransStillHasSplit (trans, split) &&
681 new_amount =
gnc_numeric_sub (old_amount, gnc_monetary_value(*imbal_mon),
717 GList *splits_dup = g_list_copy(trans->splits);
718 for (splits = splits_dup; splits; splits = splits->next)
720 Split *split = splits->data;
721 if (! xaccTransStillHasSplit(trans, split))
continue;
731 PERR(
"Split has no commodity");
734 balance_split = get_trading_split(trans, root, commodity);
760 g_list_free(splits_dup);
763 PERR(
"Balancing currencies unbalanced value");
777 FindCommonExclSCurrency (
SplitList *splits,
783 if (!splits)
return NULL;
785 for (node = splits; node; node = node->next)
787 Split *s = node->data;
790 if (s == excl_split)
continue;
792 g_return_val_if_fail (s->acc, NULL);
804 if ( (!aa) && bb) rb = NULL;
805 else if ( (!ab) && ba) rb = NULL;
806 else if ( (!ba) && ab) ra = NULL;
807 else if ( (!bb) && aa) ra = NULL;
808 else if ( aa && bb && ab && ba )
824 if ( aa && ab ) ra = NULL;
830 ra = ( aa && ab ) ? NULL : rb;
833 if ((!ra) && (!rb))
return NULL;
846 return FindCommonExclSCurrency(splits, ra, rb, NULL);
855 if (!trans)
return NULL;
857 if (trans->splits == NULL)
return NULL;
859 g_return_val_if_fail (book, NULL);
861 split = trans->splits->data;
863 if (!split || NULL == split->acc)
return NULL;
868 retval = FindCommonCurrency (trans->splits, ra, rb);
887 commodity_equal (gconstpointer a, gconstpointer b)
891 if ( cc == NULL || cc->commodity == NULL ||
892 !GNC_IS_COMMODITY( cc->commodity ) )
return -1;
893 if ( com == NULL || !GNC_IS_COMMODITY( com ) )
return 1;
900 commodity_compare( gconstpointer a, gconstpointer b)
903 if (ca == NULL || ca->commodity == NULL ||
904 !GNC_IS_COMMODITY( ca->commodity ) )
906 if (cb == NULL || cb->commodity == NULL ||
907 !GNC_IS_COMMODITY( cb->commodity ) )
911 if (cb == NULL || cb->commodity == NULL ||
912 !GNC_IS_COMMODITY( cb->commodity ) )
914 if (ca->count == cb->count)
916 return ca->count > cb->count ? 1 : -1;
932 GSList *comlist = NULL, *found = NULL;
934 if (!trans)
return NULL;
936 if (trans->splits == NULL)
return NULL;
938 g_return_val_if_fail (book, NULL);
944 for (node = trans->splits; node; node = node->next)
946 Split *s = node->data;
947 unsigned int curr_weight;
949 if (s == NULL || s->acc == NULL)
continue;
959 if (com_scratch == NULL)
continue;
964 found = g_slist_find_custom(comlist, com_scratch, commodity_equal);
966 if (comlist == NULL || found == NULL)
969 count->commodity = com_scratch;
970 count->count = curr_weight;
971 comlist = g_slist_append(comlist, count);
976 count->count += curr_weight;
979 found = g_slist_sort( comlist, commodity_compare);
981 if ( found && found->data && (((
CommodityCount*)(found->data))->commodity != NULL))
987 return xaccTransFindOldCommonCurrency( trans, book );
1018 if (NULL == trans->splits)
1020 PWARN (
"Transaction \"%s\" has no splits in it!", trans->description);
1027 PWARN (
"no common transaction currency found for trans=\"%s\" (%s);",
1028 trans->description, guid_str);
1030 for (node = trans->splits; node; node = node->next)
1032 Split *split = node->data;
1033 if (NULL == split->acc)
1035 PWARN (
" split=\"%s\" is not in any account!", split->memo);
1040 PWARN (
"setting to split=\"%s\" account=\"%s\" commodity=\"%s\"",
1054 for (node = trans->splits; node; node = node->next)
1056 Split *sp = node->data;
1064 if (acc_currency == currency)
1083 PWARN (
"Adjusted split with mismatched values, desc=\"%s\" memo=\"%s\""
1084 " old amount %s %s, new amount %s",
1085 trans->description, sp->memo,
1114 if (!account)
return;
1118 if (commodity)
return;
1136 PERR (
"Account \"%s\" does not have a commodity!",
1143 extern void qof_instance_set_dirty (
QofInstance*);
1146 xaccAccountDeleteOldData (
Account *account)
1148 if (!account)
return;
1155 qof_instance_set_dirty (QOF_INSTANCE (account));
1160 scrub_trans_currency_helper (
Transaction *t, gpointer data)
1167 scrub_account_commodity_helper (
Account *account, gpointer data)
1170 xaccAccountDeleteOldData (account);
1180 scrub_account_commodity_helper (acc, NULL);
1189 gboolean *commodity_has_quote_src = (gboolean *)data;
1196 move_quote_source (
Account *account, gpointer data)
1200 gboolean new_style = GPOINTER_TO_INT(data);
1201 const char *source, *tz;
1210 if (!source || !*source)
1233 gboolean new_style = FALSE;
1236 if (!root || !table)
1244 move_quote_source(root, GINT_TO_POINTER(new_style));
1246 GINT_TO_POINTER(new_style));
1247 LEAVE(
"Migration done");
1253 xaccAccountScrubKvp (
Account *account)
1259 if (!account)
return;
1261 str = kvp_frame_get_string(account->inst.kvp_data,
"notes");
1264 str2 = g_strstrip(g_strdup(str));
1265 if (strlen(str2) == 0)
1270 str = kvp_frame_get_string(account->inst.kvp_data,
"placeholder");
1271 if (str && strcmp(str,
"false") == 0)
1277 kvp_frame_set_frame_nc(account->inst.kvp_data,
"hbci", NULL);
1286 gboolean placeholder)
1290 g_return_val_if_fail (root, NULL);
1295 PERR (
"No currency specified!");
void xaccAccountSetType(Account *acc, GNCAccountType tip)
void xaccSplitSetValue(Split *s, gnc_numeric amt)
int xaccAccountTreeForEachTransaction(Account *acc, TransactionCallback proc, void *data)
gboolean gnc_commodity_table_foreach_commodity(const gnc_commodity_table *table, gboolean(*f)(gnc_commodity *cm, gpointer user_data), gpointer user_data)
gboolean gnc_numeric_equal(gnc_numeric a, gnc_numeric b)
void xaccTransScrubCurrency(Transaction *trans)
gboolean gnc_commodity_is_currency(const gnc_commodity *cm)
gchar * gnc_num_dbg_to_string(gnc_numeric n)
int gnc_commodity_get_fraction(const gnc_commodity *cm)
void gnc_account_append_child(Account *new_parent, Account *child)
gboolean xaccTransUseTradingAccounts(const Transaction *trans)
SplitList * xaccAccountGetSplitList(const Account *acc)
const char * gnc_commodity_get_mnemonic(const gnc_commodity *cm)
void xaccAccountTreeScrubCommodities(Account *acc)
gnc_commodity * DxaccAccountGetCurrency(const Account *acc)
void gnc_account_foreach_descendant(const Account *acc, AccountCb thunk, gpointer user_data)
QofBook * qof_instance_get_book(gconstpointer)
gnc_quote_source * gnc_quote_source_add_new(const char *source_name, gboolean supported)
#define G_LOG_DOMAIN
Functions providing the SX List as a plugin page.
#define PINFO(format, args...)
GNCAccountType xaccAccountGetType(const Account *acc)
void xaccAccountScrubCommodity(Account *account)
gboolean gnc_commodity_get_quote_flag(const gnc_commodity *cm)
int xaccAccountGetCommoditySCU(const Account *acc)
gboolean kvp_frame_is_empty(const KvpFrame *frame)
void gnc_commodity_set_quote_tz(gnc_commodity *cm, const char *tz)
#define DEBUG(format, args...)
gboolean gnc_commodity_equal(const gnc_commodity *a, const gnc_commodity *b)
gnc_numeric gnc_numeric_add(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
gboolean gnc_numeric_zero_p(gnc_numeric a)
Transaction * xaccSplitGetParent(const Split *split)
const char * gnc_commodity_get_namespace(const gnc_commodity *cm)
gchar * guid_to_string_buff(const GncGUID *guid, gchar *buff)
void gnc_commodity_set_quote_flag(gnc_commodity *cm, const gboolean flag)
gboolean xaccTransIsBalanced(const Transaction *trans)
#define PERR(format, args...)
#define ENTER(format, args...)
void xaccTransSetCurrency(Transaction *trans, gnc_commodity *curr)
Account * gnc_account_lookup_by_name(const Account *parent, const char *name)
#define PWARN(format, args...)
convert single-entry accounts to clean double-entry
void gnc_commodity_set_quote_source(gnc_commodity *cm, gnc_quote_source *src)
void xaccSplitSetAmount(Split *s, gnc_numeric amt)
Account handling public routines.
void xaccAccountSetPlaceholder(Account *acc, gboolean val)
gnc_numeric xaccTransGetImbalanceValue(const Transaction *trans)
void dxaccAccountSetPriceSrc(Account *acc, const char *src)
#define GUID_ENCODING_LENGTH
void gnc_monetary_list_free(MonetaryList *list)
void xaccTransScrubImbalance(Transaction *trans, Account *root, Account *account)
const char * dxaccAccountGetQuoteTZ(const Account *acc)
void xaccSplitScrub(Split *split)
void xaccTransScrubSplits(Transaction *trans)
void kvp_frame_set_slot_nc(KvpFrame *frame, const gchar *key, KvpValue *value)
void xaccAccountScrubOrphans(Account *acc)
void xaccTransScrubOrphans(Transaction *trans)
#define xaccTransGetBook(X)
void xaccTransCommitEdit(Transaction *trans)
gnc_numeric gnc_numeric_div(gnc_numeric x, gnc_numeric y, gint64 denom, gint how)
void xaccTransBeginEdit(Transaction *trans)
void dxaccAccountSetQuoteTZ(Account *acc, const char *tz)
gnc_commodity * gnc_account_get_currency_or_parent(const Account *account)
Split * xaccMallocSplit(QofBook *book)
#define xaccTransGetGUID(X)
gnc_numeric gnc_numeric_sub(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
gnc_quote_source * gnc_quote_source_lookup_by_internal(const char *name)
const char * dxaccAccountGetPriceSrc(const Account *acc)
gnc_numeric xaccSplitGetValue(const Split *split)
void xaccAccountBeginEdit(Account *acc)
Account * xaccSplitGetAccount(const Split *s)
gnc_commodity * xaccAccountGetCommodity(const Account *acc)
gnc_commodity * xaccTransGetCurrency(const Transaction *trans)
MonetaryList * xaccTransGetImbalance(const Transaction *trans)
struct KvpFrameImpl KvpFrame
#define LEAVE(format, args...)
Account * xaccMallocAccount(QofBook *book)
GNCNumericErrorCode gnc_numeric_check(gnc_numeric a)
void xaccAccountTreeScrubOrphans(Account *acc)
KvpFrame * kvp_frame_get_frame(const KvpFrame *frame, const gchar *path)
Account * gnc_account_get_root(Account *acc)
const char * xaccAccountGetName(const Account *acc)
void xaccAccountTreeScrubQuoteSources(Account *root, gnc_commodity_table *table)
gint gnc_numeric_same(gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
API for Transactions and Splits (journal entries)
void xaccAccountCommitEdit(Account *acc)
void xaccAccountSetName(Account *acc, const char *str)
Commodity handling public routines.
gboolean gnc_commodity_equiv(const gnc_commodity *a, const gnc_commodity *b)
gboolean gnc_commodity_is_iso(const gnc_commodity *cm)
const gchar * QofLogModule
void xaccAccountSetCommodity(Account *acc, gnc_commodity *com)
gnc_numeric xaccSplitGetAmount(const Split *split)