GnuCash 2.4.99
gnc-file-aqb-import.c
00001 /*
00002  * gnc-file-aqb-import.c --
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of
00007  * the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, contact:
00016  *
00017  * Free Software Foundation           Voice:  +1-617-542-5942
00018  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652
00019  * Boston, MA  02110-1301,  USA       gnu@gnu.org
00020  */
00021 
00033 #include "config.h"
00034 
00035 #include <glib/gi18n.h>
00036 #include <glib/gstdio.h>
00037 #include <fcntl.h>
00038 #include <unistd.h>
00039 
00040 #include "gnc-ab-utils.h"
00041 
00042 #ifdef AQBANKING_VERSION_5_PLUS
00043 # include <gwenhywfar/syncio_file.h>
00044 # include <gwenhywfar/syncio_buffered.h>
00045 typedef GWEN_SYNCIO GWEN_IO_LAYER;
00046 #else
00047 # include <gwenhywfar/io_file.h>
00048 # include <gwenhywfar/io_buffered.h>
00049 # include <gwenhywfar/iomanager.h>
00050 #endif
00051 
00052 #include "dialog-ab-trans.h"
00053 #include "gnc-file.h"
00054 #include "gnc-file-aqb-import.h"
00055 #include "gnc-gwen-gui.h"
00056 #include "gnc-ui.h"
00057 #include "gnc-ui-util.h"
00058 #include "import-account-matcher.h"
00059 #include "import-main-matcher.h"
00060 
00061 /* This static indicates the debugging module that this .o belongs to.  */
00062 static QofLogModule log_module = GNC_MOD_IMPORT;
00063 
00064 void
00065 gnc_file_aqbanking_import(const gchar *aqbanking_importername,
00066                           const gchar *aqbanking_profilename,
00067                           gboolean execute_transactions)
00068 {
00069     gchar *default_dir;
00070     gchar *selected_filename = NULL;
00071     gint dtaus_fd = -1;
00072     AB_BANKING *api = NULL;
00073     gboolean online = FALSE;
00074     GncGWENGui *gui = NULL;
00075     AB_IMEXPORTER *importer;
00076     GWEN_DB_NODE *db_profiles = NULL;
00077     GWEN_DB_NODE *db_profile;
00078     AB_IMEXPORTER_CONTEXT *context = NULL;
00079     GWEN_IO_LAYER *io = NULL;
00080     GncABImExContextImport *ieci = NULL;
00081     AB_JOB_LIST2 *job_list = NULL;
00082     AB_JOB_LIST2_ITERATOR *jit;
00083     AB_JOB *job;
00084     AB_JOB_STATUS job_status;
00085     gboolean successful = TRUE;
00086     int num_jobs = 0;
00087     int num_jobs_failed = 0;
00088     int max_failures = 5;
00089     GString *errstr = NULL;
00090 
00091     /* Select a file */
00092     default_dir = gnc_get_default_directory(GCONF_SECTION_AQBANKING);
00093     selected_filename = gnc_file_dialog(_("Select a file to import"),
00094                                         NULL, default_dir,
00095                                         GNC_FILE_DIALOG_IMPORT);
00096     g_free(default_dir);
00097 
00098     if (!selected_filename)
00099         goto cleanup;
00100     DEBUG("filename: %s", selected_filename);
00101 
00102     /* Remember the directory as the default */
00103     default_dir = g_path_get_dirname(selected_filename);
00104     gnc_set_default_directory(GCONF_SECTION_AQBANKING, default_dir);
00105     g_free(default_dir);
00106 
00107     dtaus_fd = g_open(selected_filename, O_RDONLY, 0);
00108     if (dtaus_fd == -1)
00109     {
00110         DEBUG("Could not open file %s", selected_filename);
00111         goto cleanup;
00112     }
00113 
00114     /* Get the API */
00115     api = gnc_AB_BANKING_new();
00116     if (!api)
00117     {
00118         g_warning("gnc_file_aqbanking_import: Couldn't get AqBanking API");
00119         goto cleanup;
00120     }
00121     if (AB_Banking_OnlineInit(api
00122 #ifdef AQBANKING_VERSION_4_EXACTLY
00123                               , 0
00124 #endif
00125                              ) != 0)
00126     {
00127         g_warning("gnc_file_aqbanking_import: "
00128                   "Couldn't initialize AqBanking API");
00129         goto cleanup;
00130     }
00131     online = TRUE;
00132 
00133     /* Get import module */
00134     importer = AB_Banking_GetImExporter(api, aqbanking_importername);
00135     if (!importer)
00136     {
00137         g_warning("Import module %s not found", aqbanking_importername);
00138         gnc_error_dialog(NULL, "%s",
00139                          _("Import module for DTAUS import not found."));
00140         goto cleanup;
00141     }
00142 
00143     /* Load the import profile */
00144     db_profiles = AB_Banking_GetImExporterProfiles(api, aqbanking_importername);
00145 
00146     /* Select profile */
00147     db_profile = GWEN_DB_GetFirstGroup(db_profiles);
00148     while (db_profile)
00149     {
00150         const gchar *name;
00151 
00152         name = GWEN_DB_GetCharValue(db_profile, "name", 0, 0);
00153         g_return_if_fail(name);
00154         if (g_ascii_strcasecmp(name, aqbanking_profilename) == 0)
00155             break;
00156         db_profile = GWEN_DB_GetNextGroup(db_profile);
00157     }
00158     if (!db_profile)
00159     {
00160         g_warning("Profile \"%s\" for importer \"%s\" not found",
00161                   aqbanking_profilename, aqbanking_importername);
00162         /* For debugging: Print those available names that have been found */
00163         db_profile = GWEN_DB_GetFirstGroup(db_profiles);
00164         while (db_profile)
00165         {
00166             const char *name = GWEN_DB_GetCharValue(db_profile, "name", 0, 0);
00167             g_warning("Only found profile \"%s\"\n", name ? name : "(null)");
00168             db_profile = GWEN_DB_GetNextGroup(db_profile);
00169         }
00170         goto cleanup;
00171     }
00172 
00173     /* Create a context to store the results */
00174     context = AB_ImExporterContext_new();
00175 
00176     /* Wrap file in buffered gwen io */
00177 #ifdef AQBANKING_VERSION_5_PLUS
00178     close(dtaus_fd);
00179     io = GWEN_SyncIo_File_new(selected_filename, GWEN_SyncIo_File_CreationMode_OpenExisting);
00180     g_assert(io);
00181     GWEN_SyncIo_AddFlags(io, GWEN_SYNCIO_FILE_FLAGS_READ);
00182     {
00183         /* We must explicitly call "Connect" on the GWEN_SYNCIO
00184          * object. */
00185         int rv = GWEN_SyncIo_Connect(io);
00186         if (rv < 0)
00187         {
00188             g_warning("gnc_file_aqbanking_import: Failed to open file %s: %d", selected_filename, rv);
00189             goto cleanup;
00190         }
00191         g_assert(GWEN_SyncIo_GetStatus(io) == GWEN_SyncIo_Status_Connected);
00192     }
00193 #else
00194     io = GWEN_Io_LayerFile_new(dtaus_fd, -1);
00195     g_assert(io);
00196     if (GWEN_Io_Manager_RegisterLayer(io))
00197     {
00198         g_warning("gnc_file_aqbanking_import: Failed to wrap file");
00199         goto cleanup;
00200     }
00201 #endif
00202     dtaus_fd = -1;
00203 
00204     /* Run the import */
00205     if (AB_ImExporter_Import(importer, context, io, db_profile
00206 #ifndef AQBANKING_VERSION_5_PLUS
00207                              , 0
00208 #endif
00209                             ))
00210     {
00211         g_warning("gnc_file_aqbanking_import: Error on import");
00212         goto cleanup;
00213     }
00214 
00215     /* Close the file */
00216 #ifdef AQBANKING_VERSION_5_PLUS
00217     GWEN_SyncIo_free(io);
00218 #else
00219     GWEN_Io_Layer_free(io);
00220 #endif
00221     io = NULL;
00222 
00223     /* Import the results */
00224     ieci = gnc_ab_import_context(context, AWAIT_TRANSACTIONS,
00225                                  execute_transactions,
00226                                  execute_transactions ? api : NULL,
00227                                  NULL);
00228 
00229     if (execute_transactions)
00230     {
00231         if (gnc_ab_ieci_run_matcher(ieci))
00232         {
00233             AB_IMEXPORTER_CONTEXT *execution_context;
00234 
00235             /* Extract the list of jobs */
00236             job_list = gnc_ab_ieci_get_job_list(ieci);
00237 
00238             /* Create a context to store possible results */
00239             execution_context = AB_ImExporterContext_new();
00240 
00241             /* Get a GUI object */
00242             gui = gnc_GWEN_Gui_get(NULL);
00243             if (!gui)
00244             {
00245                 g_warning("gnc_file_aqbanking_import: Couldn't initialize Gwenhywfar GUI");
00246                 goto cleanup;
00247             }
00248 
00249             /* And execute the jobs */
00250             AB_Banking_ExecuteJobs(api, job_list, execution_context
00251 #ifndef AQBANKING_VERSION_5_PLUS
00252                                    , 0
00253 #endif
00254                                   );
00255 
00256             /* Ignore the return value of AB_Banking_ExecuteJobs(), as the job's
00257              * status always describes better whether the job was actually
00258              * transferred to and accepted by the bank.  See also
00259              * http://lists.gnucash.org/pipermail/gnucash-de/2008-September/006389.html
00260              */
00261 
00262             /* So we must go through all jobs and check AB_Job_GetStatus(job)
00263              * to give the appropriate feedback if any of the jobs didn't
00264              * work. */
00265 
00266             jit = AB_Job_List2_First(job_list);
00267             if (jit)
00268             {
00269 
00270                 job = AB_Job_List2Iterator_Data(jit);
00271                 while (job)
00272                 {
00273                     num_jobs += 1;
00274                     job_status = AB_Job_GetStatus(job);
00275                     if (job_status != AB_Job_StatusFinished
00276                             && job_status != AB_Job_StatusPending)
00277                     {
00278                         successful = FALSE;
00279                         num_jobs_failed += 1;
00280 
00281                         if (num_jobs_failed <= max_failures)
00282                         {
00283                             if (num_jobs_failed == 1)
00284                             {
00285                                 errstr = g_string_new("Failed jobs:\n");
00286                             }
00287                             g_string_append_printf(errstr, _("Job %d status %d - %s: %s \n")
00288                                                    , num_jobs
00289                                                    , job_status
00290                                                    , AB_Job_Status2Char(job_status)
00291                                                    , AB_Job_GetResultText(job));
00292                         }
00293                         else
00294                         {
00295                             if (num_jobs_failed == (max_failures + 1) )
00296                             {
00297                                 /* indicate that additional failures exist */
00298                                 g_string_append(errstr, _("...\n"));
00299                             }
00300                         }
00301                     }
00302                     job = AB_Job_List2Iterator_Next(jit);
00303                 } /* while */
00304 
00305                 AB_Job_List2Iterator_free(jit);
00306             }
00307 
00308             if (!successful)
00309             {
00310                 g_warning("%s", errstr->str);
00311                 gnc_error_dialog(NULL,
00312                                  _("An error occurred while executing jobs: %d of %d failed. "
00313                                    "Please check the log window or gnucash.trace for the exact "
00314                                    "error message.\n\n%s")
00315                                  , num_jobs_failed, num_jobs, errstr->str);
00316             }
00317             else
00318             {
00319                 if (num_jobs == 0)
00320                 {
00321                     gnc_info_dialog(NULL,
00322                                     _("No jobs to be send.")
00323                                    );
00324                 }
00325                 else
00326                 {
00327                     gnc_info_dialog(NULL, ngettext
00328                                     ("The job was executed successfully, but as a precaution "
00329                                      "please check the log window for potential errors.",
00330                                      "All %d jobs were executed successfully, but as a precaution "
00331                                      "please check the log window for potential errors.",
00332                                      num_jobs), num_jobs);
00333                 }
00334             }
00335             AB_ImExporterContext_free(execution_context);
00336         }
00337     }
00338 
00339 cleanup:
00340     if (io)
00341     {
00342 #ifdef AQBANKING_VERSION_5_PLUS
00343         GWEN_SyncIo_free(io);
00344 #else
00345         GWEN_Io_Layer_free(io);
00346 #endif
00347     }
00348 
00349     if (job_list)
00350         AB_Job_List2_FreeAll(job_list);
00351     if (ieci)
00352         g_free(ieci);
00353     if (context)
00354         AB_ImExporterContext_free(context);
00355     if (db_profiles)
00356         GWEN_DB_Group_free(db_profiles);
00357     if (gui)
00358         gnc_GWEN_Gui_release(gui);
00359     if (online)
00360 #ifdef AQBANKING_VERSION_4_EXACTLY
00361         AB_Banking_OnlineFini(api, 0);
00362 #else
00363         AB_Banking_OnlineFini(api);
00364 #endif
00365     if (api)
00366         gnc_AB_BANKING_fini(api);
00367     if (dtaus_fd != -1)
00368         close(dtaus_fd);
00369     if (selected_filename)
00370         g_free(selected_filename);
00371     if (errstr)
00372         g_string_free(errstr, TRUE);
00373 
00374 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines