1 /*
2 * gnc-ab-utils.c --
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of
7 * the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, contact:
16 *
17 * Free Software Foundation Voice: +1-617-542-5942
18 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
19 * Boston, MA 02110-1301, USA gnu@gnu.org
20 */
21
22 /**
23 * @internal
24 * @file gnc-ab-utils.c
25 * @brief AqBanking utility functions
26 * @author Copyright (C) 2002 Christian Stimming <stimming@tuhh.de>
27 * @author Copyright (C) 2008 Andreas Koehler <andi5.py@gmx.net>
28 */
29
30 #include <config.h>
31
32 #include "gnc-ab-utils.h"
33
34 #include <glib/gi18n.h>
35 #include <gwenhywfar/gwenhywfar.h>
36 #include <aqbanking/banking.h>
37 #ifdef AQBANKING6
38 #include <aqbanking/types/balance.h>
39 #if (AQBANKING_VERSION_INT >= 60400)
40 #include <aqbanking/types/refaccount.h>
41 #include <gnc-aqbanking-templates.h>
42 #endif
43 #endif
44 #include "window-reconcile.h"
45 #include "Transaction.h"
46 #include "dialog-ab-trans.h"
47 #include "gnc-ab-kvp.h"
48 #include "gnc-glib-utils.h"
49 #include "gnc-gwen-gui.h"
50 #include "gnc-prefs.h"
51 #include "gnc-ui.h"
52 #include "import-account-matcher.h"
53 #include "import-main-matcher.h"
54 #include "import-utilities.h"
55 #include "qof.h"
56 #include "engine-helpers.h"
57 #ifdef AQBANKING6
58 # include <aqbanking/gui/abgui.h>
59 #else
60 # include <aqbanking/abgui.h>
61 #endif
62
63 /* This static indicates the debugging module that this .o belongs to. */
64 G_GNUC_UNUSED static QofLogModule log_module = G_LOG_DOMAIN;
65
66 /* Global variables for AB_BANKING caching. */
67 static AB_BANKING *gnc_AB_BANKING = NULL;
68 static gint gnc_AB_BANKING_refcount = 0;
69
70 static gpointer join_ab_strings_cb(const gchar *str, gpointer user_data);
71 static Account *gnc_ab_accinfo_to_gnc_acc(GtkWidget *parent,
72 AB_IMEXPORTER_ACCOUNTINFO *account_info);
73 static Account *gnc_ab_txn_to_gnc_acc(GtkWidget *parent,
74 const AB_TRANSACTION *transaction);
75 static const AB_TRANSACTION *txn_transaction_cb(
76 const AB_TRANSACTION *element, gpointer user_data);
77 static AB_IMEXPORTER_ACCOUNTINFO *txn_accountinfo_cb(
78 AB_IMEXPORTER_ACCOUNTINFO *element, gpointer user_data);
79 static AB_IMEXPORTER_ACCOUNTINFO *bal_accountinfo_cb(
80 AB_IMEXPORTER_ACCOUNTINFO *element, gpointer user_data);
81
82 struct _GncABImExContextImport
83 {
84 guint awaiting;
85 gboolean txn_found;
86 Account *gnc_acc;
87 GNC_AB_ACCOUNT_SPEC *ab_acc;
88 gboolean execute_txns;
89 AB_BANKING *api;
90 GtkWidget *parent;
91 GNC_AB_JOB_LIST2 *job_list;
92 GNCImportMainMatcher *generic_importer;
93 GData *tmp_job_list;
94 };
95
96 static inline time64
gnc_gwen_date_to_time64(const GNC_GWEN_DATE * date)97 gnc_gwen_date_to_time64 (const GNC_GWEN_DATE* date)
98 {
99 #if AQBANKING_VERSION_INT >= 59900
100 return gnc_dmy2time64_neutral(GWEN_Date_GetDay(date),
101 GWEN_Date_GetMonth(date),
102 GWEN_Date_GetYear(date));
103 #else
104 int month, day, year;
105 GWEN_Time_GetBrokenDownDate(date, &day, &month, &year);
106 /* GWEN_Time_GetBrokenDownDate returns localtime(3) format; month is [0..11] */
107 return gnc_dmy2time64_neutral(day, month + 1, year);
108 #endif
109 }
110
111 void
gnc_GWEN_Init(void)112 gnc_GWEN_Init(void)
113 {
114 gchar* gwen_logging = g_strdup(g_getenv("GWEN_LOGLEVEL"));
115 gchar* aqb_logging = g_strdup(g_getenv("AQBANKING_LOGLEVEL"));
116
117 /* Initialize gwen library */
118 GWEN_Init();
119
120 /* Initialize gwen logging */
121 if (gnc_prefs_get_bool(GNC_PREFS_GROUP_AQBANKING, GNC_PREF_VERBOSE_DEBUG))
122 {
123 if (!gwen_logging)
124 {
125 GWEN_Logger_SetLevel(NULL, GWEN_LoggerLevel_Info);
126 GWEN_Logger_SetLevel(GWEN_LOGDOMAIN, GWEN_LoggerLevel_Info);
127 }
128 if (!aqb_logging)
129 GWEN_Logger_SetLevel(AQBANKING_LOGDOMAIN, GWEN_LoggerLevel_Debug);
130 }
131 else
132 {
133 if (!gwen_logging)
134 {
135 GWEN_Logger_SetLevel(NULL, GWEN_LoggerLevel_Error);
136 GWEN_Logger_SetLevel(GWEN_LOGDOMAIN, GWEN_LoggerLevel_Error);
137 }
138 if (!aqb_logging)
139 GWEN_Logger_SetLevel(AQBANKING_LOGDOMAIN, GWEN_LoggerLevel_Warning);
140 }
141 g_free(gwen_logging);
142 g_free(aqb_logging);
143 gnc_GWEN_Gui_log_init();
144 }
145
146 void
gnc_GWEN_Fini(void)147 gnc_GWEN_Fini(void)
148 {
149 /* Shutdown the GWEN_GUIs */
150 gnc_GWEN_Gui_shutdown();
151 GWEN_Logger_SetLevel(NULL, GWEN_LoggerLevel_Error);
152 GWEN_Logger_SetLevel(GWEN_LOGDOMAIN, GWEN_LoggerLevel_Warning);
153 GWEN_Logger_SetLevel(AQBANKING_LOGDOMAIN, GWEN_LoggerLevel_Warning);
154
155 /* Finalize gwen library */
156 GWEN_Fini();
157 }
158
159 static GWEN_GUI *gnc_gwengui_extended_by_ABBanking;
160
161 AB_BANKING *
gnc_AB_BANKING_new(void)162 gnc_AB_BANKING_new(void)
163 {
164 AB_BANKING *api;
165
166 if (gnc_AB_BANKING)
167 {
168 /* API cached. */
169 api = gnc_AB_BANKING;
170
171 /* Init the API again. */
172 if (gnc_AB_BANKING_refcount == 0)
173 g_return_val_if_fail(AB_Banking_Init(api) == 0, NULL);
174
175 }
176 else
177 {
178 api = AB_Banking_new("gnucash", NULL, 0);
179 g_return_val_if_fail(api, NULL);
180
181 #if AQBANKING_VERSION_INT >= 59925 \
182 || (AQBANKING_VERSION_INT >= 50709 && AQBANKING_VERSION_INT < 59900)
183 /* These two values must be set because newest bank regulation requires
184 the bank servers to require it. The string itself results from our
185 registration with the German bank association at
186 https://www.hbci-zka.de/register/prod_register.htm (where the
187 registration was requested and is managed by cstim). The function call was
188 introduced in aqbanking-5.99.25 and aqbanking-5.7.9. */
189 AB_Banking_RuntimeConfig_SetCharValue(api, "fintsRegistrationKey", "412748A1836CDD07181CE1910");
190 AB_Banking_RuntimeConfig_SetCharValue(api, "fintsApplicationVersionString", PROJECT_VERSION);
191 #endif
192
193 #ifndef AQBANKING6
194 /* Check for config migration */
195 if (AB_Banking_HasConf4(api) != 0)
196 {
197 if (AB_Banking_HasConf3(api) == 0)
198 {
199 PINFO("gnc_AB_BANKING_new: importing aqbanking3 configuration\n");
200 if (AB_Banking_ImportConf3(api) < 0)
201 {
202 PINFO("gnc_AB_BANKING_new: unable to import aqbanking3 configuration\n");
203 }
204 }
205 else if (AB_Banking_HasConf2(api) == 0)
206 {
207 PINFO("gnc_AB_BANKING_new: importing aqbanking2 configuration\n");
208 if (AB_Banking_ImportConf2(api) < 0)
209 {
210 PINFO("gnc_AB_BANKING_new: unable to import aqbanking2 configuration\n");
211 }
212 }
213 }
214 #endif
215
216 /* Init the API */
217 g_return_val_if_fail(AB_Banking_Init(api) == 0, NULL);
218 gnc_gwengui_extended_by_ABBanking = GWEN_Gui_GetGui();
219 AB_Gui_Extend(gnc_gwengui_extended_by_ABBanking, api);
220
221 /* Cache it */
222 gnc_AB_BANKING = api;
223 gnc_AB_BANKING_refcount = 0;
224 }
225
226 gnc_AB_BANKING_refcount++;
227
228 return api;
229 }
230
231 void
gnc_AB_BANKING_delete(AB_BANKING * api)232 gnc_AB_BANKING_delete(AB_BANKING *api)
233 {
234 if (!api)
235 api = gnc_AB_BANKING;
236
237 if (api)
238 {
239 if (api == gnc_AB_BANKING)
240 {
241 gnc_AB_BANKING = NULL;
242 gnc_AB_BANKING_fini(api);
243 }
244
245 AB_Banking_free(api);
246 }
247 }
248
249
250 gint
gnc_AB_BANKING_fini(AB_BANKING * api)251 gnc_AB_BANKING_fini(AB_BANKING *api)
252 {
253 if (api == gnc_AB_BANKING)
254 {
255 if (--gnc_AB_BANKING_refcount == 0)
256 {
257 if (gnc_gwengui_extended_by_ABBanking)
258 AB_Gui_Unextend(gnc_gwengui_extended_by_ABBanking);
259 gnc_gwengui_extended_by_ABBanking = NULL;
260 return AB_Banking_Fini(api);
261 }
262 }
263 else
264 {
265 if (gnc_gwengui_extended_by_ABBanking)
266 AB_Gui_Unextend(gnc_gwengui_extended_by_ABBanking);
267 gnc_gwengui_extended_by_ABBanking = NULL;
268 return AB_Banking_Fini(api);
269 }
270 return 0;
271 }
272
273 GNC_AB_ACCOUNT_SPEC *
gnc_ab_get_ab_account(const AB_BANKING * api,Account * gnc_acc)274 gnc_ab_get_ab_account(const AB_BANKING *api, Account *gnc_acc)
275 {
276 GNC_AB_ACCOUNT_SPEC *ab_account = NULL;
277 const gchar *bankcode = NULL;
278 const gchar *accountid = NULL;
279 guint32 account_uid = 0;
280
281 bankcode = gnc_ab_get_account_bankcode(gnc_acc);
282 accountid = gnc_ab_get_account_accountid(gnc_acc);
283 account_uid = gnc_ab_get_account_uid (gnc_acc);
284
285 if (account_uid > 0)
286 {
287 #ifdef AQBANKING6
288 gint rv;
289
290 rv = AB_Banking_GetAccountSpecByUniqueId(api, account_uid, &ab_account);
291
292 if ( (rv<0 || !ab_account) && bankcode && *bankcode &&
293 accountid && *accountid)
294 {
295 /* Finding the account by code and number is suspended in AQBANKING 6 pending
296 * implementation of a replacement for AB_Banking_GetAccountByCodeAndNumber.
297 */
298 PINFO("gnc_ab_get_ab_account: No AB_ACCOUNT found for UID %d, "
299 "trying bank code\n", account_uid);
300 return NULL;
301 }
302 return ab_account;
303 #else
304 ab_account = AB_Banking_GetAccount(api, account_uid);
305
306 if (!ab_account && bankcode && *bankcode && accountid && *accountid)
307 {
308 PINFO("gnc_ab_get_ab_account: No AB_ACCOUNT found for UID %d, "
309 "trying bank code\n", account_uid);
310 ab_account = AB_Banking_GetAccountByCodeAndNumber(api, bankcode,
311 accountid);
312 }
313 return ab_account;
314
315 }
316 else if (bankcode && *bankcode && accountid && *accountid)
317 {
318 ab_account = AB_Banking_GetAccountByCodeAndNumber(api, bankcode,
319 accountid);
320 return ab_account;
321 #endif
322 }
323
324 return NULL;
325 }
326
327 gchar *
gnc_AB_VALUE_to_readable_string(const AB_VALUE * value)328 gnc_AB_VALUE_to_readable_string(const AB_VALUE *value)
329 {
330 if (value)
331 return g_strdup_printf("%.2f %s",
332 AB_Value_GetValueAsDouble(value),
333 AB_Value_GetCurrency(value));
334 else
335 return g_strdup_printf("%.2f", 0.0);
336 }
337
338
339 gchar*
gnc_ab_create_online_id(const gchar * bankcode,const gchar * accountnumber)340 gnc_ab_create_online_id(const gchar *bankcode, const gchar *accountnumber)
341 {
342 gchar *online_id;
343
344 /* The accountnumber may have leading zeros, depending on where them
345 * accountnumber is came from, e.g. the accountnumber of accountinfo
346 * has no leading zeros while the (local)accountnumber of a transaction
347 * has leading zeros.
348 * So remove all leading '0', to get a consistent online_id.
349 */
350 while (accountnumber && *accountnumber == '0')
351 accountnumber++;
352
353 online_id = g_strconcat(bankcode ? bankcode : "",
354 accountnumber ? accountnumber : "",
355 (gchar*)NULL);
356
357 return online_id;
358 }
359
360 /**
361 * Take a string from a GWEN_STRINGLIST, strip invalid utf8 and join it
362 * to the rest.
363 */
364 static gpointer
join_ab_strings_cb(const gchar * str,gpointer user_data)365 join_ab_strings_cb(const gchar *str, gpointer user_data)
366 {
367 gchar **acc = user_data;
368 gchar *tmp;
369
370 if (!str || !*str)
371 return NULL;
372
373 tmp = g_strdup(str);
374 g_strstrip(tmp);
375 gnc_utf8_strip_invalid_and_controls(tmp);
376
377 if (*acc)
378 {
379 gchar *join = g_strjoin(" ", *acc, tmp, (gchar*) NULL);
380 g_free(*acc);
381 g_free(tmp);
382 *acc = join;
383 }
384 else
385 {
386 *acc = tmp;
387 }
388 return NULL;
389 }
390
391 gchar *
gnc_ab_get_remote_name(const AB_TRANSACTION * ab_trans)392 gnc_ab_get_remote_name(const AB_TRANSACTION *ab_trans)
393 {
394 #ifdef AQBANKING6
395 const char* ab_remote_name;
396 #else
397 const GWEN_STRINGLIST *ab_remote_name;
398 #endif
399 gchar *gnc_other_name = NULL;
400
401 g_return_val_if_fail(ab_trans, NULL);
402
403 ab_remote_name = AB_Transaction_GetRemoteName(ab_trans);
404 if (ab_remote_name)
405 #ifdef AQBANKING6
406 gnc_other_name = g_strdup(ab_remote_name);
407 #else
408 GWEN_StringList_ForEach(ab_remote_name, join_ab_strings_cb,
409 &gnc_other_name);
410 #endif
411 if (!gnc_other_name || !*gnc_other_name)
412 {
413 g_free(gnc_other_name);
414 gnc_other_name = NULL;
415 }
416
417 return gnc_other_name;
418 }
419
420 gchar *
gnc_ab_get_purpose(const AB_TRANSACTION * ab_trans,gboolean is_ofx)421 gnc_ab_get_purpose(const AB_TRANSACTION *ab_trans, gboolean is_ofx)
422 {
423 #ifdef AQBANKING6
424 # if AQBANKING_VERSION_INT < 59929
425 # error "You are using an old beta version of aqbanking > 5.99.0 but < 5.99.29, please upgrade to the latest 5.99.29 or newer."
426 # endif
427 #else
428 const /* only const in aqbanking < 5.99 */
429 #endif
430 GWEN_STRINGLIST *ab_purpose;
431 const char *ab_transactionText = NULL;
432 gchar *gnc_description = NULL;
433
434 g_return_val_if_fail(ab_trans, g_strdup(""));
435
436 if (!is_ofx && gnc_prefs_get_bool(GNC_PREFS_GROUP_AQBANKING, GNC_PREF_USE_TRANSACTION_TXT))
437 {
438 /* According to AqBanking, some of the non-swift lines have a special
439 * meaning. Some banks place valuable text into the transaction text,
440 * hence we put this text in front of the purpose. */
441 ab_transactionText = AB_Transaction_GetTransactionText(ab_trans);
442 if (ab_transactionText)
443 gnc_description = g_strdup(ab_transactionText);
444 }
445
446 ab_purpose =
447 #ifdef AQBANKING6
448 /* With aqbanking-5.99.29, the identical function as before is now available under this new name. */
449 AB_Transaction_GetPurposeAsStringList
450 #else
451 AB_Transaction_GetPurpose
452 #endif
453 (ab_trans);
454 if (ab_purpose)
455 GWEN_StringList_ForEach(ab_purpose, join_ab_strings_cb,
456 &gnc_description);
457
458 #ifdef AQBANKING6
459 /* With aqbanking>=5.99, the return value must now be free'd */
460 GWEN_StringList_free(ab_purpose);
461 #endif
462
463 if (!gnc_description)
464 gnc_description = g_strdup("");
465
466 return gnc_description;
467 }
468
469 gchar *
gnc_ab_description_to_gnc(const AB_TRANSACTION * ab_trans,gboolean is_ofx)470 gnc_ab_description_to_gnc(const AB_TRANSACTION *ab_trans, gboolean is_ofx)
471 {
472 /* Description */
473 gchar *description = gnc_ab_get_purpose(ab_trans, is_ofx);
474 gchar *other_name = gnc_ab_get_remote_name(ab_trans);
475 gchar *retval;
476
477 if (other_name)
478 {
479 if (description && *description)
480 {
481 retval = g_strdup_printf("%s; %s", description, other_name);
482 }
483 else
484 {
485 retval = g_strdup(other_name);
486 }
487 }
488 else
489 {
490 if (description && *description)
491 {
492 retval = g_strdup(description);
493 }
494 else
495 {
496 retval = g_strdup(_("Unspecified"));
497 }
498 }
499 g_free(description);
500 g_free(other_name);
501
502 return retval;
503 }
504
505 gchar *
gnc_ab_memo_to_gnc(const AB_TRANSACTION * ab_trans)506 gnc_ab_memo_to_gnc(const AB_TRANSACTION *ab_trans)
507 {
508 const gchar *ab_remote_accountnumber =
509 AB_Transaction_GetRemoteAccountNumber(ab_trans);
510 const gchar *ab_remote_bankcode =
511 AB_Transaction_GetRemoteBankCode(ab_trans);
512
513 gchar *ab_other_accountid;
514 gchar *ab_other_bankcode;
515
516 gboolean have_accountid;
517 gboolean have_bankcode;
518
519 gchar *retval;
520
521 // For SEPA transactions, we need to ask for something different here
522 if (!ab_remote_accountnumber)
523 ab_remote_accountnumber = AB_Transaction_GetRemoteIban(ab_trans);
524 if (!ab_remote_bankcode)
525 ab_remote_bankcode = AB_Transaction_GetRemoteBic(ab_trans);
526
527 ab_other_accountid = g_strdup(ab_remote_accountnumber ? ab_remote_accountnumber : "");
528 ab_other_bankcode = g_strdup(ab_remote_bankcode ? ab_remote_bankcode : "");
529
530 /* Ensure string is in utf8 */
531 gnc_utf8_strip_invalid(ab_other_accountid);
532 gnc_utf8_strip_invalid(ab_other_bankcode);
533
534 /* and -then- trim it */
535 g_strstrip(ab_other_accountid);
536 g_strstrip(ab_other_bankcode);
537
538
539 have_accountid = ab_other_accountid && *ab_other_accountid;
540 have_bankcode = ab_other_bankcode && *ab_other_bankcode;
541
542 if ( have_accountid || have_bankcode )
543 {
544 retval = g_strdup_printf("%s %s %s %s",
545 have_accountid ? _("Account") : "",
546 have_accountid ? ab_other_accountid : "",
547 have_bankcode ? _("Bank") : "",
548 have_bankcode ? ab_other_bankcode : ""
549 );
550 g_strstrip(retval);
551 }
552 else
553 {
554 retval = g_strdup("");
555 }
556
557 g_free(ab_other_accountid);
558 g_free(ab_other_bankcode);
559
560 return retval;
561 }
562
563 Transaction *
gnc_ab_trans_to_gnc(const AB_TRANSACTION * ab_trans,Account * gnc_acc)564 gnc_ab_trans_to_gnc(const AB_TRANSACTION *ab_trans, Account *gnc_acc)
565 {
566 QofBook *book;
567 Transaction *gnc_trans;
568 const gchar *fitid;
569 const GNC_GWEN_DATE *valuta_date;
570 time64 current_time;
571 const char *custref;
572 gchar *description;
573 Split *split;
574 gchar *memo;
575
576 g_return_val_if_fail(ab_trans && gnc_acc, NULL);
577
578 /* Create new GnuCash transaction for the given AqBanking one */
579 book = gnc_account_get_book(gnc_acc);
580 gnc_trans = xaccMallocTransaction(book);
581 xaccTransBeginEdit(gnc_trans);
582
583 /* Date / Time */
584 valuta_date = AB_Transaction_GetValutaDate(ab_trans);
585 if (!valuta_date)
586 {
587 const GNC_GWEN_DATE *normal_date = AB_Transaction_GetDate(ab_trans);
588 if (normal_date)
589 valuta_date = normal_date;
590 }
591 if (valuta_date)
592 {
593 time64 secs = gnc_gwen_date_to_time64(valuta_date);
594 xaccTransSetDatePostedSecsNormalized(gnc_trans, secs);
595 }
596 else
597 {
598 g_warning("transaction_cb: Oops, date 'valuta_date' was NULL");
599 }
600 xaccTransSetDateEnteredSecs(gnc_trans, gnc_time (NULL));
601
602 /* Currency. We take simply the default currency of the gnucash account */
603 xaccTransSetCurrency(gnc_trans, xaccAccountGetCommodity(gnc_acc));
604
605 /* Trans-Num or Split-Action set with gnc_set_num_action below per book
606 * option */
607
608 fitid = AB_Transaction_GetFiId(ab_trans);
609
610 /* Description */
611 description = gnc_ab_description_to_gnc(ab_trans, (fitid && *fitid));
612 xaccTransSetDescription(gnc_trans, description);
613 g_free(description);
614
615 /* Notes. */
616 /* xaccTransSetNotes(gnc_trans, g_notes); */
617 /* But Nobody ever uses the Notes field? */
618
619 /* Add one split */
620 split = xaccMallocSplit(book);
621 xaccSplitSetParent(split, gnc_trans);
622 xaccSplitSetAccount(split, gnc_acc);
623
624 /* Set the transaction number or split action field based on book option.
625 * We use the "customer reference", if there is one. */
626 custref = AB_Transaction_GetCustomerReference(ab_trans);
627 if (custref && *custref
628 && g_ascii_strncasecmp(custref, "NONREF", 6) != 0)
629 gnc_set_num_action (gnc_trans, split, custref, NULL);
630
631 /* Set OFX unique transaction ID */
632 if (fitid && *fitid)
633 gnc_import_set_split_online_id(split, fitid);
634
635 /* FIXME: Extract function */
636 {
637 /* Amount into the split */
638 const AB_VALUE *ab_value = AB_Transaction_GetValue(ab_trans);
639 double d_value = ab_value ? AB_Value_GetValueAsDouble (ab_value) : 0.0;
640 AB_TRANSACTION_TYPE ab_type = AB_Transaction_GetType (ab_trans);
641 gnc_numeric gnc_amount;
642
643 /*printf("Transaction with value %f has type %d\n", d_value, ab_type);*/
644 /* If the value is positive, but the transaction type says the
645 money is transferred away from our account (Transfer instead of
646 DebitNote), we switch the value to negative. */
647 if (d_value > 0.0 && ab_type == AB_Transaction_TypeTransfer)
648 d_value = -d_value;
649
650 gnc_amount = double_to_gnc_numeric(
651 d_value,
652 xaccAccountGetCommoditySCU(gnc_acc),
653 GNC_HOW_RND_ROUND_HALF_UP);
654 if (!ab_value)
655 g_warning("transaction_cb: Oops, value was NULL. Using 0");
656 xaccSplitSetBaseValue(split, gnc_amount, xaccAccountGetCommodity(gnc_acc));
657 }
658
659 /* Memo in the Split. */
660 memo = gnc_ab_memo_to_gnc(ab_trans);
661 xaccSplitSetMemo(split, memo);
662 g_free(memo);
663
664 return gnc_trans;
665 }
666
667 /**
668 * Call gnc_import_select_account() on the online id constructed using
669 * the information in @a acc_info.
670 *
671 * @param parent Parent Widget
672 * @param acc_info AB_IMEXPORTER_ACCOUNTINFO
673 * @return A GnuCash account, or NULL otherwise
674 */
675 static Account *
gnc_ab_accinfo_to_gnc_acc(GtkWidget * parent,AB_IMEXPORTER_ACCOUNTINFO * acc_info)676 gnc_ab_accinfo_to_gnc_acc(GtkWidget *parent, AB_IMEXPORTER_ACCOUNTINFO *acc_info)
677 {
678 const gchar *bankcode, *accountnumber;
679 gchar *online_id;
680 Account *gnc_acc;
681
682 g_return_val_if_fail(acc_info, NULL);
683
684 bankcode = AB_ImExporterAccountInfo_GetBankCode(acc_info);
685 accountnumber = AB_ImExporterAccountInfo_GetAccountNumber(acc_info);
686 online_id = gnc_ab_create_online_id(bankcode, accountnumber);
687 gnc_acc = gnc_import_select_account(
688 parent, online_id, 1, AB_ImExporterAccountInfo_GetAccountName(acc_info),
689 NULL, ACCT_TYPE_NONE, NULL, NULL);
690 if (!gnc_acc)
691 {
692 g_warning("gnc_ab_accinfo_to_gnc_acc: Could not determine source account"
693 " for online_id %s", online_id);
694 }
695 g_free(online_id);
696
697 return gnc_acc;
698 }
699
700
701 /**
702 * Call gnc_import_select_account() on the online id constructed using
703 * the local information in @a transaction.
704 *
705 * @param parent Parent Widget
706 * @param transaction AB_TRANSACTION
707 * @return A GnuCash account, or NULL otherwise
708 */
709 static Account *
gnc_ab_txn_to_gnc_acc(GtkWidget * parent,const AB_TRANSACTION * transaction)710 gnc_ab_txn_to_gnc_acc(GtkWidget *parent, const AB_TRANSACTION *transaction)
711 {
712 const gchar *bankcode, *accountnumber;
713 gchar *online_id;
714 Account *gnc_acc;
715
716 g_return_val_if_fail(transaction, NULL);
717
718 bankcode = AB_Transaction_GetLocalBankCode(transaction);
719 accountnumber = AB_Transaction_GetLocalAccountNumber(transaction);
720 if (!bankcode && !accountnumber)
721 {
722 return NULL;
723 }
724
725 online_id = gnc_ab_create_online_id(bankcode, accountnumber);
726 gnc_acc = gnc_import_select_account(
727 parent, online_id, 1, AB_Transaction_GetLocalName(transaction),
728 NULL, ACCT_TYPE_NONE, NULL, NULL);
729 if (!gnc_acc)
730 {
731 g_warning("gnc_ab_txn_to_gnc_acc: Could not determine source account"
732 " for online_id %s", online_id);
733 }
734 g_free(online_id);
735
736 return gnc_acc;
737 }
738
739 static const AB_TRANSACTION *
txn_transaction_cb(const AB_TRANSACTION * element,gpointer user_data)740 txn_transaction_cb(const AB_TRANSACTION *element, gpointer user_data)
741 {
742 GncABImExContextImport *data = user_data;
743 Transaction *gnc_trans;
744 GncABTransType trans_type;
745 Account* txnacc;
746
747 g_return_val_if_fail(element && data, NULL);
748
749 /* Create a GnuCash transaction from ab_trans */
750 txnacc = gnc_ab_txn_to_gnc_acc(GTK_WIDGET(data->parent), element);
751 gnc_trans = gnc_ab_trans_to_gnc(element, txnacc ? txnacc : data->gnc_acc);
752
753 if (data->execute_txns && data->ab_acc)
754 {
755 AB_TRANSACTION *ab_trans = AB_Transaction_dup(element);
756 GNC_AB_JOB *job;
757
758 /* NEW: The imported transaction has been imported into gnucash.
759 * Now also add it as a job to aqbanking */
760 #ifdef AQBANKING6
761 AB_Transaction_SetLocalBankCode(
762 ab_trans, AB_AccountSpec_GetBankCode(data->ab_acc));
763 AB_Transaction_SetLocalAccountNumber(
764 ab_trans, AB_AccountSpec_GetAccountNumber(data->ab_acc));
765 #else
766 AB_Transaction_SetLocalBankCode(
767 ab_trans, AB_Account_GetBankCode(data->ab_acc));
768 AB_Transaction_SetLocalAccountNumber(
769 ab_trans, AB_Account_GetAccountNumber(data->ab_acc));
770 #endif
771 AB_Transaction_SetLocalCountry(ab_trans, "DE");
772
773
774 switch (AB_Transaction_GetType(ab_trans))
775 {
776 case AB_Transaction_TypeDebitNote:
777 trans_type = SINGLE_DEBITNOTE;
778 break;
779 case AB_Transaction_TypeTransaction:
780 /* trans_type = SINGLE_INTERNAL_TRANSFER;
781 * break; */
782 case AB_Transaction_TypeTransfer:
783 #ifndef AQBANKING6
784 case AB_Transaction_TypeEuTransfer:
785 #endif
786 default:
787 trans_type = SEPA_TRANSFER;
788 break;
789 } /* switch */
790
791 job = gnc_ab_get_trans_job(data->ab_acc, ab_trans, trans_type);
792
793 /* Check whether we really got a job */
794 #ifdef AQBANKING6
795 if (!job || AB_AccountSpec_GetTransactionLimitsForCommand(data->ab_acc, AB_Transaction_GetCommand(job))==NULL)
796 #else
797 if (!job || AB_Job_CheckAvailability(job))
798 #endif
799 {
800 /* Oops, no job, probably not supported by bank */
801 if (gnc_verify_dialog(
802 GTK_WINDOW (data->parent), FALSE, "%s",
803 _("The backend found an error during the preparation "
804 "of the job. It is not possible to execute this job.\n"
805 "\n"
806 "Most probably the bank does not support your chosen "
807 "job or your Online Banking account does not have the permission "
808 "to execute this job. More error messages might be "
809 "visible on your console log.\n"
810 "\n"
811 "Do you want to enter the job again?")))
812 {
813 gnc_error_dialog (GTK_WINDOW (data->parent),
814 "Sorry, not implemented yet. Please check the console or trace file logs to see which job was rejected.");
815 }
816 }
817 else
818 {
819 gnc_gen_trans_list_add_trans_with_ref_id(data->generic_importer,
820 gnc_trans,
821 #ifdef AQBANKING6
822 AB_Transaction_GetUniqueId(job));
823 #else
824 AB_Job_GetJobId(job));
825 #endif
826 /* AB_Job_List2_PushBack(data->job_list, job); -> delayed until trans is successfully imported */
827 g_datalist_set_data(&data->tmp_job_list, gnc_AB_JOB_to_readable_string(job), job);
828 }
829 AB_Transaction_free(ab_trans);
830 }
831 else
832 {
833 /* Instead of xaccTransCommitEdit(gnc_trans) */
834 gnc_gen_trans_list_add_trans(data->generic_importer, gnc_trans);
835 }
836
837 return NULL;
838 }
839
gnc_ab_trans_processed_cb(GNCImportTransInfo * trans_info,gboolean imported,gpointer user_data)840 static void gnc_ab_trans_processed_cb(GNCImportTransInfo *trans_info,
841 gboolean imported,
842 gpointer user_data)
843 {
844 GncABImExContextImport *data = user_data;
845 gchar *jobname = gnc_AB_JOB_ID_to_string(gnc_import_TransInfo_get_ref_id(trans_info));
846 GNC_AB_JOB *job = g_datalist_get_data(&data->tmp_job_list, jobname);
847
848 if (imported)
849 {
850 #ifdef AQBANKING6
851 AB_Transaction_List2_PushBack(data->job_list, job);
852 #else
853 AB_Job_List2_PushBack(data->job_list, job);
854 #endif
855 }
856 else
857 {
858 #ifdef AQBANKING6
859 AB_Transaction_free(job);
860 #else
861 AB_Job_free(job);
862 #endif
863 }
864
865 g_datalist_remove_data(&data->tmp_job_list, jobname);
866 }
867
868 gchar *
gnc_AB_JOB_to_readable_string(const GNC_AB_JOB * job)869 gnc_AB_JOB_to_readable_string(const GNC_AB_JOB *job)
870 {
871 if (job)
872 {
873 #ifdef AQBANKING6
874 return gnc_AB_JOB_ID_to_string(AB_Transaction_GetUniqueId(job));
875 #else
876 return gnc_AB_JOB_ID_to_string(AB_Job_GetJobId(job));
877 #endif
878 }
879 else
880 {
881 return gnc_AB_JOB_ID_to_string(0);
882 }
883 }
884 gchar *
gnc_AB_JOB_ID_to_string(gulong job_id)885 gnc_AB_JOB_ID_to_string(gulong job_id)
886 {
887 return g_strdup_printf("job_%lu", job_id);
888 }
889
890
891
892 static AB_IMEXPORTER_ACCOUNTINFO *
txn_accountinfo_cb(AB_IMEXPORTER_ACCOUNTINFO * element,gpointer user_data)893 txn_accountinfo_cb(AB_IMEXPORTER_ACCOUNTINFO *element, gpointer user_data)
894 {
895 GncABImExContextImport *data = user_data;
896 Account *gnc_acc;
897
898 g_return_val_if_fail(element && data, NULL);
899
900 if (data->awaiting & IGNORE_TRANSACTIONS)
901 /* Ignore them */
902 return NULL;
903
904 #ifdef AQBANKING6
905 if (!AB_ImExporterAccountInfo_GetFirstTransaction(element, AB_Transaction_TypeStatement, 0))
906 #else
907 if (!AB_ImExporterAccountInfo_GetFirstTransaction(element))
908 #endif
909 /* No transaction found */
910 return NULL;
911 else
912 data->awaiting |= FOUND_TRANSACTIONS;
913
914 if (!(data->awaiting & AWAIT_TRANSACTIONS))
915 {
916 if (gnc_verify_dialog (GTK_WINDOW (data->parent), TRUE, "%s",
917 _("The bank has sent transaction information "
918 "in its response."
919 "\n"
920 "Do you want to import it?")))
921 {
922 data->awaiting |= AWAIT_TRANSACTIONS;
923 }
924 else
925 {
926 data->awaiting |= IGNORE_TRANSACTIONS;
927 return NULL;
928 }
929 }
930
931 /* Lookup the corresponding gnucash account */
932 gnc_acc = gnc_ab_accinfo_to_gnc_acc(GTK_WIDGET(data->parent), element);
933 if (!gnc_acc) return NULL;
934 data->gnc_acc = gnc_acc;
935
936 if (data->execute_txns)
937 {
938 /* Retrieve the aqbanking account that belongs to this gnucash
939 * account */
940 data->ab_acc = gnc_ab_get_ab_account(data->api, gnc_acc);
941 if (!data->ab_acc)
942 {
943 gnc_error_dialog(GTK_WINDOW (data->parent), "%s",
944 _("No Online Banking account found for this "
945 "gnucash account. These transactions will "
946 "not be executed by Online Banking."));
947 }
948 }
949 else
950 {
951 data->ab_acc = NULL;
952 }
953
954 if (!data->generic_importer)
955 {
956 data->generic_importer = gnc_gen_trans_list_new(data->parent, NULL,
957 TRUE, 14, TRUE);
958 if (data->execute_txns)
959 {
960 gnc_gen_trans_list_add_tp_cb(data->generic_importer,
961 gnc_ab_trans_processed_cb, data);
962 }
963 }
964
965 /* Iterate through all transactions */
966 #ifdef AQBANKING6
967 {
968 AB_TRANSACTION_LIST *ab_trans_list = AB_ImExporterAccountInfo_GetTransactionList(element);
969 if (ab_trans_list)
970 AB_Transaction_List_ForEachByType(ab_trans_list,
971 txn_transaction_cb, data,
972 AB_Transaction_TypeStatement, 0);
973 }
974 #else
975 AB_ImExporterAccountInfo_TransactionsForEach(element, txn_transaction_cb,
976 data);
977 #endif
978 return NULL;
979 }
980
981 static AB_IMEXPORTER_ACCOUNTINFO *
bal_accountinfo_cb(AB_IMEXPORTER_ACCOUNTINFO * element,gpointer user_data)982 bal_accountinfo_cb(AB_IMEXPORTER_ACCOUNTINFO *element, gpointer user_data)
983 {
984 GncABImExContextImport *data = user_data;
985 Account *gnc_acc;
986 const AB_BALANCE *booked_bal, *noted_bal;
987 const AB_VALUE *booked_val = NULL, *noted_val = NULL;
988 gdouble booked_value, noted_value;
989 gnc_numeric value;
990 time64 booked_tt = 0;
991 GtkWidget *dialog;
992 gboolean show_recn_window = FALSE;
993 #ifndef AQBANKING6
994 AB_ACCOUNT_STATUS *best = NULL;
995 #endif
996
997 g_return_val_if_fail(element && data, NULL);
998
999 if (data->awaiting & IGNORE_BALANCES)
1000 /* Ignore them */
1001 return NULL;
1002
1003 #ifdef AQBANKING6
1004 if (!AB_ImExporterAccountInfo_GetFirstBalance(element))
1005 #else
1006 if (!AB_ImExporterAccountInfo_GetFirstAccountStatus(element))
1007 #endif
1008 /* No balance found */
1009 return NULL;
1010 else
1011 data->awaiting |= FOUND_BALANCES;
1012
1013 #ifdef AQBANKING6
1014 /* Lookup the most recent BALANCE available */
1015 booked_bal=AB_Balance_List_GetLatestByType(AB_ImExporterAccountInfo_GetBalanceList(element),
1016 AB_Balance_TypeBooked);
1017 #else
1018 {
1019 AB_ACCOUNT_STATUS *item = NULL;
1020 const GWEN_TIME *best_time = NULL;
1021 /* Lookup the most recent ACCOUNT_STATUS available */
1022 item = AB_ImExporterAccountInfo_GetFirstAccountStatus(element);
1023 while (item)
1024 {
1025 const GWEN_TIME *item_time = AB_AccountStatus_GetTime(item);
1026 if (!best || GWEN_Time_Diff(best_time, item_time) < 0.0)
1027 {
1028 best = item;
1029 best_time = item_time;
1030 }
1031 item = AB_ImExporterAccountInfo_GetNextAccountStatus(element);
1032 }
1033
1034 booked_bal = AB_AccountStatus_GetBookedBalance(best);
1035 }
1036 #endif
1037
1038 if (!(data->awaiting & AWAIT_BALANCES))
1039 {
1040 GtkWindow *parent = data->generic_importer ?
1041 GTK_WINDOW(data->generic_importer) :
1042 GTK_WINDOW(data->parent);
1043 const char* balance_msg =
1044 _("The bank has sent balance information in its response.\n"
1045 "Do you want to import it?");
1046 /* Ignore zero balances if we don't await a balance */
1047 if (!booked_bal || AB_Value_IsZero(AB_Balance_GetValue(booked_bal)))
1048 return NULL;
1049
1050 /* Ask the user whether to import unawaited non-zero balance */
1051 if (gnc_verify_dialog (parent, TRUE, "%s", balance_msg))
1052 {
1053 data->awaiting |= AWAIT_BALANCES;
1054 }
1055 else
1056 {
1057 data->awaiting |= IGNORE_BALANCES;
1058 return NULL;
1059 }
1060 }
1061
1062 /* Lookup the corresponding gnucash account */
1063 gnc_acc = gnc_ab_accinfo_to_gnc_acc(GTK_WIDGET (data->parent), element);
1064 if (!gnc_acc) return NULL;
1065 data->gnc_acc = gnc_acc;
1066
1067 /* Lookup booked balance and time */
1068 if (booked_bal)
1069 {
1070 #ifdef AQBANKING6
1071 const GWEN_DATE *ti = AB_Balance_GetDate(booked_bal);
1072 #else
1073 const GNC_GWEN_DATE *ti = AB_Balance_GetTime(booked_bal);
1074 #endif
1075 if (ti)
1076 {
1077 booked_tt = gnc_gwen_date_to_time64(ti);
1078 }
1079 else
1080 {
1081 /* No time found? Use today because the HBCI query asked for today's
1082 * balance. */
1083 booked_tt = gnc_time64_get_day_neutral(gnc_time(NULL));
1084 }
1085 booked_val = AB_Balance_GetValue(booked_bal);
1086 if (booked_val)
1087 {
1088 booked_value = AB_Value_GetValueAsDouble(booked_val);
1089 }
1090 else
1091 {
1092 g_warning("bal_accountinfo_cb: booked_val == NULL. Assuming 0");
1093 booked_value = 0.0;
1094 }
1095 }
1096 else
1097 {
1098 g_warning("bal_accountinfo_cb: booked_bal == NULL. Assuming 0");
1099 booked_tt = 0;
1100 booked_value = 0.0;
1101 }
1102
1103 /* Lookup noted balance */
1104 #ifdef AQBANKING6
1105 noted_bal = AB_Balance_List_GetLatestByType(AB_ImExporterAccountInfo_GetBalanceList(element),
1106 AB_Balance_TypeNoted);
1107 #else
1108 noted_bal = AB_AccountStatus_GetNotedBalance(best);
1109 #endif
1110 if (noted_bal)
1111 {
1112 noted_val = AB_Balance_GetValue(noted_bal);
1113 if (noted_val)
1114 noted_value = AB_Value_GetValueAsDouble(noted_val);
1115 else
1116 {
1117 g_warning("bal_accountinfo_cb: noted_val == NULL. Assuming 0");
1118 noted_value = 0.0;
1119 }
1120 }
1121 else
1122 {
1123 g_warning("bal_accountinfo_cb: noted_bal == NULL. Assuming 0");
1124 noted_value = 0.0;
1125 }
1126
1127 value = double_to_gnc_numeric(booked_value,
1128 xaccAccountGetCommoditySCU(gnc_acc),
1129 GNC_HOW_RND_ROUND_HALF_UP);
1130 if (noted_value == 0.0 && booked_value == 0.0)
1131 {
1132 dialog = gtk_message_dialog_new(
1133 GTK_WINDOW(data->parent),
1134 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
1135 GTK_MESSAGE_INFO,
1136 GTK_BUTTONS_OK,
1137 "%s",
1138 /* Translators: Strings from this file are needed only in
1139 countries that have one of aqbanking's Online Banking
1140 techniques available. This is 'OFX DirectConnect'
1141 (U.S. and others), 'HBCI' (in Germany), or 'YellowNet'
1142 (Switzerland). If none of these techniques are available
1143 in your country, you may safely ignore strings from the
1144 import-export/hbci subdirectory. */
1145 _("The downloaded Online Banking Balance was zero.\n\n"
1146 "Either this is the correct balance, or your bank does not "
1147 "support Balance download in this Online Banking version. "
1148 "In the latter case you should choose a different "
1149 "Online Banking version number in the Online Banking "
1150 "(AqBanking or HBCI) Setup. After that, try again to "
1151 "download the Online Banking Balance."));
1152 gtk_dialog_run(GTK_DIALOG(dialog));
1153 gtk_widget_destroy(dialog);
1154
1155 }
1156 else
1157 {
1158 gnc_numeric reconc_balance = xaccAccountGetReconciledBalance(gnc_acc);
1159
1160 gchar *booked_str = gnc_AB_VALUE_to_readable_string(booked_val);
1161 gchar *message1 = g_strdup_printf(
1162 _("Result of Online Banking job:\n"
1163 "Account booked balance is %s"),
1164 booked_str);
1165 gchar *message2 =
1166 (noted_value == 0.0) ?
1167 g_strdup("") :
1168 g_strdup_printf(_("For your information: This account also "
1169 "has a noted balance of %s\n"),
1170 gnc_AB_VALUE_to_readable_string(noted_val));
1171
1172 if (gnc_numeric_equal(value, reconc_balance))
1173 {
1174 const gchar *message3 =
1175 _("The booked balance is identical to the current "
1176 "reconciled balance of the account.");
1177 dialog = gtk_message_dialog_new(
1178 GTK_WINDOW(data->parent),
1179 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
1180 GTK_MESSAGE_INFO,
1181 GTK_BUTTONS_OK,
1182 "%s\n%s\n%s",
1183 message1, message2, message3);
1184 gtk_dialog_run(GTK_DIALOG(dialog));
1185 gtk_widget_destroy(GTK_WIDGET(dialog));
1186
1187 }
1188 else
1189 {
1190 const char *message3 = _("Reconcile account now?");
1191
1192 show_recn_window = gnc_verify_dialog (GTK_WINDOW (data->parent), TRUE, "%s\n%s\n%s",
1193 message1, message2, message3);
1194 }
1195 g_free(booked_str);
1196 g_free(message1);
1197 g_free(message2);
1198 }
1199
1200 /* Show reconciliation window */
1201 if (show_recn_window)
1202 recnWindowWithBalance(GTK_WIDGET (data->parent), gnc_acc, value, booked_tt);
1203
1204 return NULL;
1205 }
1206
1207 GncABImExContextImport *
gnc_ab_import_context(AB_IMEXPORTER_CONTEXT * context,guint awaiting,gboolean execute_txns,AB_BANKING * api,GtkWidget * parent)1208 gnc_ab_import_context(AB_IMEXPORTER_CONTEXT *context,
1209 guint awaiting, gboolean execute_txns,
1210 AB_BANKING *api, GtkWidget *parent)
1211 {
1212 GncABImExContextImport *data = g_new(GncABImExContextImport, 1);
1213 #ifdef AQBANKING6
1214 AB_IMEXPORTER_ACCOUNTINFO_LIST *ab_ail;
1215 #endif
1216 g_return_val_if_fail(context, NULL);
1217 /* Do not await and ignore at the same time */
1218 g_return_val_if_fail(!(awaiting & AWAIT_BALANCES)
1219 || !(awaiting & IGNORE_BALANCES),
1220 NULL);
1221 g_return_val_if_fail(!(awaiting & AWAIT_TRANSACTIONS)
1222 || !(awaiting & IGNORE_TRANSACTIONS),
1223 NULL);
1224 /* execute_txns must be FALSE if txns are not awaited */
1225 g_return_val_if_fail(awaiting & AWAIT_TRANSACTIONS || !execute_txns, NULL);
1226 /* An api is needed for the jobs */
1227 g_return_val_if_fail(!execute_txns || api, NULL);
1228
1229 data->awaiting = awaiting;
1230 data->txn_found = FALSE;
1231 data->execute_txns = execute_txns;
1232 data->api = api;
1233 data->parent = parent;
1234 #ifdef AQBANKING6
1235 data->job_list = AB_Transaction_List2_new();
1236 #else
1237 data->job_list = AB_Job_List2_new();
1238 #endif
1239 data->tmp_job_list = NULL;
1240 data->generic_importer = NULL;
1241
1242 g_datalist_init(&data->tmp_job_list);
1243
1244 /* Import transactions */
1245 #ifdef AQBANKING6
1246 ab_ail = AB_ImExporterContext_GetAccountInfoList(context);
1247 if (ab_ail && AB_ImExporterAccountInfo_List_GetCount(ab_ail))
1248 {
1249 if (!(awaiting & IGNORE_TRANSACTIONS))
1250 AB_ImExporterAccountInfo_List_ForEach(ab_ail, txn_accountinfo_cb,
1251 data);
1252
1253 /* populate and display the matching window */
1254 if (data->generic_importer)
1255 gnc_gen_trans_list_show_all(data->generic_importer);
1256
1257 /* Check balances */
1258 if (!(awaiting & IGNORE_BALANCES))
1259 AB_ImExporterAccountInfo_List_ForEach(ab_ail, bal_accountinfo_cb,
1260 data);
1261 }
1262 #else
1263 if (!(awaiting & IGNORE_TRANSACTIONS))
1264 AB_ImExporterContext_AccountInfoForEach(context, txn_accountinfo_cb,
1265 data);
1266
1267 /* populate and display the matching window */
1268 if (data->generic_importer)
1269 gnc_gen_trans_list_show_all(data->generic_importer);
1270
1271 /* Check balances */
1272 if (!(awaiting & IGNORE_BALANCES))
1273 AB_ImExporterContext_AccountInfoForEach(context, bal_accountinfo_cb,
1274 data);
1275 #endif
1276
1277 /* Check bank-messages */
1278 {
1279 AB_MESSAGE * bankmsg = AB_ImExporterContext_GetFirstMessage(context);
1280 while (bankmsg)
1281 {
1282 const char* subject = AB_Message_GetSubject(bankmsg);
1283 const char* text = AB_Message_GetText(bankmsg);
1284 gnc_info_dialog(GTK_WINDOW (data->parent), "%s\n%s %s\n%s",
1285 _("The bank has sent a message in its response."),
1286 _("Subject:"),
1287 subject,
1288 text);
1289
1290 #ifdef AQBANKING6
1291 bankmsg = AB_Message_List_Next(bankmsg);
1292 #else
1293 bankmsg = AB_ImExporterContext_GetNextMessage(context); // The iterator is incremented within aqbanking
1294 #endif
1295 }
1296 }
1297
1298 return data;
1299 }
1300
1301 guint
gnc_ab_ieci_get_found(GncABImExContextImport * ieci)1302 gnc_ab_ieci_get_found(GncABImExContextImport *ieci)
1303 {
1304 g_return_val_if_fail(ieci, 0);
1305
1306 return ieci->awaiting;
1307 }
1308
1309 GNC_AB_JOB_LIST2 *
gnc_ab_ieci_get_job_list(GncABImExContextImport * ieci)1310 gnc_ab_ieci_get_job_list(GncABImExContextImport *ieci)
1311 {
1312 g_return_val_if_fail(ieci, NULL);
1313
1314 return ieci->job_list;
1315 }
1316
1317 gboolean
gnc_ab_ieci_run_matcher(GncABImExContextImport * ieci)1318 gnc_ab_ieci_run_matcher(GncABImExContextImport *ieci)
1319 {
1320 g_return_val_if_fail(ieci, FALSE);
1321
1322 return gnc_gen_trans_list_run(ieci->generic_importer);
1323 }
1324
1325 GWEN_DB_NODE *
gnc_ab_get_permanent_certs(void)1326 gnc_ab_get_permanent_certs(void)
1327 {
1328 int rv;
1329 GWEN_DB_NODE *perm_certs = NULL;
1330 AB_BANKING *banking = gnc_AB_BANKING_new();
1331
1332 g_return_val_if_fail(banking, NULL);
1333 rv = AB_Banking_LoadSharedConfig(banking, "certs", &perm_certs);
1334 gnc_AB_BANKING_fini(banking);
1335 g_return_val_if_fail(rv >= 0, NULL);
1336 return perm_certs;
1337 }
1338
1339 #if (AQBANKING_VERSION_INT >= 60400)
1340 GList*
gnc_ab_trans_templ_list_new_from_ref_accounts(GNC_AB_ACCOUNT_SPEC * ab_acc)1341 gnc_ab_trans_templ_list_new_from_ref_accounts(GNC_AB_ACCOUNT_SPEC *ab_acc)
1342 {
1343 GList *retval = NULL;
1344 AB_REFERENCE_ACCOUNT *ra;
1345 AB_REFERENCE_ACCOUNT_LIST *ral;
1346 GWEN_BUFFER *accNameForTemplate = GWEN_Buffer_new(0,120,0,0);
1347 gnc_numeric zero = gnc_numeric_zero();
1348
1349 /* get the target account list */
1350 ral = AB_AccountSpec_GetRefAccountList(ab_acc);
1351 ra = AB_ReferenceAccount_List_First(ral);
1352
1353 /* fill the template list with the target accounts */
1354 while (ra)
1355 {
1356 GncABTransTempl *new_templ = gnc_ab_trans_templ_new();
1357 const char *iban = AB_ReferenceAccount_GetIban(ra);
1358 const char *accName = AB_ReferenceAccount_GetAccountName(ra);
1359 GWEN_Buffer_Reset(accNameForTemplate);
1360 if (accName)
1361 {
1362 GWEN_Buffer_AppendString(accNameForTemplate, accName);
1363 GWEN_Buffer_AppendString(accNameForTemplate, ": ");
1364 }
1365 GWEN_Buffer_AppendString(accNameForTemplate, iban);
1366 gnc_ab_trans_templ_set_name(new_templ, GWEN_Buffer_GetStart(accNameForTemplate));
1367 gnc_ab_trans_templ_set_recp_name(new_templ, AB_ReferenceAccount_GetOwnerName(ra));
1368 gnc_ab_trans_templ_set_recp_account(new_templ, AB_ReferenceAccount_GetIban(ra));
1369 gnc_ab_trans_templ_set_recp_bankcode(new_templ, AB_ReferenceAccount_GetBic(ra));
1370 gnc_ab_trans_templ_set_amount(new_templ, zero);
1371 retval = g_list_prepend (retval, new_templ);
1372 ra = AB_ReferenceAccount_List_Next(ra);
1373 }
1374 retval = g_list_reverse (retval);
1375
1376 GWEN_Buffer_free(accNameForTemplate);
1377
1378 return retval;
1379 }
1380 #endif
1381