/************************* * * * * * * * * * * * * *************************** Copyright (c) 1999-2005 Ryan Bobko ryan@ostrich-emulators.com 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, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ************************** * * * * * * * * * * * * **************************/ #include "ofxplugin.h" #include "qhacc.h" #include "qhaccext.h" #include "qhacctable.h" #include "qhaccutils.h" #include "guiconstants.h" #include // plugin factory calls extern "C" { QHaccPlugin * create(){ return new OFXImporter; } void destroy( OFXImporter * p ){ delete p; } } //extern OfxCallbackRegistry cb_registry; const OFXInfo OFXImporter::pinfo; OFXImporter::OFXImporter() : QHaccIOPlugin() { accounts=0; transactions=0; splits=0; } OFXImporter::~OFXImporter(){ delete accounts; delete transactions; delete splits; } const PluginInfo& OFXImporter::info() const { return pinfo; } bool OFXImporter::connect( QHacc * e, const QString& h, QString& ){ engine=e; home=h; transactions=new QHaccTable( QC::TCOLS, QC::TCOLTYPES, QC::TABLENAMES[QC::TRANT] ); accounts =new QHaccTable( QC::ACOLS, QC::ACOLTYPES, QC::TABLENAMES[QC::ACCTT] ); splits =new QHaccTable( QC::SCOLS, QC::SCOLTYPES, QC::TABLENAMES[QC::SPLTT] ); transactions->setPK( QC::TID ); accounts->setPK( QC::AID ); splits->setPK( QC::SID ); // figure out which journal we want auto_ptr rs=engine->getLs(); journal=rs->at( engine->getIP( "JOURNALINDEX" ) ); return true; } bool OFXImporter::load( QString& ){ LibofxContextPtr ofxctx=libofx_get_new_context(); ofx_set_statement_cb( ofxctx, OFXImporter::ofx_statement_cb, this ); ofx_set_account_cb( ofxctx, OFXImporter::ofx_account_cb, this ); ofx_set_transaction_cb( ofxctx, OFXImporter::ofx_transaction_cb, this ); ofx_set_security_cb( ofxctx, OFXImporter::ofx_security_cb, this ); ofx_set_status_cb( ofxctx, OFXImporter::ofx_status_cb, this ); /* ofx_prep_cb( (void *) this, OFXImporter::ofx_statement_cb, (void *) this, OFXImporter::ofx_account_cb, (void *) this, OFXImporter::ofx_transaction_cb, (void *) this, OFXImporter::ofx_security_cb, (void *) this, OFXImporter::ofx_status_cb ); char * file=new char[home.length()]; strcpy( file, home ); char * files[]={ file, file }; */ // libofx expects its arguments from the command line, so // we need to pad the first array index libofx_proc_file( ofxctx, home, AUTODETECT ); //delete [] file; return true; } bool OFXImporter::exprt( QHaccResultSet * data ){ data[QC::ACCTT].load( accounts ); data[QC::TRANT].load( transactions ); data[QC::SPLTT].load( splits ); /* for( int i=0; ihandleA( data ); return 0; } int OFXImporter::ofx_transaction_cb( const struct OfxTransactionData data, void * obj ){ ( ( OFXImporter * )obj )->handleT( data ); return 0; } int OFXImporter::ofx_security_cb( const struct OfxSecurityData, void * ){ std::ostream * str=0; if( Utils::debug( Utils::DBGMAJOR, str ) ) *str<<"security transactions are not implemented"<getBlankA(); if( data.account_id_valid ) acct.set( QC::ANUM, data.account_id ); //if( data.account_name_valid==true ) acct.set( QC::ANAME, data.account_name ); if( data.account_type_valid ){ switch( data.account_type ){ // these type numbers come from qhacc.cpp, setHome() function // but they should really come from the accounttypes table case OfxAccountData::OFX_CHECKING: acct.set( QC::ADEFAULTNUM, GUIC::ACCTINCRSTR ); case OfxAccountData::OFX_SAVINGS: acct.set( QC::ATYPE, QC::ASSET ); break; case OfxAccountData::OFX_CREDITLINE: case OfxAccountData::OFX_CREDITCARD: acct.set( QC::ATYPE, QC::LIABILITY ); break; case OfxAccountData::OFX_MONEYMRKT: case OfxAccountData::OFX_INVESTMENT: acct.set( QC::ATYPE, QC::EQUITY ); break; default: acct.set( QC::ATYPE, QC::EXPENSE ); } } Account a=accounts->getWhere( TableSelect( QC::ANAME, acct[QC::ANAME] ) ); if( a.isNull() ){ TableCol maxid( accounts->max( QC::AID ).getu()+1 ); acct.set( QC::AID, maxid ); accounts->add( acct ); a=acct; } return a; } void OFXImporter::handleT( const struct OfxTransactionData data ){ Transaction t( QC::TCOLS ); Split s( QC::SCOLS ); if( data.account_id_valid ){ Account a=accounts->getWhere( TableSelect( QC::ANUM, data.account_id ) ); if( a.isNull() ) a=handleA( *( data.account_ptr ) ); s.set( QC::SACCTID, a[QC::AID] ); } TableCol maxtid( transactions->max( QC::TID ).getu()+1 ); TableCol maxsid( splits->max( QC::SID ).getu()+1 ); t.set( QC::TID, maxtid ); t.set( QC::TTYPE, QC::REGULAR ); t.set( QC::TLID, journal[QC::LID] ); s.set( QC::SID, maxsid ); s.set( QC::STID, maxtid ); s.set( QC::SRECO, QC::NREC ); s.set( QC::SRECODATE, QC::XDATE ); if( data.name_valid ) t.set( QC::TPAYEE, data.name ); if( data.check_number_valid ) t.set( QC::TNUM, data.check_number ); if( data.amount_valid ) s.set( QC::SSUM, TableCol( ( float )data.amount ) ); if( data.memo_valid ) t.set( QC::TMEMO, data.memo ); if( data.date_posted_valid ){ tm * timer=localtime( &( data.date_posted ) ); t.set( QC::TDATE, QDate( 1900+timer->tm_year, timer->tm_mon+1, timer->tm_mday ) ); } transactions->add( t ); splits->add( s ); } OFXInfo::OFXInfo(){ targ=SINGLEFILE; description="Open Financial eXchange"; stubby="OFX"; }