00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00026 #include "config.h"
00027
00028 #include <gtk/gtk.h>
00029 #include <glib/gi18n.h>
00030 #include <stdio.h>
00031 #include <string.h>
00032 #include <sys/time.h>
00033 #include <libguile.h>
00034 #include <math.h>
00035
00036 #include <libofx/libofx.h>
00037 #include "import-account-matcher.h"
00038 #include "import-commodity-matcher.h"
00039 #include "import-utilities.h"
00040 #include "import-main-matcher.h"
00041
00042 #include "Account.h"
00043 #include "Transaction.h"
00044 #include "gnc-associate-account.h"
00045 #include "gnc-ofx-import.h"
00046 #include "gnc-file.h"
00047 #include "gnc-engine.h"
00048 #include "gnc-ui-util.h"
00049 #include "gnc-glib-utils.h"
00050 #include "core-utils/gnc-gconf-utils.h"
00051 #include "gnome-utils/gnc-ui.h"
00052 #include "gnome-utils/dialog-account.h"
00053
00054 #include "gnc-ofx-kvp.h"
00055
00056 #define GCONF_SECTION "dialogs/import/ofx"
00057
00058 static QofLogModule log_module = GNC_MOD_IMPORT;
00059
00060
00061
00062
00063
00064
00065
00066
00067 GNCImportMainMatcher *gnc_ofx_importer_gui = NULL;
00068 static gboolean auto_create_commodity = FALSE;
00069 static Account *ofx_parent_account = NULL;
00070
00071 GList *ofx_created_commodites = NULL;
00072
00073
00074
00075
00076
00077
00078
00079
00080 int ofx_proc_security_cb(const struct OfxSecurityData data, void * security_user_data);
00081 int ofx_proc_transaction_cb(struct OfxTransactionData data, void * transaction_user_data);
00082 int ofx_proc_account_cb(struct OfxAccountData data, void * account_user_data);
00083 static double ofx_get_investment_amount(const struct OfxTransactionData* data);
00084
00085 static const gchar *gnc_ofx_ttype_to_string(TransactionType t)
00086 {
00087 switch (t)
00088 {
00089 case OFX_CREDIT:
00090 return "Generic credit";
00091 case OFX_DEBIT:
00092 return "Generic debit";
00093 case OFX_INT:
00094 return "Interest earned or paid (Note: Depends on signage of amount)";
00095 case OFX_DIV:
00096 return "Dividend";
00097 case OFX_FEE:
00098 return "FI fee";
00099 case OFX_SRVCHG:
00100 return "Service charge";
00101 case OFX_DEP:
00102 return "Deposit";
00103 case OFX_ATM:
00104 return "ATM debit or credit (Note: Depends on signage of amount)";
00105 case OFX_POS:
00106 return "Point of sale debit or credit (Note: Depends on signage of amount)";
00107 case OFX_XFER:
00108 return "Transfer";
00109 case OFX_CHECK:
00110 return "Check";
00111 case OFX_PAYMENT:
00112 return "Electronic payment";
00113 case OFX_CASH:
00114 return "Cash withdrawal";
00115 case OFX_DIRECTDEP:
00116 return "Direct deposit";
00117 case OFX_DIRECTDEBIT:
00118 return "Merchant initiated debit";
00119 case OFX_REPEATPMT:
00120 return "Repeating payment/standing order";
00121 case OFX_OTHER:
00122 return "Other";
00123 default:
00124 return "Unknown transaction type";
00125 }
00126 }
00127
00128 static const gchar *gnc_ofx_invttype_to_str(InvTransactionType t)
00129 {
00130 switch (t)
00131 {
00132 case OFX_BUYDEBT:
00133 return "BUYDEBT (Buy debt security)";
00134 case OFX_BUYMF:
00135 return "BUYMF (Buy mutual fund)";
00136 case OFX_BUYOPT:
00137 return "BUYOPT (Buy option)";
00138 case OFX_BUYOTHER:
00139 return "BUYOTHER (Buy other security type)";
00140 case OFX_BUYSTOCK:
00141 return "BUYSTOCK (Buy stock))";
00142 case OFX_CLOSUREOPT:
00143 return "CLOSUREOPT (Close a position for an option)";
00144 case OFX_INCOME:
00145 return "INCOME (Investment income is realized as cash into the investment account)";
00146 case OFX_INVEXPENSE:
00147 return "INVEXPENSE (Misc investment expense that is associated with a specific security)";
00148 case OFX_JRNLFUND:
00149 return "JRNLFUND (Journaling cash holdings between subaccounts within the same investment account)";
00150 case OFX_MARGININTEREST:
00151 return "MARGININTEREST (Margin interest expense)";
00152 case OFX_REINVEST:
00153 return "REINVEST (Reinvestment of income)";
00154 case OFX_RETOFCAP:
00155 return "RETOFCAP (Return of capital)";
00156 case OFX_SELLDEBT:
00157 return "SELLDEBT (Sell debt security. Used when debt is sold, called, or reached maturity)";
00158 case OFX_SELLMF:
00159 return "SELLMF (Sell mutual fund)";
00160 case OFX_SELLOPT:
00161 return "SELLOPT (Sell option)";
00162 case OFX_SELLOTHER:
00163 return "SELLOTHER (Sell other type of security)";
00164 case OFX_SELLSTOCK:
00165 return "SELLSTOCK (Sell stock)";
00166 case OFX_SPLIT:
00167 return "SPLIT (Stock or mutial fund split)";
00168 case OFX_TRANSFER:
00169 return "TRANSFER (Transfer holdings in and out of the investment account)";
00170 default:
00171 return "ERROR, this investment transaction type is unknown. This is a bug in ofxdump";
00172 }
00173
00174 }
00175
00176
00177 int ofx_proc_security_cb(const struct OfxSecurityData data, void * security_user_data)
00178 {
00179 const char* cusip = NULL;
00180 const char* default_fullname = NULL;
00181 const char* default_mnemonic = NULL;
00182
00183 if (data.unique_id_valid)
00184 {
00185 cusip = data.unique_id;
00186 }
00187 if (data.secname_valid)
00188 {
00189 default_fullname = data.secname;
00190 }
00191 if (data.ticker_valid)
00192 {
00193 default_mnemonic = data.ticker;
00194 }
00195
00196 if (auto_create_commodity)
00197 {
00198 gnc_commodity *commodity =
00199 gnc_import_select_commodity(cusip,
00200 FALSE,
00201 default_fullname,
00202 default_mnemonic);
00203
00204 if (!commodity)
00205 {
00206 QofBook *book = gnc_get_current_book();
00207 gnc_quote_source *source;
00208 gint source_selection = 0;
00209 const char *commodity_namespace = NULL;
00210 int fraction = 1;
00211
00212 if (data.unique_id_type_valid)
00213 {
00214 commodity_namespace = data.unique_id_type;
00215 }
00216
00217 g_warning("Creating a new commodity, cusip=%s", cusip);
00218
00219 commodity = gnc_commodity_new(book,
00220 default_fullname,
00221 commodity_namespace,
00222 default_mnemonic,
00223 cusip,
00224 fraction);
00225
00226
00227 gnc_commodity_begin_edit(commodity);
00228 gnc_commodity_user_set_quote_flag (commodity, TRUE);
00229 source = gnc_quote_source_lookup_by_ti (SOURCE_SINGLE, source_selection);
00230 gnc_commodity_set_quote_source(commodity, source);
00231 gnc_commodity_commit_edit(commodity);
00232
00233
00234 gnc_commodity_table_insert(gnc_get_current_commodities(), commodity);
00235
00236
00237 ofx_created_commodites = g_list_prepend(ofx_created_commodites, commodity);
00238 }
00239 }
00240 else
00241 {
00242 gnc_import_select_commodity(cusip,
00243 TRUE,
00244 default_fullname,
00245 default_mnemonic);
00246 }
00247 return 0;
00248 }
00249
00250 static void gnc_ofx_set_split_memo(const struct OfxTransactionData* data, Split *split)
00251 {
00252 g_assert(data);
00253 g_assert(split);
00254
00255
00256
00257 if (data->name_valid)
00258 {
00259 xaccSplitSetMemo(split, data->name);
00260 }
00261 else if (data->memo_valid)
00262 {
00263 xaccSplitSetMemo(split, data->memo);
00264 }
00265 }
00266 static gnc_numeric gnc_ofx_numeric_from_double(double value, const gnc_commodity *commodity)
00267 {
00268 return double_to_gnc_numeric (value,
00269 gnc_commodity_get_fraction(commodity),
00270 GNC_HOW_RND_ROUND_HALF_UP);
00271 }
00272 static gnc_numeric gnc_ofx_numeric_from_double_txn(double value, const Transaction* txn)
00273 {
00274 return gnc_ofx_numeric_from_double(value, xaccTransGetCurrency(txn));
00275 }
00276
00277
00278
00279 static Account *gnc_ofx_new_account(const char* name,
00280 const gnc_commodity * account_commodity,
00281 Account *parent_account,
00282 GNCAccountType new_account_default_type)
00283 {
00284 Account *result;
00285 GList * valid_types = NULL;
00286
00287 g_assert(name);
00288 g_assert(account_commodity);
00289 g_assert(parent_account);
00290
00291 if (new_account_default_type != ACCT_TYPE_NONE)
00292 {
00293
00294 valid_types =
00295 g_list_prepend(valid_types,
00296 GINT_TO_POINTER(new_account_default_type));
00297 if (!xaccAccountTypesCompatible(xaccAccountGetType(parent_account), new_account_default_type))
00298 {
00299
00300 valid_types =
00301 g_list_prepend(valid_types,
00302 GINT_TO_POINTER(xaccAccountGetType(parent_account)));
00303 }
00304 }
00305 result = gnc_ui_new_accounts_from_name_with_defaults (name,
00306 valid_types,
00307 account_commodity,
00308 parent_account);
00309 g_list_free(valid_types);
00310 return result;
00311 }
00312
00313
00314 int ofx_proc_transaction_cb(struct OfxTransactionData data, void * transaction_user_data)
00315 {
00316 char dest_string[255];
00317 time_t current_time;
00318 Account *account;
00319 Account *investment_account = NULL;
00320 Account *income_account = NULL;
00321 gchar *investment_account_text;
00322 gnc_commodity *currency = NULL;
00323 gnc_commodity *investment_commodity = NULL;
00324 gnc_numeric gnc_amount, gnc_units;
00325 QofBook *book;
00326 Transaction *transaction;
00327 Split *split;
00328 gchar *notes, *tmp;
00329
00330 g_assert(gnc_ofx_importer_gui);
00331
00332 if (!data.account_id_valid)
00333 {
00334 PERR("account ID for this transaction is unavailable!");
00335 return 0;
00336 }
00337
00338 account = gnc_import_select_account(gnc_gen_trans_list_widget(gnc_ofx_importer_gui),
00339 data.account_id, 0, NULL, NULL,
00340 ACCT_TYPE_NONE, NULL, NULL);
00341 if (account == NULL)
00342 {
00343 PERR("Unable to find account for id %s", data.account_id);
00344 return 0;
00345 }
00346
00347 if (data.name_valid)
00348 gnc_utf8_strip_invalid(data.name);
00349 if (data.memo_valid)
00350 gnc_utf8_strip_invalid(data.memo);
00351 if (data.check_number_valid)
00352 gnc_utf8_strip_invalid(data.check_number);
00353 if (data.reference_number_valid)
00354 gnc_utf8_strip_invalid(data.reference_number);
00355
00356
00357 book = gnc_account_get_book(account);
00358 transaction = xaccMallocTransaction(book);
00359 xaccTransBeginEdit(transaction);
00360
00361 if (data.date_initiated_valid)
00362 {
00363 xaccTransSetDatePostedSecs(transaction, data.date_initiated);
00364 }
00365 else if (data.date_posted_valid)
00366 {
00367 xaccTransSetDatePostedSecs(transaction, data.date_posted);
00368 }
00369
00370 if (data.date_posted_valid)
00371 {
00372 xaccTransSetDatePostedSecs(transaction, data.date_posted);
00373 }
00374
00375 current_time = time(NULL);
00376 xaccTransSetDateEnteredSecs(transaction, mktime(localtime(¤t_time)));
00377
00378 if (data.check_number_valid)
00379 {
00380 xaccTransSetNum(transaction, data.check_number);
00381 }
00382 else if (data.reference_number_valid)
00383 {
00384 xaccTransSetNum(transaction, data.reference_number);
00385 }
00386
00387 if (data.name_valid)
00388 {
00389 xaccTransSetDescription(transaction, data.name);
00390 }
00391 else if (data.memo_valid)
00392 {
00393 xaccTransSetDescription(transaction, data.memo);
00394 }
00395
00396
00397 notes = g_strdup_printf("OFX ext. info: ");
00398
00399 if (data.transactiontype_valid)
00400 {
00401 tmp = notes;
00402 notes = g_strdup_printf("%s%s%s", tmp, "|Trans type:",
00403 gnc_ofx_ttype_to_string(data.transactiontype));
00404 g_free(tmp);
00405 }
00406
00407 if (data.invtransactiontype_valid)
00408 {
00409 tmp = notes;
00410 notes = g_strdup_printf("%s%s%s", tmp, "|Investment Trans type:",
00411 gnc_ofx_invttype_to_str(data.invtransactiontype));
00412 g_free(tmp);
00413 }
00414 if (data.memo_valid && data.name_valid)
00415 {
00416 tmp = notes;
00417 notes = g_strdup_printf("%s%s%s", tmp, "|Memo:", data.memo);
00418 g_free(tmp);
00419 }
00420 if (data.date_funds_available_valid)
00421 {
00422 Timespec ts;
00423 timespecFromTime_t(&ts, data.date_funds_available);
00424 gnc_timespec_to_iso8601_buff (ts, dest_string);
00425 tmp = notes;
00426 notes = g_strdup_printf("%s%s%s", tmp, "|Date funds available:", dest_string);
00427 g_free(tmp);
00428 }
00429 if (data.server_transaction_id_valid)
00430 {
00431 tmp = notes;
00432 notes = g_strdup_printf("%s%s%s", tmp, "|Server trans ID (conf. number):", data.server_transaction_id);
00433 g_free(tmp);
00434 }
00435 if (data.standard_industrial_code_valid)
00436 {
00437 tmp = notes;
00438 notes = g_strdup_printf("%s%s%ld", tmp, "|Standard Industrial Code:", data.standard_industrial_code);
00439 g_free(tmp);
00440
00441 }
00442 if (data.payee_id_valid)
00443 {
00444 tmp = notes;
00445 notes = g_strdup_printf("%s%s%s", tmp, "|Payee ID:", data.payee_id);
00446 g_free(tmp);
00447 }
00448
00449
00450
00451
00452 if (data.fi_id_corrected_valid)
00453 {
00454 PERR("WRITEME: GnuCash ofx_proc_transaction(): WARNING: This transaction corrected a previous transaction, but we created a new one instead!\n");
00455 tmp = notes;
00456 notes = g_strdup_printf("%s%s%s%s", tmp, "|This corrects transaction #", data.fi_id_corrected, "but GnuCash didn't process the correction!");
00457 g_free(tmp);
00458 }
00459 xaccTransSetNotes(transaction, notes);
00460 g_free(notes);
00461
00462 if (data.account_ptr && data.account_ptr->currency_valid)
00463 {
00464 DEBUG("Currency from libofx: %s", data.account_ptr->currency);
00465 currency = gnc_commodity_table_lookup( gnc_get_current_commodities (),
00466 GNC_COMMODITY_NS_CURRENCY,
00467 data.account_ptr->currency);
00468 }
00469 else
00470 {
00471 DEBUG("Currency from libofx unavailable, defaulting to account's default");
00472 currency = xaccAccountGetCommodity(account);
00473 }
00474
00475 xaccTransSetCurrency(transaction, currency);
00476 if (data.amount_valid)
00477 {
00478 if (!data.invtransactiontype_valid)
00479 {
00480
00481 DEBUG("Adding split; Ordinary banking transaction, money flows from or into the source account");
00482 split = xaccMallocSplit(book);
00483 xaccTransAppendSplit(transaction, split);
00484 xaccAccountInsertSplit(account, split);
00485
00486 gnc_amount = gnc_ofx_numeric_from_double_txn(data.amount, transaction);
00487 xaccSplitSetBaseValue(split, gnc_amount, xaccTransGetCurrency(transaction));
00488
00489
00490
00491 if (data.memo_valid)
00492 {
00493 xaccSplitSetMemo(split, data.memo);
00494 }
00495 if (data.fi_id_valid)
00496 {
00497 gnc_import_set_split_online_id(split, data.fi_id);
00498 }
00499 }
00500
00501 else if (data.unique_id_valid
00502 && data.security_data_valid
00503 && data.security_data_ptr != NULL
00504 && data.security_data_ptr->secname_valid)
00505 {
00506 gboolean choosing_account = TRUE;
00507
00508
00509
00510
00511
00512
00513 investment_commodity = gnc_import_select_commodity(data.unique_id,
00514 FALSE,
00515 NULL,
00516 NULL);
00517 if (investment_commodity != NULL)
00518 {
00519
00520
00521 investment_account_text = g_strdup_printf(
00522
00523
00524
00525 _("Stock account for security \"%s\""),
00526 data.security_data_ptr->secname);
00527
00528
00529
00530
00531 investment_account = gnc_import_select_account(NULL,
00532 data.unique_id, FALSE, investment_account_text,
00533 investment_commodity, ACCT_TYPE_STOCK, NULL, NULL);
00534
00535 if (investment_account
00536 && xaccAccountGetCommodity(investment_account) != investment_commodity)
00537 investment_account = NULL;
00538
00539
00540 while (!investment_account && choosing_account)
00541 {
00542
00543
00544
00545 if (auto_create_commodity && ofx_parent_account)
00546 {
00547
00548 investment_account = ofx_parent_account;
00549 }
00550 else
00551 {
00552
00553 investment_account = gnc_import_select_account(
00554 gnc_gen_trans_list_widget(gnc_ofx_importer_gui),
00555 data.unique_id,
00556 TRUE,
00557 investment_account_text,
00558 investment_commodity,
00559 ACCT_TYPE_STOCK,
00560 NULL,
00561 &choosing_account);
00562 }
00563
00564 if (investment_account && xaccAccountGetCommodity(investment_account) != investment_commodity)
00565 {
00566 if (auto_create_commodity
00567 && xaccAccountTypesCompatible(xaccAccountGetType(investment_account),
00568 ACCT_TYPE_STOCK))
00569 {
00570
00571
00572
00573
00574
00575
00576 Account *parent_account = investment_account;
00577 investment_account =
00578 gnc_ofx_new_account(investment_account_text,
00579 investment_commodity,
00580 parent_account,
00581 ACCT_TYPE_STOCK);
00582 if (investment_account)
00583 {
00584 gnc_import_set_acc_online_id(investment_account, data.unique_id);
00585 choosing_account = FALSE;
00586 ofx_parent_account = parent_account;
00587 }
00588 else
00589 {
00590 ofx_parent_account = NULL;
00591 }
00592 }
00593 else
00594 {
00595
00596
00597 choosing_account =
00598 gnc_verify_dialog(
00599 gnc_gen_trans_list_widget(gnc_ofx_importer_gui), TRUE,
00600 "The chosen account \"%s\" does not have the correct "
00601 "currency/security \"%s\" (it has \"%s\" instead). "
00602 "This account cannot be used. "
00603 "Do you want to choose again?",
00604 xaccAccountGetName(investment_account),
00605 gnc_commodity_get_fullname(investment_commodity),
00606 gnc_commodity_get_fullname(xaccAccountGetCommodity(investment_account)));
00607
00608 gnc_import_set_acc_online_id(investment_account, "");
00609 investment_account = NULL;
00610 }
00611 }
00612 }
00613 if (!investment_account)
00614 {
00615 PERR("No investment account found for text: %s\n", investment_account_text);
00616 }
00617 g_free (investment_account_text);
00618 investment_account_text = NULL;
00619
00620 if (investment_account != NULL &&
00621 data.unitprice_valid &&
00622 data.units_valid &&
00623 ( data.invtransactiontype != OFX_INCOME ) )
00624 {
00625 DEBUG("Adding investment split; Money flows from or into the stock account");
00626 split = xaccMallocSplit(book);
00627 xaccTransAppendSplit(transaction, split);
00628 xaccAccountInsertSplit(investment_account, split);
00629
00630 gnc_amount = gnc_ofx_numeric_from_double (ofx_get_investment_amount(&data),
00631 investment_commodity);
00632 gnc_units = gnc_ofx_numeric_from_double (data.units, investment_commodity);
00633 xaccSplitSetAmount(split, gnc_units);
00634 xaccSplitSetValue(split, gnc_amount);
00635
00636 if (data.security_data_ptr->memo_valid)
00637 {
00638 xaccSplitSetMemo(split, data.security_data_ptr->memo);
00639 }
00640 if (data.fi_id_valid)
00641 {
00642 gnc_import_set_split_online_id(split, data.fi_id);
00643 }
00644 }
00645 else
00646 {
00647 if (investment_account)
00648 PERR("The investment account, units or unitprice was not found for the investment transaction");
00649 }
00650 }
00651 else
00652 {
00653 PERR("Commodity not found for the investment transaction");
00654 }
00655
00656 if (data.invtransactiontype_valid && investment_account)
00657 {
00658 if (data.invtransactiontype == OFX_REINVEST
00659 || data.invtransactiontype == OFX_INCOME)
00660 {
00661 DEBUG("Now let's find an account for the destination split");
00662
00663 income_account = gnc_ofx_kvp_get_assoc_account(investment_account);
00664
00665 if (income_account == NULL)
00666 {
00667 DEBUG("Couldn't find an associated income account");
00668 investment_account_text = g_strdup_printf(
00669
00670
00671
00672 _("Income account for security \"%s\""),
00673 data.security_data_ptr->secname);
00674 income_account = gnc_import_select_account(
00675 gnc_gen_trans_list_widget(gnc_ofx_importer_gui),
00676 NULL,
00677 1,
00678 investment_account_text,
00679 currency,
00680 ACCT_TYPE_INCOME,
00681 NULL,
00682 NULL);
00683 gnc_ofx_kvp_set_assoc_account(investment_account,
00684 income_account);
00685 DEBUG("KVP written");
00686
00687 }
00688 else
00689 {
00690 DEBUG("Found at least one associated income account");
00691 }
00692 }
00693 if (income_account != NULL &&
00694 data.invtransactiontype == OFX_REINVEST)
00695 {
00696 DEBUG("Adding investment split; Money flows from the income account");
00697 split = xaccMallocSplit(book);
00698 xaccTransAppendSplit(transaction, split);
00699 xaccAccountInsertSplit(income_account, split);
00700
00701 gnc_amount = gnc_ofx_numeric_from_double_txn (data.amount, transaction);
00702 xaccSplitSetBaseValue(split, gnc_amount, xaccTransGetCurrency(transaction));
00703
00704
00705 gnc_ofx_set_split_memo(&data, split);
00706 }
00707 if (income_account != NULL &&
00708 data.invtransactiontype == OFX_INCOME)
00709 {
00710 DEBUG("Adding investment split; Money flows from the income account");
00711 split = xaccMallocSplit(book);
00712 xaccTransAppendSplit(transaction, split);
00713 xaccAccountInsertSplit(income_account, split);
00714
00715 gnc_amount = gnc_ofx_numeric_from_double_txn (-data.amount,
00716 transaction);
00717 xaccSplitSetBaseValue(split, gnc_amount, xaccTransGetCurrency(transaction));
00718
00719
00720 gnc_ofx_set_split_memo(&data, split);
00721 }
00722 }
00723
00724 if (data.invtransactiontype_valid
00725 && data.invtransactiontype != OFX_REINVEST)
00726 {
00727 DEBUG("Adding investment split; Money flows from or to the cash account");
00728 split = xaccMallocSplit(book);
00729 xaccTransAppendSplit(transaction, split);
00730 xaccAccountInsertSplit(account, split);
00731
00732 gnc_amount = gnc_ofx_numeric_from_double_txn(
00733 -ofx_get_investment_amount(&data), transaction);
00734 xaccSplitSetBaseValue(split, gnc_amount,
00735 xaccTransGetCurrency(transaction));
00736
00737
00738 gnc_ofx_set_split_memo(&data, split);
00739 }
00740 }
00741
00742
00743 if (xaccTransCountSplits(transaction) > 0)
00744 {
00745 DEBUG("%d splits sent to the importer gui", xaccTransCountSplits(transaction));
00746 gnc_gen_trans_list_add_trans (gnc_ofx_importer_gui, transaction);
00747 }
00748 else
00749 {
00750 PERR("No splits in transaction (missing account?), ignoring.");
00751 xaccTransDestroy(transaction);
00752 xaccTransCommitEdit(transaction);
00753 }
00754 }
00755 else
00756 {
00757 PERR("The transaction doesn't have a valid amount");
00758 xaccTransDestroy(transaction);
00759 xaccTransCommitEdit(transaction);
00760 }
00761
00762 return 0;
00763 }
00764
00765
00766
00767
00768
00769
00770
00771
00772 int ofx_proc_account_cb(struct OfxAccountData data, void * account_user_data)
00773 {
00774 Account *selected_account;
00775 gnc_commodity_table * commodity_table;
00776 gnc_commodity * default_commodity;
00777 GNCAccountType default_type = ACCT_TYPE_NONE;
00778 gchar * account_description;
00779 const gchar * account_type_name = _("Unknown OFX account");
00780
00781 if (data.account_id_valid)
00782 {
00783 commodity_table = gnc_get_current_commodities ();
00784 if (data.currency_valid)
00785 {
00786 DEBUG("Currency from libofx: %s", data.currency);
00787 default_commodity = gnc_commodity_table_lookup(commodity_table,
00788 GNC_COMMODITY_NS_CURRENCY,
00789 data.currency);
00790 }
00791 else
00792 {
00793 default_commodity = NULL;
00794 }
00795
00796 if (data.account_type_valid)
00797 {
00798 switch (data.account_type)
00799 {
00800 case OFX_CHECKING :
00801 default_type = ACCT_TYPE_BANK;
00802 account_type_name = _("Unknown OFX checking account");
00803 break;
00804 case OFX_SAVINGS :
00805 default_type = ACCT_TYPE_BANK;
00806 account_type_name = _("Unknown OFX savings account");
00807 break;
00808 case OFX_MONEYMRKT :
00809 default_type = ACCT_TYPE_MONEYMRKT;
00810 account_type_name = _("Unknown OFX money market account");
00811 break;
00812 case OFX_CREDITLINE :
00813 default_type = ACCT_TYPE_CREDITLINE;
00814 account_type_name = _("Unknown OFX credit line account");
00815 break;
00816 case OFX_CMA :
00817 default_type = ACCT_TYPE_NONE;
00818 account_type_name = _("Unknown OFX CMA account");
00819 break;
00820 case OFX_CREDITCARD :
00821 default_type = ACCT_TYPE_CREDIT;
00822 account_type_name = _("Unknown OFX credit card account");
00823 break;
00824 case OFX_INVESTMENT :
00825 default_type = ACCT_TYPE_BANK;
00826 account_type_name = _("Unknown OFX investment account");
00827 break;
00828 default:
00829 PERR("WRITEME: ofx_proc_account() This is an unknown account type!");
00830 }
00831 }
00832
00833 gnc_utf8_strip_invalid(data.account_name);
00834 account_description = g_strdup_printf(
00835
00836
00837
00838 "%s \"%s\"",
00839 account_type_name,
00840 data.account_name);
00841 selected_account = gnc_import_select_account(NULL,
00842 data.account_id, 1,
00843 account_description, default_commodity,
00844 default_type, NULL, NULL);
00845 g_free(account_description);
00846 }
00847 else
00848 {
00849 PERR("account online ID not available");
00850 }
00851
00852 return 0;
00853 }
00854
00855 double ofx_get_investment_amount(const struct OfxTransactionData* data)
00856 {
00857 g_assert(data);
00858 switch (data->invtransactiontype)
00859 {
00860 case OFX_BUYDEBT:
00861 case OFX_BUYMF:
00862 case OFX_BUYOPT:
00863 case OFX_BUYOTHER:
00864 case OFX_BUYSTOCK:
00865 return fabs(data->amount);
00866 case OFX_SELLDEBT:
00867 case OFX_SELLMF:
00868 case OFX_SELLOPT:
00869 case OFX_SELLOTHER:
00870 case OFX_SELLSTOCK:
00871 return -1 * fabs(data->amount);
00872 default:
00873 return -1 * data->amount;
00874 }
00875 }
00876
00877 void gnc_file_ofx_import (void)
00878 {
00879 extern int ofx_PARSER_msg;
00880 extern int ofx_DEBUG_msg;
00881 extern int ofx_WARNING_msg;
00882 extern int ofx_ERROR_msg;
00883 extern int ofx_INFO_msg;
00884 extern int ofx_STATUS_msg;
00885 char *selected_filename;
00886 char *default_dir;
00887 LibofxContextPtr libofx_context = libofx_get_new_context();
00888
00889 ofx_PARSER_msg = false;
00890 ofx_DEBUG_msg = false;
00891 ofx_WARNING_msg = true;
00892 ofx_ERROR_msg = true;
00893 ofx_INFO_msg = true;
00894 ofx_STATUS_msg = false;
00895
00896 DEBUG("gnc_file_ofx_import(): Begin...\n");
00897
00898 default_dir = gnc_get_default_directory(GCONF_SECTION);
00899 selected_filename = gnc_file_dialog(_("Select an OFX/QFX file to process"),
00900 NULL,
00901 default_dir,
00902 GNC_FILE_DIALOG_IMPORT);
00903 g_free(default_dir);
00904
00905 if (selected_filename != NULL)
00906 {
00907 #ifdef G_OS_WIN32
00908 gchar *conv_name;
00909 #endif
00910
00911
00912 default_dir = g_path_get_dirname(selected_filename);
00913 gnc_set_default_directory(GCONF_SECTION, default_dir);
00914 g_free(default_dir);
00915
00916
00917 DEBUG("Filename found: %s", selected_filename);
00918
00919
00920 gnc_ofx_importer_gui = gnc_gen_trans_list_new(NULL, NULL, FALSE, 42);
00921
00922
00923 auto_create_commodity =
00924 gnc_gconf_get_bool(GCONF_IMPORT_SECTION, "auto_create_commodity", NULL);
00925
00926
00927
00928
00929 ofx_set_account_cb(libofx_context, ofx_proc_account_cb, 0);
00930 ofx_set_transaction_cb(libofx_context, ofx_proc_transaction_cb, 0);
00931 ofx_set_security_cb(libofx_context, ofx_proc_security_cb, 0);
00932
00933
00934 #ifdef G_OS_WIN32
00935 conv_name = g_win32_locale_filename_from_utf8(selected_filename);
00936 g_free(selected_filename);
00937 selected_filename = conv_name;
00938 #endif
00939
00940 DEBUG("Opening selected file");
00941 libofx_proc_file(libofx_context, selected_filename, AUTODETECT);
00942 g_free(selected_filename);
00943 }
00944
00945 if (ofx_created_commodites)
00946 {
00947
00948
00949 g_warning("Created %d new commodities during import", g_list_length(ofx_created_commodites));
00950 g_list_free(ofx_created_commodites);
00951 ofx_created_commodites = NULL;
00952 }
00953 else
00954 {
00955
00956 }
00957 }
00958
00959