|
|
|
/***************************************************************************
|
|
|
|
reportstestcommon.cpp
|
|
|
|
-------------------
|
|
|
|
copyright : (C) 2002-2005 by Thomas Baumgart
|
|
|
|
email : ipwizard@users.sourceforge.net
|
|
|
|
Ace Jones <ace.j@hotpop.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. *
|
|
|
|
* *
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
#include <tqvaluelist.h>
|
|
|
|
#include <tqvaluevector.h>
|
|
|
|
#include <tqdom.h>
|
|
|
|
#include <tqfile.h>
|
|
|
|
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <tdeversion.h>
|
|
|
|
#include <kglobal.h>
|
|
|
|
#include <kglobalsettings.h>
|
|
|
|
#include <klocale.h>
|
|
|
|
#include <kstandarddirs.h>
|
|
|
|
|
|
|
|
#include "kreportsviewtest.h"
|
|
|
|
|
|
|
|
#define private public
|
|
|
|
#include "pivottable.h"
|
|
|
|
#include "tquerytable.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);
|
|
|
|
|
|
|
|
TQString acAsset;
|
|
|
|
TQString acLiability;
|
|
|
|
TQString acExpense;
|
|
|
|
TQString acIncome;
|
|
|
|
TQString acChecking;
|
|
|
|
TQString acCredit;
|
|
|
|
TQString acSolo;
|
|
|
|
TQString acParent;
|
|
|
|
TQString acChild;
|
|
|
|
TQString acSecondChild;
|
|
|
|
TQString acGrandChild1;
|
|
|
|
TQString acGrandChild2;
|
|
|
|
TQString acForeign;
|
|
|
|
TQString acCanChecking;
|
|
|
|
TQString acJpyChecking;
|
|
|
|
TQString acCanCash;
|
|
|
|
TQString acJpyCash;
|
|
|
|
TQString inBank;
|
|
|
|
TQString eqStock1;
|
|
|
|
TQString eqStock2;
|
|
|
|
TQString acInvestment;
|
|
|
|
TQString acStock1;
|
|
|
|
TQString acStock2;
|
|
|
|
TQString acDividends;
|
|
|
|
TQString acInterest;
|
|
|
|
TQString acTax;
|
|
|
|
TQString acCash;
|
|
|
|
|
|
|
|
TransactionHelper::TransactionHelper( const TQDate& _date, const TQString& _action, MyMoneyMoney _value, const TQString& _accountid, const TQString& _categoryid, const TQString& _currencyid, const TQString& _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);
|
|
|
|
|
|
|
|
TQString 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 TQDate& _date, const TQString& _action, MyMoneyMoney _shares, MyMoneyMoney _price, const TQString& _stockaccountid, const TQString& _transferid, const TQString& _categoryid )
|
|
|
|
{
|
|
|
|
init(_date, _action, _shares, _price, _stockaccountid, _transferid, _categoryid);
|
|
|
|
}
|
|
|
|
|
|
|
|
void InvTransactionHelper::init( const TQDate& _date, const TQString& _action, MyMoneyMoney _shares, MyMoneyMoney _price, const TQString& _stockaccountid, const TQString& _transferid, const TQString& _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
|
|
|
|
TQString stockid = stockaccount.currencyId();
|
|
|
|
TQString 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString makeAccount( const TQString& _name, MyMoneyAccount::accountTypeE _type, MyMoneyMoney _balance, const TQDate& _open, const TQString& _parent, TQString _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 TQString& _currencyid, const TQDate& _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();
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString makeEquity(const TQString& _name, const TQString& _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 TQString& _id, const TQDate& _date, const MyMoneyMoney& _price )
|
|
|
|
{
|
|
|
|
MyMoneyFile* file = MyMoneyFile::instance();
|
|
|
|
MyMoneyFileTransaction ft;
|
|
|
|
TQString 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, TQDomDocument* doc )
|
|
|
|
{
|
|
|
|
TQDomProcessingInstruction instruct = doc->createProcessingInstruction(TQString("xml"), TQString("version=\"1.0\" encoding=\"utf-8\""));
|
|
|
|
doc->appendChild(instruct);
|
|
|
|
|
|
|
|
TQDomElement root = doc->createElement("KMYMONEY-FILE");
|
|
|
|
doc->appendChild(root);
|
|
|
|
|
|
|
|
TQDomElement reports = doc->createElement("REPORTS");
|
|
|
|
root.appendChild(reports);
|
|
|
|
|
|
|
|
TQDomElement report = doc->createElement("REPORT");
|
|
|
|
filter.write(report,doc);
|
|
|
|
reports.appendChild(report);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void writeTabletoHTML( const PivotTable& table, const TQString& _filename )
|
|
|
|
{
|
|
|
|
static unsigned filenumber = 1;
|
|
|
|
TQString filename = _filename;
|
|
|
|
if ( filename.isEmpty() )
|
|
|
|
{
|
|
|
|
filename = TQString("report-%1%2.html").arg((filenumber<10)?"0":"").arg(filenumber);
|
|
|
|
++filenumber;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQFile g( filename );
|
|
|
|
g.open( IO_WriteOnly );
|
|
|
|
TQTextStream(&g) << table.renderHTML();
|
|
|
|
g.close();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void writeTabletoHTML( const QueryTable& table, const TQString& _filename )
|
|
|
|
{
|
|
|
|
static unsigned filenumber = 1;
|
|
|
|
TQString filename = _filename;
|
|
|
|
if ( filename.isEmpty() )
|
|
|
|
{
|
|
|
|
filename = TQString("report-%1%2.html").arg((filenumber<10)?"0":"").arg(filenumber);
|
|
|
|
++filenumber;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQFile g( filename );
|
|
|
|
g.open( IO_WriteOnly );
|
|
|
|
TQTextStream(&g) << table.renderHTML();
|
|
|
|
g.close();
|
|
|
|
}
|
|
|
|
|
|
|
|
void writeTabletoCSV( const PivotTable& table, const TQString& _filename )
|
|
|
|
{
|
|
|
|
static unsigned filenumber = 1;
|
|
|
|
TQString filename = _filename;
|
|
|
|
if ( filename.isEmpty() )
|
|
|
|
{
|
|
|
|
filename = TQString("report-%1%2.csv").arg((filenumber<10)?"0":"").arg(filenumber);
|
|
|
|
++filenumber;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQFile g( filename );
|
|
|
|
g.open( IO_WriteOnly );
|
|
|
|
TQTextStream(&g) << table.renderCSV();
|
|
|
|
g.close();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void writeTabletoCSV( const QueryTable& table, const TQString& _filename )
|
|
|
|
{
|
|
|
|
static unsigned filenumber = 1;
|
|
|
|
TQString filename = _filename;
|
|
|
|
if ( filename.isEmpty() )
|
|
|
|
{
|
|
|
|
filename = TQString("qreport-%1%2.csv").arg((filenumber<10)?"0":"").arg(filenumber);
|
|
|
|
++filenumber;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQFile g( filename );
|
|
|
|
g.open( IO_WriteOnly );
|
|
|
|
TQTextStream(&g) << table.renderCSV();
|
|
|
|
g.close();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void writeRCFtoXML( const MyMoneyReport& filter, const TQString& _filename )
|
|
|
|
{
|
|
|
|
static unsigned filenum = 1;
|
|
|
|
TQString filename = _filename;
|
|
|
|
if ( filename.isEmpty() ) {
|
|
|
|
filename = TQString("report-%1%2.xml").arg(TQString::number(filenum).rightJustify(2, '0'));
|
|
|
|
++filenum;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQDomDocument* doc = new TQDomDocument("KMYMONEY-FILE");
|
|
|
|
Q_CHECK_PTR(doc);
|
|
|
|
|
|
|
|
writeRCFtoXMLDoc(filter,doc);
|
|
|
|
|
|
|
|
TQFile g( filename );
|
|
|
|
g.open( IO_WriteOnly );
|
|
|
|
|
|
|
|
TQTextStream stream(&g);
|
|
|
|
#if KDE_IS_VERSION(3,2,0)
|
|
|
|
stream.setEncoding(TQTextStream::UnicodeUTF8);
|
|
|
|
stream << doc->toString();
|
|
|
|
#else
|
|
|
|
//stream.setEncoding(TQTextStream::Locale);
|
|
|
|
TQString temp = doc->toString();
|
|
|
|
stream << temp.data();
|
|
|
|
#endif
|
|
|
|
g.close();
|
|
|
|
|
|
|
|
delete doc;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool readRCFfromXMLDoc( TQValueList<MyMoneyReport>& list, TQDomDocument* doc )
|
|
|
|
{
|
|
|
|
bool result = false;
|
|
|
|
|
|
|
|
TQDomElement rootElement = doc->documentElement();
|
|
|
|
if(!rootElement.isNull())
|
|
|
|
{
|
|
|
|
TQDomNode child = rootElement.firstChild();
|
|
|
|
while(!child.isNull() && child.isElement())
|
|
|
|
{
|
|
|
|
TQDomElement childElement = child.toElement();
|
|
|
|
if("REPORTS" == childElement.tagName())
|
|
|
|
{
|
|
|
|
result = true;
|
|
|
|
TQDomNode 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( TQValueList<MyMoneyReport>& list, const TQString& filename )
|
|
|
|
{
|
|
|
|
int result = false;
|
|
|
|
TQFile f( filename );
|
|
|
|
f.open( IO_ReadOnly );
|
|
|
|
TQDomDocument* doc = new TQDomDocument;
|
|
|
|
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.
|
|
|
|
|
|
|
|
TQDomDocument* doc = new TQDomDocument("KMYMONEY-FILE");
|
|
|
|
Q_CHECK_PTR(doc);
|
|
|
|
|
|
|
|
writeRCFtoXMLDoc(filter,doc);
|
|
|
|
TQValueList<MyMoneyReport> 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 TQString& _html, const TQString& _search)
|
|
|
|
{
|
|
|
|
TQRegExp re(TQString("%1[<>/td]*([\\-.0-9,]*)").arg(_search));
|
|
|
|
re.search(_html);
|
|
|
|
TQString found = re.cap(1);
|
|
|
|
found.remove(',');
|
|
|
|
|
|
|
|
return MyMoneyMoney(found.toDouble());
|
|
|
|
}
|
|
|
|
|
|
|
|
} // end namespace test
|
|
|
|
|
|
|
|
// vim:cin:si:ai:et:ts=2:sw=2:
|