Merge branches/aqbanking3 (r17287) into trunk.

Port the HBCI import-export module to AqBanking3.  Depending on the aqbanking
version found, either the classic hbci/ module or the new, very similar, module
aqbanking3/ for AqBanking >= 3 is built and installed.  The influence on the
rest of the code is minimal.

BP


git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@17288 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Andreas Köhler
2008-07-08 20:35:50 +00:00
parent 2e7af494c3
commit fe11af9045
36 changed files with 9985 additions and 28 deletions

View File

@@ -831,38 +831,46 @@ AC_SUBST(OFX_DIR)
### --------------------------------------------------------------------------
### MT940
AC_ARG_ENABLE( mt940,
[ --enable-mt940 Obsolete, included in --enable-hbci],
[ --enable-mt940 obsolete, included in --enable-aqbanking],
if test "x$enableval" != "xno" ; then
AC_MSG_ERROR([--enable-mt940 is obsolete -- all functionality is already included in --enable-hbci])
AC_MSG_ERROR([--enable-mt940 is obsolete -- all functionality is already included in --enable-aqbanking])
fi)
### --------------------------------------------------------------------------
### HBCI
AC_ARG_ENABLE( hbci,
[ --enable-hbci compile with HBCI support (needs AqBanking)],
### AqBanking
AC_ARG_ENABLE( aqbanking,
[ --enable-aqbanking compile with AqBanking support],
if test "x$enableval" != "xno" ; then
HBCI_DIR=hbci
want_aqbanking=yes
fi)
if test x${HBCI_DIR} = xhbci ;
AC_ARG_ENABLE( hbci,
[ --enable-hbci an alias for --enable-aqbanking],
if test "x$enableval" != "xno" ; then
want_aqbanking=yes
fi)
if test x${want_aqbanking} = xyes ;
then
# Check for Aqbanking library
# aqbanking-1.6.1 was released on 2005-11-04; aqbanking ships with
# a pkg-config file since 1.6.1.
PKG_CHECK_MODULES(HBCI, aqbanking >= 1.6.1 aqbanking < 2.9.0 gwenhywfar, [], [
AC_MSG_ERROR([Could not find aqbanking > 1.6.0 and < 2.9.0. If you use --enable-hbci, you *have* to have aqbanking installed. Note that gnucash requires aqbanking2 and not (yet) aqbanking3!])
# Check for Aqbanking library
# aqbanking-1.6.1 was released on 2005-11-04; aqbanking ships with
# a pkg-config file since 1.6.1.
PKG_CHECK_MODULES(AQBANKING, aqbanking >= 3.0.0 gwenhywfar, [AQBANKING_DIR=aqbanking], [
PKG_CHECK_MODULES(AQBANKING, aqbanking >= 1.6.1 aqbanking < 2.9.0 gwenhywfar, [AQBANKING_DIR=hbci], [
AC_MSG_ERROR([Could not find aqbanking > 1.6.0. If you use --enable-aqbanking or --enable-hbci, you *have* to have aqbanking installed!])
])
])
# also check for ktoblzcheck
AC_CHECK_HEADERS(ktoblzcheck.h)
if test "x$ac_cv_header_ktoblzcheck_h" != xno; then
HBCI_LIBS="${HBCI_LIBS} -lktoblzcheck"
fi
# also check for ktoblzcheck
AC_CHECK_HEADERS(ktoblzcheck.h)
if test "x$ac_cv_header_ktoblzcheck_h" != xno; then
AQBANKING_LIBS="${AQBANKING_LIBS} -lktoblzcheck"
fi
AS_SCRUB_INCLUDE(HBCI_CFLAGS)
AC_SUBST(HBCI_LIBS)
AC_SUBST(HBCI_CFLAGS)
AS_SCRUB_INCLUDE(AQBANKING_CFLAGS)
AC_SUBST(AQBANKING_LIBS)
AC_SUBST(AQBANKING_CFLAGS)
fi
AC_SUBST(HBCI_DIR)
AC_SUBST(AQBANKING_DIR)
### --------------------------------------------------------------------------
### i18n
@@ -1537,6 +1545,8 @@ AC_CONFIG_FILES(po/Makefile.in
src/import-export/ofx/test/Makefile
src/import-export/csv/Makefile
src/import-export/log-replay/Makefile
src/import-export/aqbanking/Makefile
src/import-export/aqbanking/schemas/Makefile
src/import-export/hbci/Makefile
src/import-export/hbci/glade/Makefile
src/import-export/hbci/schemas/Makefile
@@ -1606,8 +1616,8 @@ fi
if test x${OFX_DIR} != x; then
components="$components ofx"
fi
if test x${HBCI_DIR} != x; then
components="$components hbci"
if test x${AQBANKING_DIR} != x; then
components="$components $AQBANKING_DIR"
fi
if test x${PYTHON_DIR} != x; then
components="$components python-bindings"

View File

@@ -1,4 +1,3 @@
:20:STARTUMS
:25:80007777/2602272001
:28C:0

View File

@@ -101,6 +101,9 @@
</xsl:choose>
</xsl:variable>
<xsl:variable name="branches">
<branch>
<prefix>gnucash/branches/aqbanking3</prefix>
</branch>
<branch>
<prefix>gnucash/branches/csv-import</prefix>
</branch>

View File

@@ -340,6 +340,7 @@ load_gnucash_modules()
{ "gnucash/import-export/ofx", 0, TRUE },
{ "gnucash/import-export/csv", 0, TRUE },
{ "gnucash/import-export/log-replay", 0, TRUE },
{ "gnucash/import-export/aqbanking", 0, TRUE },
{ "gnucash/import-export/hbci", 0, TRUE },
{ "gnucash/report/report-system", 0, FALSE },
{ "gnucash/report/stylesheets", 0, FALSE },

View File

@@ -1,7 +1,7 @@
SUBDIRS = . schemas qif qif-import \
${OFX_DIR} ${HBCI_DIR} log-replay test csv
${OFX_DIR} ${AQBANKING_DIR} log-replay test csv
DIST_SUBDIRS = schemas qif qif-import qif-io-core \
ofx hbci log-replay test csv
ofx aqbanking hbci log-replay test csv
pkglib_LTLIBRARIES=libgncmod-generic-import.la

View File

@@ -0,0 +1,78 @@
SUBDIRS = . schemas
pkglib_LTLIBRARIES = libgncmod-aqbanking.la
libgncmod_aqbanking_la_SOURCES = \
dialog-ab-trans.c \
dialog-daterange.c \
druid-ab-initial.c \
gnc-ab-getbalance.c \
gnc-ab-gettrans.c \
gnc-ab-kvp.c \
gnc-ab-trans-templ.c \
gnc-ab-transfer.c \
gnc-ab-utils.c \
gnc-file-aqb-import.c \
gnc-gwen-gui.c \
gnc-plugin-aqbanking.c \
gncmod-aqbanking.c
noinst_HEADERS = \
dialog-ab-trans.h \
dialog-daterange.h \
druid-ab-initial.h \
gnc-ab-getbalance.h \
gnc-ab-gettrans.h \
gnc-ab-kvp.h \
gnc-ab-trans-templ.h \
gnc-ab-transfer.h \
gnc-ab-utils.h \
gnc-file-aqb-import.h \
gnc-gwen-gui.h \
gnc-plugin-aqbanking.h
libgncmod_aqbanking_la_LDFLAGS = -avoid-version
libgncmod_aqbanking_la_LIBADD = \
${top_builddir}/src/import-export/libgncmod-generic-import.la \
${top_builddir}/src/gnome/libgnc-gnome.la \
${top_builddir}/src/gnome-utils/libgncmod-gnome-utils.la \
${top_builddir}/src/app-utils/libgncmod-app-utils.la \
${top_builddir}/src/engine/libgncmod-engine.la \
${top_builddir}/src/core-utils/libgnc-core-utils.la \
${top_builddir}/src/gnc-module/libgnc-module.la \
${GNOME_LIBS} \
${GLADE_LIBS} \
${QOF_LIBS} \
${GLIB_LIBS} \
${AQBANKING_LIBS}
AM_CFLAGS = \
-I${top_srcdir}/src \
-I${top_srcdir}/src/import-export \
-I${top_srcdir}/src/gnome \
-I${top_srcdir}/src/register/ledger-core \
-I${top_srcdir}/src/register/register-gnome \
-I${top_srcdir}/src/register/register-core \
-I${top_srcdir}/src/gnome-utils \
-I${top_srcdir}/src/app-utils \
-I${top_srcdir}/src/engine \
-I${top_srcdir}/src/core-utils \
-I${top_srcdir}/src/gnc-module \
${GNOME_CFLAGS} \
${GLADE_CFLAGS} \
${QOF_CFLAGS} \
${GLIB_CFLAGS} \
${AQBANKING_CFLAGS}
uidir = $(GNC_UI_DIR)
ui_DATA = \
gnc-plugin-aqbanking-ui.xml
gladedir = $(GNC_GLADE_DIR)
glade_DATA = \
aqbanking.glade
EXTRA_DIST = ${ui_DATA} ${glade_DATA}
INCLUDES = -DG_LOG_DOMAIN=\"gnc.import.aqbanking\"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,143 @@
/*
* dialog-ab-trans.h --
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact:
*
* Free Software Foundation Voice: +1-617-542-5942
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
* Boston, MA 02110-1301, USA gnu@gnu.org
*/
/**
* @addtogroup Import_Export
* @{
* @addtogroup AqBanking
* @{
* @file dialog-ab-trans.h
* @brief Dialog for AqBanking transaction data
* @author Copyright (C) 2002 Christian Stimming <stimming@tuhh.de>
* @author Copyright (C) 2004 Bernd Wagner
* @author Copyright (C) 2006 David Hampton <hampton@employees.org>
* @author Copyright (C) 2008 Andreas Koehler <andi5.py@gmx.net>
*/
#ifndef DIALOG_AB_TRANS_H
#define DIALOG_AB_TRANS_H
#include <gtk/gtk.h>
#include <aqbanking/banking.h>
#include "Account.h"
G_BEGIN_DECLS
#define GNC_RESPONSE_NOW GTK_RESPONSE_YES
#define GNC_RESPONSE_LATER GTK_RESPONSE_NO
typedef struct _GncABTransDialog GncABTransDialog;
typedef enum _GncABTransType GncABTransType;
enum _GncABTransType {
SINGLE_TRANSFER = 0,
SINGLE_DEBITNOTE,
SINGLE_INTERNAL_TRANSFER
};
/**
* FIXME
*
* @param parent Widget to use as parent, may be NULL
* @param ab_acc FIXME
* @param commodity_scu FIXME
* @param trans_type Type of transaction
* @param templates A GList of template transactions which will become fully
* managed by the dialog, so do not free it and retrieve snapshots via
* gnc_ab_trans_dialog_get_templ()
* @return FIXME
*/
GncABTransDialog *gnc_ab_trans_dialog_new(GtkWidget *parent, AB_ACCOUNT *ab_acc,
gint commodity_scu,
GncABTransType trans_type,
GList *templates);
/**
* FIXME
*
* @param td Transaction dialog
* @param ab_acc AqBanking account
* @return FIXME
*/
gint gnc_ab_trans_dialog_run_until_ok(GncABTransDialog *td);
/**
* FIXME
*
* @param td Transaction dialog
*/
void gnc_ab_trans_dialog_free(GncABTransDialog *td);
/**
* Retrieve the current list of transaction templates from the dialog @a
* td, unless @a changed is a specified location and the templates have
* not been touched by the user.
*
* @param td Transaction dialog
* @param changed Location to store whether the templates have been
* changed, may be NULL
* @return The a newly allocated list of the internal transaction
* templates. Free this one via g_list_free().
*/
GList *gnc_ab_trans_dialog_get_templ(const GncABTransDialog *td,
gboolean *changed);
/**
* Retrieve the widget used as parent.
*
* @param td Transaction dialog
* @return The parent
*/
GtkWidget *gnc_ab_trans_dialog_get_parent(const GncABTransDialog *td);
/**
* FIXME
*
* @param td Transaction dialog
* @return FIXME
*/
const AB_TRANSACTION *gnc_ab_trans_dialog_get_ab_trans(
const GncABTransDialog *td);
/**
* FIXME
*
* @param td Transaction dialog
* @return FIXME
*/
AB_JOB *gnc_ab_trans_dialog_get_job(const GncABTransDialog *td);
/**
* FIXME
*
* @param td Transaction dialog
* @return FIXME
*/
AB_JOB *gnc_ab_get_trans_job(AB_ACCOUNT *ab_acc, const AB_TRANSACTION *ab_trans,
GncABTransType trans_type);
G_END_DECLS
/** @} */
/** @} */
#endif /* DIALOG_AB_TRANS_H */

View File

@@ -0,0 +1,148 @@
/*
* dialog-daterange.c --
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact:
*
* Free Software Foundation Voice: +1-617-542-5942
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
* Boston, MA 02110-1301, USA gnu@gnu.org
*/
/**
* @internal
* @file dialog-daterange.c
* @brief Dialog for date range entry
* @author Copyright (C) 2002 Christian Stimming <stimming@tuhh.de>
* @author Copyright (C) 2008 Andreas Koehler <andi5.py@gmx.net>
*/
#include "config.h"
#include "dialog-daterange.h"
#include "dialog-utils.h"
#include "gnc-date-edit.h"
/* This static indicates the debugging module that this .o belongs to. */
static QofLogModule log_module = G_LOG_DOMAIN;
typedef struct _DaterangeInfo DaterangeInfo;
void ddr_toggled_cb(GtkToggleButton *button, gpointer user_data);
struct _DaterangeInfo
{
GtkWidget *enter_from_button;
GtkWidget *enter_to_button;
GtkWidget *from_dateedit;
GtkWidget *to_dateedit;
};
gboolean
gnc_ab_enter_daterange(GtkWidget *parent,
const char *heading,
Timespec *from_date,
gboolean *last_retv_date,
gboolean *first_possible_date,
Timespec *to_date,
gboolean *to_now)
{
GladeXML *xml;
GtkWidget *dialog;
GtkWidget *heading_label;
GtkWidget *first_button;
GtkWidget *last_retrieval_button;
GtkWidget *now_button;
DaterangeInfo info;
gint result;
xml = gnc_glade_xml_new("aqbanking.glade", "Date Range Dialog");
dialog = glade_xml_get_widget(xml, "Date Range Dialog");
g_object_set_data_full(G_OBJECT(dialog), "xml", xml, g_object_unref);
glade_xml_signal_autoconnect_full(xml, gnc_glade_autoconnect_full_func,
&info);
if (parent)
gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(parent));
heading_label = glade_xml_get_widget(xml, "heading_label");
first_button = glade_xml_get_widget(xml, "first_button");
last_retrieval_button = glade_xml_get_widget(xml, "last_retrieval_button");
info.enter_from_button = glade_xml_get_widget(xml, "enter_from_button");
now_button = glade_xml_get_widget(xml, "now_button");
info.enter_to_button = glade_xml_get_widget(xml, "enter_to_button");
info.from_dateedit = gnc_date_edit_new_ts(*from_date, FALSE, FALSE);
gtk_container_add(GTK_CONTAINER(glade_xml_get_widget(xml, "enter_from_box")),
info.from_dateedit);
gtk_widget_show(info.from_dateedit);
info.to_dateedit = gnc_date_edit_new_ts(*to_date, FALSE, FALSE);
gtk_container_add(GTK_CONTAINER(glade_xml_get_widget(xml, "enter_to_box")),
info.to_dateedit);
gtk_widget_show(info.to_dateedit);
if (*last_retv_date) {
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(last_retrieval_button),
TRUE);
} else {
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(first_button), TRUE);
gtk_widget_set_sensitive(last_retrieval_button, FALSE);
}
gtk_widget_set_sensitive(info.from_dateedit, FALSE);
gtk_widget_set_sensitive(info.to_dateedit, FALSE);
gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);
if (heading)
gtk_label_set_text(GTK_LABEL(heading_label), heading);
gtk_widget_show(dialog);
result = gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_hide(dialog);
if (result == GTK_RESPONSE_OK) {
*from_date = gnc_date_edit_get_date_ts(
GNC_DATE_EDIT(info.from_dateedit));
*last_retv_date = gtk_toggle_button_get_active(
GTK_TOGGLE_BUTTON(last_retrieval_button));
*first_possible_date = gtk_toggle_button_get_active(
GTK_TOGGLE_BUTTON(first_button));
*to_date = gnc_date_edit_get_date_ts(
GNC_DATE_EDIT(info.to_dateedit));
*to_now = gtk_toggle_button_get_active(
GTK_TOGGLE_BUTTON(now_button));
}
gtk_widget_destroy(dialog);
return result == GTK_RESPONSE_OK;
}
void
ddr_toggled_cb(GtkToggleButton *button, gpointer user_data)
{
DaterangeInfo *info = user_data;
g_return_if_fail(info);
gtk_widget_set_sensitive(info->from_dateedit,
gtk_toggle_button_get_active(
GTK_TOGGLE_BUTTON(info->enter_from_button)));
gtk_widget_set_sensitive(info->to_dateedit,
gtk_toggle_button_get_active(
GTK_TOGGLE_BUTTON(info->enter_to_button)));
}

View File

@@ -0,0 +1,67 @@
/*
* dialog-daterange.h --
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact:
*
* Free Software Foundation Voice: +1-617-542-5942
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
* Boston, MA 02110-1301, USA gnu@gnu.org
*/
/**
* @addtogroup Import_Export
* @{
* @addtogroup AqBanking
* @{
* @file dialog-daterange.h
* @brief Dialog for date range entry
* @author Copyright (C) 2002 Christian Stimming <stimming@tuhh.de>
* @author Copyright (C) 2008 Andreas Koehler <andi5.py@gmx.net>
*/
#ifndef DIALOG_DATERANGE_H
#define DIALOG_DATERANGE_H
#include <gtk/gtk.h>
#include "qof.h"
G_BEGIN_DECLS
/**
* Show a dialog to pick a time frame using a sensible set of default options.
*
* @param parent Widget to use as parent, may be NULL
* @param heading Descriptive text showed at the top, may be NULL
* @param from_date Location to read from the initial and write to the final
* value of the from date entry
* @param last_retv_date Location to read from whether the caller knows the last
* retrieval date and write to whether the corresponding button has been chosen
* @param first_possible_date Location to write to whether the earliest possible
* date button has been chosen
* @param to_date Location to read from the initial and write to the final value
* of the to date entry
* @param to_now Location to write to whether the to now button has been chosen
*/
gboolean gnc_ab_enter_daterange(GtkWidget *parent,
const char *heading,
Timespec *from_date,
gboolean *last_retv_date,
gboolean *first_possible_date,
Timespec *to_date,
gboolean *to_now);
G_END_DECLS
#endif /* DIALOG_DATERANGE_H */

View File

@@ -0,0 +1,776 @@
/*
* druid-ab-initial.c --
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact:
*
* Free Software Foundation Voice: +1-617-542-5942
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
* Boston, MA 02110-1301, USA gnu@gnu.org
*/
/**
* @internal
* @file druid-ab-initial.c
* @brief AqBanking setup functionality
* @author Copyright (C) 2002 Christian Stimming <stimming@tuhh.de>
* @author Copyright (C) 2006 David Hampton <hampton@employees.org>
* @author Copyright (C) 2008 Andreas Koehler <andi5.py@gmx.net>
*/
#include "config.h"
#include <aqbanking/banking.h>
#include <glib.h>
#include <glib/gi18n.h>
#include <glib/gstdio.h>
#include <gdk/gdkkeysyms.h>
#include <fcntl.h>
#include <unistd.h>
#include "dialog-utils.h"
#include "druid-ab-initial.h"
#include "druid-utils.h"
#include "gnc-ab-kvp.h"
#include "gnc-ab-utils.h"
#include "gnc-component-manager.h"
#include "gnc-glib-utils.h"
#include "gnc-ui.h"
#include "gnc-ui-util.h"
#include "gnc-session.h"
#include "import-account-matcher.h"
/* This static indicates the debugging module that this .o belongs to. */
static QofLogModule log_module = G_LOG_DOMAIN;
#define DRUID_AB_INITIAL_CM_CLASS "druid-ab-initial"
typedef struct _ABInitialInfo ABInitialInfo;
typedef struct _DeferredInfo DeferredInfo;
typedef struct _AccCbData AccCbData;
typedef struct _RevLookupData RevLookupData;
gboolean dai_key_press_event_cb(GtkWidget *widget, GdkEventKey *event, gpointer user_data);
void dai_cancel_cb(GnomeDruid *druid, gpointer user_data);
void dai_destroy_cb(GtkObject *object, gpointer user_data);
void dai_wizard_page_prepare_cb(GnomeDruidPage *druid_page, GtkWidget *widget, gpointer user_data);
void dai_wizard_button_clicked_cb(GtkButton *button, gpointer user_data);
void dai_match_page_prepare_cb(GnomeDruidPage *druid_page, GtkWidget *widget, gpointer user_data);
void dai_finish_cb(GnomeDruidPage *druid_page, GtkWidget *widget, gpointer user_data);
static gboolean banking_has_accounts(AB_BANKING *banking);
static void hash_from_kvp_acc_cb(Account *gnc_acc, gpointer user_data);
static void druid_enable_next_button(ABInitialInfo *info);
static void druid_disable_next_button(ABInitialInfo *info);
static void child_exit_cb(GPid pid, gint status, gpointer data);
static gchar *ab_account_longname(const AB_ACCOUNT *ab_acc);
static AB_ACCOUNT *update_account_list_acc_cb(AB_ACCOUNT *ab_acc, gpointer user_data);
static void update_account_list(ABInitialInfo *info);
static gboolean find_gnc_acc_cb(gpointer key, gpointer value, gpointer user_data);
static gboolean clear_line_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer user_data);
static void account_list_changed_cb(GtkTreeSelection *selection, gpointer user_data);
static void clear_kvp_acc_cb(Account *gnc_acc, gpointer user_data);
static void save_kvp_acc_cb(gpointer key, gpointer value, gpointer user_data);
static void cm_close_handler(gpointer user_data);
struct _ABInitialInfo {
GtkWidget *window;
GtkWidget *druid;
/* account match page */
GtkTreeView *account_view;
GtkListStore *account_store;
/* managed by child_exit_cb */
DeferredInfo *deferred_info;
/* AqBanking stuff */
AB_BANKING *api;
/* AB_ACCOUNT* -> Account* -- DO NOT DELETE THE KEYS! */
GHashTable *gnc_hash;
};
struct _DeferredInfo {
ABInitialInfo *initial_info;
gchar *wizard_path;
gboolean qt_probably_unavailable;
};
struct _AccCbData {
AB_BANKING *api;
GHashTable *hash;
};
struct _RevLookupData {
Account *gnc_acc;
AB_ACCOUNT *ab_acc;
};
enum account_list_cols {
ACCOUNT_LIST_COL_INDEX = 0,
ACCOUNT_LIST_COL_AB_NAME,
ACCOUNT_LIST_COL_AB_ACCT,
ACCOUNT_LIST_COL_GNC_NAME,
ACCOUNT_LIST_COL_CHECKED,
NUM_ACCOUNT_LIST_COLS
};
gboolean
dai_key_press_event_cb(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
{
if (event->keyval == GDK_Escape) {
gtk_widget_destroy(widget);
return TRUE;
} else {
return FALSE;
}
}
void
dai_cancel_cb(GnomeDruid *druid, gpointer user_data)
{
ABInitialInfo *info = user_data;
gtk_widget_destroy(info->window);
}
void
dai_destroy_cb(GtkObject *object, gpointer user_data)
{
ABInitialInfo *info = user_data;
gnc_unregister_gui_component_by_data(DRUID_AB_INITIAL_CM_CLASS, info);
if (info->deferred_info) {
g_message("Online Banking druid is being closed but the wizard is still "
"running. Inoring.");
/* Tell child_exit_cb() that there is no druid anymore */
info->deferred_info->initial_info = NULL;
}
if (info->gnc_hash) {
AB_Banking_OnlineFini(info->api);
g_hash_table_destroy(info->gnc_hash);
info->gnc_hash = NULL;
}
if (info->api) {
gnc_AB_BANKING_delete(info->api);
info->api = NULL;
}
gtk_widget_destroy(info->window);
info->window = NULL;
g_free(info);
}
void
dai_wizard_page_prepare_cb(GnomeDruidPage *druid_page, GtkWidget *widget,
gpointer user_data)
{
ABInitialInfo *info = user_data;
g_return_if_fail(info->api);
if (banking_has_accounts(info->api))
druid_enable_next_button(info);
else
druid_disable_next_button(info);
}
void
dai_wizard_button_clicked_cb(GtkButton *button, gpointer user_data)
{
ABInitialInfo *info = user_data;
AB_BANKING *banking = info->api;
GWEN_BUFFER *buf;
gboolean wizard_exists;
const gchar *wizard_path;
gboolean qt_probably_unavailable = FALSE;
g_return_if_fail(banking);
ENTER("user_data: %p", user_data);
if (info->deferred_info) {
LEAVE("Wizard is still running");
return;
}
/* This is the point where we look for and start an external
* application shipped with aqbanking that contains the setup druid
* for AqBanking related stuff. It requires qt (but not kde). This
* application contains the very verbose step-by-step setup wizard
* for the AqBanking account, and the application is shared with
* other AqBanking-based financial managers that offer the AqBanking
* features (e.g. KMyMoney). See gnucash-devel discussion here
* https://lists.gnucash.org/pipermail/gnucash-devel/2004-December/012351.html
*/
buf = GWEN_Buffer_new(NULL, 300, 0, 0);
AB_Banking_FindWizard(banking, "", NULL, buf);
wizard_exists = *GWEN_Buffer_GetStart(buf) != 0;
wizard_path = GWEN_Buffer_GetStart(buf);
if (wizard_exists) {
/* Really check whether the file exists */
gint fd = g_open(wizard_path, O_RDONLY, 0);
if (fd == -1)
wizard_exists = FALSE;
else
close(fd);
}
#ifdef G_OS_WIN32
{
const char *check_file = "qtdemo.exe";
gchar *found_program = g_find_program_in_path(check_file);
if (found_program) {
g_debug("Yes, we found the Qt demo program in %s\n", found_program);
g_free(found_program);
} else {
g_warning("Ouch, no Qt demo program was found. Qt not installed?\n");
qt_probably_unavailable = TRUE;
}
}
#endif
druid_disable_next_button(info);
if (wizard_exists) {
/* Call the qt wizard. See the note above about why this
* approach is chosen. */
GPid pid;
GError *error = NULL;
gchar *argv[2];
gboolean spawned;
argv[0] = g_strdup (wizard_path);
argv[1] = NULL;
spawned = g_spawn_async (NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD,
NULL, NULL, &pid, &error);
g_free (argv[0]);
if (error)
g_critical(
"Error on starting AqBanking setup wizard: Code %d: %s",
error->code, error->message ? error->message : "(null)");
if (!spawned) {
g_critical("Could not start AqBanking setup wizard: %s",
error->message ? error->message : "(null)");
g_error_free (error);
} else {
/* Keep a reference to info that can survive info */
info->deferred_info = g_new0(DeferredInfo, 1);
info->deferred_info->initial_info = info;
info->deferred_info->wizard_path = g_strdup(wizard_path);
info->deferred_info->qt_probably_unavailable =
qt_probably_unavailable;
g_child_watch_add (pid, child_exit_cb, info->deferred_info);
}
} else {
g_warning("on_aqhbci_button: Oops, no aqhbci setup wizard found.");
gnc_error_dialog
(info->window,
_("The external program \"AqBanking Setup Wizard\" has not "
"been found. \n\n"
"The %s package should include the "
"program \"qt3-wizard\". Please check your installation to "
"ensure this program is present. On some distributions this "
"may require installing additional packages."),
QT3_WIZARD_PACKAGE);
druid_disable_next_button(info);
}
GWEN_Buffer_free(buf);
LEAVE(" ");
}
void
dai_match_page_prepare_cb(GnomeDruidPage *druid_page, GtkWidget *widget,
gpointer user_data)
{
ABInitialInfo *info = user_data;
Account *root;
AccCbData data;
g_return_if_fail(info && info->api);
/* No way back */
gnome_druid_set_buttons_sensitive(GNOME_DRUID(info->druid),
FALSE, TRUE, TRUE, TRUE);
/* Load aqbanking accounts */
AB_Banking_OnlineInit(info->api);
/* Determine current mapping */
root = gnc_book_get_root_account(gnc_get_current_book());
info->gnc_hash = g_hash_table_new(&g_direct_hash, &g_direct_equal);
data.api = info->api;
data.hash = info->gnc_hash;
gnc_account_foreach_descendant(
root, (AccountCb) hash_from_kvp_acc_cb, &data);
/* Update the graphical representation */
update_account_list(info);
}
void
dai_finish_cb(GnomeDruidPage *druid_page, GtkWidget *widget,
gpointer user_data)
{
ABInitialInfo *info = user_data;
Account *root;
g_return_if_fail(info && info->gnc_hash);
/* Commit the changes */
root = gnc_book_get_root_account(gnc_get_current_book());
gnc_account_foreach_descendant(root, (AccountCb) clear_kvp_acc_cb, NULL);
g_hash_table_foreach(info->gnc_hash, (GHFunc) save_kvp_acc_cb, NULL);
gtk_widget_destroy(info->window);
}
static gboolean
banking_has_accounts(AB_BANKING *banking)
{
AB_ACCOUNT_LIST2 *accl;
gboolean result;
g_return_val_if_fail(banking, FALSE);
AB_Banking_OnlineInit(banking);
accl = AB_Banking_GetAccounts(banking);
if (accl && (AB_Account_List2_GetSize(accl) > 0))
result = TRUE;
else
result = FALSE;
if (accl)
AB_Account_List2_free(accl);
AB_Banking_OnlineFini(banking);
return result;
}
static void
hash_from_kvp_acc_cb(Account *gnc_acc, gpointer user_data)
{
AccCbData *data = user_data;
AB_ACCOUNT *ab_acc;
ab_acc = gnc_ab_get_ab_account(data->api, gnc_acc);
if (ab_acc)
g_hash_table_insert(data->hash, ab_acc, gnc_acc);
}
static void
druid_enable_next_button(ABInitialInfo *info)
{
g_return_if_fail(info);
gnome_druid_set_buttons_sensitive(GNOME_DRUID(info->druid),
TRUE, TRUE, TRUE, TRUE);
}
static void
druid_disable_next_button(ABInitialInfo *info)
{
g_return_if_fail(info);
gnome_druid_set_buttons_sensitive(GNOME_DRUID(info->druid),
TRUE, FALSE, TRUE, TRUE);
}
static void
child_exit_cb(GPid pid, gint status, gpointer data)
{
DeferredInfo *deferred_info = data;
ABInitialInfo *info = deferred_info->initial_info;
gint exit_status;
#ifdef G_OS_WIN32
exit_status = status;
#else
exit_status = WEXITSTATUS(status);
#endif
g_spawn_close_pid(pid);
if (!info) {
g_message("Online Banking wizard exited, but the druid has been "
"destroyed already");
goto cleanup_child_exit_cb;
}
if (exit_status == 0) {
druid_enable_next_button(info);
} else {
if (deferred_info->qt_probably_unavailable) {
g_warning("on_aqhbci_button: Oops, aqhbci wizard return nonzero "
"value: %d. The called program was \"%s\".\n",
exit_status, deferred_info->wizard_path);
gnc_error_dialog
(info->window,
_("The external program \"AqBanking Setup Wizard\" failed "
"to run successfully because the "
"additional software \"Qt\" was not found. "
"Please install the \"Qt/Windows Open Source Edition\" "
"from Trolltech by downloading it from www.trolltech.com"
"\n\n"
"If you have installed Qt already, you will have to adapt "
"the PATH variable of your system appropriately. "
"Contact the GnuCash developers if you need further "
"assistance on how to install Qt correctly."
"\n\n"
"Online Banking cannot be setup without Qt. Press \"Close\" "
"now, then \"Cancel\" to cancel the Online Banking setup."));
} else {
g_warning("on_aqhbci_button: Oops, aqhbci wizard return nonzero "
"value: %d. The called program was \"%s\".\n",
exit_status, deferred_info->wizard_path);
gnc_error_dialog
(info->window,
_("The external program \"AqBanking Setup Wizard\" failed "
"to run successfully. Online Banking can only be setup "
"if this wizard has run successfully. "
"Please try running the \"AqBanking Setup Wizard\" again."));
}
druid_disable_next_button(info);
}
cleanup_child_exit_cb:
g_free(deferred_info->wizard_path);
g_free(deferred_info);
if (info)
info->deferred_info = NULL;
}
static gchar *
ab_account_longname(const AB_ACCOUNT *ab_acc)
{
gchar *bankname;
gchar *result;
const char *bankcode;
g_return_val_if_fail(ab_acc, NULL);
bankname = gnc_utf8_strip_invalid_strdup(AB_Account_GetBankName(ab_acc));
bankcode = AB_Account_GetBankCode(ab_acc);
/* Translators: Strings are 1. Account code, 2. Bank name, 3. Bank code. */
if (bankname && *bankname)
result = g_strdup_printf(_("%s at %s (code %s)"),
AB_Account_GetAccountNumber(ab_acc),
bankname,
bankcode);
else
result = g_strdup_printf(_("%s at bank code %s"),
AB_Account_GetAccountNumber(ab_acc),
bankcode);
g_free(bankname);
return result;
}
static AB_ACCOUNT *
update_account_list_acc_cb(AB_ACCOUNT *ab_acc, gpointer user_data)
{
ABInitialInfo *info = user_data;
gchar *gnc_name, *ab_name;
Account *gnc_acc;
GtkTreeIter iter;
g_return_val_if_fail(ab_acc && info, NULL);
ab_name = ab_account_longname(ab_acc);
/* Get corresponding gnucash account */
gnc_acc = g_hash_table_lookup(info->gnc_hash, ab_acc);
/* Build the text for the gnucash account. */
if (gnc_acc)
gnc_name = xaccAccountGetFullName(gnc_acc);
else
gnc_name = g_strdup("");
/* Add item to the list store */
gtk_list_store_append(info->account_store, &iter);
gtk_list_store_set(info->account_store, &iter,
ACCOUNT_LIST_COL_AB_NAME, ab_name,
ACCOUNT_LIST_COL_AB_ACCT, ab_acc,
ACCOUNT_LIST_COL_GNC_NAME, gnc_name,
ACCOUNT_LIST_COL_CHECKED, FALSE,
-1);
g_free(gnc_name);
g_free(ab_name);
return NULL;
}
static void
update_account_list(ABInitialInfo *info)
{
AB_ACCOUNT_LIST2 *acclist;
g_return_if_fail(info && info->api && info->gnc_hash);
/* Detach model from view while updating */
g_object_ref(info->account_store);
gtk_tree_view_set_model(info->account_view, NULL);
/* Refill the list */
gtk_list_store_clear(info->account_store);
acclist = AB_Banking_GetAccounts(info->api);
if (acclist)
AB_Account_List2_ForEach(acclist, update_account_list_acc_cb, info);
else
g_warning("update_account_list: Oops, account list from AB_Banking "
"is NULL");
/* Attach model to view again */
gtk_tree_view_set_model(info->account_view,
GTK_TREE_MODEL(info->account_store));
g_object_unref(info->account_store);
}
static gboolean
find_gnc_acc_cb(gpointer key, gpointer value, gpointer user_data)
{
RevLookupData *data = user_data;
g_return_val_if_fail(data, TRUE);
if (value == data->gnc_acc) {
data->ab_acc = (AB_ACCOUNT*) key;
return TRUE;
}
return FALSE;
}
static gboolean
clear_line_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter,
gpointer user_data)
{
RevLookupData *data = user_data;
GtkListStore *store = GTK_LIST_STORE(model);
gpointer ab_acc;
g_return_val_if_fail(data && store, FALSE);
gtk_tree_model_get(model, iter, ACCOUNT_LIST_COL_AB_ACCT, &ab_acc, -1);
if (ab_acc == data->ab_acc) {
gtk_list_store_set(store, iter, ACCOUNT_LIST_COL_GNC_NAME, "",
ACCOUNT_LIST_COL_CHECKED, TRUE, -1);
return TRUE;
}
return FALSE;
}
static void
account_list_changed_cb(GtkTreeSelection *selection, gpointer user_data)
{
ABInitialInfo *info = user_data;
GtkTreeModel *model;
GtkTreeIter iter;
AB_ACCOUNT *ab_acc;
gchar *longname, *gnc_name;
Account *old_value, *gnc_acc;
const gchar *currency;
gnc_commodity *commodity = NULL;
gboolean ok_pressed;
g_return_if_fail(info);
if (!gtk_tree_selection_get_selected(selection, &model, &iter))
return;
gtk_tree_model_get(model, &iter, ACCOUNT_LIST_COL_AB_ACCT, &ab_acc, -1);
/* Avoid recursion when unselecting the item again */
g_signal_handlers_block_by_func(selection, account_list_changed_cb, info);
gtk_tree_selection_unselect_iter(selection, &iter);
g_signal_handlers_unblock_by_func(selection, account_list_changed_cb, info);
if (ab_acc) {
old_value = g_hash_table_lookup(info->gnc_hash, ab_acc);
longname = ab_account_longname(ab_acc);
currency = AB_Account_GetCurrency(ab_acc);
if (currency && *currency) {
commodity = gnc_commodity_table_lookup(
gnc_commodity_table_get_table(gnc_get_current_book()),
GNC_COMMODITY_NS_CURRENCY,
currency);
}
gnc_acc = gnc_import_select_account(info->window, NULL, TRUE,
longname, commodity, ACCT_TYPE_BANK,
old_value, &ok_pressed);
g_free(longname);
if (ok_pressed && old_value != gnc_acc) {
if (gnc_acc) {
RevLookupData data;
/* Lookup and clear other mappings to gnc_acc */
data.gnc_acc = gnc_acc;
data.ab_acc = NULL;
g_hash_table_find(info->gnc_hash, (GHRFunc) find_gnc_acc_cb,
&data);
if (data.ab_acc) {
g_hash_table_remove(info->gnc_hash, data.ab_acc);
gtk_tree_model_foreach(
GTK_TREE_MODEL(info->account_store),
(GtkTreeModelForeachFunc) clear_line_cb,
&data);
}
/* Map ab_acc to gnc_acc */
g_hash_table_insert(info->gnc_hash, ab_acc, gnc_acc);
gnc_name = xaccAccountGetFullName(gnc_acc);
gtk_list_store_set(info->account_store, &iter,
ACCOUNT_LIST_COL_GNC_NAME, gnc_name,
ACCOUNT_LIST_COL_CHECKED, TRUE,
-1);
g_free(gnc_name);
} else {
g_hash_table_remove(info->gnc_hash, ab_acc);
gtk_list_store_set(info->account_store, &iter,
ACCOUNT_LIST_COL_GNC_NAME, "",
ACCOUNT_LIST_COL_CHECKED, TRUE,
-1);
}
}
}
}
static void
clear_kvp_acc_cb(Account *gnc_acc, gpointer user_data)
{
if (gnc_ab_get_account_uid(gnc_acc))
gnc_ab_set_account_uid(gnc_acc, 0);
if (gnc_ab_get_account_accountid(gnc_acc))
gnc_ab_set_account_accountid(gnc_acc, "");
if (gnc_ab_get_account_bankcode(gnc_acc))
gnc_ab_set_account_bankcode(gnc_acc, "");
}
static void
save_kvp_acc_cb(gpointer key, gpointer value, gpointer user_data)
{
AB_ACCOUNT *ab_acc = key;
Account *gnc_acc = value;
guint32 ab_account_uid;
const gchar *ab_accountid, *gnc_accountid;
const gchar *ab_bankcode, *gnc_bankcode;
g_return_if_fail(ab_acc && gnc_acc);
ab_account_uid = AB_Account_GetUniqueId(ab_acc);
if (gnc_ab_get_account_uid(gnc_acc) != ab_account_uid)
gnc_ab_set_account_uid(gnc_acc, ab_account_uid);
ab_accountid = AB_Account_GetAccountNumber(ab_acc);
gnc_accountid = gnc_ab_get_account_accountid(gnc_acc);
if (ab_accountid
&& (!gnc_accountid
|| (strcmp(ab_accountid, gnc_accountid) != 0)))
gnc_ab_set_account_accountid(gnc_acc, ab_accountid);
ab_bankcode = AB_Account_GetBankCode(ab_acc);
gnc_bankcode = gnc_ab_get_account_bankcode(gnc_acc);
if (ab_bankcode
&& (!gnc_bankcode
|| (strcmp(gnc_bankcode, ab_bankcode) != 0)))
gnc_ab_set_account_bankcode(gnc_acc, ab_bankcode);
}
static void
cm_close_handler(gpointer user_data)
{
ABInitialInfo *info = user_data;
gtk_widget_destroy(info->window);
}
void
gnc_ab_initial_druid(void)
{
ABInitialInfo *info;
GladeXML *xml;
GtkTreeViewColumn *column;
GtkTreeSelection *selection;
gint component_id;
info = g_new0(ABInitialInfo, 1);
xml = gnc_glade_xml_new("aqbanking.glade", "AqBanking Init Druid");
info->window = glade_xml_get_widget(xml, "AqBanking Init Druid");
g_object_set_data_full(G_OBJECT(info->window), "xml", xml, g_object_unref);
glade_xml_signal_autoconnect_full(xml, gnc_glade_autoconnect_full_func,
info);
info->druid = glade_xml_get_widget(xml, "ab_init_druid");
gnc_druid_set_colors(GNOME_DRUID(info->druid));
info->api = gnc_AB_BANKING_new();
info->deferred_info = NULL;
info->gnc_hash = NULL;
info->account_view =
GTK_TREE_VIEW(glade_xml_get_widget(xml, "account_page_view"));
info->account_store = gtk_list_store_new(NUM_ACCOUNT_LIST_COLS,
G_TYPE_INT, G_TYPE_STRING,
G_TYPE_POINTER, G_TYPE_STRING,
G_TYPE_BOOLEAN);
gtk_tree_view_set_model(info->account_view,
GTK_TREE_MODEL(info->account_store));
g_object_unref(info->account_store);
column = gtk_tree_view_column_new_with_attributes(
_("Online Banking Account Name"), gtk_cell_renderer_text_new(),
"text", ACCOUNT_LIST_COL_AB_NAME, (gchar*) NULL);
gtk_tree_view_append_column(info->account_view, column);
column = gtk_tree_view_column_new_with_attributes(
_("GnuCash Account Name"), gtk_cell_renderer_text_new(),
"text", ACCOUNT_LIST_COL_GNC_NAME, (gchar*) NULL);
gtk_tree_view_column_set_expand(column, TRUE);
gtk_tree_view_append_column(info->account_view, column);
column = gtk_tree_view_column_new_with_attributes(
_("New?"), gtk_cell_renderer_toggle_new(),
"active", ACCOUNT_LIST_COL_CHECKED, (gchar*) NULL);
gtk_tree_view_append_column(info->account_view, column);
selection = gtk_tree_view_get_selection(info->account_view);
g_signal_connect(selection, "changed",
G_CALLBACK(account_list_changed_cb), info);
component_id = gnc_register_gui_component(DRUID_AB_INITIAL_CM_CLASS,
NULL, cm_close_handler, info);
gnc_gui_component_set_session(component_id, gnc_get_current_session());
gtk_widget_show(info->window);
}

View File

@@ -0,0 +1,51 @@
/*
* druid-ab-initial.h -- aqbanking creation functionality
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact:
*
* Free Software Foundation Voice: +1-617-542-5942
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
* Boston, MA 02110-1301, USA gnu@gnu.org
*/
/**
* @addtogroup Import_Export
* @{
* @addtogroup AqBanking
* @{
* @file druid-ab-initial.h
* @brief AqBanking setup functionality
* @author Copyright (C) 2002 Christian Stimming <stimming@tuhh.de>
* @author Copyright (C) 2008 Andreas Koehler <andi5.py@gmx.net>
*/
#ifndef DRUID_AB_INITIAL_H
#define DRUID_AB_INITIAL_H
#include <glib.h>
G_BEGIN_DECLS
/**
* Create and show a druid for the aqbanking setup.
*/
void gnc_ab_initial_druid(void);
G_END_DECLS
/** @} */
/** @} */
#endif /* DRUID_AB_INITIAL_H */

View File

@@ -0,0 +1,251 @@
/*
* gnc-ab-getbalance.c --
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact:
*
* Free Software Foundation Voice: +1-617-542-5942
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
* Boston, MA 02110-1301, USA gnu@gnu.org
*/
/**
* @internal
* @file gnc-ab-getbalance.c
* @brief AqBanking getbalance functions
* @author Copyright (C) 2002 Christian Stimming <stimming@tuhh.de>
* @author Copyright (C) 2008 Andreas Koehler <andi5.py@gmx.net>
*/
#include "config.h"
#include <glib/gi18n.h>
#include <aqbanking/banking.h>
#include <aqbanking/jobgetbalance.h>
#include "gnc-ab-getbalance.h"
#include "gnc-ab-kvp.h"
#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;
void
gnc_ab_getbalance(GtkWidget *parent, Account *gnc_acc)
{
AB_BANKING *api;
gboolean online = FALSE;
AB_ACCOUNT *ab_acc;
AB_JOB *job = NULL;
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;
g_return_if_fail(parent && gnc_acc);
/* Get the API */
api = gnc_AB_BANKING_new();
if (!api) {
g_warning("gnc_ab_gettrans: Couldn't get AqBanking API");
return;
}
if (AB_Banking_OnlineInit(api) != 0) {
g_warning("gnc_ab_gettrans: Couldn't initialize AqBanking API");
goto cleanup;
}
online = TRUE;
/* Get the AqBanking Account */
ab_acc = gnc_ab_get_ab_account(api, gnc_acc);
if (!ab_acc) {
g_warning("gnc_ab_getbalance: No AqBanking account found");
goto cleanup;
}
/* Get a GetBalance job and enqueue it */
job = AB_JobGetBalance_new(ab_acc);
if (!job || AB_Job_CheckAvailability(job, 0)) {
g_warning("gnc_ab_getbalance: JobGetBalance not available for this "
"account");
goto cleanup;
}
job_list = AB_Job_List2_new();
AB_Job_List2_PushBack(job_list, job);
/* Get a GUI object */
gui = gnc_GWEN_Gui_get(parent);
if (!gui) {
g_warning("gnc_ab_getbalance: Couldn't initialize Gwenhywfar GUI");
goto cleanup;
}
/* Create a context to store the results */
context = AB_ImExporterContext_new();
/* Execute the job */
if (AB_Banking_ExecuteJobs(api, job_list, context, 0)) {
g_warning("gnc_ab_getbalance: Error on executing job");
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;
}
/* 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 (context)
AB_ImExporterContext_free(context);
if (gui)
gnc_GWEN_Gui_release(gui);
if (job_list)
AB_Job_List2_free(job_list);
if (job)
AB_Job_free(job);
if (online)
AB_Banking_OnlineFini(api);
gnc_AB_BANKING_fini(api);
}

View File

@@ -0,0 +1,53 @@
/*
* gnc-ab-get-balance.h --
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact:
*
* Free Software Foundation Voice: +1-617-542-5942
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
* Boston, MA 02110-1301, USA gnu@gnu.org
*/
/**
* @addtogroup Import_Export
* @{
* @addtogroup AqBanking
* @{
* @file gnc-ab-getbalance.h
* @brief AqBanking getbalance functions
* @author Copyright (C) 2002 Christian Stimming <stimming@tuhh.de>
* @author Copyright (C) 2008 Andreas Koehler <andi5.py@gmx.net>
*/
#ifndef GNC_AB_GETBALANCE_H
#define GNC_AB_GETBALANCE_H
#include <gtk/gtk.h>
#include "Account.h"
G_BEGIN_DECLS
/**
* Execute a GetBalance job, show the resulting balance and offer to reconcile
* the GnuCash account.
*
* @param parent Widget to use as parent, may be NULL
* @param gnc_acc GnuCash account to fetch balance for
*/
void gnc_ab_getbalance(GtkWidget *parent, Account *gnc_acc);
G_END_DECLS
#endif /* GNC_AB_GETBALANCE_H */

View File

@@ -0,0 +1,245 @@
/*
* gnc-ab-gettrans.c --
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact:
*
* Free Software Foundation Voice: +1-617-542-5942
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
* Boston, MA 02110-1301, USA gnu@gnu.org
*/
/**
* @internal
* @file gnc-ab-gettrans.c
* @brief AqBanking get transactions functions
* @author Copyright (C) 2002 Christian Stimming <stimming@tuhh.de>
* @author Copyright (C) 2008 Andreas Koehler <andi5.py@gmx.net>
*/
#include "config.h"
#include <glib/gi18n.h>
#include <aqbanking/banking.h>
#include <aqbanking/jobgettransactions.h>
#include "Account.h"
#include "dialog-daterange.h"
#include "gnc-ab-gettrans.h"
#include "gnc-ab-kvp.h"
#include "gnc-ab-utils.h"
#include "gnc-gwen-gui.h"
#include "import-main-matcher.h"
/* This static indicates the debugging module that this .o belongs to. */
static QofLogModule log_module = G_LOG_DOMAIN;
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;
GNCImportMainMatcher *importer_generic;
};
static gboolean
gettrans_dates(GtkWidget *parent, Account *gnc_acc,
GWEN_TIME **from_date, GWEN_TIME **to_date)
{
Timespec last_timespec, until_timespec;
time_t now = time(NULL);
gboolean use_last_date = TRUE;
gboolean use_earliest_date = TRUE;
gboolean use_until_now = TRUE;
g_return_val_if_fail(from_date && to_date, FALSE);
/* Get time of last retrieval */
last_timespec = gnc_ab_get_account_trans_retrieval(gnc_acc);
if (last_timespec.tv_sec == 0) {
use_last_date = FALSE;
timespecFromTime_t(&last_timespec, now);
}
timespecFromTime_t(&until_timespec, now);
/* Let the user choose the date range of retrieval */
if (!gnc_ab_enter_daterange(parent, NULL,
&last_timespec,
&use_last_date, &use_earliest_date,
&until_timespec, &use_until_now))
return FALSE;
/* Now calculate from date */
if (use_earliest_date) {
*from_date = NULL;
} else {
if (use_last_date)
last_timespec = gnc_ab_get_account_trans_retrieval(gnc_acc);
*from_date = GWEN_Time_fromSeconds(timespecToTime_t(last_timespec));
}
/* Now calculate to date */
if (use_until_now)
timespecFromTime_t(&until_timespec, now);
*to_date = GWEN_Time_fromSeconds(timespecToTime_t(until_timespec));
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)
{
AB_BANKING *api;
gboolean online = FALSE;
AB_ACCOUNT *ab_acc;
GWEN_TIME *from_date = NULL, *to_date = NULL;
Timespec until_timespec;
AB_JOB *job = NULL;
AB_JOB_LIST2 *job_list = NULL;
GncGWENGui *gui = NULL;
AB_IMEXPORTER_CONTEXT *context = NULL;
AB_IMEXPORTER_ACCOUNTINFO *acc_info = NULL;
g_return_if_fail(parent && gnc_acc);
/* Get the API */
api = gnc_AB_BANKING_new();
if (!api) {
g_warning("gnc_ab_gettrans: Couldn't get AqBanking API");
return;
}
if (AB_Banking_OnlineInit(api) != 0) {
g_warning("gnc_ab_gettrans: Couldn't initialize AqBanking API");
goto cleanup;
}
online = TRUE;
/* Get the AqBanking Account */
ab_acc = gnc_ab_get_ab_account(api, gnc_acc);
if (!ab_acc) {
g_warning("gnc_ab_gettrans: No AqBanking account found");
goto cleanup;
}
/* Get the start and end dates for the GetTransactions job. */
if (!gettrans_dates(parent, gnc_acc, &from_date, &to_date)) {
g_debug("gnc_ab_gettrans: gettrans_dates aborted");
goto cleanup;
}
/* Use this as a local storage for the until_time below. */
timespecFromTime_t(&until_timespec, GWEN_Time_toTime_t(to_date));
/* Get a GetTransactions job and enqueue it */
job = AB_JobGetTransactions_new(ab_acc);
if (!job || AB_Job_CheckAvailability(job, 0)) {
g_warning("gnc_ab_gettrans: JobGetTransactions not available for this "
"account");
goto cleanup;
}
AB_JobGetTransactions_SetFromTime(job, from_date);
AB_JobGetTransactions_SetToTime(job, to_date);
job_list = AB_Job_List2_new();
AB_Job_List2_PushBack(job_list, job);
/* Get a GUI object */
gui = gnc_GWEN_Gui_get(parent);
if (!gui) {
g_warning("gnc_ab_gettrans: Couldn't initialize Gwenhywfar GUI");
goto cleanup;
}
/* Create a context to store the results */
context = AB_ImExporterContext_new();
/* Execute the job */
if (AB_Banking_ExecuteJobs(api, job_list, context, 0)) {
g_warning("gnc_ab_gettrans: Error on executing job");
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 {
/* No transaction found */
GtkWidget *dialog = gtk_message_dialog_new(
GTK_WINDOW(parent),
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO,
GTK_BUTTONS_OK,
"%s",
_("The Online Banking import returned no transactions "
"for the selected time period."));
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
}
/* Store the date of this retrieval */
gnc_ab_set_account_trans_retrieval(gnc_acc, until_timespec);
cleanup:
if (context)
AB_ImExporterContext_free(context);
if (gui)
gnc_GWEN_Gui_release(gui);
if (job_list)
AB_Job_List2_free(job_list);
if (job)
AB_Job_free(job);
if (to_date)
GWEN_Time_free(to_date);
if (from_date)
GWEN_Time_free(from_date);
if (online)
AB_Banking_OnlineFini(api);
gnc_AB_BANKING_fini(api);
}

View File

@@ -0,0 +1,50 @@
/*
* gnc-ab-get-balance.h --
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact:
*
* Free Software Foundation Voice: +1-617-542-5942
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
* Boston, MA 02110-1301, USA gnu@gnu.org
*/
/**
* @addtogroup Import_Export
* @{
* @addtogroup AqBanking
* @{
* @file gnc-ab-getbalance.h
* @brief AqBanking getbalance functions
* @author Copyright (C) 2002 Christian Stimming
* @author Copyright (C) 2008 Andreas Koehler <andi5.py@gmx.net>
*/
#ifndef GNC_AB_GETTRANS_H
#define GNC_AB_GETTRANS_H
#include <glib.h>
G_BEGIN_DECLS
/**
* Execute a GetTransactions job.
*
* @param parent Widget to use as parent, may be NULL
* @param gnc_acc GnuCash account to fetch transactions for
*/
void gnc_ab_gettrans(GtkWidget *parent, Account *gnc_acc);
G_END_DECLS
#endif /* GNC_AB_GETTRANS_H */

View File

@@ -0,0 +1,176 @@
/*
* gnc-ab-kvp.c --
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact:
*
* Free Software Foundation Voice: +1-617-542-5942
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
* Boston, MA 02110-1301, USA gnu@gnu.org
*/
/**
* @internal
* @file gnc-ab-kvp.c
* @brief AqBanking KVP handling
* @author Copyright (C) 2002 Christian Stimming <stimming@tuhh.de>
* @author Copyright (C) 2008 Andreas Koehler <andi5.py@gmx.net>
*/
#include "config.h"
#include "gnc-ab-kvp.h"
#define AB_KEY "hbci"
#define AB_ACCOUNT_ID "account-id"
#define AB_ACCOUNT_UID "account-uid"
#define AB_BANK_CODE "bank-code"
#define AB_TRANS_RETRIEVAL "trans-retrieval"
#define AB_TEMPLATES "template-list"
/* This static indicates the debugging module that this .o belongs to. */
static QofLogModule log_module = G_LOG_DOMAIN;
static void force_account_dirty(Account *acct);
static kvp_frame *gnc_ab_get_account_kvp(const Account *a, gboolean create);
static kvp_frame *gnc_ab_get_book_kvp(QofBook *b, gboolean create);
G_CONST_RETURN gchar *
gnc_ab_get_account_accountid(const Account *a)
{
kvp_frame *frame = gnc_ab_get_account_kvp(a, FALSE);
kvp_value *value = kvp_frame_get_slot(frame, AB_ACCOUNT_ID);
return kvp_value_get_string(value);
}
void
gnc_ab_set_account_accountid(Account *a, const gchar *id)
{
kvp_frame *frame = gnc_ab_get_account_kvp(a, TRUE);
kvp_value *value = kvp_value_new_string(id);
xaccAccountBeginEdit(a);
kvp_frame_set_slot_nc(frame, AB_ACCOUNT_ID, value);
force_account_dirty(a);
xaccAccountCommitEdit(a);
}
G_CONST_RETURN gchar *
gnc_ab_get_account_bankcode(const Account *a)
{
kvp_frame *frame = gnc_ab_get_account_kvp(a, FALSE);
kvp_value *value = kvp_frame_get_slot(frame, AB_BANK_CODE);
return kvp_value_get_string(value);
}
void
gnc_ab_set_account_bankcode(Account *a, const gchar *code)
{
kvp_frame *frame = gnc_ab_get_account_kvp(a, TRUE);
kvp_value *value = kvp_value_new_string(code);
xaccAccountBeginEdit(a);
kvp_frame_set_slot_nc(frame, AB_BANK_CODE, value);
force_account_dirty(a);
xaccAccountCommitEdit(a);
}
guint32
gnc_ab_get_account_uid(const Account *a)
{
kvp_frame *frame = gnc_ab_get_account_kvp(a, FALSE);
kvp_value *value = kvp_frame_get_slot(frame, AB_ACCOUNT_UID);
return (guint32) kvp_value_get_gint64(value);
}
void
gnc_ab_set_account_uid(Account *a, guint32 uid)
{
kvp_frame *frame = gnc_ab_get_account_kvp(a, TRUE);
kvp_value *value = kvp_value_new_gint64(uid);
xaccAccountBeginEdit(a);
kvp_frame_set_slot_nc(frame, AB_ACCOUNT_UID, value);
force_account_dirty(a);
xaccAccountCommitEdit(a);
}
Timespec
gnc_ab_get_account_trans_retrieval(const Account *a)
{
kvp_frame *frame = gnc_ab_get_account_kvp(a, FALSE);
kvp_value *value = kvp_frame_get_slot(frame, AB_TRANS_RETRIEVAL);
return kvp_value_get_timespec(value);
}
void
gnc_ab_set_account_trans_retrieval(Account *a, Timespec time)
{
kvp_frame *frame = gnc_ab_get_account_kvp(a, TRUE);
kvp_value *value = kvp_value_new_timespec(time);
xaccAccountBeginEdit(a);
kvp_frame_set_slot_nc(frame, AB_TRANS_RETRIEVAL, value);
force_account_dirty(a);
xaccAccountCommitEdit(a);
}
GList *
gnc_ab_get_book_template_list(QofBook *b)
{
kvp_frame *frame = gnc_ab_get_book_kvp(b, FALSE);
kvp_value *value = kvp_frame_get_slot(frame, AB_TEMPLATES);
return kvp_value_get_glist(value);
}
void
gnc_ab_set_book_template_list(QofBook *b, GList *template_list)
{
kvp_frame *frame = gnc_ab_get_book_kvp(b, TRUE);
kvp_value *value = kvp_value_new_glist_nc(template_list);
kvp_frame_set_slot_nc(frame, AB_TEMPLATES, value);
qof_book_kvp_changed(b);
}
static void
force_account_dirty(Account *acct)
{
gchar *name = g_strdup(xaccAccountGetName(acct));
/* This is necessary because modifying the KvpFrames doesn't mark
* accounts dirty, which means the changes wont be propagated to the
* backend.
*/
xaccAccountSetName(acct, name);
g_free(name);
}
static kvp_frame *
gnc_ab_get_account_kvp(const Account *a, gboolean create)
{
kvp_frame *toplevel = xaccAccountGetSlots(a);
kvp_frame *result = kvp_frame_get_frame(toplevel, AB_KEY);
if (!result && create) {
result = kvp_frame_new();
kvp_frame_add_frame_nc(toplevel, AB_KEY, result);
}
return result;
}
static kvp_frame *
gnc_ab_get_book_kvp(QofBook *b, gboolean create)
{
kvp_frame *toplevel = qof_book_get_slots(b);
kvp_frame *result = kvp_frame_get_frame(toplevel, AB_KEY);
if (!result && create) {
result = kvp_frame_new();
kvp_frame_add_frame_nc(toplevel, AB_KEY, result);
}
return result;
}

View File

@@ -0,0 +1,148 @@
/*
* gnc-ab-kvp.h --
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact:
*
* Free Software Foundation Voice: +1-617-542-5942
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
* Boston, MA 02110-1301, USA gnu@gnu.org
*/
/**
* @addtogroup Import_Export
* @{
* @addtogroup AqBanking
* @{
* @file gnc-ab-kvp.h
* @brief AqBanking KVP handling
* @author Copyright (C) 2002 Christian Stimming <stimming@tuhh.de>
* @author Copyright (C) 2008 Andreas Koehler <andi5.py@gmx.net>
*/
#ifndef GNC_AB_KVP_H
#define GNC_AB_KVP_H
#include <glib.h>
#include "Account.h"
G_BEGIN_DECLS
/** @name Account
* @{ */
/**
* Return a non-copied pointer to the accountid string in the Account @a a.
* The gchar* is still owned by the kvp_frame, so don't free it until you want
* to delete the whole kvp_frame.
*
* @param a Account
* @return Account ID
*/
const gchar *gnc_ab_get_account_accountid(const Account *a);
/**
* Set the accountid string in the Account @a a to @a id. A copy of the string
* will be stored. The Account will be marked as "dirty".
*
* @param a Account
* @param id Account ID
*/
void gnc_ab_set_account_accountid(Account *a, const gchar *id);
/**
* Return a non-copied pointer to the bankcode string in the Account @a a. The
* gchar* is still owned by the kvp_frame, so don't free it until you want to
* delete the whole kvp_frame.
*
* @param a Account
* @return Bank code
*/
const gchar *gnc_ab_get_account_bankcode(const Account *a);
/**
* Set the bankcode string in the Account @a a to @a code. A copy of the string
* will be stored. The Account will be marked as "dirty".
*
* @param a Account
* @param code Bank code
*/
void gnc_ab_set_account_bankcode(Account *a, const gchar *code);
/**
* Return the unique id for the AB_BANKING account in the Account @a a.
*
* @param a Account
* @return Unique ID
*/
guint32 gnc_ab_get_account_uid(const Account *a);
/**
* Set the unique id for the AB_BANKING account in the Account @a a to @a uid.
* The Account will be marked as "dirty".
*
* @param a Account
* @param uid Unique ID
*/
void gnc_ab_set_account_uid(Account *a, guint32 uid);
/**
* Return the time of last online transaction retrieval for Account @a a.
*
* @param a Account
* @return Retrieval time
*/
Timespec gnc_ab_get_account_trans_retrieval(const Account *a);
/**
* Set the time of last online transaction retrieval for Account @a a. The
* account will be marked as "dirty".
*
* @param a Account
* @param time Retrieval time
*/
void gnc_ab_set_account_trans_retrieval(Account *a, Timespec time);
/** @} */
/** @name Book
* @{ */
/**
* Return a non-copied pointer to the GList of kvp_frames which eventually are
* the template transactions, stored in the given book.
*
* @param b Book
* @return Template list
*/
GList *gnc_ab_get_book_template_list(QofBook *b);
/**
* Set the GList of kvp_frames of template transactions in the Book @a b to @a
* template_list. No copy of the GList will be stored, the callee becomes the
* owner and the caller must not free it. The book will be marked "dirty".
*
* @param b Book
* @param template_list Template list
*/
void gnc_ab_set_book_template_list(QofBook *b, GList *template_list);
/** @} */
G_END_DECLS
/** @} */
/** @} */
#endif /* GNC_AB_KVP_H */

View File

@@ -0,0 +1,285 @@
/*
* gnc-ab-trans-templ.c --
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact:
*
* Free Software Foundation Voice: +1-617-542-5942
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
* Boston, MA 02110-1301, USA gnu@gnu.org
*/
/**
* @internal
* @file gnc-ab-trans-templ.c
* @brief Templates for AqBanking transactions
* @author Copyright (C) 2002 Christian Stimming <stimming@tuhh.de>
* @author Copyright (C) 2008 Andreas Koehler <andi5.py@gmx.net>
*/
#include "config.h"
#include "gnc-ab-trans-templ.h"
/* This static indicates the debugging module that this .o belongs to. */
static QofLogModule log_module = G_LOG_DOMAIN;
/* kvp_frame slot names */
#define TT_NAME "name"
#define TT_RNAME "rnam"
#define TT_RACC "racc"
#define TT_RBCODE "rbcd"
#define TT_PURPOS "purp"
#define TT_PURPOSCT "purc"
#define TT_AMOUNT "amou"
struct _GncABTransTempl
{
/* Name of this Template */
gchar *name;
gchar *name_key; /* Collation key */
/* Recipient */
gchar *recp_name;
gchar *recp_account;
gchar *recp_bankcode;
/* Amount */
gnc_numeric amount;
/* Purpose, description */
gchar *purpose;
gchar *purpose_cont;
};
GncABTransTempl *
gnc_ab_trans_templ_new(void)
{
return gnc_ab_trans_templ_new_full(NULL, NULL, NULL, NULL,
gnc_numeric_zero(), NULL, NULL);
}
GncABTransTempl *
gnc_ab_trans_templ_new_full(const char *name, const char *recp_name,
const char *recp_account, const char *recp_bankcode,
gnc_numeric amount, const char *purpose,
const char *purpose_cont)
{
GncABTransTempl *r = g_new(GncABTransTempl, 1);
r->name = g_strdup(name);
r->name_key = g_utf8_collate_key(name, -1);
r->recp_name = g_strdup(recp_name);
r->recp_account = g_strdup(recp_account);
r->recp_bankcode = g_strdup(recp_bankcode);
r->amount = amount;
r->purpose = g_strdup(purpose);
r->purpose_cont = g_strdup(purpose_cont);
return r;
}
GncABTransTempl *
gnc_ab_trans_templ_new_from_kvp(const kvp_frame *k)
{
g_return_val_if_fail(k, NULL);
return gnc_ab_trans_templ_new_full(
kvp_value_get_string(kvp_frame_get_slot(k, TT_NAME)),
kvp_value_get_string(kvp_frame_get_slot(k, TT_RNAME)),
kvp_value_get_string(kvp_frame_get_slot(k, TT_RACC)),
kvp_value_get_string(kvp_frame_get_slot(k, TT_RBCODE)),
kvp_value_get_numeric(kvp_frame_get_slot(k, TT_AMOUNT)),
kvp_value_get_string(kvp_frame_get_slot(k, TT_PURPOS)),
kvp_value_get_string(kvp_frame_get_slot(k, TT_PURPOSCT)));
}
GList *
gnc_ab_trans_templ_list_new_from_kvp_list(GList *v)
{
GList *res = NULL;
GList *iter;
for (iter = v; iter; iter = iter->next) {
kvp_frame *frame = kvp_value_get_frame((kvp_value*) iter->data);
res = g_list_prepend(res, gnc_ab_trans_templ_new_from_kvp(frame));
}
res = g_list_reverse(res);
return res;
}
void
gnc_ab_trans_templ_free(GncABTransTempl *t)
{
if (!t) return;
g_free(t->name);
g_free(t->name_key);
g_free(t->recp_name);
g_free(t->recp_account);
g_free(t->recp_bankcode);
g_free(t->purpose);
g_free(t->purpose_cont);
g_free(t);
}
void
gnc_ab_trans_templ_list_free(GList *l)
{
GList *iter;
for (iter = l; iter; iter = iter->next)
gnc_ab_trans_templ_free((GncABTransTempl*) iter->data);
g_list_free(l);
}
kvp_frame *
gnc_ab_trans_templ_to_kvp(const GncABTransTempl *t)
{
kvp_frame *k;
g_return_val_if_fail(t, NULL);
k = kvp_frame_new();
kvp_frame_set_slot(k, TT_NAME, kvp_value_new_string(t->name));
kvp_frame_set_slot(k, TT_RNAME, kvp_value_new_string(t->recp_name));
kvp_frame_set_slot(k, TT_RACC, kvp_value_new_string(t->recp_account));
kvp_frame_set_slot(k, TT_RBCODE, kvp_value_new_string(t->recp_bankcode));
kvp_frame_set_slot(k, TT_AMOUNT, kvp_value_new_gnc_numeric(t->amount));
kvp_frame_set_slot(k, TT_PURPOS, kvp_value_new_string(t->purpose));
kvp_frame_set_slot(k, TT_PURPOSCT, kvp_value_new_string(t->purpose_cont));
return k;
}
GList *
gnc_ab_trans_templ_list_to_kvp_list(GList *k)
{
GList *res = NULL;
GList *iter;
for (iter = k; iter; iter = iter->next) {
GncABTransTempl *t = (GncABTransTempl*) iter->data;
kvp_value *value = kvp_value_new_frame_nc(gnc_ab_trans_templ_to_kvp(t));
res = g_list_prepend(res, value);
}
res = g_list_reverse(res);
return res;
}
const gchar *
gnc_ab_trans_templ_get_name(const GncABTransTempl *t)
{
g_return_val_if_fail(t, NULL);
return t->name;
}
const gchar *
gnc_ab_trans_templ_get_recp_name(const GncABTransTempl *t)
{
g_return_val_if_fail(t, NULL);
return t->recp_name;
}
const gchar *
gnc_ab_trans_templ_get_recp_account(const GncABTransTempl *t)
{
g_return_val_if_fail(t, NULL);
return t->recp_account;
}
const gchar *
gnc_ab_trans_templ_get_recp_bankcode(const GncABTransTempl *t)
{
g_return_val_if_fail(t, NULL);
return t->recp_bankcode;
}
gnc_numeric
gnc_ab_trans_templ_get_amount(const GncABTransTempl *t)
{
g_return_val_if_fail(t, gnc_numeric_zero());
return t->amount;
}
const gchar *
gnc_ab_trans_templ_get_purpose(const GncABTransTempl *t)
{
g_return_val_if_fail(t, NULL);
return t->purpose;
}
const gchar *
gnc_ab_trans_templ_get_purpose_cont(const GncABTransTempl *t)
{
g_return_val_if_fail(t, NULL);
return t->purpose_cont;
}
void
gnc_ab_trans_templ_set_name(GncABTransTempl *t, const gchar *name)
{
g_return_if_fail(t);
g_free(t->name);
t->name = g_strdup(name);
}
void
gnc_ab_trans_templ_set_recp_name(GncABTransTempl *t, const gchar *recp_name)
{
g_return_if_fail(t);
g_free(t->recp_name);
t->recp_name = g_strdup(recp_name);
}
void
gnc_ab_trans_templ_set_recp_account(GncABTransTempl *t,
const gchar *recp_account)
{
g_return_if_fail(t);
g_free(t->recp_account);
t->recp_account = g_strdup(recp_account);
}
void
gnc_ab_trans_templ_set_recp_bankcode(GncABTransTempl *t,
const gchar *recp_bankcode)
{
g_return_if_fail(t);
g_free(t->recp_bankcode);
t->recp_bankcode = g_strdup(recp_bankcode);
}
void
gnc_ab_trans_templ_set_amount(GncABTransTempl *t, gnc_numeric amount)
{
g_return_if_fail(t);
t->amount = amount;
}
void
gnc_ab_trans_templ_set_purpose(GncABTransTempl *t, const gchar *purpose)
{
g_return_if_fail(t);
g_free(t->purpose);
t->purpose = g_strdup(purpose);
}
void
gnc_ab_trans_templ_set_purpose_cont(GncABTransTempl *t,
const gchar *purpose_cont)
{
g_return_if_fail(t);
g_free(t->purpose_cont);
t->purpose_cont = g_strdup(purpose_cont);
}

View File

@@ -0,0 +1,221 @@
/*
* gnc-ab-trans-templ.h --
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact:
*
* Free Software Foundation Voice: +1-617-542-5942
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
* Boston, MA 02110-1301, USA gnu@gnu.org
*/
/**
* @addtogroup Import_Export
* @{
* @addtogroup AqBanking
* @{
* @file gnc-ab-trans-templ.h
* @brief Templates for AqBanking transactions
* @author Copyright (C) 2003 Christian Stimming <stimming@tuhh.de>
* @author Copyright (C) 2008 Andreas Koehler <andi5.py@gmx.net>
*/
#ifndef GNC_AB_TRANS_TEMPL_H
#define GNC_AB_TRANS_TEMPL_H
#include <glib.h>
#include "qof.h"
G_BEGIN_DECLS
/** A template for an AqBanking transaction */
typedef struct _GncABTransTempl GncABTransTempl;
/**
* Create a template with unset contents.
*
* @return A newly allocated GncABTransTempl
*/
GncABTransTempl *gnc_ab_trans_templ_new(void);
/**
* Create a template with given contents.
*
* @param name Name of the template
* @param recp_name Name of the recipient
* @param recp_account Account Number of the recipient
* @param recp_bankcode Bank Code of the recipient
* @param amount Amount
* @param purpose First purpose line
* @param purpose_cont Second purpose line
* @return A newly allocated GncABTransTempl
*/
GncABTransTempl *gnc_ab_trans_templ_new_full(
const gchar *name, const gchar *recp_name, const gchar *recp_account,
const gchar *recp_bankcode, gnc_numeric amount, const gchar *purpose,
const gchar *purpose_cont);
/**
* Create a template, taking the values from a kvp_frame.
*
* @param k kvp_frame
* @return A newly allocated GncABTransTempl
*/
GncABTransTempl *gnc_ab_trans_templ_new_from_kvp(const kvp_frame *k);
/**
* Create a list of templates from a list of kvp_values which in turn
* contain a kvp_frame.
*
* @param v GList of kvp_values
* @return A GList of newly allocated GncABTransTempls
*/
GList *gnc_ab_trans_templ_list_new_from_kvp_list(GList *v);
/**
* Free the memory used by a template.
*
* @param t GncABTransTempl to be freed
*/
void gnc_ab_trans_templ_free(GncABTransTempl *t);
/**
* Free the memory used by a list of templates, including the list itself.
*
* @param l GList of GncABTransTempl
*/
void gnc_ab_trans_templ_list_free(GList *l);
/**
* Create a kvp_frame a given template.
*
* @param t Template
* @return A newly allocated kvp_frame
*/
kvp_frame *gnc_ab_trans_templ_to_kvp(const GncABTransTempl *t);
/**
* Create a list of kvp_values, which in turn contain a kvp_frame, from a list
* of templates.
*
* @param k GList of GncABTransTempls
* @return GList of newly allocated kvp_values
*/
GList *gnc_ab_trans_templ_list_to_kvp_list(GList *k);
/**
* @param t Template
* @return Name of the template, an internal string
*/
const gchar *gnc_ab_trans_templ_get_name(const GncABTransTempl *t);
/**
* @param t Template
* @return Name of the recipient, an internal string
*/
const gchar *gnc_ab_trans_templ_get_recp_name(const GncABTransTempl *t);
/**
* @param t Template
* @return Account Number of the recipient, an internal string
*/
const gchar *gnc_ab_trans_templ_get_recp_account(const GncABTransTempl *t);
/**
* @param t Template
* @return Bank Code of the recipient, an internal string
*/
const gchar *gnc_ab_trans_templ_get_recp_bankcode(const GncABTransTempl *t);
/**
* @param t Template
* @return Amount
*/
gnc_numeric gnc_ab_trans_templ_get_amount(const GncABTransTempl *t);
/**
* @param t Template
* @return First purpose line, an internal string
*/
const gchar *gnc_ab_trans_templ_get_purpose(const GncABTransTempl *t);
/**
* @param t Template
* @return Second purpose line, an internal string
*/
const gchar *gnc_ab_trans_templ_get_purpose_cont(const GncABTransTempl *t);
/**
* Set the name of a template.
*
* @param t Template
* @param name Name
*/
void gnc_ab_trans_templ_set_name(GncABTransTempl *t, const gchar *name);
/**
* Replace the Account Number of the recipient stored in a template.
*
* @param t Template
* @param recp_name Account Number of the recipient
*/
void gnc_ab_trans_templ_set_recp_name(GncABTransTempl *t,
const gchar *recp_name);
/**
* Replace the Account Number of the recipient stored in a template.
*
* @param t Template
* @param recp_account Account Number of the recipient
*/
void gnc_ab_trans_templ_set_recp_account(GncABTransTempl *t,
const gchar *recp_account);
/**
* Replace the Bank Code of the recipient stored in a template.
*
* @param t Template
* @param recp_bankcode Bank Code of the recipient
*/
void gnc_ab_trans_templ_set_recp_bankcode(GncABTransTempl *t,
const gchar *recp_bankcode);
/**
* Replace the amount stored in a template.
*
* @param t Template
* @param amount Amount
*/
void gnc_ab_trans_templ_set_amount(GncABTransTempl *t, gnc_numeric amount);
/**
* Replace the first purpose line stored in a template.
*
* @param t Template
* @param purpose First purpose line
*/
void gnc_ab_trans_templ_set_purpose(GncABTransTempl *t, const gchar *purpose);
/**
* Replace the second purpose line stored in a template.
*
* @param t Template
* @param purpose_cont Second purpose line
*/
void gnc_ab_trans_templ_set_purpose_cont(GncABTransTempl *t,
const gchar *purpose_cont);
G_END_DECLS
#endif /* GNC_AB_TRANS_TEMPL_H */

View File

@@ -0,0 +1,283 @@
/*
* gnc-ab-transfer.c --
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact:
*
* Free Software Foundation Voice: +1-617-542-5942
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
* Boston, MA 02110-1301, USA gnu@gnu.org
*/
/**
* @internal
* @file gnc-ab-utils.c
* @brief AqBanking transfer functions
* @author Copyright (C) 2002 Christian Stimming <stimming@tuhh.de>
* @author Copyright (C) 2004 Bernd Wagner
* @author Copyright (C) 2006 David Hampton <hampton@employees.org>
* @author Copyright (C) 2008 Andreas Koehler <andi5.py@gmx.net>
*/
#include "config.h"
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <aqbanking/banking.h>
#include "Transaction.h"
#include "dialog-transfer.h"
#include "gnc-ab-transfer.h"
#include "gnc-ab-kvp.h"
#include "gnc-ab-utils.h"
#include "gnc-ab-trans-templ.h"
#include "gnc-gwen-gui.h"
#include "gnc-ui.h"
/* This static indicates the debugging module that this .o belongs to. */
static QofLogModule log_module = G_LOG_DOMAIN;
static void save_templates(GtkWidget *parent, Account *gnc_acc, GList *templates,
gboolean dont_ask);
static void txn_created_cb(Transaction *trans, gpointer user_data);
static void
save_templates(GtkWidget *parent, Account *gnc_acc, GList *templates,
gboolean dont_ask)
{
g_return_if_fail(gnc_acc);
if (dont_ask || gnc_verify_dialog(
parent, FALSE, "%s",
_("You have changed the list of online transfer templates, "
"but you cancelled the transfer dialog. "
"Do you nevertheless want to store the changes?"))) {
GList *kvp_list = gnc_ab_trans_templ_list_to_kvp_list(templates);
gnc_ab_set_book_template_list(gnc_account_get_book(gnc_acc), kvp_list);
}
}
static void
txn_created_cb(Transaction *trans, gpointer user_data)
{
Transaction **trans_loc = user_data;
if (!trans) return;
g_return_if_fail(trans_loc);
*trans_loc = trans;
}
void
gnc_ab_maketrans(GtkWidget *parent, Account *gnc_acc,
GncABTransType trans_type)
{
AB_BANKING *api;
gboolean online = FALSE;
AB_ACCOUNT *ab_acc;
GncABTransDialog *dialog = NULL;
GList *templates = NULL;
GncABTransDialog *td = NULL;
gboolean successful;
gboolean aborted = FALSE;
g_return_if_fail(parent && gnc_acc);
/* Get the API */
api = gnc_AB_BANKING_new();
if (!api) {
g_warning("gnc_ab_maketrans: Couldn't get AqBanking API");
return;
}
if (AB_Banking_OnlineInit(api) != 0) {
g_warning("gnc_ab_maketrans: Couldn't initialize AqBanking API");
goto cleanup;
}
online = TRUE;
/* Get the AqBanking Account */
ab_acc = gnc_ab_get_ab_account(api, gnc_acc);
if (!ab_acc) {
g_warning("gnc_ab_gettrans: No AqBanking account found");
goto cleanup;
}
/* Get list of template transactions */
templates = gnc_ab_trans_templ_list_new_from_kvp_list(
gnc_ab_get_book_template_list(gnc_account_get_book(gnc_acc)));
/* Create new ABTransDialog */
td = gnc_ab_trans_dialog_new(parent, ab_acc,
xaccAccountGetCommoditySCU(gnc_acc),
trans_type, templates);
templates = NULL;
/* Repeat until AqBanking action was successful or user pressed cancel */
do {
GncGWENGui *gui = NULL;
gint result;
gboolean changed;
const AB_TRANSACTION *ab_trans;
AB_JOB *job = NULL;
AB_JOB_LIST2 *job_list = NULL;
XferDialog *xfer_dialog = NULL;
gnc_numeric amount;
gchar *description;
gchar *memo;
Transaction *gnc_trans = NULL;
/* Get a GUI object */
gui = gnc_GWEN_Gui_get(parent);
if (!gui) {
g_warning("gnc_ab_maketrans: Couldn't initialize Gwenhywfar GUI");
aborted = TRUE;
goto repeat;
}
/* Let the user enter the values */
result = gnc_ab_trans_dialog_run_until_ok(td);
if (result != GNC_RESPONSE_NOW && result != GNC_RESPONSE_LATER) {
aborted = TRUE;
goto repeat;
}
/* Save the templates */
templates = gnc_ab_trans_dialog_get_templ(td, &changed);
if (changed)
save_templates(parent, gnc_acc, templates,
(result == GNC_RESPONSE_NOW));
g_list_free(templates);
templates = NULL;
/* Get a job and enqueue it */
ab_trans = gnc_ab_trans_dialog_get_ab_trans(td);
job = gnc_ab_trans_dialog_get_job(td);
if (!job || AB_Job_CheckAvailability(job, 0)) {
if (!gnc_verify_dialog(
parent, 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?")))
aborted = TRUE;
goto repeat;
}
job_list = AB_Job_List2_new();
AB_Job_List2_PushBack(job_list, job);
/* Setup a Transfer Dialog for the GnuCash transaction */
xfer_dialog = gnc_xfer_dialog(gnc_ab_trans_dialog_get_parent(td),
gnc_acc);
switch (trans_type) {
case SINGLE_DEBITNOTE:
gnc_xfer_dialog_set_title(
xfer_dialog, _("Online Banking Direct Debit Note"));
gnc_xfer_dialog_lock_to_account_tree(xfer_dialog);
break;
case SINGLE_INTERNAL_TRANSFER:
gnc_xfer_dialog_set_title(
xfer_dialog, _("Online Banking Bank-Internal Transfer"));
gnc_xfer_dialog_lock_from_account_tree(xfer_dialog);
break;
case SINGLE_TRANSFER:
default:
gnc_xfer_dialog_set_title(
xfer_dialog, _("Online Banking Transaction"));
gnc_xfer_dialog_lock_from_account_tree(xfer_dialog);
}
amount = double_to_gnc_numeric(
AB_Value_GetValueAsDouble(AB_Transaction_GetValue(ab_trans)),
xaccAccountGetCommoditySCU(gnc_acc),
GNC_RND_ROUND);
gnc_xfer_dialog_set_amount(xfer_dialog, amount);
description = gnc_ab_description_to_gnc(ab_trans);
gnc_xfer_dialog_set_description(xfer_dialog, description);
g_free(description);
memo = gnc_ab_memo_to_gnc(ab_trans);
gnc_xfer_dialog_set_memo(xfer_dialog, memo);
g_free(memo);
gnc_xfer_dialog_set_txn_cb(xfer_dialog, txn_created_cb, &gnc_trans);
/* And run it */
successful = gnc_xfer_dialog_run_until_done(xfer_dialog);
/* On cancel, go back to the AB transaction dialog */
if (!successful || !gnc_trans) {
successful = FALSE;
goto repeat;
}
if (result == GNC_RESPONSE_NOW) {
/* Finally, execute the job */
successful = AB_Banking_ExecuteJobs(api, job_list, NULL, 0) == 0;
if (!successful
|| AB_Job_GetStatus(job) != AB_Job_StatusFinished) {
successful = FALSE;
if (!gnc_verify_dialog(
parent, FALSE, "%s",
_("An error occurred while executing the job. Please check "
"the log window for the exact error message.\n"
"\n"
"Do you want to enter the job again?"))) {
/* _("The job was sent to the bank successfully, but the " */
/* "bank is refusing to execute the job. Please check " */
/* "the log window for the exact error message of the " */
/* "bank. The line with the error message contains a " */
/* "code number that is greater than 9000.\n" */
/* "\n" */
/* "Do you want to enter the job again?"))) { */
aborted = TRUE;
}
}
}
/* Simply ignore any other case */
repeat:
/* Clean up */
if (gnc_trans && !successful) {
xaccTransBeginEdit(gnc_trans);
xaccTransDestroy(gnc_trans);
xaccTransCommitEdit(gnc_trans);
gnc_trans = NULL;
}
if (job_list) {
AB_Job_List2_free(job_list);
job_list = NULL;
}
if (job) {
AB_Job_free(job);
job = NULL;
}
if (gui) {
gnc_GWEN_Gui_release(gui);
gui = NULL;
}
} while (!successful && !aborted);
cleanup:
if (td)
gnc_ab_trans_dialog_free(td);
if (online)
AB_Banking_OnlineFini(api);
gnc_AB_BANKING_fini(api);
}

View File

@@ -0,0 +1,58 @@
/*
* gnc-ab-transfer.h --
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact:
*
* Free Software Foundation Voice: +1-617-542-5942
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
* Boston, MA 02110-1301, USA gnu@gnu.org
*/
/**
* @addtogroup Import_Export
* @{
* @addtogroup AqBanking
* @{
* @file gnc-ab-transfer.h
* @brief Dialog for AqBanking transaction data
* @author Copyright (C) 2002 Christian Stimming <stimming@tuhh.de>
* @author Copyright (C) 2008 Andreas Koehler <andi5.py@gmx.net>
*/
#ifndef GNC_AB_TRANSFER_H
#define GNC_AB_TRANSFER_H
#include <gtk/gtk.h>
#include "Account.h"
#include "dialog-ab-trans.h"
G_BEGIN_DECLS
/**
* FIXME
*
* @param parent Widget to use as parent, may be NULL
* @param gnc_acc GnuCash account to fetch balance for
* @param trans_type Type of transaction
*/
void gnc_ab_maketrans(GtkWidget *parent, Account *gnc_acc,
GncABTransType trans_type);
G_END_DECLS
/** @} */
/** @} */
#endif /* GNC_AB_TRANSFER_H */

View File

@@ -0,0 +1,414 @@
/*
* gnc-ab-utils.c --
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact:
*
* Free Software Foundation Voice: +1-617-542-5942
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
* Boston, MA 02110-1301, USA gnu@gnu.org
*/
/**
* @internal
* @file gnc-ab-utils.c
* @brief AqBanking utility functions
* @author Copyright (C) 2002 Christian Stimming <stimming@tuhh.de>
* @author Copyright (C) 2008 Andreas Koehler <andi5.py@gmx.net>
*/
#include "config.h"
#include <glib/gi18n.h>
#include <gwenhywfar/gwenhywfar.h>
#include <aqbanking/banking.h>
#include "Transaction.h"
#include "gnc-ab-kvp.h"
#include "gnc-ab-utils.h"
#include "gnc-glib-utils.h"
#include "gnc-gwen-gui.h"
#include "import-utilities.h"
#include "qof.h"
/* This static indicates the debugging module that this .o belongs to. */
static QofLogModule log_module = G_LOG_DOMAIN;
/* Global variables for AB_BANKING caching. */
static AB_BANKING *gnc_AB_BANKING = NULL;
static gint gnc_AB_BANKING_refcount = 0;
static gpointer join_ab_strings_cb(const gchar *str, gpointer user_data);
void
gnc_GWEN_Init(void)
{
gint i;
/* Initialize gwen library */
GWEN_Init();
/* Initialize gwen logging */
GWEN_Logger_SetLevel(NULL, GWEN_LoggerLevel_Debug);
GWEN_Logger_SetLevel(GWEN_LOGDOMAIN, GWEN_LoggerLevel_Debug);
GWEN_Logger_SetLevel(AQBANKING_LOGDOMAIN, GWEN_LoggerLevel_Debug);
gnc_GWEN_Gui_log_init();
}
void
gnc_GWEN_Fini(void)
{
/* Shutdown the GWEN_GUIs */
gnc_GWEN_Gui_shutdown();
GWEN_Logger_SetLevel(NULL, GWEN_LoggerLevel_Warning);
GWEN_Logger_SetLevel(GWEN_LOGDOMAIN, GWEN_LoggerLevel_Warning);
GWEN_Logger_SetLevel(AQBANKING_LOGDOMAIN, GWEN_LoggerLevel_Warning);
/* Finalize gwen library */
GWEN_Fini();
}
AB_BANKING *
gnc_AB_BANKING_new(void)
{
AB_BANKING *api;
if (gnc_AB_BANKING) {
/* API cached. */
api = gnc_AB_BANKING;
/* Init the API again. */
if (gnc_AB_BANKING_refcount == 0)
g_return_val_if_fail(AB_Banking_Init(api) == 0, NULL);
} else {
api = AB_Banking_new("gnucash", NULL, 0);
g_return_val_if_fail(api, NULL);
/* Init the API */
g_return_val_if_fail(AB_Banking_Init(api) == 0, NULL);
/* Cache it */
gnc_AB_BANKING = api;
gnc_AB_BANKING_refcount = 0;
}
gnc_AB_BANKING_refcount++;
return api;
}
void
gnc_AB_BANKING_delete(AB_BANKING *api)
{
if (!api)
api = gnc_AB_BANKING;
if (api) {
if (api == gnc_AB_BANKING) {
gnc_AB_BANKING = NULL;
if (gnc_AB_BANKING_refcount > 0)
AB_Banking_Fini(api);
}
AB_Banking_free(api);
}
}
gint
gnc_AB_BANKING_fini(AB_BANKING *api)
{
if (api == gnc_AB_BANKING) {
if (--gnc_AB_BANKING_refcount == 0)
return AB_Banking_Fini(api);
} else {
return AB_Banking_Fini(api);
}
return 0;
}
AB_ACCOUNT *
gnc_ab_get_ab_account(const AB_BANKING *api, Account *gnc_acc)
{
AB_ACCOUNT *ab_account = NULL;
const gchar *bankcode = NULL;
const gchar *accountid = NULL;
guint32 account_uid = 0;
bankcode = gnc_ab_get_account_bankcode(gnc_acc);
accountid = gnc_ab_get_account_accountid(gnc_acc);
account_uid = gnc_ab_get_account_uid (gnc_acc);
if (account_uid > 0) {
ab_account = AB_Banking_GetAccount(api, account_uid);
if (!ab_account && bankcode && *bankcode && accountid && *accountid) {
g_message("gnc_ab_get_ab_account: No AB_ACCOUNT found for UID %d, "
"trying bank code\n", account_uid);
ab_account = AB_Banking_GetAccountByCodeAndNumber(api, bankcode,
accountid);
}
return ab_account;
} else if (bankcode && *bankcode && accountid && *accountid) {
ab_account = AB_Banking_GetAccountByCodeAndNumber(api, bankcode,
accountid);
return ab_account;
}
return NULL;
}
gchar *
gnc_AB_VALUE_to_readable_string(const AB_VALUE *value)
{
if (value)
return g_strdup_printf("%.2f %s",
AB_Value_GetValueAsDouble(value),
AB_Value_GetCurrency(value));
else
return g_strdup_printf("%.2f", 0.0);
}
/**
* Take a string from a GWEN_STRINGLIST, strip invalid utf8 and join it
* to the rest.
*/
static gpointer
join_ab_strings_cb(const gchar *str, gpointer user_data)
{
gchar **acc = user_data;
gchar *tmp;
if (!str || !*str)
return NULL;
tmp = g_strdup(str);
g_strstrip(tmp);
gnc_utf8_strip_invalid(tmp);
if (*acc) {
gchar *join = g_strjoin(" ", *acc, tmp, (gchar*) NULL);
g_free(*acc);
g_free(tmp);
*acc = join;
} else {
*acc = tmp;
}
return NULL;
}
gchar *
gnc_ab_get_remote_name(const AB_TRANSACTION *ab_trans)
{
const GWEN_STRINGLIST *ab_remote_name;
gchar *gnc_other_name = NULL;
g_return_val_if_fail(ab_trans, NULL);
ab_remote_name = AB_Transaction_GetPurpose(ab_trans);
if (ab_remote_name)
GWEN_StringList_ForEach(ab_remote_name, join_ab_strings_cb,
&gnc_other_name);
if (!gnc_other_name || !*gnc_other_name) {
g_free(gnc_other_name);
gnc_other_name = NULL;
}
return gnc_other_name;
}
gchar *
gnc_ab_get_purpose(const AB_TRANSACTION *ab_trans)
{
const GWEN_STRINGLIST *ab_purpose;
gchar *gnc_description = NULL;
g_return_val_if_fail(ab_trans, g_strdup(""));
ab_purpose = AB_Transaction_GetPurpose(ab_trans);
if (ab_purpose)
GWEN_StringList_ForEach(ab_purpose, join_ab_strings_cb,
&gnc_description);
if (!gnc_description)
gnc_description = g_strdup("");
return gnc_description;
}
gchar *
gnc_ab_description_to_gnc(const AB_TRANSACTION *ab_trans)
{
/* Description */
gchar *description = gnc_ab_get_purpose(ab_trans);
gchar *other_name = gnc_ab_get_remote_name(ab_trans);
gchar *retval;
if (other_name) {
if (description && *description) {
retval = g_strdup_printf("%s; %s", description, other_name);
} else {
retval = g_strdup(other_name);
}
} else {
if (description && *description) {
retval = g_strdup(description);
} else {
retval = g_strdup(_("Unspecified"));
}
}
g_free(description);
g_free(other_name);
return retval;
}
gchar *
gnc_ab_memo_to_gnc(const AB_TRANSACTION *ab_trans)
{
const gchar *ab_remote_accountnumber =
AB_Transaction_GetRemoteAccountNumber(ab_trans);
const gchar *ab_remote_bankcode =
AB_Transaction_GetRemoteBankCode(ab_trans);
gchar *ab_other_accountid =
g_strdup(ab_remote_accountnumber ? ab_remote_accountnumber
: _("unknown"));
gchar *ab_other_bankcode =
g_strdup(ab_remote_bankcode ? ab_remote_bankcode
: _("unknown"));
gchar *retval;
g_strstrip(ab_other_accountid);
g_strstrip(ab_other_bankcode);
/* Ensure string is in utf8 */
gnc_utf8_strip_invalid(ab_other_accountid);
gnc_utf8_strip_invalid(ab_other_bankcode);
if (ab_other_accountid && *ab_other_accountid) {
retval = g_strdup_printf("%s %s %s %s",
_("Account"), ab_other_accountid,
_("Bank"), ab_other_bankcode);
} else {
retval = g_strdup("");
}
g_free(ab_other_accountid);
g_free(ab_other_bankcode);
return retval;
}
Transaction *
gnc_ab_trans_to_gnc(const AB_TRANSACTION *ab_trans, Account *gnc_acc)
{
QofBook *book;
Transaction *gnc_trans;
const gchar *fitid;
const GWEN_TIME *valuta_date;
time_t current_time;
const char *custref;
gchar *description;
Split *split;
const AB_VALUE *ab_value;
gnc_numeric gnc_amount;
gchar *memo;
g_return_val_if_fail(ab_trans && gnc_acc, NULL);
/* Create new GnuCash transaction for the given AqBanking one */
book = gnc_account_get_book(gnc_acc);
gnc_trans = xaccMallocTransaction(book);
xaccTransBeginEdit(gnc_trans);
/* Set OFX unique transaction ID */
fitid = AB_Transaction_GetFiId(ab_trans);
if (fitid && *fitid)
gnc_import_set_trans_online_id(gnc_trans, fitid);
/* Date / Time */
valuta_date = AB_Transaction_GetValutaDate(ab_trans);
if (!valuta_date) {
const GWEN_TIME *normal_date = AB_Transaction_GetDate(ab_trans);
if (normal_date)
valuta_date = normal_date;
}
if (valuta_date)
xaccTransSetDateSecs(gnc_trans, GWEN_Time_toTime_t(valuta_date));
else
g_warning("transaction_cb: Oops, date 'valuta_date' was NULL");
current_time = time(NULL);
xaccTransSetDateEnteredSecs(gnc_trans, mktime(localtime(&current_time)));
/* Currency. We take simply the default currency of the gnucash account */
xaccTransSetCurrency(gnc_trans, xaccAccountGetCommodity(gnc_acc));
/* Number. We use the "customer reference", if there is one. */
custref = AB_Transaction_GetCustomerReference(ab_trans);
if (custref && *custref
&& g_ascii_strncasecmp(custref, "NONREF", 6) != 0)
xaccTransSetNum(gnc_trans, custref);
/* Description */
description = gnc_ab_description_to_gnc(ab_trans);
xaccTransSetDescription(gnc_trans, description);
g_free(description);
/* Notes. */
/* xaccTransSetNotes(gnc_trans, g_notes); */
/* But Nobody ever uses the Notes field? */
/* Add one split */
split = xaccMallocSplit(book);
xaccSplitSetParent(split, gnc_trans);
xaccSplitSetAccount(split, gnc_acc);
/* Amount into the split */
ab_value = AB_Transaction_GetValue(ab_trans);
gnc_amount = double_to_gnc_numeric(
ab_value ? AB_Value_GetValueAsDouble(ab_value) : 0.0,
xaccAccountGetCommoditySCU(gnc_acc),
GNC_RND_ROUND);
if (!ab_value)
g_warning("transaction_cb: Oops, value was NULL. Using 0");
xaccSplitSetBaseValue(split, gnc_amount, xaccAccountGetCommodity(gnc_acc));
/* Memo in the Split. */
memo = gnc_ab_memo_to_gnc(ab_trans);
xaccSplitSetMemo(split, memo);
g_free(memo);
return gnc_trans;
}
AB_ACCOUNT_STATUS *
gnc_ab_get_best_accountstatus(AB_IMEXPORTER_ACCOUNTINFO *acc_info)
{
AB_ACCOUNT_STATUS *item, *best = NULL;
const GWEN_TIME *best_time;
g_return_val_if_fail(acc_info, NULL);
item = AB_ImExporterAccountInfo_GetFirstAccountStatus(acc_info);
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);
}
return best;
}

View File

@@ -0,0 +1,174 @@
/*
* gnc-ab-utils.h --
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact:
*
* Free Software Foundation Voice: +1-617-542-5942
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
* Boston, MA 02110-1301, USA gnu@gnu.org
*/
/**
* @addtogroup Import_Export
* @{
* @addtogroup AqBanking
* @{
* @file gnc-ab-utils.h
* @brief AqBanking utility functions
* @author Copyright (C) 2002 Christian Stimming <stimming@tuhh.de>
* @author Copyright (C) 2008 Andreas Koehler <andi5.py@gmx.net>
*/
#ifndef GNC_AB_UTILS_H
#define GNC_AB_UTILS_H
#include <glib.h>
#include <aqbanking/banking.h>
#include "Account.h"
G_BEGIN_DECLS
#define GCONF_SECTION_AQBANKING "dialogs/import/hbci"
#define KEY_FORMAT_SWIFT940 "format_swift_mt940"
#define KEY_FORMAT_SWIFT942 "format_swift_mt942"
#define KEY_FORMAT_DTAUS "format_dtaus"
/**
* Initialize the gwenhywfar library by calling GWEN_Init() and setting up
* gwenhywfar logging.
*/
void gnc_GWEN_Init(void);
/**
* Finalize the gwenhywfar library.
*/
void gnc_GWEN_Fini(void);
/**
* If there is a cached AB_BANKING object, return it initialized. Otherwise,
* create a new AB_BANKING, let it load its environment from its default
* configuration and cache it.
*
* @return The AB_BANKING object
*/
AB_BANKING *gnc_AB_BANKING_new(void);
/**
* Delete the AB_BANKING @a api. If this is also the one that was cached by
* gnc_AB_BANKING_new(), then all references are deleted, too.
*
* @param api AB_BANKING or NULL for the cached AB_BANKING object
*/
void gnc_AB_BANKING_delete(AB_BANKING *api);
/**
* Finish the AB_BANKING @a api. If this is also the one that was cached by
* gnc_AB_BANKING_new(), then finish only if the decremented reference count
* reaches zero. After this call, you may only call gnc_AB_BANKING_new() to get
* the api again in a properly initialized state.
*
* @param api AB_BANKING object
* @return Zero on success
*/
gint gnc_AB_BANKING_fini(AB_BANKING *api);
/**
* Get the corresponding AqBanking account to the GnuCash account @a gnc_acc.
* Of course this only works after the GnuCash account has been set up for
* AqBanking use, i.e. the kvp_frame "hbci/..." has been filled with
* information.
*
* @param api The AB_BANKING to get the AB_ACCOUNT from
* @param gnc_acc The GnuCash account to query for AB_ACCOUNT reference data
* @return The AB_ACCOUNT found or NULL otherwise
*/
AB_ACCOUNT *gnc_ab_get_ab_account(const AB_BANKING *api, Account *gnc_acc);
/**
* Print the value of @a value with two decimal places and @a value's
* currency appended, or 0.0 otherwise
*
* @param value AB_VALUE or NULL
* @return A newly allocated string
*/
gchar *gnc_AB_VALUE_to_readable_string(const AB_VALUE *value);
/**
* Retrieve the merged "remote name" fields from a transaction. The returned
* string must be g_free'd by the caller. If there was no "remote name" field,
* NULL (!) is returned.
*
* @param ab_trans AqBanking transaction
* @return A newly allocated string or NULL otherwise
*/
gchar *gnc_ab_get_remote_name(const AB_TRANSACTION *ab_trans);
/**
* Retrieve the merged purpose fields from a transaction. The returned string
* must be g_free'd by the caller. If there was no purpose, an empty (but
* allocated) string is returned.
*
* @param ab_trans AqBanking transaction
* @return A newly allocated string, may be ""
*/
gchar *gnc_ab_get_purpose(const AB_TRANSACTION *ab_trans);
/**
* Create the appropriate description field for a GnuCash Transaction by the
* information given in the AB_TRANSACTION @a ab_trans. The returned string
* must be g_free'd by the caller.
*
* @param ab_trans AqBanking transaction
* @return A newly allocated string, may be ""
*/
gchar *gnc_ab_description_to_gnc(const AB_TRANSACTION *ab_trans);
/**
* Create the appropriate memo field for a GnuCash Split by the information
* given in the AB_TRANSACTION @a ab_trans. The returned string must be
* g_free'd by the caller.
*
* @param ab_trans AqBanking transaction
* @return A newly allocated string, may be ""
*/
gchar *gnc_ab_memo_to_gnc(const AB_TRANSACTION *ab_trans);
/**
* Create an unbalanced and dirty GnuCash transaction with a split to @a gnc_acc
* from the information available in the AqBanking transaction @a ab_trans.
*
* @param ab_trans AqBanking transaction
* @param gnc_acc Account of to use for the split
* @return A dirty GnuCash transaction or NULL otherwise
*/
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.
*
* @param acc_info ACCOUNTINFO
* @return An AB_ACCOUNT_STATUS internal to @a acc_info, or NULL otherwise
*/
AB_ACCOUNT_STATUS *gnc_ab_get_best_accountstatus(
AB_IMEXPORTER_ACCOUNTINFO *acc_info);
G_END_DECLS
/** @} */
/** @} */
#endif /* GNC_AB_UTILS_H */

View File

@@ -0,0 +1,344 @@
/*
* gnc-file-aqb-import.c --
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact:
*
* Free Software Foundation Voice: +1-617-542-5942
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
* Boston, MA 02110-1301, USA gnu@gnu.org
*/
/**
* @internal
* @file gnc-file-aqb-import.c
* @brief DTAUS import module code
* @author Copyright (C) 2002 Benoit Grégoire <bock@step.polymtl.ca>
* @author Copyright (C) 2003 Jan-Pascal van Best <janpascal@vanbest.org>
* @author Copyright (C) 2006 Florian Steinel
* @author Copyright (C) 2006 Christian Stimming
* @author Copyright (C) 2008 Andreas Koehler <andi5.py@gmx.net>
*/
#include "config.h"
#include <glib/gi18n.h>
#include <glib/gstdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <gwenhywfar/io_file.h>
#include <gwenhywfar/io_buffered.h>
#include <gwenhywfar/iomanager.h>
#include "dialog-ab-trans.h"
#include "gnc-ab-utils.h"
#include "gnc-file.h"
#include "gnc-file-aqb-import.h"
#include "gnc-gwen-gui.h"
#include "gnc-ui.h"
#include "gnc-ui-util.h"
#include "import-account-matcher.h"
#include "import-main-matcher.h"
/* 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,
gboolean execute_transactions)
{
gchar *default_dir;
gchar *selected_filename = NULL;
gint dtaus_fd = -1;
AB_BANKING *api = NULL;
gboolean online = FALSE;
GncGWENGui *gui = NULL;
AB_IMEXPORTER *importer;
GWEN_DB_NODE *db_profiles = NULL;
GWEN_DB_NODE *db_profile;
AB_IMEXPORTER_CONTEXT *context = NULL;
GWEN_IO_LAYER *io, *buffio;
GNCImportMainMatcher *importer_generic_gui = NULL;
AB_JOB_LIST2 *job_list = NULL;
/* Select a file */
default_dir = gnc_get_default_directory(GCONF_SECTION_AQBANKING);
selected_filename = gnc_file_dialog(_("Select a file to import"),
NULL, default_dir,
GNC_FILE_DIALOG_IMPORT);
g_free(default_dir);
if (!selected_filename)
goto cleanup;
DEBUG("filename: %s", selected_filename);
/* Remember the directory as the default */
default_dir = g_path_get_dirname(selected_filename);
gnc_set_default_directory(GCONF_SECTION_AQBANKING, default_dir);
g_free(default_dir);
dtaus_fd = g_open(selected_filename, O_RDONLY, 0);
if (dtaus_fd == -1) {
DEBUG("Could not open file %s", selected_filename);
goto cleanup;
}
/* Get the API */
api = gnc_AB_BANKING_new();
if (!api) {
g_warning("gnc_file_aqbanking_import: Couldn't get AqBanking API");
goto cleanup;
}
if (AB_Banking_OnlineInit(api) != 0) {
g_warning("gnc_file_aqbanking_import: "
"Couldn't initialize AqBanking API");
goto cleanup;
}
online = TRUE;
/* Get a GUI object */
gui = gnc_GWEN_Gui_get(NULL);
if (!gui) {
g_warning("gnc_ab_getbalance: Couldn't initialize Gwenhywfar GUI");
goto cleanup;
}
/* Get import module */
importer = AB_Banking_GetImExporter(api, aqbanking_importername);
if (!importer) {
g_warning("Import module %s not found", aqbanking_importername);
gnc_error_dialog(NULL, "%s",
_("Import module for DTAUS import not found."));
goto cleanup;
}
/* Load the import profile */
db_profiles = AB_Banking_GetImExporterProfiles(api, aqbanking_importername);
/* Select profile */
db_profile = GWEN_DB_GetFirstGroup(db_profiles);
while (db_profile) {
const gchar *name;
name = GWEN_DB_GetCharValue(db_profile, "name", 0, 0);
g_return_if_fail(name);
if (g_ascii_strcasecmp(name, aqbanking_profilename)==0)
break;
db_profile = GWEN_DB_GetNextGroup(db_profile);
}
if (!db_profile) {
g_warning("Profile \"%s\" for importer \"%s\" not found",
aqbanking_profilename, aqbanking_importername);
/* For debugging: Print those available names that have been found */
db_profile = GWEN_DB_GetFirstGroup(db_profiles);
while (db_profile) {
const char *name = GWEN_DB_GetCharValue(db_profile, "name", 0, 0);
g_warning("Only found profile \"%s\"\n", name ? name : "(null)");
db_profile = GWEN_DB_GetNextGroup(db_profile);
}
goto cleanup;
}
/* Create a context to store the results */
context = AB_ImExporterContext_new();
/* Wrap file in buffered gwen io */
io = GWEN_Io_LayerFile_new(dtaus_fd, -1);
dtaus_fd = -1;
buffio = GWEN_Io_LayerBuffered_new(io);
if (GWEN_Io_Manager_RegisterLayer(buffio)) {
g_warning("gnc_file_aqbanking_import: Failed to wrap file");
goto cleanup;
}
/* Run the import */
if (AB_ImExporter_Import(importer, context, buffio, db_profile, 0)) {
g_warning("gnc_file_aqbanking_import: Error on import");
goto cleanup;
}
/* 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 transactions from the context into gnucash */
job_list = import_context(api, context, importer_generic_gui,
execute_transactions);
if (execute_transactions) {
if (gnc_gen_trans_list_run(importer_generic_gui)) {
/* FIXME */
/* gnc_hbci_multijob_execute(NULL, api, job_list, gui); */
}
}
cleanup:
if (job_list)
AB_Job_List2_free(job_list);
if (importer_generic_gui)
gnc_gen_trans_list_delete(importer_generic_gui);
if (context)
AB_ImExporterContext_free(context);
if (db_profiles)
GWEN_DB_Group_free(db_profiles);
if (gui)
gnc_GWEN_Gui_release(gui);
if (online)
AB_Banking_OnlineFini(api);
if (api)
gnc_AB_BANKING_fini(api);
if (dtaus_fd != -1)
close(dtaus_fd);
if (selected_filename)
g_free(selected_filename);
}

View File

@@ -0,0 +1,69 @@
/*
* gnc-file-aqb-import.h --
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact:
*
* Free Software Foundation Voice: +1-617-542-5942
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
* Boston, MA 02110-1301, USA gnu@gnu.org
*/
/**
* @addtogroup Import_Export
* @{
* @addtogroup AqBanking
* @{
* @file gnc-file-aqb-import.h
* @brief DTAUS import module interface
* @author Copyright (C) 2002 Benoit Grégoire <bock@step.polymtl.ca>
* @author Copyright (C) 2008 Andreas Koehler <andi5.py@gmx.net>
*/
#ifndef GNC_FILE_AQB_IMPORT_H
#define GNC_FILE_AQB_IMPORT_H
#include <glib.h>
G_BEGIN_DECLS
/**
* This routine will pop up a standard file selection dialog asking the user to
* pick a file to import. This file will be opened and read. Its contents will
* be imported into the current book, using the import matcher from
* import-main-matcher.h.
*
* @param aqbanking_importername The aqbanking importer module that should be
* used. Possible values: "dtaus", "csv", "swift", or more.
*
* @param aqbanking_formatname In aqbanking, each importer has one or more data
* formats available which define the actual data fields that should be used.
* In aqbanking, such a different format is called a "profile". Possible values
* for swift: "swift-mt940" or "swift-mt942", but for all others: "default", or
* more precisely: Look into $datadir/aqbanking/imexporters and look into the
* "name" field of the foo.conf files.
*
* @param exec_as_aqbanking_jobs If TRUE, additionally queue the imported
* transactions as online jobs over aqbanking/HBCI. If FALSE, just import the
* transactions and that's it.
*/
void gnc_file_aqbanking_import (const gchar *aqbanking_importername,
const gchar *aqbanking_formatname,
gboolean exec_as_aqbanking_jobs);
G_END_DECLS
/** @} */
/** @} */
#endif /* GNC_FILE_AQB_IMPORT_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,80 @@
/*
* gnc-gwen-gui.h --
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact:
*
* Free Software Foundation Voice: +1-617-542-5942
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
* Boston, MA 02110-1301, USA gnu@gnu.org
*/
/**
* @addtogroup Import_Export
* @{
* @addtogroup AqBanking
* @{
* @file gnc-gwen-gui.h
* @brief GUI callbacks for AqBanking
* @author Copyright (C) 2002 Christian Stimming <stimming@tuhh.de>
* @author Copyright (C) 2008 Andreas Koehler <andi5.py@gmx.net>
*/
#ifndef GNC_GWEN_GUI_H
#define GNC_GWEN_GUI_H
#include <gtk/gtk.h>
G_BEGIN_DECLS
typedef struct _GncGWENGui GncGWENGui;
/**
* Hook our logging into the gwenhywfar logging framework by creating a
* minimalistic GWEN_GUI with only a callback for Gwen_Gui_LogHook(). This
* function can be called more than once, it will unref and replace the
* currently set GWEN_GUI though.
*/
void gnc_GWEN_Gui_log_init(void);
/**
* When called for the first time, create a unique GncGWENGui object featuring a
* GWEN_GUI with all necessary callbacks, which can serve as a user interface
* for AqBanking jobs. On later calls, return the object only when it is not
* active and save to use. Typically, you only need to call
* gnc_GWEN_Gui_release() once your job has finished.
*
* @param parent Widget to set new dialogs transient for, may be NULL
* @return The unique GncGWENGui object or NULL otherwise
*/
GncGWENGui *gnc_GWEN_Gui_get(GtkWidget *parent);
/**
* Currently a no-op. The GncGWENGui will not be freed and it is considered
* finished once the first tracked progress has ended.
*
* @param gui The GncGwenGUI returned by gnc_GWEN_Gui_get()
*/
void gnc_GWEN_Gui_release(GncGWENGui *gui);
/**
* Free all memory related to both the full-blown and minimalistic GUI objects.
*/
void gnc_GWEN_Gui_shutdown(void);
G_END_DECLS
/** @} */
/** @} */
#endif /* GNC_GWEN_GUI_H */

View File

@@ -0,0 +1,34 @@
<ui>
<menubar>
<menu name="File" action="FileAction">
<menu name="FileImport" action="FileImportAction">
<placeholder name="FileImportPlaceholder">
<menuitem name="FileMt940Import" action="Mt940ImportAction"/>
<menuitem name="FileMt942Import" action="Mt942ImportAction"/>
<menuitem name="FileDtausImport" action="DtausImportAction"/>
<menuitem name="FileDtausImportsend" action="DtausImportSendAction"/>
<!-- When CsvImport works:
<menuitem name="FileCsvImport" action="CsvImportAction"/>
<menuitem name="FileCsvImportsend" action="CsvImportSendAction"/>
-->
</placeholder>
</menu>
</menu>
<menu name="Actions" action="ActionsAction">
<placeholder name="ActionsPlaceholder">
<menu name="OnlineActions" action="OnlineActionsAction">
<menuitem name="ABGetBalance" action="ABGetBalanceAction"/>
<menuitem name="ABGetTrans" action="ABGetTransAction"/>
<menuitem name="ABIssueTrans" action="ABIssueTransAction"/>
<menuitem name="ABIssueIntTrans" action="ABIssueIntTransAction"/>
<menuitem name="ABIssueDirectDebit" action="ABIssueDirectDebitAction"/>
</menu>
</placeholder>
</menu>
<menu name="Tools" action="ToolsAction">
<placeholder name="ToolsPlaceholder">
<menuitem name="ABSetup" action="ABSetupAction"/>
</placeholder>
</menu>
</menubar>
</ui>

View File

@@ -0,0 +1,472 @@
/*
* gnc-plugin-aqbanking.c --
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact:
*
* Free Software Foundation Voice: +1-617-542-5942
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
* Boston, MA 02110-1301, USA gnu@gnu.org
*/
/**
* @internal
* @file gnc-plugin-aqbanking.c
* @brief Plugin registration of the AqBanking module
* @author Copyright (C) 2002 Christian Stimming <stimming@tuhh.de>
* @author Copyright (C) 2003 David Hampton <hampton@employees.org>
* @author Copyright (C) 2008 Andreas Koehler <andi5.py@gmx.net>
*/
#include "config.h"
#include <glib/gi18n.h>
#include "Account.h"
#include "dialog-ab-trans.h"
#include "druid-ab-initial.h"
#include "gnc-ab-getbalance.h"
#include "gnc-ab-gettrans.h"
#include "gnc-ab-transfer.h"
#include "gnc-ab-utils.h"
#include "gnc-file-aqb-import.h"
#include "gnc-gconf-utils.h"
#include "gnc-plugin-aqbanking.h"
#include "gnc-plugin-manager.h"
#include "gnc-plugin-page-account-tree.h"
#include "gnc-plugin-page-register.h"
/* This static indicates the debugging module that this .o belongs to. */
static QofLogModule log_module = G_LOG_DOMAIN;
static void gnc_plugin_aqbanking_class_init(GncPluginAqBankingClass *klass);
static void gnc_plugin_aqbanking_init(GncPluginAqBanking *plugin);
static void gnc_plugin_aqbanking_add_to_window(GncPlugin *plugin, GncMainWindow *window, GQuark type);
static void gnc_plugin_aqbanking_remove_from_window(GncPlugin *plugin, GncMainWindow *window, GQuark type);
/* Object callbacks */
static void gnc_plugin_ab_main_window_page_added(GncMainWindow *window, GncPluginPage *page, gpointer user_data);
static void gnc_plugin_ab_main_window_page_changed(GncMainWindow *window, GncPluginPage *page, gpointer user_data);
static void gnc_plugin_ab_account_selected(GncPluginPage *plugin_page, Account *account, gpointer user_data);
/* Auxiliary functions */
static Account *main_window_to_account(GncMainWindow *window);
/* Command callbacks */
static void gnc_plugin_ab_cmd_setup(GtkAction *action, GncMainWindowActionData *data);
static void gnc_plugin_ab_cmd_get_balance(GtkAction *action, GncMainWindowActionData *data);
static void gnc_plugin_ab_cmd_get_transactions(GtkAction *action, GncMainWindowActionData *data);
static void gnc_plugin_ab_cmd_issue_transaction(GtkAction *action, GncMainWindowActionData *data);
static void gnc_plugin_ab_cmd_issue_inttransaction(GtkAction *action, GncMainWindowActionData *data);
static void gnc_plugin_ab_cmd_issue_direct_debit(GtkAction *action, GncMainWindowActionData *data);
static void gnc_plugin_ab_cmd_mt940_import(GtkAction *action, GncMainWindowActionData *data);
static void gnc_plugin_ab_cmd_mt942_import(GtkAction *action, GncMainWindowActionData *data);
static void gnc_plugin_ab_cmd_dtaus_import(GtkAction *action, GncMainWindowActionData *data);
static void gnc_plugin_ab_cmd_dtaus_importsend(GtkAction *action, GncMainWindowActionData *data);
#define PLUGIN_ACTIONS_NAME "gnc-plugin-aqbanking-actions"
#define PLUGIN_UI_FILENAME "gnc-plugin-aqbanking-ui.xml"
static GtkActionEntry gnc_plugin_actions [] = {
/* Menus */
{ "OnlineActionsAction", NULL, N_("_Online Actions"), NULL, NULL, NULL },
/* Menu Items */
{ "ABSetupAction", NULL, N_("_Online Banking Setup..."), NULL,
N_("Initial setup of Online Banking access (HBCI, or OFX DirectConnect, using AqBanking)"),
G_CALLBACK(gnc_plugin_ab_cmd_setup) },
{ "ABGetBalanceAction", NULL, N_("Get _Balance"), NULL,
N_("Get the account balance online through Online Banking"),
G_CALLBACK(gnc_plugin_ab_cmd_get_balance) },
{ "ABGetTransAction", NULL, N_("Get _Transactions..."), NULL,
N_("Get the transactions online through Online Banking"),
G_CALLBACK(gnc_plugin_ab_cmd_get_transactions) },
{ "ABIssueTransAction", NULL, N_("_Issue Transaction..."), NULL,
N_("Issue a new transaction online through Online Banking"),
G_CALLBACK(gnc_plugin_ab_cmd_issue_transaction) },
{ "ABIssueIntTransAction", NULL, N_("I_nternal Transaction..."), NULL,
N_("Issue a new bank-internal transaction online through Online Banking"),
G_CALLBACK(gnc_plugin_ab_cmd_issue_inttransaction) },
{ "ABIssueDirectDebitAction", NULL, N_("_Direct Debit..."), NULL,
N_("Issue a new direct debit note online through Online Banking"),
G_CALLBACK(gnc_plugin_ab_cmd_issue_direct_debit) },
/* File -> Import menu item */
{ "Mt940ImportAction", GTK_STOCK_CONVERT, N_("Import _MT940"), NULL,
N_("Import a MT940 file into GnuCash"),
G_CALLBACK(gnc_plugin_ab_cmd_mt940_import) },
{ "Mt942ImportAction", GTK_STOCK_CONVERT, N_("Import MT94_2"), NULL,
N_("Import a MT942 file into GnuCash"),
G_CALLBACK(gnc_plugin_ab_cmd_mt942_import) },
{ "DtausImportAction", GTK_STOCK_CONVERT, N_("Import _DTAUS"), NULL,
N_("Import a DTAUS file into GnuCash"),
G_CALLBACK(gnc_plugin_ab_cmd_dtaus_import) },
/* #ifdef CSV_IMPORT_FUNCTIONAL */
/* { "CsvImportAction", GTK_STOCK_CONVERT, N_("Import _CSV"), NULL, */
/* N_("Import a CSV file into GnuCash"), */
/* G_CALLBACK(gnc_plugin_ab_cmd_csv_import) }, */
/* { "CsvImportSendAction", GTK_STOCK_CONVERT, N_("Import CSV and s_end..."), NULL, */
/* N_("Import a CSV file into GnuCash and send the transfers online through Online Banking"), */
/* G_CALLBACK(gnc_plugin_ab_cmd_csv_importsend) }, */
/* #endif */
{ "DtausImportSendAction", GTK_STOCK_CONVERT, N_("Import DTAUS and _send..."), NULL,
N_("Import a DTAUS file into GnuCash and send the transfers online through Online Banking"),
G_CALLBACK(gnc_plugin_ab_cmd_dtaus_importsend) },
};
static guint gnc_plugin_n_actions = G_N_ELEMENTS(gnc_plugin_actions);
static const gchar *need_account_actions[] = {
"ABGetBalanceAction",
"ABGetTransAction",
"ABIssueTransAction",
"ABIssueIntTransAction",
"ABIssueDirectDebitAction",
NULL
};
/************************************************************
* Object Implementation *
************************************************************/
G_DEFINE_TYPE(GncPluginAqBanking, gnc_plugin_aqbanking, GNC_TYPE_PLUGIN)
GncPlugin *
gnc_plugin_aqbanking_new(void)
{
return GNC_PLUGIN(g_object_new(GNC_TYPE_PLUGIN_AQBANKING, (gchar*) NULL));
}
static void
gnc_plugin_aqbanking_class_init(GncPluginAqBankingClass *klass)
{
GncPluginClass *plugin_class = GNC_PLUGIN_CLASS(klass);
/* plugin info */
plugin_class->plugin_name = GNC_PLUGIN_AQBANKING_NAME;
/* widget addition/removal */
plugin_class->actions_name = PLUGIN_ACTIONS_NAME;
plugin_class->actions = gnc_plugin_actions;
plugin_class->n_actions = gnc_plugin_n_actions;
plugin_class->ui_filename = PLUGIN_UI_FILENAME;
plugin_class->add_to_window = gnc_plugin_aqbanking_add_to_window;
plugin_class->remove_from_window = gnc_plugin_aqbanking_remove_from_window;
}
static void
gnc_plugin_aqbanking_init(GncPluginAqBanking *plugin)
{
}
/**
* Called when this plugin is added to a main window. Connect a few callbacks
* here to track page changes.
*/
static void
gnc_plugin_aqbanking_add_to_window(GncPlugin *plugin, GncMainWindow *window,
GQuark type)
{
g_signal_connect(window, "page_added",
G_CALLBACK(gnc_plugin_ab_main_window_page_added),
plugin);
g_signal_connect(window, "page_changed",
G_CALLBACK(gnc_plugin_ab_main_window_page_changed),
plugin);
}
static void
gnc_plugin_aqbanking_remove_from_window(GncPlugin *plugin, GncMainWindow *window,
GQuark type)
{
g_signal_handlers_disconnect_by_func(
window, G_CALLBACK(gnc_plugin_ab_main_window_page_changed), plugin);
g_signal_handlers_disconnect_by_func(
window, G_CALLBACK(gnc_plugin_ab_main_window_page_added), plugin);
}
/************************************************************
* Object Callbacks *
************************************************************/
/**
* A new page has been added to a main window. Connect a signal to it so that
* we can track when accounts are selected.
*/
static void
gnc_plugin_ab_main_window_page_added(GncMainWindow *window, GncPluginPage *page,
gpointer user_data)
{
const gchar *page_name;
ENTER("main window %p, page %p", window, page);
if (!GNC_IS_PLUGIN_PAGE(page)) {
LEAVE("no plugin_page");
return;
}
page_name = gnc_plugin_page_get_plugin_name(page);
if (!page_name) {
LEAVE("no page_name of plugin_page");
return;
}
if (strcmp(page_name, GNC_PLUGIN_PAGE_ACCOUNT_TREE_NAME) == 0) {
DEBUG("account tree page, adding signal");
g_signal_connect(page, "account_selected",
G_CALLBACK(gnc_plugin_ab_account_selected), NULL);
}
LEAVE(" ");
}
/**
* Whenever the current page has changed, update the aqbanking menus based upon
* the page that is currently selected.
*/
static void
gnc_plugin_ab_main_window_page_changed(GncMainWindow *window,
GncPluginPage *page, gpointer user_data)
{
}
/**
* An account had been (de)selected in an "account tree" page. Update the hbci
* menus appropriately.
*/
static void
gnc_plugin_ab_account_selected(GncPluginPage *plugin_page, Account *account,
gpointer user_data)
{
GtkActionGroup *action_group;
GncMainWindow *window;
g_return_if_fail(GNC_IS_PLUGIN_PAGE(plugin_page));
window = GNC_MAIN_WINDOW(plugin_page->window);
g_return_if_fail(GNC_IS_MAIN_WINDOW(window));
action_group = gnc_main_window_get_action_group(window, PLUGIN_ACTIONS_NAME);
g_return_if_fail(GTK_IS_ACTION_GROUP(action_group));
gnc_plugin_update_actions(action_group, need_account_actions,
"sensitive", account != NULL);
}
/************************************************************
* Auxiliary Functions *
************************************************************/
/**
* Given a pointer to a main window, try and extract an Account from it. If the
* current page is an "account tree" page, get the account corresponding to the
* selected account. (What if multiple accounts are selected?) If the current
* page is a "register" page, get the head account for the register. (Returns
* NULL for a general ledger or search register.)
*
* @param window A pointer to a GncMainWindow object.
* @return A pointer to an account, if one can be determined from the current
* page. NULL otherwise.
*/
static Account *
main_window_to_account(GncMainWindow *window)
{
GncPluginPage *page;
const gchar *page_name;
Account *account = NULL;
const gchar *account_name;
ENTER("main window %p", window);
if (!GNC_IS_MAIN_WINDOW(window)) {
LEAVE("no main_window");
return NULL;
}
page = gnc_main_window_get_current_page(window);
if (!GNC_IS_PLUGIN_PAGE(page)) {
LEAVE("no plugin_page");
return NULL;
}
page_name = gnc_plugin_page_get_plugin_name(page);
if (!page_name) {
LEAVE("no page_name of plugin_page");
return NULL;
}
if (strcmp(page_name, GNC_PLUGIN_PAGE_REGISTER_NAME) == 0) {
DEBUG("register page");
account = gnc_plugin_page_register_get_account(
GNC_PLUGIN_PAGE_REGISTER(page));
} else if (strcmp(page_name, GNC_PLUGIN_PAGE_ACCOUNT_TREE_NAME) == 0) {
DEBUG("account tree page");
account = gnc_plugin_page_account_tree_get_current_account(
GNC_PLUGIN_PAGE_ACCOUNT_TREE(page));
} else {
account = NULL;
}
account_name = account ? xaccAccountGetName(account) : NULL;
LEAVE("account %s(%p)", account_name ? account_name : "(null)", account);
return account;
}
/************************************************************
* Command Callbacks *
************************************************************/
static void
gnc_plugin_ab_cmd_setup(GtkAction *action, GncMainWindowActionData *data)
{
ENTER("action %p, main window data %p", action, data);
gnc_ab_initial_druid();
LEAVE(" ");
}
static void
gnc_plugin_ab_cmd_get_balance(GtkAction *action, GncMainWindowActionData *data)
{
Account *account;
ENTER("action %p, main window data %p", action, data);
account = main_window_to_account(data->window);
if (account == NULL) {
g_message("No AqBanking account selected");
LEAVE("no account");
return;
}
gnc_ab_getbalance(GTK_WIDGET(data->window), account);
LEAVE(" ");
}
static void
gnc_plugin_ab_cmd_get_transactions(GtkAction *action,
GncMainWindowActionData *data)
{
Account *account;
ENTER("action %p, main window data %p", action, data);
account = main_window_to_account(data->window);
if (account == NULL) {
g_message("No AqBanking account selected");
LEAVE("no account");
return;
}
gnc_ab_gettrans(GTK_WIDGET(data->window), account);
LEAVE(" ");
}
static void
gnc_plugin_ab_cmd_issue_transaction(GtkAction *action,
GncMainWindowActionData *data)
{
Account *account;
ENTER("action %p, main window data %p", action, data);
account = main_window_to_account(data->window);
if (account == NULL) {
g_message("No AqBanking account selected");
LEAVE("no account");
return;
}
gnc_ab_maketrans(GTK_WIDGET(data->window), account, SINGLE_TRANSFER);
LEAVE(" ");
}
static void
gnc_plugin_ab_cmd_issue_inttransaction(GtkAction *action,
GncMainWindowActionData *data)
{
Account *account;
ENTER("action %p, main window data %p", action, data);
account = main_window_to_account(data->window);
if (account == NULL) {
g_message("No AqBanking account selected");
LEAVE("no account");
return;
}
gnc_ab_maketrans(GTK_WIDGET(data->window), account,
SINGLE_INTERNAL_TRANSFER);
LEAVE(" ");
}
static void
gnc_plugin_ab_cmd_issue_direct_debit(GtkAction *action,
GncMainWindowActionData *data)
{
Account *account;
ENTER("action %p, main window data %p", action, data);
account = main_window_to_account(data->window);
if (account == NULL) {
g_message("No AqBanking account selected");
LEAVE("no account");
return;
}
gnc_ab_maketrans(GTK_WIDGET(data->window), account, SINGLE_DEBITNOTE);
LEAVE(" ");
}
static void
gnc_plugin_ab_cmd_mt940_import(GtkAction *action, GncMainWindowActionData *data)
{
gchar *format = gnc_gconf_get_string(GCONF_SECTION_AQBANKING,
KEY_FORMAT_SWIFT940, NULL);
gnc_file_aqbanking_import("swift", format ? format : "swift-mt940", FALSE);
g_free(format);
}
static void
gnc_plugin_ab_cmd_mt942_import(GtkAction *action, GncMainWindowActionData *data)
{
gchar *format = gnc_gconf_get_string(GCONF_SECTION_AQBANKING,
KEY_FORMAT_SWIFT942, NULL);
gnc_file_aqbanking_import("swift", format ? format : "swift-mt942", FALSE);
g_free(format);
}
static void
gnc_plugin_ab_cmd_dtaus_import(GtkAction *action, GncMainWindowActionData *data)
{
gchar *format = gnc_gconf_get_string(GCONF_SECTION_AQBANKING,
KEY_FORMAT_DTAUS, NULL);
gnc_file_aqbanking_import("dtaus", format ? format : "default", FALSE);
g_free(format);
}
static void
gnc_plugin_ab_cmd_dtaus_importsend(GtkAction *action,
GncMainWindowActionData *data)
{
gchar *format = gnc_gconf_get_string(GCONF_SECTION_AQBANKING,
KEY_FORMAT_DTAUS, NULL);
gnc_file_aqbanking_import("dtaus", format ? format : "default", TRUE);
g_free(format);
}
/************************************************************
* Plugin Bootstrapping *
************************************************************/
void
gnc_plugin_aqbanking_create_plugin(void)
{
GncPlugin *plugin = gnc_plugin_aqbanking_new();
gnc_plugin_manager_add_plugin(gnc_plugin_manager_get(), plugin);
}

View File

@@ -0,0 +1,83 @@
/*
* gnc-plugin-aqbanking.h --
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact:
*
* Free Software Foundation Voice: +1-617-542-5942
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
* Boston, MA 02110-1301, USA gnu@gnu.org
*/
/**
* @addtogroup Import_Export
* @{
* @addtogroup AqBanking
* @{
* @file gnc-plugin-aqbanking.h
* @brief Plugin registration of the AqBanking module
* @author Copyright (C) 2003 David Hampton <hampton@employees.org>
* @author Copyright (C) 2008 Andreas Koehler <andi5.py@gmx.net>
*/
#ifndef GNC_PLUGIN_AQBANKING_H
#define GNC_PLUGIN_AQBANKING_H
#include <glib.h>
#include "gnc-plugin.h"
G_BEGIN_DECLS
/* type macros */
#define GNC_TYPE_PLUGIN_AQBANKING (gnc_plugin_aqbanking_get_type())
#define GNC_PLUGIN_AQBANKING(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GNC_TYPE_PLUGIN_AQBANKING, GncPluginAqBanking))
#define GNC_PLUGIN_AQBANKING_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GNC_TYPE_PLUGIN_AQBANKING, GncPluginAqBankingClass))
#define GNC_IS_PLUGIN_AQBANKING(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GNC_TYPE_PLUGIN_AQBANKING))
#define GNC_IS_PLUGIN_AQBANKING_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GNC_TYPE_PLUGIN_AQBANKING))
#define GNC_PLUGIN_AQBANKING_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GNC_TYPE_PLUGIN_AQBANKING, GncPluginAqBankingClass))
#define GNC_PLUGIN_AQBANKING_NAME "gnc-plugin-aqbanking"
/* typedefs & structures */
typedef struct {
GncPlugin gnc_plugin;
} GncPluginAqBanking;
typedef struct {
GncPluginClass gnc_plugin;
} GncPluginAqBankingClass;
/* function prototypes */
/**
* @return The glib runtime type of an aqbanking plugin page
**/
GType gnc_plugin_aqbanking_get_type(void);
/**
* @return A new GncPluginAqBanking object
*/
GncPlugin* gnc_plugin_aqbanking_new(void);
/**
* Create a new GncPluginAqBanking object and register it.
*/
void gnc_plugin_aqbanking_create_plugin(void);
G_END_DECLS
/** @} */
/** @} */
#endif /* GNC_PLUGIN_AQBANKING_H */

View File

@@ -0,0 +1,91 @@
/*
* gncmod-aqbanking.c --
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact:
*
* Free Software Foundation Voice: +1-617-542-5942
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
* Boston, MA 02110-1301, USA gnu@gnu.org
*/
/**
* @internal
* @file gncmod-aqbanking.c
* @brief Module definition/initialization for AqBanking support
* @author Copyright (C) 2002 Christian Stimming <stimming@tuhh.de>
* @author Copyright (C) 2008 Andreas Koehler <andi5.py@gmx.net>
*/
#include "config.h"
#include "gnc-ab-utils.h"
#include "gnc-module.h"
#include "gnc-module-api.h"
#include "gnc-plugin-aqbanking.h"
#include "dialog-preferences.h"
GNC_MODULE_API_DECL(libgncmod_aqbanking)
/* version of the gnc module system interface we require */
gint libgncmod_aqbanking_gnc_module_system_interface = 0;
/* module versioning uses libtool semantics. */
gint libgncmod_aqbanking_gnc_module_current = 0;
gint libgncmod_aqbanking_gnc_module_revision = 0;
gint libgncmod_aqbanking_gnc_module_age = 0;
gchar *
libgncmod_aqbanking_gnc_module_path(void)
{
return g_strdup("gnucash/import-export/aqbanking");
}
gchar *
libgncmod_aqbanking_gnc_module_description(void) {
return g_strdup("Support for Online Banking protocols");
}
gint
libgncmod_aqbanking_gnc_module_init(gint refcount)
{
/* Load modules we depend on */
if(!gnc_module_load("gnucash/engine", 0)
|| !gnc_module_load("gnucash/app-utils", 0)
|| !gnc_module_load("gnucash/gnome-utils", 0)
|| !gnc_module_load("gnucash/import-export", 0)) {
return FALSE;
}
/* Add menu items with C callbacks */
gnc_plugin_aqbanking_create_plugin();
gnc_preferences_add_to_page("aqbanking.glade", "aqbanking_prefs",
"Online Banking");
/* Initialize gwen library */
gnc_GWEN_Init();
return 1;
}
gint
libgncmod_aqbanking_gnc_module_end(gint refcount) {
/* Delete the shared AB_BANKING object */
gnc_AB_BANKING_delete(NULL);
/* Finalize gwen library */
gnc_GWEN_Fini();
return 1;
}

View File

@@ -0,0 +1,21 @@
schemadir = @GCONF_SCHEMA_FILE_DIR@
schemas_in_files = \
apps_gnucash_dialog_hbci.schemas.in
schema_DATA = $(schemas_in_files:.schemas.in=.schemas)
@INTLTOOL_SCHEMAS_RULE@
EXTRA_DIST = $(schemas_in_files)
CLEANFILES = $(schema_DATA)
install-data-local:
if GCONF_SCHEMAS_INSTALL
-mkdir -p $(DESTDIR)$(GCONF_SCHEMA_CONFIG_SOURCE_DIRONLY)
GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-install-rule $(schema_DATA)
endif
uninstall-local:
if GCONF_SCHEMAS_INSTALL
GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-uninstall-rule $(schema_DATA)
endif

View File

@@ -0,0 +1,143 @@
<?xml version="1.0"?>
<gconfschemafile>
<schemalist>
<schema>
<key>/schemas/apps/gnucash/dialogs/import/hbci/position</key>
<applyto>/apps/gnucash/dialogs/import/hbci/connection_dialog/window_position</applyto>
<owner>gnucash</owner>
<type>list</type>
<list_type>int</list_type>
<locale name="C">
<short>Window position</short>
<long>
The X,Y coordinates of the top left corner of the dialog
when it was last closed.
</long>
</locale>
</schema>
<schema>
<key>/schemas/apps/gnucash/dialogs/import/hbci/geometry</key>
<applyto>/apps/gnucash/dialogs/import/hbci/connection_dialog/window_geometry</applyto>
<owner>gnucash</owner>
<type>list</type>
<list_type>int</list_type>
<locale name="C">
<short>Window geometry</short>
<long>
The width and size of the dialog when it was last closed.
</long>
</locale>
</schema>
<schema>
<key>/schemas/apps/gnucash/dialogs/import/hbci/close_on_finish</key>
<applyto>/apps/gnucash/dialogs/import/hbci/close_on_finish</applyto>
<owner>gnucash</owner>
<type>bool</type>
<default>True</default>
<locale name="C">
<short>Close dialog when finished</short>
<long>
If active, the window will be closed automatically when you
finish the HBCI/AqBanking import process. Otherwise it will
stay open.
</long>
</locale>
</schema>
<schema>
<key>/schemas/apps/gnucash/dialogs/import/hbci/remember_pin</key>
<applyto>/apps/gnucash/dialogs/import/hbci/remember_pin</applyto>
<owner>gnucash</owner>
<type>bool</type>
<default>False</default>
<locale name="C">
<short>Remember the PIN in memory</short>
<long>If active, the PIN for HBCI/AqBanking actions will be
remembered in memory during a session. Otherwise it will have
to be entered again each time during a session when it is
needed.</long>
</locale>
</schema>
<schema>
<key>/schemas/apps/gnucash/dialogs/import/hbci/verbose_debug</key>
<applyto>/apps/gnucash/dialogs/import/hbci/verbose_debug</applyto>
<owner>gnucash</owner>
<type>bool</type>
<default>False</default>
<locale name="C">
<short>Verbose HBCI debug messages</short>
<long>Enables verbose debug messages for HBCI/AqBanking Online Banking.</long>
</locale>
</schema>
<schema>
<key>/schemas/apps/gnucash/dialogs/import/hbci/format_dtaus</key>
<applyto>/apps/gnucash/dialogs/import/hbci/format_dtaus</applyto>
<owner>gnucash</owner>
<type>string</type>
<default>default</default>
<locale name="C">
<short>DTAUS import data format</short>
<long>
This setting specifies the data format when importing DTAUS
files. The AqBanking library offers various import formats
(called "profiles") of which you can choose one here.
</long>
</locale>
</schema>
<schema>
<key>/schemas/apps/gnucash/dialogs/import/hbci/format_csv</key>
<applyto>/apps/gnucash/dialogs/import/hbci/format_csv</applyto>
<owner>gnucash</owner>
<type>string</type>
<default>default</default>
<locale name="C">
<short>CSV import data format</short>
<long>
This setting specifies the data format when importing CSV
files. The AqBanking library offers various import formats
(called "profiles") of which you can choose one here.
</long>
</locale>
</schema>
<schema>
<key>/schemas/apps/gnucash/dialogs/import/hbci/format_swift_mt940</key>
<applyto>/apps/gnucash/dialogs/import/hbci/format_swift_mt940</applyto>
<owner>gnucash</owner>
<type>string</type>
<default>swift-mt940</default>
<locale name="C">
<short>SWIFT MT940 import data format</short>
<long>
This setting specifies the data format when importing SWIFT
MT940 files. The AqBanking library offers various import
formats (called "profiles") of which you can choose one here.
</long>
</locale>
</schema>
<schema>
<key>/schemas/apps/gnucash/dialogs/import/hbci/format_swift_mt942</key>
<applyto>/apps/gnucash/dialogs/import/hbci/format_swift_mt942</applyto>
<owner>gnucash</owner>
<type>string</type>
<default>swift-mt942</default>
<locale name="C">
<short>SWIFT MT942 import data format</short>
<long>
This setting specifies the data format when importing SWIFT
MT942 files. The AqBanking library offers various import
formats (called "profiles") of which you can choose one here.
</long>
</locale>
</schema>
</schemalist>
</gconfschemafile>

View File

@@ -56,7 +56,7 @@ libgncmod_hbci_la_LIBADD = \
${GLADE_LIBS} \
${QOF_LIBS} \
${GLIB_LIBS} \
${HBCI_LIBS}
${AQBANKING_LIBS}
AM_CFLAGS = \
-I${top_srcdir}/src \
@@ -77,7 +77,7 @@ AM_CFLAGS = \
${GLADE_CFLAGS} \
${QOF_CFLAGS} \
${GLIB_CFLAGS} \
${HBCI_CFLAGS}
${AQBANKING_CFLAGS}
#gladedir = $(GNC_GLADE_DIR)
#glade_DATA =