--- Begin Message ---
Package: gnucash
Version: 2.2.4-2
Severity: important
Tags: fixed-upstream patch
Hi Thomas,
on the Gnucash development mailing list David Reiser [1]reported a
problem with fetching transactions via OFX directconnect: OFX statements
get successfully downloaded by AqBanking but don't get imported to Gnucash.
1.
http://www.nabble.com/ofxdirectconnect-in-aqbanking3-branch-td18354864.html
Fortunately the bug is fixed in upstream in the changeset [2]17347,
which has been released with Gnucash 2.2.6 recently. I've extracted the
changeset and attached it to this mail as a patch. You should be able to
apply this patch on top of the unpackaged (thus already patched) source
package of gnucash 2.2.4-2 using the command
"patch -p0 < /path/to/aqb_data_handoff.patch".
2. http://svn.gnucash.org/trac/changeset/17347
It would be very helpful if this patch finds its way into the release of
Debian Lenny.
Regards
Micha
Index: src/import-export/aqbanking/gnc-ab-transfer.c
===================================================================
--- src/import-export/aqbanking/gnc-ab-transfer.c (Revision 17346)
+++ src/import-export/aqbanking/gnc-ab-transfer.c (Revision 17347)
@@ -133,6 +133,8 @@
gchar *description;
gchar *memo;
Transaction *gnc_trans = NULL;
+ AB_IMEXPORTER_CONTEXT *context = NULL;
+ GncABImExContextImport *ieci = NULL;
/* Get a GUI object */
gui = gnc_GWEN_Gui_get(parent);
@@ -226,8 +228,11 @@
}
if (result == GNC_RESPONSE_NOW) {
+ /* Create a context to store possible results */
+ context = AB_ImExporterContext_new();
+
/* Finally, execute the job */
- successful = AB_Banking_ExecuteJobs(api, job_list, NULL, 0) == 0;
+ successful = AB_Banking_ExecuteJobs(api, job_list, context, 0) == 0;
if (!successful
|| AB_Job_GetStatus(job) != AB_Job_StatusFinished) {
@@ -248,6 +253,9 @@
aborted = TRUE;
}
}
+
+ /* Import the results, awaiting nothing */
+ ieci = gnc_ab_import_context(context, 0, FALSE, NULL, parent);
}
/* Simply ignore any other case */
@@ -259,6 +267,10 @@
xaccTransCommitEdit(gnc_trans);
gnc_trans = NULL;
}
+ if (ieci)
+ g_free(ieci);
+ if (context)
+ AB_ImExporterContext_free(context);
if (job_list) {
AB_Job_List2_free(job_list);
job_list = NULL;
Index: src/import-export/aqbanking/gnc-ab-getbalance.c
===================================================================
--- src/import-export/aqbanking/gnc-ab-getbalance.c (Revision 17346)
+++ src/import-export/aqbanking/gnc-ab-getbalance.c (Revision 17347)
@@ -38,7 +38,6 @@
#include "gnc-ab-utils.h"
#include "gnc-gwen-gui.h"
#include "gnc-ui.h"
-#include "RecnWindow.h"
/* This static indicates the debugging module that this .o belongs to. */
static QofLogModule log_module = G_LOG_DOMAIN;
@@ -53,15 +52,7 @@
AB_JOB_LIST2 *job_list = NULL;
GncGWENGui *gui = NULL;
AB_IMEXPORTER_CONTEXT *context = NULL;
- AB_IMEXPORTER_ACCOUNTINFO *acc_info = NULL;
- AB_ACCOUNT_STATUS *status = NULL;
- const AB_BALANCE *booked_bal, *noted_bal;
- const AB_VALUE *booked_val = NULL, *noted_val = NULL;
- gdouble booked_value, noted_value;
- gnc_numeric value;
- time_t booked_tt = 0;
- GtkWidget *dialog;
- gboolean show_recn_window = FALSE;
+ GncABImExContextImport *ieci = NULL;
g_return_if_fail(parent && gnc_acc);
@@ -110,133 +101,12 @@
goto cleanup;
}
- /* Lookup account in context */
- acc_info = AB_ImExporterContext_FindAccountInfo(
- context, gnc_ab_get_account_bankcode(gnc_acc),
- gnc_ab_get_account_accountid(gnc_acc));
- if (!acc_info) {
- g_warning("gnc_ab_getbalance: No accountinfo result for this account");
- goto cleanup;
- }
+ /* Import the results */
+ ieci = gnc_ab_import_context(context, AWAIT_BALANCES, FALSE, NULL, parent);
- /* Lookup newest data */
- status = gnc_ab_get_best_accountstatus(acc_info);
- if (!status) {
- g_warning("gnc_ab_getbalance: No accountstatus result for this account");
- goto cleanup;
- }
-
- /* Lookup booked balance and time */
- booked_bal = AB_AccountStatus_GetBookedBalance(status);
- if (booked_bal) {
- const GWEN_TIME *ti = AB_Balance_GetTime(booked_bal);
- if (ti) {
- booked_tt = GWEN_Time_toTime_t(ti);
- } else {
- /* No time found? Use today because the HBCI query asked for today's
- * balance. */
- booked_tt = gnc_timet_get_day_start(time(NULL));
- }
- booked_val = AB_Balance_GetValue(booked_bal);
- if (booked_val) {
- booked_value = AB_Value_GetValueAsDouble(booked_val);
- } else {
- g_warning("gnc_ab_getbalance: booked_val == NULL. Assuming 0");
- booked_value = 0.0;
- }
- } else {
- g_warning("gnc_ab_getbalance: booked_bal == NULL. Assuming 0");
- booked_tt = 0;
- booked_value = 0.0;
- }
-
- /* Lookup noted balance */
- noted_bal = AB_AccountStatus_GetNotedBalance(status);
- if (noted_bal) {
- noted_val = AB_Balance_GetValue(noted_bal);
- if (noted_val)
- noted_value = AB_Value_GetValueAsDouble(noted_val);
- else {
- g_warning("gnc_ab_getbalance: noted_val == NULL. Assuming 0");
- noted_value = 0.0;
- }
- } else {
- g_warning("gnc_ab_getbalance: noted_bal == NULL. Assuming 0");
- noted_value = 0.0;
- }
-
- value = double_to_gnc_numeric(booked_value,
- xaccAccountGetCommoditySCU(gnc_acc),
- GNC_RND_ROUND);
- if (noted_value == 0.0 && booked_value == 0.0) {
- dialog = gtk_message_dialog_new(
- GTK_WINDOW(parent),
- GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_INFO,
- GTK_BUTTONS_OK,
- "%s",
- /* Translators: Strings from this file are needed only in
- * countries that have one of aqbanking's Online Banking
- * techniques available. This is 'OFX DirectConnect'
- * (U.S. and others), 'HBCI' (in Germany), or 'YellowNet'
- * (Switzerland). If none of these techniques are available
- * in your country, you may safely ignore strings from the
- * import-export/hbci subdirectory. */
- _("The downloaded Online Banking Balance was zero.\n\n"
- "Either this is the correct balance, or your bank does not "
- "support Balance download in this Online Banking version. "
- "In the latter case you should choose a different "
- "Online Banking version number in the Online Banking "
- "(AqBanking or HBCI) Setup. After that, try again to "
- "download the Online Banking Balance."));
- gtk_dialog_run(GTK_DIALOG(dialog));
- gtk_widget_destroy(dialog);
-
- } else {
- gnc_numeric reconc_balance = xaccAccountGetReconciledBalance(gnc_acc);
-
- gchar *booked_str = gnc_AB_VALUE_to_readable_string(booked_val);
- gchar *message1 = g_strdup_printf(
- _("Result of Online Banking job: \n"
- "Account booked balance is %s"),
- booked_str);
- gchar *message2 =
- (noted_value == 0.0) ?
- g_strdup("") :
- g_strdup_printf(_("For your information: This account also "
- "has a noted balance of %s\n"),
- gnc_AB_VALUE_to_readable_string(noted_val));
-
- if (gnc_numeric_equal(value, reconc_balance)) {
- const gchar *message3 =
- _("The booked balance is identical to the current "
- "reconciled balance of the account.");
- dialog = gtk_message_dialog_new(
- GTK_WINDOW(parent),
- GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_INFO,
- GTK_BUTTONS_OK,
- "%s\n%s\n%s",
- message1, message2, message3);
- gtk_dialog_run(GTK_DIALOG(dialog));
- gtk_widget_destroy(GTK_WIDGET(dialog));
-
- } else {
- const char *message3 = _("Reconcile account now?");
-
- show_recn_window = gnc_verify_dialog(parent,TRUE, "%s\n%s\n%s",
- message1, message2, message3);
- }
- g_free(booked_str);
- g_free(message1);
- g_free(message2);
- }
-
- /* Show reconciliation window */
- if (show_recn_window)
- recnWindowWithBalance(parent, gnc_acc, value, booked_tt);
-
cleanup:
+ if (ieci)
+ g_free(ieci);
if (context)
AB_ImExporterContext_free(context);
if (gui)
Index: src/import-export/aqbanking/gnc-ab-gettrans.c
===================================================================
--- src/import-export/aqbanking/gnc-ab-gettrans.c (Revision 17346)
+++ src/import-export/aqbanking/gnc-ab-gettrans.c (Revision 17347)
@@ -47,7 +47,6 @@
typedef struct _TransListData TransListData;
static gboolean gettrans_dates(GtkWidget *parent, Account *gnc_acc, GWEN_TIME **from_date, GWEN_TIME **to_date);
-static const AB_TRANSACTION *transaction_cb(const AB_TRANSACTION *ab_trans, gpointer user_data);
struct _TransListData {
Account *gnc_acc;
@@ -98,28 +97,6 @@
return TRUE;
}
-/**
- * Callback function for AB_ImExporterAccountInfo_TransactionsForEach(). The
- * conversion from AqBanking to GnuCash transaction is done here, once for each
- * AB_TRANSACTION.
- */
-static const AB_TRANSACTION *
-transaction_cb(const AB_TRANSACTION *ab_trans, gpointer user_data)
-{
- TransListData *data = user_data;
- Transaction *gnc_trans;
-
- g_return_val_if_fail(ab_trans && data, NULL);
-
- /* Create a GnuCash transaction from ab_trans */
- gnc_trans = gnc_ab_trans_to_gnc(ab_trans, data->gnc_acc);
-
- /* Instead of xaccTransCommitEdit(gnc_trans) */
- gnc_gen_trans_list_add_trans(data->importer_generic, gnc_trans);
-
- return NULL;
-}
-
void
gnc_ab_gettrans(GtkWidget *parent, Account *gnc_acc)
{
@@ -132,7 +109,7 @@
AB_JOB_LIST2 *job_list = NULL;
GncGWENGui *gui = NULL;
AB_IMEXPORTER_CONTEXT *context = NULL;
- AB_IMEXPORTER_ACCOUNTINFO *acc_info = NULL;
+ GncABImExContextImport *ieci = NULL;
g_return_if_fail(parent && gnc_acc);
@@ -191,25 +168,10 @@
goto cleanup;
}
- /* Lookup account in context */
- acc_info = AB_ImExporterContext_FindAccountInfo(
- context, gnc_ab_get_account_bankcode(gnc_acc),
- gnc_ab_get_account_accountid(gnc_acc));
- if (!acc_info) {
- g_warning("gnc_ab_gettrans: No accountinfo result for this account");
- goto cleanup;
- }
-
- if (AB_ImExporterAccountInfo_GetFirstTransaction(acc_info)) {
- /* Import transactions */
-
- TransListData data;
- data.importer_generic = gnc_gen_trans_list_new(parent, NULL, TRUE, 14);
- data.gnc_acc = gnc_acc;
-
- AB_ImExporterAccountInfo_TransactionsForEach(acc_info, transaction_cb,
- &data);
- } else {
+ /* Import the results */
+ ieci = gnc_ab_import_context(context, AWAIT_TRANSACTIONS, FALSE, NULL,
+ parent);
+ if (!(gnc_ab_ieci_get_found(ieci) & FOUND_TRANSACTIONS)) {
/* No transaction found */
GtkWidget *dialog = gtk_message_dialog_new(
GTK_WINDOW(parent),
@@ -227,6 +189,8 @@
gnc_ab_set_account_trans_retrieval(gnc_acc, until_timespec);
cleanup:
+ if (ieci)
+ g_free(ieci);
if (context)
AB_ImExporterContext_free(context);
if (gui)
Index: src/import-export/aqbanking/gnc-ab-utils.c
===================================================================
--- src/import-export/aqbanking/gnc-ab-utils.c (Revision 17346)
+++ src/import-export/aqbanking/gnc-ab-utils.c (Revision 17347)
@@ -33,11 +33,16 @@
#include <gwenhywfar/gwenhywfar.h>
#include <aqbanking/banking.h>
+#include "RecnWindow.h"
#include "Transaction.h"
+#include "dialog-ab-trans.h"
#include "gnc-ab-kvp.h"
#include "gnc-ab-utils.h"
#include "gnc-glib-utils.h"
#include "gnc-gwen-gui.h"
+#include "gnc-ui.h"
+#include "import-account-matcher.h"
+#include "import-main-matcher.h"
#include "import-utilities.h"
#include "qof.h"
@@ -49,7 +54,27 @@
static gint gnc_AB_BANKING_refcount = 0;
static gpointer join_ab_strings_cb(const gchar *str, gpointer user_data);
+static Account *gnc_ab_accinfo_to_gnc_acc(
+ AB_IMEXPORTER_ACCOUNTINFO *account_info);
+static const AB_TRANSACTION *txn_transaction_cb(
+ const AB_TRANSACTION *element, gpointer user_data);
+static AB_IMEXPORTER_ACCOUNTINFO *txn_accountinfo_cb(
+ AB_IMEXPORTER_ACCOUNTINFO *element, gpointer user_data);
+static AB_IMEXPORTER_ACCOUNTINFO *bal_accountinfo_cb(
+ AB_IMEXPORTER_ACCOUNTINFO *element, gpointer user_data);
+struct _GncABImExContextImport {
+ guint awaiting;
+ gboolean txn_found;
+ Account *gnc_acc;
+ AB_ACCOUNT *ab_acc;
+ gboolean execute_txns;
+ AB_BANKING *api;
+ GtkWidget *parent;
+ AB_JOB_LIST2 *job_list;
+ GNCImportMainMatcher *generic_importer;
+};
+
void
gnc_GWEN_Init(void)
{
@@ -393,22 +418,381 @@
return gnc_trans;
}
-AB_ACCOUNT_STATUS *
-gnc_ab_get_best_accountstatus(AB_IMEXPORTER_ACCOUNTINFO *acc_info)
+/**
+ * Call gnc_import_select_account() on the online id constructed using
+ * the information in @a acc_info.
+ *
+ * @param acc_info AB_IMEXPORTER_ACCOUNTINFO
+ * @return A GnuCash account, or NULL otherwise
+ */
+static Account *
+gnc_ab_accinfo_to_gnc_acc(AB_IMEXPORTER_ACCOUNTINFO *acc_info)
{
+ gchar *online_id;
+ Account *gnc_acc;
+
+ g_return_val_if_fail(acc_info, NULL);
+
+ online_id = g_strconcat(AB_ImExporterAccountInfo_GetBankCode(acc_info),
+ AB_ImExporterAccountInfo_GetAccountNumber(acc_info),
+ (gchar*)NULL);
+ gnc_acc = gnc_import_select_account(
+ NULL, online_id, 1, AB_ImExporterAccountInfo_GetAccountName(acc_info),
+ NULL, ACCT_TYPE_NONE, NULL, NULL);
+ if (!gnc_acc) {
+ g_warning("gnc_ab_accinfo_to_gnc_acc: Could not determine source account"
+ " for online_id %s", online_id);
+ }
+ g_free(online_id);
+
+ return gnc_acc;
+}
+
+static const AB_TRANSACTION *
+txn_transaction_cb(const AB_TRANSACTION *element, gpointer user_data)
+{
+ GncABImExContextImport *data = user_data;
+ Transaction *gnc_trans;
+
+ g_return_val_if_fail(element && data, NULL);
+
+ /* Create a GnuCash transaction from ab_trans */
+ gnc_trans = gnc_ab_trans_to_gnc(element, data->gnc_acc);
+
+ /* Instead of xaccTransCommitEdit(gnc_trans) */
+ gnc_gen_trans_list_add_trans(data->generic_importer, gnc_trans);
+
+ if (data->execute_txns && data->ab_acc) {
+ AB_TRANSACTION *ab_trans = AB_Transaction_dup(element);
+ AB_JOB *job;
+
+ /* NEW: The imported transaction has been imported into gnucash.
+ * Now also add it as a job to aqbanking */
+ AB_Transaction_SetLocalBankCode(
+ ab_trans, AB_Account_GetBankCode(data->ab_acc));
+ AB_Transaction_SetLocalAccountNumber(
+ ab_trans, AB_Account_GetAccountNumber(data->ab_acc));
+ AB_Transaction_SetLocalCountry(ab_trans, "DE");
+
+ job = gnc_ab_get_trans_job(data->ab_acc, ab_trans, SINGLE_DEBITNOTE);
+
+ /* Check whether we really got a job */
+ if (!job) {
+ /* Oops, no job, probably not supported by bank */
+ if (gnc_verify_dialog(
+ NULL, FALSE, "%s",
+ _("The backend found an error during the preparation "
+ "of the job. It is not possible to execute this job. \n"
+ "\n"
+ "Most probable the bank does not support your chosen "
+ "job or your Online Banking account does not have the permission "
+ "to execute this job. More error messages might be "
+ "visible on your console log.\n"
+ "\n"
+ "Do you want to enter the job again?"))) {
+ gnc_error_dialog(NULL, "Sorry, not implemented yet.");
+ }
+ /* else */
+ }
+ AB_Job_List2_PushBack(data->job_list, job);
+
+ AB_Transaction_free(ab_trans);
+ }
+
+ return NULL;
+}
+
+static AB_IMEXPORTER_ACCOUNTINFO *
+txn_accountinfo_cb(AB_IMEXPORTER_ACCOUNTINFO *element, gpointer user_data)
+{
+ GncABImExContextImport *data = user_data;
+ Account *gnc_acc;
+
+ g_return_val_if_fail(element && data, NULL);
+
+ if (data->awaiting & IGNORE_TRANSACTIONS)
+ /* Ignore them */
+ return NULL;
+
+ if (!AB_ImExporterAccountInfo_GetFirstTransaction(element))
+ /* No transaction found */
+ return NULL;
+ else
+ data->awaiting |= FOUND_TRANSACTIONS;
+
+ if (!(data->awaiting & AWAIT_TRANSACTIONS)) {
+ if (gnc_verify_dialog(data->parent, TRUE, "%s",
+ _("The bank has sent transaction information "
+ "in its response."
+ "\n"
+ "Do you want to import it?"))) {
+ data->awaiting |= AWAIT_TRANSACTIONS;
+ } else {
+ data->awaiting |= IGNORE_TRANSACTIONS;
+ return NULL;
+ }
+ }
+
+ /* Lookup the corresponding gnucash account */
+ gnc_acc = gnc_ab_accinfo_to_gnc_acc(element);
+ if (!gnc_acc) return NULL;
+ data->gnc_acc = gnc_acc;
+
+ if (data->execute_txns) {
+ /* Retrieve the aqbanking account that belongs to this gnucash
+ * account */
+ data->ab_acc = gnc_ab_get_ab_account(data->api, gnc_acc);
+ if (!data->ab_acc) {
+ gnc_error_dialog(NULL, "%s",
+ _("No Online Banking account found for this "
+ "gnucash account. These transactions will "
+ "not be executed by Online Banking."));
+ }
+ } else {
+ data->ab_acc = NULL;
+ }
+
+ if (!data->generic_importer)
+ data->generic_importer = gnc_gen_trans_list_new(data->parent, NULL,
+ TRUE, 14);
+
+ /* Iterate through all transactions */
+ AB_ImExporterAccountInfo_TransactionsForEach(element, txn_transaction_cb,
+ data);
+
+ return NULL;
+}
+
+static AB_IMEXPORTER_ACCOUNTINFO *
+bal_accountinfo_cb(AB_IMEXPORTER_ACCOUNTINFO *element, gpointer user_data)
+{
+ GncABImExContextImport *data = user_data;
+ Account *gnc_acc;
AB_ACCOUNT_STATUS *item, *best = NULL;
const GWEN_TIME *best_time;
+ const AB_BALANCE *booked_bal, *noted_bal;
+ const AB_VALUE *booked_val = NULL, *noted_val = NULL;
+ gdouble booked_value, noted_value;
+ gnc_numeric value;
+ time_t booked_tt = 0;
+ GtkWidget *dialog;
+ gboolean show_recn_window = FALSE;
- g_return_val_if_fail(acc_info, NULL);
+ g_return_val_if_fail(element && data, NULL);
- item = AB_ImExporterAccountInfo_GetFirstAccountStatus(acc_info);
+ if (data->awaiting & IGNORE_BALANCES)
+ /* Ignore them */
+ return NULL;
+
+ if (!AB_ImExporterAccountInfo_GetFirstAccountStatus(element))
+ /* No balance found */
+ return NULL;
+ else
+ data->awaiting |= FOUND_BALANCES;
+
+ if (!(data->awaiting & AWAIT_BALANCES)) {
+ if (gnc_verify_dialog(data->parent, TRUE, "%s",
+ _("The bank has sent balance information "
+ "in its response."
+ "\n"
+ "Do you want to import it?"))) {
+ data->awaiting |= AWAIT_BALANCES;
+ } else {
+ data->awaiting |= IGNORE_BALANCES;
+ return NULL;
+ }
+ }
+
+ /* Lookup the corresponding gnucash account */
+ gnc_acc = gnc_ab_accinfo_to_gnc_acc(element);
+ if (!gnc_acc) return NULL;
+ data->gnc_acc = gnc_acc;
+
+ /* Lookup the most recent ACCOUNT_STATUS available */
+ item = AB_ImExporterAccountInfo_GetFirstAccountStatus(element);
while (item) {
const GWEN_TIME *item_time = AB_AccountStatus_GetTime(item);
if (!best || GWEN_Time_Diff(best_time, item_time) < 0.0) {
best = item;
best_time = item_time;
}
- item = AB_ImExporterAccountInfo_GetNextAccountStatus(acc_info);
+ item = AB_ImExporterAccountInfo_GetNextAccountStatus(element);
}
- return best;
+
+ /* Lookup booked balance and time */
+ booked_bal = AB_AccountStatus_GetBookedBalance(best);
+ if (booked_bal) {
+ const GWEN_TIME *ti = AB_Balance_GetTime(booked_bal);
+ if (ti) {
+ booked_tt = GWEN_Time_toTime_t(ti);
+ } else {
+ /* No time found? Use today because the HBCI query asked for today's
+ * balance. */
+ booked_tt = gnc_timet_get_day_start(time(NULL));
+ }
+ booked_val = AB_Balance_GetValue(booked_bal);
+ if (booked_val) {
+ booked_value = AB_Value_GetValueAsDouble(booked_val);
+ } else {
+ g_warning("bal_accountinfo_cb: booked_val == NULL. Assuming 0");
+ booked_value = 0.0;
+ }
+ } else {
+ g_warning("bal_accountinfo_cb: booked_bal == NULL. Assuming 0");
+ booked_tt = 0;
+ booked_value = 0.0;
+ }
+
+ /* Lookup noted balance */
+ noted_bal = AB_AccountStatus_GetNotedBalance(best);
+ if (noted_bal) {
+ noted_val = AB_Balance_GetValue(noted_bal);
+ if (noted_val)
+ noted_value = AB_Value_GetValueAsDouble(noted_val);
+ else {
+ g_warning("bal_accountinfo_cb: noted_val == NULL. Assuming 0");
+ noted_value = 0.0;
+ }
+ } else {
+ g_warning("bal_accountinfo_cb: noted_bal == NULL. Assuming 0");
+ noted_value = 0.0;
+ }
+
+ value = double_to_gnc_numeric(booked_value,
+ xaccAccountGetCommoditySCU(gnc_acc),
+ GNC_RND_ROUND);
+ if (noted_value == 0.0 && booked_value == 0.0) {
+ dialog = gtk_message_dialog_new(
+ GTK_WINDOW(data->parent),
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_INFO,
+ GTK_BUTTONS_OK,
+ "%s",
+ /* Translators: Strings from this file are needed only in
+ * countries that have one of aqbanking's Online Banking
+ * techniques available. This is 'OFX DirectConnect'
+ * (U.S. and others), 'HBCI' (in Germany), or 'YellowNet'
+ * (Switzerland). If none of these techniques are available
+ * in your country, you may safely ignore strings from the
+ * import-export/hbci subdirectory. */
+ _("The downloaded Online Banking Balance was zero.\n\n"
+ "Either this is the correct balance, or your bank does not "
+ "support Balance download in this Online Banking version. "
+ "In the latter case you should choose a different "
+ "Online Banking version number in the Online Banking "
+ "(AqBanking or HBCI) Setup. After that, try again to "
+ "download the Online Banking Balance."));
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+
+ } else {
+ gnc_numeric reconc_balance = xaccAccountGetReconciledBalance(gnc_acc);
+
+ gchar *booked_str = gnc_AB_VALUE_to_readable_string(booked_val);
+ gchar *message1 = g_strdup_printf(
+ _("Result of Online Banking job: \n"
+ "Account booked balance is %s"),
+ booked_str);
+ gchar *message2 =
+ (noted_value == 0.0) ?
+ g_strdup("") :
+ g_strdup_printf(_("For your information: This account also "
+ "has a noted balance of %s\n"),
+ gnc_AB_VALUE_to_readable_string(noted_val));
+
+ if (gnc_numeric_equal(value, reconc_balance)) {
+ const gchar *message3 =
+ _("The booked balance is identical to the current "
+ "reconciled balance of the account.");
+ dialog = gtk_message_dialog_new(
+ GTK_WINDOW(data->parent),
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_INFO,
+ GTK_BUTTONS_OK,
+ "%s\n%s\n%s",
+ message1, message2, message3);
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(GTK_WIDGET(dialog));
+
+ } else {
+ const char *message3 = _("Reconcile account now?");
+
+ show_recn_window = gnc_verify_dialog(data->parent,TRUE, "%s\n%s\n%s",
+ message1, message2, message3);
+ }
+ g_free(booked_str);
+ g_free(message1);
+ g_free(message2);
+ }
+
+ /* Show reconciliation window */
+ if (show_recn_window)
+ recnWindowWithBalance(data->parent, gnc_acc, value, booked_tt);
+
+ return NULL;
}
+
+GncABImExContextImport *
+gnc_ab_import_context(AB_IMEXPORTER_CONTEXT *context,
+ guint awaiting, gboolean execute_txns,
+ AB_BANKING *api, GtkWidget *parent)
+{
+ GncABImExContextImport *data = g_new(GncABImExContextImport, 1);
+
+ g_return_val_if_fail(context, NULL);
+ /* Do not await and ignore at the same time */
+ g_return_val_if_fail(!(awaiting & AWAIT_BALANCES)
+ || !(awaiting & IGNORE_BALANCES),
+ NULL);
+ g_return_val_if_fail(!(awaiting & AWAIT_TRANSACTIONS)
+ || !(awaiting & IGNORE_TRANSACTIONS),
+ NULL);
+ /* execute_txns must be FALSE if txns are not awaited */
+ g_return_val_if_fail(awaiting & AWAIT_TRANSACTIONS || !execute_txns, NULL);
+ /* An api is needed for the jobs */
+ g_return_val_if_fail(!execute_txns || api, NULL);
+
+ data->awaiting = awaiting;
+ data->txn_found = FALSE;
+ data->execute_txns = execute_txns;
+ data->api = api;
+ data->parent = parent;
+ data->job_list = NULL;
+ data->generic_importer = NULL;
+
+ /* Import transactions */
+ if (!(awaiting & IGNORE_TRANSACTIONS))
+ AB_ImExporterContext_AccountInfoForEach(context, txn_accountinfo_cb,
+ data);
+
+ /* Check balances */
+ if (!(awaiting & IGNORE_BALANCES))
+ AB_ImExporterContext_AccountInfoForEach(context, bal_accountinfo_cb,
+ data);
+
+ return data;
+}
+
+guint
+gnc_ab_ieci_get_found(GncABImExContextImport *ieci)
+{
+ g_return_val_if_fail(ieci, 0);
+
+ return ieci->awaiting;
+}
+
+AB_JOB_LIST2 *
+gnc_ab_ieci_get_job_list(GncABImExContextImport *ieci)
+{
+ g_return_val_if_fail(ieci, NULL);
+
+ return ieci->job_list;
+}
+
+gboolean
+gnc_ab_ieci_run_matcher(GncABImExContextImport *ieci)
+{
+ g_return_val_if_fail(ieci, FALSE);
+
+ return gnc_gen_trans_list_run(ieci->generic_importer);
+}
Index: src/import-export/aqbanking/gnc-ab-utils.h
===================================================================
--- src/import-export/aqbanking/gnc-ab-utils.h (Revision 17346)
+++ src/import-export/aqbanking/gnc-ab-utils.h (Revision 17347)
@@ -34,6 +34,7 @@
#define GNC_AB_UTILS_H
#include <glib.h>
+#include <gtk/gtk.h>
#include <aqbanking/banking.h>
#include "Account.h"
@@ -45,6 +46,15 @@
#define KEY_FORMAT_SWIFT942 "format_swift_mt942"
#define KEY_FORMAT_DTAUS "format_dtaus"
+typedef struct _GncABImExContextImport GncABImExContextImport;
+
+#define AWAIT_BALANCES 1 << 1
+#define FOUND_BALANCES 1 << 2
+#define IGNORE_BALANCES 1 << 3
+#define AWAIT_TRANSACTIONS 1 << 4
+#define FOUND_TRANSACTIONS 1 << 5
+#define IGNORE_TRANSACTIONS 1 << 6
+
/**
* Initialize the gwenhywfar library by calling GWEN_Init() and setting up
* gwenhywfar logging.
@@ -156,16 +166,58 @@
Transaction *gnc_ab_trans_to_gnc(const AB_TRANSACTION *ab_trans, Account *gnc_acc);
/**
- * Lookup the most recent ACCOUNT_STATUS available in an ACCOUNTINFO as
- * extracted from an IMEXPORTER_CONTEXT. This can be used to determine the
- * reported account balance most up-to-date.
+ * Import balances and transactions found in a AB_IMEXPORTER_CONTEXT into
+ * GnuCash. By using @a awaiting the caller can specify what the user will
+ * expect to receive. By using @a execute_txns, transactions in @a context can
+ * be used to generate corresponding AqBanking jobs, e.g. after a file import.
*
- * @param acc_info ACCOUNTINFO
- * @return An AB_ACCOUNT_STATUS internal to @a acc_info, or NULL otherwise
+ * @param context AB_IMEXPORTER_CONTEXT to import
+ *
+ * @param awaiting Information the caller expects to receive or wants to ignore,
+ * bitmask of AWAIT_* or IGNORE_* values
+ *
+ * @param execute_txns If @a awaiting contains AWAIT_TRANSACTIONS, whether to
+ * create an aqbanking job for each of the transactions found
+ *
+ * @param api If @a execute_txns is TRUE, the AB_BANKING to get
+ * AB_ACCOUNTs from
+ *
+ * @param parent Widget to set new dialogs transient for, may be NULL
+ *
+ * @return A new GncABImExContextImport object which must be freed with
+ * g_free(), or NULL otherwise. If execute_txns is TRUE, additionally
+ * gnc_ab_ieci_get_job_list() must be called and the result freed with
+ * AB_Job_List2_FreeAll()
*/
-AB_ACCOUNT_STATUS *gnc_ab_get_best_accountstatus(
- AB_IMEXPORTER_ACCOUNTINFO *acc_info);
+GncABImExContextImport *gnc_ab_import_context(
+ AB_IMEXPORTER_CONTEXT *context, guint awaiting, gboolean execute_txns,
+ AB_BANKING *api, GtkWidget *parent);
+/**
+ * Extract awaiting from @a data.
+ *
+ * @param ieci The return value of gnc_ab_import_context()
+ * @return The initial awaiting bitmask plus IGNORE_* for unexpected and then
+ * ignored items, and FOUND_* for non-empty items
+ */
+guint gnc_ab_ieci_get_found(GncABImExContextImport *ieci);
+
+/**
+ * Extract the job list from @a data.
+ *
+ * @param ieci The return value of gnc_ab_import_context()
+ * @return The list of jobs, freeable with AB_Job_List2_FreeAll()
+ */
+AB_JOB_LIST2 *gnc_ab_ieci_get_job_list(GncABImExContextImport *ieci);
+
+/**
+ * Run the generic transaction matcher dialog.
+ *
+ * @param ieci The return value of gnc_ab_import_context()
+ * @return The return value of gnc_gen_trans_list_run().
+ */
+gboolean gnc_ab_ieci_run_matcher(GncABImExContextImport *ieci);
+
G_END_DECLS
/** @} */
Index: src/import-export/aqbanking/gnc-file-aqb-import.c
===================================================================
--- src/import-export/aqbanking/gnc-file-aqb-import.c (Revision 17346)
+++ src/import-export/aqbanking/gnc-file-aqb-import.c (Revision 17347)
@@ -53,143 +53,6 @@
/* This static indicates the debugging module that this .o belongs to. */
static QofLogModule log_module = GNC_MOD_IMPORT;
-typedef struct _ImportData ImportData;
-
-static const AB_TRANSACTION *transaction_cb(
- const AB_TRANSACTION *element, gpointer user_data);
-static AB_IMEXPORTER_ACCOUNTINFO *accountinfo_cb(
- AB_IMEXPORTER_ACCOUNTINFO *element, gpointer user_data);
-static AB_JOB_LIST2 *import_context(
- AB_BANKING *api, AB_IMEXPORTER_CONTEXT *context,
- GNCImportMainMatcher *importer_generic_gui, gboolean execute_transactions);
-
-struct _ImportData {
- AB_BANKING *api;
- GNCImportMainMatcher *importer_generic;
- gboolean execute_transactions;
- AB_JOB_LIST2 *job_list;
- Account *gnc_acc;
- AB_ACCOUNT *ab_acc;
-};
-
-static const AB_TRANSACTION *
-transaction_cb(const AB_TRANSACTION *element, gpointer user_data)
-{
- ImportData *data = user_data;
- Transaction *gnc_trans;
- AB_JOB *job;
-
- g_return_val_if_fail(element && data, NULL);
-
- /* Create a GnuCash transaction from ab_trans */
- gnc_trans = gnc_ab_trans_to_gnc(element, data->gnc_acc);
-
- /* Instead of xaccTransCommitEdit(gnc_trans) */
- gnc_gen_trans_list_add_trans(data->importer_generic, gnc_trans);
-
- if (data->ab_acc) {
- AB_TRANSACTION *ab_trans = AB_Transaction_dup(element);
-
- /* NEW: The imported transaction has been imported into gnucash.
- * Now also add it as a job to aqbanking */
- AB_Transaction_SetLocalBankCode(
- ab_trans, AB_Account_GetBankCode(data->ab_acc));
- AB_Transaction_SetLocalAccountNumber(
- ab_trans, AB_Account_GetAccountNumber(data->ab_acc));
- AB_Transaction_SetLocalCountry(ab_trans, "DE");
-
- job = gnc_ab_get_trans_job(data->ab_acc, ab_trans, SINGLE_DEBITNOTE);
-
- /* Check whether we really got a job */
- if (!job) {
- /* Oops, no job, probably not supported by bank */
- if (gnc_verify_dialog(
- NULL, FALSE, "%s",
- _("The backend found an error during the preparation "
- "of the job. It is not possible to execute this job. \n"
- "\n"
- "Most probable the bank does not support your chosen "
- "job or your Online Banking account does not have the permission "
- "to execute this job. More error messages might be "
- "visible on your console log.\n"
- "\n"
- "Do you want to enter the job again?"))) {
- gnc_error_dialog(NULL, "Sorry, not implemented yet.");
- }
- /* else */
- }
- AB_Job_List2_PushBack(data->job_list, job);
-
- AB_Transaction_free(ab_trans);
- }
-
- return NULL;
-}
-
-static AB_IMEXPORTER_ACCOUNTINFO *
-accountinfo_cb(AB_IMEXPORTER_ACCOUNTINFO *element, gpointer user_data)
-{
- Account *gnc_acc;
- ImportData *data = user_data;
- const gchar *bank_code =
- AB_ImExporterAccountInfo_GetBankCode(element);
- const gchar *account_number =
- AB_ImExporterAccountInfo_GetAccountNumber(element);
- const gchar *account_name =
- AB_ImExporterAccountInfo_GetAccountName(element);
- gchar *online_id;
-
- g_return_val_if_fail(element && data, NULL);
-
- online_id = g_strconcat(bank_code, account_number, (gchar*)NULL);
- gnc_acc = gnc_import_select_account(NULL, online_id, 1, account_name, NULL,
- ACCT_TYPE_NONE, NULL, NULL);
- g_free(online_id);
-
- if (gnc_acc) {
- /* Store chosen gnucash account in callback data */
- data->gnc_acc = gnc_acc;
-
- if (data->execute_transactions) {
- /* Retrieve the aqbanking account that belongs to this gnucash
- * account */
- data->ab_acc = gnc_ab_get_ab_account(data->api, gnc_acc);
- if (!data->ab_acc) {
- gnc_error_dialog(NULL, "%s",
- _("No Online Banking account found for this "
- "gnucash account. These transactions will "
- "not be executed by Online Banking."));
- }
- } else {
- data->ab_acc = NULL;
- }
-
- /* Iterate through all transactions. */
- AB_ImExporterAccountInfo_TransactionsForEach(element, transaction_cb,
- data);
- }
- return NULL;
-}
-
-static AB_JOB_LIST2 *
-import_context(AB_BANKING *api, AB_IMEXPORTER_CONTEXT *context,
- GNCImportMainMatcher *importer_generic_gui,
- gboolean execute_transactions)
-{
- ImportData data;
-
- g_return_val_if_fail(api && context && importer_generic_gui, NULL);
- data.api = api;
- data.importer_generic = importer_generic_gui;
- data.execute_transactions = execute_transactions;
- data.job_list = NULL;
-
- /* Iterate through all accounts */
- AB_ImExporterContext_AccountInfoForEach(context, accountinfo_cb, &data);
-
- return data.job_list;
-}
-
void
gnc_file_aqbanking_import(const gchar *aqbanking_importername,
const gchar *aqbanking_profilename,
@@ -206,7 +69,7 @@
GWEN_DB_NODE *db_profile;
AB_IMEXPORTER_CONTEXT *context = NULL;
GWEN_IO_LAYER *io, *buffio;
- GNCImportMainMatcher *importer_generic_gui = NULL;
+ GncABImExContextImport *ieci = NULL;
AB_JOB_LIST2 *job_list = NULL;
/* Select a file */
@@ -308,15 +171,17 @@
/* Close the file */
GWEN_Io_Layer_free(buffio);
- /* Create importer GUI */
- importer_generic_gui = gnc_gen_trans_list_new(NULL, NULL, TRUE, 14);
+ /* Import the results */
+ ieci = gnc_ab_import_context(context, AWAIT_TRANSACTIONS,
+ execute_transactions,
+ execute_transactions ? api : NULL,
+ NULL);
- /* Import the transactions from the context into gnucash */
- job_list = import_context(api, context, importer_generic_gui,
- execute_transactions);
+ /* Extract the list of jobs */
+ job_list = gnc_ab_ieci_get_job_list(ieci);
if (execute_transactions) {
- if (gnc_gen_trans_list_run(importer_generic_gui)) {
+ if (gnc_ab_ieci_run_matcher(ieci)) {
/* FIXME */
/* gnc_hbci_multijob_execute(NULL, api, job_list, gui); */
}
@@ -324,9 +189,9 @@
cleanup:
if (job_list)
- AB_Job_List2_free(job_list);
- if (importer_generic_gui)
- gnc_gen_trans_list_delete(importer_generic_gui);
+ AB_Job_List2_FreeAll(job_list);
+ if (ieci)
+ g_free(ieci);
if (context)
AB_ImExporterContext_free(context);
if (db_profiles)
--- End Message ---