diff --git a/kmymoney/mymoney/tests/mymoneyfile-test.cpp b/kmymoney/mymoney/tests/mymoneyfile-test.cpp index a3ee834f4..6b9de76e3 100644 --- a/kmymoney/mymoney/tests/mymoneyfile-test.cpp +++ b/kmymoney/mymoney/tests/mymoneyfile-test.cpp @@ -1,2780 +1,2828 @@ /*************************************************************************** mymoneyfiletest.cpp ------------------- copyright : (C) 2002 by Thomas Baumgart email : ipwizard@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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 "mymoneyfile-test.h" #include #include #include #include #include #include #include "mymoneystoragemgr_p.h" #include "mymoneytestutils.h" #include "mymoneymoney.h" #include "mymoneyinstitution.h" #include "mymoneyaccount.h" #include "mymoneysecurity.h" #include "mymoneytransaction.h" #include "mymoneytransactionfilter.h" #include "mymoneysplit.h" #include "mymoneyprice.h" #include "mymoneypayee.h" #include "mymoneyenums.h" #include "onlinejob.h" #include "payeeidentifier/ibanandbic/ibanbic.h" #include "payeeidentifier/payeeidentifierloader.h" #include "payeeidentifiertyped.h" #include "mymoneystoragenames.h" using namespace MyMoneyStandardAccounts; QTEST_GUILESS_MAIN(MyMoneyFileTest) void MyMoneyFileTest::objectAdded(eMyMoney::File::Object type, const QString& id) { Q_UNUSED(type); m_objectsAdded += id; } void MyMoneyFileTest::objectRemoved(eMyMoney::File::Object type, const QString& id) { Q_UNUSED(type); m_objectsRemoved += id; } void MyMoneyFileTest::objectModified(eMyMoney::File::Object type, const QString& id) { Q_UNUSED(type); m_objectsModified += id; } void MyMoneyFileTest::clearObjectLists() { m_objectsAdded.clear(); m_objectsModified.clear(); m_objectsRemoved.clear(); m_balanceChanged.clear(); m_valueChanged.clear(); } void MyMoneyFileTest::balanceChanged(const MyMoneyAccount& account) { m_balanceChanged += account.id(); } void MyMoneyFileTest::valueChanged(const MyMoneyAccount& account) { m_valueChanged += account.id(); } // this method will be called once at the beginning of the test void MyMoneyFileTest::initTestCase() { m = MyMoneyFile::instance(); connect(m, &MyMoneyFile::objectAdded, this, &MyMoneyFileTest::objectAdded); connect(m, &MyMoneyFile::objectRemoved, this, &MyMoneyFileTest::objectRemoved); connect(m, &MyMoneyFile::objectModified, this, &MyMoneyFileTest::objectModified); connect(m, &MyMoneyFile::balanceChanged, this, &MyMoneyFileTest::balanceChanged); connect(m, &MyMoneyFile::valueChanged, this, &MyMoneyFileTest::valueChanged); } // this method will be called before each testfunction void MyMoneyFileTest::init() { storage = new MyMoneyStorageMgr; m->attachStorage(storage); clearObjectLists(); } // this method will be called after each testfunction void MyMoneyFileTest::cleanup() { m->detachStorage(storage); delete storage; } void MyMoneyFileTest::testEmptyConstructor() { MyMoneyPayee user = m->user(); QCOMPARE(user.name(), QString()); QCOMPARE(user.address(), QString()); QCOMPARE(user.city(), QString()); QCOMPARE(user.state(), QString()); QCOMPARE(user.postcode(), QString()); QCOMPARE(user.telephone(), QString()); QCOMPARE(user.email(), QString()); QCOMPARE(m->institutionCount(), static_cast(0)); QCOMPARE(m->dirty(), false); QCOMPARE(m->accountCount(), static_cast(5)); } void MyMoneyFileTest::testAddOneInstitution() { MyMoneyInstitution institution; institution.setName("institution1"); institution.setTown("town"); institution.setStreet("street"); institution.setPostcode("postcode"); institution.setTelephone("telephone"); institution.setManager("manager"); institution.setSortcode("sortcode"); // MyMoneyInstitution institution_file("", institution); MyMoneyInstitution institution_id("I000002", institution); MyMoneyInstitution institution_noname(institution); institution_noname.setName(QString()); QString id; QCOMPARE(m->institutionCount(), static_cast(0)); storage->d_func()->m_dirty = false; clearObjectLists(); MyMoneyFileTransaction ft; try { m->addInstitution(institution); ft.commit(); QCOMPARE(institution.id(), QLatin1String("I000001")); QCOMPARE(m->institutionCount(), static_cast(1)); QCOMPARE(m->dirty(), true); QCOMPARE(m_objectsRemoved.count(), 0); QCOMPARE(m_objectsAdded.count(), 1); QCOMPARE(m_objectsModified.count(), 0); QCOMPARE(m_balanceChanged.count(), 0); QCOMPARE(m_valueChanged.count(), 0); QCOMPARE(m_objectsAdded[0], QLatin1String("I000001")); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } clearObjectLists(); ft.restart(); try { m->addInstitution(institution_id); QFAIL("Missing expected exception"); } catch (const MyMoneyException &) { ft.commit(); QCOMPARE(m->institutionCount(), static_cast(1)); } ft.restart(); try { m->addInstitution(institution_noname); QFAIL("Missing expected exception"); } catch (const MyMoneyException &) { ft.commit(); QCOMPARE(m->institutionCount(), static_cast(1)); } QCOMPARE(m_objectsRemoved.count(), 0); QCOMPARE(m_objectsAdded.count(), 0); QCOMPARE(m_objectsModified.count(), 0); QCOMPARE(m_balanceChanged.count(), 0); QCOMPARE(m_valueChanged.count(), 0); } void MyMoneyFileTest::testAddTwoInstitutions() { testAddOneInstitution(); MyMoneyInstitution institution; institution.setName("institution2"); institution.setTown("town"); institution.setStreet("street"); institution.setPostcode("postcode"); institution.setTelephone("telephone"); institution.setManager("manager"); institution.setSortcode("sortcode"); QString id; storage->d_func()->m_dirty = false; MyMoneyFileTransaction ft; try { m->addInstitution(institution); ft.commit(); QCOMPARE(institution.id(), QLatin1String("I000002")); QCOMPARE(m->institutionCount(), static_cast(2)); QCOMPARE(m->dirty(), true); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } storage->d_func()->m_dirty = false; try { institution = m->institution("I000001"); QCOMPARE(institution.id(), QLatin1String("I000001")); QCOMPARE(m->institutionCount(), static_cast(2)); QCOMPARE(m->dirty(), false); institution = m->institution("I000002"); QCOMPARE(institution.id(), QLatin1String("I000002")); QCOMPARE(m->institutionCount(), static_cast(2)); QCOMPARE(m->dirty(), false); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } } void MyMoneyFileTest::testRemoveInstitution() { testAddTwoInstitutions(); MyMoneyInstitution i; QCOMPARE(m->institutionCount(), static_cast(2)); i = m->institution("I000001"); QCOMPARE(i.id(), QLatin1String("I000001")); QCOMPARE(i.accountCount(), static_cast(0)); clearObjectLists(); storage->d_func()->m_dirty = false; MyMoneyFileTransaction ft; try { m->removeInstitution(i); QCOMPARE(m_objectsRemoved.count(), 0); ft.commit(); QCOMPARE(m->institutionCount(), static_cast(1)); QCOMPARE(m->dirty(), true); QCOMPARE(m_objectsRemoved.count(), 1); QCOMPARE(m_objectsAdded.count(), 0); QCOMPARE(m_objectsModified.count(), 0); QCOMPARE(m_balanceChanged.count(), 0); QCOMPARE(m_valueChanged.count(), 0); QCOMPARE(m_objectsRemoved[0], QLatin1String("I000001")); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } storage->d_func()->m_dirty = false; try { m->institution("I000001"); QFAIL("Missing expected exception"); } catch (const MyMoneyException &) { QCOMPARE(m->institutionCount(), static_cast(1)); QCOMPARE(m->dirty(), false); } clearObjectLists(); ft.restart(); try { m->removeInstitution(i); QFAIL("Missing expected exception"); } catch (const MyMoneyException &) { ft.commit(); QCOMPARE(m->institutionCount(), static_cast(1)); QCOMPARE(m->dirty(), false); QCOMPARE(m_objectsRemoved.count(), 0); } } void MyMoneyFileTest::testInstitutionRetrieval() { testAddOneInstitution(); storage->d_func()->m_dirty = false; MyMoneyInstitution institution; QCOMPARE(m->institutionCount(), static_cast(1)); try { institution = m->institution("I000001"); QCOMPARE(institution.id(), QLatin1String("I000001")); QCOMPARE(m->institutionCount(), static_cast(1)); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } try { institution = m->institution("I000002"); QFAIL("Missing expected exception"); } catch (const MyMoneyException &) { QCOMPARE(m->institutionCount(), static_cast(1)); } QCOMPARE(m->dirty(), false); } void MyMoneyFileTest::testInstitutionListRetrieval() { QList list; storage->d_func()->m_dirty = false; list = m->institutionList(); QCOMPARE(m->dirty(), false); QCOMPARE(list.count(), 0); testAddTwoInstitutions(); storage->d_func()->m_dirty = false; list = m->institutionList(); QCOMPARE(m->dirty(), false); QCOMPARE(list.count(), 2); QList::ConstIterator it; it = list.constBegin(); QVERIFY((*it).name() == "institution1" || (*it).name() == "institution2"); ++it; QVERIFY((*it).name() == "institution2" || (*it).name() == "institution1"); ++it; QVERIFY(it == list.constEnd()); } void MyMoneyFileTest::testInstitutionModify() { testAddTwoInstitutions(); MyMoneyInstitution institution; institution = m->institution("I000001"); institution.setStreet("new street"); institution.setTown("new town"); institution.setPostcode("new postcode"); institution.setTelephone("new telephone"); institution.setManager("new manager"); institution.setName("new name"); institution.setSortcode("new sortcode"); storage->d_func()->m_dirty = false; clearObjectLists(); MyMoneyFileTransaction ft; try { m->modifyInstitution(institution); ft.commit(); QCOMPARE(institution.id(), QLatin1String("I000001")); QCOMPARE(m->institutionCount(), static_cast(2)); QCOMPARE(m->dirty(), true); QCOMPARE(m_objectsRemoved.count(), 0); QCOMPARE(m_objectsAdded.count(), 0); QCOMPARE(m_objectsModified.count(), 1); QCOMPARE(m_balanceChanged.count(), 0); QCOMPARE(m_valueChanged.count(), 0); QCOMPARE(m_objectsModified[0], QLatin1String("I000001")); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } MyMoneyInstitution newInstitution; newInstitution = m->institution("I000001"); QCOMPARE(newInstitution.id(), QLatin1String("I000001")); QCOMPARE(newInstitution.street(), QLatin1String("new street")); QCOMPARE(newInstitution.town(), QLatin1String("new town")); QCOMPARE(newInstitution.postcode(), QLatin1String("new postcode")); QCOMPARE(newInstitution.telephone(), QLatin1String("new telephone")); QCOMPARE(newInstitution.manager(), QLatin1String("new manager")); QCOMPARE(newInstitution.name(), QLatin1String("new name")); QCOMPARE(newInstitution.sortcode(), QLatin1String("new sortcode")); storage->d_func()->m_dirty = false; ft.restart(); MyMoneyInstitution failInstitution2("I000003", newInstitution); try { m->modifyInstitution(failInstitution2); QFAIL("Exception expected"); } catch (const MyMoneyException &) { ft.commit(); QCOMPARE(failInstitution2.id(), QLatin1String("I000003")); QCOMPARE(m->institutionCount(), static_cast(2)); QCOMPARE(m->dirty(), false); } } void MyMoneyFileTest::testSetFunctions() { MyMoneyPayee user = m->user(); QCOMPARE(user.name(), QString()); QCOMPARE(user.address(), QString()); QCOMPARE(user.city(), QString()); QCOMPARE(user.state(), QString()); QCOMPARE(user.postcode(), QString()); QCOMPARE(user.telephone(), QString()); QCOMPARE(user.email(), QString()); MyMoneyFileTransaction ft; storage->d_func()->m_dirty = false; user.setName("Name"); m->setUser(user); QCOMPARE(m->dirty(), true); storage->d_func()->m_dirty = false; user.setAddress("Street"); m->setUser(user); QCOMPARE(m->dirty(), true); storage->d_func()->m_dirty = false; user.setCity("Town"); m->setUser(user); QCOMPARE(m->dirty(), true); storage->d_func()->m_dirty = false; user.setState("County"); m->setUser(user); QCOMPARE(m->dirty(), true); storage->d_func()->m_dirty = false; user.setPostcode("Postcode"); m->setUser(user); QCOMPARE(m->dirty(), true); storage->d_func()->m_dirty = false; user.setTelephone("Telephone"); m->setUser(user); QCOMPARE(m->dirty(), true); storage->d_func()->m_dirty = false; user.setEmail("Email"); m->setUser(user); QCOMPARE(m->dirty(), true); storage->d_func()->m_dirty = false; ft.commit(); user = m->user(); QCOMPARE(user.name(), QLatin1String("Name")); QCOMPARE(user.address(), QLatin1String("Street")); QCOMPARE(user.city(), QLatin1String("Town")); QCOMPARE(user.state(), QLatin1String("County")); QCOMPARE(user.postcode(), QLatin1String("Postcode")); QCOMPARE(user.telephone(), QLatin1String("Telephone")); QCOMPARE(user.email(), QLatin1String("Email")); } void MyMoneyFileTest::testAddAccounts() { testAddTwoInstitutions(); MyMoneyAccount a, b, c; a.setAccountType(eMyMoney::Account::Type::Checkings); b.setAccountType(eMyMoney::Account::Type::Checkings); MyMoneyInstitution institution; storage->d_func()->m_dirty = false; QCOMPARE(m->accountCount(), static_cast(5)); institution = m->institution("I000001"); QCOMPARE(institution.id(), QLatin1String("I000001")); a.setName("Account1"); a.setInstitutionId(institution.id()); a.setCurrencyId("EUR"); clearObjectLists(); MyMoneyFileTransaction ft; try { MyMoneyAccount parent = m->asset(); m->addAccount(a, parent); ft.commit(); QCOMPARE(m->accountCount(), static_cast(6)); QCOMPARE(a.parentAccountId(), QLatin1String("AStd::Asset")); QCOMPARE(a.id(), QLatin1String("A000001")); QCOMPARE(a.institutionId(), QLatin1String("I000001")); QCOMPARE(a.currencyId(), QLatin1String("EUR")); QCOMPARE(m->dirty(), true); QCOMPARE(m->asset().accountList().count(), 1); QCOMPARE(m->asset().accountList()[0], QLatin1String("A000001")); institution = m->institution("I000001"); QCOMPARE(institution.accountCount(), static_cast(1)); QCOMPARE(institution.accountList()[0], QLatin1String("A000001")); QCOMPARE(m_objectsRemoved.count(), 0); QCOMPARE(m_objectsAdded.count(), 1); QCOMPARE(m_objectsModified.count(), 2); QCOMPARE(m_balanceChanged.count(), 0); QCOMPARE(m_valueChanged.count(), 0); QVERIFY(m_objectsAdded.contains(QLatin1String("A000001"))); QVERIFY(m_objectsModified.contains(QLatin1String("I000001"))); QVERIFY(m_objectsModified.contains(QLatin1String("AStd::Asset"))); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } // try to add this account again, should not work ft.restart(); try { MyMoneyAccount parent = m->asset(); m->addAccount(a, parent); QFAIL("Expecting exception!"); } catch (const MyMoneyException &) { ft.commit(); } // check that we can modify the local object and // reload it from the file a.setName("AccountX"); a = m->account("A000001"); QCOMPARE(a.name(), QLatin1String("Account1")); storage->d_func()->m_dirty = false; // check if we can get the same info to a different object c = m->account("A000001"); QCOMPARE(c.accountType(), eMyMoney::Account::Type::Checkings); QCOMPARE(c.id(), QLatin1String("A000001")); QCOMPARE(c.name(), QLatin1String("Account1")); QCOMPARE(c.institutionId(), QLatin1String("I000001")); QCOMPARE(m->dirty(), false); // add a second account institution = m->institution("I000002"); b.setName("Account2"); b.setInstitutionId(institution.id()); b.setCurrencyId("EUR"); clearObjectLists(); ft.restart(); try { MyMoneyAccount parent = m->asset(); m->addAccount(b, parent); ft.commit(); QCOMPARE(m->dirty(), true); QCOMPARE(b.id(), QLatin1String("A000002")); QCOMPARE(b.currencyId(), QLatin1String("EUR")); QCOMPARE(b.parentAccountId(), QLatin1String("AStd::Asset")); QCOMPARE(m->accountCount(), static_cast(7)); institution = m->institution("I000001"); QCOMPARE(institution.accountCount(), static_cast(1)); QCOMPARE(institution.accountList()[0], QLatin1String("A000001")); institution = m->institution("I000002"); QCOMPARE(institution.accountCount(), static_cast(1)); QCOMPARE(institution.accountList()[0], QLatin1String("A000002")); QCOMPARE(m->asset().accountList().count(), 2); QCOMPARE(m->asset().accountList()[0], QLatin1String("A000001")); QCOMPARE(m->asset().accountList()[1], QLatin1String("A000002")); QCOMPARE(m_objectsRemoved.count(), 0); QCOMPARE(m_objectsAdded.count(), 1); QCOMPARE(m_objectsModified.count(), 2); QCOMPARE(m_balanceChanged.count(), 0); QCOMPARE(m_valueChanged.count(), 0); QVERIFY(m_objectsAdded.contains(QLatin1String("A000002"))); QVERIFY(m_objectsModified.contains(QLatin1String("I000002"))); QVERIFY(m_objectsModified.contains(QLatin1String("AStd::Asset"))); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } MyMoneyAccount p; p = m->account("A000002"); QCOMPARE(p.accountType(), eMyMoney::Account::Type::Checkings); QCOMPARE(p.id(), QLatin1String("A000002")); QCOMPARE(p.name(), QLatin1String("Account2")); QCOMPARE(p.institutionId(), QLatin1String("I000002")); QCOMPARE(p.currencyId(), QLatin1String("EUR")); } void MyMoneyFileTest::testAddCategories() { MyMoneyAccount a, b, c; a.setAccountType(eMyMoney::Account::Type::Income); a.setOpeningDate(QDate::currentDate()); b.setAccountType(eMyMoney::Account::Type::Expense); storage->d_func()->m_dirty = false; QCOMPARE(m->accountCount(), static_cast(5)); QCOMPARE(a.openingDate(), QDate::currentDate()); QVERIFY(!b.openingDate().isValid()); a.setName("Account1"); a.setCurrencyId("EUR"); clearObjectLists(); MyMoneyFileTransaction ft; try { MyMoneyAccount parent = m->income(); m->addAccount(a, parent); ft.commit(); QCOMPARE(m->accountCount(), static_cast(6)); QCOMPARE(a.parentAccountId(), QLatin1String("AStd::Income")); QCOMPARE(a.id(), QLatin1String("A000001")); QCOMPARE(a.institutionId(), QString()); QCOMPARE(a.currencyId(), QLatin1String("EUR")); QCOMPARE(a.openingDate(), QDate(1900, 1, 1)); QCOMPARE(m->dirty(), true); QCOMPARE(m->income().accountList().count(), 1); QCOMPARE(m->income().accountList()[0], QLatin1String("A000001")); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } // add a second category, expense this time b.setName("Account2"); b.setCurrencyId("EUR"); clearObjectLists(); ft.restart(); try { MyMoneyAccount parent = m->expense(); m->addAccount(b, parent); ft.commit(); QCOMPARE(m->dirty(), true); QCOMPARE(b.id(), QLatin1String("A000002")); QCOMPARE(a.institutionId(), QString()); QCOMPARE(b.currencyId(), QLatin1String("EUR")); QCOMPARE(b.openingDate(), QDate(1900, 1, 1)); QCOMPARE(b.parentAccountId(), QLatin1String("AStd::Expense")); QCOMPARE(m->accountCount(), static_cast(7)); QCOMPARE(m->income().accountList().count(), 1); QCOMPARE(m->expense().accountList().count(), 1); QCOMPARE(m->income().accountList()[0], QLatin1String("A000001")); QCOMPARE(m->expense().accountList()[0], QLatin1String("A000002")); QCOMPARE(m_objectsRemoved.count(), 0); QCOMPARE(m_objectsAdded.count(), 1); QCOMPARE(m_objectsModified.count(), 1); QCOMPARE(m_balanceChanged.count(), 0); QCOMPARE(m_valueChanged.count(), 0); QVERIFY(m_objectsAdded.contains(QLatin1String("A000002"))); QVERIFY(m_objectsModified.contains(QLatin1String("AStd::Expense"))); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } } void MyMoneyFileTest::testModifyAccount() { testAddAccounts(); storage->d_func()->m_dirty = false; MyMoneyAccount p = m->account("A000001"); MyMoneyInstitution institution; QCOMPARE(p.accountType(), eMyMoney::Account::Type::Checkings); QCOMPARE(p.name(), QLatin1String("Account1")); p.setName("New account name"); MyMoneyFileTransaction ft; clearObjectLists(); try { m->modifyAccount(p); ft.commit(); QCOMPARE(m->dirty(), true); QCOMPARE(m->accountCount(), static_cast(7)); QCOMPARE(p.accountType(), eMyMoney::Account::Type::Checkings); QCOMPARE(p.name(), QLatin1String("New account name")); QCOMPARE(m_objectsRemoved.count(), 0); QCOMPARE(m_objectsAdded.count(), 0); QCOMPARE(m_objectsModified.count(), 1); QCOMPARE(m_balanceChanged.count(), 0); QCOMPARE(m_valueChanged.count(), 0); QVERIFY(m_objectsModified.contains(QLatin1String("A000001"))); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } storage->d_func()->m_dirty = false; // try to move account to new institution p.setInstitutionId("I000002"); ft.restart(); clearObjectLists(); try { m->modifyAccount(p); ft.commit(); QCOMPARE(m->dirty(), true); QCOMPARE(m->accountCount(), static_cast(7)); QCOMPARE(p.accountType(), eMyMoney::Account::Type::Checkings); QCOMPARE(p.name(), QLatin1String("New account name")); QCOMPARE(p.institutionId(), QLatin1String("I000002")); institution = m->institution("I000001"); QCOMPARE(institution.accountCount(), static_cast(0)); institution = m->institution("I000002"); QCOMPARE(institution.accountCount(), static_cast(2)); QCOMPARE(institution.accountList()[0], QLatin1String("A000002")); QCOMPARE(institution.accountList()[1], QLatin1String("A000001")); QCOMPARE(m_objectsRemoved.count(), 0); QCOMPARE(m_objectsAdded.count(), 0); QCOMPARE(m_objectsModified.count(), 3); QCOMPARE(m_balanceChanged.count(), 0); QCOMPARE(m_valueChanged.count(), 0); QVERIFY(m_objectsModified.contains(QLatin1String("A000001"))); QVERIFY(m_objectsModified.contains(QLatin1String("I000001"))); QVERIFY(m_objectsModified.contains(QLatin1String("I000002"))); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } storage->d_func()->m_dirty = false; // try to change to an account type that is allowed p.setAccountType(eMyMoney::Account::Type::Savings); ft.restart(); try { m->modifyAccount(p); ft.commit(); QCOMPARE(m->dirty(), true); QCOMPARE(m->accountCount(), static_cast(7)); QCOMPARE(p.accountType(), eMyMoney::Account::Type::Savings); QCOMPARE(p.name(), QLatin1String("New account name")); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } storage->d_func()->m_dirty = false; // try to change to an account type that is not allowed p.setAccountType(eMyMoney::Account::Type::CreditCard); ft.restart(); try { m->modifyAccount(p); QFAIL("Expecting exception!"); } catch (const MyMoneyException &) { ft.commit(); } storage->d_func()->m_dirty = false; // try to fool engine a bit p.setParentAccountId("A000001"); ft.restart(); try { m->modifyAccount(p); QFAIL("Expecting exception!"); } catch (const MyMoneyException &) { ft.commit(); } } void MyMoneyFileTest::testReparentAccount() { testAddAccounts(); storage->d_func()->m_dirty = false; MyMoneyAccount p = m->account("A000001"); MyMoneyAccount q = m->account("A000002"); MyMoneyAccount o = m->account(p.parentAccountId()); // make A000001 a child of A000002 clearObjectLists(); MyMoneyFileTransaction ft; try { QVERIFY(p.parentAccountId() != q.id()); QCOMPARE(o.accountCount(), 2); QCOMPARE(q.accountCount(), 0); m->reparentAccount(p, q); ft.commit(); QCOMPARE(m->dirty(), true); QCOMPARE(p.parentAccountId(), q.id()); QCOMPARE(q.accountCount(), 1); QCOMPARE(q.id(), QLatin1String("A000002")); QCOMPARE(p.id(), QLatin1String("A000001")); QCOMPARE(q.accountList()[0], p.id()); QCOMPARE(m_objectsRemoved.count(), 0); QCOMPARE(m_objectsAdded.count(), 0); QCOMPARE(m_objectsModified.count(), 3); QCOMPARE(m_balanceChanged.count(), 0); QCOMPARE(m_valueChanged.count(), 0); QVERIFY(m_objectsModified.contains(QLatin1String("A000001"))); QVERIFY(m_objectsModified.contains(QLatin1String("A000002"))); QVERIFY(m_objectsModified.contains(QLatin1String("AStd::Asset"))); o = m->account(o.id()); QCOMPARE(o.accountCount(), 1); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } } void MyMoneyFileTest::testRemoveStdAccount(const MyMoneyAccount& acc) { QString txt("Exception expected while removing account "); txt += acc.id(); MyMoneyFileTransaction ft; try { m->removeAccount(acc); QFAIL(qPrintable(txt)); } catch (const MyMoneyException &) { ft.commit(); } } void MyMoneyFileTest::testRemoveAccount() { MyMoneyInstitution institution; testAddAccounts(); QCOMPARE(m->accountCount(), static_cast(7)); storage->d_func()->m_dirty = false; QString id; MyMoneyAccount p = m->account("A000001"); clearObjectLists(); MyMoneyFileTransaction ft; try { MyMoneyAccount q("Ainvalid", p); m->removeAccount(q); QFAIL("Exception expected!"); } catch (const MyMoneyException &) { ft.commit(); } ft.restart(); try { QCOMPARE(m_objectsRemoved.count(), 0); QCOMPARE(m_objectsAdded.count(), 0); QCOMPARE(m_objectsModified.count(), 0); m->removeAccount(p); ft.commit(); QCOMPARE(m->dirty(), true); QCOMPARE(m->accountCount(), static_cast(6)); institution = m->institution("I000001"); QCOMPARE(institution.accountCount(), static_cast(0)); QCOMPARE(m->asset().accountList().count(), 1); QCOMPARE(m_objectsRemoved.count(), 1); QCOMPARE(m_objectsModified.count(), 2); QCOMPARE(m_objectsAdded.count(), 0); QCOMPARE(m_balanceChanged.count(), 0); QCOMPARE(m_valueChanged.count(), 0); QVERIFY(m_objectsRemoved.contains(QLatin1String("A000001"))); QVERIFY(m_objectsModified.contains(QLatin1String("I000001"))); QVERIFY(m_objectsModified.contains(QLatin1String("AStd::Asset"))); institution = m->institution("I000002"); QCOMPARE(institution.accountCount(), static_cast(1)); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } // Check that the standard account-groups cannot be removed testRemoveStdAccount(m->liability()); testRemoveStdAccount(m->asset()); testRemoveStdAccount(m->expense()); testRemoveStdAccount(m->income()); } void MyMoneyFileTest::testRemoveAccountTree() { testReparentAccount(); MyMoneyAccount a = m->account("A000002"); clearObjectLists(); MyMoneyFileTransaction ft; // remove the account try { m->removeAccount(a); ft.commit(); QCOMPARE(m_objectsRemoved.count(), 1); QCOMPARE(m_objectsModified.count(), 3); QCOMPARE(m_objectsAdded.count(), 0); QCOMPARE(m_balanceChanged.count(), 0); QCOMPARE(m_valueChanged.count(), 0); QVERIFY(m_objectsRemoved.contains(QLatin1String("A000002"))); QVERIFY(m_objectsModified.contains(QLatin1String("A000001"))); QVERIFY(m_objectsModified.contains(QLatin1String("I000002"))); QVERIFY(m_objectsModified.contains(QLatin1String("AStd::Asset"))); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } QCOMPARE(m->accountCount(), static_cast(6)); // make sure it's gone try { m->account("A000002"); QFAIL("Exception expected!"); } catch (const MyMoneyException &) { } // make sure that children are re-parented to parent account try { a = m->account("A000001"); QCOMPARE(a.parentAccountId(), m->asset().id()); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } } void MyMoneyFileTest::testAccountListRetrieval() { QList list; storage->d_func()->m_dirty = false; m->accountList(list); QCOMPARE(m->dirty(), false); QCOMPARE(list.count(), 0); testAddAccounts(); storage->d_func()->m_dirty = false; list.clear(); m->accountList(list); QCOMPARE(m->dirty(), false); QCOMPARE(list.count(), 2); QCOMPARE(list[0].accountType(), eMyMoney::Account::Type::Checkings); QCOMPARE(list[1].accountType(), eMyMoney::Account::Type::Checkings); } void MyMoneyFileTest::testAddTransaction() { testAddAccounts(); MyMoneyTransaction t, p; MyMoneyAccount exp1; exp1.setAccountType(eMyMoney::Account::Type::Expense); exp1.setName("Expense1"); MyMoneyAccount exp2; exp2.setAccountType(eMyMoney::Account::Type::Expense); exp2.setName("Expense2"); MyMoneyFileTransaction ft; try { MyMoneyAccount parent = m->expense(); m->addAccount(exp1, parent); m->addAccount(exp2, parent); ft.commit(); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } // fake the last modified flag to check that the // date is updated when we add the transaction MyMoneyAccount a = m->account("A000001"); a.setLastModified(QDate(1, 2, 3)); ft.restart(); try { m->modifyAccount(a); ft.commit(); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } ft.restart(); QCOMPARE(m->accountCount(), static_cast(9)); a = m->account("A000001"); QCOMPARE(a.lastModified(), QDate(1, 2, 3)); // construct a transaction and add it to the pool t.setPostDate(QDate(2002, 2, 1)); t.setMemo("Memotext"); MyMoneySplit split1; MyMoneySplit split2; split1.setAccountId("A000001"); split1.setShares(MyMoneyMoney(-1000, 100)); split1.setValue(MyMoneyMoney(-1000, 100)); split2.setAccountId("A000003"); split2.setValue(MyMoneyMoney(1000, 100)); split2.setShares(MyMoneyMoney(1000, 100)); try { t.addSplit(split1); t.addSplit(split2); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } /* // FIXME: we don't have a payee and a number field right now // guess we should have a number field per split, don't know // about the payee t.setMethod(MyMoneyCheckingTransaction::Withdrawal); t.setPayee("Thomas Baumgart"); t.setNumber("1234"); t.setState(MyMoneyCheckingTransaction::Cleared); */ storage->d_func()->m_dirty = false; ft.restart(); clearObjectLists(); try { m->addTransaction(t); ft.commit(); QCOMPARE(m_objectsRemoved.count(), 0); QCOMPARE(m_objectsModified.count(), 0); QCOMPARE(m_objectsAdded.count(), 1); QCOMPARE(m_balanceChanged.count(), 2); QCOMPARE(m_balanceChanged.count("A000001"), 1); QCOMPARE(m_balanceChanged.count("A000003"), 1); QCOMPARE(m_valueChanged.count(), 0); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } ft.restart(); clearObjectLists(); QCOMPARE(t.id(), QLatin1String("T000000000000000001")); QCOMPARE(t.postDate(), QDate(2002, 2, 1)); QCOMPARE(t.entryDate(), QDate::currentDate()); QCOMPARE(m->dirty(), true); // check the balance of the accounts a = m->account("A000001"); QCOMPARE(a.lastModified(), QDate::currentDate()); QCOMPARE(a.balance(), MyMoneyMoney(-1000, 100)); MyMoneyAccount b = m->account("A000003"); QCOMPARE(b.lastModified(), QDate::currentDate()); QCOMPARE(b.balance(), MyMoneyMoney(1000, 100)); storage->d_func()->m_dirty = false; // locate transaction in MyMoneyFile via id try { p = m->transaction("T000000000000000001"); QCOMPARE(m_balanceChanged.count(), 0); QCOMPARE(m_valueChanged.count(), 0); QCOMPARE(p.splitCount(), static_cast(2)); QCOMPARE(p.memo(), QLatin1String("Memotext")); QCOMPARE(p.splits()[0].accountId(), QLatin1String("A000001")); QCOMPARE(p.splits()[1].accountId(), QLatin1String("A000003")); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } // check if it's in the account(s) as well try { p = m->transaction("A000001", 0); QCOMPARE(m_balanceChanged.count(), 0); QCOMPARE(m_valueChanged.count(), 0); QCOMPARE(p.id(), QLatin1String("T000000000000000001")); QCOMPARE(p.splitCount(), static_cast(2)); QCOMPARE(p.memo(), QLatin1String("Memotext")); QCOMPARE(p.splits()[0].accountId(), QLatin1String("A000001")); QCOMPARE(p.splits()[1].accountId(), QLatin1String("A000003")); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } try { p = m->transaction("A000003", 0); QCOMPARE(m_balanceChanged.count(), 0); QCOMPARE(m_valueChanged.count(), 0); QCOMPARE(p.id(), QLatin1String("T000000000000000001")); QCOMPARE(p.splitCount(), static_cast(2)); QCOMPARE(p.memo(), QLatin1String("Memotext")); QCOMPARE(p.splits()[0].accountId(), QLatin1String("A000001")); QCOMPARE(p.splits()[1].accountId(), QLatin1String("A000003")); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } } void MyMoneyFileTest::testIsStandardAccount() { QCOMPARE(m->isStandardAccount(m->liability().id()), true); QCOMPARE(m->isStandardAccount(m->asset().id()), true); QCOMPARE(m->isStandardAccount(m->expense().id()), true); QCOMPARE(m->isStandardAccount(m->income().id()), true); QCOMPARE(m->isStandardAccount("A00001"), false); } void MyMoneyFileTest::testHasActiveSplits() { testAddTransaction(); QCOMPARE(m->hasActiveSplits("A000001"), true); QCOMPARE(m->hasActiveSplits("A000002"), false); } void MyMoneyFileTest::testModifyTransactionSimple() { // this will test that we can modify the basic attributes // of a transaction testAddTransaction(); MyMoneyTransaction t = m->transaction("T000000000000000001"); t.setMemo("New Memotext"); storage->d_func()->m_dirty = false; MyMoneyFileTransaction ft; clearObjectLists(); try { m->modifyTransaction(t); ft.commit(); QCOMPARE(m_objectsRemoved.count(), 0); QCOMPARE(m_objectsModified.count(), 1); QCOMPARE(m_objectsAdded.count(), 0); QCOMPARE(m_balanceChanged.count(), 2); QCOMPARE(m_balanceChanged.count(QLatin1String("A000001")), 1); QCOMPARE(m_balanceChanged.count(QLatin1String("A000003")), 1); QCOMPARE(m_valueChanged.count(), 0); t = m->transaction("T000000000000000001"); QCOMPARE(t.memo(), QLatin1String("New Memotext")); QCOMPARE(m->dirty(), true); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } } void MyMoneyFileTest::testModifyTransactionNewPostDate() { // this will test that we can modify the basic attributes // of a transaction testAddTransaction(); MyMoneyTransaction t = m->transaction("T000000000000000001"); t.setPostDate(QDate(2004, 2, 1)); storage->d_func()->m_dirty = false; MyMoneyFileTransaction ft; clearObjectLists(); try { m->modifyTransaction(t); ft.commit(); t = m->transaction("T000000000000000001"); QCOMPARE(t.postDate(), QDate(2004, 2, 1)); t = m->transaction("A000001", 0); QCOMPARE(t.id(), QLatin1String("T000000000000000001")); QCOMPARE(m->dirty(), true); QCOMPARE(m_objectsRemoved.count(), 0); QCOMPARE(m_objectsModified.count(), 1); QCOMPARE(m_objectsAdded.count(), 0); QCOMPARE(m_balanceChanged.count(), 2); QCOMPARE(m_balanceChanged.count(QLatin1String("A000001")), 1); QCOMPARE(m_balanceChanged.count(QLatin1String("A000003")), 1); QCOMPARE(m_valueChanged.count(), 0); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } } void MyMoneyFileTest::testModifyTransactionNewAccount() { // this will test that we can modify the basic attributes // of a transaction testAddTransaction(); MyMoneyTransaction t = m->transaction("T000000000000000001"); MyMoneySplit s; s = t.splits()[0]; s.setAccountId("A000002"); t.modifySplit(s); storage->d_func()->m_dirty = false; MyMoneyFileTransaction ft; clearObjectLists(); try { MyMoneyTransactionFilter f1("A000001"); MyMoneyTransactionFilter f2("A000002"); MyMoneyTransactionFilter f3("A000003"); QCOMPARE(m->transactionList(f1).count(), 1); QCOMPARE(m->transactionList(f2).count(), 0); QCOMPARE(m->transactionList(f3).count(), 1); m->modifyTransaction(t); ft.commit(); t = m->transaction("T000000000000000001"); QCOMPARE(t.postDate(), QDate(2002, 2, 1)); t = m->transaction("A000002", 0); QCOMPARE(m->dirty(), true); QCOMPARE(m->transactionList(f1).count(), 0); QCOMPARE(m->transactionList(f2).count(), 1); QCOMPARE(m->transactionList(f3).count(), 1); QCOMPARE(m_objectsRemoved.count(), 0); QCOMPARE(m_objectsModified.count(), 1); QCOMPARE(m_objectsAdded.count(), 0); QCOMPARE(m_balanceChanged.count(), 3); QCOMPARE(m_balanceChanged.count(QLatin1String("A000001")), 1); QCOMPARE(m_balanceChanged.count(QLatin1String("A000002")), 1); QCOMPARE(m_balanceChanged.count(QLatin1String("A000003")), 1); QCOMPARE(m_valueChanged.count(), 0); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } } void MyMoneyFileTest::testRemoveTransaction() { testModifyTransactionNewPostDate(); MyMoneyTransaction t; t = m->transaction("T000000000000000001"); storage->d_func()->m_dirty = false; MyMoneyFileTransaction ft; clearObjectLists(); try { m->removeTransaction(t); ft.commit(); QCOMPARE(m->dirty(), true); QCOMPARE(m->transactionCount(), static_cast(0)); MyMoneyTransactionFilter f1("A000001"); MyMoneyTransactionFilter f2("A000002"); MyMoneyTransactionFilter f3("A000003"); QCOMPARE(m->transactionList(f1).count(), 0); QCOMPARE(m->transactionList(f2).count(), 0); QCOMPARE(m->transactionList(f3).count(), 0); QCOMPARE(m_objectsRemoved.count(), 1); QCOMPARE(m_objectsModified.count(), 0); QCOMPARE(m_objectsAdded.count(), 0); QCOMPARE(m_balanceChanged.count(), 2); QCOMPARE(m_balanceChanged.count(QLatin1String("A000001")), 1); QCOMPARE(m_balanceChanged.count(QLatin1String("A000003")), 1); QCOMPARE(m_valueChanged.count(), 0); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } } /* * This function is currently not implemented. It's kind of tricky * because it modifies a lot of objects in a single call. This might * be a problem for the undo/redo stuff. That's why I left it out in * the first run. We migh add it, if we need it. * / void testMoveSplits() { testModifyTransactionNewPostDate(); QCOMPARE(m->account("A000001").transactionCount(), 1); QCOMPARE(m->account("A000002").transactionCount(), 0); QCOMPARE(m->account("A000003").transactionCount(), 1); try { m->moveSplits("A000001", "A000002"); QCOMPARE(m->account("A000001").transactionCount(), 0); QCOMPARE(m->account("A000002").transactionCount(), 1); QCOMPARE(m->account("A000003").transactionCount(), 1); } catch(const MyMoneyException &e) { QFAIL("Unexpected exception!"); } } */ void MyMoneyFileTest::testBalanceTotal() { testAddTransaction(); MyMoneyTransaction t; // construct a transaction and add it to the pool t.setPostDate(QDate(2002, 2, 1)); t.setMemo("Memotext"); MyMoneySplit split1; MyMoneySplit split2; MyMoneyFileTransaction ft; try { split1.setAccountId("A000002"); split1.setShares(MyMoneyMoney(-1000, 100)); split1.setValue(MyMoneyMoney(-1000, 100)); split2.setAccountId("A000004"); split2.setValue(MyMoneyMoney(1000, 100)); split2.setShares(MyMoneyMoney(1000, 100)); t.addSplit(split1); t.addSplit(split2); m->addTransaction(t); ft.commit(); ft.restart(); QCOMPARE(t.id(), QLatin1String("T000000000000000002")); QCOMPARE(m->totalBalance("A000001"), MyMoneyMoney(-1000, 100)); QCOMPARE(m->totalBalance("A000002"), MyMoneyMoney(-1000, 100)); MyMoneyAccount p = m->account("A000001"); MyMoneyAccount q = m->account("A000002"); m->reparentAccount(p, q); ft.commit(); // check totalBalance() and balance() with combinations of parameters QCOMPARE(m->totalBalance("A000001"), MyMoneyMoney(-1000, 100)); QCOMPARE(m->totalBalance("A000002"), MyMoneyMoney(-2000, 100)); QVERIFY(m->totalBalance("A000002", QDate(2002, 1, 15)).isZero()); QCOMPARE(m->balance("A000001"), MyMoneyMoney(-1000, 100)); QCOMPARE(m->balance("A000002"), MyMoneyMoney(-1000, 100)); // Date of a transaction QCOMPARE(m->balance("A000001", QDate(2002, 2, 1)), MyMoneyMoney(-1000, 100)); QCOMPARE(m->balance("A000002", QDate(2002, 2, 1)), MyMoneyMoney(-1000, 100)); // Date after last transaction QCOMPARE(m->balance("A000001", QDate(2002, 2, 1)), MyMoneyMoney(-1000, 100)); QCOMPARE(m->balance("A000002", QDate(2002, 2, 1)), MyMoneyMoney(-1000, 100)); // Date before first transaction QVERIFY(m->balance("A000001", QDate(2002, 1, 15)).isZero()); QVERIFY(m->balance("A000002", QDate(2002, 1, 15)).isZero()); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } // Now check for exceptions try { // Account not found for balance() QVERIFY(m->balance("A000005").isZero()); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } try { // Account not found for totalBalance() QVERIFY(m->totalBalance("A000005").isZero()); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } } void MyMoneyFileTest::testSetAccountName() { MyMoneyFileTransaction ft; clearObjectLists(); try { m->setAccountName(stdAccNames[stdAccLiability], "Verbindlichkeiten"); ft.commit(); QCOMPARE(m_objectsRemoved.count(), 0); QCOMPARE(m_objectsModified.count(), 1); QCOMPARE(m_objectsAdded.count(), 0); QCOMPARE(m_balanceChanged.count(), 0); QCOMPARE(m_valueChanged.count(), 0); QVERIFY(m_objectsModified.contains(QLatin1String("AStd::Liability"))); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } ft.restart(); clearObjectLists(); try { m->setAccountName(stdAccNames[stdAccAsset], QString::fromUtf8("Vermögen")); ft.commit(); QCOMPARE(m_objectsRemoved.count(), 0); QCOMPARE(m_objectsModified.count(), 1); QCOMPARE(m_objectsAdded.count(), 0); QCOMPARE(m_balanceChanged.count(), 0); QCOMPARE(m_valueChanged.count(), 0); QVERIFY(m_objectsModified.contains(QLatin1String("AStd::Asset"))); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } ft.restart(); clearObjectLists(); try { m->setAccountName(stdAccNames[stdAccExpense], "Ausgaben"); ft.commit(); QCOMPARE(m_objectsRemoved.count(), 0); QCOMPARE(m_objectsModified.count(), 1); QCOMPARE(m_objectsAdded.count(), 0); QCOMPARE(m_balanceChanged.count(), 0); QCOMPARE(m_valueChanged.count(), 0); QVERIFY(m_objectsModified.contains(QLatin1String("AStd::Expense"))); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } ft.restart(); clearObjectLists(); try { m->setAccountName(stdAccNames[stdAccIncome], "Einnahmen"); ft.commit(); QCOMPARE(m_objectsRemoved.count(), 0); QCOMPARE(m_objectsModified.count(), 1); QCOMPARE(m_objectsAdded.count(), 0); QCOMPARE(m_balanceChanged.count(), 0); QCOMPARE(m_valueChanged.count(), 0); QVERIFY(m_objectsModified.contains(QLatin1String("AStd::Income"))); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } ft.restart(); QCOMPARE(m->liability().name(), QLatin1String("Verbindlichkeiten")); QCOMPARE(m->asset().name(), QString::fromUtf8("Vermögen")); QCOMPARE(m->expense().name(), QLatin1String("Ausgaben")); QCOMPARE(m->income().name(), QLatin1String("Einnahmen")); try { m->setAccountName("A000001", "New account name"); ft.commit(); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } } void MyMoneyFileTest::testAddPayee() { MyMoneyPayee p; p.setName("THB"); QCOMPARE(m->dirty(), false); MyMoneyFileTransaction ft; try { m->addPayee(p); ft.commit(); QCOMPARE(m->dirty(), true); QCOMPARE(p.id(), QLatin1String("P000001")); QCOMPARE(m_objectsRemoved.count(), 0); QCOMPARE(m_objectsModified.count(), 0); QCOMPARE(m_objectsAdded.count(), 1); QCOMPARE(m_balanceChanged.count(), 0); QCOMPARE(m_valueChanged.count(), 0); QVERIFY(m_objectsAdded.contains(QLatin1String("P000001"))); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } } void MyMoneyFileTest::testModifyPayee() { MyMoneyPayee p; testAddPayee(); clearObjectLists(); p = m->payee("P000001"); p.setName("New name"); MyMoneyFileTransaction ft; try { m->modifyPayee(p); ft.commit(); p = m->payee("P000001"); QCOMPARE(p.name(), QLatin1String("New name")); QCOMPARE(m_objectsRemoved.count(), 0); QCOMPARE(m_objectsModified.count(), 1); QCOMPARE(m_objectsAdded.count(), 0); QCOMPARE(m_balanceChanged.count(), 0); QCOMPARE(m_valueChanged.count(), 0); QVERIFY(m_objectsModified.contains(QLatin1String("P000001"))); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } } void MyMoneyFileTest::testRemovePayee() { MyMoneyPayee p; testAddPayee(); clearObjectLists(); QCOMPARE(m->payeeList().count(), 1); p = m->payee("P000001"); MyMoneyFileTransaction ft; try { m->removePayee(p); ft.commit(); QCOMPARE(m->payeeList().count(), 0); QCOMPARE(m_objectsRemoved.count(), 1); QCOMPARE(m_objectsModified.count(), 0); QCOMPARE(m_objectsAdded.count(), 0); QCOMPARE(m_balanceChanged.count(), 0); QCOMPARE(m_valueChanged.count(), 0); QVERIFY(m_objectsRemoved.contains(QLatin1String("P000001"))); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } } void MyMoneyFileTest::testPayeeWithIdentifier() { MyMoneyPayee p; try { MyMoneyFileTransaction ft; m->addPayee(p); ft.commit(); p = m->payee(p.id()); payeeIdentifier ident = payeeIdentifierLoader::instance()->createPayeeIdentifier(payeeIdentifiers::ibanBic::staticPayeeIdentifierIid()); payeeIdentifierTyped iban(ident); iban->setIban(QLatin1String("DE82 2007 0024 0066 6446 00")); ft.restart(); p.addPayeeIdentifier(iban); m->modifyPayee(p); ft.commit(); p = m->payee(p.id()); QCOMPARE(p.payeeIdentifiers().count(), 1); ident = p.payeeIdentifiers().first(); try { iban = payeeIdentifierTyped(ident); } catch (...) { QFAIL("Unexpected exception"); } QCOMPARE(iban->electronicIban(), QLatin1String("DE82200700240066644600")); } catch (const MyMoneyException& e) { unexpectedException(e); } } void MyMoneyFileTest::testAddTransactionStd() { testAddAccounts(); MyMoneyTransaction t, p; MyMoneyAccount a; a = m->account("A000001"); // construct a transaction and add it to the pool t.setPostDate(QDate(2002, 2, 1)); t.setMemo("Memotext"); MyMoneySplit split1; MyMoneySplit split2; split1.setAccountId("A000001"); split1.setShares(MyMoneyMoney(-1000, 100)); split1.setValue(MyMoneyMoney(-1000, 100)); split2.setAccountId(stdAccNames[stdAccExpense]); split2.setValue(MyMoneyMoney(1000, 100)); split2.setShares(MyMoneyMoney(1000, 100)); try { t.addSplit(split1); t.addSplit(split2); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } /* // FIXME: we don't have a payee and a number field right now // guess we should have a number field per split, don't know // about the payee t.setMethod(MyMoneyCheckingTransaction::Withdrawal); t.setPayee("Thomas Baumgart"); t.setNumber("1234"); t.setState(MyMoneyCheckingTransaction::Cleared); */ storage->d_func()->m_dirty = false; MyMoneyFileTransaction ft; try { m->addTransaction(t); ft.commit(); QFAIL("Missing expected exception!"); } catch (const MyMoneyException &) { } QCOMPARE(m->dirty(), false); } void MyMoneyFileTest::testAttachStorage() { MyMoneyStorageMgr *store = new MyMoneyStorageMgr; MyMoneyFile *file = new MyMoneyFile; QCOMPARE(file->storageAttached(), false); try { file->attachStorage(store); QCOMPARE(file->storageAttached(), true); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } try { file->attachStorage(store); QFAIL("Exception expected!"); } catch (const MyMoneyException &) { } try { file->attachStorage(0); QFAIL("Exception expected!"); } catch (const MyMoneyException &) { } try { file->detachStorage(store); QCOMPARE(file->storageAttached(), false); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } delete store; delete file; } void MyMoneyFileTest::testAccount2Category() { testReparentAccount(); QCOMPARE(m->accountToCategory("A000001"), QLatin1String("Account2:Account1")); QCOMPARE(m->accountToCategory("A000002"), QLatin1String("Account2")); } void MyMoneyFileTest::testCategory2Account() { testAddTransaction(); MyMoneyAccount a = m->account("A000003"); MyMoneyAccount b = m->account("A000004"); MyMoneyFileTransaction ft; try { m->reparentAccount(b, a); ft.commit(); QCOMPARE(m->categoryToAccount("Expense1"), QLatin1String("A000003")); QCOMPARE(m->categoryToAccount("Expense1:Expense2"), QLatin1String("A000004")); QVERIFY(m->categoryToAccount("Acc2").isEmpty()); } catch (const MyMoneyException &e) { unexpectedException(e); } } void MyMoneyFileTest::testAttachedStorage() { QCOMPARE(m->storageAttached(), true); QVERIFY(m->storage() != 0); MyMoneyStorageMgr *p = m->storage(); m->detachStorage(p); QCOMPARE(m->storageAttached(), false); QCOMPARE(m->storage(), static_cast(0)); m->attachStorage(p); QCOMPARE(m->storageAttached(), true); QVERIFY(m->storage() != 0); } void MyMoneyFileTest::testHasAccount() { testAddAccounts(); MyMoneyAccount a, b; a.setAccountType(eMyMoney::Account::Type::Checkings); a.setName("Account3"); b = m->account("A000001"); MyMoneyFileTransaction ft; try { m->addAccount(a, b); ft.commit(); QCOMPARE(m->accountCount(), static_cast(8)); QCOMPARE(a.parentAccountId(), QLatin1String("A000001")); QCOMPARE(m->hasAccount("A000001", "Account3"), true); QCOMPARE(m->hasAccount("A000001", "Account2"), false); QCOMPARE(m->hasAccount("A000002", "Account3"), false); } catch (const MyMoneyException &e) { unexpectedException(e); } } void MyMoneyFileTest::testAddEquityAccount() { MyMoneyAccount i; i.setName("Investment"); i.setAccountType(eMyMoney::Account::Type::Investment); MyMoneyFileTransaction ft; try { MyMoneyAccount parent = m->asset(); m->addAccount(i, parent); ft.commit(); } catch (const MyMoneyException &e) { unexpectedException(e); } // keep a copy for later use m_inv = i; // make sure, that only equity accounts can be children to it MyMoneyAccount a; a.setName("Testaccount"); QList list; list << eMyMoney::Account::Type::Checkings; list << eMyMoney::Account::Type::Savings; list << eMyMoney::Account::Type::Cash; list << eMyMoney::Account::Type::CreditCard; list << eMyMoney::Account::Type::Loan; list << eMyMoney::Account::Type::CertificateDep; list << eMyMoney::Account::Type::Investment; list << eMyMoney::Account::Type::MoneyMarket; list << eMyMoney::Account::Type::Asset; list << eMyMoney::Account::Type::Liability; list << eMyMoney::Account::Type::Currency; list << eMyMoney::Account::Type::Income; list << eMyMoney::Account::Type::Expense; list << eMyMoney::Account::Type::AssetLoan; QList::Iterator it; for (it = list.begin(); it != list.end(); ++it) { a.setAccountType(*it); ft.restart(); try { char msg[100]; m->addAccount(a, i); sprintf(msg, "Can add non-equity type %d to investment", (int)*it); QFAIL(msg); } catch (const MyMoneyException &) { ft.commit(); } } ft.restart(); try { a.setName("Teststock"); a.setAccountType(eMyMoney::Account::Type::Stock); m->addAccount(a, i); ft.commit(); } catch (const MyMoneyException &e) { unexpectedException(e); } } void MyMoneyFileTest::testReparentEquity() { testAddEquityAccount(); testAddEquityAccount(); MyMoneyAccount parent; // check the bad cases QList list; list << eMyMoney::Account::Type::Checkings; list << eMyMoney::Account::Type::Savings; list << eMyMoney::Account::Type::Cash; list << eMyMoney::Account::Type::CertificateDep; list << eMyMoney::Account::Type::MoneyMarket; list << eMyMoney::Account::Type::Asset; list << eMyMoney::Account::Type::AssetLoan; list << eMyMoney::Account::Type::Currency; parent = m->asset(); testReparentEquity(list, parent); list.clear(); list << eMyMoney::Account::Type::CreditCard; list << eMyMoney::Account::Type::Loan; list << eMyMoney::Account::Type::Liability; parent = m->liability(); testReparentEquity(list, parent); list.clear(); list << eMyMoney::Account::Type::Income; parent = m->income(); testReparentEquity(list, parent); list.clear(); list << eMyMoney::Account::Type::Expense; parent = m->expense(); testReparentEquity(list, parent); // now check the good case MyMoneyAccount stock = m->account("A000002"); MyMoneyAccount inv = m->account(m_inv.id()); MyMoneyFileTransaction ft; try { m->reparentAccount(stock, inv); ft.commit(); } catch (const MyMoneyException &e) { unexpectedException(e); } } void MyMoneyFileTest::testReparentEquity(QList& list, MyMoneyAccount& parent) { MyMoneyAccount a; MyMoneyAccount stock = m->account("A000002"); QList::Iterator it; MyMoneyFileTransaction ft; for (it = list.begin(); it != list.end(); ++it) { a.setName(QString("Testaccount %1").arg((int)*it)); a.setAccountType(*it); try { m->addAccount(a, parent); char msg[100]; m->reparentAccount(stock, a); sprintf(msg, "Can reparent stock to non-investment type %d account", (int)*it); QFAIL(msg); } catch (const MyMoneyException &) { ft.commit(); } ft.restart(); } } void MyMoneyFileTest::testBaseCurrency() { MyMoneySecurity base("EUR", "Euro", QChar(0x20ac)); MyMoneySecurity ref; // make sure, no base currency is set try { ref = m->baseCurrency(); QVERIFY(ref.id().isEmpty()); } catch (const MyMoneyException &e) { unexpectedException(e); } // make sure, we cannot assign an unknown currency try { m->setBaseCurrency(base); QFAIL("Missing expected exception"); } catch (const MyMoneyException &) { } MyMoneyFileTransaction ft; // add the currency and try again try { m->addCurrency(base); m->setBaseCurrency(base); ft.commit(); } catch (const MyMoneyException &e) { unexpectedException(e); } ft.restart(); // make sure, the base currency is set try { ref = m->baseCurrency(); QCOMPARE(ref.id(), QLatin1String("EUR")); QCOMPARE(ref.name(), QLatin1String("Euro")); QVERIFY(ref.tradingSymbol() == QChar(0x20ac)); } catch (const MyMoneyException &e) { unexpectedException(e); } // check if it gets reset when attaching a new storage m->detachStorage(storage); MyMoneyStorageMgr* newStorage = new MyMoneyStorageMgr; m->attachStorage(newStorage); ref = m->baseCurrency(); QVERIFY(ref.id().isEmpty()); m->detachStorage(newStorage); delete newStorage; m->attachStorage(storage); ref = m->baseCurrency(); QCOMPARE(ref.id(), QLatin1String("EUR")); QCOMPARE(ref.name(), QLatin1String("Euro")); QVERIFY(ref.tradingSymbol() == QChar(0x20ac)); } void MyMoneyFileTest::testOpeningBalanceNoBase() { MyMoneyAccount openingAcc; MyMoneySecurity base; try { base = m->baseCurrency(); openingAcc = m->openingBalanceAccount(base); QFAIL("Missing expected exception"); } catch (const MyMoneyException &) { } } void MyMoneyFileTest::testOpeningBalance() { MyMoneyAccount openingAcc; MyMoneySecurity second("USD", "US Dollar", "$"); testBaseCurrency(); try { openingAcc = m->openingBalanceAccount(m->baseCurrency()); QCOMPARE(openingAcc.parentAccountId(), m->equity().id()); QCOMPARE(openingAcc.name(), MyMoneyFile::openingBalancesPrefix()); QCOMPARE(openingAcc.openingDate(), QDate::currentDate()); } catch (const MyMoneyException &e) { unexpectedException(e); } // add a second currency MyMoneyFileTransaction ft; try { m->addCurrency(second); ft.commit(); } catch (const MyMoneyException &e) { unexpectedException(e); } QString refName = QString("%1 (%2)").arg(MyMoneyFile::openingBalancesPrefix()).arg("USD"); try { openingAcc = m->openingBalanceAccount(second); QCOMPARE(openingAcc.parentAccountId(), m->equity().id()); QCOMPARE(openingAcc.name(), refName); QCOMPARE(openingAcc.openingDate(), QDate::currentDate()); } catch (const MyMoneyException &e) { unexpectedException(e); } } void MyMoneyFileTest::testModifyStdAccount() { QVERIFY(m->asset().currencyId().isEmpty()); QCOMPARE(m->asset().name(), QLatin1String("Asset")); testBaseCurrency(); QVERIFY(m->asset().currencyId().isEmpty()); QVERIFY(!m->baseCurrency().id().isEmpty()); MyMoneyFileTransaction ft; try { MyMoneyAccount acc = m->asset(); acc.setName("Anlagen"); acc.setCurrencyId(m->baseCurrency().id()); m->modifyAccount(acc); ft.commit(); QCOMPARE(m->asset().name(), QLatin1String("Anlagen")); QCOMPARE(m->asset().currencyId(), m->baseCurrency().id()); } catch (const MyMoneyException &e) { unexpectedException(e); } ft.restart(); try { MyMoneyAccount acc = m->asset(); acc.setNumber("Test"); m->modifyAccount(acc); QFAIL("Missing expected exception"); } catch (const MyMoneyException &) { ft.rollback(); } } void MyMoneyFileTest::testAddPrice() { testAddAccounts(); testBaseCurrency(); MyMoneyAccount p; MyMoneyFileTransaction ft; try { p = m->account("A000002"); p.setCurrencyId("RON"); m->modifyAccount(p); ft.commit(); QCOMPARE(m->account("A000002").currencyId(), QLatin1String("RON")); } catch (const MyMoneyException &e) { unexpectedException(e); } clearObjectLists(); ft.restart(); MyMoneyPrice price("EUR", "RON", QDate::currentDate(), MyMoneyMoney(4.1), "Test source"); m->addPrice(price); ft.commit(); QCOMPARE(m_balanceChanged.count(), 0); QCOMPARE(m_valueChanged.count(), 1); QCOMPARE(m_valueChanged.count("A000002"), 1); clearObjectLists(); ft.restart(); MyMoneyPrice priceReciprocal("RON", "EUR", QDate::currentDate(), MyMoneyMoney(1 / 4.1), "Test source reciprocal price"); m->addPrice(priceReciprocal); ft.commit(); QCOMPARE(m_balanceChanged.count(), 0); QCOMPARE(m_valueChanged.count(), 1); QCOMPARE(m_valueChanged.count("A000002"), 1); } void MyMoneyFileTest::testRemovePrice() { testAddPrice(); clearObjectLists(); MyMoneyFileTransaction ft; MyMoneyPrice price("EUR", "RON", QDate::currentDate(), MyMoneyMoney(4.1), "Test source"); m->removePrice(price); ft.commit(); QCOMPARE(m_balanceChanged.count(), 0); QCOMPARE(m_valueChanged.count(), 1); QCOMPARE(m_valueChanged.count("A000002"), 1); } void MyMoneyFileTest::testGetPrice() { testAddPrice(); // the price for the current date is found QVERIFY(m->price("EUR", "RON", QDate::currentDate()).isValid()); // the price for the current date is returned when asking for the next day with exact date set to false { const MyMoneyPrice &price = m->price("EUR", "RON", QDate::currentDate().addDays(1), false); QVERIFY(price.isValid() && price.date() == QDate::currentDate()); } // no price is returned while asking for the next day with exact date set to true QVERIFY(!m->price("EUR", "RON", QDate::currentDate().addDays(1), true).isValid()); // no price is returned while asking for the previous day with exact date set to true/false because all prices are newer QVERIFY(!m->price("EUR", "RON", QDate::currentDate().addDays(-1), false).isValid()); QVERIFY(!m->price("EUR", "RON", QDate::currentDate().addDays(-1), true).isValid()); // add two more prices MyMoneyFileTransaction ft; m->addPrice(MyMoneyPrice("EUR", "RON", QDate::currentDate().addDays(3), MyMoneyMoney(4.1), "Test source")); m->addPrice(MyMoneyPrice("EUR", "RON", QDate::currentDate().addDays(5), MyMoneyMoney(4.1), "Test source")); ft.commit(); clearObjectLists(); // extra tests for the exactDate=false behavior { const MyMoneyPrice &price = m->price("EUR", "RON", QDate::currentDate().addDays(2), false); QVERIFY(price.isValid() && price.date() == QDate::currentDate()); } { const MyMoneyPrice &price = m->price("EUR", "RON", QDate::currentDate().addDays(3), false); QVERIFY(price.isValid() && price.date() == QDate::currentDate().addDays(3)); } { const MyMoneyPrice &price = m->price("EUR", "RON", QDate::currentDate().addDays(4), false); QVERIFY(price.isValid() && price.date() == QDate::currentDate().addDays(3)); } { const MyMoneyPrice &price = m->price("EUR", "RON", QDate::currentDate().addDays(5), false); QVERIFY(price.isValid() && price.date() == QDate::currentDate().addDays(5)); } { const MyMoneyPrice &price = m->price("EUR", "RON", QDate::currentDate().addDays(6), false); QVERIFY(price.isValid() && price.date() == QDate::currentDate().addDays(5)); } } void MyMoneyFileTest::testAddAccountMissingCurrency() { testAddTwoInstitutions(); MyMoneySecurity base("EUR", "Euro", QChar(0x20ac)); MyMoneyAccount a; a.setAccountType(eMyMoney::Account::Type::Checkings); MyMoneyInstitution institution; storage->d_func()->m_dirty = false; QCOMPARE(m->accountCount(), static_cast(5)); institution = m->institution("I000001"); QCOMPARE(institution.id(), QLatin1String("I000001")); a.setName("Account1"); a.setInstitutionId(institution.id()); clearObjectLists(); MyMoneyFileTransaction ft; try { m->addCurrency(base); m->setBaseCurrency(base); MyMoneyAccount parent = m->asset(); m->addAccount(a, parent); ft.commit(); QCOMPARE(m->account("A000001").currencyId(), QLatin1String("EUR")); } catch (const MyMoneyException &e) { unexpectedException(e); } } void MyMoneyFileTest::testAddTransactionToClosedAccount() { QSKIP("Test not implemented yet", SkipAll); } void MyMoneyFileTest::testRemoveTransactionFromClosedAccount() { QSKIP("Test not implemented yet", SkipAll); } void MyMoneyFileTest::testModifyTransactionInClosedAccount() { QSKIP("Test not implemented yet", SkipAll); } void MyMoneyFileTest::testStorageId() { QString id; // make sure id will be setup if it does not exist MyMoneyFileTransaction ft; try { m->setValue("kmm-id", ""); ft.commit(); } catch (const MyMoneyException &e) { unexpectedException(e); } try { // check for a new id id = m->storageId(); QVERIFY(!id.isEmpty()); // check that it is the same if we ask again QCOMPARE(id, m->storageId()); } catch (const MyMoneyException &e) { unexpectedException(e); } } void MyMoneyFileTest::testHasMatchingOnlineBalance_emptyAccountWithoutImportedBalance() { AddOneAccount(); MyMoneyAccount a = m->account("A000001"); QCOMPARE(m->hasMatchingOnlineBalance(a), false); } void MyMoneyFileTest::testHasMatchingOnlineBalance_emptyAccountWithEqualImportedBalance() { AddOneAccount(); MyMoneyAccount a = m->account("A000001"); a.setValue("lastImportedTransactionDate", QDate(2011, 12, 1).toString(Qt::ISODate)); a.setValue("lastStatementBalance", MyMoneyMoney().toString()); MyMoneyFileTransaction ft; m->modifyAccount(a); ft.commit(); QCOMPARE(m->hasMatchingOnlineBalance(a), true); } void MyMoneyFileTest::testHasMatchingOnlineBalance_emptyAccountWithUnequalImportedBalance() { AddOneAccount(); MyMoneyAccount a = m->account("A000001"); a.setValue("lastImportedTransactionDate", QDate(2011, 12, 1).toString(Qt::ISODate)); a.setValue("lastStatementBalance", MyMoneyMoney::ONE.toString()); MyMoneyFileTransaction ft; m->modifyAccount(a); ft.commit(); QCOMPARE(m->hasMatchingOnlineBalance(a), false); } void MyMoneyFileTest::testHasNewerTransaction_withoutAnyTransaction_afterLastImportedTransaction() { AddOneAccount(); MyMoneyAccount a = m->account("A000001"); QDate dateOfLastTransactionImport(2011, 12, 1); // There are no transactions at all: QCOMPARE(m->hasNewerTransaction(a.id(), dateOfLastTransactionImport), false); } void MyMoneyFileTest::testHasNewerTransaction_withoutNewerTransaction_afterLastImportedTransaction() { AddOneAccount(); QString accId("A000001"); QDate dateOfLastTransactionImport(2011, 12, 1); MyMoneyFileTransaction ft; MyMoneyTransaction t; // construct a transaction at the day of the last transaction import and add it to the pool t.setPostDate(dateOfLastTransactionImport); MyMoneySplit split1; split1.setAccountId(accId); split1.setShares(MyMoneyMoney(-1000, 100)); split1.setValue(MyMoneyMoney(-1000, 100)); t.addSplit(split1); ft.restart(); m->addTransaction(t); ft.commit(); QCOMPARE(m->hasNewerTransaction(accId, dateOfLastTransactionImport), false); } void MyMoneyFileTest::testHasNewerTransaction_withNewerTransaction_afterLastImportedTransaction() { AddOneAccount(); QString accId("A000001"); QDate dateOfLastTransactionImport(2011, 12, 1); QDate dateOfDayAfterLastTransactionImport(dateOfLastTransactionImport.addDays(1)); MyMoneyFileTransaction ft; MyMoneyTransaction t; // construct a transaction a day after the last transaction import and add it to the pool t.setPostDate(dateOfDayAfterLastTransactionImport); MyMoneySplit split1; split1.setAccountId(accId); split1.setShares(MyMoneyMoney(-1000, 100)); split1.setValue(MyMoneyMoney(-1000, 100)); t.addSplit(split1); ft.restart(); m->addTransaction(t); ft.commit(); QCOMPARE(m->hasNewerTransaction(accId, dateOfLastTransactionImport), true); } void MyMoneyFileTest::AddOneAccount() { QString accountId = "A000001"; MyMoneyAccount a; a.setAccountType(eMyMoney::Account::Type::Checkings); storage->d_func()->m_dirty = false; QCOMPARE(m->accountCount(), static_cast(5)); a.setName("Account1"); a.setCurrencyId("EUR"); clearObjectLists(); MyMoneyFileTransaction ft; try { MyMoneyAccount parent = m->asset(); m->addAccount(a, parent); ft.commit(); QCOMPARE(m->accountCount(), static_cast(6)); QCOMPARE(a.parentAccountId(), QLatin1String("AStd::Asset")); QCOMPARE(a.id(), accountId); QCOMPARE(a.currencyId(), QLatin1String("EUR")); QCOMPARE(m->dirty(), true); QCOMPARE(m->asset().accountList().count(), 1); QCOMPARE(m->asset().accountList()[0], accountId); QCOMPARE(m_objectsRemoved.count(), 0); QCOMPARE(m_objectsAdded.count(), 1); QCOMPARE(m_objectsModified.count(), 1); QCOMPARE(m_balanceChanged.count(), 0); QCOMPARE(m_valueChanged.count(), 0); QVERIFY(m_objectsAdded.contains(accountId.toLatin1())); QVERIFY(m_objectsModified.contains(QLatin1String("AStd::Asset"))); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } } void MyMoneyFileTest::testCountTransactionsWithSpecificReconciliationState_noTransactions() { AddOneAccount(); QString accountId = "A000001"; QCOMPARE(m->countTransactionsWithSpecificReconciliationState(accountId, eMyMoney::TransactionFilter::State::NotReconciled), 0); } void MyMoneyFileTest::testCountTransactionsWithSpecificReconciliationState_transactionWithWantedReconcileState() { AddOneAccount(); QString accountId = "A000001"; // construct split & transaction MyMoneySplit split; split.setAccountId(accountId); split.setShares(MyMoneyMoney(-1000, 100)); split.setValue(MyMoneyMoney(-1000, 100)); MyMoneyTransaction transaction; transaction.setPostDate(QDate(2013, 1, 1)); transaction.addSplit(split); // add transaction MyMoneyFileTransaction ft; m->addTransaction(transaction); ft.commit(); QCOMPARE(m->countTransactionsWithSpecificReconciliationState(accountId, eMyMoney::TransactionFilter::State::NotReconciled), 1); } void MyMoneyFileTest::testCountTransactionsWithSpecificReconciliationState_transactionWithUnwantedReconcileState() { AddOneAccount(); QString accountId = "A000001"; // construct split & transaction MyMoneySplit split; split.setAccountId(accountId); split.setShares(MyMoneyMoney(-1000, 100)); split.setValue(MyMoneyMoney(-1000, 100)); split.setReconcileFlag(eMyMoney::Split::State::Reconciled); MyMoneyTransaction transaction; transaction.setPostDate(QDate(2013, 1, 1)); transaction.addSplit(split); // add transaction MyMoneyFileTransaction ft; m->addTransaction(transaction); ft.commit(); QCOMPARE(m->countTransactionsWithSpecificReconciliationState(accountId, eMyMoney::TransactionFilter::State::NotReconciled), 0); } void MyMoneyFileTest::testAddOnlineJob() { QSKIP("Need dummy task for this test", SkipAll); #if 0 // Add a onlineJob onlineJob job(new germanOnlineTransfer()); MyMoneyFileTransaction ft; m->addOnlineJob(job); QCOMPARE(job.id(), QString("O000001")); ft.commit(); QCOMPARE(m_objectsRemoved.count(), 0); QCOMPARE(m_objectsAdded.count(), 1); QCOMPARE(m_objectsModified.count(), 0); QCOMPARE(m_balanceChanged.count(), 0); QCOMPARE(m_valueChanged.count(), 0); #endif } void MyMoneyFileTest::testGetOnlineJob() { QSKIP("Need dummy task for this test", SkipAll); testAddOnlineJob(); const onlineJob requestedJob = m->getOnlineJob("O000001"); QVERIFY(!requestedJob.isNull()); QCOMPARE(requestedJob.id(), QString("O000001")); } void MyMoneyFileTest::testRemoveOnlineJob() { QSKIP("Need dummy task for this test", SkipAll); #if 0 // Add a onlineJob onlineJob job(new germanOnlineTransfer()); onlineJob job2(new germanOnlineTransfer()); onlineJob job3(new germanOnlineTransfer()); MyMoneyFileTransaction ft; m->addOnlineJob(job); m->addOnlineJob(job2); m->addOnlineJob(job3); ft.commit(); clearObjectLists(); ft.restart(); m->removeOnlineJob(job); m->removeOnlineJob(job2); ft.commit(); QCOMPARE(m_objectsRemoved.count(), 2); QCOMPARE(m_objectsAdded.count(), 0); QCOMPARE(m_objectsModified.count(), 0); QCOMPARE(m_balanceChanged.count(), 0); QCOMPARE(m_valueChanged.count(), 0); #endif } void MyMoneyFileTest::testOnlineJobRollback() { QSKIP("Need dummy task for this test", SkipAll); #if 0 // Add a onlineJob onlineJob job(new germanOnlineTransfer()); onlineJob job2(new germanOnlineTransfer()); onlineJob job3(new germanOnlineTransfer()); MyMoneyFileTransaction ft; m->addOnlineJob(job); m->addOnlineJob(job2); m->addOnlineJob(job3); ft.rollback(); QCOMPARE(m_objectsRemoved.count(), 0); QCOMPARE(m_objectsAdded.count(), 0); QCOMPARE(m_objectsModified.count(), 0); QCOMPARE(m_balanceChanged.count(), 0); QCOMPARE(m_valueChanged.count(), 0); #endif } void MyMoneyFileTest::testRemoveLockedOnlineJob() { QSKIP("Need dummy task for this test", SkipAll); #if 0 // Add a onlineJob onlineJob job(new germanOnlineTransfer()); job.setLock(true); QVERIFY(job.isLocked()); MyMoneyFileTransaction ft; m->addOnlineJob(job); ft.commit(); clearObjectLists(); // Try removing locked transfer ft.restart(); m->removeOnlineJob(job); ft.commit(); QVERIFY2(m_objectsRemoved.count() == 0, "Online Job was locked, removing is not allowed"); QVERIFY(m_objectsAdded.count() == 0); QVERIFY(m_objectsModified.count() == 0); QVERIFY(m_balanceChanged.count() == 0); QVERIFY(m_valueChanged.count() == 0); #endif } /** @todo */ void MyMoneyFileTest::testModifyOnlineJob() { QSKIP("Need dummy task for this test", SkipAll); #if 0 // Add a onlineJob onlineJob job(new germanOnlineTransfer()); MyMoneyFileTransaction ft; m->addOnlineJob(job); ft.commit(); clearObjectLists(); // Modify online job job.setJobSend(); ft.restart(); m->modifyOnlineJob(job); ft.commit(); QCOMPARE(m_objectsRemoved.count(), 0); QCOMPARE(m_objectsAdded.count(), 0); QCOMPARE(m_objectsModified.count(), 1); QCOMPARE(m_balanceChanged.count(), 0); QCOMPARE(m_valueChanged.count(), 0); //onlineJob modifiedJob = m->getOnlineJob( job.id() ); //QCOMPARE(modifiedJob.responsibleAccount(), QString("Std::Assert")); #endif } void MyMoneyFileTest::testClearedBalance() { testAddTransaction(); MyMoneyTransaction t1; MyMoneyTransaction t2; // construct a transaction and add it to the pool t1.setPostDate(QDate(2002, 2, 1)); t1.setMemo("Memotext"); t2.setPostDate(QDate(2002, 2, 4)); t2.setMemo("Memotext"); MyMoneySplit split1; MyMoneySplit split2; MyMoneySplit split3; MyMoneySplit split4; MyMoneyFileTransaction ft; try { split1.setAccountId("A000002"); split1.setShares(MyMoneyMoney(-1000, 100)); split1.setValue(MyMoneyMoney(-1000, 100)); split1.setReconcileFlag(eMyMoney::Split::State::Cleared); split2.setAccountId("A000004"); split2.setValue(MyMoneyMoney(1000, 100)); split2.setShares(MyMoneyMoney(1000, 100)); split2.setReconcileFlag(eMyMoney::Split::State::Cleared); t1.addSplit(split1); t1.addSplit(split2); m->addTransaction(t1); ft.commit(); ft.restart(); QCOMPARE(t1.id(), QLatin1String("T000000000000000002")); split3.setAccountId("A000002"); split3.setShares(MyMoneyMoney(-2000, 100)); split3.setValue(MyMoneyMoney(-2000, 100)); split3.setReconcileFlag(eMyMoney::Split::State::Cleared); split4.setAccountId("A000004"); split4.setValue(MyMoneyMoney(2000, 100)); split4.setShares(MyMoneyMoney(2000, 100)); split4.setReconcileFlag(eMyMoney::Split::State::Cleared); t2.addSplit(split3); t2.addSplit(split4); m->addTransaction(t2); ft.commit(); ft.restart(); QCOMPARE(m->balance("A000001", QDate(2002, 2, 4)), MyMoneyMoney(-1000, 100)); QCOMPARE(m->balance("A000002", QDate(2002, 2, 4)), MyMoneyMoney(-3000, 100)); // Date of last cleared transaction QCOMPARE(m->clearedBalance("A000002", QDate(2002, 2, 1)), MyMoneyMoney(-1000, 100)); // Date of last transaction QCOMPARE(m->balance("A000002", QDate(2002, 2, 4)), MyMoneyMoney(-3000, 100)); // Date before first transaction QVERIFY(m->clearedBalance("A000002", QDate(2002, 1, 15)).isZero()); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } } void MyMoneyFileTest::testAdjustedValues() { // create a checking account, an expeense, an investment account and a stock AddOneAccount(); MyMoneyAccount exp1; exp1.setAccountType(eMyMoney::Account::Type::Expense); exp1.setName("Expense1"); exp1.setCurrencyId("EUR"); MyMoneyFileTransaction ft; try { MyMoneyAccount parent = m->expense(); m->addAccount(exp1, parent); ft.commit(); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } testAddEquityAccount(); testBaseCurrency(); MyMoneySecurity stockSecurity(QLatin1String("Blubber"), QLatin1String("TestsockSecurity"), QLatin1String("BLUB"), 1000, 1000, 1000); stockSecurity.setTradingCurrency(QLatin1String("BLUB")); // add the security ft.restart(); try { m->addSecurity(stockSecurity); ft.commit(); } catch (const MyMoneyException &e) { unexpectedException(e); } MyMoneyAccount i = m->accountByName("Investment"); MyMoneyAccount stock; ft.restart(); try { stock.setName("Teststock"); stock.setCurrencyId(stockSecurity.id()); stock.setAccountType(eMyMoney::Account::Type::Stock); m->addAccount(stock, i); ft.commit(); } catch (const MyMoneyException &e) { unexpectedException(e); } // values taken from real example on https://bugs.kde.org/show_bug.cgi?id=345655 MyMoneySplit s1, s2, s3; s1.setAccountId(QLatin1String("A000001")); s1.setShares(MyMoneyMoney(QLatin1String("-99901/1000"))); s1.setValue(MyMoneyMoney(QLatin1String("-999/10"))); s2.setAccountId(exp1.id()); s2.setShares(MyMoneyMoney(QLatin1String("-611/250"))); s2.setValue(MyMoneyMoney(QLatin1String("-61/25"))); s3.setAccountId(stock.id()); s3.setAction(eMyMoney::Split::InvestmentTransactionType::BuyShares); s3.setShares(MyMoneyMoney(QLatin1String("64901/100000"))); s3.setPrice(MyMoneyMoney(QLatin1String("157689/1000"))); s3.setValue(MyMoneyMoney(QLatin1String("102340161/1000000"))); MyMoneyTransaction t; t.setCommodity(QLatin1String("EUR")); t.setPostDate(QDate::currentDate()); t.addSplit(s1); t.addSplit(s2); t.addSplit(s3); // make sure the split sum is not zero QVERIFY(!t.splitSum().isZero()); ft.restart(); try { m->addTransaction(t); ft.commit(); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } QCOMPARE(t.splitById(s1.id()).shares(), MyMoneyMoney(QLatin1String("-999/10"))); QCOMPARE(t.splitById(s1.id()).value(), MyMoneyMoney(QLatin1String("-999/10"))); QCOMPARE(t.splitById(s2.id()).shares(), MyMoneyMoney(QLatin1String("-61/25"))); QCOMPARE(t.splitById(s2.id()).value(), MyMoneyMoney(QLatin1String("-61/25"))); QCOMPARE(t.splitById(s3.id()).shares(), MyMoneyMoney(QLatin1String("649/1000"))); QCOMPARE(t.splitById(s3.id()).value(), MyMoneyMoney(QLatin1String("10234/100"))); QCOMPARE(t.splitById(s3.id()).price(), MyMoneyMoney(QLatin1String("157689/1000"))); QCOMPARE(t.splitSum(), MyMoneyMoney()); // now reset and check if modify also works s1.setShares(MyMoneyMoney(QLatin1String("-999/10"))); s1.setValue(MyMoneyMoney(QLatin1String("-999/10"))); s2.setShares(MyMoneyMoney(QLatin1String("-61/25"))); s2.setValue(MyMoneyMoney(QLatin1String("-61/25"))); s3.setShares(MyMoneyMoney(QLatin1String("649/1000"))); s3.setPrice(MyMoneyMoney(QLatin1String("157689/1000"))); s3.setValue(MyMoneyMoney(QLatin1String("102340161/1000000"))); t.modifySplit(s1); t.modifySplit(s2); t.modifySplit(s3); // make sure the split sum is not zero QVERIFY(!t.splitSum().isZero()); ft.restart(); try { m->modifyTransaction(t); ft.commit(); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } // we need to get the transaction from the engine, as modifyTransaction does // not return the modified values MyMoneyTransaction t2 = m->transaction(t.id()); QCOMPARE(t2.splitById(s3.id()).shares(), MyMoneyMoney(QLatin1String("649/1000"))); QCOMPARE(t2.splitById(s3.id()).value(), MyMoneyMoney(QLatin1String("10234/100"))); QCOMPARE(t2.splitById(s3.id()).price(), MyMoneyMoney(QLatin1String("157689/1000"))); QCOMPARE(t2.splitSum(), MyMoneyMoney()); } void MyMoneyFileTest::testVatAssignment() { MyMoneyAccount acc; MyMoneyAccount vat; MyMoneyAccount expense; testAddTransaction(); vat.setName("VAT"); vat.setCurrencyId("EUR"); vat.setAccountType(eMyMoney::Account::Type::Expense); // make it a VAT account vat.setValue(QLatin1String("VatRate"), QLatin1String("20/100")); MyMoneyFileTransaction ft; try { MyMoneyAccount parent = m->expense(); m->addAccount(vat, parent); QVERIFY(!vat.id().isEmpty()); acc = m->account(QLatin1String("A000001")); expense = m->account(QLatin1String("A000003")); QCOMPARE(acc.name(), QLatin1String("Account1")); QCOMPARE(expense.name(), QLatin1String("Expense1")); expense.setValue(QLatin1String("VatAccount"), vat.id()); m->modifyAccount(expense); ft.commit(); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } // the categories are setup now for gross value entry MyMoneyTransaction tr; MyMoneySplit sp; MyMoneyMoney amount(1707, 100); // setup the transaction sp.setShares(amount); sp.setValue(amount); sp.setAccountId(acc.id()); tr.addSplit(sp); sp.clearId(); sp.setShares(-amount); sp.setValue(-amount); sp.setAccountId(expense.id()); tr.addSplit(sp); QCOMPARE(m->addVATSplit(tr, acc, expense, amount), true); QCOMPARE(tr.splits().count(), 3); QCOMPARE(tr.splitByAccount(acc.id()).shares().toString(), MyMoneyMoney(1707, 100).toString()); QCOMPARE(tr.splitByAccount(expense.id()).shares().toString(), MyMoneyMoney(-1422, 100).toString()); QCOMPARE(tr.splitByAccount(vat.id()).shares().toString(), MyMoneyMoney(-285, 100).toString()); QCOMPARE(tr.splitSum().toString(), MyMoneyMoney().toString()); tr.removeSplits(); ft.restart(); try { expense.setValue(QLatin1String("VatAmount"), QLatin1String("net")); m->modifyAccount(expense); ft.commit(); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } // the categories are setup now for net value entry amount = MyMoneyMoney(1422, 100); sp.clearId(); sp.setShares(amount); sp.setValue(amount); sp.setAccountId(acc.id()); tr.addSplit(sp); sp.clearId(); sp.setShares(-amount); sp.setValue(-amount); sp.setAccountId(expense.id()); tr.addSplit(sp); QCOMPARE(m->addVATSplit(tr, acc, expense, amount), true); QCOMPARE(tr.splits().count(), 3); QCOMPARE(tr.splitByAccount(acc.id()).shares().toString(), MyMoneyMoney(1706, 100).toString()); QCOMPARE(tr.splitByAccount(expense.id()).shares().toString(), MyMoneyMoney(-1422, 100).toString()); QCOMPARE(tr.splitByAccount(vat.id()).shares().toString(), MyMoneyMoney(-284, 100).toString()); QCOMPARE(tr.splitSum().toString(), MyMoneyMoney().toString()); } void MyMoneyFileTest::testEmptyFilter() { testAddTransaction(); try { QList > tList; MyMoneyTransactionFilter filter; MyMoneyFile::instance()->transactionList(tList, filter); QCOMPARE(tList.count(), 2); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } } + +void MyMoneyFileTest::testAddSecurity() +{ + // create a checking account, an expeense, an investment account and a stock + AddOneAccount(); + + MyMoneyAccount exp1; + exp1.setAccountType(eMyMoney::Account::Type::Expense); + exp1.setName("Expense1"); + exp1.setCurrencyId("EUR"); + + MyMoneyFileTransaction ft; + try { + MyMoneyAccount parent = m->expense(); + m->addAccount(exp1, parent); + ft.commit(); + } catch (const MyMoneyException &) { + QFAIL("Unexpected exception!"); + } + + testAddEquityAccount(); + + testBaseCurrency(); + MyMoneySecurity stockSecurity(QLatin1String("Blubber"), QLatin1String("TestsockSecurity"), QLatin1String("BLUB"), 1000, 1000, 1000); + stockSecurity.setTradingCurrency(QLatin1String("BLUB")); + // add the security + ft.restart(); + try { + m->addSecurity(stockSecurity); + ft.commit(); + } catch (const MyMoneyException &e) { + unexpectedException(e); + } + + // check that we can get it via the security method + try { + MyMoneySecurity sec = m->security(stockSecurity.id()); + } catch (const MyMoneyException &e) { + unexpectedException(e); + } + + // and also via the currency method + try { + MyMoneySecurity sec = m->currency(stockSecurity.id()); + } catch (const MyMoneyException &e) { + unexpectedException(e); + } +} diff --git a/kmymoney/mymoney/tests/mymoneyfile-test.h b/kmymoney/mymoney/tests/mymoneyfile-test.h index 50037b26f..06a5393a2 100644 --- a/kmymoney/mymoney/tests/mymoneyfile-test.h +++ b/kmymoney/mymoney/tests/mymoneyfile-test.h @@ -1,130 +1,131 @@ /*************************************************************************** mymoneyfiletest.h ------------------- copyright : (C) 2002 by Thomas Baumgart email : ipwizard@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * 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. * * * ***************************************************************************/ #ifndef MYMONEYFILETEST_H #define MYMONEYFILETEST_H #include #include #define KMM_MYMONEY_UNIT_TESTABLE friend class MyMoneyFileTest; #include "mymoneyfile.h" #include "mymoneyaccount.h" #include "storage/mymoneystoragemgr.h" class MyMoneyFileTest : public QObject { Q_OBJECT protected: MyMoneyFile *m; MyMoneyStorageMgr* storage; MyMoneyAccount m_inv; private Q_SLOTS: void initTestCase(); void init(); void cleanup(); void testEmptyConstructor(); void testAddOneInstitution(); void testAddTwoInstitutions(); void testRemoveInstitution(); void testInstitutionRetrieval(); void testInstitutionListRetrieval(); void testInstitutionModify(); void testSetFunctions(); void testAddAccounts(); void testAddCategories(); void testModifyAccount(); void testModifyStdAccount(); void testReparentAccount(); void testRemoveAccount(); void testRemoveAccountTree(); void testAccountListRetrieval(); void testAddTransaction(); void testIsStandardAccount(); void testHasActiveSplits(); void testModifyTransactionSimple(); void testModifyTransactionNewPostDate(); void testModifyTransactionNewAccount(); void testRemoveTransaction(); void testBalanceTotal(); void testSetAccountName(); void testAddPayee(); void testModifyPayee(); void testRemovePayee(); void testPayeeWithIdentifier(); void testAddTransactionStd(); void testAttachStorage(); void testAccount2Category(); void testCategory2Account(); void testAttachedStorage(); void testHasAccount(); void testAddEquityAccount(); void testReparentEquity(); void testBaseCurrency(); void testOpeningBalanceNoBase(); void testOpeningBalance(); void testAddPrice(); void testRemovePrice(); void testGetPrice(); void testAddAccountMissingCurrency(); void testAddTransactionToClosedAccount(); void testRemoveTransactionFromClosedAccount(); void testModifyTransactionInClosedAccount(); void testStorageId(); void testHasMatchingOnlineBalance_emptyAccountWithoutImportedBalance(); void testHasMatchingOnlineBalance_emptyAccountWithEqualImportedBalance(); void testHasMatchingOnlineBalance_emptyAccountWithUnequalImportedBalance(); void testHasNewerTransaction_withoutAnyTransaction_afterLastImportedTransaction(); void testHasNewerTransaction_withoutNewerTransaction_afterLastImportedTransaction(); void testHasNewerTransaction_withNewerTransaction_afterLastImportedTransaction(); void testCountTransactionsWithSpecificReconciliationState_noTransactions(); void testCountTransactionsWithSpecificReconciliationState_transactionWithWantedReconcileState(); void testCountTransactionsWithSpecificReconciliationState_transactionWithUnwantedReconcileState(); void testAddOnlineJob(); void testGetOnlineJob(); void testRemoveOnlineJob(); void testRemoveLockedOnlineJob(); void testOnlineJobRollback(); void testModifyOnlineJob(); void testClearedBalance(); void testAdjustedValues(); void testVatAssignment(); void testEmptyFilter(); + void testAddSecurity(); private Q_SLOTS: void objectAdded(eMyMoney::File::Object type, const QString &id); void objectModified(eMyMoney::File::Object type, const QString &id); void objectRemoved(eMyMoney::File::Object type, const QString& id); void balanceChanged(const MyMoneyAccount& account); void valueChanged(const MyMoneyAccount& account); private: void testRemoveStdAccount(const MyMoneyAccount& acc); void testReparentEquity(QList& list, MyMoneyAccount& parent); void clearObjectLists(); void AddOneAccount(); private: QStringList m_objectsAdded; QStringList m_objectsModified; QStringList m_objectsRemoved; QStringList m_balanceChanged; QStringList m_valueChanged; }; #endif