29 #include <glib/gi18n.h> 36 #include <libofx/libofx.h> 44 #include "engine-helpers.h" 54 #include "dialog-utils.h" 55 #include "window-reconcile.h" 59 #include <unordered_map> 61 #define GNC_PREFS_GROUP "dialogs.import.ofx" 62 #define GNC_PREF_AUTO_COMMODITY "auto-create-commodity" 64 static QofLogModule log_module = GNC_MOD_IMPORT;
71 static gboolean auto_create_commodity = FALSE;
72 static Account *ofx_parent_account = NULL;
74 typedef struct OfxTransactionData OfxTransactionData;
77 typedef struct _ofx_info
80 GNCImportMainMatcher *gnc_ofx_importer_gui;
82 Account *last_investment_account;
84 gint num_trans_processed;
86 gboolean run_reconcile;
92 static void runMatcher(
ofx_info* info,
char * selected_filename, gboolean go_to_next_file);
101 static const char *PROP_OFX_INCOME_ACCOUNT =
"ofx-income-account";
104 get_associated_income_account(
const Account* investment_account)
108 g_assert(investment_account);
110 PROP_OFX_INCOME_ACCOUNT, &income_guid,
113 gnc_account_get_book(investment_account));
114 guid_free (income_guid);
119 set_associated_income_account(
Account* investment_account,
122 const GncGUID * income_acc_guid;
124 g_assert(investment_account);
125 g_assert(income_account);
130 PROP_OFX_INCOME_ACCOUNT, income_acc_guid,
135 int ofx_proc_statement_cb (
struct OfxStatementData data,
void * statement_user_data);
136 int ofx_proc_security_cb (
const struct OfxSecurityData data,
void * security_user_data);
137 int ofx_proc_transaction_cb (OfxTransactionData data,
void *user_data);
138 int ofx_proc_account_cb (
struct OfxAccountData data,
void * account_user_data);
139 static double ofx_get_investment_amount (
const OfxTransactionData* data);
141 static const gchar *gnc_ofx_ttype_to_string(TransactionType t)
146 return "Generic credit";
148 return "Generic debit";
150 return "Interest earned or paid (Note: Depends on signage of amount)";
156 return "Service charge";
160 return "ATM debit or credit (Note: Depends on signage of amount)";
162 return "Point of sale debit or credit (Note: Depends on signage of amount)";
168 return "Electronic payment";
170 return "Cash withdrawal";
172 return "Direct deposit";
173 case OFX_DIRECTDEBIT:
174 return "Merchant initiated debit";
176 return "Repeating payment/standing order";
180 return "Unknown transaction type";
184 static const gchar *gnc_ofx_invttype_to_str(InvTransactionType t)
189 return "BUYDEBT (Buy debt security)";
191 return "BUYMF (Buy mutual fund)";
193 return "BUYOPT (Buy option)";
195 return "BUYOTHER (Buy other security type)";
197 return "BUYSTOCK (Buy stock))";
199 return "CLOSUREOPT (Close a position for an option)";
201 return "INCOME (Investment income is realized as cash into the investment account)";
203 return "INVEXPENSE (Misc investment expense that is associated with a specific security)";
205 return "JRNLFUND (Journaling cash holdings between subaccounts within the same investment account)";
206 case OFX_MARGININTEREST:
207 return "MARGININTEREST (Margin interest expense)";
209 return "REINVEST (Reinvestment of income)";
211 return "RETOFCAP (Return of capital)";
213 return "SELLDEBT (Sell debt security. Used when debt is sold, called, or reached maturity)";
215 return "SELLMF (Sell mutual fund)";
217 return "SELLOPT (Sell option)";
219 return "SELLOTHER (Sell other type of security)";
221 return "SELLSTOCK (Sell stock)";
223 return "SPLIT (Stock or mutial fund split)";
225 return "TRANSFER (Transfer holdings in and out of the investment account)";
226 #ifdef HAVE_LIBOFX_VERSION_0_10 227 case OFX_INVBANKTRAN:
228 return "Transfer cash in and out of the investment account";
231 return "ERROR, this investment transaction type is unknown. This is a bug in ofxdump";
237 sanitize_string (gchar* str)
240 const int length = -1;
241 while (!g_utf8_validate (str, length, (
const gchar **)(&inval)))
246 int ofx_proc_security_cb(
const struct OfxSecurityData data,
void * security_user_data)
249 char* default_fullname = NULL;
250 char* default_mnemonic = NULL;
252 if (data.unique_id_valid)
256 if (data.secname_valid)
260 if (data.ticker_valid)
265 if (auto_create_commodity)
267 gnc_commodity *commodity =
275 QofBook *book = gnc_get_current_book();
276 gnc_quote_source *source;
277 gint source_selection = 0;
278 char *commodity_namespace = NULL;
281 if (data.unique_id_type_valid)
286 g_warning(
"Creating a new commodity, cusip=%s", cusip);
296 gnc_commodity_begin_edit(commodity);
300 gnc_commodity_commit_edit(commodity);
305 g_free (commodity_namespace);
318 g_free (default_mnemonic);
319 g_free (default_fullname);
323 static void gnc_ofx_set_split_memo(
const OfxTransactionData* data, Split *split)
330 if (data->name_valid)
334 else if (data->memo_valid)
339 static gnc_numeric gnc_ofx_numeric_from_double(
double value,
const gnc_commodity *commodity)
345 static gnc_numeric gnc_ofx_numeric_from_double_txn(
double value,
const Transaction* txn)
352 static Account *gnc_ofx_new_account(GtkWindow* parent,
354 const gnc_commodity * account_commodity,
359 GList * valid_types = NULL;
362 g_assert(account_commodity);
363 g_assert(parent_account);
369 g_list_prepend(valid_types,
370 GINT_TO_POINTER(new_account_default_type));
375 g_list_prepend(valid_types,
383 g_list_free(valid_types);
411 if (tzname[1][0] !=
' ' && !stm.tm_isdst)
414 if (daylight && !stm.tm_isdst)
422 set_transaction_dates(Transaction *transaction, OfxTransactionData *data)
433 if (data->date_posted_valid && (data->date_posted != 0))
436 data->date_posted = fix_ofx_bug_39 (data->date_posted);
439 else if (data->date_initiated_valid && (data->date_initiated != 0))
442 data->date_initiated = fix_ofx_bug_39 (data->date_initiated);
455 fill_transaction_description(Transaction *transaction, OfxTransactionData *data)
458 if (data->name_valid)
462 else if (data->memo_valid)
469 fill_transaction_notes(Transaction *transaction, OfxTransactionData *data)
472 char *notes = g_strdup_printf(
"OFX ext. info: ");
474 if (data->transactiontype_valid)
477 notes = g_strdup_printf(
"%s%s%s", tmp,
"|Trans type:",
478 gnc_ofx_ttype_to_string(data->transactiontype));
482 if (data->invtransactiontype_valid)
485 notes = g_strdup_printf(
"%s%s%s", tmp,
"|Investment Trans type:",
486 gnc_ofx_invttype_to_str(data->invtransactiontype));
489 if (data->memo_valid && data->name_valid)
492 notes = g_strdup_printf(
"%s%s%s", tmp,
"|Memo:", data->memo);
495 if (data->date_funds_available_valid)
498 time64 time = data->date_funds_available;
502 notes = g_strdup_printf(
"%s%s%s", tmp,
503 "|Date funds available:", dest_string);
506 if (data->server_transaction_id_valid)
509 notes = g_strdup_printf(
"%s%s%s", tmp,
510 "|Server trans ID (conf. number):",
511 sanitize_string (data->server_transaction_id));
514 if (data->standard_industrial_code_valid)
517 notes = g_strdup_printf(
"%s%s%ld", tmp,
518 "|Standard Industrial Code:",
519 data->standard_industrial_code);
523 if (data->payee_id_valid)
526 notes = g_strdup_printf(
"%s%s%s", tmp,
"|Payee ID:",
527 sanitize_string (data->payee_id));
533 if (data->fi_id_corrected_valid)
536 PERR(
"WRITEME: GnuCash ofx_proc_transaction(): WARNING: This transaction corrected a previous transaction, but we created a new one instead!\n");
537 notes = g_strdup_printf(
"%s%s%s%s", tmp,
538 "|This corrects transaction #",
539 sanitize_string (data->fi_id_corrected),
540 "but GnuCash didn't process the correction!");
549 process_bank_transaction(Transaction *transaction,
Account *import_account,
550 OfxTransactionData *data,
ofx_info *info)
553 gnc_numeric gnc_amount;
555 double amount = data->amount;
556 #ifdef HAVE_LIBOFX_VERSION_0_10 557 if (data->currency_ratio_valid && data->currency_ratio != 0)
558 amount *= data->currency_ratio;
561 DEBUG(
"Adding split; Ordinary banking transaction, money flows from or into the source account");
565 gnc_amount = gnc_ofx_numeric_from_double_txn(amount, transaction);
569 if (data->check_number_valid)
575 const char *num_value =
576 strcasecmp (data->check_number,
"null") == 0 ?
"" :
578 gnc_set_num_action(transaction, split, num_value, NULL);
580 else if (data->reference_number_valid)
582 const char *num_value =
583 strcasecmp (data->reference_number,
"null") == 0 ?
"" :
585 gnc_set_num_action(transaction, split, num_value, NULL);
589 if (data->memo_valid)
593 if (data->fi_id_valid)
601 gnc_commodity *commodity;
608 create_investment_subaccount(GtkWindow *parent,
Account* parent_acct,
613 gnc_ofx_new_account(parent,
618 if (investment_account)
621 inv_data->choosing = FALSE;
622 ofx_parent_account = parent_acct;
626 ofx_parent_account = NULL;
628 return investment_account;
632 continue_account_selection(GtkWidget* parent,
Account* account,
633 gnc_commodity* commodity)
635 gboolean keep_going =
637 GTK_WINDOW (parent), TRUE,
638 "The chosen account \"%s\" does not have the correct " 639 "currency/security \"%s\" (it has \"%s\" instead). " 640 "This account cannot be used. " 641 "Do you want to choose again?",
651 choose_investment_account_helper(OfxTransactionData *data,
ofx_info *info,
654 Account *investment_account, *parent_account;
657 parent_account = info->last_investment_account;
659 parent_account = ofx_parent_account;
664 TRUE, inv_data->acct_text,
666 parent_account, &inv_data->choosing);
667 if (investment_account &&
672 if (!ofx_parent_account && parent_account &&
676 ofx_parent_account = parent_account;
678 info->last_investment_account = investment_account;
679 return investment_account;
683 if (auto_create_commodity && ofx_parent_account)
686 create_investment_subaccount(GTK_WINDOW(info->parent),
695 continue_account_selection(GTK_WIDGET(info->parent),
696 investment_account, inv_data->commodity);
697 investment_account = NULL;
700 return investment_account;
704 choose_investment_account(OfxTransactionData *data,
ofx_info *info,
705 gnc_commodity *commodity)
707 Account* investment_account = NULL;
715 inv_data.acct_text = g_strdup_printf(
716 _(
"Stock account for security \"%s\""),
717 sanitize_string (data->security_data_ptr->secname));
720 g_strdup_printf(
"%s%s", data->account_id, data->unique_id);
723 while (!investment_account && inv_data.choosing)
724 investment_account = choose_investment_account_helper(data, info,
726 if (!investment_account)
728 PERR(
"No investment account found for text: %s\n", inv_data.acct_text);
730 g_free (inv_data.acct_text);
731 g_free (inv_data.online_id);
733 return investment_account;
737 choose_income_account(
Account* investment_account, Transaction *transaction,
738 OfxTransactionData *data,
ofx_info *info)
740 Account *income_account = NULL;
741 DEBUG(
"Now let's find an account for the destination split");
743 get_associated_income_account(investment_account);
745 if (income_account == NULL)
747 char *income_account_text;
749 DEBUG(
"Couldn't find an associated income account");
753 income_account_text = g_strdup_printf(
754 _(
"Income account for security \"%s\""),
755 sanitize_string (data->security_data_ptr->secname));
758 income_account_text, currency,
760 info->last_income_account, NULL);
762 if (income_account != NULL)
764 info->last_income_account = income_account;
765 set_associated_income_account(investment_account,
767 DEBUG(
"KVP written");
772 DEBUG(
"Found at least one associated income account");
775 return income_account;
779 add_investment_split(Transaction* transaction,
Account* account,
780 OfxTransactionData *data)
783 QofBook *book = gnc_account_get_book(account);
784 gnc_numeric gnc_amount, gnc_units;
786 DEBUG(
"Adding investment split; Money flows from or into the stock account");
792 gnc_ofx_numeric_from_double_txn(ofx_get_investment_amount(data),
794 gnc_units = gnc_ofx_numeric_from_double (data->units, commodity);
799 if (data->check_number_valid)
801 gnc_set_num_action(transaction, split, data->check_number, NULL);
803 else if (data->reference_number_valid)
805 gnc_set_num_action(transaction, split,
806 data->reference_number, NULL);
808 if (data->security_data_ptr->memo_valid)
811 sanitize_string (data->security_data_ptr->memo));
813 if (data->fi_id_valid &&
822 add_currency_split(Transaction *transaction,
Account* account,
823 double amount, OfxTransactionData *data)
826 QofBook *book = gnc_account_get_book(account);
827 gnc_numeric gnc_amount;
832 gnc_amount = gnc_ofx_numeric_from_double_txn(amount, transaction);
836 gnc_ofx_set_split_memo(data, split);
837 if (data->fi_id_valid)
847 process_investment_transaction(Transaction *transaction,
Account *import_account,
848 OfxTransactionData *data,
ofx_info *info)
850 Account *investment_account = NULL;
851 Account *income_account = NULL;
852 gnc_commodity *investment_commodity;
853 double amount = data->amount;
855 g_return_if_fail(data->invtransactiontype_valid);
861 if (data->invtransactiontype != OFX_REINVEST)
863 DEBUG(
"Adding investment cash split.");
864 add_currency_split(transaction, import_account,
865 -ofx_get_investment_amount(data), data);
870 if (!investment_commodity)
872 PERR(
"Commodity not found for the investment transaction");
875 investment_account = choose_investment_account(data, info,
876 investment_commodity);
878 if (!investment_account)
880 PERR(
"Failed to determine an investment asset account.");
884 if (data->invtransactiontype != OFX_INCOME)
886 if (data->unitprice_valid && data->units_valid)
887 add_investment_split(transaction, investment_account, data);
889 PERR(
"Unable to add investment split, unit price or units were invalid.");
892 if (!(data->invtransactiontype == OFX_REINVEST
893 || data->invtransactiontype == OFX_INCOME))
897 #ifdef HAVE_LIBOFX_VERSION_0_10 898 if (data->currency_ratio_valid && data->currency_ratio != 0)
899 amount *= data->currency_ratio;
901 income_account = choose_income_account(investment_account,
902 transaction, data, info);
903 g_return_if_fail(income_account);
905 DEBUG(
"Adding investment income split.");
906 if (data->invtransactiontype == OFX_REINVEST)
907 add_currency_split(transaction, income_account, amount, data);
909 add_currency_split(transaction, income_account, -amount, data);
912 int ofx_proc_transaction_cb(OfxTransactionData data,
void *user_data)
915 gnc_commodity *currency = NULL;
917 Transaction *transaction;
920 g_assert(info->parent);
922 if (!data.amount_valid)
924 PERR(
"The transaction doesn't have a valid amount");
928 if (!data.account_id_valid)
930 PERR(
"account ID for this transaction is unavailable!");
939 info->last_import_account, NULL);
940 if (import_account == NULL)
942 PERR(
"Unable to find account for id %s", data.account_id);
945 info->last_import_account = import_account;
951 if (data.check_number_valid)
953 if (data.reference_number_valid)
957 book = gnc_account_get_book(import_account);
961 set_transaction_dates(transaction, &data);
962 fill_transaction_description(transaction, &data);
963 fill_transaction_notes(transaction, &data);
965 if (data.account_ptr && data.account_ptr->currency_valid)
967 DEBUG(
"Currency from libofx: %s", data.account_ptr->currency);
968 currency = gnc_commodity_table_lookup( gnc_get_current_commodities (),
969 GNC_COMMODITY_NS_CURRENCY,
970 data.account_ptr->currency);
974 DEBUG(
"Currency from libofx unavailable, defaulting to account's default");
980 if (!data.invtransactiontype_valid
981 #ifdef HAVE_LIBOFX_VERSION_0_10
982 || data.invtransactiontype == OFX_INVBANKTRAN
985 process_bank_transaction(transaction, import_account, &data, info);
986 else if (data.unique_id_valid
987 && data.security_data_valid
988 && data.security_data_ptr != NULL
989 && data.security_data_ptr->secname_valid)
990 process_investment_transaction(transaction, import_account,
994 PERR(
"Unsupported OFX transaction type.");
1003 DEBUG(
"%d splits sent to the importer gui",
1005 info->trans_list = g_list_prepend (info->trans_list, transaction);
1009 PERR(
"No splits in transaction (missing account?), ignoring.");
1014 info->num_trans_processed += 1;
1019 int ofx_proc_statement_cb (
struct OfxStatementData data,
void * statement_user_data)
1022 struct OfxStatementData *statement = g_new (
struct OfxStatementData, 1);
1024 info->statement = g_list_prepend (info->statement, statement);
1029 int ofx_proc_account_cb(
struct OfxAccountData data,
void * account_user_data)
1031 gnc_commodity_table * commodity_table;
1032 gnc_commodity * default_commodity;
1034 gchar * account_description;
1035 GtkWidget * main_widget;
1039 gboolean new_book = gnc_is_new_book();
1043 const gchar * account_type_name = _(
"Unknown OFX account");
1045 if (data.account_id_valid)
1047 commodity_table = gnc_get_current_commodities ();
1048 if (data.currency_valid)
1050 DEBUG(
"Currency from libofx: %s", data.currency);
1051 default_commodity = gnc_commodity_table_lookup(commodity_table,
1052 GNC_COMMODITY_NS_CURRENCY,
1057 default_commodity = NULL;
1060 if (data.account_type_valid)
1062 switch (data.account_type)
1064 case OfxAccountData::OFX_CHECKING:
1066 account_type_name = _(
"Unknown OFX checking account");
1068 case OfxAccountData::OFX_SAVINGS:
1070 account_type_name = _(
"Unknown OFX savings account");
1072 case OfxAccountData::OFX_MONEYMRKT:
1074 account_type_name = _(
"Unknown OFX money market account");
1076 case OfxAccountData::OFX_CREDITLINE:
1078 account_type_name = _(
"Unknown OFX credit line account");
1080 case OfxAccountData::OFX_CMA:
1083 account_type_name = _(
"Unknown OFX CMA account");
1085 case OfxAccountData::OFX_CREDITCARD:
1087 account_type_name = _(
"Unknown OFX credit card account");
1089 case OfxAccountData::OFX_INVESTMENT:
1091 account_type_name = _(
"Unknown OFX investment account");
1094 PERR(
"WRITEME: ofx_proc_account() This is an unknown account type!");
1110 account_description = g_strdup_printf (
1122 if (gtk_widget_get_realized (main_widget))
1123 parent = main_widget;
1125 parent = GTK_WIDGET(gtk_window_get_transient_for (GTK_WINDOW(main_widget)));
1129 account_description, default_commodity,
1130 default_type, NULL, NULL);
1134 info->last_import_account = account;
1137 g_free(account_description);
1141 PERR(
"account online ID not available");
1147 double ofx_get_investment_amount(
const OfxTransactionData* data)
1149 double amount = data->amount;
1150 #ifdef HAVE_LIBOFX_VERSION_0_10 1151 if (data->invtransactiontype == OFX_INVBANKTRAN)
1153 if (data->currency_ratio_valid && data->currency_ratio != 0)
1154 amount *= data->currency_ratio;
1157 switch (data->invtransactiontype)
1164 return fabs(amount);
1170 return -1 * fabs(amount);
1178 gnc_file_ofx_import_process_file (
ofx_info* info);
1182 gnc_ofx_process_next_file (GtkDialog *dialog, gpointer user_data)
1186 g_list_free_full (info->statement, g_free);
1187 info->statement = NULL;
1190 info->file_list = g_slist_delete_link (info->file_list, info->file_list);
1191 if (info->file_list)
1192 gnc_file_ofx_import_process_file (info);
1201 gnc_ofx_on_match_click (GtkDialog *dialog, gint response_id, gpointer user_data)
1205 info->response = response_id;
1209 gnc_ofx_match_done (GtkDialog *dialog, gpointer user_data)
1216 if (info->response != GTK_RESPONSE_OK)
1219 if (info->trans_list)
1226 runMatcher (info, NULL,
true);
1230 if (info->run_reconcile && info->statement && info->statement->data)
1232 auto statement =
static_cast<struct OfxStatementData*
>(info->statement->data);
1235 statement->account_id,
1237 if (account && statement->ledger_balance_valid)
1243 RecnWindow* rec_window = recnWindowWithBalance (GTK_WIDGET (info->parent), account, value,
1244 statement->ledger_balance_date);
1247 g_signal_connect (G_OBJECT (gnc_ui_reconcile_window_get_window (rec_window)),
"destroy",
1248 G_CALLBACK (gnc_ofx_match_done), info);
1249 if (info->statement->next)
1250 info->statement = info->statement->next;
1253 g_list_free_full (g_list_first (info->statement), g_free);
1254 info->statement = NULL;
1261 if (info->statement && info->statement->next)
1263 info->statement = info->statement->next;
1264 gnc_ofx_match_done (dialog, user_data);
1269 g_list_free_full (g_list_first (info->statement), g_free);
1270 info->statement = NULL;
1273 gnc_ofx_process_next_file (NULL, info);
1279 reconcile_when_close_toggled_cb (GtkToggleButton *togglebutton,
ofx_info* info)
1281 info->run_reconcile = gtk_toggle_button_get_active (togglebutton);
1285 make_date_amount_key (
const Split* split)
1287 std::ostringstream ss;
1294 runMatcher (
ofx_info* info,
char * selected_filename, gboolean go_to_next_file)
1296 GtkWindow *parent = info->parent;
1297 GList* trans_list_remain = NULL;
1298 std::unordered_map <std::string,Account*> trans_map;
1304 info->num_trans_processed = 0;
1306 gnc_window_show_progress (_(
"Removing duplicate transactions…"), 100);
1313 for(GList* node = info->trans_list; node; node=node->next)
1315 auto trans =
static_cast<Transaction*
>(node->data);
1318 auto date_amount_key = make_date_amount_key (split);
1320 auto it = trans_map.find (date_amount_key);
1321 if (it != trans_map.end() && it->second != account)
1332 DEBUG (
"Potential transfer %s %s %s %s\n", name1, name2, amtstr, datestr);
1338 trans_list_remain = g_list_prepend (trans_list_remain, trans);
1342 trans_map[date_amount_key] = account;
1344 info->num_trans_processed ++;
1347 g_list_free (info->trans_list);
1348 info->trans_list = g_list_reverse (trans_list_remain);
1349 DEBUG(
"%d transactions remaining to process in file %s\n", g_list_length (info->trans_list),
1352 gnc_window_show_progress (
nullptr, -1);
1358 if (info->num_trans_processed)
1360 gnc_info_dialog (parent, _(
"While importing transactions from OFX file '%s' found %d previously imported transactions, no new transactions."),
1362 info->num_trans_processed);
1364 info->response = GTK_RESPONSE_OK;
1365 gnc_ofx_match_done (NULL, info);
1378 G_CALLBACK (gnc_ofx_match_done),
1384 G_CALLBACK (gnc_ofx_on_match_click),
1392 info->statement != NULL,
1393 info->run_reconcile);
1399 (info->gnc_ofx_importer_gui)),
1401 G_CALLBACK (reconcile_when_close_toggled_cb),
1408 gnc_file_ofx_import_process_file (
ofx_info* info)
1410 LibofxContextPtr libofx_context;
1411 char* filename = NULL;
1412 char * selected_filename = NULL;
1413 GtkWindow *parent = info->parent;
1415 if (info->file_list == NULL)
1418 filename =
static_cast<char*
>(info->file_list->data);
1419 libofx_context = libofx_get_new_context();
1422 selected_filename = g_win32_locale_filename_from_utf8 (filename);
1425 selected_filename = filename;
1427 DEBUG(
"Filename found: %s", selected_filename);
1430 info->num_trans_processed = 0;
1431 info->statement = NULL;
1434 ofx_set_statement_cb (libofx_context, ofx_proc_statement_cb, info);
1435 ofx_set_account_cb (libofx_context, ofx_proc_account_cb, info);
1436 ofx_set_transaction_cb (libofx_context, ofx_proc_transaction_cb, info);
1437 ofx_set_security_cb (libofx_context, ofx_proc_security_cb, info);
1442 libofx_proc_file (libofx_context, selected_filename, AUTODETECT);
1445 libofx_free_context(libofx_context);
1446 runMatcher(info, selected_filename,
true);
1447 g_free(selected_filename);
1453 extern int ofx_PARSER_msg;
1454 extern int ofx_DEBUG_msg;
1455 extern int ofx_WARNING_msg;
1456 extern int ofx_ERROR_msg;
1457 extern int ofx_INFO_msg;
1458 extern int ofx_STATUS_msg;
1459 GSList* selected_filenames = NULL;
1461 GList *filters = NULL;
1463 GtkFileFilter* filter = gtk_file_filter_new ();
1466 ofx_PARSER_msg =
false;
1467 ofx_DEBUG_msg =
false;
1468 ofx_WARNING_msg =
true;
1469 ofx_ERROR_msg =
true;
1470 ofx_INFO_msg =
true;
1471 ofx_STATUS_msg =
false;
1473 DEBUG(
"gnc_file_ofx_import(): Begin...\n");
1475 default_dir = gnc_get_default_directory(GNC_PREFS_GROUP);
1476 gtk_file_filter_set_name (filter, _(
"Open/Quicken Financial Exchange file (*.ofx, *.qfx)"));
1477 gtk_file_filter_add_pattern (filter,
"*.[oqOQ][fF][xX]");
1478 filters = g_list_prepend( filters, filter );
1480 selected_filenames = gnc_file_dialog_multi (parent,
1481 _(
"Select one or multiple OFX/QFX file(s) to process"),
1484 GNC_FILE_DIALOG_IMPORT);
1485 g_free(default_dir);
1487 if (selected_filenames)
1490 default_dir = g_path_get_dirname(static_cast<char*>(selected_filenames->data));
1491 gnc_set_default_directory(GNC_PREFS_GROUP, default_dir);
1492 g_free(default_dir);
1495 auto_create_commodity =
1498 DEBUG(
"Opening selected file(s)");
1501 info->num_trans_processed = 0;
1502 info->statement = NULL;
1503 info->last_investment_account = NULL;
1504 info->last_import_account = NULL;
1505 info->last_income_account = NULL;
1506 info->parent = parent;
1507 info->run_reconcile = FALSE;
1508 info->file_list = selected_filenames;
1509 info->trans_list = NULL;
1512 gnc_file_ofx_import_process_file (info);
void xaccSplitSetValue(Split *split, gnc_numeric val)
The xaccSplitSetValue() method sets the value of this split in the transaction's commodity.
gnc_commodity * gnc_commodity_table_insert(gnc_commodity_table *table, gnc_commodity *comm)
Add a new commodity to the commodity table.
Account * gnc_account_get_parent(const Account *acc)
This routine returns a pointer to the parent of the specified account.
#define xaccTransAppendSplit(t, s)
Add a split to the transaction.
Transaction * xaccMallocTransaction(QofBook *book)
The xaccMallocTransaction() will malloc memory and initialize it.
void xaccSplitSetBaseValue(Split *s, gnc_numeric value, const gnc_commodity *base_currency)
Depending on the base_currency, set either the value or the amount of this split or both: If the base...
void gnc_gen_trans_list_show_reconcile_after_close_button(GNCImportMainMatcher *info, bool reconcile_after_close, bool active)
Show and set the reconcile after close check button.
void xaccTransSetDatePostedSecsNormalized(Transaction *trans, time64 time)
This function sets the posted date of the transaction, specified by a time64 (see ctime(3))...
int gnc_commodity_get_fraction(const gnc_commodity *cm)
Retrieve the fraction for the specified commodity.
void qof_instance_get(const QofInstance *inst, const gchar *first_prop,...)
Wrapper for g_object_get.
Split * xaccTransGetSplit(const Transaction *trans, int i)
Return a pointer to the indexed split in this transaction's split list.
time64 xaccTransGetDate(const Transaction *trans)
Retrieve the posted date of the transaction.
gboolean gnc_account_is_root(const Account *account)
This routine indicates whether the specified account is the root node of an account tree...
This quote source pulls from a single specific web site.
This file contains the functions to present a gui to the user for creating a new account or editing a...
gnc_numeric double_to_gnc_numeric(double n, gint64 denom, gint how)
Convert a floating-point number to a gnc_numeric.
QofBook * qof_instance_get_book(gconstpointer inst)
Return the book pointer.
void gnc_gen_trans_list_show_all(GNCImportMainMatcher *info)
Shows widgets.
gnc_commodity * gnc_import_select_commodity(const char *cusip, gboolean ask_on_unknown, const char *default_fullname, const char *default_mnemonic)
Must be called with a string containing a unique identifier for the commodity.
GtkWindow * gnc_ui_get_main_window(GtkWidget *widget)
Get a pointer to the final GncMainWindow widget is rooted in.
utility functions for the GnuCash UI
#define G_LOG_DOMAIN
Functions providing the SX List as a plugin page.
GNCAccountType xaccAccountGetType(const Account *acc)
Returns the account's account type.
int xaccAccountGetCommoditySCU(const Account *acc)
Return the SCU for the account.
void xaccTransSetNotes(Transaction *trans, const char *notes)
Sets the transaction Notes.
#define DEBUG(format, args...)
Print a debugging message.
Functions that are supported by all types of windows.
void qof_instance_set(QofInstance *inst, const gchar *first_prop,...)
Wrapper for g_object_set Group setting multiple parameters in a single begin/commit/rollback.
#define GNC_PREFS_GROUP_IMPORT
The preferences used by the importer.
void xaccAccountSetOnlineID(Account *acc, const char *id)
Set the account's online_id, the identifier (e.g.
void xaccTransSetDescription(Transaction *trans, const char *desc)
Sets the transaction Description.
Transaction matcher main window.
Account * gnc_import_select_account(GtkWidget *parent, const gchar *account_online_id_value, gboolean prompt_on_no_match, const gchar *account_human_description, const gnc_commodity *new_account_default_commodity, GNCAccountType new_account_default_type, Account *default_selection, gboolean *ok_pressed)
Must be called with a string containing a unique identifier for the account.
Transaction * xaccSplitGetParent(const Split *split)
Returns the parent transaction of the split.
Ofx import module interface.
Generic and very flexible account matcher/picker.
gchar * gnc_numeric_to_string(gnc_numeric n)
Convert to string.
gnc_quote_source * gnc_quote_source_lookup_by_ti(QuoteSourceType type, gint index)
Given the type/index of a quote source, find the data structure identified by this pair...
#define PERR(format, args...)
Log a serious error.
void gnc_commodity_user_set_quote_flag(gnc_commodity *cm, const gboolean flag)
Set the automatic price quote flag for the specified commodity, based on user input.
void gnc_gen_trans_list_add_trans(GNCImportMainMatcher *gui, Transaction *trans)
Add a newly imported Transaction to the Transaction Importer.
struct tm * gnc_localtime_r(const time64 *secs, struct tm *time)
fill out a time struct from a 64-bit time value adjusted for the current time zone.
void gnc_file_ofx_import(GtkWindow *parent)
The gnc_file_ofx_import() routine will pop up a standard file selection dialogue asking the user to p...
gnc_numeric gnc_numeric_reduce(gnc_numeric n)
Return input after reducing it by Greater Common Factor (GCF) elimination.
void xaccTransSetCurrency(Transaction *trans, gnc_commodity *curr)
Set a new currency on a transaction.
void xaccTransDestroy(Transaction *trans)
Destroys a transaction.
bool gnc_gen_trans_list_empty(GNCImportMainMatcher *info)
Checks whether there are no transactions to match.
gboolean qof_log_check(QofLogModule domain, QofLogLevel level)
Check to see if the given log_module is configured to log at the given log_level. ...
Stock accounts will typically be shown in registers which show three columns: price, number of shares, and value.
int xaccTransCountSplits(const Transaction *trans)
Returns the number of splits in this transaction.
#define xaccAccountGetGUID(X)
char * qof_print_date(time64 secs)
Convenience; calls through to qof_print_date_dmy_buff().
void gnc_commodity_set_quote_source(gnc_commodity *cm, gnc_quote_source *src)
Set the automatic price quote source for the specified commodity.
void xaccSplitSetAmount(Split *split, gnc_numeric amt)
The xaccSplitSetAmount() method sets the amount in the account's commodity that the split should have...
gchar * gnc_account_get_full_name(const Account *account)
The gnc_account_get_full_name routine returns the fully qualified name of the account using the given...
Account handling public routines.
GtkWidget * gnc_gen_trans_list_get_reconcile_after_close_button(GNCImportMainMatcher *info)
Returns the reconcile after close check button.
gboolean xaccAccountTypesCompatible(GNCAccountType parent_type, GNCAccountType child_type)
Return TRUE if accounts of type parent_type can have accounts of type child_type as children...
GtkWidget * gnc_gen_trans_list_widget(GNCImportMainMatcher *info)
Returns the widget of this dialog.
Income accounts are used to denote income.
void xaccSplitSetMemo(Split *split, const char *memo)
The memo is an arbitrary string associated with a split.
gnc_commodity * gnc_commodity_new(QofBook *book, const char *fullname, const char *name_space, const char *mnemonic, const char *cusip, int fraction)
Create a new commodity.
line of credit – don't use this for now, see NUM_ACCOUNT_TYPES
GNCImportMainMatcher * gnc_gen_trans_list_new(GtkWidget *parent, const gchar *heading, bool all_from_same_account, gint match_date_hardlimit, bool show_all)
Create a new generic transaction dialog window and return it.
The bank account type denotes a savings or checking account held at a bank.
const char * gnc_commodity_get_fullname(const gnc_commodity *cm)
Retrieve the full name for the specified commodity.
void gnc_utf8_strip_invalid(gchar *str)
Strip any non-UTF-8 characters from a string.
gnc_numeric gnc_numeric_abs(gnc_numeric a)
Returns a newly created gnc_numeric that is the absolute value of the given gnc_numeric value...
#define MAX_DATE_LENGTH
The maximum length of a string created by the date printers.
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...
asset (and liability) accounts indicate generic, generalized accounts that are none of the above...
All type declarations for the whole Gnucash engine.
GNCAccountType
The account types are used to determine how the transaction data in the account is displayed...
Split * xaccMallocSplit(QofBook *book)
Constructor.
Generic api to store and retrieve preferences.
gchar * gnc_utf8_strip_invalid_strdup(const gchar *str)
Returns a newly allocated copy of the given string but with any non-UTF-8 character stripped from it...
Account * gnc_ui_new_accounts_from_name_with_defaults(GtkWindow *parent, const char *name, GList *valid_types, const gnc_commodity *default_commodity, Account *parent_acct)
Display a modal window for creating a new account.
void xaccAccountBeginEdit(Account *acc)
The xaccAccountBeginEdit() subroutine is the first phase of a two-phase-commit wrapper for account up...
Account * xaccSplitGetAccount(const Split *split)
Returns the account of this split, which was set through xaccAccountInsertSplit().
gnc_commodity * xaccAccountGetCommodity(const Account *acc)
Get the account's commodity.
gnc_commodity * xaccTransGetCurrency(const Transaction *trans)
Returns the valuation commodity of this transaction.
#define xaccAccountInsertSplit(acc, s)
The xaccAccountInsertSplit() method will insert the indicated split into the indicated account...
void gnc_gen_trans_list_delete(GNCImportMainMatcher *info)
Deletes the given object.
void xaccSplitSetOnlineID(Split *split, const char *id)
The online_id is the OFX/HBCI "FITID" recorded on a split when it is imported.
gboolean gnc_prefs_get_bool(const gchar *group, const gchar *pref_name)
Get a boolean value from the preferences backend.
bank account type – don't use this for now, see NUM_ACCOUNT_TYPES
Preference keys for the generic importer.
Round to the nearest integer, rounding away from zero when there are two equidistant nearest integers...
time64 gnc_time(time64 *tbuf)
get the current time
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
void xaccTransSetDateEnteredSecs(Transaction *trans, time64 secs)
Modify the date of when the transaction was entered.
const char * xaccAccountGetName(const Account *acc)
Get the account's name.
A Generic commodity matcher/picker.
API for Transactions and Splits (journal entries)
The type used to store guids in C.
char * gnc_time64_to_iso8601_buff(time64 time, char *buff)
The gnc_time64_to_iso8601_buff() routine takes the input UTC time64 value and prints it as an ISO-860...
void xaccAccountCommitEdit(Account *acc)
ThexaccAccountCommitEdit() subroutine is the second phase of a two-phase-commit wrapper for account u...
The Credit card account is used to denote credit (e.g.
gnc_numeric xaccSplitGetAmount(const Split *split)
Returns the amount of the split in the account's commodity.
Account * xaccAccountLookup(const GncGUID *guid, QofBook *book)
The xaccAccountLookup() subroutine will return the account associated with the given id...