From: <vo...@us...> - 2013-07-01 12:43:32
|
Revision: 4225 http://sourceforge.net/p/moneymanagerex/code/4225 Author: vomikan Date: 2013-07-01 12:43:28 +0000 (Mon, 01 Jul 2013) Log Message: ----------- separate folder for impoer and export files Modified Paths: -------------- trunk/build/bakefiles/common.bkl trunk/build/msw/makefile.gcc trunk/build/msw/makefile.vc trunk/build/msw/tests/makefile.gcc trunk/build/msw/tests/makefile.vc trunk/src/mmOption.cpp trunk/src/mmex.cpp trunk/src/tests/Makefile.in trunk/src/util.cpp Added Paths: ----------- trunk/src/import_export/ trunk/src/import_export/ofximport.cpp.new trunk/src/import_export/ofximport.h.new trunk/src/import_export/qif_export.cpp trunk/src/import_export/qif_export.h trunk/src/import_export/qif_import.cpp trunk/src/import_export/qif_import.h trunk/src/import_export/univcsvdialog.cpp trunk/src/import_export/univcsvdialog.h Removed Paths: ------------- trunk/src/ofximport.cpp.new trunk/src/ofximport.h.new trunk/src/qif_export.cpp trunk/src/qif_export.h trunk/src/qif_import.cpp trunk/src/qif_import.h trunk/src/univcsvdialog.cpp trunk/src/univcsvdialog.h Modified: trunk/build/bakefiles/common.bkl =================================================================== --- trunk/build/bakefiles/common.bkl 2013-07-01 10:48:53 UTC (rev 4224) +++ trunk/build/bakefiles/common.bkl 2013-07-01 12:43:28 UTC (rev 4225) @@ -186,8 +186,8 @@ <if cond="1">/mac</if> </set> - <headers>$(fileList( [ 'src/*.h', 'src/reports/*.h', 'src/db/*.h' ] ))</headers> - <sources>$(fileList( [ 'src/*.cpp', 'src/reports/*.cpp', 'src/db/*.cpp', 'src/' + PLATF_DIR + '/*.cpp' ] ))</sources> + <headers>$(fileList( [ 'src/*.h', 'src/reports/*.h', 'src/db/*.h', 'src/import_export/*.h' ] ))</headers> + <sources>$(fileList( [ 'src/*.cpp', 'src/reports/*.cpp', 'src/db/*.cpp', 'src/' + PLATF_DIR + '/*.cpp', 'src/import_export/*.cpp' ] ))</sources> <!-- Microsoft compilers only, enable PDB for Release build --> Modified: trunk/build/msw/makefile.gcc =================================================================== --- trunk/build/msw/makefile.gcc 2013-07-01 10:48:53 UTC (rev 4224) +++ trunk/build/msw/makefile.gcc 2013-07-01 12:43:28 UTC (rev 4225) @@ -142,8 +142,6 @@ mmex_optionsdialog.o \ mmex_paths.o \ mmex_payeedialog.o \ - mmex_qif_export.o \ - mmex_qif_import.o \ mmex_recentfiles.o \ mmex_relocatecategorydialog.o \ mmex_relocatepayeedialog.o \ @@ -152,7 +150,6 @@ mmex_stockdialog.o \ mmex_stockspanel.o \ mmex_transdialog.o \ - mmex_univcsvdialog.o \ mmex_util.o \ mmex_budget.o \ mmex_budgetcategorysummary.o \ @@ -184,6 +181,9 @@ mmex_transaction.o \ mmex_transactionbill.o \ mmex_platfdep.o \ + mmex_qif_export.o \ + mmex_qif_import.o \ + mmex_univcsvdialog.o \ mmex_resources_mmex_rc.o ### Conditionally set variables: ### @@ -648,12 +648,6 @@ mmex_payeedialog.o: ../../src/payeedialog.cpp $(CXX) -c -o $@ $(MMEX_CXXFLAGS) $(CPPDEPS) $< -mmex_qif_export.o: ../../src/qif_export.cpp - $(CXX) -c -o $@ $(MMEX_CXXFLAGS) $(CPPDEPS) $< - -mmex_qif_import.o: ../../src/qif_import.cpp - $(CXX) -c -o $@ $(MMEX_CXXFLAGS) $(CPPDEPS) $< - mmex_recentfiles.o: ../../src/recentfiles.cpp $(CXX) -c -o $@ $(MMEX_CXXFLAGS) $(CPPDEPS) $< @@ -678,9 +672,6 @@ mmex_transdialog.o: ../../src/transdialog.cpp $(CXX) -c -o $@ $(MMEX_CXXFLAGS) $(CPPDEPS) $< -mmex_univcsvdialog.o: ../../src/univcsvdialog.cpp - $(CXX) -c -o $@ $(MMEX_CXXFLAGS) $(CPPDEPS) $< - mmex_util.o: ../../src/util.cpp $(CXX) -c -o $@ $(MMEX_CXXFLAGS) $(CPPDEPS) $< @@ -774,6 +765,15 @@ mmex_platfdep.o: ../../src/win/platfdep.cpp $(CXX) -c -o $@ $(MMEX_CXXFLAGS) $(CPPDEPS) $< +mmex_qif_export.o: ../../src/import_export/qif_export.cpp + $(CXX) -c -o $@ $(MMEX_CXXFLAGS) $(CPPDEPS) $< + +mmex_qif_import.o: ../../src/import_export/qif_import.cpp + $(CXX) -c -o $@ $(MMEX_CXXFLAGS) $(CPPDEPS) $< + +mmex_univcsvdialog.o: ../../src/import_export/univcsvdialog.cpp + $(CXX) -c -o $@ $(MMEX_CXXFLAGS) $(CPPDEPS) $< + mmex_resources_mmex_rc.o: ../../resources/mmex.rc windres --use-temp-file -i$< -o$@ --define HAVE_W32API_H $(____WX_SHARED_26_p_1) $(__WXUNICODE_DEFINE_p_2) $(__WXDEBUG_DEFINE_p_2) --define __WXMSW__ --include-dir $(WX_DIR)$(WXLIBPATH)\msw$(WXLIBPOSTFIX) --include-dir $(WX_DIR)/include $(__DEBUG_DEFINE_p_4) --include-dir ../../lib/sqlite --include-dir ../../lib/wxsqlite --include-dir ../../lib/lua/src --include-dir ../../lib --define NOPCH Modified: trunk/build/msw/makefile.vc =================================================================== --- trunk/build/msw/makefile.vc 2013-07-01 10:48:53 UTC (rev 4224) +++ trunk/build/msw/makefile.vc 2013-07-01 12:43:28 UTC (rev 4225) @@ -143,8 +143,6 @@ mmex_optionsdialog.obj \ mmex_paths.obj \ mmex_payeedialog.obj \ - mmex_qif_export.obj \ - mmex_qif_import.obj \ mmex_recentfiles.obj \ mmex_relocatecategorydialog.obj \ mmex_relocatepayeedialog.obj \ @@ -153,7 +151,6 @@ mmex_stockdialog.obj \ mmex_stockspanel.obj \ mmex_transdialog.obj \ - mmex_univcsvdialog.obj \ mmex_util.obj \ mmex_budget.obj \ mmex_budgetcategorysummary.obj \ @@ -184,7 +181,10 @@ mmex_subcategory.obj \ mmex_transaction.obj \ mmex_transactionbill.obj \ - mmex_platfdep.obj + mmex_platfdep.obj \ + mmex_qif_export.obj \ + mmex_qif_import.obj \ + mmex_univcsvdialog.obj MMEX_RESOURCES = \ mmex_resources_mmex.res @@ -781,12 +781,6 @@ mmex_payeedialog.obj: ..\..\src\payeedialog.cpp $(CXX) /c /nologo /TP /Fo$@ $(MMEX_CXXFLAGS) ..\..\src\payeedialog.cpp -mmex_qif_export.obj: ..\..\src\qif_export.cpp - $(CXX) /c /nologo /TP /Fo$@ $(MMEX_CXXFLAGS) ..\..\src\qif_export.cpp - -mmex_qif_import.obj: ..\..\src\qif_import.cpp - $(CXX) /c /nologo /TP /Fo$@ $(MMEX_CXXFLAGS) ..\..\src\qif_import.cpp - mmex_recentfiles.obj: ..\..\src\recentfiles.cpp $(CXX) /c /nologo /TP /Fo$@ $(MMEX_CXXFLAGS) ..\..\src\recentfiles.cpp @@ -811,9 +805,6 @@ mmex_transdialog.obj: ..\..\src\transdialog.cpp $(CXX) /c /nologo /TP /Fo$@ $(MMEX_CXXFLAGS) ..\..\src\transdialog.cpp -mmex_univcsvdialog.obj: ..\..\src\univcsvdialog.cpp - $(CXX) /c /nologo /TP /Fo$@ $(MMEX_CXXFLAGS) ..\..\src\univcsvdialog.cpp - mmex_util.obj: ..\..\src\util.cpp $(CXX) /c /nologo /TP /Fo$@ $(MMEX_CXXFLAGS) ..\..\src\util.cpp @@ -907,6 +898,15 @@ mmex_platfdep.obj: ..\..\src\win\platfdep.cpp $(CXX) /c /nologo /TP /Fo$@ $(MMEX_CXXFLAGS) ..\..\src\win\platfdep.cpp +mmex_qif_export.obj: ..\..\src\import_export\qif_export.cpp + $(CXX) /c /nologo /TP /Fo$@ $(MMEX_CXXFLAGS) ..\..\src\import_export\qif_export.cpp + +mmex_qif_import.obj: ..\..\src\import_export\qif_import.cpp + $(CXX) /c /nologo /TP /Fo$@ $(MMEX_CXXFLAGS) ..\..\src\import_export\qif_import.cpp + +mmex_univcsvdialog.obj: ..\..\src\import_export\univcsvdialog.cpp + $(CXX) /c /nologo /TP /Fo$@ $(MMEX_CXXFLAGS) ..\..\src\import_export\univcsvdialog.cpp + mmex_resources_mmex.res: ..\..\resources\mmex.rc rc /fo$@ /d WIN32 $(____WX_SHARED_46_p_1) $(__WXUNICODE_DEFINE_p_2) $(__WXDEBUG_DEFINE_p_2) /d __WXMSW__ /i $(WX_DIR)$(__WXLIBPATH_FILENAMES_2)\msw$(WXLIBPOSTFIX) /i $(WX_DIR)\include $(____DEBUGINFO_55_p_1) $(__DEBUG_DEFINE_p_4) /i ..\..\lib\sqlite /i ..\..\lib\wxsqlite /i ..\..\lib\lua\src /i ..\..\lib /d NOPCH /d _WINDOWS ..\..\resources\mmex.rc Modified: trunk/build/msw/tests/makefile.gcc =================================================================== --- trunk/build/msw/tests/makefile.gcc 2013-07-01 10:48:53 UTC (rev 4224) +++ trunk/build/msw/tests/makefile.gcc 2013-07-01 12:43:28 UTC (rev 4225) @@ -141,8 +141,6 @@ mmex_tests_optionsdialog.o \ mmex_tests_paths.o \ mmex_tests_payeedialog.o \ - mmex_tests_qif_export.o \ - mmex_tests_qif_import.o \ mmex_tests_recentfiles.o \ mmex_tests_relocatecategorydialog.o \ mmex_tests_relocatepayeedialog.o \ @@ -151,7 +149,6 @@ mmex_tests_stockdialog.o \ mmex_tests_stockspanel.o \ mmex_tests_transdialog.o \ - mmex_tests_univcsvdialog.o \ mmex_tests_util.o \ mmex_tests_budget.o \ mmex_tests_budgetcategorysummary.o \ @@ -183,6 +180,9 @@ mmex_tests_transaction.o \ mmex_tests_transactionbill.o \ mmex_tests_platfdep.o \ + mmex_tests_qif_export.o \ + mmex_tests_qif_import.o \ + mmex_tests_univcsvdialog.o \ mmex_tests_dbwrapper_test.o \ mmex_tests_mmex_lua_test.o \ mmex_tests_mmex_tests.o \ @@ -661,12 +661,6 @@ mmex_tests_payeedialog.o: ../../../src/payeedialog.cpp $(CXX) -c -o $@ $(MMEX_TESTS_CXXFLAGS) $(CPPDEPS) $< -mmex_tests_qif_export.o: ../../../src/qif_export.cpp - $(CXX) -c -o $@ $(MMEX_TESTS_CXXFLAGS) $(CPPDEPS) $< - -mmex_tests_qif_import.o: ../../../src/qif_import.cpp - $(CXX) -c -o $@ $(MMEX_TESTS_CXXFLAGS) $(CPPDEPS) $< - mmex_tests_recentfiles.o: ../../../src/recentfiles.cpp $(CXX) -c -o $@ $(MMEX_TESTS_CXXFLAGS) $(CPPDEPS) $< @@ -691,9 +685,6 @@ mmex_tests_transdialog.o: ../../../src/transdialog.cpp $(CXX) -c -o $@ $(MMEX_TESTS_CXXFLAGS) $(CPPDEPS) $< -mmex_tests_univcsvdialog.o: ../../../src/univcsvdialog.cpp - $(CXX) -c -o $@ $(MMEX_TESTS_CXXFLAGS) $(CPPDEPS) $< - mmex_tests_util.o: ../../../src/util.cpp $(CXX) -c -o $@ $(MMEX_TESTS_CXXFLAGS) $(CPPDEPS) $< @@ -787,6 +778,15 @@ mmex_tests_platfdep.o: ../../../src/win/platfdep.cpp $(CXX) -c -o $@ $(MMEX_TESTS_CXXFLAGS) $(CPPDEPS) $< +mmex_tests_qif_export.o: ../../../src/import_export/qif_export.cpp + $(CXX) -c -o $@ $(MMEX_TESTS_CXXFLAGS) $(CPPDEPS) $< + +mmex_tests_qif_import.o: ../../../src/import_export/qif_import.cpp + $(CXX) -c -o $@ $(MMEX_TESTS_CXXFLAGS) $(CPPDEPS) $< + +mmex_tests_univcsvdialog.o: ../../../src/import_export/univcsvdialog.cpp + $(CXX) -c -o $@ $(MMEX_TESTS_CXXFLAGS) $(CPPDEPS) $< + mmex_tests_dbwrapper_test.o: ../../../src/tests/dbwrapper_test.cpp $(CXX) -c -o $@ $(MMEX_TESTS_CXXFLAGS) $(CPPDEPS) $< Modified: trunk/build/msw/tests/makefile.vc =================================================================== --- trunk/build/msw/tests/makefile.vc 2013-07-01 10:48:53 UTC (rev 4224) +++ trunk/build/msw/tests/makefile.vc 2013-07-01 12:43:28 UTC (rev 4225) @@ -143,8 +143,6 @@ mmex_tests_optionsdialog.obj \ mmex_tests_paths.obj \ mmex_tests_payeedialog.obj \ - mmex_tests_qif_export.obj \ - mmex_tests_qif_import.obj \ mmex_tests_recentfiles.obj \ mmex_tests_relocatecategorydialog.obj \ mmex_tests_relocatepayeedialog.obj \ @@ -153,7 +151,6 @@ mmex_tests_stockdialog.obj \ mmex_tests_stockspanel.obj \ mmex_tests_transdialog.obj \ - mmex_tests_univcsvdialog.obj \ mmex_tests_util.obj \ mmex_tests_budget.obj \ mmex_tests_budgetcategorysummary.obj \ @@ -185,6 +182,9 @@ mmex_tests_transaction.obj \ mmex_tests_transactionbill.obj \ mmex_tests_platfdep.obj \ + mmex_tests_qif_export.obj \ + mmex_tests_qif_import.obj \ + mmex_tests_univcsvdialog.obj \ mmex_tests_dbwrapper_test.obj \ mmex_tests_mmex_lua_test.obj \ mmex_tests_mmex_tests.obj \ @@ -752,12 +752,6 @@ mmex_tests_payeedialog.obj: ..\..\..\src\payeedialog.cpp $(CXX) /c /nologo /TP /Fo$@ $(MMEX_TESTS_CXXFLAGS) ..\..\..\src\payeedialog.cpp -mmex_tests_qif_export.obj: ..\..\..\src\qif_export.cpp - $(CXX) /c /nologo /TP /Fo$@ $(MMEX_TESTS_CXXFLAGS) ..\..\..\src\qif_export.cpp - -mmex_tests_qif_import.obj: ..\..\..\src\qif_import.cpp - $(CXX) /c /nologo /TP /Fo$@ $(MMEX_TESTS_CXXFLAGS) ..\..\..\src\qif_import.cpp - mmex_tests_recentfiles.obj: ..\..\..\src\recentfiles.cpp $(CXX) /c /nologo /TP /Fo$@ $(MMEX_TESTS_CXXFLAGS) ..\..\..\src\recentfiles.cpp @@ -782,9 +776,6 @@ mmex_tests_transdialog.obj: ..\..\..\src\transdialog.cpp $(CXX) /c /nologo /TP /Fo$@ $(MMEX_TESTS_CXXFLAGS) ..\..\..\src\transdialog.cpp -mmex_tests_univcsvdialog.obj: ..\..\..\src\univcsvdialog.cpp - $(CXX) /c /nologo /TP /Fo$@ $(MMEX_TESTS_CXXFLAGS) ..\..\..\src\univcsvdialog.cpp - mmex_tests_util.obj: ..\..\..\src\util.cpp $(CXX) /c /nologo /TP /Fo$@ $(MMEX_TESTS_CXXFLAGS) ..\..\..\src\util.cpp @@ -878,6 +869,15 @@ mmex_tests_platfdep.obj: ..\..\..\src\win\platfdep.cpp $(CXX) /c /nologo /TP /Fo$@ $(MMEX_TESTS_CXXFLAGS) ..\..\..\src\win\platfdep.cpp +mmex_tests_qif_export.obj: ..\..\..\src\import_export\qif_export.cpp + $(CXX) /c /nologo /TP /Fo$@ $(MMEX_TESTS_CXXFLAGS) ..\..\..\src\import_export\qif_export.cpp + +mmex_tests_qif_import.obj: ..\..\..\src\import_export\qif_import.cpp + $(CXX) /c /nologo /TP /Fo$@ $(MMEX_TESTS_CXXFLAGS) ..\..\..\src\import_export\qif_import.cpp + +mmex_tests_univcsvdialog.obj: ..\..\..\src\import_export\univcsvdialog.cpp + $(CXX) /c /nologo /TP /Fo$@ $(MMEX_TESTS_CXXFLAGS) ..\..\..\src\import_export\univcsvdialog.cpp + mmex_tests_dbwrapper_test.obj: ..\..\..\src\tests\dbwrapper_test.cpp $(CXX) /c /nologo /TP /Fo$@ $(MMEX_TESTS_CXXFLAGS) ..\..\..\src\tests\dbwrapper_test.cpp Added: trunk/src/import_export/ofximport.cpp.new =================================================================== --- trunk/src/import_export/ofximport.cpp.new (rev 0) +++ trunk/src/import_export/ofximport.cpp.new 2013-07-01 12:43:28 UTC (rev 4225) @@ -0,0 +1,758 @@ +/*******************************************************************\ + * ofximport.cpp * + * moneymanagerex * + * * + * Adapted from gnucash source, many thanks to the gnucash team. * + * Adapted by Wesley Ellis on 11/12/09. * + * * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 2 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License* + * along with this program; if not, contact: * + * * + * Free Software Foundation Voice: +1-617-542-5942 * + * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 * + * Boston, MA 02110-1301, USA gn...@gn... * + \*******************************************************************/ + +#include "ofximport.h" +#include <libofx/libofx.h> +#include "util.h" +#include "dbwrapper.h" +#include "guiid.h" +#include "fileviewerdialog.h" +#include "mmex.h" +#include "mmcoredb.h" + +//Instantiate Import Log here + +/********************************************************************\ + * mmOfxImport + * Entry point + \********************************************************************/ + +//mmImportMatcher *mmImportMatcherGui = NULL; + +/* + int ofx_proc_status_cb(struct OfxStatusData data) + { + return 0; + } + */ + +int ofx_proc_security_cb(const struct OfxSecurityData data, void * security_user_data); +int ofx_proc_transaction_cb(struct OfxTransactionData data, void * transaction_user_data); +int ofx_proc_account_cb(struct OfxAccountData data, void * account_user_data); + +int ofx_proc_security_cb(const struct OfxSecurityData data, void * security_user_data) +{ + wxChar * tmp_cusip=NULL; + wxChar * tmp_default_fullname=NULL; + wxChar * tmp_default_mnemonic=NULL; + double * tmp_unitprice=NULL; + wxChar * tmp_notes=NULL; + wxDateTime * tmp_pdate=NULL; + //wxChar * tmp_currency=NULL; + + mmStockDialog::OnAccountButton + + if(data.unique_id_valid==true) + { + tmp_cusip=(wxChar *)data.unique_id; + } + if(data.secname_valid==true) + { + tmp_default_fullname=(wxChar *)data.secname; + } + if(data.ticker_valid==true) + { + tmp_default_symbol=(wxChar *)data.ticker; + } + if(data.unitprice_valid==true) + { + tmp_unitprice = (double *)data.unitprice; + } + if(data.memo_valid==true) + { + tmp_notes = (wxChar *)data.memo; + } + if(data.date_unitprice_valid==true) + { + tmp_pdate=(wxDateTime *)data.memo; + } + //Currency to be used once we sort out how to convert to the currency used by the database + /*if(data.currency_valid==true) + { + tmp_currency=(wxChar *)data.currency; + }*/ + + static const char sql[] = + "insert into STOCK_V1 ( " + "HELDAT, PURCHASEDATE, STOCKNAME, SYMBOL, " + "NUMSHARES, PURCHASEPRICE, NOTES, CURRENTPRICE, " + "VALUE, COMMISSION " + " ) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; + + wxSQLite3Statement st = db_->PrepareStatement(sql); + + int i = 0; + st.Bind(++i, accountID_); + st.Bind(++i, tmp_pdate); + st.Bind(++i, tmp_default_fullname); + st.Bind(++i, tmp_default_symbol); + st.Bind(++i, numShares); + st.Bind(++i, tmp_unitprice); + st.Bind(++i, tmp_notes); + st.Bind(++i, "cPrice"); + st.Bind(++i, "cValue"); + st.Bind(++i, "commission"); + + wxASSERT(st.GetParamCount() == i); + + st.ExecuteUpdate(); + st.Finalize(); + + return 0; +} + +int ofx_proc_transaction_cb(struct OfxTransactionData data, void * transaction_user_data) +{ + wxChar dest_string[255]; + wxDateTime current_time; + mmAccount *account; + mmAccount *investment_account=NULL; + mmAccount *income_account=NULL; + kvp_frame * acc_frame; + kvp_value * kvp_val; + const GUID * income_acc_guid; + wxChar *investment_account_text; + gnc_commodity *currency=NULL; + gnc_commodity *investment_commodity=NULL; + gnc_numeric gnc_amount, gnc_units; + GNCBook *book; + Transaction *transaction; + Split *split; + gchar *notes, *tmp; + + g_assert(gnc_ofx_importer_gui); + + if(data.account_id_valid==true){ + //Check to see if account alredy exists based on the account number. + + + //If account does not match account number of any account, wxDialog to select the account or create a new one. + wxArrayString as; + int importAccountID = -1; + + wxSQLite3ResultSet q1 = db_->ExecuteQuery(g_AccountNameSQL); + while (q1.NextRow()) + { + as.Add(q1.GetString("ACCOUNTNAME")); + } + q1.Finalize(); + + wxSingleChoiceDialog* scd = new wxSingleChoiceDialog(0, _("Choose Account to import to:"), + _("OFX Import"), as); + if (scd->ShowModal() != wxID_OK) + return -1; + + wxString acctName = scd->GetStringSelection(); + importAccountID = mmDBWrapper::getAccountID(db_, acctName); + + if(importAccountID!=NULL) + { + /********** Create the transaction and setup transaction data ************/ + boost::shared_ptr<mmBankTransaction> pTransaction(new mmBankTransaction(core->db_)); + book = gnc_account_get_book(account); + transaction = xaccMallocTransaction(book); + xaccTransBeginEdit(transaction); + + // fi_id can be used to identify duplicate downloads/imports + /*if(data.fi_id_valid==true){ + pTransaction->fi_id_ = data.fi_id); + }*/ + + // This could be useful. + /*if(data.date_initiated_valid==true){ + pTransaction->date_transaction = data.date_initiated; + } + else if(data.date_posted_valid==true){ + pTransaction->date_transaction = data.date_posted; + }*/ + + // We will use the posted date as the date of the transaction + if(data.date_posted_valid==true){ + pTransaction->date_ = data.date_posted); + } + + //Enter the check number of the transaction + /* + if(data.check_number_valid==true){ + pTransaction->?? = data.check_number); + }*/ + // Might present in addition to or instead of a check_number. Not necessarily a number + /*else if(data.reference_number_valid==true){ + pTransaction->?? = data.reference_number); + }*/ + + // Put transaction name in Description, or memo if name unavailable + /*if(data.name_valid==true){ + pTransaction->??? = data.name); + } + else if(data.memo_valid==true){ + pTransaction->notes_ = data.memo); + }*/ + + /* Put everything else in the Notes field */ + wxString notes_str; + + if(data.transactiontype_valid==true){ + switch(data.transactiontype){ + case OFX_CREDIT: notes_str = "Generic credit"; + break; + case OFX_DEBIT: notes_str = "Generic debit"; + break; + case OFX_INT: notes_str = "Interest earned or paid (Note: Depends on signage of amount)"; + break; + case OFX_DIV: notes_str = "Dividend"; + break; + case OFX_FEE: notes_str = "FI fee"; + break; + case OFX_SRVCHG: notes_str = "Service charge"; + break; + case OFX_DEP: notes_str = "Deposit"; + break; + case OFX_ATM: notes_str = "ATM debit or credit (Note: Depends on signage of amount)"; + break; + case OFX_POS: notes_str = "Point of sale debit or credit (Note: Depends on signage of amount)"; + break; + case OFX_XFER: notes_str = "Transfer"; + break; + case OFX_CHECK: notes_str = "Check"; + break; + case OFX_PAYMENT: notes_str = "Electronic payment"; + break; + case OFX_CASH: notes_str = "Cash withdrawal"; + break; + case OFX_DIRECTDEP: notes_str = "Direct deposit"; + break; + case OFX_DIRECTDEBIT: notes_str = "Merchant initiated debit"; + break; + case OFX_REPEATPMT: notes_str = "Repeating payment/standing order"; + break; + case OFX_OTHER: notes_str = "Other"; + break; + default : notes_str = "Unknown transaction type"; + break; + } + pTransaction->notes_ = notes_str; + } + + //Not using this as of yet + /*if(data.invtransactiontype_valid==true){ + switch(data.invtransactiontype){ + case OFX_BUYDEBT: strncpy(dest_string, "BUYDEBT (Buy debt security)", sizeof(dest_string)); + break; + case OFX_BUYMF: strncpy(dest_string, "BUYMF (Buy mutual fund)", sizeof(dest_string)); + break; + case OFX_BUYOPT: strncpy(dest_string, "BUYOPT (Buy option)", sizeof(dest_string)); + break; + case OFX_BUYOTHER: strncpy(dest_string, "BUYOTHER (Buy other security type)", sizeof(dest_string)); + break; + case OFX_BUYSTOCK: strncpy(dest_string, "BUYSTOCK (Buy stock))", sizeof(dest_string)); + break; + case OFX_CLOSUREOPT: strncpy(dest_string, "CLOSUREOPT (Close a position for an option)", sizeof(dest_string)); + break; + case OFX_INCOME: strncpy(dest_string, "INCOME (Investment income is realized as cash into the investment account)", sizeof(dest_string)); + break; + case OFX_INVEXPENSE: strncpy(dest_string, "INVEXPENSE (Misc investment expense that is associated with a specific security)", sizeof(dest_string)); + break; + case OFX_JRNLFUND: strncpy(dest_string, "JRNLFUND (Journaling cash holdings between subaccounts within the same investment account)", sizeof(dest_string)); + break; + case OFX_MARGININTEREST: strncpy(dest_string, "MARGININTEREST (Margin interest expense)", sizeof(dest_string)); + break; + case OFX_REINVEST: strncpy(dest_string, "REINVEST (Reinvestment of income)", sizeof(dest_string)); + break; + case OFX_RETOFCAP: strncpy(dest_string, "RETOFCAP (Return of capital)", sizeof(dest_string)); + break; + case OFX_SELLDEBT: strncpy(dest_string, "SELLDEBT (Sell debt security. Used when debt is sold, called, or reached maturity)", sizeof(dest_string)); + break; + case OFX_SELLMF: strncpy(dest_string, "SELLMF (Sell mutual fund)", sizeof(dest_string)); + break; + case OFX_SELLOPT: strncpy(dest_string, "SELLOPT (Sell option)", sizeof(dest_string)); + break; + case OFX_SELLOTHER: strncpy(dest_string, "SELLOTHER (Sell other type of security)", sizeof(dest_string)); + break; + case OFX_SELLSTOCK: strncpy(dest_string, "SELLSTOCK (Sell stock)", sizeof(dest_string)); + break; + case OFX_SPLIT: strncpy(dest_string, "SPLIT (Stock or mutial fund split)", sizeof(dest_string)); + break; + case OFX_TRANSFER: strncpy(dest_string, "TRANSFER (Transfer holdings in and out of the investment account)", sizeof(dest_string)); + break; + default: strncpy(dest_string, "ERROR, this investment transaction type is unknown. This is a bug in ofxdump", sizeof(dest_string)); + break; + } + tmp=notes; + notes=g_strdup_printf("%s%s%s",tmp,"|Investment Trans type:", dest_string); + g_free(tmp); + }*/ + + //Append to the Notes filed + if(data.memo_valid){ + wxString notes_memo = pTransaction.notes_& Append(data.memo); + pTransaction-> notes_ = notes_memo; + } + // Not using this + /* + if(data.date_funds_available_valid==true){ + Timespec ts; + timespecFromTime_t(&ts, data.date_funds_available); + gnc_timespec_to_iso8601_buff (ts, dest_string); + tmp=notes; + notes=g_strdup_printf("%s%s%s",tmp,"|Date funds available:", dest_string); + g_free(tmp); + } + // Not using this + if(data.server_transaction_id_valid==true){ + tmp=notes; + notes=g_strdup_printf("%s%s%s",tmp, "|Server trans ID (conf. number):", data.server_transaction_id); + g_free(tmp); + } + // Not using this + if(data.standard_industrial_code_valid==true){ + tmp=notes; + notes=g_strdup_printf("%s%s%ld",tmp, "|Standard Industrial Code:",data.standard_industrial_code); + g_free(tmp); + + }*/ + + //Add the payee + if(data.payee_id_valid==true){ + wxSting payee = data.payee_id; + if (payee.Trim().IsEmpty()) + { + payee = "Unknown"; + } + + if (!core->payeeList_.payeeExists(payee)) + { + log << _("Adding payee ") << payee << endl; + payeeID = core->payeeList_.addPayee(payee); + } + else + payeeID = core->payeeList_.getPayeeID(payee); + pTransaction->payee_ = payeeList_.getPayeeSharedPtr(payeeID); + } + + + if ( data.account_ptr && data.account_ptr->currency_valid ) + { + DEBUG("Currency from libofx: %s",data.account_ptr->currency); + currency = gnc_commodity_table_lookup( gnc_get_current_commodities (), + GNC_COMMODITY_NS_CURRENCY, + data.account_ptr->currency); + } + else + { + DEBUG("Currency from libofx unavailable, defaulting to account's default"); + currency = xaccAccountGetCommodity(account); + } + + xaccTransSetCurrency(transaction,currency); + if(data.amount_valid==true) + { + if(data.invtransactiontype_valid==false) + { + /*************Process a normal transaction ***************************/ + DEBUG("Adding split; Ordinary banking transaction, money flows from or into the source account"); + split=xaccMallocSplit(book); + xaccTransAppendSplit(transaction,split); + xaccAccountInsertSplit(account,split); + + gnc_amount = double_to_gnc_numeric (data.amount, + gnc_commodity_get_fraction(xaccTransGetCurrency(transaction)), + GNC_RND_ROUND); + xaccSplitSetBaseValue(split, gnc_amount, xaccTransGetCurrency(transaction)); + + /* Also put the ofx transaction's memo in the split's memo field */ + if(data.memo_valid==true){ + xaccSplitSetMemo(split, data.memo); + } + } + else if(data.unique_id_valid == true + && data.security_data_valid + && data.security_data_ptr != NULL + && data.security_data_ptr->secname_valid == true) + { + /************************ Process an investment transaction ******************************/ + /* Note that the ACCT_TYPE_STOCK account type should be replaced with something + derived from data.invtranstype*/ + investment_commodity = gnc_import_select_commodity(data.unique_id, + 0, + NULL, + NULL); + if(investment_commodity!=NULL) + { + investment_account_text = g_strdup_printf( /* This string is a default account + name. It MUST NOT contain the + character ':' anywhere in it or + in any translations. */ + _("Stock account for security \"%s\""), + data.security_data_ptr->secname); + investment_account = gnc_import_select_account(NULL, + data.unique_id, + 1, + investment_account_text, + investment_commodity, + ACCT_TYPE_STOCK, + NULL, + NULL); + g_free (investment_account_text); + investment_account_text = NULL; + if(investment_account!=NULL&& + data.unitprice_valid==true&& + data.units_valid==true&& + ( data.invtransactiontype!=OFX_INCOME ) ) + { + DEBUG("Adding investment split; Money flows from or into the stock account"); + split=xaccMallocSplit(book); + xaccTransAppendSplit(transaction,split); + xaccAccountInsertSplit(investment_account,split); + + gnc_amount = double_to_gnc_numeric (-(data.amount), + gnc_commodity_get_fraction(investment_commodity), + GNC_RND_ROUND); + gnc_units = double_to_gnc_numeric (data.units, + gnc_commodity_get_fraction(investment_commodity), + GNC_RND_ROUND); + xaccSplitSetAmount(split, gnc_units); + xaccSplitSetValue(split, gnc_amount); + + if(data.security_data_ptr->memo_valid==true) + { + xaccSplitSetMemo(split, data.security_data_ptr->memo); + } + } + else + { + PERR("The investment account, units or unitprice was not found for the investment transaction"); + } + } + else + { + PERR("Commodity not found for the investment transaction"); + } + + if(data.invtransactiontype_valid==true) + { + if(data.invtransactiontype==OFX_REINVEST||data.invtransactiontype==OFX_INCOME) + { + DEBUG("Now let's find an account for the destination split"); + + acc_frame=xaccAccountGetSlots(investment_account); + kvp_val = kvp_frame_get_slot(acc_frame, + "ofx/associated-income-account"); + if (kvp_val != NULL) + { + income_account = xaccAccountLookup(kvp_value_get_guid(kvp_val),book); + } + if(income_account==NULL) + { + DEBUG("Couldn't find an associated income account"); + investment_account_text = g_strdup_printf( /* This string is a default account + name. It MUST NOT contain the + character ':' anywhere in it or + in any translations. */ + _("Income account for security \"%s\""), + data.security_data_ptr->secname); + income_account=gnc_import_select_account(NULL, + NULL, + 1, + investment_account_text, + currency, + ACCT_TYPE_INCOME, + NULL, + NULL); + income_acc_guid = xaccAccountGetGUID(income_account); + kvp_val = kvp_value_new_guid(income_acc_guid); + if( acc_frame==NULL) + { + DEBUG("The kvp_frame was NULL, allocating new one"); + acc_frame = kvp_frame_new(); + } + kvp_frame_set_slot_nc(acc_frame, "ofx/associated-income-account", + kvp_val); + DEBUG("KVP written"); + + } + else + { + DEBUG("Found at least one associated income account"); + } + } + if(income_account!=NULL&& + data.invtransactiontype==OFX_REINVEST) + { + DEBUG("Adding investment split; Money flows from the income account"); + split=xaccMallocSplit(book); + xaccTransAppendSplit(transaction,split); + xaccAccountInsertSplit(income_account,split); + + gnc_amount = double_to_gnc_numeric (data.amount, + gnc_commodity_get_fraction(xaccTransGetCurrency(transaction)), + GNC_RND_ROUND); + xaccSplitSetBaseValue(split, gnc_amount, xaccTransGetCurrency(transaction)); + + /* Also put the ofx transaction name in the splits memo field, or ofx memo if name is unavailable */ + if(data.name_valid==true){ + xaccSplitSetMemo(split, data.name); + } + else if(data.memo_valid==true){ + xaccSplitSetMemo(split, data.memo); + } + } + if(income_account!=NULL&& + data.invtransactiontype==OFX_INCOME) + { + DEBUG("Adding investment split; Money flows from the income account"); + split=xaccMallocSplit(book); + xaccTransAppendSplit(transaction,split); + xaccAccountInsertSplit(income_account,split); + + gnc_amount = double_to_gnc_numeric (-data.amount,/*OFX_INCOME amounts come in as positive numbers*/ + gnc_commodity_get_fraction(xaccTransGetCurrency(transaction)), + GNC_RND_ROUND); + xaccSplitSetBaseValue(split, gnc_amount, xaccTransGetCurrency(transaction)); + + /* Also put the ofx transaction name in the splits memo field, or ofx memo if name is unavailable */ + if(data.name_valid==true){ + xaccSplitSetMemo(split, data.name); + } + else if(data.memo_valid==true){ + xaccSplitSetMemo(split, data.memo); + } + } + + + if(data.invtransactiontype!=OFX_REINVEST) + { + DEBUG("Adding investment split; Money flows from or to the cash account"); + split=xaccMallocSplit(book); + xaccTransAppendSplit(transaction,split); + xaccAccountInsertSplit(account,split); + + gnc_amount = double_to_gnc_numeric (data.amount, + gnc_commodity_get_fraction(xaccTransGetCurrency(transaction)), + GNC_RND_ROUND); + xaccSplitSetBaseValue(split, gnc_amount, xaccTransGetCurrency(transaction)); + + /* Also put the ofx transaction name in the splits memo field, or ofx memo if name is unavailable */ + if(data.name_valid==true){ + xaccSplitSetMemo(split, data.name); + } + else if(data.memo_valid==true){ + xaccSplitSetMemo(split, data.memo); + } + + } + } + } + + /* Use new importer GUI. */ + DEBUG("%d splits sent to the importer gui",xaccTransCountSplits(transaction)); + gnc_gen_trans_list_add_trans (gnc_ofx_importer_gui, transaction); + } + else + { + PERR("The transaction doesn't have a valid amount"); + xaccTransDestroy(transaction); + xaccTransCommitEdit(transaction); + } + + } + else + { + PERR("Unable to find the account!"); + } + } + else + { + PERR("account ID for this transaction is unavailable!"); + } + + core->bTransactionList_.addTransaction(core, pTransaction); + + return 0; +}//end ofx_proc_transaction() + +/* + int ofx_proc_statement_cb(struct OfxStatementData data, void * statement_user_data) + { + return 0; + }//end ofx_proc_statement() + */ + +int ofx_proc_account_cb(struct OfxAccountData data, /*void * account_user_data*/) +{ + Account *selected_account; + gnc_commodity_table * commodity_table; + gnc_commodity * default_commodity; + GNCAccountType default_type=ACCT_TYPE_NONE; + gchar * account_description; + gchar * account_type_name = NULL; + + + //Find out if account data is valid + if(data.account_id_valid==true){ + + //Check to see if account exists + //If account exists load account + //Else set default for new account wizzard to account + //If select account, load that account + //Else, create a new account by running the new account wizzard with the account number filled in and not modifiable + + //Check to see if the currency is valid + if( data.currency_valid == true) + { + //Log the currency + DEBUG("Currency from libofx: %s",data.currency); + //Set the currency for the account to data.currency + default_commodity = gnc_commodity_table_lookup(commodity_table, + GNC_COMMODITY_NS_CURRENCY, + data.currency); + } + else + { + default_commodity = NULL; + } + + //Make sure the account type is valid + if(data.account_type_valid==true){ + switch(data.account_type){ + case OFX_CHECKING : + //Set the default for the new account wizzard to Checking/Savings + default_type=ACCT_TYPE_BANK; + account_type_name = g_strdup_printf(_("Unknown OFX checking account")); + break; + case OFX_SAVINGS : + default_type=ACCT_TYPE_BANK; + account_type_name = g_strdup_printf(_("Unknown OFX savings account")); + break; + case OFX_MONEYMRKT : + default_type=ACCT_TYPE_MONEYMRKT; + account_type_name = g_strdup_printf(_("Unknown OFX money market account")); + break; + case OFX_CREDITLINE : + default_type=ACCT_TYPE_CREDITLINE; + account_type_name = g_strdup_printf(_("Unknown OFX credit line account")); + break; + case OFX_CMA : + default_type=ACCT_TYPE_NONE; + account_type_name = g_strdup_printf(_("Unknown OFX CMA account")); + break; + case OFX_CREDITCARD : + default_type=ACCT_TYPE_CREDIT; + account_type_name = g_strdup_printf(_("Unknown OFX credit card account")); + break; + case OFX_INVESTMENT : + default_type=ACCT_TYPE_BANK; + account_type_name = g_strdup_printf(_("Unknown OFX investment account")); + break; + default: PERR("WRITEME: ofx_proc_account() This is an unknown account type!"); + } + } + + gnc_utf8_strip_invalid(data.account_name); + account_description = g_strdup_printf( /* This string is a default account + name. It MUST NOT contain the + character ':' anywhere in it or + in any translation. */ + "%s \"%s\"", + account_type_name, + data.account_name); + selected_account = gnc_import_select_account(NULL, + data.account_id, 1, + account_description, default_commodity, + default_type, NULL, NULL); + g_free(account_description); + g_free(account_type_name); + } + else + { + PERR("account online ID not available"); + } + + return 0; +} + +void mmOfxImport () +{ + extern int ofx_PARSER_msg; + extern int ofx_DEBUG_msg; + extern int ofx_WARNING_msg; + extern int ofx_ERROR_msg; + extern int ofx_INFO_msg; + extern int ofx_STATUS_msg; + char *selected_filename; + char *default_dir; + LibofxContextPtr libofx_context = libofx_get_new_context(); + + ofx_PARSER_msg = false; + ofx_DEBUG_msg = false; + ofx_WARNING_msg = true; + ofx_ERROR_msg = true; + ofx_INFO_msg = true; + ofx_STATUS_msg = false; + + DEBUG("gnc_file_ofx_import(): Begin...\n"); + + default_dir = gnc_get_default_directory(GCONF_SECTION); + selected_filename = gnc_file_dialog(_("Select an OFX/QFX file to process"), + NULL, + default_dir, + GNC_FILE_DIALOG_IMPORT); + g_free(default_dir); + + if(selected_filename!=NULL) + { + + + /* Remember the directory as the default. */ + default_dir = g_path_get_dirname(selected_filename); + gnc_set_default_directory(GCONF_SECTION, default_dir); + g_free(default_dir); + + /*strncpy(file,selected_filename, 255);*/ + DEBUG("Filename found: %s",selected_filename); + + /* Create the Generic transaction importer GUI. */ + gnc_ofx_importer_gui = gnc_gen_trans_list_new(NULL, NULL, FALSE, 42); + + /* Initialize libofx */ + + /*ofx_set_statement_cb(libofx_context, ofx_proc_statement_cb, 0);*/ + ofx_set_account_cb(libofx_context, ofx_proc_account_cb, 0); + ofx_set_transaction_cb(libofx_context, ofx_proc_transaction_cb, 0); + ofx_set_security_cb(libofx_context, ofx_proc_security_cb, 0); + /*ofx_set_status_cb(libofx_context, ofx_proc_status_cb, 0);*/ + + + + DEBUG("Opening selected file"); + libofx_proc_file(libofx_context, selected_filename, AUTODETECT); + free(selected_filename); + } + +} + + + Added: trunk/src/import_export/ofximport.h.new =================================================================== --- trunk/src/import_export/ofximport.h.new (rev 0) +++ trunk/src/import_export/ofximport.h.new 2013-07-01 12:43:28 UTC (rev 4225) @@ -0,0 +1,15 @@ +/* + * ofximport.h + * moneymanagerex + * + * Created by Wesley Ellis on 11/12/09. + * Copyright 2009 __MyCompanyName__. All rights reserved. + * + */ + +#ifndef OFX_IMPORT_H +#define OFX_IMPORT_H + + +void mmOfxImport(); +#endif Added: trunk/src/import_export/qif_export.cpp =================================================================== --- trunk/src/import_export/qif_export.cpp (rev 0) +++ trunk/src/import_export/qif_export.cpp 2013-07-01 12:43:28 UTC (rev 4225) @@ -0,0 +1,558 @@ +/******************************************************* + ********************************************************/ +#include "../constants.h" +#include "qif_export.h" +#include "../util.h" +#include "../paths.h" + +IMPLEMENT_DYNAMIC_CLASS( mmQIFExportDialog, wxDialog ) + +BEGIN_EVENT_TABLE( mmQIFExportDialog, wxDialog ) + EVT_CHECKBOX(wxID_ANY, mmQIFExportDialog::OnCheckboxClick ) + EVT_BUTTON(wxID_OK, mmQIFExportDialog::OnOk) + EVT_BUTTON(wxID_CANCEL, mmQIFExportDialog::OnCancel) + EVT_CLOSE(mmQIFExportDialog::OnQuit) +END_EVENT_TABLE() + +mmQIFExportDialog::mmQIFExportDialog( + mmCoreDB* core, + wxWindow* parent, wxWindowID id, + const wxString& caption, const wxPoint& pos, + const wxSize& size, long style +) : + core_(core), + parent_(parent) +{ + Create(parent, id, caption, pos, size, style); +} + +bool mmQIFExportDialog::Create( wxWindow* parent, wxWindowID id, const wxString& caption, + const wxPoint& pos, const wxSize& size, long style ) +{ + SetExtraStyle(GetExtraStyle()|wxWS_EX_BLOCK_EVENTS); + wxDialog::Create( parent, id, caption, pos, size, style ); + + CreateControls(); + GetSizer()->Fit(this); + GetSizer()->SetSizeHints(this); + SetIcon(mmex::getProgramIcon()); + Centre(); + Fit(); + + fillControls(); + + return TRUE; +} + +void mmQIFExportDialog::fillControls() +{ + wxArrayString accounts_type; + accounts_type.Add(ACCOUNT_TYPE_BANK); + accounts_type.Add(ACCOUNT_TYPE_TERM); + accounts_id_ = core_->accountList_.getAccountsID(accounts_type); + + for (size_t i = 0; i < accounts_id_.Count(); ++i) + { + accounts_name_.Add(core_->accountList_.GetAccountName(accounts_id_[i])); + items_index_.Add(i); + } +} + +void mmQIFExportDialog::CreateControls() +{ + int border = 5; + int fieldWidth = 180; + wxSizerFlags flags, flagsExpand; + flags.Align(wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL).Border(wxALL, border); + flagsExpand.Align(wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL).Border(wxALL, border).Expand().Proportion(1); + + wxBoxSizer* main_sizer = new wxBoxSizer(wxVERTICAL); + this->SetSizer(main_sizer); + wxBoxSizer* box_sizer1 = new wxBoxSizer(wxVERTICAL); + main_sizer->Add(box_sizer1, flagsExpand); + + wxNotebook* export_notebook = new wxNotebook(this, + wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_MULTILINE ); + wxPanel* main_tab = new wxPanel(export_notebook, wxID_ANY); + export_notebook->AddPage(main_tab, _("Parameters")); + wxBoxSizer *tab1_sizer = new wxBoxSizer(wxVERTICAL); + main_tab->SetSizer(tab1_sizer); + + wxPanel* log_tab = new wxPanel(export_notebook, wxID_ANY); + export_notebook->AddPage(log_tab, _("Log")); + wxBoxSizer *tab2_sizer = new wxBoxSizer(wxVERTICAL); + log_tab->SetSizer(tab2_sizer); + + box_sizer1->Add(export_notebook, flagsExpand); + + // + wxString choices[] = { _("QIF"), _("CSV")}; + int num = sizeof(choices) / sizeof(wxString); + m_radio_box_ = new wxRadioBox(main_tab, wxID_ANY, "" + , wxDefaultPosition, wxDefaultSize, num, choices, 2, wxRA_SPECIFY_COLS); + tab1_sizer->Add(m_radio_box_, flags.Center()); + + wxFlexGridSizer* flex_sizer = new wxFlexGridSizer(0, 2, 0, 0); + tab1_sizer->Add(flex_sizer, flags.Left()); + + // Categories ------------------------------------------------- + cCategs_ = new wxCheckBox(main_tab, wxID_ANY, + _("Categories"), wxDefaultPosition, wxDefaultSize, wxCHK_2STATE ); + cCategs_->SetValue(FALSE); + flex_sizer->Add(cCategs_, flags); + flex_sizer->AddSpacer(1); + + // Accounts -------------------------------------------- + accountsCheckBox_ = new wxCheckBox( main_tab, wxID_ANY, _("Accounts") + , wxDefaultPosition, wxDefaultSize, wxCHK_2STATE ); + bSelectedAccounts_ = new wxButton(main_tab, wxID_STATIC, _("All") + , wxDefaultPosition, wxSize(fieldWidth,-1)); + bSelectedAccounts_ -> Connect(wxID_ANY, + wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(mmQIFExportDialog::OnAccountsButton), NULL, this); + accountsCheckBox_->SetValue(true); + flex_sizer->Add(accountsCheckBox_, flags); + flex_sizer->Add(bSelectedAccounts_, flags); + + // From Date -------------------------------------------- + dateFromCheckBox_ = new wxCheckBox( main_tab, wxID_ANY, _("From Date") + , wxDefaultPosition, wxDefaultSize, wxCHK_2STATE ); + fromDateCtrl_ = new wxDatePickerCtrl( main_tab, wxID_STATIC, wxDefaultDateTime + , wxDefaultPosition, wxSize(fieldWidth,-1), wxDP_DROPDOWN); + fromDateCtrl_->Enable(false); + flex_sizer->Add(dateFromCheckBox_, flags); + flex_sizer->Add(fromDateCtrl_, flags); + + // To Date -------------------------------------------- + dateToCheckBox_ = new wxCheckBox( main_tab, wxID_ANY, _("To Date") + , wxDefaultPosition, wxDefaultSize, wxCHK_2STATE ); + toDateCtrl_ = new wxDatePickerCtrl( main_tab, wxID_STATIC, wxDefaultDateTime + , wxDefaultPosition, wxSize(fieldWidth,-1), wxDP_DROPDOWN); + toDateCtrl_->Enable(false); + flex_sizer->Add(dateToCheckBox_, flags); + flex_sizer->Add(toDateCtrl_, flags); + + // Encoding -------------------------------------------- + + // File Name -------------------------------------------- + toFileCheckBox_ = new wxCheckBox( main_tab, wxID_ANY, _("Write to File") + , wxDefaultPosition, wxDefaultSize, wxCHK_2STATE ); + toFileCheckBox_->SetValue(true); + file_name_label_ = new wxStaticText(main_tab, wxID_ANY, _("File Name:")); + button_search_ = new wxButton(main_tab, wxID_SAVE, _("Choose &file")); + button_search_->Connect(wxID_SAVE, wxEVT_COMMAND_BUTTON_CLICKED + , wxCommandEventHandler(mmQIFExportDialog::OnFileSearch), NULL, this); + + m_text_ctrl_ = new wxTextCtrl(main_tab, wxID_FILE, wxEmptyString, + wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER ); + m_text_ctrl_->Connect(wxID_FILE, wxEVT_COMMAND_TEXT_UPDATED + , wxCommandEventHandler(mmQIFExportDialog::OnFileNameChanged), NULL, this); + m_text_ctrl_->Connect(wxID_FILE, wxEVT_COMMAND_TEXT_ENTER + , wxCommandEventHandler(mmQIFExportDialog::OnFileNameEntered), NULL, this); + + flex_sizer->Add(toFileCheckBox_, flags); + flex_sizer->AddSpacer(1); + flex_sizer->Add(file_name_label_, flags); + flex_sizer->Add(button_search_, flags); + tab1_sizer->Add(m_text_ctrl_, 0, wxALL|wxGROW, border); + + //Log viewer + log_field_ = new wxTextCtrl( log_tab, wxID_ANY, "" + , wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxHSCROLL ); + tab2_sizer->Add(log_field_, 1, wxGROW|wxALL, border); + + wxButton* itemClearButton = new wxButton(log_tab, wxID_CLEAR, _("Clear")); + tab2_sizer->Add(itemClearButton, flags.Center()); + itemClearButton->Connect(wxID_CLEAR, wxEVT_COMMAND_BUTTON_CLICKED + , wxCommandEventHandler(mmQIFExportDialog::OnButtonClear), NULL, this); + + /********************************************************************************************** + Button Panel with OK and Cancel Buttons + ***********************************************************************************************/ + wxPanel* buttons_panel = new wxPanel(this, wxID_ANY); + main_sizer->Add(buttons_panel, flags.Center().Border(wxALL, 0)); + + wxStdDialogButtonSizer* buttons_sizer = new wxStdDialogButtonSizer; + buttons_panel->SetSizer(buttons_sizer); + + wxButton* itemButtonOK = new wxButton( buttons_panel, wxID_OK, _("&OK")); + wxButton* itemButtonCancel_ = new wxButton( buttons_panel, wxID_CANCEL, _("&Cancel")); + itemButtonOK->Connect(wxID_OK, wxEVT_COMMAND_BUTTON_CLICKED + , wxCommandEventHandler(mmQIFExportDialog::OnOk), NULL, this); + + buttons_sizer->Add(itemButtonOK, flags.Border(wxBOTTOM|wxRIGHT, 10)); + buttons_sizer->Add(itemButtonCancel_, flags); + + buttons_sizer->Realize(); + +} + +void mmQIFExportDialog::OnButtonClear(wxCommandEvent& /*event*/) +{ + log_field_->Clear(); +} + +void mmQIFExportDialog::OnAccountsButton(wxCommandEvent& /*event*/) +{ + items_index_.clear(); + wxMultiChoiceDialog s_acc(this, _("Choose Account to Export from:") + , _("QIF Export"), accounts_name_); + if (s_acc.ShowModal() == wxID_OK) + items_index_ = s_acc.GetSelections(); + if (items_index_.GetCount() == 1) + { + bSelectedAccounts_->SetLabel(core_->accountList_.GetAccountName(accounts_id_[items_index_[0]])); + } + else if (items_index_.GetCount() > 1) + { + bSelectedAccounts_->SetLabel("..."); + } + for (size_t i = 0; i < items_index_.GetCount(); ++i) + { + *log_field_ << (core_->accountList_.GetAccountName(accounts_id_[items_index_[i]])); + *log_field_ << "\n"; + } +} + +void mmQIFExportDialog::OnFileSearch(wxCommandEvent& /*event*/) +{ + wxString fileName = m_text_ctrl_->GetValue(); + const bool qif_csv = m_radio_box_->GetSelection() == 0; + + const wxString choose_ext = qif_csv ? _("QIF Files") : _("CSV Files"); + fileName = wxFileSelector(qif_csv + ? _("Choose QIF data file to Export") + : _("Choose CSV data file to Export"), + wxEmptyString, fileName, wxEmptyString, + choose_ext + (qif_csv ? " (*.qif)|*.qif;*.QIF" : " (*.csv)|*.csv;*.CSV") + , wxFD_SAVE | wxFD_OVERWRITE_PROMPT); + + if (!fileName.IsEmpty()) + correctEmptyFileExt(qif_csv ? "qif":"csv" , fileName); + m_text_ctrl_->SetValue(fileName); +} + +void mmQIFExportDialog::OnOk(wxCommandEvent& /*event*/) +{ + bool bCorrect = false; + wxString sErrorMsg = ""; + if (core_->accountList_.getNumAccounts() == 0 && accountsCheckBox_->GetValue()) + { + sErrorMsg =_("No Account available for export"); + } + else if (items_index_.Count() < 1 && accountsCheckBox_->GetValue()) + { + sErrorMsg =_("No Accounts selected for export"); + } + else if (toFileCheckBox_->GetValue() && m_text_ctrl_->GetValue().IsEmpty()) + { + sErrorMsg =_("File name is empty"); + } + else if (dateToCheckBox_->GetValue() && dateFromCheckBox_->GetValue() && fromDateCtrl_->GetValue() > toDateCtrl_->GetValue()) + { + sErrorMsg =_("To Date less than From Date"); + } + else + bCorrect = true; + + if (bCorrect) + mmExportQIF(); + else + wxMessageBox(sErrorMsg, _("QIF Export"), wxOK|wxICON_WARNING); +} + +void mmQIFExportDialog::OnCancel(wxCommandEvent& /*event*/) +{ + + EndModal(wxID_CANCEL); +} + +void mmQIFExportDialog::OnQuit(wxCloseEvent& /*event*/) +{ + EndModal(wxID_CANCEL); +} +void mmQIFExportDialog::OnCheckboxClick( wxCommandEvent& /*event*/ ) +{ + bSelectedAccounts_->Enable(accountsCheckBox_->GetValue()); + if (dateFromCheckBox_->GetValue()) dateFromCheckBox_->SetValue(accountsCheckBox_->GetValue()); + if (dateToCheckBox_->GetValue()) dateToCheckBox_->SetValue(accountsCheckBox_->GetValue()); + fromDateCtrl_->Enable(dateFromCheckBox_->GetValue()); + toDateCtrl_->Enable(dateToCheckBox_->GetValue()); + button_search_->Enable(toFileCheckBox_->GetValue()); + file_name_label_->Enable(toFileCheckBox_->GetValue()); + m_text_ctrl_->Enable(toFileCheckBox_->GetValue()); + +} + +void mmQIFExportDialog::OnFileNameChanged(wxCommandEvent& event) +{ + wxString file_name = m_text_ctrl_->GetValue(); + if (file_name.Contains("\n") || file_name.Contains("file://")) + { + + file_name.Replace("\n", ""); +#ifdef __WXGTK__ + file_name.Replace("file://", ""); + file_name.Trim(); +#endif + m_text_ctrl_->SetEvtHandlerEnabled(false); + m_text_ctrl_->SetValue(file_name); + m_text_ctrl_->SetEvtHandlerEnabled(true); + } + event.Skip(); + + wxFileName csv_file(file_name); + +} +void mmQIFExportDialog::OnFileNameEntered(wxCommandEvent& event) +{ + wxString file_name = m_text_ctrl_->GetValue(); + file_name.Trim(); + + event.Skip(); + wxCommandEvent evt(wxEVT_COMMAND_BUTTON_CLICKED, wxID_SAVE); + this->GetEventHandler()->AddPendingEvent(evt); +} + +wxString mmQIFExportDialog::writeAccHeader(int accountID, bool qif) +{ + wxString buffer = ""; + if (qif) + { + mmAccount* pAccount = core_->accountList_.GetAccountSharedPtr(accountID); + wxASSERT(pAccount); + mmCurrency* pCurrency = pAccount->currency_; + wxASSERT(pCurrency); + + const wxString sAccName = core_->accountList_.GetAccountName(accountID); + double dInitBalance = pAccount->initialBalance_; + const wxString sInitBalance = wxString::Format("%f", dInitBalance); + const wxString sCurrencyCode = "[" + pCurrency->currencySymbol_ + "]"; + + buffer = wxString("!Account") << "\n" + << "N" << sAccName << "\n" + << "TBank" << "\n" + << "D" << sCurrencyCode << "\n" + << (dInitBalance != 0 ? wxString("$") << sInitBalance << "\n" : "") + << "^" << "\n" + << "!Type:Cash" << "\n"; + } + return buffer; +} + +wxString mmQIFExportDialog::exportCategories(bool qif) +{ + wxString buffer_qif, buffer_csv; + + buffer_qif << "!Type:Cat" << "\n"; + for (const auto& category: core_->categoryList_.entries_) + { + const wxString categ_name = category->categName_; + bool bIncome = false; + core_->bTransactionList_.IsCategoryUsed(category->categID_ + , -1, bIncome, false); + buffer_qif << "N" << categ_name << "\n" + << (bIncome ? "I" : "E") << "\n" + << "^" << "\n"; + buffer_csv << categ_name << delimit_ << "\n"; + + for (const auto& sub_category: category->children_) + { + bIncome = false; + bool bSubcateg = sub_category->categID_ != -1; + core_->bTransactionList_.IsCategoryUsed(category->categID_ + , sub_category->categID_, bIncome, false); + wxString full_categ_name = wxString() + << categ_name << (qif ? (bSubcateg ? wxString()<<":" : wxString()<<"") : delimit_) + << sub_category->categName_; + buffer_qif << "N" << full_categ_name << "\n" + << (bIncome ? "I" : "E") << "\n" + << "^" << "\n"; + buffer_csv << full_categ_name << "\n"; + } + } + return qif ? buffer_qif : buffer_csv; +} + +void mmQIFExportDialog::mmExportQIF() +{ + const bool qif_csv = m_radio_box_->GetSelection() == 0; + const bool exp_categ = cCategs_->GetValue(); + const bool exp_transactions = (accountsCheckBox_->GetValue() && items_index_.GetCount()>0); + const bool write_to_file = toFileCheckBox_->GetValue(); + wxString sErrorMsg; + wxString buffer; + delimit_ = core_->dbInfoSettings_->GetStringSetting("DELIMITER", mmex::DEFDELIMTER); + long numRecords = 0; + + //Export categories + if (exp_categ) + { + buffer << exportCategories(qif_csv); + sErrorMsg << _("Categories exported") << "\n"; + } + + //Export transactions + numRecords = 0; + wxArrayInt transferTrxId; + + if (exp_transactions) + { + wxArrayInt selected_accounts_id; + for (size_t a = 0; a < items_index_.Count() ; ++a) + { + selected_accounts_id.Add(accounts_id_[items_index_[a]]); + } + + for (size_t a = 0; a < selected_accounts_id.Count(); ++a) + { + int fromAccountID = selected_accounts_id[a]; + wxString acctName = core_->accountList_.GetAccountName(fromAccountID); + + buffer << writeAccHeader(fromAccountID, qif_csv); + + for (const auto& pBankTransaction : core_->bTransactionList_.transactions_) + { + if ((pBankTransaction->accountID_ != fromAccountID) && (pBankTransaction->toAccountID_ != fromAccountID)) + continue; + + if (dateFromCheckBox_->GetValue() && pBankTransaction->date_ < fromDateCtrl_->GetValue() ) + continue; + if (dateToCheckBox_->GetValue() && pBankTransaction->date_ > toDateCtrl_->GetValue() ) + continue; + + wxDateTime dtdt = pBankTransaction->date_; + wxString dateString = mmGetDateForDisplay(dtdt); + + wxString payee = core_->payeeList_.GetPayeeName(pBankTransaction->payeeID_); + wxString type = pBankTransaction->transType_; + + int trans_id = pBankTransaction->transactionID(); + int fAccountID = pBankTransaction->accountID_; + const wxString fromAccount = core_->accountList_.GetAccountName(fAccountID); + int tAccountID = pBankTransaction->toAccountID_; + + wxString transNum = pBankTransaction->transNum_; + wxString categ = ""; + if (pBankTransaction->categID_ != -1) + categ = pBankTransaction->fullCatStr_; + wxString notes = (pBankTransaction->notes_); + notes.Replace("''", "'"); + notes.Replace("\n", " "); + + double value = pBankTransaction->amt_; + wxString amount = /*adjustedExportAmount(amtSeparator,*/ wxString()<<value/*)*/; + wxString toamount; + + if (transferTrxId.Index(trans_id) == wxNOT_FOUND) + numRecords++; + if (type == "Transfer") + { + const wxString toAccount = core_->accountList_.GetAccountName(tAccountID); + double tovalue = pBankTransaction->toAmt_; + toamount = /*adjustedExportAmount(amtSeparator,*/ wxString()<<tovalue/*)*/; + wxString amount_temp = amount; + + if (tAccountID == fromAccountID) { + categ = wxString::Format("[%s]", fromAccount); + amount = toamount; + toamount = amount_temp; + toamount.Prepend("-"); + } else if (fAccountID == fromAccountID) { + categ = wxString::Format("[%s]", toAccount); + amount.Prepend("-"); + } + if (selected_accounts_id.Index(tAccountID) == wxNOT_FOUND) + transferTrxId.Add(trans_id); + //Transaction number used to make transaction unique + // to proper merge transfer records + if (transNum.IsEmpty() && notes.IsEmpty()) + transNum = wxString::Format("#%ld", trans_id); + } + else if (type == "Withdrawal") + amount.Prepend("-"); + + if (qif_csv) + { + buffer << "D" << dateString << "\n"; + buffer << "T" << amount << "\n"; + if (!payee.IsEmpty()) + buffer << "P" << payee << "\n"; + if (!transNum.IsEmpty()) + buffer << "N" << transNum << "\n"; + if (!categ.IsEmpty()) + buffer << "L" << categ << "\n"; + if (!notes.IsEmpty()) + buffer << "M" << notes << "\n"; + } + + //if categ id is empty that mean this is split transaction + if (pBankTransaction->categID_ == -1) + { + mmSplitTransactionEntries* splits = pBankTransaction->splitEntries_; + pBankTransaction->getSplitTransactions(splits); + + for (int i = 0; i < (int)splits->entries_.size(); ++i) + { + value = splits->entries_[i]->splitAmount_; + if (type == "Withdraw... [truncated message content] |