GnuCash c935c2f+
Loading...
Searching...
No Matches
gnc-ab-transfer.c
1/*
2 * gnc-ab-transfer.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
32#include <config.h>
33
34#include <glib/gi18n.h>
35#include <gtk/gtk.h>
36#include <aqbanking/banking.h>
37
38#include <gnc-aqbanking-templates.h>
39#include <Transaction.h>
40#include "dialog-transfer.h"
41#include "gnc-ab-transfer.h"
42#include "gnc-ab-kvp.h"
43#include "gnc-ab-utils.h"
44#include "gnc-gwen-gui.h"
45#include "gnc-ui.h"
46
47/* This static indicates the debugging module that this .o belongs to. */
48G_GNUC_UNUSED static QofLogModule log_module = G_LOG_DOMAIN;
49
50static void txn_created_cb(Transaction *trans, gpointer user_data);
51
52#if (AQBANKING_VERSION_INT >= 60400)
53static void
54save_templates(GtkWidget *parent, Account *gnc_acc, GList *templates,
55 gboolean dont_ask)
56{
57 g_return_if_fail(gnc_acc);
58 if (dont_ask || gnc_verify_dialog (
59 GTK_WINDOW (parent), FALSE, "%s",
60 _("You have changed the list of online transfer templates, "
61 "but you cancelled the transfer dialog. "
62 "Do you nevertheless want to store the changes?")))
63 {
64 gnc_ab_set_book_template_list(gnc_account_get_book(gnc_acc), templates);
65 }
66}
67#endif
68
69static void
70txn_created_cb(Transaction *trans, gpointer user_data)
71{
72 Transaction **trans_loc = user_data;
73
74 if (!trans) return;
75 g_return_if_fail(trans_loc);
76 *trans_loc = trans;
77}
78
79void
80gnc_ab_maketrans(GtkWidget *parent, Account *gnc_acc,
81 GncABTransType trans_type)
82{
83 AB_BANKING *api;
84 GNC_AB_ACCOUNT_SPEC *ab_acc;
85 GList *templates = NULL;
86 GncABTransDialog *td = NULL;
87 gboolean successful = FALSE;
88 gboolean aborted = FALSE;
89
90 g_return_if_fail(parent && gnc_acc);
91
92 /* Get the API */
93 api = gnc_AB_BANKING_new();
94 if (!api)
95 {
96 g_warning("gnc_ab_maketrans: Couldn't get AqBanking API");
97 return;
98 }
99 /* Get the AqBanking Account */
100 ab_acc = gnc_ab_get_ab_account(api, gnc_acc);
101 if (!ab_acc)
102 {
103 g_warning("gnc_ab_gettrans: No AqBanking account found");
104 gnc_error_dialog (GTK_WINDOW (parent), _("No valid online banking account assigned."));
105 goto cleanup;
106 }
107
108#if (AQBANKING_VERSION_INT >= 60400)
109 if (trans_type == SEPA_INTERNAL_TRANSFER)
110 {
111 /* Generate list of template transactions from the reference accounts*/
112 templates = gnc_ab_trans_templ_list_new_from_ref_accounts (ab_acc);
113 if (templates == NULL)
114 {
115 g_warning ("gnc_ab_gettrans: No reference accounts found");
116 gnc_error_dialog (GTK_WINDOW (parent), _("No reference accounts found."));
117 goto cleanup;
118 }
119 }
120 else
121#endif
122 {
123 /* Get list of template transactions */
125 gnc_account_get_book(gnc_acc));
126 }
127
128 /* Create new ABTransDialog */
129 td = gnc_ab_trans_dialog_new(parent, ab_acc,
131 trans_type, templates);
132 templates = NULL;
133
134 /* Repeat until AqBanking action was successful or user pressed cancel */
135 do
136 {
137 GncGWENGui *gui = NULL;
138 gint result;
139 const AB_TRANSACTION *ab_trans;
140 GNC_AB_JOB *job = NULL;
141 GNC_AB_JOB_LIST2 *job_list = NULL;
142 XferDialog *xfer_dialog = NULL;
143 gnc_numeric amount;
144 gchar *description;
145 gchar *memo;
146 Transaction *gnc_trans = NULL;
147 AB_IMEXPORTER_CONTEXT *context = NULL;
148 GNC_AB_JOB_STATUS job_status;
149 GncABImExContextImport *ieci = NULL;
150
151
152 /* Let the user enter the values */
154
155#if (AQBANKING_VERSION_INT >= 60400)
156 gboolean changed;
157 templates = gnc_ab_trans_dialog_get_templ(td, &changed);
158 if (trans_type != SEPA_INTERNAL_TRANSFER && changed)
159 {
160 /* Save the templates */
161 save_templates(parent, gnc_acc, templates,
162 (result == GNC_RESPONSE_NOW));
163 }
164 g_list_free(templates);
165 templates = NULL;
166#endif
167
168 if (result != GNC_RESPONSE_NOW && result != GNC_RESPONSE_LATER)
169 {
170 aborted = TRUE;
171 goto repeat;
172 }
173
174 /* Get a job and enqueue it */
177 if (!job || AB_AccountSpec_GetTransactionLimitsForCommand(ab_acc, AB_Transaction_GetCommand(job))==NULL)
178 {
179 if (!gnc_verify_dialog (
180 GTK_WINDOW (parent), FALSE, "%s",
181 _("The backend found an error during the preparation "
182 "of the job. It is not possible to execute this job.\n"
183 "\n"
184 "Most probable the bank does not support your chosen "
185 "job or your Online Banking account does not have the permission "
186 "to execute this job. More error messages might be "
187 "visible on your console log.\n"
188 "\n"
189 "Do you want to enter the job again?")))
190 aborted = TRUE;
191 goto repeat;
192 }
193 job_list = AB_Transaction_List2_new();
194 AB_Transaction_List2_PushBack(job_list, job);
195 /* Setup a Transfer Dialog for the GnuCash transaction */
196 xfer_dialog = gnc_xfer_dialog(gnc_ab_trans_dialog_get_parent(td),
197 gnc_acc);
198 switch (trans_type)
199 {
200 case SINGLE_DEBITNOTE:
201 gnc_xfer_dialog_set_title(
202 xfer_dialog, _("Online Banking Direct Debit Note"));
203 gnc_xfer_dialog_lock_to_account_tree(xfer_dialog);
204 break;
205 case SINGLE_INTERNAL_TRANSFER:
206 gnc_xfer_dialog_set_title(
207 xfer_dialog, _("Online Banking Bank-Internal Transfer"));
208 gnc_xfer_dialog_lock_from_account_tree(xfer_dialog);
209 break;
210 case SEPA_TRANSFER:
211 gnc_xfer_dialog_set_title(
212 xfer_dialog, _("Online Banking European (SEPA) Transfer"));
213 gnc_xfer_dialog_lock_from_account_tree(xfer_dialog);
214 break;
215#if (AQBANKING_VERSION_INT >= 60400)
216 case SEPA_INTERNAL_TRANSFER:
217 gnc_xfer_dialog_set_title (
218 xfer_dialog, _("Online Banking European (SEPA) Internal Transfer"));
219 gnc_xfer_dialog_lock_from_account_tree (xfer_dialog);
220 break;
221#endif
222 case SEPA_DEBITNOTE:
223 gnc_xfer_dialog_set_title(
224 xfer_dialog, _("Online Banking European (SEPA) Debit Note"));
225 gnc_xfer_dialog_lock_to_account_tree(xfer_dialog);
226 break;
227 case SINGLE_TRANSFER:
228 default:
229 gnc_xfer_dialog_set_title(
230 xfer_dialog, _("Online Banking Transaction"));
231 gnc_xfer_dialog_lock_from_account_tree(xfer_dialog);
232 }
233 gnc_xfer_dialog_set_to_show_button_active(xfer_dialog, TRUE);
234
235 amount = double_to_gnc_numeric(
236 AB_Value_GetValueAsDouble(AB_Transaction_GetValue(ab_trans)),
239 gnc_xfer_dialog_set_amount(xfer_dialog, amount);
240 gnc_xfer_dialog_set_amount_sensitive(xfer_dialog, FALSE);
241 gnc_xfer_dialog_set_date_sensitive(xfer_dialog, FALSE);
242
243 /* OFX doesn't do transfers. */
244 description = gnc_ab_description_to_gnc(ab_trans, FALSE);
245 gnc_xfer_dialog_set_description(xfer_dialog, description);
246 g_free(description);
247
248 memo = gnc_ab_memo_to_gnc(ab_trans);
249 gnc_xfer_dialog_set_memo(xfer_dialog, memo);
250 g_free(memo);
251
252 gnc_xfer_dialog_set_txn_cb(xfer_dialog, txn_created_cb, &gnc_trans);
253
254 /* And run it */
255 successful = gnc_xfer_dialog_run_until_done(xfer_dialog);
256
257 /* On cancel, go back to the AB transaction dialog */
258 if (!successful || !gnc_trans)
259 {
260 successful = FALSE;
261 goto repeat;
262 }
263
264 if (result == GNC_RESPONSE_NOW)
265 {
266 /* Create a context to store possible results */
267 context = AB_ImExporterContext_new();
268
269 gui = gnc_GWEN_Gui_get(parent);
270 if (!gui)
271 {
272 g_warning("gnc_ab_maketrans: Couldn't initialize Gwenhywfar GUI");
273 aborted = TRUE;
274 goto repeat;
275 }
276
277 /* Finally, execute the job */
278 AB_Banking_SendCommands(api, job_list, context);
279 /* Ignore the return value of AB_Banking_ExecuteJobs(), as the job's
280 * status always describes better whether the job was actually
281 * transferred to and accepted by the bank. See also
282 * https://lists.gnucash.org/pipermail/gnucash-de/2008-September/006389.html
283 */
284 job_status = AB_Transaction_GetStatus(job);
285 if (job_status != AB_Transaction_StatusAccepted
286 && job_status != AB_Transaction_StatusPending)
287 {
288 successful = FALSE;
289 if (!gnc_verify_dialog (
290 GTK_WINDOW (parent), FALSE, "%s",
291 _("An error occurred while executing the job. Please check "
292 "the log window for the exact error message.\n"
293 "\n"
294 "Do you want to enter the job again?")))
295 {
296 aborted = TRUE;
297 }
298 }
299 else
300 {
301 successful = TRUE;
302 }
303
304 if (successful)
305 {
306 /* Import the results, awaiting nothing */
307 ieci = gnc_ab_import_context(context, 0, FALSE, NULL, parent);
308 }
309 }
310 /* Simply ignore any other case */
311
312repeat:
313 /* Clean up */
314 if (gnc_trans && !successful)
315 {
316 xaccTransBeginEdit(gnc_trans);
317 xaccTransDestroy(gnc_trans);
318 xaccTransCommitEdit(gnc_trans);
319 gnc_trans = NULL;
320 }
321 if (ieci)
322 g_free(ieci);
323 if (context)
324 AB_ImExporterContext_free(context);
325 if (job_list)
326 {
327 AB_Transaction_List2_free(job_list);
328 job_list = NULL;
329 }
330 if (job)
331 {
332 AB_Transaction_free(job);
333 job = NULL;
334 }
335 if (gui)
336 {
338 gui = NULL;
339 }
340
341 }
342 while (!successful && !aborted);
343
344cleanup:
345 if (td)
348}
API for Transactions and Splits (journal entries)
AqBanking KVP handling.
Dialog for AqBanking transaction data.
AqBanking utility functions.
GUI callbacks for AqBanking.
int xaccAccountGetCommoditySCU(const Account *acc)
Return the SCU for the account.
Definition Account.cpp:2745
GNC_AB_ACCOUNT_SPEC * gnc_ab_get_ab_account(const AB_BANKING *api, Account *gnc_acc)
Get the corresponding AqBanking account to the GnuCash account gnc_acc.
GtkWidget * gnc_ab_trans_dialog_get_parent(const GncABTransDialog *td)
Retrieve the widget used as parent.
gchar * gnc_ab_memo_to_gnc(const AB_TRANSACTION *ab_trans)
Create the appropriate memo field for a GnuCash Split by the information given in the AB_TRANSACTION ...
GncABTransDialog * gnc_ab_trans_dialog_new(GtkWidget *parent, GNC_AB_ACCOUNT_SPEC *ab_acc, gint commodity_scu, GncABTransType trans_type, GList *templates)
Create a new AqBanking transfer dialog.
GNC_AB_JOB * gnc_ab_trans_dialog_get_job(const GncABTransDialog *td)
Receive the Aqbanking job filled by the dialog.
void gnc_ab_maketrans(GtkWidget *parent, Account *gnc_acc, GncABTransType trans_type)
Create SEPA transfers.
GncGWENGui * gnc_GWEN_Gui_get(GtkWidget *parent)
When called for the first time, create a unique GncGWENGui object featuring a GWEN_GUI with all neces...
GncABImExContextImport * gnc_ab_import_context(AB_IMEXPORTER_CONTEXT *context, guint awaiting, gboolean execute_txns, AB_BANKING *api, GtkWidget *parent)
Import balances and transactions found in a AB_IMEXPORTER_CONTEXT into GnuCash.
gchar * gnc_ab_description_to_gnc(const AB_TRANSACTION *ab_trans, gboolean is_ofx)
Create the appropriate description field for a GnuCash Transaction by the information given in the AB...
gint gnc_AB_BANKING_fini(AB_BANKING *api)
Finish the AB_BANKING api.
gint gnc_ab_trans_dialog_run_until_ok(GncABTransDialog *td)
Run the Aqbanking transfer dialog until correct values where entered or the user cancelled the dialog...
GList * gnc_ab_trans_templ_list_new_from_book(QofBook *b)
Obtain the list of QofTemplates saved in a Book.
const AB_TRANSACTION * gnc_ab_trans_dialog_get_ab_trans(const GncABTransDialog *td)
Receive the Aqbanking Transaction filled by the dialog.
void gnc_GWEN_Gui_release(GncGWENGui *gui)
Currently a no-op.
AB_BANKING * gnc_AB_BANKING_new(void)
If there is a cached AB_BANKING object, return it initialized.
void gnc_ab_trans_dialog_free(GncABTransDialog *td)
Free a Aqbanking transfer dialog.
void gnc_ab_set_book_template_list(QofBook *b, GList *template_list)
Set the GList of kvp_frames of template transactions in the Book b to template_list.
void xaccTransDestroy(Transaction *trans)
Destroys a transaction.
void xaccTransCommitEdit(Transaction *trans)
The xaccTransCommitEdit() method indicates that the changes to the transaction and its splits are com...
void xaccTransBeginEdit(Transaction *trans)
The xaccTransBeginEdit() method must be called before any changes are made to a transaction or any of...
gnc_numeric double_to_gnc_numeric(double in, gint64 denom, gint how)
Convert a floating-point number to a gnc_numeric.
@ GNC_HOW_RND_ROUND_HALF_UP
Round to the nearest integer, rounding away from zero when there are two equidistant nearest integers...
STRUCTS.