/*************************************************************************** reportstestcommon.cpp ------------------- copyright : (C) 2002-2005 by Thomas Baumgart email : ipwizard@users.sourceforge.net Ace Jones ***************************************************************************/ /*************************************************************************** * * * 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. * * * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include "kreportsviewtest.h" #define private public #include "pivottable.h" #include "querytable.h" #undef private using namespace reports; #include "../mymoney/mymoneysecurity.h" #include "../mymoney/mymoneyprice.h" #include "../mymoney/storage/mymoneystoragedump.h" #include "../mymoney/mymoneyreport.h" #include "../mymoney/mymoneystatement.h" #include "../mymoney/storage/mymoneystoragexml.h" #include "reportstestcommon.h" namespace test { const MyMoneyMoney moCheckingOpen(0.0); const MyMoneyMoney moCreditOpen(-0.0); const MyMoneyMoney moConverterCheckingOpen(1418.0); const MyMoneyMoney moConverterCreditOpen(-418.0); const MyMoneyMoney moZero(0.0); const MyMoneyMoney moSolo(234.12); const MyMoneyMoney moParent1(88.01); const MyMoneyMoney moParent2(133.22); const MyMoneyMoney moParent(moParent1+moParent2); const MyMoneyMoney moChild(14.00); const MyMoneyMoney moThomas(5.11); const MyMoneyMoney moNoPayee(8944.70); QString acAsset; QString acLiability; QString acExpense; QString acIncome; QString acChecking; QString acCredit; QString acSolo; QString acParent; QString acChild; QString acSecondChild; QString acGrandChild1; QString acGrandChild2; QString acForeign; QString acCanChecking; QString acJpyChecking; QString acCanCash; QString acJpyCash; QString inBank; QString eqStock1; QString eqStock2; QString acInvestment; QString acStock1; QString acStock2; QString acDividends; QString acInterest; QString acTax; QString acCash; TransactionHelper::TransactionHelper( const QDate& _date, const QString& _action, MyMoneyMoney _value, const QString& _accountid, const QString& _categoryid, const QString& _currencyid, const QString& _payee ) { // _currencyid is the currency of the transaction, and of the _value // both the account and category can have their own currency (athough the category having // a foreign currency is not yet supported by the program, the reports will still allow it, // so it must be tested.) MyMoneyFile* file = MyMoneyFile::instance(); bool haspayee = ! _payee.isEmpty(); MyMoneyPayee payeeTest = file->payeeByName(_payee); MyMoneyFileTransaction ft; setPostDate(_date); QString currencyid = _currencyid; if ( currencyid.isEmpty() ) currencyid=MyMoneyFile::instance()->baseCurrency().id(); setCommodity(currencyid); MyMoneyMoney price; MyMoneySplit splitLeft; if ( haspayee ) splitLeft.setPayeeId(payeeTest.id()); splitLeft.setAction(_action); splitLeft.setValue(-_value); price = MyMoneyFile::instance()->price(currencyid, file->account(_accountid).currencyId(),_date).rate(file->account(_accountid).currencyId()); splitLeft.setShares(-_value * price); splitLeft.setAccountId(_accountid); addSplit(splitLeft); MyMoneySplit splitRight; if ( haspayee ) splitRight.setPayeeId(payeeTest.id()); splitRight.setAction(_action); splitRight.setValue(_value); price = MyMoneyFile::instance()->price(currencyid, file->account(_categoryid).currencyId(),_date).rate(file->account(_categoryid).currencyId()); splitRight.setShares(_value * price ); splitRight.setAccountId(_categoryid); addSplit(splitRight); MyMoneyFile::instance()->addTransaction(*this); ft.commit(); } TransactionHelper::~TransactionHelper() { MyMoneyFileTransaction ft; MyMoneyFile::instance()->removeTransaction(*this); ft.commit(); } void TransactionHelper::update(void) { MyMoneyFileTransaction ft; MyMoneyFile::instance()->modifyTransaction(*this); ft.commit(); } InvTransactionHelper::InvTransactionHelper( const QDate& _date, const QString& _action, MyMoneyMoney _shares, MyMoneyMoney _price, const QString& _stockaccountid, const QString& _transferid, const QString& _categoryid ) { init(_date, _action, _shares, _price, _stockaccountid, _transferid, _categoryid); } void InvTransactionHelper::init( const QDate& _date, const QString& _action, MyMoneyMoney _shares, MyMoneyMoney _price, const QString& _stockaccountid, const QString& _transferid, const QString& _categoryid ) { MyMoneyFile* file = MyMoneyFile::instance(); MyMoneyAccount stockaccount = file->account(_stockaccountid); MyMoneyMoney value = _shares * _price; setPostDate(_date); setCommodity("USD"); MyMoneySplit s1; s1.setValue(value); s1.setAccountId(_stockaccountid); if ( _action == MyMoneySplit::ActionReinvestDividend ) { s1.setShares(_shares); s1.setAction(MyMoneySplit::ActionReinvestDividend); MyMoneySplit s2; s2.setAccountId(_categoryid); s2.setShares(-value); s2.setValue(-value); addSplit(s2); } else if ( _action == MyMoneySplit::ActionDividend || _action == MyMoneySplit::ActionYield ) { s1.setAccountId(_categoryid); s1.setShares(-value); s1.setValue(-value); // Split 2 will be the zero-amount investment split that serves to // mark this transaction as a cash dividend and note which stock account // it belongs to. MyMoneySplit s2; s2.setValue(0); s2.setShares(0); s2.setAction(_action); s2.setAccountId(_stockaccountid); addSplit(s2); MyMoneySplit s3; s3.setAccountId(_transferid); s3.setShares(value); s3.setValue(value); addSplit(s3); } else if ( _action == MyMoneySplit::ActionBuyShares ) { s1.setShares(_shares); s1.setAction(MyMoneySplit::ActionBuyShares); MyMoneySplit s3; s3.setAccountId(_transferid); s3.setShares(-value); s3.setValue(-value); addSplit(s3); } addSplit(s1); //kdDebug(2) << "created transaction, now adding..." << endl; MyMoneyFileTransaction ft; file->addTransaction(*this); //kdDebug(2) << "updating price..." << endl; // update the price, while we're here QString stockid = stockaccount.currencyId(); QString basecurrencyid = file->baseCurrency().id(); MyMoneyPrice price = file->price( stockid, basecurrencyid, _date, true ); if ( !price.isValid() ) { MyMoneyPrice newprice( stockid, basecurrencyid, _date, _price, "test" ); file->addPrice(newprice); } ft.commit(); //kdDebug(2) << "successfully added " << id() << endl; } QString makeAccount( const QString& _name, MyMoneyAccount::accountTypeE _type, MyMoneyMoney _balance, const QDate& _open, const QString& _parent, QString _currency, bool _taxReport ) { MyMoneyAccount info; MyMoneyFileTransaction ft; info.setName(_name); info.setAccountType(_type); info.setOpeningDate(_open); if ( _currency != "" ) info.setCurrencyId(_currency); else info.setCurrencyId(MyMoneyFile::instance()->baseCurrency().id()); if(_taxReport) info.setValue("Tax", "Yes"); MyMoneyAccount parent = MyMoneyFile::instance()->account(_parent); MyMoneyFile::instance()->addAccount( info, parent ); // create the opening balance transaction if any if(!_balance.isZero()) { MyMoneySecurity sec = MyMoneyFile::instance()->currency(info.currencyId()); MyMoneyFile::instance()->openingBalanceAccount(sec); MyMoneyFile::instance()->createOpeningBalanceTransaction(info, _balance); } ft.commit(); return info.id(); } void makePrice(const QString& _currencyid, const QDate& _date, const MyMoneyMoney& _price ) { MyMoneyFileTransaction ft; MyMoneyFile* file = MyMoneyFile::instance(); MyMoneySecurity curr = file->currency(_currencyid); MyMoneyPrice price(_currencyid, file->baseCurrency().id(), _date, _price, "test"); file->addPrice(price); ft.commit(); } QString makeEquity(const QString& _name, const QString& _symbol ) { MyMoneySecurity equity; MyMoneyFileTransaction ft; equity.setName( _name ); equity.setTradingSymbol( _symbol ); equity.setSmallestAccountFraction( 1000 ); equity.setSecurityType( MyMoneySecurity::SECURITY_NONE /*MyMoneyEquity::ETYPE_STOCK*/ ); MyMoneyFile::instance()->addSecurity( equity ); ft.commit(); return equity.id(); } void makeEquityPrice(const QString& _id, const QDate& _date, const MyMoneyMoney& _price ) { MyMoneyFile* file = MyMoneyFile::instance(); MyMoneyFileTransaction ft; QString basecurrencyid = file->baseCurrency().id(); MyMoneyPrice price = file->price( _id, basecurrencyid, _date, true ); if ( !price.isValid() ) { MyMoneyPrice newprice( _id, basecurrencyid, _date, _price, "test" ); file->addPrice(newprice); } ft.commit(); } void writeRCFtoXMLDoc( const MyMoneyReport& filter, QDomDocument* doc ) { QDomProcessingInstruction instruct = doc->createProcessingInstruction(QString("xml"), QString("version=\"1.0\" encoding=\"utf-8\"")); doc->appendChild(instruct); QDomElement root = doc->createElement("KMYMONEY-FILE"); doc->appendChild(root); QDomElement reports = doc->createElement("REPORTS"); root.appendChild(reports); QDomElement report = doc->createElement("REPORT"); filter.write(report,doc); reports.appendChild(report); } void writeTabletoHTML( const PivotTable& table, const QString& _filename ) { static unsigned filenumber = 1; QString filename = _filename; if ( filename.isEmpty() ) { filename = QString("report-%1%2.html").arg((filenumber<10)?"0":"").arg(filenumber); ++filenumber; } QFile g( filename ); g.open( IO_WriteOnly ); QTextStream(&g) << table.renderHTML(); g.close(); } void writeTabletoHTML( const QueryTable& table, const QString& _filename ) { static unsigned filenumber = 1; QString filename = _filename; if ( filename.isEmpty() ) { filename = QString("report-%1%2.html").arg((filenumber<10)?"0":"").arg(filenumber); ++filenumber; } QFile g( filename ); g.open( IO_WriteOnly ); QTextStream(&g) << table.renderHTML(); g.close(); } void writeTabletoCSV( const PivotTable& table, const QString& _filename ) { static unsigned filenumber = 1; QString filename = _filename; if ( filename.isEmpty() ) { filename = QString("report-%1%2.csv").arg((filenumber<10)?"0":"").arg(filenumber); ++filenumber; } QFile g( filename ); g.open( IO_WriteOnly ); QTextStream(&g) << table.renderCSV(); g.close(); } void writeTabletoCSV( const QueryTable& table, const QString& _filename ) { static unsigned filenumber = 1; QString filename = _filename; if ( filename.isEmpty() ) { filename = QString("qreport-%1%2.csv").arg((filenumber<10)?"0":"").arg(filenumber); ++filenumber; } QFile g( filename ); g.open( IO_WriteOnly ); QTextStream(&g) << table.renderCSV(); g.close(); } void writeRCFtoXML( const MyMoneyReport& filter, const QString& _filename ) { static unsigned filenum = 1; QString filename = _filename; if ( filename.isEmpty() ) { filename = QString("report-%1%2.xml").arg(QString::number(filenum).rightJustify(2, '0')); ++filenum; } QDomDocument* doc = new QDomDocument("KMYMONEY-FILE"); Q_CHECK_PTR(doc); writeRCFtoXMLDoc(filter,doc); QFile g( filename ); g.open( IO_WriteOnly ); QTextStream stream(&g); #if KDE_IS_VERSION(3,2,0) stream.setEncoding(QTextStream::UnicodeUTF8); stream << doc->toString(); #else //stream.setEncoding(QTextStream::Locale); QString temp = doc->toString(); stream << temp.data(); #endif g.close(); delete doc; } bool readRCFfromXMLDoc( QValueList& list, QDomDocument* doc ) { bool result = false; QDomElement rootElement = doc->documentElement(); if(!rootElement.isNull()) { QDomNode child = rootElement.firstChild(); while(!child.isNull() && child.isElement()) { QDomElement childElement = child.toElement(); if("REPORTS" == childElement.tagName()) { result = true; QDomNode subchild = child.firstChild(); while(!subchild.isNull() && subchild.isElement()) { MyMoneyReport filter; if ( filter.read(subchild.toElement())) { list += filter; } subchild = subchild.nextSibling(); } } child = child.nextSibling(); } } return result; } bool readRCFfromXML( QValueList& list, const QString& filename ) { int result = false; QFile f( filename ); f.open( IO_ReadOnly ); QDomDocument* doc = new QDomDocument; if(doc->setContent(&f, FALSE)) { result = readRCFfromXMLDoc(list,doc); } delete doc; return result; } void XMLandback( MyMoneyReport& filter ) { // this function writes the filter to XML, and then reads // it back from XML overwriting the original filter; // in all cases, the result should be the same if the read // & write methods are working correctly. QDomDocument* doc = new QDomDocument("KMYMONEY-FILE"); Q_CHECK_PTR(doc); writeRCFtoXMLDoc(filter,doc); QValueList list; if ( readRCFfromXMLDoc(list,doc) && list.count() > 0 ) filter = list[0]; else throw new MYMONEYEXCEPTION("Failed to load report from XML"); delete doc; } MyMoneyMoney searchHTML(const QString& _html, const QString& _search) { QRegExp re(QString("%1[<>/td]*([\\-.0-9,]*)").arg(_search)); re.search(_html); QString found = re.cap(1); found.remove(','); return MyMoneyMoney(found.toDouble()); } } // end namespace test // vim:cin:si:ai:et:ts=2:sw=2: