Reduce GncImportMatchMap to just the account

There is no added value in storing the book and account together
The book is easily retrieved from the account (as was
illustrated in the gnc_account_imap_new function).

I looked through the commit history to understand why this struct
was originally created and a long time ago it also had
a reference to a kvp frame.
This commit is contained in:
Geert Janssens 2023-02-03 00:56:49 +01:00
parent 376f0bfae9
commit 99506d331a
9 changed files with 170 additions and 271 deletions

View File

@ -44,20 +44,6 @@
/* This static indicates the debugging module that this .o belongs to. */
static QofLogModule UNUSED_VAR log_module = G_LOG_DOMAIN;
/**************************************************
* account_imap_destroy
*
* Destroy an import map. But all stored entries will
* still continue to exist in the underlying kvp frame
* of the account.
**************************************************/
static void
account_imap_destroy (GncImportMatchMap *imap)
{
if (!imap) return;
g_free (imap);
}
/**************************************************
* gnc_csv_account_map_search
*
@ -76,17 +62,13 @@ Account * gnc_csv_account_map_search (const gchar *map_string)
/* Go through list of accounts */
for (ptr = accts; ptr; ptr = g_list_next (ptr))
{
GncImportMatchMap *tmp_imap;
Account *tmp_acc = ptr->data;
tmp_imap = gnc_account_imap_create_imap (ptr->data);
if (gnc_account_imap_find_account (tmp_imap, CSV_CATEGORY, map_string) != NULL)
if (gnc_account_imap_find_account (tmp_acc, CSV_CATEGORY, map_string))
{
account = ptr->data;
account_imap_destroy (tmp_imap);
account = tmp_acc;
break;
}
account_imap_destroy (tmp_imap);
}
g_list_free (accts);
@ -146,22 +128,12 @@ gnc_csv_account_map_load_mappings (GtkTreeModel *mappings_store)
void
gnc_csv_account_map_change_mappings (Account *old_account, Account *new_account, const gchar *map_string)
{
GncImportMatchMap *tmp_imap;
if (strlen (map_string) == 0)
return;
if (old_account != NULL)
{
tmp_imap = gnc_account_imap_create_imap (old_account);
gnc_account_imap_delete_account (tmp_imap, CSV_CATEGORY, map_string);
account_imap_destroy (tmp_imap);
}
if (old_account)
gnc_account_imap_delete_account (old_account, CSV_CATEGORY, map_string);
if (new_account != NULL)
{
tmp_imap = gnc_account_imap_create_imap (new_account);
gnc_account_imap_add_account (tmp_imap, CSV_CATEGORY, map_string, new_account);
account_imap_destroy (tmp_imap);
}
if (new_account)
gnc_account_imap_add_account (new_account, CSV_CATEGORY, map_string, new_account);
}

View File

@ -62,10 +62,9 @@ static QofLogModule log_module = GNC_MOD_IMPORT;
* Forward declared prototypes *
\********************************************************************/
static void
matchmap_store_destination (GncImportMatchMap *matchmap,
GNCImportTransInfo *trans_info,
gboolean use_match);
static void matchmap_store_destination(Account* base_acc,
GNCImportTransInfo* trans_info,
gboolean use_match);
/********************************************************************\
@ -331,8 +330,8 @@ GdkPixbuf* gen_probability_pixbuf(gint score_original, GNCImportSettings *settin
* MatchMap related functions (storing and retrieving)
*/
/* Tokenize a string and append to an existing GList(or an empty GList)
* the tokens
/* Tokenize a string and append the tokens to an existing GList
* (or an empty GList)
*/
static GList*
tokenize_string(GList* existing_tokens, const char *string)
@ -394,10 +393,7 @@ TransactionGetTokens(GNCImportTransInfo *info)
tokens = tokenize_string(tokens, text);
}
/* remember the list of tokens for later.. */
info->match_tokens = tokens;
/* return the pointer to the GList */
return tokens;
}
@ -405,12 +401,11 @@ TransactionGetTokens(GNCImportTransInfo *info)
* if there is an exact match of the description and memo
*/
static Account *
matchmap_find_destination (GncImportMatchMap *matchmap, GNCImportTransInfo *info)
matchmap_find_destination (Account *base_acc, GNCImportTransInfo *info)
{
g_assert (info);
auto tmp_map = (matchmap ? matchmap : gnc_account_imap_create_imap
(xaccSplitGetAccount
(gnc_import_TransInfo_get_fsplit (info))));
auto orig_acc = (base_acc ? base_acc : xaccSplitGetAccount
(gnc_import_TransInfo_get_fsplit (info)));
Account *result = nullptr;
if (gnc_prefs_get_bool (GNC_PREFS_GROUP_IMPORT, GNC_PREF_USE_BAYES))
@ -419,17 +414,14 @@ matchmap_find_destination (GncImportMatchMap *matchmap, GNCImportTransInfo *info
GList* tokens = TransactionGetTokens(info);
/* try to find the destination account for this transaction from its tokens */
result = gnc_account_imap_find_account_bayes(tmp_map, tokens);
result = gnc_account_imap_find_account_bayes(orig_acc, tokens);
}
else
result = gnc_account_imap_find_account
(tmp_map, GNCIMPORT_DESC,
(orig_acc, GNCIMPORT_DESC,
xaccTransGetDescription (gnc_import_TransInfo_get_trans (info)));
if (!matchmap)
g_free (tmp_map);
return result;
}
@ -438,7 +430,7 @@ matchmap_find_destination (GncImportMatchMap *matchmap, GNCImportTransInfo *info
matching/duplicate transaction is used; otherwise, the stored
destination_acc pointer is used. */
static void
matchmap_store_destination (GncImportMatchMap *matchmap,
matchmap_store_destination (Account *base_acc,
GNCImportTransInfo *trans_info,
gboolean use_match)
{
@ -457,10 +449,8 @@ matchmap_store_destination (GncImportMatchMap *matchmap,
if (!dest)
return;
auto tmp_matchmap = ((matchmap) ? matchmap :
gnc_account_imap_create_imap
(xaccSplitGetAccount
(gnc_import_TransInfo_get_fsplit (trans_info))));
auto orig_acc = (base_acc ? base_acc : xaccSplitGetAccount
(gnc_import_TransInfo_get_fsplit (trans_info)));
if (gnc_prefs_get_bool (GNC_PREFS_GROUP_IMPORT, GNC_PREF_USE_BAYES))
{
@ -468,7 +458,7 @@ matchmap_store_destination (GncImportMatchMap *matchmap,
auto tokens = TransactionGetTokens(trans_info);
/* add the tokens to the imap with the given destination account */
gnc_account_imap_add_account_bayes(tmp_matchmap, tokens, dest);
gnc_account_imap_add_account_bayes(orig_acc, tokens, dest);
}
else
{
@ -478,13 +468,10 @@ matchmap_store_destination (GncImportMatchMap *matchmap,
(gnc_import_TransInfo_get_fsplit (trans_info));
if (desc && *desc)
gnc_account_imap_add_account (tmp_matchmap, GNCIMPORT_DESC, desc, dest);
gnc_account_imap_add_account (orig_acc, GNCIMPORT_DESC, desc, dest);
if (memo && *memo)
gnc_account_imap_add_account (tmp_matchmap, GNCIMPORT_MEMO, memo, dest);
gnc_account_imap_add_account (orig_acc, GNCIMPORT_MEMO, memo, dest);
}
if (!matchmap)
g_free (tmp_matchmap);
}
@ -492,11 +479,11 @@ matchmap_store_destination (GncImportMatchMap *matchmap,
/** @brief The transaction matching heuristics are here.
*/
void split_find_match (GNCImportTransInfo * trans_info,
Split * split,
gint display_threshold,
gint date_threshold,
gint date_not_threshold,
double fuzzy_amount_difference)
Split * split,
gint display_threshold,
gint date_threshold,
gint date_not_threshold,
double fuzzy_amount_difference)
{
gint prob = 0;
@ -757,7 +744,7 @@ update_desc_and_notes (const GNCImportTransInfo* trans_info)
}
static void
process_reconcile(GncImportMatchMap *matchmap,
process_reconcile(Account *base_acc,
GNCImportTransInfo *trans_info,
GNCImportMatchInfo *selected_match)
{
@ -784,7 +771,7 @@ process_reconcile(GncImportMatchMap *matchmap,
xaccTransCommitEdit(selected_match->trans);
/* Store the mapping to the other account in the MatchMap. */
matchmap_store_destination(matchmap, trans_info, true);
matchmap_store_destination(base_acc, trans_info, true);
/* Erase the downloaded transaction */
xaccTransDestroy(trans_info->trans);
@ -797,7 +784,7 @@ process_reconcile(GncImportMatchMap *matchmap,
/** /brief -- Processes one match
according to its selected action. */
gboolean
gnc_import_process_trans_item (GncImportMatchMap *matchmap,
gnc_import_process_trans_item (Account *base_acc,
GNCImportTransInfo *trans_info)
{
g_assert (trans_info);
@ -885,7 +872,7 @@ gnc_import_process_trans_item (GncImportMatchMap *matchmap,
/*DEBUG("CommitEdit selected_match")*/
xaccTransCommitEdit(selected_match->trans);
process_reconcile (matchmap, trans_info, selected_match);
process_reconcile (base_acc, trans_info, selected_match);
}
}
return true;
@ -907,7 +894,7 @@ gnc_import_process_trans_item (GncImportMatchMap *matchmap,
else
{
/* Reconcile the matching transaction */
process_reconcile(matchmap, trans_info, selected_match);
process_reconcile(base_acc, trans_info, selected_match);
}
}
return true;
@ -1014,7 +1001,7 @@ gboolean gnc_import_exists_online_id (Transaction *trans, GHashTable* acct_id_ha
/** Create a new object of GNCImportTransInfo here. */
GNCImportTransInfo *
gnc_import_TransInfo_new (Transaction *trans, GncImportMatchMap *matchmap)
gnc_import_TransInfo_new (Transaction *trans, Account *base_acc)
{
g_assert (trans);
@ -1029,7 +1016,7 @@ gnc_import_TransInfo_new (Transaction *trans, GncImportMatchMap *matchmap)
/* Try to find a previously selected destination account
string match for the ADD action */
gnc_import_TransInfo_set_destacc (transaction_info,
matchmap_find_destination (matchmap, transaction_info),
matchmap_find_destination (base_acc, transaction_info),
false);
return transaction_info;
}
@ -1091,17 +1078,17 @@ gnc_import_TransInfo_init_matches (GNCImportTransInfo *trans_info,
* Return whether a new destination account was effectively set */
gboolean
gnc_import_TransInfo_refresh_destacc (GNCImportTransInfo *transaction_info,
GncImportMatchMap *matchmap)
Account *base_acc)
{
g_assert(transaction_info);
auto orig_destacc = gnc_import_TransInfo_get_destacc(transaction_info);
/* if we haven't manually selected a destination account for this transaction */
if (!gnc_import_TransInfo_get_destacc_selected_manually(transaction_info))
{
/* Try to find the destination account for this transaction based on prior ones */
auto new_destacc = matchmap_find_destination(matchmap, transaction_info);
auto orig_destacc = gnc_import_TransInfo_get_destacc(transaction_info);
auto new_destacc = matchmap_find_destination(base_acc, transaction_info);
gnc_import_TransInfo_set_destacc(transaction_info, new_destacc, false);
return (new_destacc != orig_destacc);
}

View File

@ -109,20 +109,20 @@ gnc_import_TransInfo_init_matches (GNCImportTransInfo *trans_info,
* and processes each ImportTransInfo according to its selected action:
* For GNCImport_ADD, the transaction is added etc. etc.
*
* Each successful match is also stored in the given ImportMatchMap,
* or, if that argument is NULL, in the ImportMatchMap of each
* Each successful match is also stored in the match map of the given
* account, or if that argument is NULL, in the match map of each
* originating account.
*
* @param matchmap The ImportMatchMap where each match should be
* stored. May be NULL, in which case the ImportMatchMap of each
* account will be used.
* @param base_acc The account where each match should be
* stored. May be NULL, in which case each originating account
* will be used.
*
* @param trans_info The ImportTransInfo item to process.
*
* @return TRUE if the item has been processed.
*/
gboolean
gnc_import_process_trans_item (GncImportMatchMap *matchmap,
gnc_import_process_trans_item (Account *base_acc,
GNCImportTransInfo *trans_info);
/** This function generates a new pixmap representing a match score.
@ -154,17 +154,16 @@ GdkPixbuf* gen_probability_pixbuf (gint score,
/** Allocates a new TransInfo object, with the Transaction 'trans'
* already stored in there. Also, this already checks the
* ImportMatchMap for automated destination account matching. The
* given MatchMap may be NULL, in which case the ImportMatchMap of the
* account's match map for automated destination account matching. The
* given account may be NULL, in which case the match map of the
* originating account will be used.
*
* @param trans The transaction that this TransInfo should work with.
*
* @param matchmap MatchMap used for automated destination account
* choosing. This may be NULL, in which case the MatchMap of the
* @param base_acc Account that will provide the match map to lookup a destination
* account. This may be NULL, in which case the match map of the
* originating account will be used. */
GNCImportTransInfo *
gnc_import_TransInfo_new (Transaction *trans, GncImportMatchMap *matchmap);
GNCImportTransInfo* gnc_import_TransInfo_new(Transaction* trans, Account* base_acc);
/** Destructor */
void gnc_import_TransInfo_delete (GNCImportTransInfo *info);
@ -226,7 +225,7 @@ gnc_import_TransInfo_set_destacc (GNCImportTransInfo *info,
/** Try to automatch a given transaction to a destination account */
gboolean
gnc_import_TransInfo_refresh_destacc (GNCImportTransInfo *transaction_info,
GncImportMatchMap *matchmap);
Account *base_acc);
/** Returns if the currently selected destination account for auto-matching was selected by the user. */
gboolean

View File

@ -163,7 +163,6 @@ protected:
//! Test for function gnc_import_TransInfo_new()
TEST_F(ImportBackendTest, CreateTransInfo)
{
GncMockImportMatchMap imap(m_import_acc);
gchar* online_id;
using namespace testing;
@ -180,11 +179,11 @@ TEST_F(ImportBackendTest, CreateTransInfo)
.WillByDefault(Return("This is the description"));
// function gnc_import_TransInfo_new() should try to find account using the description from the transaction
EXPECT_CALL(imap, find_account(_, StrEq("This is the description")))
EXPECT_CALL(*m_import_acc, find_account(_, StrEq("This is the description")))
.WillOnce(Return(m_dest_acc));
// call function to be tested
GNCImportTransInfo *trans_info = gnc_import_TransInfo_new(m_trans, &imap);
GNCImportTransInfo *trans_info = gnc_import_TransInfo_new(m_trans, m_import_acc);
// check 'trans_info'
EXPECT_EQ(gnc_import_TransInfo_get_fsplit(trans_info), m_split);
@ -230,7 +229,6 @@ TEST_F(ImportBackendBayesTest, CreateTransInfo)
{
using namespace testing;
GncMockImportMatchMap imap(m_import_acc);
time64 date(GncDateTime(GncDate(2020, 3, 18)));
struct tm *tm_struct;
char local_day_of_week[16];
@ -264,7 +262,7 @@ TEST_F(ImportBackendBayesTest, CreateTransInfo)
.WillByDefault(Return(date));
// check tokens created from transaction
EXPECT_CALL(imap, find_account_bayes(AllOf(
EXPECT_CALL(*m_import_acc, find_account_bayes(AllOf(
Each(Not(StrEq(""))), // tokens must not be empty strings
Each(Not(HasSubstr(" "))), // tokens must not contain separator
Not(HasDuplicates()), // tokens must be unique
@ -275,7 +273,7 @@ TEST_F(ImportBackendBayesTest, CreateTransInfo)
.WillOnce(Return(m_dest_acc));
// call function to be tested
GNCImportTransInfo *trans_info = gnc_import_TransInfo_new(m_trans, &imap);
GNCImportTransInfo *trans_info = gnc_import_TransInfo_new(m_trans, m_import_acc);
// check 'trans_info'
EXPECT_EQ(gnc_import_TransInfo_get_fsplit(trans_info), m_split);

View File

@ -5706,90 +5706,71 @@ xaccAccountForEachTransaction(const Account *acc, TransactionCallback proc,
#define IMAP_FRAME "import-map"
#define IMAP_FRAME_BAYES "import-map-bayes"
/* Obtain an ImportMatchMap object from an Account or a Book */
GncImportMatchMap *
gnc_account_imap_create_imap (Account *acc)
{
GncImportMatchMap *imap;
if (!acc) return NULL;
imap = g_new0(GncImportMatchMap, 1);
/* Cache the book for easy lookups; store the account/book for
* marking dirtiness
*/
imap->acc = acc;
imap->book = gnc_account_get_book (acc);
return imap;
}
/* Look up an Account in the map */
Account*
gnc_account_imap_find_account (GncImportMatchMap *imap,
gnc_account_imap_find_account (Account *acc,
const char *category,
const char *key)
{
GValue v = G_VALUE_INIT;
GncGUID * guid = NULL;
Account *retval;
if (!imap || !key) return NULL;
if (!acc || !key) return NULL;
std::vector<std::string> path {IMAP_FRAME};
if (category)
path.push_back (category);
path.push_back (key);
qof_instance_get_path_kvp (QOF_INSTANCE (imap->acc), &v, path);
qof_instance_get_path_kvp (QOF_INSTANCE (acc), &v, path);
if (G_VALUE_HOLDS_BOXED (&v))
guid = (GncGUID*)g_value_get_boxed (&v);
retval = xaccAccountLookup (guid, imap->book);
retval = xaccAccountLookup (guid, gnc_account_get_book(acc));
g_value_unset (&v);
return retval;
}
/* Store an Account in the map */
void
gnc_account_imap_add_account (GncImportMatchMap *imap,
gnc_account_imap_add_account (Account *acc,
const char *category,
const char *key,
Account *acc)
Account *added_acc)
{
GValue v = G_VALUE_INIT;
if (!imap || !key || !acc || (strlen (key) == 0)) return;
if (!acc || !key || !added_acc || (strlen (key) == 0)) return;
std::vector<std::string> path {IMAP_FRAME};
if (category)
path.emplace_back (category);
path.emplace_back (key);
g_value_init (&v, GNC_TYPE_GUID);
g_value_set_boxed (&v, xaccAccountGetGUID (acc));
xaccAccountBeginEdit (imap->acc);
qof_instance_set_path_kvp (QOF_INSTANCE (imap->acc), &v, path);
qof_instance_set_dirty (QOF_INSTANCE (imap->acc));
xaccAccountCommitEdit (imap->acc);
g_value_set_boxed (&v, xaccAccountGetGUID (added_acc));
xaccAccountBeginEdit (acc);
qof_instance_set_path_kvp (QOF_INSTANCE (acc), &v, path);
qof_instance_set_dirty (QOF_INSTANCE (acc));
xaccAccountCommitEdit (acc);
g_value_unset (&v);
}
/* Remove a reference to an Account in the map */
void
gnc_account_imap_delete_account (GncImportMatchMap *imap,
gnc_account_imap_delete_account (Account *acc,
const char *category,
const char *key)
{
if (!imap || !key) return;
if (!acc || !key) return;
std::vector<std::string> path {IMAP_FRAME};
if (category)
path.emplace_back (category);
path.emplace_back (key);
xaccAccountBeginEdit (imap->acc);
if (qof_instance_has_path_slot (QOF_INSTANCE (imap->acc), path))
xaccAccountBeginEdit (acc);
if (qof_instance_has_path_slot (QOF_INSTANCE (acc), path))
{
qof_instance_slot_path_delete (QOF_INSTANCE (imap->acc), path);
qof_instance_slot_path_delete (QOF_INSTANCE (acc), path);
if (category)
qof_instance_slot_path_delete_if_empty (QOF_INSTANCE (imap->acc), {IMAP_FRAME, category});
qof_instance_slot_path_delete_if_empty (QOF_INSTANCE (imap->acc), {IMAP_FRAME});
qof_instance_slot_path_delete_if_empty (QOF_INSTANCE (acc), {IMAP_FRAME, category});
qof_instance_slot_path_delete_if_empty (QOF_INSTANCE (acc), {IMAP_FRAME});
}
qof_instance_set_dirty (QOF_INSTANCE (imap->acc));
xaccAccountCommitEdit (imap->acc);
qof_instance_set_dirty (QOF_INSTANCE (acc));
xaccAccountCommitEdit (acc);
}
/*--------------------------------------------------------------------------
@ -5876,7 +5857,7 @@ highest_probability(FinalProbabilityVec const & probabilities)
}
static ProbabilityVec
get_first_pass_probabilities(GncImportMatchMap * imap, GList * tokens)
get_first_pass_probabilities(Account* acc, GList * tokens)
{
ProbabilityVec ret;
/* find the probability for each account that contains any of the tokens
@ -5885,7 +5866,7 @@ get_first_pass_probabilities(GncImportMatchMap * imap, GList * tokens)
{
TokenAccountsInfo tokenInfo{};
auto path = std::string{IMAP_FRAME_BAYES "/"} + static_cast <char const *> (current_token->data) + "/";
qof_instance_foreach_slot_prefix (QOF_INSTANCE (imap->acc), path, &build_token_info, tokenInfo);
qof_instance_foreach_slot_prefix (QOF_INSTANCE (acc), path, &build_token_info, tokenInfo);
for (auto const & current_account_token : tokenInfo.accounts)
{
auto item = std::find_if(ret.begin(), ret.end(), [&current_account_token]
@ -6078,12 +6059,13 @@ static constexpr double threshold = .90 * probability_factor; /* 90% */
/** Look up an Account in the map */
Account*
gnc_account_imap_find_account_bayes (GncImportMatchMap *imap, GList *tokens)
gnc_account_imap_find_account_bayes (Account *acc, GList *tokens)
{
if (!imap)
if (!acc)
return nullptr;
check_import_map_data (imap->book);
auto first_pass = get_first_pass_probabilities(imap, tokens);
auto book = gnc_account_get_book(acc);
check_import_map_data (book);
auto first_pass = get_first_pass_probabilities(acc, tokens);
if (!first_pass.size())
return nullptr;
auto final_probabilities = build_probabilities(first_pass);
@ -6100,25 +6082,25 @@ gnc_account_imap_find_account_bayes (GncImportMatchMap *imap, GList *tokens)
} catch (gnc::guid_syntax_exception&) {
return nullptr;
}
auto account = xaccAccountLookup (reinterpret_cast<GncGUID*>(&guid), imap->book);
auto account = xaccAccountLookup (reinterpret_cast<GncGUID*>(&guid), book);
return account;
}
static void
change_imap_entry (GncImportMatchMap *imap, std::string const & path, int64_t token_count)
change_imap_entry (Account *acc, std::string const & path, int64_t token_count)
{
GValue value = G_VALUE_INIT;
PINFO("Source Account is '%s', Count is '%" G_GINT64_FORMAT "'",
xaccAccountGetName (imap->acc), token_count);
xaccAccountGetName (acc), token_count);
// check for existing guid entry
if (qof_instance_has_slot (QOF_INSTANCE(imap->acc), path.c_str ()))
if (qof_instance_has_slot (QOF_INSTANCE(acc), path.c_str ()))
{
int64_t existing_token_count = 0;
// get the existing_token_count value
qof_instance_get_path_kvp (QOF_INSTANCE (imap->acc), &value, {path});
qof_instance_get_path_kvp (QOF_INSTANCE (acc), &value, {path});
if (G_VALUE_HOLDS_INT64 (&value))
existing_token_count = g_value_get_int64 (&value);
@ -6134,16 +6116,16 @@ change_imap_entry (GncImportMatchMap *imap, std::string const & path, int64_t to
g_value_set_int64 (&value, token_count);
// Add or Update the entry based on guid
qof_instance_set_path_kvp (QOF_INSTANCE (imap->acc), &value, {path});
gnc_features_set_used (imap->book, GNC_FEATURE_GUID_FLAT_BAYESIAN);
qof_instance_set_path_kvp (QOF_INSTANCE (acc), &value, {path});
gnc_features_set_used (gnc_account_get_book(acc), GNC_FEATURE_GUID_FLAT_BAYESIAN);
g_value_unset (&value);
}
/** Updates the imap for a given account using a list of tokens */
void
gnc_account_imap_add_account_bayes (GncImportMatchMap *imap,
gnc_account_imap_add_account_bayes (Account *acc,
GList *tokens,
Account *acc)
Account *added_acc)
{
GList *current_token;
gint64 token_count;
@ -6151,20 +6133,20 @@ gnc_account_imap_add_account_bayes (GncImportMatchMap *imap,
char *guid_string;
ENTER(" ");
if (!imap)
if (!acc)
{
LEAVE(" ");
return;
}
check_import_map_data (imap->book);
check_import_map_data (gnc_account_get_book(acc));
g_return_if_fail (acc != NULL);
account_fullname = gnc_account_get_full_name(acc);
xaccAccountBeginEdit (imap->acc);
g_return_if_fail (added_acc != NULL);
account_fullname = gnc_account_get_full_name(added_acc);
xaccAccountBeginEdit (acc);
PINFO("account name: '%s'", account_fullname);
guid_string = guid_to_string (xaccAccountGetGUID (acc));
guid_string = guid_to_string (xaccAccountGetGUID (added_acc));
/* process each token in the list */
for (current_token = g_list_first(tokens); current_token;
@ -6181,11 +6163,11 @@ gnc_account_imap_add_account_bayes (GncImportMatchMap *imap,
PINFO("adding token '%s'", (char*)current_token->data);
auto path = std::string {IMAP_FRAME_BAYES} + '/' + static_cast<char*>(current_token->data) + '/' + guid_string;
/* change the imap entry for the account */
change_imap_entry (imap, path, token_count);
change_imap_entry (acc, path, token_count);
}
/* free up the account fullname and guid string */
qof_instance_set_dirty (QOF_INSTANCE (imap->acc));
xaccAccountCommitEdit (imap->acc);
qof_instance_set_dirty (QOF_INSTANCE (acc));
xaccAccountCommitEdit (acc);
g_free (account_fullname);
g_free (guid_string);
LEAVE(" ");

View File

@ -68,12 +68,6 @@ typedef struct
QofInstanceClass parent_class;
} AccountClass;
typedef struct
{
Account *acc;
QofBook *book;
} GncImportMatchMap;
/* --- type macros --- */
#define GNC_TYPE_ACCOUNT (gnc_account_get_type ())
#define GNC_ACCOUNT(o) \
@ -1576,33 +1570,28 @@ typedef enum
int xaccAccountTreeForEachTransaction(Account *acc,
TransactionCallback proc, void *data);
/** Obtain an ImportMatchMap object from an Account or a Book
*/
GncImportMatchMap *gnc_account_imap_create_imap (Account *acc);
/* Look up an Account in the map non-Baysian
*/
Account* gnc_account_imap_find_account (GncImportMatchMap *imap, const char* category,
Account* gnc_account_imap_find_account (Account* acc, const char* category,
const char *key);
/* Store an Account in the map non Baysian
*/
void gnc_account_imap_add_account (GncImportMatchMap *imap, const char *category,
const char *key, Account *acc);
void gnc_account_imap_add_account (Account* acc, const char *category,
const char *key, Account *added_acc);
/* Remove a reference to an Account in the map non Baysian
*/
void gnc_account_imap_delete_account (GncImportMatchMap *imap, const char *category,
const char *key);
void gnc_account_imap_delete_account(Account* acc, const char* category, const char* key);
/** Look up an Account in the map using Baysian
*/
Account* gnc_account_imap_find_account_bayes (GncImportMatchMap *imap, GList* tokens);
Account* gnc_account_imap_find_account_bayes (Account* acc, GList* tokens);
/** Updates the imap for a given account using a list of tokens
*/
void gnc_account_imap_add_account_bayes (GncImportMatchMap *imap, GList* tokens,
Account *acc);
void gnc_account_imap_add_account_bayes (Account* acc, GList* tokens,
Account *added_acc);
typedef struct imap_info
{

View File

@ -69,36 +69,30 @@ xaccAccountGetSplitList (const Account *account)
}
GncImportMatchMap *
gnc_account_imap_create_imap (Account *acc)
{
SCOPED_TRACE("");
auto mockaccount = gnc_mockaccount(acc);
return mockaccount ? mockaccount->create_imap() : nullptr;
}
Account*
gnc_account_imap_find_account (
GncImportMatchMap *imap,
Account *acc,
const char* category,
const char *key)
{
return ((GncMockImportMatchMap*)imap)->find_account(category, key);
auto mockaccount = gnc_mockaccount(acc);
return mockaccount->find_account(category, key);
}
void
gnc_account_imap_add_account (
GncImportMatchMap *imap,
Account *acc,
const char *category,
const char *key,
Account *acc)
Account *dest_acc)
{
((GncMockImportMatchMap*)imap)->add_account(category, key, acc);
auto mockaccount = gnc_mockaccount(acc);
mockaccount->add_account(category, key, dest_acc);
}
Account*
gnc_account_imap_find_account_bayes (
GncImportMatchMap *imap,
Account *acc,
GList *tokens)
{
std::vector<const char*> tokenVec;
@ -108,14 +102,15 @@ gnc_account_imap_find_account_bayes (
tokenVec.push_back(static_cast <char const *> (token->data));
}
return ((GncMockImportMatchMap*)imap)->find_account_bayes(tokenVec);
auto mockaccount = gnc_mockaccount(acc);
return mockaccount->find_account_bayes(tokenVec);
}
void
gnc_account_imap_add_account_bayes (
GncImportMatchMap *imap,
Account *acc,
GList *tokens,
Account *acc)
Account *added_acc)
{
std::vector<const char*> tokenVec;
@ -124,6 +119,7 @@ gnc_account_imap_add_account_bayes (
tokenVec.push_back(static_cast <char const *> (token->data));
}
((GncMockImportMatchMap*)imap)->add_account_bayes(tokenVec, acc);
auto mockaccount = gnc_mockaccount(acc);
mockaccount->add_account_bayes(tokenVec, added_acc);
}

View File

@ -44,7 +44,10 @@ public:
MOCK_CONST_METHOD0(get_book, QofBook*());
MOCK_CONST_METHOD2(for_each_transaction, gint(TransactionCallback, void*));
MOCK_CONST_METHOD0(xaccAccountGetSplitList, SplitList*());
MOCK_METHOD0(create_imap, GncImportMatchMap*());
MOCK_METHOD2(find_account, Account *(const char*, const char*));
MOCK_METHOD3(add_account, void(const char*, const char*, Account*));
MOCK_METHOD1(find_account_bayes, Account *(std::vector<const char*>&));
MOCK_METHOD2(add_account_bayes, void(std::vector<const char*>&, Account*));
protected:
/* Protect destructor to avoid MockAccount objects to be created on stack. MockAccount
@ -53,23 +56,6 @@ protected:
};
// mock up for GncImportMatchMap
class GncMockImportMatchMap : public GncImportMatchMap
{
public:
GncMockImportMatchMap(MockAccount* account)
{
acc = account;
book = account->get_book();
};
MOCK_METHOD2(find_account, Account *(const char*, const char*));
MOCK_METHOD3(add_account, void(const char*, const char*, Account*));
MOCK_METHOD1(find_account_bayes, Account *(std::vector<const char*>&));
MOCK_METHOD2(add_account_bayes, void(std::vector<const char*>&, Account*));
};
// type conversion functions
static inline MockAccount*
gnc_mockaccount (Account *account)

View File

@ -81,15 +81,6 @@ protected:
Account *t_expense_account {};
};
TEST_F(ImapTest, CreateImap) {
GncImportMatchMap *imap = gnc_account_imap_create_imap (t_bank_account);
EXPECT_NE(nullptr, imap);
EXPECT_EQ(t_bank_account, imap->acc);
EXPECT_EQ(gnc_account_get_book(t_bank_account), imap->book);
g_free(imap);
}
static const char* IMAP_FRAME = "import-map";
static const char* IMAP_FRAME_BAYES = "import-map-bayes";
@ -98,15 +89,14 @@ class ImapPlainTest : public ImapTest
protected:
void SetUp() {
ImapTest::SetUp();
t_imap = gnc_account_imap_create_imap (t_bank_account);
t_acc = t_bank_account;
}
void TearDown() {
g_free(t_imap);
ImapTest::TearDown();
}
GncImportMatchMap *t_imap {};
Account *t_acc {};
};
TEST_F(ImapPlainTest, FindAccount)
@ -119,11 +109,11 @@ TEST_F(ImapPlainTest, FindAccount)
root->set_path({IMAP_FRAME, "pepper"}, new KvpValue{*acc1_val});
root->set_path({IMAP_FRAME, "salt"}, new KvpValue{*acc2_val});
EXPECT_EQ(t_expense_account1, gnc_account_imap_find_account(t_imap, "foo", "bar"));
EXPECT_EQ(t_expense_account2, gnc_account_imap_find_account(t_imap, "baz", "waldo"));
EXPECT_EQ(t_expense_account1, gnc_account_imap_find_account(t_imap, NULL, "pepper"));
EXPECT_EQ(t_expense_account2, gnc_account_imap_find_account(t_imap, NULL, "salt"));
EXPECT_EQ(nullptr, gnc_account_imap_find_account(t_imap, "salt", NULL));
EXPECT_EQ(t_expense_account1, gnc_account_imap_find_account(t_acc, "foo", "bar"));
EXPECT_EQ(t_expense_account2, gnc_account_imap_find_account(t_acc, "baz", "waldo"));
EXPECT_EQ(t_expense_account1, gnc_account_imap_find_account(t_acc, NULL, "pepper"));
EXPECT_EQ(t_expense_account2, gnc_account_imap_find_account(t_acc, NULL, "salt"));
EXPECT_EQ(nullptr, gnc_account_imap_find_account(t_acc, "salt", NULL));
}
TEST_F(ImapPlainTest, AddAccount)
@ -131,23 +121,23 @@ TEST_F(ImapPlainTest, AddAccount)
// prevent the embedded beginedit/committedit from doing anything
qof_instance_increase_editlevel(QOF_INSTANCE(t_bank_account));
qof_instance_mark_clean(QOF_INSTANCE(t_bank_account));
gnc_account_imap_add_account(t_imap, "foo", "bar", t_expense_account1);
gnc_account_imap_add_account(t_imap, "baz", "waldo", t_expense_account2);
gnc_account_imap_add_account(t_imap, NULL, "pepper", t_expense_account1);
gnc_account_imap_add_account(t_imap, NULL, "salt", t_expense_account2);
gnc_account_imap_add_account(t_acc, "foo", "bar", t_expense_account1);
gnc_account_imap_add_account(t_acc, "baz", "waldo", t_expense_account2);
gnc_account_imap_add_account(t_acc, NULL, "pepper", t_expense_account1);
gnc_account_imap_add_account(t_acc, NULL, "salt", t_expense_account2);
EXPECT_EQ(1, qof_instance_get_editlevel(QOF_INSTANCE(t_bank_account)));
EXPECT_TRUE(qof_instance_get_dirty_flag(QOF_INSTANCE(t_bank_account)));
qof_instance_mark_clean(QOF_INSTANCE(t_bank_account));
gnc_account_imap_add_account(t_imap, NULL, NULL, t_expense_account2);
gnc_account_imap_add_account(t_acc, NULL, NULL, t_expense_account2);
EXPECT_FALSE(qof_instance_get_dirty_flag(QOF_INSTANCE(t_bank_account)));
gnc_account_imap_add_account(t_imap, "pork", "sausage", NULL);
gnc_account_imap_add_account(t_acc, "pork", "sausage", NULL);
EXPECT_FALSE(qof_instance_get_dirty_flag(QOF_INSTANCE(t_bank_account)));
qof_instance_reset_editlevel(QOF_INSTANCE(t_bank_account));
auto root = qof_instance_get_slots(QOF_INSTANCE(t_bank_account));
auto value = root->get_slot({IMAP_FRAME, "foo", "bar"});
auto check_account = [this](KvpValue* v) {
return xaccAccountLookup(v->get<GncGUID*>(), this->t_imap->book); };
return xaccAccountLookup(v->get<GncGUID*>(), gnc_account_get_book(this->t_acc)); };
EXPECT_EQ(t_expense_account1, check_account(value));
value = root->get_slot({IMAP_FRAME, "baz", "waldo"});
EXPECT_EQ(t_expense_account2, check_account(value));
@ -168,30 +158,30 @@ TEST_F(ImapPlainTest, DeleteAccount)
// prevent the embedded beginedit/committedit from doing anything
qof_instance_increase_editlevel(QOF_INSTANCE(t_bank_account));
qof_instance_mark_clean(QOF_INSTANCE(t_bank_account));
gnc_account_imap_add_account(t_imap, "foo", "bar", t_expense_account1);
gnc_account_imap_add_account(t_imap, "foo", "waldo", t_expense_account2);
gnc_account_imap_add_account(t_imap, NULL, "pepper", t_expense_account1);
gnc_account_imap_add_account(t_acc, "foo", "bar", t_expense_account1);
gnc_account_imap_add_account(t_acc, "foo", "waldo", t_expense_account2);
gnc_account_imap_add_account(t_acc, NULL, "pepper", t_expense_account1);
EXPECT_EQ(1, qof_instance_get_editlevel(QOF_INSTANCE(t_bank_account)));
EXPECT_TRUE(qof_instance_get_dirty_flag(QOF_INSTANCE(t_bank_account)));
qof_instance_mark_clean(QOF_INSTANCE(t_bank_account));
gnc_account_imap_delete_account(t_imap, NULL, NULL);
gnc_account_imap_delete_account(t_acc, NULL, NULL);
EXPECT_FALSE(qof_instance_get_dirty_flag(QOF_INSTANCE(t_bank_account)));
gnc_account_imap_delete_account(t_imap, "foo", "waldo");
gnc_account_imap_delete_account(t_acc, "foo", "waldo");
EXPECT_TRUE(qof_instance_get_dirty_flag(QOF_INSTANCE(t_bank_account)));
qof_instance_mark_clean(QOF_INSTANCE(t_bank_account));
EXPECT_EQ(t_expense_account1, gnc_account_imap_find_account(t_imap, "foo", "bar"));
EXPECT_EQ(nullptr, gnc_account_imap_find_account(t_imap, "foo", "waldo"));
EXPECT_EQ(t_expense_account1, gnc_account_imap_find_account(t_acc, "foo", "bar"));
EXPECT_EQ(nullptr, gnc_account_imap_find_account(t_acc, "foo", "waldo"));
auto root = qof_instance_get_slots(QOF_INSTANCE(t_bank_account));
EXPECT_EQ(nullptr, root->get_slot(path1));
gnc_account_imap_delete_account(t_imap, "foo", "bar");
gnc_account_imap_delete_account(t_acc, "foo", "bar");
EXPECT_TRUE(qof_instance_get_dirty_flag(QOF_INSTANCE(t_bank_account)));
qof_instance_mark_clean(QOF_INSTANCE(t_bank_account));
EXPECT_EQ(nullptr, root->get_slot(path2));
gnc_account_imap_delete_account(t_imap, NULL, "pepper");
gnc_account_imap_delete_account(t_acc, NULL, "pepper");
EXPECT_TRUE(qof_instance_get_dirty_flag(QOF_INSTANCE(t_bank_account)));
qof_instance_mark_clean(QOF_INSTANCE(t_bank_account));
EXPECT_EQ(nullptr, root->get_slot(path3));
@ -258,23 +248,23 @@ TEST_F(ImapBayesTest, FindAccountBayes)
root->set_path({std::string{IMAP_FRAME_BAYES} + "/" + pepper + "/" + acct1_guid}, new KvpValue{*value});
root->set_path({std::string{IMAP_FRAME_BAYES} + "/" + salt + "/" + acct2_guid}, new KvpValue{*value});
auto account = gnc_account_imap_find_account_bayes(t_imap, t_list1);
auto account = gnc_account_imap_find_account_bayes(t_acc, t_list1);
EXPECT_EQ(t_expense_account1, account);
account = gnc_account_imap_find_account_bayes(t_imap, t_list2);
account = gnc_account_imap_find_account_bayes(t_acc, t_list2);
EXPECT_EQ(t_expense_account2, account);
account = gnc_account_imap_find_account_bayes(t_imap, t_list3);
account = gnc_account_imap_find_account_bayes(t_acc, t_list3);
EXPECT_EQ(t_expense_account1, account);
account = gnc_account_imap_find_account_bayes(t_imap, t_list4);
account = gnc_account_imap_find_account_bayes(t_acc, t_list4);
EXPECT_EQ(t_expense_account2, account);
account = gnc_account_imap_find_account_bayes(t_imap, t_list5);
account = gnc_account_imap_find_account_bayes(t_acc, t_list5);
EXPECT_EQ(nullptr, account);
// only imap entries with exact token matching should be considered
root->set_path({std::string{IMAP_FRAME_BAYES} + "/" + pepper + waldo + "/" + acct2_guid}, new KvpValue{*value});
account = gnc_account_imap_find_account_bayes(t_imap, t_list3);
account = gnc_account_imap_find_account_bayes(t_acc, t_list3);
EXPECT_EQ(t_expense_account1, account);
root->set_path({std::string{IMAP_FRAME_BAYES} + "/" + pepper + "/" + waldo + "/" + acct2_guid}, new KvpValue{*value});
account = gnc_account_imap_find_account_bayes(t_imap, t_list3);
account = gnc_account_imap_find_account_bayes(t_acc, t_list3);
EXPECT_EQ(t_expense_account1, account);
}
@ -283,14 +273,14 @@ TEST_F(ImapBayesTest, AddAccountBayes)
// prevent the embedded beginedit/committedit from doing anything
qof_instance_increase_editlevel(QOF_INSTANCE(t_bank_account));
qof_instance_mark_clean(QOF_INSTANCE(t_bank_account));
gnc_account_imap_add_account_bayes(t_imap, t_list1, t_expense_account1);
gnc_account_imap_add_account_bayes(t_imap, t_list2, t_expense_account2);
gnc_account_imap_add_account_bayes(t_imap, t_list3, t_expense_account1);
gnc_account_imap_add_account_bayes(t_imap, t_list4, t_expense_account2);
gnc_account_imap_add_account_bayes(t_acc, t_list1, t_expense_account1);
gnc_account_imap_add_account_bayes(t_acc, t_list2, t_expense_account2);
gnc_account_imap_add_account_bayes(t_acc, t_list3, t_expense_account1);
gnc_account_imap_add_account_bayes(t_acc, t_list4, t_expense_account2);
EXPECT_EQ(1, qof_instance_get_editlevel(QOF_INSTANCE(t_bank_account)));
EXPECT_TRUE(qof_instance_get_dirty_flag(QOF_INSTANCE(t_bank_account)));
qof_instance_mark_clean(QOF_INSTANCE(t_bank_account));
gnc_account_imap_add_account_bayes(t_imap, t_list5, NULL);
gnc_account_imap_add_account_bayes(t_acc, t_list5, NULL);
EXPECT_FALSE(qof_instance_get_dirty_flag(QOF_INSTANCE(t_bank_account)));
qof_instance_reset_editlevel(QOF_INSTANCE(t_bank_account));
@ -299,7 +289,7 @@ TEST_F(ImapBayesTest, AddAccountBayes)
auto acct2_guid = guid_to_string (xaccAccountGetGUID(t_expense_account2));
auto value = root->get_slot({std::string{IMAP_FRAME_BAYES} + "/foo/bar"});
auto check_account = [this](KvpValue* v) {
return (v->get<const char*>(), this->t_imap->book); };
return (v->get<const char*>(), gnc_account_get_book(this->t_acc)); };
value = root->get_slot({std::string{IMAP_FRAME_BAYES} + "/" + foo + "/" + acct1_guid});
EXPECT_EQ(1, value->get<int64_t>());
value = root->get_slot({std::string{IMAP_FRAME_BAYES} + "/" + bar + "/" + acct1_guid});
@ -316,7 +306,7 @@ TEST_F(ImapBayesTest, AddAccountBayes)
EXPECT_EQ(nullptr, value);
qof_instance_increase_editlevel(QOF_INSTANCE(t_bank_account));
gnc_account_imap_add_account_bayes(t_imap, t_list2, t_expense_account2);
gnc_account_imap_add_account_bayes(t_acc, t_list2, t_expense_account2);
qof_instance_mark_clean(QOF_INSTANCE(t_bank_account));
qof_instance_reset_editlevel(QOF_INSTANCE(t_bank_account));
value = root->get_slot({std::string{IMAP_FRAME_BAYES} + "/" + baz + "/" + acct2_guid});
@ -326,7 +316,7 @@ TEST_F(ImapBayesTest, AddAccountBayes)
TEST_F(ImapBayesTest, ConvertBayesData)
{
auto root = qof_instance_get_slots(QOF_INSTANCE(t_bank_account));
auto book = qof_instance_get_slots(QOF_INSTANCE(t_imap->book));
auto book = qof_instance_get_slots(QOF_INSTANCE(gnc_account_get_book(this->t_acc)));
auto acct1_guid = guid_to_string (xaccAccountGetGUID(t_expense_account1)); //Food
auto acct2_guid = guid_to_string (xaccAccountGetGUID(t_expense_account2)); //Drink
auto acct3_guid = guid_to_string (xaccAccountGetGUID(t_asset_account2)); //Asset-Bank
@ -345,7 +335,7 @@ TEST_F(ImapBayesTest, ConvertBayesData)
/* make sure to reset the conversion has been run flag */
gnc_account_reset_convert_bayes_to_flat ();
/*Calling into the imap functions should trigger a conversion.*/
gnc_account_imap_add_account_bayes(t_imap, t_list5, t_expense_account2); //pork and sausage; account Food
gnc_account_imap_add_account_bayes(t_acc, t_list5, t_expense_account2); //pork and sausage; account Food
// convert from 'Asset-Bank' to 'Asset-Bank' guid
auto value = root->get_slot({std::string{IMAP_FRAME_BAYES} + "/severely/divided/token/" + acct3_guid});
EXPECT_EQ(10, value->get<int64_t>());
@ -373,10 +363,10 @@ TEST_F (ImapBayesTest, import_map_with_delimiters)
{
GList * tokens {nullptr};
tokens = g_list_prepend (tokens, const_cast<char*> ("one/two/three"));
gnc_account_imap_add_account_bayes (t_imap, tokens, t_expense_account1);
gnc_account_imap_add_account_bayes (t_imap, tokens, t_expense_account1);
gnc_account_imap_add_account_bayes (t_imap, tokens, t_expense_account1);
auto account = gnc_account_imap_find_account_bayes (t_imap, tokens);
gnc_account_imap_add_account_bayes (t_acc, tokens, t_expense_account1);
gnc_account_imap_add_account_bayes (t_acc, tokens, t_expense_account1);
gnc_account_imap_add_account_bayes (t_acc, tokens, t_expense_account1);
auto account = gnc_account_imap_find_account_bayes (t_acc, tokens);
EXPECT_EQ (account, t_expense_account1);
}
@ -384,8 +374,8 @@ TEST_F (ImapBayesTest, get_bayes_info)
{
GList * tokens {nullptr};
tokens = g_list_prepend (tokens, const_cast <char*> ("one/two/three"));
gnc_account_imap_add_account_bayes(t_imap, tokens, t_expense_account1);
auto account = gnc_account_imap_find_account_bayes (t_imap, tokens);
gnc_account_imap_add_account_bayes(t_acc, tokens, t_expense_account1);
auto account = gnc_account_imap_find_account_bayes (t_acc, tokens);
EXPECT_EQ (account, t_expense_account1);
auto infos = gnc_account_imap_get_info_bayes (t_bank_account);
EXPECT_EQ (g_list_first (infos), g_list_last (infos));