diff -Naur ../gnucash-2.6.4-orig/src/import-export/aqb/assistant-ab-initial.c src/import-export/aqb/assistant-ab-initial.c --- ../gnucash-2.6.4-orig/src/import-export/aqb/assistant-ab-initial.c 2014-05-02 12:42:37.000000000 -0700 +++ src/import-export/aqb/assistant-ab-initial.c 2015-11-01 13:42:02.881771000 -0800 @@ -730,7 +730,7 @@ currency); } - gnc_acc = gnc_import_select_account(info->window, NULL, TRUE, + gnc_acc = gnc_import_select_account(info->window, AQB_IMPORTER_ONLINE_ID_NAMESPACE_AQB, NULL, TRUE, longname, commodity, ACCT_TYPE_BANK, old_value, &ok_pressed); g_free(longname); diff -Naur ../gnucash-2.6.4-orig/src/import-export/aqb/gnc-ab-utils.c src/import-export/aqb/gnc-ab-utils.c --- ../gnucash-2.6.4-orig/src/import-export/aqb/gnc-ab-utils.c 2014-05-02 12:42:37.000000000 -0700 +++ src/import-export/aqb/gnc-ab-utils.c 2015-11-01 13:46:54.485718000 -0800 @@ -593,7 +593,8 @@ accountnumber ? accountnumber : "", (gchar*)NULL); gnc_acc = gnc_import_select_account( - NULL, online_id, 1, AB_ImExporterAccountInfo_GetAccountName(acc_info), + NULL, AQB_IMPORTER_ONLINE_ID_NAMESPACE_AQB, online_id, 1, + AB_ImExporterAccountInfo_GetAccountName(acc_info), NULL, ACCT_TYPE_NONE, NULL, NULL); if (!gnc_acc) { diff -Naur ../gnucash-2.6.4-orig/src/import-export/import-account-matcher.c src/import-export/import-account-matcher.c --- ../gnucash-2.6.4-orig/src/import-export/import-account-matcher.c 2014-09-08 12:08:24.000000000 -0700 +++ src/import-export/import-account-matcher.c 2015-11-02 10:21:32.094141000 -0800 @@ -47,6 +47,15 @@ #define STATE_SECTION "dialogs/import/generic_matcher/account_matcher" +/* + * Struct to enable passing as single argument to worker function + * via gnc_account_foreach_descendant_until() + */ +struct fully_qualified_online_id { + const gchar *account_online_id_namespace; + const gchar *account_online_id_value; +}; + /*-******************************************************************\ * Functions needed by gnc_import_select_account * @@ -63,6 +72,7 @@ picker->account_tree_sw = NULL; picker->auto_create = TRUE; picker->account_human_description = NULL; + picker->account_online_id_namespace = NULL; picker->account_online_id_value = NULL; picker->account_online_id_label = NULL; picker->new_account_default_commodity = NULL; @@ -80,17 +90,44 @@ **************************************************/ static gpointer test_acct_online_id_match(Account *acct, gpointer param_online_id) { - const gchar * current_online_id = gnc_import_get_acc_online_id(acct); - if ( (current_online_id != NULL - && param_online_id != NULL ) - && strcmp( current_online_id, param_online_id ) == 0 ) + struct fully_qualified_online_id *fqoi = param_online_id; + const gchar *current_online_id; + + if (!param_online_id) + { + return NULL; + } + + if (!fqoi->account_online_id_value) + { + return NULL; + } + + /* + * First try matching online_id with the specified namespace + */ + current_online_id = + gnc_import_get_acc_online_id(acct, fqoi->account_online_id_namespace); + + if ( (current_online_id != NULL) + && strcmp( current_online_id, fqoi->account_online_id_value ) == 0 ) { return (gpointer *) acct; } - else + + /* + * For compatibility with pre-online-id-namespace versions of + * the account data, try again with no namespace + */ + current_online_id = gnc_import_get_acc_online_id(acct, NULL); + + if ( (current_online_id != NULL) + && strcmp( current_online_id, fqoi->account_online_id_value ) == 0 ) { - return NULL; + return (gpointer *) acct; } + + return NULL; } @@ -193,17 +230,25 @@ } else if ( picker->account_online_id_value != NULL) { + struct fully_qualified_online_id fqoi; + + fqoi.account_online_id_value = picker->account_online_id_value; + fqoi.account_online_id_namespace = picker->account_online_id_namespace; + /* find the old account for this on line id value and reset it */ old_id_acc = gnc_account_foreach_descendant_until(gnc_get_current_root_account (), test_acct_online_id_match, /* This argument will only be used as a "const char*" */ - (void*)picker->account_online_id_value); + (void*)&fqoi); if (old_id_acc != NULL) - gnc_import_set_acc_online_id(old_id_acc, ""); + gnc_import_set_acc_online_id(old_id_acc, + picker->account_online_id_namespace, ""); - gnc_import_set_acc_online_id(picker->retAccount, picker->account_online_id_value); + gnc_import_set_acc_online_id(picker->retAccount, + picker->account_online_id_namespace, + picker->account_online_id_value); gtk_assistant_set_page_complete (assistant, page, TRUE); } else @@ -222,6 +267,7 @@ * Main call for use with a dialog *******************************************************/ Account * gnc_import_select_account(GtkWidget *parent, + const gchar * account_online_id_namespace, const gchar * account_online_id_value, gboolean auto_create, const gchar * account_human_description, @@ -245,46 +291,25 @@ picker = g_new0(AccountPickerDialog, 1); picker->account_online_id_value = account_online_id_value; + picker->account_online_id_value = account_online_id_namespace; picker->account_human_description = account_human_description; picker->new_account_default_commodity = new_account_default_commodity; picker->new_account_default_type = new_account_default_type; - /*DEBUG("Looking for account with online_id: \"%s\"", account_online_id_value);*/ + DEBUG("Looking for account with online_id: \"%s\"", + account_online_id_value); if (account_online_id_value != NULL) { + struct fully_qualified_online_id fqoi; + + fqoi.account_online_id_value = account_online_id_value; + fqoi.account_online_id_namespace = account_online_id_namespace; + retval = gnc_account_foreach_descendant_until(gnc_get_current_root_account (), test_acct_online_id_match, /* This argument will only be used as a "const char*" */ - (void*)account_online_id_value); - - /* BEGIN: try again without extra space at the end */ - /* - * libofx, used for file import, generates online_id as - * ACCTID + space + ACCTKEY which differs from the online_id - * generated by aqbanking for online ofx transfer as ACCTID. - * - * If a gnucash account has been associated with an online_id - * via aqbanking data, it is not possible to construct an OFX - * file for gnucash import that matches the same online_id - * because even with no ACCTKEY in the file, there will be a - * trailing space. - * - * This is a hack to overcome that problem. - */ - if ((retval == NULL) && g_str_has_suffix(account_online_id_value, " ")) - { - gchar *trimmed = g_strndup(account_online_id_value, strlen(account_online_id_value) - 1); - if (trimmed) - { - retval = gnc_account_foreach_descendant_until( - gnc_get_current_root_account (), - test_acct_online_id_match, - (void *)trimmed); - } - g_free(trimmed); - } - /* END: try again without extra space at the end */ + (void*)&fqoi); } if (retval == NULL && auto_create != 0) { @@ -364,7 +389,8 @@ if ( account_online_id_value != NULL) { - gnc_import_set_acc_online_id(retval, account_online_id_value); + gnc_import_set_acc_online_id(retval, + account_online_id_namespace, account_online_id_value); } ok_pressed_retval = TRUE; break; @@ -472,11 +498,16 @@ /*DEBUG("Looking for account with online_id: %s", picker->account_online_id_value);*/ if (picker->account_online_id_value != NULL) { + struct fully_qualified_online_id fqoi; + + fqoi.account_online_id_value = picker->account_online_id_value; + fqoi.account_online_id_namespace = picker->account_online_id_namespace; + picker->retAccount = gnc_account_foreach_descendant_until(gnc_get_current_root_account (), test_acct_online_id_match, /* This argument will only be used as a "const char*" */ - (void*)picker->account_online_id_value); + (void*)&fqoi); } if (picker->account_human_description != NULL) diff -Naur ../gnucash-2.6.4-orig/src/import-export/import-account-matcher.h src/import-export/import-account-matcher.h --- ../gnucash-2.6.4-orig/src/import-export/import-account-matcher.h 2014-05-02 12:42:24.000000000 -0700 +++ src/import-export/import-account-matcher.h 2015-11-01 13:31:23.997043000 -0800 @@ -35,6 +35,12 @@ #include "gnc-tree-view-account.h" +/* + * online_id namespace names + */ +#define AQB_IMPORTER_ONLINE_ID_NAMESPACE_AQB "aqb" +#define AQB_IMPORTER_ONLINE_ID_NAMESPACE_OFX "ofx" + typedef struct { GtkWidget *dialog; /* Dialog Widget */ @@ -43,6 +49,7 @@ GtkWidget *account_tree_sw; /* Scroll Window for Account tree */ gboolean auto_create; /* Auto create retAccount, can be used to step over this stage */ const gchar *account_human_description; /* description for on line id, incoming */ + const gchar *account_online_id_namespace; /* On line id namespace, incoming */ const gchar *account_online_id_value; /* On line id value, incoming */ GtkWidget *account_online_id_label; /* the label Widget for the on line id, incoming */ const gnc_commodity *new_account_default_commodity; /* new account default commodity, incoming */ @@ -62,6 +69,10 @@ @param parent The parent widget. Can be NULL. + @param account_online_id_namespace The string containing the + name of the namespace for account_online_id_value. Typically, + the namespace name will be the importer module name. + @param account_online_id_value The string containing your unique account_id coming from some string of your module. This is the normal mode of operation. Can be NULL. @@ -113,6 +124,7 @@ account was found or created. */ Account * gnc_import_select_account(GtkWidget *parent, + const gchar * account_online_id_namespace, const gchar * account_online_id_value, gboolean auto_create, const gchar * account_human_description, diff -Naur ../gnucash-2.6.4-orig/src/import-export/import-main-matcher.c src/import-export/import-main-matcher.c --- ../gnucash-2.6.4-orig/src/import-export/import-main-matcher.c 2014-09-08 12:08:24.000000000 -0700 +++ src/import-export/import-main-matcher.c 2015-11-02 11:52:34.951315000 -0800 @@ -259,6 +259,7 @@ old_acc = gnc_import_TransInfo_get_destacc (trans_info); new_acc = gnc_import_select_account(info->dialog, NULL, + NULL, TRUE, _("Destination account for the auto-balance split."), xaccTransGetCurrency(gnc_import_TransInfo_get_trans(trans_info)), diff -Naur ../gnucash-2.6.4-orig/src/import-export/import-utilities.c src/import-export/import-utilities.c --- ../gnucash-2.6.4-orig/src/import-export/import-utilities.c 2014-09-08 12:08:24.000000000 -0700 +++ src/import-export/import-utilities.c 2015-11-02 10:28:30.625453000 -0800 @@ -40,25 +40,60 @@ * Account, Transaction and Split \********************************************************************/ -const gchar * gnc_import_get_acc_online_id(Account * account) +const gchar * gnc_import_get_acc_online_id(Account * account, + const gchar * namespace) { kvp_frame * frame; + const gchar * retval; + gchar * online_id_path = "online_id"; frame = xaccAccountGetSlots(account); - return kvp_frame_get_string(frame, "online_id"); + + if (namespace) + { + const gchar * oiprefix = "online_ids/"; + + online_id_path = g_malloc(strlen(oiprefix) + strlen(namespace) + 1); + strcpy(online_id_path, oiprefix); + strcat(online_id_path, namespace); + } + + retval = kvp_frame_get_string(frame, online_id_path); + if (namespace) + { + g_free(online_id_path); + } + return retval; } /* Used in the midst of editing a transaction; make it save the * account data. */ void gnc_import_set_acc_online_id(Account * account, + const gchar * namespace, const gchar * string_value) { kvp_frame * frame; + gchar * online_id_path = "online_id"; + g_return_if_fail (account != NULL); frame = xaccAccountGetSlots(account); + + if (namespace) + { + const gchar * oiprefix = "online_ids/"; + + online_id_path = g_malloc(strlen(oiprefix) + strlen(namespace) + 1); + strcpy(online_id_path, oiprefix); + strcat(online_id_path, namespace); + } + xaccAccountBeginEdit (account); - kvp_frame_set_str(frame, "online_id", string_value); + kvp_frame_set_str(frame, online_id_path, string_value); qof_instance_set_dirty (QOF_INSTANCE (account)); xaccAccountCommitEdit (account); + if (namespace) + { + g_free(online_id_path); + } } const gchar * gnc_import_get_trans_online_id(Transaction * transaction) diff -Naur ../gnucash-2.6.4-orig/src/import-export/import-utilities.h src/import-export/import-utilities.h --- ../gnucash-2.6.4-orig/src/import-export/import-utilities.h 2014-05-02 12:42:24.000000000 -0700 +++ src/import-export/import-utilities.h 2015-11-02 10:01:56.222349000 -0800 @@ -44,8 +44,10 @@ Accounts. @{ */ -const gchar * gnc_import_get_acc_online_id(Account * account); +const gchar * gnc_import_get_acc_online_id(Account * account, + const gchar * namespace); void gnc_import_set_acc_online_id(Account * account, + const gchar * namespace, const gchar * string_value); /** @} */ /** @name Setter-getters diff -Naur ../gnucash-2.6.4-orig/src/import-export/ofx/gnc-ofx-import.c src/import-export/ofx/gnc-ofx-import.c --- ../gnucash-2.6.4-orig/src/import-export/ofx/gnc-ofx-import.c 2014-09-27 14:01:12.000000000 -0700 +++ src/import-export/ofx/gnc-ofx-import.c 2015-11-02 11:58:41.877189000 -0800 @@ -354,6 +354,7 @@ gnc_utf8_strip_invalid (data.account_id); account = gnc_import_select_account(gnc_gen_trans_list_widget(gnc_ofx_importer_gui), + AQB_IMPORTER_ONLINE_ID_NAMESPACE_OFX, data.account_id, 0, NULL, NULL, ACCT_TYPE_NONE, NULL, NULL); @@ -567,6 +568,7 @@ data.account_id, data.unique_id); investment_account = gnc_import_select_account(NULL, + AQB_IMPORTER_ONLINE_ID_NAMESPACE_OFX, investment_account_onlineid, 1, investment_account_text, @@ -596,6 +598,7 @@ // Let the user choose an account investment_account = gnc_import_select_account( gnc_gen_trans_list_widget(gnc_ofx_importer_gui), + AQB_IMPORTER_ONLINE_ID_NAMESPACE_OFX, data.unique_id, TRUE, investment_account_text, @@ -625,7 +628,10 @@ ACCT_TYPE_STOCK); if (investment_account) { - gnc_import_set_acc_online_id(investment_account, data.unique_id); + gnc_import_set_acc_online_id( + investment_account, + AQB_IMPORTER_ONLINE_ID_NAMESPACE_OFX, + data.unique_id); choosing_account = FALSE; ofx_parent_account = parent_account; } @@ -649,7 +655,8 @@ gnc_commodity_get_fullname(investment_commodity), gnc_commodity_get_fullname(xaccAccountGetCommodity(investment_account))); // We must also delete the online_id that was set in gnc_import_select_account() - gnc_import_set_acc_online_id(investment_account, ""); + gnc_import_set_acc_online_id(investment_account, + AQB_IMPORTER_ONLINE_ID_NAMESPACE_OFX, ""); investment_account = NULL; } } @@ -730,6 +737,7 @@ sanitize_string (data.security_data_ptr->secname)); income_account = gnc_import_select_account( gnc_gen_trans_list_widget(gnc_ofx_importer_gui), + AQB_IMPORTER_ONLINE_ID_NAMESPACE_OFX, NULL, 1, investment_account_text, @@ -912,7 +920,8 @@ "%s \"%s\"", account_type_name, data.account_name); - gnc_import_select_account(NULL, data.account_id, 1, + gnc_import_select_account(NULL, AQB_IMPORTER_ONLINE_ID_NAMESPACE_OFX, + data.account_id, 1, account_description, default_commodity, default_type, NULL, NULL); g_free(account_description);