diff --git a/CMakeLists.txt b/CMakeLists.txt index 15783a357..6bca518a0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,334 +1,334 @@ # The CMake version we require cmake_minimum_required(VERSION 3.1) # Setting the name of the main project project(KMyMoney VERSION "4.100.0") # Determine the GIT reference (if we're based on GIT) if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git") execute_process(COMMAND git rev-parse --short HEAD WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" OUTPUT_VARIABLE VERSION_SUFFIX OUTPUT_STRIP_TRAILING_WHITESPACE) set(VERSION_SUFFIX "-${VERSION_SUFFIX}") # Add variables which are similar to the build in names of cmake set(PROJECT_VERSION_SUFFIX "${VERSION_SUFFIX}") set(${PROJECT_NAME}_VERSION_SUFFIX "${VERSION_SUFFIX}") endif() # Automoc all sources set(CMAKE_AUTOMOC TRUE) if (POLICY CMP0063) cmake_policy(SET CMP0063 NEW) # Policy introduced in CMake version 3.3 endif() ######################### General Requirements ########################## find_package(ECM 0.0.11 REQUIRED NO_MODULE) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules) include(KDEInstallDirs) include(KDECMakeSettings) include(FeatureSummary) include(GenerateExportHeader) include(KMyMoneyMacros) set(GPG_ENCRYPTION "no") set (OPT_KF5_COMPONENTS DocTools Holidays Contacts Akonadi IdentityManagement Activities Kross) find_package(Gpgmepp) if (Gpgmepp_FOUND) set(GPG_ENCRYPTION "yes") else() set(OPT_KF5_COMPONENTS ${OPT_KF5_COMPONENTS} Gpgmepp) endif() find_package(Qt5 5.6 REQUIRED COMPONENTS Core DBus Widgets Svg Sql Xml Test PrintSupport) find_package(KF5 5.2 REQUIRED COMPONENTS Archive CoreAddons Config ConfigWidgets I18n Completion KCMUtils ItemModels ItemViews Service Wallet IconThemes XmlGui TextWidgets Notifications KIO OPTIONAL_COMPONENTS ${OPT_KF5_COMPONENTS} ) find_package(LibAlkimia5 7.0.0 REQUIRED) find_package(KChart 2.6.0 REQUIRED) if(KF5Gpgmepp_FOUND) set(GPG_ENCRYPTION "yes") add_definitions(-DGpgmepp_FOUND) endif() add_definitions(-DQT_USE_QSTRINGBUILDER -DQT_NO_CAST_TO_ASCII -DQT_NO_URL_CAST_FROM_STRING) set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) # use DBus only on Linux if(CMAKE_SYSTEM_NAME MATCHES "Linux") set(KMM_DBUS 1) endif() set(CMAKE_INCLUDE_CURRENT_DIR ON) include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR}) # check for Doxygen find_package(Doxygen) if(DOXYGEN_FOUND) set(APIDOC_DIR ${CMAKE_CURRENT_BINARY_DIR}/apidocs) make_directory("${APIDOC_DIR}") configure_file(${CMAKE_CURRENT_SOURCE_DIR}/kmymoney.doxygen.in ${CMAKE_CURRENT_BINARY_DIR}/kmymoney.doxygen IMMEDIATE) add_custom_target(apidoc "${DOXYGEN}" "${CMAKE_CURRENT_BINARY_DIR}/kmymoney.doxygen") endif(DOXYGEN_FOUND) # check some include files exists set(CMAKE_REQUIRED_DEFINITIONS -D_XOPEN_SOURCE=500 -D_BSD_SOURCE) include (CheckIncludeFile) check_include_file("sys/types.h" HAVE_SYS_TYPES_H) check_include_file("unistd.h" HAVE_UNISTD_H) check_include_file("pwd.h" HAVE_PWD_H) check_include_file("windows.h" HAVE_WINDOWS_H) check_include_file("lmcons.h" HAVE_LMCONS_H) check_include_file("process.h" HAVE_PROCESS_H) # include check for members in structs include (CheckStructHasMember) ######################### Special Requirements ########################## # This is needed for QtSqlite and QtDesigner # (they'll install files to ${QT_INSTALL_DIR}/plugins/) get_filename_component(QT_BIN_DIR "${QT_MOC_EXECUTABLE}" PATH) get_filename_component(QT_DIR ${QT_BIN_DIR} PATH) set(QT_INSTALL_DIR ${QT_DIR} CACHE PATH "Qt install prefix defaults to the Qt prefix: ${QT_DIR}") if(KF5IdentityManagement_FOUND AND KF5Akonadi_FOUND AND KF5Contacts_FOUND) set(KMM_ADDRESSBOOK_FOUND true) endif() # check for optional QWebEngine option(ENABLE_WEBENGINE "Enable QWebEngine" OFF) if(ENABLE_WEBENGINE) find_package(Qt5WebEngineWidgets 5.8 REQUIRED) - if(Qt5WebEngineWidgets_VERSION VERSION_GREATER 5.8.99 AND Qt5WebEngineWidgets_VERSION VERSION_LESS 5.9.2) + if(Qt5WebEngineWidgets_VERSION VERSION_GREATER 5.8.99 AND Qt5WebEngineWidgets_VERSION VERSION_LESS 5.9.3) message(WARNING "QWebEngine version ${Qt5WebEngineWidgets_VERSION} is known to be unstable with KMyMoney") endif() else(ENABLE_WEBENGINE) find_package(KF5WebKit REQUIRED) endif(ENABLE_WEBENGINE) # check for optional OFX support set(LIBOFX_DEFAULT "AUTO") if(DEFINED ENABLE_LIBOFX) set(LIBOFX_DEFAULT ${ENABLE_LIBOFX}) endif(DEFINED ENABLE_LIBOFX) option(ENABLE_LIBOFX "Enable OFX plugin" ON) if(ENABLE_LIBOFX) find_package(LibOfx) if(NOT LIBOFX_FOUND) if(NOT LIBOFX_DEFAULT STREQUAL "AUTO") message(FATAL_ERROR "LibOFX not found") endif(NOT LIBOFX_DEFAULT STREQUAL "AUTO") set(ENABLE_LIBOFX OFF CACHE BOOL "Enable OFX plugin" FORCE) else(NOT LIBOFX_FOUND) check_struct_has_member("struct OfxFiLogin" "clientuid" "libofx/libofx.h" LIBOFX_HAVE_CLIENTUID) endif(NOT LIBOFX_FOUND) endif(ENABLE_LIBOFX) # check for optional KBanking support set(KBANKING_FOUND "AUTO") mark_as_advanced(KBANKING_FOUND) if(DEFINED ENABLE_KBANKING) set(KBANKING_FOUND OFF) endif(DEFINED ENABLE_KBANKING) option(ENABLE_KBANKING "Enable KBanking plugin" ON) if(ENABLE_KBANKING) find_package(Qt5QuickWidgets) # Includes Qt5Qml find_package(AQBANKING 5.6.5) find_package(gwenhywfar 4.15.3) find_package(gwengui-cpp) find_package(gwengui-qt5) if (AQBANKING_FOUND AND gwengui-cpp_FOUND AND gwengui-qt5_FOUND AND Qt5QuickWidgets_FOUND) set(KBANKING_FOUND ON) else() if(NOT KBANKING_FOUND STREQUAL "AUTO") message(FATAL_ERROR "KBanking requirements not met") endif(NOT KBANKING_FOUND STREQUAL "AUTO") set(KBANKING_FOUND OFF) set(ENABLE_KBANKING OFF CACHE BOOL "Enable KBanking plugin" FORCE) endif () endif(ENABLE_KBANKING) # check for optional Weboob support set(WEBOOB_FOUND "AUTO") mark_as_advanced(WEBOOB_FOUND) if(DEFINED ENABLE_WEBOOB) set(WEBOOB_FOUND OFF) endif(DEFINED ENABLE_WEBOOB) option(ENABLE_WEBOOB "Enable weboob plugin" ON) if(ENABLE_WEBOOB) if(KF5Kross_FOUND) set(WEBOOB_FOUND ON) else(KF5Kross_FOUND) if(NOT WEBOOB_FOUND STREQUAL "AUTO") message(FATAL_ERROR "Weboob requirements not met") endif(NOT WEBOOB_FOUND STREQUAL "AUTO") set(WEBOOB_FOUND OFF) set(ENABLE_WEBOOB OFF CACHE BOOL "Enable weboob plugin" FORCE) endif(KF5Kross_FOUND) endif(ENABLE_WEBOOB) # check for optional ical support set(LIBICAL_DEFAULT "AUTO") if(DEFINED ENABLE_LIBICAL) set(LIBICAL_DEFAULT ${ENABLE_LIBICAL}) endif(DEFINED ENABLE_LIBICAL) option(ENABLE_LIBICAL "Enable Calendar plugin" ON) if(ENABLE_LIBICAL) find_package(Libical) if(NOT LIBICAL_FOUND) if(NOT LIBICAL_DEFAULT STREQUAL "AUTO") message(FATAL_ERROR "LIBICAL not found") endif(NOT LIBICAL_DEFAULT STREQUAL "AUTO") set(ENABLE_LIBICAL OFF CACHE BOOL "Enable Calendar plugin" FORCE) endif(NOT LIBICAL_FOUND) endif(ENABLE_LIBICAL) option(ENABLE_QIFIMPORTER "Enable QIF Importer" ON) option(ENABLE_QIFEXPORTER "Enable QIF Exporter" ON) # TODO: this should be removed enable_testing() ######################### Settings ########################## # If no build type is set, use "Release with Debug Info" if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE RelWithDebInfo) endif(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING "Choose the type of build. Possible values are: 'Release' 'RelWithDebInfo' 'Debug' 'DebugKMM' 'Debugfull' 'Profile' The default value is: 'RelWithDebInfo'" FORCE) # tells gcc to enable exception handling include(KDECompilerSettings) kde_enable_exceptions() if(CMAKE_SYSTEM_NAME MATCHES "Linux") set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--as-needed") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed") endif() # IDEA: Set on a per target base set(CMAKE_POSITION_INDEPENDENT_CODE ON) if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") # be more pedantic about common symbols set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-common -Wextra") if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wlogical-op") endif() # DebugKMM, Debugfull, Profile set(CMAKE_CXX_FLAGS_DEBUGKMM "-g -O2 -fno-reorder-blocks -fno-schedule-insns -fno-inline") set(CMAKE_CXX_FLAGS_DEBUGFULL "-g3 -fno-inline") set(CMAKE_CXX_FLAGS_PROFILE "-g3 -fno-inline -ftest-coverage -fprofile-arcs") # be pedantic about undefined symbols when linking shared libraries if(CMAKE_SYSTEM_NAME MATCHES "Linux" OR CMAKE_SYSTEM_NAME MATCHES "kFreeBSD" OR CMAKE_SYSTEM_NAME STREQUAL "GNU") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined -Wl,--as-needed") endif() endif() # preprocessor definitions in case this is a debug build set(CMAKE_CXX_FLAGS_DEBUGFULL "${CMAKE_CXX_FLAGS_DEBUGFULL} -DQT_STRICT_ITERATORS -DKMM_DEBUG") set(CMAKE_CXX_FLAGS_DEBUGKMM "${CMAKE_CXX_FLAGS_DEBUGFULL} -DKMM_DEBUG") option(USE_MODELTEST "Compile with ModelTest code (default=OFF)" OFF) option(USE_QT_DESIGNER "Install KMyMoney specific widget library for Qt-Designer (default=OFF)" OFF) ######################### The Actual Targets ########################## add_subdirectory( libkgpgfile ) add_subdirectory( tools ) add_subdirectory( kmymoney ) if(KF5DocTools_FOUND) add_subdirectory( doc ) endif() ######################### Output Results ############################# # create the config.h file out of the config.h.cmake configure_file("config-kmymoney.h.cmake" "${CMAKE_CURRENT_BINARY_DIR}/config-kmymoney.h") configure_file("config-kmymoney-version.h.cmake" "${CMAKE_CURRENT_BINARY_DIR}/config-kmymoney-version.h") # this macro maps the boolean variable ${_varname} to "yes"/"no" # and writes the output to the variable nice_${_varname} macro(nice_yesno _varname) if(${_varname}) set("nice_${_varname}" "yes") else(${_varname}) set("nice_${_varname}" "no") endif(${_varname}) endmacro() nice_yesno("KF5Holidays_FOUND") nice_yesno("Gpgmepp_FOUND") nice_yesno("KMM_ADDRESSBOOK_FOUND") nice_yesno("LIBOFX_FOUND") nice_yesno("LIBOFX_HAVE_CLIENTUID") nice_yesno("KBANKING_FOUND") nice_yesno("WEBOOB_FOUND") nice_yesno("LIBICAL_FOUND") nice_yesno("ENABLE_SQLCIPHER") nice_yesno("USE_QT_DESIGNER") nice_yesno("USE_MODELTEST") nice_yesno("DOXYGEN_FOUND") nice_yesno("ENABLE_WEBENGINE") message(" -------- KMyMoney ${PROJECT_VERSION}${PROJECT_VERSION_SUFFIX} -------- Configure results (user options): -------------------------------------------- GpgME Encryption: ${GPG_ENCRYPTION} KDE PIM holidays: ${nice_KF5Holidays_FOUND} KDE PIM addressbook: ${nice_KMM_ADDRESSBOOK_FOUND} OFX plugin: ${nice_LIBOFX_FOUND} OFX supports CLIENTUID: ${nice_LIBOFX_HAVE_CLIENTUID} KBanking plugin: ${nice_KBANKING_FOUND} weboob plugin: ${nice_WEBOOB_FOUND} iCalendar export plugin: ${nice_LIBICAL_FOUND} SQLCipher plugin: ${nice_ENABLE_SQLCIPHER} QWebEngine: ${nice_ENABLE_WEBENGINE} -------------------------------------------- Configure results (developer options): -------------------------------------------- Qt-Designer library support: ${nice_USE_QT_DESIGNER} Generate modeltest code: ${nice_USE_MODELTEST} Generate API documentation with Doxygen: ${nice_DOXYGEN_FOUND}") message(" Build type: ${CMAKE_BUILD_TYPE}") diff --git a/kmymoney/converter/tests/converter-test.cpp b/kmymoney/converter/tests/converter-test.cpp index 462871a04..0a3072e05 100644 --- a/kmymoney/converter/tests/converter-test.cpp +++ b/kmymoney/converter/tests/converter-test.cpp @@ -1,199 +1,199 @@ /*************************************************************************** convertertest.cpp ------------------- copyright : (C) 2002 by Thomas Baumgart email : ipwizard@users.sourceforge.net Ace Jones ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "converter-test.h" -#include +#include #include // uses helper functions from reports tests #include "reportstestcommon.h" using namespace test; #include "mymoneyinstitution.h" #include "mymoneysecurity.h" #include "mymoneyprice.h" #include "mymoneyreport.h" #include "mymoneystatement.h" #include "storage/mymoneystoragexml.h" #include "storage/mymoneystoragedump.h" #include "webpricequote.h" QTEST_GUILESS_MAIN(ConverterTest) using namespace convertertest; void ConverterTest::init() { storage = new MyMoneySeqAccessMgr; file = MyMoneyFile::instance(); file->attachStorage(storage); MyMoneyFileTransaction ft; file->addCurrency(MyMoneySecurity("CAD", "Canadian Dollar", "C$")); file->addCurrency(MyMoneySecurity("USD", "US Dollar", "$")); file->addCurrency(MyMoneySecurity("JPY", "Japanese Yen", QChar(0x00A5), 1)); file->addCurrency(MyMoneySecurity("GBP", "British Pound", "#")); file->setBaseCurrency(file->currency("USD")); MyMoneyPayee payeeTest("Test Payee"); file->addPayee(payeeTest); MyMoneyPayee payeeTest2("Thomas Baumgart"); file->addPayee(payeeTest2); acAsset = (MyMoneyFile::instance()->asset().id()); acLiability = (MyMoneyFile::instance()->liability().id()); acExpense = (MyMoneyFile::instance()->expense().id()); acIncome = (MyMoneyFile::instance()->income().id()); acChecking = makeAccount("Checking Account", eMyMoney::Account::Checkings, moConverterCheckingOpen, QDate(2004, 5, 15), acAsset); acCredit = makeAccount("Credit Card", eMyMoney::Account::CreditCard, moConverterCreditOpen, QDate(2004, 7, 15), acLiability); acSolo = makeAccount("Solo", eMyMoney::Account::Expense, MyMoneyMoney(), QDate(2004, 1, 11), acExpense); acParent = makeAccount("Parent", eMyMoney::Account::Expense, MyMoneyMoney(), QDate(2004, 1, 11), acExpense); acChild = makeAccount("Child", eMyMoney::Account::Expense, MyMoneyMoney(), QDate(2004, 2, 11), acParent); acForeign = makeAccount("Foreign", eMyMoney::Account::Expense, MyMoneyMoney(), QDate(2004, 1, 11), acExpense); MyMoneyInstitution i("Bank of the World", "", "", "", "", "", ""); file->addInstitution(i); inBank = i.id(); ft.commit(); } void ConverterTest::cleanup() { file->detachStorage(storage); delete storage; } void ConverterTest::testWebQuotes_data() { QTest::addColumn("symbol"); QTest::addColumn("testname"); QTest::addColumn("source"); QTest::newRow("Yahoo UK") << "VOD.L" << "test Yahoo UK" << "Yahoo UK"; QTest::newRow("Yahoo Currency") << "EUR > USD" << "test Yahoo Currency" << "Yahoo Currency"; QTest::newRow("Financial Express") << "0585239" << "test Financial Express" << "Financial Express"; QTest::newRow("Yahoo France") << "EAD.PA" << "test Yahoo France" << "Yahoo France"; QTest::newRow("Globe & Mail") << "50492" << "test Globe-Mail" << "Globe & Mail"; QTest::newRow("MSN Canada") << "TDB647" << "test MSN.CA" << "MSN.CA"; // QTest::newRow("Finanztreff") << "BASF.SE" << "test Finanztreff" << "Finanztreff"; // QTest::newRow("boerseonline") << "symbol" << "test boerseonline" << "boerseonline"; // QTest::newRow("Wallstreet-Online.DE (Default)") << "symbol" << "test Wallstreet-Online.DE (Default)" << "Wallstreet-Online.DE (Default)"; // QTest::newRow("Financial Times UK") << "DZGEAE" << "test Financial Times UK Funds" << "Financial Times UK Funds"); QTest::newRow("Yahoo Canada") << "UTS.TO" << "test Yahoo Canada" << "Yahoo Canada"; // QTest::newRow("Wallstreed-Online.DE (Hamburg)") << "TDB647" << "test Wallstreet-Online.DE (Hamburg)" << "Wallstreet-Online.DE (Hamburg)"; // QTest::newRow("Gielda Papierow Wartosciowych (GPW)") << "TDB647" << "test Gielda Papierow Wartosciowych (GPW)" << "Gielda Papierow Wartosciowych (GPW)"; // QTest::newRow("OMX Baltic") << "TDB647" << "test OMX Baltic funds" << "OMX Baltic funds"; QTest::newRow("Finance::Quote usa") << "DIS" << "test F::Q usa" << "Finance::Quote usa"; //UNTESTED: Other F::Q sources, local files, user custom sources } void ConverterTest::testWebQuotesDefault() { #ifdef PERFORM_ONLINE_TESTS try { WebPriceQuote q; QuoteReceiver qr(&q); q.launch("DIS", "test default"); // qDebug() << "ConverterTest::testWebQuotes(): quote for " << q.m_symbol << " on " << qr.m_date.toString() << " is " << qr.m_price.toString() << " errors(" << qr.m_errors.count() << "): " << qr.m_errors.join(" /// "); // No errors allowed QVERIFY(qr.m_errors.count() == 0); // Quote date should be within the last week, or something bad is going on. QVERIFY(qr.m_date <= QDate::currentDate()); QVERIFY(qr.m_date >= QDate::currentDate().addDays(-7)); // Quote value should at least be positive QVERIFY(qr.m_price.isPositive()); } catch (const MyMoneyException &e) { QFAIL(qPrintable(e.what())); } #endif } void ConverterTest::testWebQuotes() { #ifdef PERFORM_ONLINE_TESTS try { WebPriceQuote q; QuoteReceiver qr(&q); QFETCH(QString, symbol); QFETCH(QString, testname); QFETCH(QString, source); q.launch(symbol, testname, source); QVERIFY(qr.m_errors.count() == 0); QVERIFY(qr.m_date <= QDate::currentDate().addDays(1)); QVERIFY(qr.m_date >= QDate::currentDate().addDays(-7)); QVERIFY(qr.m_price.isPositive()); } catch (const MyMoneyException &e) { QFAIL(qPrintable(e.what())); } #endif } void ConverterTest::testDateFormat() { try { MyMoneyDateFormat format("%mm-%dd-%yyyy"); QVERIFY(format.convertString("1-5-2005") == QDate(2005, 1, 5)); QVERIFY(format.convertString("jan-15-2005") == QDate(2005, 1, 15)); QVERIFY(format.convertString("august-25-2005") == QDate(2005, 8, 25)); format = MyMoneyDateFormat("%mm/%dd/%yy"); QVERIFY(format.convertString("1/5/05") == QDate(2005, 1, 5)); QVERIFY(format.convertString("jan/15/05") == QDate(2005, 1, 15)); QVERIFY(format.convertString("august/25/05") == QDate(2005, 8, 25)); format = MyMoneyDateFormat("%d\\.%m\\.%yy"); QVERIFY(format.convertString("1.5.05") == QDate(2005, 5, 1)); QVERIFY(format.convertString("15.jan.05") == QDate(2005, 1, 15)); QVERIFY(format.convertString("25.august.05") == QDate(2005, 8, 25)); format = MyMoneyDateFormat("%yyyy\\\\%dddd\\\\%mmmmmmmmmmm"); QVERIFY(format.convertString("2005\\31\\12") == QDate(2005, 12, 31)); QVERIFY(format.convertString("2005\\15\\jan") == QDate(2005, 1, 15)); QVERIFY(format.convertString("2005\\25\\august") == QDate(2005, 8, 25)); format = MyMoneyDateFormat("%m %dd, %yyyy"); QVERIFY(format.convertString("jan 15, 2005") == QDate(2005, 1, 15)); QVERIFY(format.convertString("august 25, 2005") == QDate(2005, 8, 25)); QVERIFY(format.convertString("january 1st, 2005") == QDate(2005, 1, 1)); format = MyMoneyDateFormat("%m %d %y"); QVERIFY(format.convertString("12/31/50", false, 2000) == QDate(1950, 12, 31)); QVERIFY(format.convertString("1/1/90", false, 2000) == QDate(1990, 1, 1)); QVERIFY(format.convertString("december 31st, 5", false) == QDate(2005, 12, 31)); } catch (const MyMoneyException &e) { QFAIL(qPrintable(e.what())); } } diff --git a/kmymoney/converter/tests/converter-test.h b/kmymoney/converter/tests/converter-test.h index 8433f0247..c1c0b6bcf 100644 --- a/kmymoney/converter/tests/converter-test.h +++ b/kmymoney/converter/tests/converter-test.h @@ -1,43 +1,43 @@ /*************************************************************************** convertertest.h ------------------- copyright : (C) 2002 by Thomas Baumgart email : ipwizard@users.sourceforge.net Ace Jones ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef CONVERTERTEST_H #define CONVERTERTEST_H -#include +#include #include "mymoneyfile.h" #include "storage/mymoneyseqaccessmgr.h" class ConverterTest : public QObject { Q_OBJECT private: MyMoneySeqAccessMgr* storage; MyMoneyFile* file; private slots: void init(); void cleanup(); void testWebQuotesDefault(); void testWebQuotes_data(); void testWebQuotes(); void testDateFormat(); }; #endif // CONVERTERTEST_H diff --git a/kmymoney/converter/tests/matchfinder-test.h b/kmymoney/converter/tests/matchfinder-test.h index 28edbb666..302c44832 100644 --- a/kmymoney/converter/tests/matchfinder-test.h +++ b/kmymoney/converter/tests/matchfinder-test.h @@ -1,107 +1,107 @@ /*************************************************************************** KMyMoney transaction importing module - tests for ExistingTransactionMatchFinder copyright : (C) 2012 by Lukasz Maszczynski ***************************************************************************/ /*************************************************************************** * * * 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 MATCHFINDERTEST_H #define MATCHFINDERTEST_H -#include +#include #include #include "mymoneyaccount.h" #include "mymoneyseqaccessmgr.h" #include "existingtransactionmatchfinder.h" #include "scheduledtransactionmatchfinder.h" class MyMoneyFile; class MatchFinderTest : public QObject { Q_OBJECT private: MyMoneyFile * file; QScopedPointer account; QScopedPointer otherAccount; QScopedPointer storage; MyMoneyPayee payee; MyMoneyPayee otherPayee; static const int MATCH_WINDOW = 4; MyMoneyTransaction ledgerTransaction; MyMoneyTransaction importTransaction; TransactionMatchFinder::MatchResult matchResult; QScopedPointer existingTrFinder; MyMoneySchedule schedule; QScopedPointer scheduledTrFinder; void setupStorage(); void setupCurrency(); void setupAccounts(); void setupPayees(); MyMoneyTransaction buildDefaultTransaction() const; MyMoneyTransaction buildMatchedTransaction(MyMoneyTransaction transaction) const; QString addTransactionToLedger(MyMoneyTransaction transaction) const; MyMoneySchedule buildNonOverdueSchedule() const; void addSchedule(MyMoneySchedule schedule) const; void expectMatchWithExistingTransaction(TransactionMatchFinder::MatchResult expectedResult); void expectMatchWithScheduledTransaction(TransactionMatchFinder::MatchResult expectedResult); private slots: void init(); void cleanup(); void testDuplicate_allMatch(); void testDuplicate_payeeEmpty(); void testDuplicate_payeeMismatch(); void testDuplicate_splitIsMarkedAsMatched(); void testPreciseMatch_noBankId(); void testPreciseMatch_importBankId(); void testPreciseMatch_payeeEmpty(); void testImpreciseMatch_matchWindowLowerBound(); void testImpreciseMatch_matchWindowUpperBound(); void testImpreciseMatch_payeeEmpty(); void testNoMatch_bankIdMismatch(); void testNoMatch_ledgerBankIdNotEmpty(); void testNoMatch_accountMismatch_withBankId(); void testNoMatch_accountMismatch_noBankId(); void testNoMatch_amountMismatch_withBankId(); void testNoMatch_amountMismatch_noBankId(); void testNoMatch_payeeMismatch(); void testNoMatch_splitIsMarkedAsMatched(); void testNoMatch_postDateMismatch_withBankId(); void testNoMatch_postDateMismatch_noBankId(); void testExistingTransactionMatch_sameTransactionId_withBankId(); void testExistingTransactionMatch_sameTransactionId_noBankId(); void testExistingTransactionMatch_multipleAccounts_withBankId(); void testExistingTransactionMatch_multipleAccounts_noBankId(); void testScheduleMatch_allMatch(); void testScheduleMatch_dueDateWithinMatchWindow(); void testScheduleMatch_amountWithinAllowedVariation(); void testScheduleMatch_overdue(); void testScheduleMismatch_dueDate(); void testScheduleMismatch_amount(); }; #endif // MATCHFINDERTEST_H diff --git a/kmymoney/misc/CMakeLists.txt b/kmymoney/misc/CMakeLists.txt index 9685518c5..3d3cd2dc8 100644 --- a/kmymoney/misc/CMakeLists.txt +++ b/kmymoney/misc/CMakeLists.txt @@ -1,55 +1,57 @@ install(PROGRAMS financequote.pl DESTINATION ${DATA_INSTALL_DIR}/kmymoney/misc) set( kmm_utils_validators_SRCS charvalidator.cpp validators.cpp ) set( kmm_utils_webconnect_SRCS webconnect.cpp ) if( ${HAVE_UNISTD_H} AND ${HAVE_PWD_H} ) set( kmm_utils_platformtools_SRCS platformtools_gnu.cpp ) elseif( ${HAVE_WINDOWS_H} AND ${HAVE_LMCONS_H} AND ${HAVE_PROCESS_H} ) set( kmm_utils_platformtools_SRCS platformtools_nognu.cpp ) else() message(FATAL_ERROR "make sure either windows.h and lmcons.h (on msvc platforms) or unistd.h and pwd.h (on other platforms) are present.") endif() set( kmm_utils_validators_HEADER charvalidator.h validators.h ) set( kmm_utils_webconnect_HEADER webconnect.h ) set( kmm_utils_platformtools_HEADER platformtools.h ) add_library(kmm_utils_validators STATIC ${kmm_utils_validators_SRCS}) add_library(kmm_utils_webconnect STATIC ${kmm_utils_webconnect_SRCS}) add_library(kmm_utils_platformtools STATIC ${kmm_utils_platformtools_SRCS}) target_link_libraries( kmm_utils_validators PUBLIC Qt5::Core + Qt5::Gui ) target_link_libraries( kmm_utils_webconnect PUBLIC Qt5::Core + Qt5::Network ) target_link_libraries( kmm_utils_platformtools PUBLIC Qt5::Core ) diff --git a/kmymoney/misc/charvalidator.h b/kmymoney/misc/charvalidator.h index 48a18a6f9..d98a89083 100644 --- a/kmymoney/misc/charvalidator.h +++ b/kmymoney/misc/charvalidator.h @@ -1,38 +1,38 @@ /* * This file is part of KMyMoney, A Personal Finance Manager by KDE * Copyright (C) 2015 Christian Dávid * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef CHARVALIDATOR_H #define CHARVALIDATOR_H -#include +#include class charValidator : public QValidator { Q_OBJECT public: charValidator(QObject* parent = 0, const QString& characters = QString()); virtual QValidator::State validate(QString& , int&) const; void setAllowedCharacters(const QString&); private: QString m_allowedCharacters; }; #endif // CHARVALIDATOR_H diff --git a/kmymoney/misc/validators.cpp b/kmymoney/misc/validators.cpp index 8523e6282..fb529fc65 100644 --- a/kmymoney/misc/validators.cpp +++ b/kmymoney/misc/validators.cpp @@ -1,41 +1,41 @@ /* * This file is part of KMyMoney, A Personal Finance Manager by KDE * Copyright (C) 2014 Christian Dávid * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "validators.h" -#include +#include bool validators::checkLineLength(const QString& text, const int& length) { const QStringList lines = text.split('\n'); foreach (QString line, lines) { if (line.length() > length) return false; } return true; } bool validators::checkCharset(const QString& text, const QString& allowedChars) { const int length = text.length(); for (int i = 0; i < length; ++i) { if (!allowedChars.contains(text.at(i))) return false; } return true; } diff --git a/kmymoney/misc/validators.h b/kmymoney/misc/validators.h index c802998d6..b6f3fd291 100644 --- a/kmymoney/misc/validators.h +++ b/kmymoney/misc/validators.h @@ -1,40 +1,40 @@ /* * This file is part of KMyMoney, A Personal Finance Manager by KDE * Copyright (C) 2014 Christian Dávid * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef VALIDATORS_H #define VALIDATORS_H -#include +#include namespace validators { enum lengthStatus { ok = 0, tooShort = -1, tooLong = 1 }; /** @brief checks if all lines in text are shorter than length */ bool checkLineLength(const QString& text, const int& length); /** @brief checks if text uses only charactes in allowedChars */ bool checkCharset(const QString& text, const QString& allowedChars); }; #endif // VALIDATORS_H diff --git a/kmymoney/misc/webconnect.cpp b/kmymoney/misc/webconnect.cpp index 7c0fb5a12..0a3402295 100644 --- a/kmymoney/misc/webconnect.cpp +++ b/kmymoney/misc/webconnect.cpp @@ -1,191 +1,191 @@ /* * This file is part of KMyMoney, A Personal Finance Manager by KDE * Copyright (C) 2017 Thomas Baumgart * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "webconnect.h" -#include -#include +#include +#include #include #include #include Q_LOGGING_CATEGORY(WebConnectLog, "WebConnect") class WebConnect::Private { public: Private(WebConnect* parent) : q(parent) , clientSocket(new QLocalSocket(parent)) , serverSocket(0) , server(new QLocalServer(parent)) , serverFail(false) , blockSize(0) { } WebConnect* q; QString socketName; QLocalSocket* clientSocket; QLocalSocket* serverSocket; QLocalServer* server; bool serverFail; quint32 blockSize; void startup() { // create a per user socket name socketName = QString("%1/KMyMoney-WebConnect").arg(QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation)); // try to find a server if (!connectToServer()) { // no other instance seems to be running, so we start the server if (!server->listen(socketName)) { qCInfo(WebConnectLog) << "Starting server failed. Try to remove stale socket."; server->removeServer(socketName); if(!server->listen(socketName)) { qCWarning(WebConnectLog) << "Starting server failed again. WebConnect not available."; serverFail = true; } } if (!serverFail) { qCInfo(WebConnectLog) << "Running in server mode"; } else { qCWarning(WebConnectLog) << "Unable to start server mode"; } } else { qCInfo(WebConnectLog) << "Running in client mode"; clientSocket->disconnectFromServer(); } } bool connectToServer() { // try to find a server qCDebug(WebConnectLog) << "Try to connect to WebConnect server"; clientSocket->setServerName(socketName); clientSocket->connectToServer(); bool rc = clientSocket->waitForConnected(200); qCDebug(WebConnectLog) << "Connect to server" << (rc ? "is ok" : "failed"); return rc; } }; WebConnect::WebConnect(QObject* parent) : QObject(parent) , d(new Private(this)) { connect(d->clientSocket, &QLocalSocket::connected, this, &WebConnect::serverConnected); connect(d->clientSocket, &QLocalSocket::disconnected, this, &WebConnect::serverDisconnected); connect(d->server, &QLocalServer::newConnection, this, &WebConnect::clientConnected); d->startup(); } WebConnect::~WebConnect() { if (d->server->isListening()) { d->server->close(); } delete d; } void WebConnect::clientConnected() { qCDebug(WebConnectLog) << "Client connected"; disconnect(d->server, &QLocalServer::newConnection, this, &WebConnect::clientConnected); if (!d->serverSocket) { qCDebug(WebConnectLog) << "Get next pending connection"; // Reset to beginning of stream d->blockSize = 0; d->serverSocket = d->server->nextPendingConnection(); connect(d->serverSocket, &QLocalSocket::disconnected, this, &WebConnect::clientDisconnected); connect(d->serverSocket, &QLocalSocket::readyRead, this, &WebConnect::dataAvailable); } } void WebConnect::clientDisconnected() { qCDebug(WebConnectLog) << "Client disconnected"; d->serverSocket->deleteLater(); d->serverSocket = 0; if (d->server->hasPendingConnections()) { qCDebug(WebConnectLog) << "Processing next pending connection"; clientConnected(); } else { qCDebug(WebConnectLog) << "Wait for next client"; connect(d->server, &QLocalServer::newConnection, this, &WebConnect::clientConnected); } } void WebConnect::serverConnected() { qCDebug(WebConnectLog) << "Server connected"; } void WebConnect::serverDisconnected() { qCDebug(WebConnectLog) << "Server disconnected"; } void WebConnect::dataAvailable() { QDataStream in(d->serverSocket); in.setVersion(QDataStream::Qt_4_0); if (d->blockSize == 0) { // Relies on the fact that we put the length into the QDataStream if (d->serverSocket->bytesAvailable() < (int)sizeof(quint32)) { return; } in >> d->blockSize; } if (d->serverSocket->bytesAvailable() < (int)sizeof(quint32) || d->serverSocket->atEnd()) { return; } QUrl url; in >> url; qCInfo(WebConnectLog) << "Processing" << url; emit gotUrl(url); } void WebConnect::loadFile(const QUrl& url) { if (d->connectToServer()) { qCInfo(WebConnectLog) << "Pass to server" << url; // transfer filename QByteArray block; QDataStream stream(&block, QIODevice::WriteOnly); stream.setVersion(QDataStream::Qt_4_0); stream << (quint32) 0; stream << url; stream.device()->seek(0); stream << (quint32)(block.size() - sizeof(quint32)); d->clientSocket->write(block); d->clientSocket->flush(); d->clientSocket->disconnectFromServer(); } else { qCWarning(WebConnectLog) << "Webconnect loadfile connection failed on client side"; } } bool WebConnect::isClient() const { return !d->server->isListening() && !d->serverFail; } diff --git a/kmymoney/models/CMakeLists.txt b/kmymoney/models/CMakeLists.txt index 807df98c8..342ac1068 100644 --- a/kmymoney/models/CMakeLists.txt +++ b/kmymoney/models/CMakeLists.txt @@ -1,36 +1,49 @@ set(libmodels_a_SOURCES ledgermodel.cpp ledgeritem.cpp ledgerproxymodel.cpp ledgerschedule.cpp ledgersplit.cpp ledgertransaction.cpp splitmodel.cpp costcentermodel.cpp payeesmodel.cpp accountsmodel.cpp accountsproxymodel.cpp onlinejobmodel.cpp onlinebankingaccountsfilterproxymodel.cpp ../mymoney/onlinejobmessage.cpp models.cpp payeeidentifiercontainermodel.cpp onlinejobmessagesmodel.cpp equitiesmodel.cpp securitiesmodel.cpp ) if (USE_MODELTEST) add_definitions( -DKMM_MODELTEST ) set(libmodels_a_SOURCES ${libmodels_a_SOURCES} modeltest.cpp) endif(USE_MODELTEST) add_library(models STATIC ${libmodels_a_SOURCES}) +if (USE_MODELTEST) + target_link_libraries(models LINK_PUBLIC kmm_mymoney kmymoney_common KF5::ItemModels + Qt5::Test ) +else(USE_MODELTEST) + +target_link_libraries(models LINK_PUBLIC + kmm_mymoney + kmymoney_common + KF5::ItemModels +) + +endif(USE_MODELTEST) + add_dependencies(models kmm_config) diff --git a/kmymoney/models/modeltest.cpp b/kmymoney/models/modeltest.cpp index 50fc950fd..30fad8d5b 100644 --- a/kmymoney/models/modeltest.cpp +++ b/kmymoney/models/modeltest.cpp @@ -1,563 +1,563 @@ /**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** ** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage ** This file may be used under the terms of the GNU Lesser General Public ** License version 2.1 as published by the Free Software Foundation and ** appearing in the file LICENSE.LGPL included in the packaging of this ** file. Please review the following information to ensure the GNU Lesser ** General Public License version 2.1 requirements will be met: ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU General ** Public License version 3.0 as published by the Free Software Foundation ** and appearing in the file LICENSE.GPL included in the packaging of this ** file. Please review the following information to ensure the GNU General ** Public License version 3.0 requirements will be met: ** http://www.gnu.org/copyleft/gpl.html. ** ** Other Usage ** Alternatively, this file may be used in accordance with the terms and ** conditions contained in a signed written agreement between you and Nokia. ** ** ** ** ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "modeltest.h" -#include +#include -#include +#include Q_DECLARE_METATYPE ( QModelIndex ) /*! Connect to all of the models signals. Whenever anything happens recheck everything. */ ModelTest::ModelTest ( QAbstractItemModel *_model, QObject *parent ) : QObject ( parent ), model ( _model ), fetchingMore ( false ) { if (!model) qFatal("%s: model must not be null", Q_FUNC_INFO); connect ( model, SIGNAL ( columnsAboutToBeInserted ( const QModelIndex &, int, int ) ), this, SLOT ( runAllTests() ) ); connect ( model, SIGNAL ( columnsAboutToBeRemoved ( const QModelIndex &, int, int ) ), this, SLOT ( runAllTests() ) ); connect ( model, SIGNAL ( columnsInserted ( const QModelIndex &, int, int ) ), this, SLOT ( runAllTests() ) ); connect ( model, SIGNAL ( columnsRemoved ( const QModelIndex &, int, int ) ), this, SLOT ( runAllTests() ) ); connect ( model, SIGNAL ( dataChanged ( const QModelIndex &, const QModelIndex & ) ), this, SLOT ( runAllTests() ) ); connect ( model, SIGNAL ( headerDataChanged ( Qt::Orientation, int, int ) ), this, SLOT ( runAllTests() ) ); connect ( model, SIGNAL ( layoutAboutToBeChanged () ), this, SLOT ( runAllTests() ) ); connect ( model, SIGNAL ( layoutChanged () ), this, SLOT ( runAllTests() ) ); connect ( model, SIGNAL ( modelReset () ), this, SLOT ( runAllTests() ) ); connect ( model, SIGNAL ( rowsAboutToBeInserted ( const QModelIndex &, int, int ) ), this, SLOT ( runAllTests() ) ); connect ( model, SIGNAL ( rowsAboutToBeRemoved ( const QModelIndex &, int, int ) ), this, SLOT ( runAllTests() ) ); connect ( model, SIGNAL ( rowsInserted ( const QModelIndex &, int, int ) ), this, SLOT ( runAllTests() ) ); connect ( model, SIGNAL ( rowsRemoved ( const QModelIndex &, int, int ) ), this, SLOT ( runAllTests() ) ); // Special checks for inserting/removing connect ( model, SIGNAL ( layoutAboutToBeChanged() ), this, SLOT ( layoutAboutToBeChanged() ) ); connect ( model, SIGNAL ( layoutChanged() ), this, SLOT ( layoutChanged() ) ); connect ( model, SIGNAL ( rowsAboutToBeInserted ( const QModelIndex &, int, int ) ), this, SLOT ( rowsAboutToBeInserted ( const QModelIndex &, int, int ) ) ); connect ( model, SIGNAL ( rowsAboutToBeRemoved ( const QModelIndex &, int, int ) ), this, SLOT ( rowsAboutToBeRemoved ( const QModelIndex &, int, int ) ) ); connect ( model, SIGNAL ( rowsInserted ( const QModelIndex &, int, int ) ), this, SLOT ( rowsInserted ( const QModelIndex &, int, int ) ) ); connect ( model, SIGNAL ( rowsRemoved ( const QModelIndex &, int, int ) ), this, SLOT ( rowsRemoved ( const QModelIndex &, int, int ) ) ); runAllTests(); } void ModelTest::runAllTests() { if ( fetchingMore ) return; nonDestructiveBasicTest(); rowCount(); columnCount(); hasIndex(); index(); parent(); data(); } /*! nonDestructiveBasicTest tries to call a number of the basic functions (not all) to make sure the model doesn't outright segfault, testing the functions that makes sense. */ void ModelTest::nonDestructiveBasicTest() { QVERIFY( model->buddy ( QModelIndex() ) == QModelIndex() ); model->canFetchMore ( QModelIndex() ); QVERIFY( model->columnCount ( QModelIndex() ) >= 0 ); QVERIFY( model->data ( QModelIndex() ) == QVariant() ); fetchingMore = true; model->fetchMore ( QModelIndex() ); fetchingMore = false; Qt::ItemFlags flags = model->flags ( QModelIndex() ); QVERIFY( flags == Qt::ItemIsDropEnabled || flags == 0 ); model->hasChildren ( QModelIndex() ); model->hasIndex ( 0, 0 ); model->headerData ( 0, Qt::Horizontal ); model->index ( 0, 0 ); model->itemData ( QModelIndex() ); QVariant cache; model->match ( QModelIndex(), -1, cache ); model->mimeTypes(); QVERIFY( model->parent ( QModelIndex() ) == QModelIndex() ); QVERIFY( model->rowCount() >= 0 ); QVariant variant; model->setData ( QModelIndex(), variant, -1 ); model->setHeaderData ( -1, Qt::Horizontal, QVariant() ); model->setHeaderData ( 999999, Qt::Horizontal, QVariant() ); QMap roles; model->sibling ( 0, 0, QModelIndex() ); model->span ( QModelIndex() ); model->supportedDropActions(); } /*! Tests model's implementation of QAbstractItemModel::rowCount() and hasChildren() Models that are dynamically populated are not as fully tested here. */ void ModelTest::rowCount() { // qDebug() << "rc"; // check top row QModelIndex topIndex = model->index ( 0, 0, QModelIndex() ); int rows = model->rowCount ( topIndex ); QVERIFY( rows >= 0 ); if ( rows > 0 ) QVERIFY( model->hasChildren ( topIndex ) ); QModelIndex secondLevelIndex = model->index ( 0, 0, topIndex ); if ( secondLevelIndex.isValid() ) { // not the top level // check a row count where parent is valid rows = model->rowCount ( secondLevelIndex ); QVERIFY( rows >= 0 ); if ( rows > 0 ) QVERIFY( model->hasChildren ( secondLevelIndex ) ); } // The models rowCount() is tested more extensively in checkChildren(), // but this catches the big mistakes } /*! Tests model's implementation of QAbstractItemModel::columnCount() and hasChildren() */ void ModelTest::columnCount() { // check top row QModelIndex topIndex = model->index ( 0, 0, QModelIndex() ); QVERIFY( model->columnCount ( topIndex ) >= 0 ); // check a column count where parent is valid QModelIndex childIndex = model->index ( 0, 0, topIndex ); if ( childIndex.isValid() ) QVERIFY( model->columnCount ( childIndex ) >= 0 ); // columnCount() is tested more extensively in checkChildren(), // but this catches the big mistakes } /*! Tests model's implementation of QAbstractItemModel::hasIndex() */ void ModelTest::hasIndex() { // qDebug() << "hi"; // Make sure that invalid values returns an invalid index QVERIFY( !model->hasIndex ( -2, -2 ) ); QVERIFY( !model->hasIndex ( -2, 0 ) ); QVERIFY( !model->hasIndex ( 0, -2 ) ); int rows = model->rowCount(); int columns = model->columnCount(); // check out of bounds QVERIFY( !model->hasIndex ( rows, columns ) ); QVERIFY( !model->hasIndex ( rows + 1, columns + 1 ) ); if ( rows > 0 ) QVERIFY( model->hasIndex ( 0, 0 ) ); // hasIndex() is tested more extensively in checkChildren(), // but this catches the big mistakes } /*! Tests model's implementation of QAbstractItemModel::index() */ void ModelTest::index() { // qDebug() << "i"; // Make sure that invalid values returns an invalid index QVERIFY( model->index ( -2, -2 ) == QModelIndex() ); QVERIFY( model->index ( -2, 0 ) == QModelIndex() ); QVERIFY( model->index ( 0, -2 ) == QModelIndex() ); int rows = model->rowCount(); int columns = model->columnCount(); if ( rows == 0 ) return; // Catch off by one errors QVERIFY( model->index ( rows, columns ) == QModelIndex() ); QVERIFY( model->index ( 0, 0 ).isValid() ); // Make sure that the same index is *always* returned QModelIndex a = model->index ( 0, 0 ); QModelIndex b = model->index ( 0, 0 ); QVERIFY( a == b ); // index() is tested more extensively in checkChildren(), // but this catches the big mistakes } /*! Tests model's implementation of QAbstractItemModel::parent() */ void ModelTest::parent() { // qDebug() << "p"; // Make sure the model wont crash and will return an invalid QModelIndex // when asked for the parent of an invalid index. QVERIFY( model->parent ( QModelIndex() ) == QModelIndex() ); if ( model->rowCount() == 0 ) return; // Column 0 | Column 1 | // QModelIndex() | | // \- topIndex | topIndex1 | // \- childIndex | childIndex1 | // Common error test #1, make sure that a top level index has a parent // that is a invalid QModelIndex. QModelIndex topIndex = model->index ( 0, 0, QModelIndex() ); QVERIFY( model->parent ( topIndex ) == QModelIndex() ); // Common error test #2, make sure that a second level index has a parent // that is the first level index. if ( model->rowCount ( topIndex ) > 0 ) { QModelIndex childIndex = model->index ( 0, 0, topIndex ); QVERIFY( model->parent ( childIndex ) == topIndex ); } // Common error test #3, the second column should NOT have the same children // as the first column in a row. // Usually the second column shouldn't have children. QModelIndex topIndex1 = model->index ( 0, 1, QModelIndex() ); if ( model->rowCount ( topIndex1 ) > 0 ) { QModelIndex childIndex = model->index ( 0, 0, topIndex ); QModelIndex childIndex1 = model->index ( 0, 0, topIndex1 ); QVERIFY( childIndex != childIndex1 ); } // Full test, walk n levels deep through the model making sure that all // parent's children correctly specify their parent. checkChildren ( QModelIndex() ); } /*! Called from the parent() test. A model that returns an index of parent X should also return X when asking for the parent of the index. This recursive function does pretty extensive testing on the whole model in an effort to catch edge cases. This function assumes that rowCount(), columnCount() and index() already work. If they have a bug it will point it out, but the above tests should have already found the basic bugs because it is easier to figure out the problem in those tests then this one. */ void ModelTest::checkChildren ( const QModelIndex &parent, int currentDepth ) { // First just try walking back up the tree. QModelIndex p = parent; while ( p.isValid() ) p = p.parent(); // For models that are dynamically populated if ( model->canFetchMore ( parent ) ) { fetchingMore = true; model->fetchMore ( parent ); fetchingMore = false; } int rows = model->rowCount ( parent ); int columns = model->columnCount ( parent ); if ( rows > 0 ) QVERIFY( model->hasChildren ( parent ) ); // Some further testing against rows(), columns(), and hasChildren() QVERIFY( rows >= 0 ); QVERIFY( columns >= 0 ); if ( rows > 0 ) QVERIFY( model->hasChildren ( parent ) ); //qDebug() << "parent:" << model->data(parent).toString() << "rows:" << rows // << "columns:" << columns << "parent column:" << parent.column(); QVERIFY( !model->hasIndex ( rows + 1, 0, parent ) ); for ( int r = 0; r < rows; ++r ) { if ( model->canFetchMore ( parent ) ) { fetchingMore = true; model->fetchMore ( parent ); fetchingMore = false; } QVERIFY( !model->hasIndex ( r, columns + 1, parent ) ); for ( int c = 0; c < columns; ++c ) { QVERIFY( model->hasIndex ( r, c, parent ) ); QModelIndex index = model->index ( r, c, parent ); // rowCount() and columnCount() said that it existed... QVERIFY( index.isValid() ); // index() should always return the same index when called twice in a row QModelIndex modifiedIndex = model->index ( r, c, parent ); QVERIFY( index == modifiedIndex ); // Make sure we get the same index if we request it twice in a row QModelIndex a = model->index ( r, c, parent ); QModelIndex b = model->index ( r, c, parent ); QVERIFY( a == b ); // Some basic checking on the index that is returned QVERIFY( index.model() == model ); QCOMPARE( index.row(), r ); QCOMPARE( index.column(), c ); // While you can technically return a QVariant usually this is a sign // of a bug in data(). Disable if this really is ok in your model. // QVERIFY( model->data ( index, Qt::DisplayRole ).isValid() ); // If the next test fails here is some somewhat useful debug you play with. if (model->parent(index) != parent) { qDebug() << r << c << currentDepth << model->data(index).toString() << model->data(parent).toString(); qDebug() << index << parent << model->parent(index); // And a view that you can even use to show the model. // QTreeView view; // view.setModel(model); // view.show(); } // Check that we can get back our real parent. QCOMPARE( model->parent ( index ), parent ); // recursively go down the children if ( model->hasChildren ( index ) && currentDepth < 10 ) { //qDebug() << r << c << "has children" << model->rowCount(index); checkChildren ( index, ++currentDepth ); }/* else { if (currentDepth >= 10) qDebug() << "checked 10 deep"; };*/ // make sure that after testing the children that the index doesn't change. QModelIndex newerIndex = model->index ( r, c, parent ); QVERIFY( index == newerIndex ); } } } /*! Tests model's implementation of QAbstractItemModel::data() */ void ModelTest::data() { // Invalid index should return an invalid qvariant QVERIFY( !model->data ( QModelIndex() ).isValid() ); if ( model->rowCount() == 0 ) return; // A valid index should have a valid QVariant data QVERIFY( model->index ( 0, 0 ).isValid() ); // shouldn't be able to set data on an invalid index QVERIFY( !model->setData ( QModelIndex(), QLatin1String ( "foo" ), Qt::DisplayRole ) ); // General Purpose roles that should return a QString QVariant variant = model->data ( model->index ( 0, 0 ), Qt::ToolTipRole ); if ( variant.isValid() ) { QVERIFY( variant.canConvert() ); } variant = model->data ( model->index ( 0, 0 ), Qt::StatusTipRole ); if ( variant.isValid() ) { QVERIFY( variant.canConvert() ); } variant = model->data ( model->index ( 0, 0 ), Qt::WhatsThisRole ); if ( variant.isValid() ) { QVERIFY( variant.canConvert() ); } // General Purpose roles that should return a QSize variant = model->data ( model->index ( 0, 0 ), Qt::SizeHintRole ); if ( variant.isValid() ) { QVERIFY( variant.canConvert () ); } // General Purpose roles that should return a QFont QVariant fontVariant = model->data ( model->index ( 0, 0 ), Qt::FontRole ); if ( fontVariant.isValid() ) { QVERIFY( fontVariant.canConvert () ); } // Check that the alignment is one we know about QVariant textAlignmentVariant = model->data ( model->index ( 0, 0 ), Qt::TextAlignmentRole ); if ( textAlignmentVariant.isValid() ) { int alignment = textAlignmentVariant.toInt(); QCOMPARE( alignment, ( alignment & ( Qt::AlignHorizontal_Mask | Qt::AlignVertical_Mask ) ) ); } // General Purpose roles that should return a QColor QVariant colorVariant = model->data ( model->index ( 0, 0 ), Qt::BackgroundColorRole ); if ( colorVariant.isValid() ) { QVERIFY( colorVariant.canConvert () ); } colorVariant = model->data ( model->index ( 0, 0 ), Qt::TextColorRole ); if ( colorVariant.isValid() ) { QVERIFY( colorVariant.canConvert () ); } // Check that the "check state" is one we know about. QVariant checkStateVariant = model->data ( model->index ( 0, 0 ), Qt::CheckStateRole ); if ( checkStateVariant.isValid() ) { int state = checkStateVariant.toInt(); QVERIFY( state == Qt::Unchecked || state == Qt::PartiallyChecked || state == Qt::Checked ); } } /*! Store what is about to be inserted to make sure it actually happens \sa rowsInserted() */ void ModelTest::rowsAboutToBeInserted ( const QModelIndex &parent, int start, int end ) { // Q_UNUSED(end); // qDebug() << "rowsAboutToBeInserted" << "start=" << start << "end=" << end << "parent=" << model->data ( parent ).toString() // << "current count of parent=" << model->rowCount ( parent ); // << "display of last=" << model->data( model->index(start-1, 0, parent) ); // qDebug() << model->index(start-1, 0, parent) << model->data( model->index(start-1, 0, parent) ); Changing c; c.parent = parent; c.oldSize = model->rowCount ( parent ); c.last = model->data ( model->index ( start - 1, 0, parent ) ); c.next = model->data ( model->index ( start, 0, parent ) ); insert.push ( c ); } /*! Confirm that what was said was going to happen actually did \sa rowsAboutToBeInserted() */ void ModelTest::rowsInserted ( const QModelIndex & parent, int start, int end ) { Changing c = insert.pop(); QVERIFY( c.parent == parent ); // qDebug() << "rowsInserted" << "start=" << start << "end=" << end << "oldsize=" << c.oldSize // << "parent=" << model->data ( parent ).toString() << "current rowcount of parent=" << model->rowCount ( parent ); // for (int ii=start; ii <= end; ii++) // { // qDebug() << "itemWasInserted:" << ii << model->data ( model->index ( ii, 0, parent )); // } // qDebug(); QVERIFY( c.oldSize + ( end - start + 1 ) == model->rowCount ( parent ) ); QVERIFY( c.last == model->data ( model->index ( start - 1, 0, c.parent ) ) ); if (c.next != model->data(model->index(end + 1, 0, c.parent))) { qDebug() << start << end; for (int i=0; i < model->rowCount(); ++i) qDebug() << model->index(i, 0).data().toString(); qDebug() << c.next << model->data(model->index(end + 1, 0, c.parent)); } QVERIFY( c.next == model->data ( model->index ( end + 1, 0, c.parent ) ) ); } void ModelTest::layoutAboutToBeChanged() { for ( int i = 0; i < qBound ( 0, model->rowCount(), 100 ); ++i ) changing.append ( QPersistentModelIndex ( model->index ( i, 0 ) ) ); } void ModelTest::layoutChanged() { for ( int i = 0; i < changing.count(); ++i ) { QPersistentModelIndex p = changing[i]; QVERIFY( p == model->index ( p.row(), p.column(), p.parent() ) ); } changing.clear(); } /*! Store what is about to be inserted to make sure it actually happens \sa rowsRemoved() */ void ModelTest::rowsAboutToBeRemoved ( const QModelIndex &parent, int start, int end ) { qDebug() << "ratbr" << parent << start << end; Changing c; c.parent = parent; c.oldSize = model->rowCount ( parent ); c.last = model->data ( model->index ( start - 1, 0, parent ) ); c.next = model->data ( model->index ( end + 1, 0, parent ) ); remove.push ( c ); } /*! Confirm that what was said was going to happen actually did \sa rowsAboutToBeRemoved() */ void ModelTest::rowsRemoved ( const QModelIndex & parent, int start, int end ) { qDebug() << "rr" << parent << start << end; Changing c = remove.pop(); QVERIFY( c.parent == parent ); QVERIFY( c.oldSize - ( end - start + 1 ) == model->rowCount ( parent ) ); QVERIFY( c.last == model->data ( model->index ( start - 1, 0, c.parent ) ) ); QVERIFY( c.next == model->data ( model->index ( start, 0, c.parent ) ) ); } diff --git a/kmymoney/models/modeltest.h b/kmymoney/models/modeltest.h index 1b254a400..5cd093aa2 100644 --- a/kmymoney/models/modeltest.h +++ b/kmymoney/models/modeltest.h @@ -1,94 +1,94 @@ /**************************************************************************** ** ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/ ** ** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** GNU Lesser General Public License Usage ** This file may be used under the terms of the GNU Lesser General Public ** License version 2.1 as published by the Free Software Foundation and ** appearing in the file LICENSE.LGPL included in the packaging of this ** file. Please review the following information to ensure the GNU Lesser ** General Public License version 2.1 requirements will be met: ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU General ** Public License version 3.0 as published by the Free Software Foundation ** and appearing in the file LICENSE.GPL included in the packaging of this ** file. Please review the following information to ensure the GNU General ** Public License version 3.0 requirements will be met: ** http://www.gnu.org/copyleft/gpl.html. ** ** Other Usage ** Alternatively, this file may be used in accordance with the terms and ** conditions contained in a signed written agreement between you and Nokia. ** ** ** ** ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef MODELTEST_H #define MODELTEST_H -#include +#include #include #include class ModelTest : public QObject { Q_OBJECT public: ModelTest( QAbstractItemModel *model, QObject *parent = 0 ); private Q_SLOTS: void nonDestructiveBasicTest(); void rowCount(); void columnCount(); void hasIndex(); void index(); void parent(); void data(); protected Q_SLOTS: void runAllTests(); void layoutAboutToBeChanged(); void layoutChanged(); void rowsAboutToBeInserted( const QModelIndex &parent, int start, int end ); void rowsInserted( const QModelIndex & parent, int start, int end ); void rowsAboutToBeRemoved( const QModelIndex &parent, int start, int end ); void rowsRemoved( const QModelIndex & parent, int start, int end ); private: void checkChildren( const QModelIndex &parent, int currentDepth = 0 ); QAbstractItemModel *model; struct Changing { QModelIndex parent; int oldSize; QVariant last; QVariant next; }; QStack insert; QStack remove; bool fetchingMore; QList changing; }; #endif diff --git a/kmymoney/models/onlinejobmessagesmodel.h b/kmymoney/models/onlinejobmessagesmodel.h index 4ef2d7fc6..d9fe820a6 100644 --- a/kmymoney/models/onlinejobmessagesmodel.h +++ b/kmymoney/models/onlinejobmessagesmodel.h @@ -1,45 +1,45 @@ /* * This file is part of KMyMoney, A Personal Finance Manager by KDE * Copyright (C) 2015 Christian Dávid * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef ONLINEJOBMESSAGESMODEL_H #define ONLINEJOBMESSAGESMODEL_H -#include +#include #include "mymoney/onlinejob.h" class onlineJobMessagesModel : public QAbstractTableModel { Q_OBJECT public: explicit onlineJobMessagesModel(QObject* parent = 0); virtual QVariant data(const QModelIndex& index, int role) const; virtual int columnCount(const QModelIndex& parent) const; virtual int rowCount(const QModelIndex& parent) const; virtual QModelIndex parent(const QModelIndex& child) const; virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const; public slots: void setOnlineJob(const onlineJob& job); protected: onlineJob m_job; }; #endif // ONLINEJOBMESSAGESMODEL_H diff --git a/kmymoney/mymoney/payeeidentifier/payeeidentifiercontainermodel.h b/kmymoney/mymoney/payeeidentifier/payeeidentifiercontainermodel.h index 8bcd7927c..853c4272c 100644 --- a/kmymoney/mymoney/payeeidentifier/payeeidentifiercontainermodel.h +++ b/kmymoney/mymoney/payeeidentifier/payeeidentifiercontainermodel.h @@ -1,84 +1,84 @@ /* * This file is part of KMyMoney, A Personal Finance Manager by KDE * Copyright (C) 2014 Christian Dávid * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef PAYEEIDENTIFIERCONTAINERMODEL_H #define PAYEEIDENTIFIERCONTAINERMODEL_H -#include +#include #include "mymoney/mymoneypayeeidentifiercontainer.h" #include "payeeidentifier/payeeidentifier.h" /** * @brief Model for MyMoneyPayeeIdentifierContainer * * Changes the user does have initernal effect only. */ class payeeIdentifierContainerModel : public QAbstractListModel { Q_OBJECT public: enum roles { payeeIdentifierType = Qt::UserRole, /**< type of payeeIdentifier */ payeeIdentifier = Qt::UserRole + 1 /**< actual payeeIdentifier */ }; payeeIdentifierContainerModel(QObject* parent = 0); virtual QVariant data(const QModelIndex& index, int role) const; /** * This model only supports to edit payeeIdentifier role with a QVariant of type * payeeIdentifier. */ virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole); virtual Qt::ItemFlags flags(const QModelIndex& index) const; virtual int rowCount(const QModelIndex& parent) const; virtual bool insertRows(int row, int count, const QModelIndex& parent); virtual bool removeRows(int row, int count, const QModelIndex& parent); /** * @brief Set source of data * * This makes the model editable. */ void setSource(MyMoneyPayeeIdentifierContainer data); /** @brief Get stored data */ QList< ::payeeIdentifier > identifiers() const; public slots: /** * @brief Removes all data from the model * * The model is not editable afterwards. */ void closeSource(); private: /** @internal * The use of a shared pointer makes this future prof. Because using identifier() causes * some unnecessary work. */ QSharedPointer m_data; }; #endif // PAYEEIDENTIFIERMODEL_H diff --git a/kmymoney/mymoney/payeeidentifier/payeeidentifierdata.h b/kmymoney/mymoney/payeeidentifier/payeeidentifierdata.h index b54644a79..4cbbe16de 100644 --- a/kmymoney/mymoney/payeeidentifier/payeeidentifierdata.h +++ b/kmymoney/mymoney/payeeidentifier/payeeidentifierdata.h @@ -1,138 +1,138 @@ /* * This file is part of KMyMoney, A Personal Finance Manager by KDE * Copyright (C) 2014 Christian Dávid * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef PAYEEIDENTIFIERDATA_H #define PAYEEIDENTIFIERDATA_H #include "payeeidentifier/kmm_payeeidentifier_export.h" -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include "storage/databasestoreableobject.h" class payeeIdentifier; class payeeIdentifierLoader; /** * @brief Define a unique identifier for an payeeIdentifier subclass * * Use this macro in your class's public section. * * This also defines the helper ::ptr, ::constPtr and className::ptr cloneSharedPtr() * * @param PIDID the payeeIdentifier id, e.g. "org.kmymoney.payeeIdentifier.swift". Must be * unique among all payeeIdentifiers as it is used internaly to store data, to compare * types and for type casting (there must not be more than one class which uses that pidid). */ #define PAYEEIDENTIFIER_IID(className, iid) \ /** @brief Returns the payeeIdentifier Iid */ \ static const QString& staticPayeeIdentifierIid() { \ static const QString _pidid = QLatin1String( iid ); \ return _pidid; \ } \ /** @brief Returns the payeeIdentifier Id */ \ virtual QString payeeIdentifierId() const { \ return className::staticPayeeIdentifierIid(); \ } /** * @brief "Something" that identifies a payee (or an account of a payee) * * The simplest form of this class is an identifier for an bank account (consisting of an account number * and a bank code). But also an e-mail address which is used by an online money-transfer service could be * such an identifier (that is the reason for the abstract name "payeeIdentifier"). * * But also the creditor identifier for debit-notes in sepa-countries can be a subclass. It does not * address an account but a company. * * Any payee (@ref MyMoneyPayee) can have several payeeIdentifiers. * * The online banking system uses payeeIdentifiers to dertermine if it is able so create a credit-transfer * to a given payee. During import the payeeIdentifiers are used to find a payee. * * You should use the shared pointer payeeIdentifier::ptr to handle payeeIdentifiers. To copy them used * cloneSharedPtr(). * * @intenal First this is more complex than creating a superset of all possible identifiers. But there * are many of them. And using this method it is a lot easier to create the comparison operators and * things like isValid(). * * @section Inheriting * * To identify the type of an payeeIdentifier you must use the macro @ref PAYEEIDENTIFIER_IID() * in the public section of your subclass. */ class KMM_PAYEEIDENTIFIER_EXPORT payeeIdentifierData : public databaseStoreableObject { public: virtual ~payeeIdentifierData() {} /** * Use PAYEEIDENTIFIER_ID(className, PIDID) to reimplement this method. */ virtual QString payeeIdentifierId() const = 0; /** * @brief Comparison operator */ virtual bool operator==(const payeeIdentifierData& other) const = 0; virtual bool operator!=(const payeeIdentifierData& other) const { return (!operator==(other)); } /** * @brief Check if this payeeIdentifier contains correct data * * You should be able to handle invalid data. It is the task of the ui to prevent * invalid data. But during several procedures invalid data could be used (e.g. * during import). */ virtual bool isValid() const = 0; /** * @brief Create a new payeeIdentifier form XML data * * @param element Note: there could be more data in that elemenet than you created in writeXML() */ virtual payeeIdentifierData* createFromXml(const QDomElement &element) const = 0; virtual payeeIdentifierData* createFromSqlDatabase(QSqlDatabase db, const QString& identId) const = 0; /** * @see MyMoneyObject::writeXML() * * @warning Do not set an attribute "type" or "id" to parent, it is used to store internal data and is * set automatically. */ virtual void writeXML(QDomDocument &document, QDomElement &parent) const = 0; protected: /** * @brief Create deep copy */ virtual payeeIdentifierData* clone() const = 0; friend class payeeIdentifierLoader; friend class payeeIdentifier; }; Q_DECLARE_INTERFACE(payeeIdentifierData, "org.kmymoney.payeeIdentifier") #endif // PAYEEIDENTIFIERDATA_H diff --git a/kmymoney/mymoney/storage/tests/mymoneydatabasemgr-test.cpp b/kmymoney/mymoney/storage/tests/mymoneydatabasemgr-test.cpp index 128dec3a9..5fc01e526 100644 --- a/kmymoney/mymoney/storage/tests/mymoneydatabasemgr-test.cpp +++ b/kmymoney/mymoney/storage/tests/mymoneydatabasemgr-test.cpp @@ -1,2354 +1,2354 @@ /*************************************************************************** mymoneydatabasemgrtest.cpp ------------------- copyright : (C) 2008 by Fernando Vilas email : fvilas@iname.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 "mymoneydatabasemgr-test.h" #include -#include +#include #include "mymoneytestutils.h" #include "mymoneymoney.h" #include "mymoneyfile.h" #include "mymoneyinstitution.h" #include "mymoneyaccount.h" #include "mymoneysecurity.h" #include "mymoneytag.h" #include "mymoneypayee.h" #include "mymoneyschedule.h" #include "mymoneyreport.h" #include "mymoneysplit.h" #include "mymoneytransaction.h" #include "mymoneybudget.h" #include "onlinetasks/dummy/tasks/dummytask.h" #include "misc/platformtools.h" #include "mymoneyenums.h" using namespace eMyMoney; QTEST_GUILESS_MAIN(MyMoneyDatabaseMgrTest) MyMoneyDatabaseMgrTest::MyMoneyDatabaseMgrTest() : m_dbAttached(false), m_canOpen(true), m_haveEmptyDataBase(false), m_file(this), m_emptyFile(this) { // Open and close the temp file so that it exists m_file.open(); m_file.close(); // The same with the empty db file m_emptyFile.open(); m_emptyFile.close(); testCaseTimer.start(); } void MyMoneyDatabaseMgrTest::init() { testStepTimer.start(); m = new MyMoneyDatabaseMgr; // Create file and close it to release possible read-write locks m_file.open(); m_file.close(); } void MyMoneyDatabaseMgrTest::cleanup() { if (m_canOpen) { // All transactions should have already been committed. //m->commitTransaction(); } if (MyMoneyFile::instance()->storageAttached()) { MyMoneyFile::instance()->detachStorage(m); m_dbAttached = false; } delete m; qDebug() << "teststep" << testStepTimer.elapsed() << "msec, total" << testCaseTimer.elapsed() << "msec"; } void MyMoneyDatabaseMgrTest::testEmptyConstructor() { MyMoneyPayee user = m->user(); QVERIFY(user.name().isEmpty()); QVERIFY(user.address().isEmpty()); QVERIFY(user.city().isEmpty()); QVERIFY(user.state().isEmpty()); QVERIFY(user.postcode().isEmpty()); QVERIFY(user.telephone().isEmpty()); QVERIFY(user.email().isEmpty()); QVERIFY(m->nextInstitutionID().isEmpty()); QVERIFY(m->nextAccountID().isEmpty()); QVERIFY(m->nextTransactionID().isEmpty()); QVERIFY(m->nextPayeeID().isEmpty()); QVERIFY(m->nextScheduleID().isEmpty()); QVERIFY(m->nextReportID().isEmpty()); QVERIFY(m->nextOnlineJobID().isEmpty()); QCOMPARE(m->institutionList().count(), 0); QList accList; m->accountList(accList); QCOMPARE(accList.count(), 0); MyMoneyTransactionFilter f; QCOMPARE(m->transactionList(f).count(), 0); QCOMPARE(m->payeeList().count(), 0); QCOMPARE(m->tagList().count(), 0); QCOMPARE(m->scheduleList().count(), 0); QCOMPARE(m->m_creationDate, QDate::currentDate()); } void MyMoneyDatabaseMgrTest::setupUrl(const QString& fname) { QString m_userName = platformTools::osUsername(); QString m_mode = //"QPSQL&mode=single"; //"QMYSQL&mode=single"; "QSQLITE&mode=single"; m_url = QUrl(QString("sql://%1@localhost/%2?driver=%3").arg(m_userName, fname, m_mode)); } void MyMoneyDatabaseMgrTest::copyDatabaseFile(QFile& src, QFile& dest) { if (src.open(QIODevice::ReadOnly)) { if (dest.open(QIODevice::WriteOnly | QIODevice::Truncate)) { dest.write(src.readAll()); dest.close(); } src.close(); } } void MyMoneyDatabaseMgrTest::testBadConnections() { // Check a connection that exists but has empty tables setupUrl(m_file.fileName()); try { QExplicitlySharedDataPointer sql = m->connectToDatabase(m_url); QVERIFY(sql); QEXPECT_FAIL("", "Will fix when correct behaviour in this case is clear.", Continue); QVERIFY(sql->open(m_url, QIODevice::ReadWrite) != 0); } catch (const MyMoneyException &e) { unexpectedException(e); } } void MyMoneyDatabaseMgrTest::testCreateDb() { try { // Fetch the list of available drivers QStringList list = QSqlDatabase::drivers(); QStringList::Iterator it = list.begin(); if (it == list.end()) { m_canOpen = false; } else { setupUrl(m_file.fileName()); QExplicitlySharedDataPointer sql = m->connectToDatabase(m_url); QVERIFY(0 != sql); //qDebug("Database driver is %s", qPrintable(sql->driverName())); // Clear the database, so there is a fresh start on each run. if (0 == sql->open(m_url, QIODevice::WriteOnly, true)) { MyMoneyFile::instance()->attachStorage(m); QVERIFY(sql->writeFile()); sql->close(); copyDatabaseFile(m_file, m_emptyFile); m_haveEmptyDataBase = true; } else { m_canOpen = false; } } } catch (const MyMoneyException &e) { unexpectedException(e); } } void MyMoneyDatabaseMgrTest::testAttachDb() { if (!m_dbAttached) { if (!m_haveEmptyDataBase) { testCreateDb(); } else { // preload database file with empty set copyDatabaseFile(m_emptyFile, m_file); } if (m_canOpen) { try { MyMoneyFile::instance()->detachStorage(); QExplicitlySharedDataPointer sql = m->connectToDatabase(m_url); QVERIFY(sql); int openStatus = sql->open(m_url, QIODevice::ReadWrite); QCOMPARE(openStatus, 0); MyMoneyFile::instance()->attachStorage(m); m_dbAttached = true; } catch (const MyMoneyException &e) { unexpectedException(e); } } } } void MyMoneyDatabaseMgrTest::testDisconnection() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); try { ((QSqlDatabase*)(m->m_sql.data()))->close(); QList accList; m->accountList(accList); } catch (const MyMoneyException &e) { unexpectedException(e); } } void MyMoneyDatabaseMgrTest::testSetFunctions() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); MyMoneyPayee user = m->user(); user.setName("Name"); m->setUser(user); user.setAddress("Street"); m->setUser(user); user.setCity("Town"); m->setUser(user); user.setState("County"); m->setUser(user); user.setPostcode("Postcode"); m->setUser(user); user.setTelephone("Telephone"); m->setUser(user); user.setEmail("Email"); m->setUser(user); m->setValue("key", "value"); user = m->user(); QVERIFY(user.name() == "Name"); QVERIFY(user.address() == "Street"); QVERIFY(user.city() == "Town"); QVERIFY(user.state() == "County"); QVERIFY(user.postcode() == "Postcode"); QVERIFY(user.telephone() == "Telephone"); QVERIFY(user.email() == "Email"); QVERIFY(m->value("key") == "value"); m->setDirty(); m->deletePair("key"); QVERIFY(m->dirty() == false); } void MyMoneyDatabaseMgrTest::testSupportFunctions() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); try { QCOMPARE(m->nextInstitutionID(), QLatin1String("I000001")); QCOMPARE(m->nextAccountID(), QLatin1String("A000001")); QCOMPARE(m->nextTransactionID(), QLatin1String("T000000000000000001")); QCOMPARE(m->nextPayeeID(), QLatin1String("P000001")); QCOMPARE(m->nextTagID(), QLatin1String("G000001")); QCOMPARE(m->nextScheduleID(), QLatin1String("SCH000001")); QCOMPARE(m->nextReportID(), QLatin1String("R000001")); QCOMPARE(m->nextOnlineJobID(), QLatin1String("O00000001")); QCOMPARE(m->liability().name(), QLatin1String("Liability")); QCOMPARE(m->asset().name(), QLatin1String("Asset")); QCOMPARE(m->expense().name(), QLatin1String("Expense")); QCOMPARE(m->income().name(), QLatin1String("Income")); QCOMPARE(m->equity().name(), QLatin1String("Equity")); QCOMPARE(m->dirty(), false); } catch (const MyMoneyException &e) { unexpectedException(e); } } void MyMoneyDatabaseMgrTest::testIsStandardAccount() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); QVERIFY(m->isStandardAccount(STD_ACC_LIABILITY) == true); QVERIFY(m->isStandardAccount(STD_ACC_ASSET) == true); QVERIFY(m->isStandardAccount(STD_ACC_EXPENSE) == true); QVERIFY(m->isStandardAccount(STD_ACC_INCOME) == true); QVERIFY(m->isStandardAccount(STD_ACC_EQUITY) == true); QVERIFY(m->isStandardAccount("A0002") == false); } void MyMoneyDatabaseMgrTest::testNewAccount() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); MyMoneyAccount a; a.setName("AccountName"); a.setNumber("AccountNumber"); a.setValue("Key", "Value"); m->addAccount(a); QCOMPARE(m->accountId(), 1ul); QList accList; m->accountList(accList); QCOMPARE(accList.count(), 1); QCOMPARE((*(accList.begin())).name(), QLatin1String("AccountName")); QCOMPARE((*(accList.begin())).id(), QLatin1String("A000001")); QCOMPARE((*(accList.begin())).value("Key"), QLatin1String("Value")); } void MyMoneyDatabaseMgrTest::testAccount() { testNewAccount(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); m->setDirty(); MyMoneyAccount a; // make sure that an invalid ID causes an exception try { a = m->account("Unknown ID"); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } QVERIFY(m->dirty() == false); // now make sure, that a real ID works try { a = m->account("A000001"); QVERIFY(a.name() == "AccountName"); QVERIFY(a.id() == "A000001"); } catch (const MyMoneyException &e) { unexpectedException(e); } } void MyMoneyDatabaseMgrTest::testAddNewAccount() { testNewAccount(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); MyMoneyAccount a, b; b.setName("Account2"); b.setNumber("Acc2"); m->addAccount(b); m->setDirty(); QVERIFY(m->accountId() == 2); QList accList; m->accountList(accList); QVERIFY(accList.count() == 2); // try to add account to undefined account try { MyMoneyAccount c("UnknownID", b); m->addAccount(c, a); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } QVERIFY(m->dirty() == false); // now try to add account 1 as sub-account to account 2 try { a = m->account("A000001"); QVERIFY(m->asset().accountList().count() == 0); m->addAccount(b, a); MyMoneyAccount acc(m->account("A000002")); QVERIFY(acc.accountList()[0] == "A000001"); QVERIFY(acc.accountList().count() == 1); QVERIFY(m->asset().accountList().count() == 0); } catch (const MyMoneyException &e) { unexpectedException(e); } } void MyMoneyDatabaseMgrTest::testAddInstitution() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); MyMoneyInstitution i; i.setName("Inst Name"); m->addInstitution(i); QVERIFY(m->institutionList().count() == 1); QVERIFY(m->institutionId() == 1); QVERIFY((*(m->institutionList().begin())).name() == "Inst Name"); QVERIFY((*(m->institutionList().begin())).id() == "I000001"); } void MyMoneyDatabaseMgrTest::testInstitution() { testAddInstitution(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); MyMoneyInstitution i; m->setDirty(); // try to find unknown institution try { i = m->institution("Unknown ID"); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } QVERIFY(m->dirty() == false); // now try to find real institution try { i = m->institution("I000001"); QVERIFY(i.name() == "Inst Name"); QVERIFY(m->dirty() == false); } catch (const MyMoneyException &e) { unexpectedException(e); } } void MyMoneyDatabaseMgrTest::testAccount2Institution() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); testAddInstitution(); testAddNewAccount(); MyMoneyInstitution i; MyMoneyAccount a, b; try { i = m->institution("I000001"); a = m->account("A000001"); } catch (const MyMoneyException &e) { unexpectedException(e); } m->setDirty(); // try to add to a false institution MyMoneyInstitution fake("Unknown ID", i); a.setInstitutionId(fake.id()); try { m->modifyAccount(a); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } QVERIFY(m->dirty() == false); // now try to do it with a real institution try { QVERIFY(i.accountList().count() == 0); a.setInstitutionId(i.id()); m->modifyAccount(a); QVERIFY(a.institutionId() == i.id()); b = m->account("A000001"); QVERIFY(b.institutionId() == i.id()); QVERIFY(i.accountList().count() == 0); } catch (const MyMoneyException &e) { unexpectedException(e); } } void MyMoneyDatabaseMgrTest::testModifyAccount() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); testAccount2Institution(); // test the OK case // //FIXME: modify 2 accounts simultaneously to trip a write error MyMoneyAccount a = m->account("A000001"); a.setName("New account name"); m->setDirty(); try { m->modifyAccount(a); MyMoneyAccount b = m->account("A000001"); QVERIFY(b.parentAccountId() == a.parentAccountId()); QVERIFY(b.name() == "New account name"); QVERIFY(b.value("Key") == "Value"); } catch (const MyMoneyException &e) { unexpectedException(e); } // modify institution to unknown id MyMoneyAccount c("Unknown ID", a); m->setDirty(); try { m->modifyAccount(c); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } // use different account type MyMoneyAccount d; d.setAccountType(Account::CreditCard); MyMoneyAccount f("A000001", d); try { m->modifyAccount(f); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } // use different parent a.setParentAccountId("A000002"); try { m->modifyAccount(c); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } } void MyMoneyDatabaseMgrTest::testModifyInstitution() { testAddInstitution(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); MyMoneyInstitution i = m->institution("I000001"); m->setDirty(); i.setName("New inst name"); try { m->modifyInstitution(i); i = m->institution("I000001"); QVERIFY(i.name() == "New inst name"); } catch (const MyMoneyException &e) { unexpectedException(e); } // try to modify an institution that does not exist MyMoneyInstitution f("Unknown ID", i); try { m->modifyInstitution(f); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } } void MyMoneyDatabaseMgrTest::testReparentAccount() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); // this one adds some accounts to the database MyMoneyAccount ex1; ex1.setAccountType(Account::Expense); MyMoneyAccount ex2; ex2.setAccountType(Account::Expense); MyMoneyAccount ex3; ex3.setAccountType(Account::Expense); MyMoneyAccount ex4; ex4.setAccountType(Account::Expense); MyMoneyAccount in; in.setAccountType(Account::Income); MyMoneyAccount ch; ch.setAccountType(Account::Checkings); ex1.setName("Sales Tax"); ex2.setName("Sales Tax 16%"); ex3.setName("Sales Tax 7%"); ex4.setName("Grosseries"); in.setName("Salary"); ch.setName("My checkings account"); ch.setValue("Key", "Value"); try { m->addAccount(ex1); m->addAccount(ex2); m->addAccount(ex3); m->addAccount(ex4); m->addAccount(in); m->addAccount(ch); QVERIFY(ex1.id() == "A000001"); QVERIFY(ex2.id() == "A000002"); QVERIFY(ex3.id() == "A000003"); QVERIFY(ex4.id() == "A000004"); QVERIFY(in.id() == "A000005"); QVERIFY(ch.id() == "A000006"); QVERIFY(ch.value("Key") == "Value"); MyMoneyAccount parent = m->expense(); m->addAccount(parent, ex1); m->addAccount(ex1, ex2); m->addAccount(parent, ex3); m->addAccount(parent, ex4); parent = m->income(); m->addAccount(parent, in); parent = m->asset(); m->addAccount(parent, ch); QVERIFY(ch.value("Key") == "Value"); MyMoneyFile::instance()->preloadCache(); QVERIFY(m->expense().accountCount() == 3); QVERIFY(m->account(ex1.id()).accountCount() == 1); QVERIFY(ex3.parentAccountId() == STD_ACC_EXPENSE); //for (int i = 0; i < 100; ++i) { m->reparentAccount(ex3, ex1); //} MyMoneyFile::instance()->preloadCache(); QVERIFY(m->expense().accountCount() == 2); QVERIFY(m->account(ex1.id()).accountCount() == 2); QVERIFY(ex3.parentAccountId() == ex1.id()); } catch (const MyMoneyException &e) { unexpectedException(e); } } void MyMoneyDatabaseMgrTest::testAddTransactions() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); testReparentAccount(); MyMoneyAccount ch; MyMoneyTransaction t1, t2; MyMoneySplit s; try { // I made some money, great s.setAccountId("A000006"); // Checkings s.setShares(MyMoneyMoney(100000, 100)); s.setValue(MyMoneyMoney(100000, 100)); QVERIFY(s.id().isEmpty()); t1.addSplit(s); s.setId(QString()); // enable re-usage of split variable s.setAccountId("A000005"); // Salary s.setShares(MyMoneyMoney(-100000, 100)); s.setValue(MyMoneyMoney(-100000, 100)); QVERIFY(s.id().isEmpty()); t1.addSplit(s); t1.setPostDate(QDate(2002, 5, 10)); } catch (const MyMoneyException &e) { unexpectedException(e); } m->setDirty(); try { ch = m->account("A000006"); QVERIFY(ch.value("Key") == "Value"); m->addTransaction(t1); QVERIFY(t1.id() == "T000000000000000001"); QVERIFY(t1.splitCount() == 2); QVERIFY(m->transactionCount() == 1); ch = m->account("A000006"); QVERIFY(ch.value("Key") == "Value"); } catch (const MyMoneyException &e) { unexpectedException(e); } try { // I spent some money, not so great s.setId(QString()); // enable re-usage of split variable s.setAccountId("A000004"); // Grosseries s.setShares(MyMoneyMoney(10000, 100)); s.setValue(MyMoneyMoney(10000, 100)); QVERIFY(s.id().isEmpty()); t2.addSplit(s); s.setId(QString()); // enable re-usage of split variable s.setAccountId("A000002"); // 16% sales tax s.setShares(MyMoneyMoney(1200, 100)); s.setValue(MyMoneyMoney(1200, 100)); QVERIFY(s.id().isEmpty()); t2.addSplit(s); s.setId(QString()); // enable re-usage of split variable s.setAccountId("A000003"); // 7% sales tax s.setShares(MyMoneyMoney(400, 100)); s.setValue(MyMoneyMoney(400, 100)); QVERIFY(s.id().isEmpty()); t2.addSplit(s); s.setId(QString()); // enable re-usage of split variable s.setAccountId("A000006"); // Checkings account s.setShares(MyMoneyMoney(-11600, 100)); s.setValue(MyMoneyMoney(-11600, 100)); QVERIFY(s.id().isEmpty()); t2.addSplit(s); t2.setPostDate(QDate(2002, 5, 9)); } catch (const MyMoneyException &e) { unexpectedException(e); } m->setDirty(); try { m->addTransaction(t2); QVERIFY(t2.id() == "T000000000000000002"); QVERIFY(t2.splitCount() == 4); QVERIFY(m->transactionCount() == 2); //QMap::ConstIterator it_k; MyMoneyTransactionFilter f; QList transactionList(m->transactionList(f)); QList::ConstIterator it_t(transactionList.constBegin()); QCOMPARE((*it_t).id(), QLatin1String("T000000000000000002")); ++it_t; QCOMPARE((*it_t).id(), QLatin1String("T000000000000000001")); ++it_t; QCOMPARE(it_t, transactionList.constEnd()); ch = m->account("A000006"); QCOMPARE(ch.value("Key"), QLatin1String("Value")); // check that the account's transaction list is updated QList list; MyMoneyTransactionFilter filter("A000006"); list = m->transactionList(filter); QCOMPARE(list.size(), 2); QList::ConstIterator it; it = list.constBegin(); //QVERIFY((*it).id() == "T000000000000000002"); QCOMPARE((*it), t2); ++it; QCOMPARE((*it), t1); ++it; QCOMPARE(it, list.constEnd()); } catch (const MyMoneyException &e) { unexpectedException(e); } } void MyMoneyDatabaseMgrTest::testTransactionCount() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); testAddTransactions(); QCOMPARE(m->transactionCount("A000001"), 0u); QCOMPARE(m->transactionCount("A000002"), 1u); QCOMPARE(m->transactionCount("A000003"), 1u); QCOMPARE(m->transactionCount("A000004"), 1u); QCOMPARE(m->transactionCount("A000005"), 1u); QCOMPARE(m->transactionCount("A000006"), 2u); } void MyMoneyDatabaseMgrTest::testAddBudget() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); MyMoneyBudget budget; budget.setName("TestBudget"); budget.setBudgetStart(QDate::currentDate()); m->addBudget(budget); QCOMPARE(m->budgetList().count(), 1); QCOMPARE(m->budgetId(), 1ul); MyMoneyBudget newBudget = m->budgetByName("TestBudget"); QCOMPARE(budget.budgetStart(), newBudget.budgetStart()); QCOMPARE(budget.name(), newBudget.name()); } void MyMoneyDatabaseMgrTest::testCopyBudget() { testAddBudget(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); try { MyMoneyBudget oldBudget = m->budgetByName("TestBudget"); MyMoneyBudget newBudget = oldBudget; newBudget.clearId(); newBudget.setName(QString("Copy of %1").arg(oldBudget.name())); m->addBudget(newBudget); QCOMPARE(m->budgetList().count(), 2); QCOMPARE(m->budgetId(), 2ul); MyMoneyBudget testBudget = m->budgetByName("TestBudget"); QCOMPARE(oldBudget.budgetStart(), testBudget.budgetStart()); QCOMPARE(oldBudget.name(), testBudget.name()); testBudget = m->budgetByName("Copy of TestBudget"); QCOMPARE(testBudget.budgetStart(), newBudget.budgetStart()); QCOMPARE(testBudget.name(), newBudget.name()); } catch (QString& s) { QFAIL(qPrintable(QString("Error in testCopyBudget(): %1").arg(qPrintable(s)))); } } void MyMoneyDatabaseMgrTest::testModifyBudget() { testAddBudget(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); MyMoneyBudget budget = m->budgetByName("TestBudget"); budget.setBudgetStart(QDate::currentDate().addDays(-1)); m->modifyBudget(budget); MyMoneyBudget newBudget = m->budgetByName("TestBudget"); QCOMPARE(budget.id(), newBudget.id()); QCOMPARE(budget.budgetStart(), newBudget.budgetStart()); QCOMPARE(budget.name(), newBudget.name()); } void MyMoneyDatabaseMgrTest::testRemoveBudget() { testAddBudget(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); MyMoneyBudget budget = m->budgetByName("TestBudget"); m->removeBudget(budget); try { budget = m->budgetByName("TestBudget"); // exception should be thrown if budget not found. QFAIL("Missing expected exception."); } catch (const MyMoneyException &) { QVERIFY(true); } } void MyMoneyDatabaseMgrTest::testBalance() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); testAddTransactions(); try { QVERIFY(m->balance("A000001", QDate()).isZero()); QCOMPARE(m->balance("A000002", QDate()), MyMoneyMoney(1200, 100)); QCOMPARE(m->balance("A000003", QDate()), MyMoneyMoney(400, 100)); //Add a transaction to zero account A000003 MyMoneyTransaction t1; MyMoneySplit s; s.setAccountId("A000003"); s.setShares(MyMoneyMoney(-400, 100)); s.setValue(MyMoneyMoney(-400, 100)); QVERIFY(s.id().isEmpty()); t1.addSplit(s); s.setId(QString()); // enable re-usage of split variable s.setAccountId("A000002"); s.setShares(MyMoneyMoney(400, 100)); s.setValue(MyMoneyMoney(400, 100)); QVERIFY(s.id().isEmpty()); t1.addSplit(s); t1.setPostDate(QDate(2007, 5, 10)); m->addTransaction(t1); QVERIFY(m->balance("A000003", QDate()).isZero()); QCOMPARE(m->totalBalance("A000001", QDate()), MyMoneyMoney(1600, 100)); QCOMPARE(m->balance("A000006", QDate(2002, 5, 9)), MyMoneyMoney(-11600, 100)); QCOMPARE(m->balance("A000005", QDate(2002, 5, 10)), MyMoneyMoney(-100000, 100)); QCOMPARE(m->balance("A000006", QDate(2002, 5, 10)), MyMoneyMoney(88400, 100)); } catch (const MyMoneyException &e) { unexpectedException(e); } } void MyMoneyDatabaseMgrTest::testModifyTransaction() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); testAddTransactions(); MyMoneyTransaction t = m->transaction("T000000000000000002"); MyMoneySplit s; MyMoneyAccount ch; // just modify simple stuff (splits) QVERIFY(t.splitCount() == 4); ch = m->account("A000006"); QVERIFY(ch.value("Key") == "Value"); s = t.splits()[0]; s.setShares(MyMoneyMoney(11000, 100)); s.setValue(MyMoneyMoney(11000, 100)); t.modifySplit(s); QVERIFY(t.splitCount() == 4); s = t.splits()[3]; s.setShares(MyMoneyMoney(-12600, 100)); s.setValue(MyMoneyMoney(-12600, 100)); t.modifySplit(s); ch = m->account("A000006"); QVERIFY(ch.value("Key") == "Value"); try { QVERIFY(m->balance("A000004", QDate()) == MyMoneyMoney(10000, 100)); QVERIFY(m->balance("A000006", QDate()) == MyMoneyMoney(100000 - 11600, 100)); QVERIFY(m->totalBalance("A000001", QDate()) == MyMoneyMoney(1600, 100)); m->modifyTransaction(t); ch = m->account("A000006"); QVERIFY(ch.value("Key") == "Value"); QVERIFY(m->balance("A000004", QDate()) == MyMoneyMoney(11000, 100)); QVERIFY(m->balance("A000006", QDate()) == MyMoneyMoney(100000 - 12600, 100)); QVERIFY(m->totalBalance("A000001", QDate()) == MyMoneyMoney(1600, 100)); } catch (const MyMoneyException &e) { unexpectedException(e); } // now modify the date t.setPostDate(QDate(2002, 5, 11)); try { ch = m->account("A000006"); QVERIFY(ch.value("Key") == "Value"); m->modifyTransaction(t); QVERIFY(m->balance("A000004", QDate()) == MyMoneyMoney(11000, 100)); QVERIFY(m->balance("A000006", QDate()) == MyMoneyMoney(100000 - 12600, 100)); QVERIFY(m->totalBalance("A000001", QDate()) == MyMoneyMoney(1600, 100)); //QMap::ConstIterator it_k; MyMoneyTransactionFilter f; QList transactionList(m->transactionList(f)); QList::ConstIterator it_t(transactionList.constBegin()); //it_k = m->m_transactionKeys.begin(); //QVERIFY((*it_k) == "2002-05-10-T000000000000000001"); QVERIFY((*it_t).id() == "T000000000000000001"); //++it_k; ++it_t; //QVERIFY((*it_k) == "2002-05-11-T000000000000000002"); QVERIFY((*it_t).id() == "T000000000000000002"); //++it_k; ++it_t; //QVERIFY(it_k == m->m_transactionKeys.end()); QVERIFY(it_t == transactionList.constEnd()); ch = m->account("A000006"); QVERIFY(ch.value("Key") == "Value"); // check that the account's transaction list is updated QList list; MyMoneyTransactionFilter filter("A000006"); list = m->transactionList(filter); QVERIFY(list.size() == 2); QList::ConstIterator it; it = list.constBegin(); QVERIFY((*it).id() == "T000000000000000001"); ++it; QVERIFY((*it).id() == "T000000000000000002"); ++it; QVERIFY(it == list.constEnd()); } catch (const MyMoneyException &e) { unexpectedException(e); } // Create another transaction MyMoneyTransaction t1; try { s.setId(QString()); // enable re-usage of split variable s.setAccountId("A000006"); // Checkings s.setShares(MyMoneyMoney(10000, 100)); s.setValue(MyMoneyMoney(10000, 100)); QVERIFY(s.id().isEmpty()); t1.addSplit(s); s.setId(QString()); // enable re-usage of split variable s.setAccountId("A000005"); // Salary s.setShares(MyMoneyMoney(-10000, 100)); s.setValue(MyMoneyMoney(-10000, 100)); QVERIFY(s.id().isEmpty()); t1.addSplit(s); t1.setPostDate(QDate(2002, 5, 10)); } catch (const MyMoneyException &e) { unexpectedException(e); } // Add it to the database m->addTransaction(t1); ch = m->account("A000005"); QVERIFY(ch.balance() == MyMoneyMoney(-100000 - 10000, 100)); QVERIFY(m->balance("A000005", QDate()) == MyMoneyMoney(-100000 - 10000, 100)); ch = m->account("A000006"); QVERIFY(ch.balance() == MyMoneyMoney(100000 - 12600 + 10000, 100)); QVERIFY(m->balance("A000006", QDate()) == MyMoneyMoney(100000 - 12600 + 10000, 100)); // Oops, the income was classified as Salary, but should have been // a refund from the grocery store. t1.splits()[1].setAccountId("A000004"); m->modifyTransaction(t1); // Make sure the account balances got updated correctly. ch = m->account("A000004"); QVERIFY(ch.balance() == MyMoneyMoney(11000 - 10000, 100)); QVERIFY(m->balance("A000004", QDate()) == MyMoneyMoney(11000 - 10000, 100)); ch = m->account("A000005"); QVERIFY(m->balance("A000005", QDate()) == MyMoneyMoney(-100000, 100)); QVERIFY(ch.balance() == MyMoneyMoney(-100000, 100)); ch = m->account("A000006"); QVERIFY(ch.balance() == MyMoneyMoney(100000 - 12600 + 10000, 100)); QVERIFY(m->balance("A000006", QDate()) == MyMoneyMoney(100000 - 12600 + 10000, 100)); } void MyMoneyDatabaseMgrTest::testRemoveUnusedAccount() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); testAccount2Institution(); MyMoneyAccount a = m->account("A000001"); MyMoneyInstitution i = m->institution("I000001"); m->setDirty(); // make sure, we cannot remove the standard account groups try { m->removeAccount(m->liability()); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } try { m->removeAccount(m->asset()); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } try { m->removeAccount(m->expense()); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } try { m->removeAccount(m->income()); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } // try to remove the account still attached to the institution try { m->removeAccount(a); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } // now really remove an account try { MyMoneyFile::instance()->preloadCache(); i = m->institution("I000001"); //QVERIFY(i.accountCount() == 0); QVERIFY(i.accountCount() == 1); QVERIFY(m->accountCount() == 7); a.setInstitutionId(QString()); m->modifyAccount(a); m->removeAccount(a); QVERIFY(m->accountCount() == 6); i = m->institution("I000001"); QVERIFY(i.accountCount() == 0); } catch (const MyMoneyException &e) { unexpectedException(e); } } void MyMoneyDatabaseMgrTest::testRemoveUsedAccount() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); testAddTransactions(); MyMoneyAccount a = m->account("A000006"); try { m->removeAccount(a); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } } void MyMoneyDatabaseMgrTest::testRemoveInstitution() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); testModifyInstitution(); testReparentAccount(); MyMoneyInstitution i; MyMoneyAccount a; // assign the checkings account to the institution try { i = m->institution("I000001"); a = m->account("A000006"); a.setInstitutionId(i.id()); m->modifyAccount(a); QVERIFY(i.accountCount() == 0); } catch (const MyMoneyException &e) { unexpectedException(e); } m->setDirty(); // now remove the institution and see if the account survived ;-) try { m->removeInstitution(i); a.setInstitutionId(QString()); m->modifyAccount(a); a = m->account("A000006"); QVERIFY(a.institutionId().isEmpty()); QVERIFY(m->institutionCount() == 0); } catch (const MyMoneyException &e) { unexpectedException(e); } } void MyMoneyDatabaseMgrTest::testRemoveTransaction() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); testAddTransactions(); MyMoneyTransaction t = m->transaction("T000000000000000002"); m->setDirty(); try { m->removeTransaction(t); QVERIFY(m->transactionCount() == 1); } catch (const MyMoneyException &e) { unexpectedException(e); } } void MyMoneyDatabaseMgrTest::testTransactionList() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); testAddTransactions(); QList list; MyMoneyTransactionFilter filter("A000006"); list = m->transactionList(filter); QVERIFY(list.count() == 2); QVERIFY(list.at(0).id() == "T000000000000000002"); QVERIFY(list.at(1).id() == "T000000000000000001"); filter.clear(); filter.addAccount(QString("A000003")); list = m->transactionList(filter); QVERIFY(list.count() == 1); QVERIFY(list.at(0).id() == "T000000000000000002"); filter.clear(); list = m->transactionList(filter); QVERIFY(list.count() == 2); QVERIFY(list.at(0).id() == "T000000000000000002"); QVERIFY(list.at(1).id() == "T000000000000000001"); // test the date filtering while split filtering is active but with an empty filter filter.clear(); filter.addPayee(QString()); filter.setDateFilter(QDate(2002, 5, 10), QDate(2002, 5, 10)); list = m->transactionList(filter); QVERIFY(list.count() == 1); QVERIFY(list.at(0).id() == "T000000000000000001"); filter.clear(); filter.addAccount(QString()); filter.setDateFilter(QDate(2002, 5, 9), QDate(2002, 5, 9)); list = m->transactionList(filter); QVERIFY(list.count() == 1); QVERIFY(list.at(0).id() == "T000000000000000002"); } void MyMoneyDatabaseMgrTest::testAddPayee() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); MyMoneyPayee p; p.setName("THB"); m->setDirty(); try { QVERIFY(m->payeeId() == 0); m->addPayee(p); QVERIFY(m->payeeId() == 1); MyMoneyPayee p1 = m->payeeByName("THB"); QVERIFY(p.id() == p1.id()); QVERIFY(p.name() == p1.name()); QVERIFY(p.address() == p1.address()); QVERIFY(p.city() == p1.city()); QVERIFY(p.state() == p1.state()); QVERIFY(p.postcode() == p1.postcode()); QVERIFY(p.telephone() == p1.telephone()); QVERIFY(p.email() == p1.email()); MyMoneyPayee::payeeMatchType m, m1; bool ignore, ignore1; QStringList keys, keys1; m = p.matchData(ignore, keys); m1 = p1.matchData(ignore1, keys1); QVERIFY(m == m1); QVERIFY(ignore == ignore1); QVERIFY(keys == keys1); QVERIFY(p.reference() == p1.reference()); QVERIFY(p.defaultAccountEnabled() == p1.defaultAccountEnabled()); QVERIFY(p.defaultAccountId() == p1.defaultAccountId()); QVERIFY(p == p1); } catch (const MyMoneyException &e) { unexpectedException(e); } } void MyMoneyDatabaseMgrTest::testSetAccountName() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); try { m->setAccountName(STD_ACC_LIABILITY, "Verbindlichkeiten"); } catch (const MyMoneyException &e) { unexpectedException(e); } try { m->setAccountName(STD_ACC_ASSET, "Verm�gen"); } catch (const MyMoneyException &e) { unexpectedException(e); } try { m->setAccountName(STD_ACC_EXPENSE, "Ausgaben"); } catch (const MyMoneyException &e) { unexpectedException(e); } try { m->setAccountName(STD_ACC_INCOME, "Einnahmen"); } catch (const MyMoneyException &e) { unexpectedException(e); } MyMoneyFile::instance()->preloadCache(); try { QVERIFY(m->liability().name() == "Verbindlichkeiten"); QVERIFY(m->asset().name() == "Verm�gen"); QVERIFY(m->expense().name() == "Ausgaben"); QVERIFY(m->income().name() == "Einnahmen"); } catch (const MyMoneyException &e) { unexpectedException(e); } try { m->setAccountName("A000001", "New account name"); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } } void MyMoneyDatabaseMgrTest::testModifyPayee() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); MyMoneyPayee p; testAddPayee(); p = m->payee("P000001"); p.setName("New name"); m->setDirty(); try { m->modifyPayee(p); p = m->payee("P000001"); QVERIFY(p.name() == "New name"); } catch (const MyMoneyException &e) { unexpectedException(e); } } void MyMoneyDatabaseMgrTest::testRemovePayee() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); testAddPayee(); m->setDirty(); // check that we can remove an unreferenced payee MyMoneyPayee p = m->payee("P000001"); try { QVERIFY(m->payeeList().count() == 1); m->removePayee(p); QVERIFY(m->payeeList().count() == 0); } catch (const MyMoneyException &e) { unexpectedException(e); } // add transaction testAddTransactions(); MyMoneyTransaction tr = m->transaction("T000000000000000001"); MyMoneySplit sp; sp = tr.splits()[0]; sp.setPayeeId("P000001"); tr.modifySplit(sp); // check that we cannot add a transaction referencing // an unknown payee try { m->modifyTransaction(tr); QFAIL("Expected exception"); } catch (const MyMoneyException &) { } // reset here, so that the // testAddPayee will not fail m->loadPayeeId(0); testAddPayee(); // check that it works when the payee exists try { m->modifyTransaction(tr); } catch (const MyMoneyException &e) { unexpectedException(e); } m->setDirty(); // now check, that we cannot remove the payee try { m->removePayee(p); QFAIL("Expected exception"); } catch (const MyMoneyException &) { } QVERIFY(m->payeeList().count() == 1); } void MyMoneyDatabaseMgrTest::testAddTag() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); MyMoneyTag ta; ta.setName("THB"); m->setDirty(); try { QVERIFY(m->tagId() == 0); m->addTag(ta); QVERIFY(m->tagId() == 1); MyMoneyTag ta1 = m->tagByName("THB"); QVERIFY(ta.id() == ta1.id()); QVERIFY(ta.name() == ta1.name()); QVERIFY(ta.isClosed() == ta1.isClosed()); QVERIFY(ta.tagColor().name() == ta1.tagColor().name()); QVERIFY(ta.notes() == ta1.notes()); QVERIFY(ta == ta1); } catch (const MyMoneyException &e) { unexpectedException(e); } } void MyMoneyDatabaseMgrTest::testModifyTag() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); MyMoneyTag ta; testAddTag(); ta = m->tag("G000001"); ta.setName("New name"); m->setDirty(); try { m->modifyTag(ta); ta = m->tag("G000001"); QVERIFY(ta.name() == "New name"); } catch (const MyMoneyException &e) { unexpectedException(e); } } void MyMoneyDatabaseMgrTest::testRemoveTag() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); testAddTag(); m->setDirty(); // check that we can remove an unreferenced tag MyMoneyTag ta = m->tag("G000001"); try { QVERIFY(m->tagList().count() == 1); m->removeTag(ta); QVERIFY(m->tagList().count() == 0); } catch (const MyMoneyException &e) { unexpectedException(e); } // add transaction testAddTransactions(); MyMoneyTransaction tr = m->transaction("T000000000000000001"); MyMoneySplit sp; sp = tr.splits()[0]; QList tagIdList; tagIdList << "G000001"; sp.setTagIdList(tagIdList); tr.modifySplit(sp); // check that we cannot add a transaction referencing // an unknown tag try { m->modifyTransaction(tr); QFAIL("Expected exception"); } catch (const MyMoneyException &) { } // reset here, so that the // testAddTag will not fail m->loadTagId(0); testAddTag(); // check that it works when the tag exists try { m->modifyTransaction(tr); } catch (const MyMoneyException &e) { unexpectedException(e); } m->setDirty(); // now check, that we cannot remove the tag try { m->removeTag(ta); QFAIL("Expected exception"); } catch (const MyMoneyException &) { } QVERIFY(m->tagList().count() == 1); } void MyMoneyDatabaseMgrTest::testRemoveAccountFromTree() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); MyMoneyAccount a, b, c; a.setName("Acc A"); b.setName("Acc B"); c.setName("Acc C"); // build a tree A -> B -> C, remove B and see if A -> C // remains in the storage manager try { m->addAccount(a); m->addAccount(b); m->addAccount(c); m->reparentAccount(b, a); m->reparentAccount(c, b); QVERIFY(a.accountList().count() == 1); QVERIFY(m->account(a.accountList()[0]).name() == "Acc B"); QVERIFY(b.accountList().count() == 1); QVERIFY(m->account(b.accountList()[0]).name() == "Acc C"); QVERIFY(c.accountList().count() == 0); m->removeAccount(b); // reload account info from titutionIDtorage a = m->account(a.id()); c = m->account(c.id()); try { b = m->account(b.id()); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } QVERIFY(a.accountList().count() == 1); QVERIFY(m->account(a.accountList()[0]).name() == "Acc C"); QVERIFY(c.accountList().count() == 0); } catch (const MyMoneyException &e) { unexpectedException(e); } } void MyMoneyDatabaseMgrTest::testPayeeName() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); testAddPayee(); MyMoneyPayee p; QString name("THB"); // OK case try { p = m->payeeByName(name); QVERIFY(p.name() == "THB"); QVERIFY(p.id() == "P000001"); } catch (const MyMoneyException &e) { unexpectedException(e); } // Not OK case name = "Thb"; try { p = m->payeeByName(name); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } } void MyMoneyDatabaseMgrTest::testTagName() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); testAddTag(); MyMoneyTag ta; QString name("THB"); // OK case try { ta = m->tagByName(name); QVERIFY(ta.name() == "THB"); QVERIFY(ta.id() == "G000001"); } catch (const MyMoneyException &e) { unexpectedException(e); } // Not OK case name = "Thb"; try { ta = m->tagByName(name); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } } void MyMoneyDatabaseMgrTest::testAssignment() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); testAddTransactions(); MyMoneyPayee user; user.setName("Thomas"); m->setUser(user); MyMoneyDatabaseMgr test = *m; testEquality(&test); } void MyMoneyDatabaseMgrTest::testEquality(const MyMoneyDatabaseMgr *t) { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); QVERIFY(m->user().name() == t->user().name()); QVERIFY(m->user().address() == t->user().address()); QVERIFY(m->user().city() == t->user().city()); QVERIFY(m->user().state() == t->user().state()); QVERIFY(m->user().postcode() == t->user().postcode()); QVERIFY(m->user().telephone() == t->user().telephone()); QVERIFY(m->user().email() == t->user().email()); //QVERIFY(m->nextInstitutionID() == t->nextInstitutionID()); //QVERIFY(m->nextAccountID() == t->nextAccountID()); //QVERIFY(m->m_nextTransactionID == t->m_nextTransactionID); //QVERIFY(m->nextPayeeID() == t->nextPayeeID()); //QVERIFY(m->m_nextScheduleID == t->m_nextScheduleID); QVERIFY(m->dirty() == t->dirty()); QVERIFY(m->m_creationDate == t->m_creationDate); QVERIFY(m->m_lastModificationDate == t->m_lastModificationDate); /* * make sure, that the keys and values are the same * on the left and the right side */ //QVERIFY(m->payeeList().keys() == t->payeeList().keys()); //QVERIFY(m->payeeList().values() == t->payeeList().values()); QVERIFY(m->payeeList() == t->payeeList()); QVERIFY(m->tagList() == t->tagList()); //QVERIFY(m->m_transactionKeys.keys() == t->m_transactionKeys.keys()); //QVERIFY(m->m_transactionKeys.values() == t->m_transactionKeys.values()); //QVERIFY(m->institutionList().keys() == t->institutionList().keys()); //QVERIFY(m->institutionList().values() == t->institutionList().values()); //QVERIFY(m->m_accountList.keys() == t->m_accountList.keys()); //QVERIFY(m->m_accountList.values() == t->m_accountList.values()); //QVERIFY(m->m_transactionList.keys() == t->m_transactionList.keys()); //QVERIFY(m->m_transactionList.values() == t->m_transactionList.values()); //QVERIFY(m->m_balanceCache.keys() == t->m_balanceCache.keys()); //QVERIFY(m->m_balanceCache.values() == t->m_balanceCache.values()); // QVERIFY(m->scheduleList().keys() == t->scheduleList().keys()); // QVERIFY(m->scheduleList().values() == t->scheduleList().values()); } void MyMoneyDatabaseMgrTest::testDuplicate() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); const MyMoneyDatabaseMgr* t; testModifyTransaction(); t = m->duplicate(); testEquality(t); delete t; } void MyMoneyDatabaseMgrTest::testAddSchedule() { /* Note addSchedule() now calls validate as it should * so we need an account id. Later this will * be checked to make sure its a valid account id. The * tests currently fail because no splits are defined * for the schedules transaction. */ testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); // put some accounts in the db, so the tests don't break testReparentAccount(); try { QVERIFY(m->scheduleList().count() == 0); MyMoneyTransaction t1; MyMoneySplit s1, s2; s1.setAccountId("A000001"); t1.addSplit(s1); s2.setAccountId("A000002"); t1.addSplit(s2); MyMoneySchedule schedule("Sched-Name", Schedule::Type::Deposit, Schedule::Occurrence::Daily, 1, Schedule::PaymentType::ManualDeposit, QDate(), QDate(), true, false); t1.setPostDate(QDate(2003, 7, 10)); schedule.setTransaction(t1); m->addSchedule(schedule); QVERIFY(m->scheduleList().count() == 1); QVERIFY(schedule.id() == "SCH000001"); //MyMoneyFile::instance()->clearCache(); // test passes without this, so why is it here for? QVERIFY(m->schedule("SCH000001").id() == "SCH000001"); } catch (const MyMoneyException &e) { unexpectedException(e); } try { MyMoneySchedule schedule("Sched-Name", Schedule::Type::Deposit, Schedule::Occurrence::Daily, 1, Schedule::PaymentType::ManualDeposit, QDate(), QDate(), true, false); m->addSchedule(schedule); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } QVERIFY(m->scheduleList().count() == 1); // now try with a bad account, so this should cause an exception try { MyMoneyTransaction t1; MyMoneySplit s1, s2; s1.setAccountId("Abadaccount1"); t1.addSplit(s1); s2.setAccountId("Abadaccount2"); //t1.addSplit(s2); MyMoneySchedule schedule("Sched-Name", Schedule::Type::Deposit, Schedule::Occurrence::Daily, 1, Schedule::PaymentType::ManualDeposit, QDate(), QDate(), true, false); t1.setPostDate(QDate(2003, 7, 10)); schedule.setTransaction(t1); m->addSchedule(schedule); QFAIL("Exception expected, but not thrown"); } catch (const MyMoneyException &) { // Exception caught as expected. } QVERIFY(m->scheduleList().count() == 1); } void MyMoneyDatabaseMgrTest::testSchedule() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); testAddSchedule(); MyMoneySchedule sched; sched = m->schedule("SCH000001"); QVERIFY(sched.name() == "Sched-Name"); QVERIFY(sched.id() == "SCH000001"); try { m->schedule("SCH000002"); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } } void MyMoneyDatabaseMgrTest::testModifySchedule() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); testAddSchedule(); MyMoneySchedule sched; sched = m->schedule("SCH000001"); sched.setId("SCH000002"); try { m->modifySchedule(sched); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } sched = m->schedule("SCH000001"); sched.setName("New Sched-Name"); try { m->modifySchedule(sched); QVERIFY(m->scheduleList().count() == 1); QVERIFY((*(m->scheduleList().begin())).name() == "New Sched-Name"); QVERIFY((*(m->scheduleList().begin())).id() == "SCH000001"); } catch (const MyMoneyException &e) { unexpectedException(e); } } void MyMoneyDatabaseMgrTest::testRemoveSchedule() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); testAddSchedule(); MyMoneySchedule sched; sched = m->schedule("SCH000001"); sched.setId("SCH000002"); try { m->removeSchedule(sched); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } sched = m->schedule("SCH000001"); try { m->removeSchedule(sched); QVERIFY(m->scheduleList().count() == 0); } catch (const MyMoneyException &e) { unexpectedException(e); } } void MyMoneyDatabaseMgrTest::testScheduleList() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); // put some accounts in the db, so the tests don't break testReparentAccount(); QDate testDate = QDate::currentDate(); QDate notOverdue = testDate.addDays(2); QDate overdue = testDate.addDays(-2); MyMoneyTransaction t1; MyMoneySplit s1, s2; s1.setAccountId("A000001"); t1.addSplit(s1); s2.setAccountId("A000002"); t1.addSplit(s2); MyMoneySchedule schedule1("Schedule 1", Schedule::Type::Bill, Schedule::Occurrence::Once, 1, Schedule::PaymentType::DirectDebit, QDate(), QDate(), false, false); t1.setPostDate(notOverdue); schedule1.setTransaction(t1); schedule1.setLastPayment(notOverdue); MyMoneyTransaction t2; MyMoneySplit s3, s4; s3.setAccountId("A000001"); t2.addSplit(s3); s4.setAccountId("A000003"); t2.addSplit(s4); MyMoneySchedule schedule2("Schedule 2", Schedule::Type::Deposit, Schedule::Occurrence::Daily, 1, Schedule::PaymentType::DirectDeposit, QDate(), QDate(), false, false); t2.setPostDate(notOverdue.addDays(1)); schedule2.setTransaction(t2); schedule2.setLastPayment(notOverdue.addDays(1)); MyMoneyTransaction t3; MyMoneySplit s5, s6; s5.setAccountId("A000005"); t3.addSplit(s5); s6.setAccountId("A000006"); t3.addSplit(s6); MyMoneySchedule schedule3("Schedule 3", Schedule::Type::Transfer, Schedule::Occurrence::Weekly, 1, Schedule::PaymentType::Other, QDate(), QDate(), false, false); t3.setPostDate(notOverdue.addDays(2)); schedule3.setTransaction(t3); schedule3.setLastPayment(notOverdue.addDays(2)); MyMoneyTransaction t4; MyMoneySplit s7, s8; s7.setAccountId("A000005"); t4.addSplit(s7); s8.setAccountId("A000006"); t4.addSplit(s8); MyMoneySchedule schedule4("Schedule 4", Schedule::Type::Bill, Schedule::Occurrence::Weekly, 1, Schedule::PaymentType::WriteChecque, QDate(), notOverdue.addDays(31), false, false); t4.setPostDate(overdue.addDays(-7)); schedule4.setTransaction(t4); try { m->addSchedule(schedule1); m->addSchedule(schedule2); m->addSchedule(schedule3); m->addSchedule(schedule4); } catch (const MyMoneyException &e) { unexpectedException(e); } QList list; // no filter list = m->scheduleList(); QVERIFY(list.count() == 4); // filter by type list = m->scheduleList(QString(), Schedule::Type::Bill); QVERIFY(list.count() == 2); QVERIFY(list[0].name() == "Schedule 1"); QVERIFY(list[1].name() == "Schedule 4"); // filter by occurrence list = m->scheduleList(QString(), Schedule::Type::Any, Schedule::Occurrence::Daily); QVERIFY(list.count() == 1); QVERIFY(list[0].name() == "Schedule 2"); // filter by payment type list = m->scheduleList(QString(), Schedule::Type::Any, Schedule::Occurrence::Any, Schedule::PaymentType::DirectDeposit); QVERIFY(list.count() == 1); QVERIFY(list[0].name() == "Schedule 2"); // filter by account list = m->scheduleList("A01"); QVERIFY(list.count() == 0); list = m->scheduleList("A000001"); QVERIFY(list.count() == 2); list = m->scheduleList("A000002"); QVERIFY(list.count() == 1); // filter by start date list = m->scheduleList(QString(), Schedule::Type::Any, Schedule::Occurrence::Any, Schedule::PaymentType::Any, notOverdue.addDays(31), QDate(), false); QVERIFY(list.count() == 3); QVERIFY(list[0].name() == "Schedule 2"); QVERIFY(list[1].name() == "Schedule 3"); QVERIFY(list[2].name() == "Schedule 4"); // filter by end date list = m->scheduleList(QString(), Schedule::Type::Any, Schedule::Occurrence::Any, Schedule::PaymentType::Any, QDate(), notOverdue.addDays(1), false); QVERIFY(list.count() == 3); QVERIFY(list[0].name() == "Schedule 1"); QVERIFY(list[1].name() == "Schedule 2"); QVERIFY(list[2].name() == "Schedule 4"); // filter by start and end date list = m->scheduleList(QString(), Schedule::Type::Any, Schedule::Occurrence::Any, Schedule::PaymentType::Any, notOverdue.addDays(-1), notOverdue.addDays(1), false); QVERIFY(list.count() == 2); QVERIFY(list[0].name() == "Schedule 1"); QVERIFY(list[1].name() == "Schedule 2"); // filter by overdue status list = m->scheduleList(QString(), Schedule::Type::Any, Schedule::Occurrence::Any, Schedule::PaymentType::Any, QDate(), QDate(), true); QVERIFY(list.count() == 1); QVERIFY(list[0].name() == "Schedule 4"); } void MyMoneyDatabaseMgrTest::testAddCurrency() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); MyMoneySecurity curr("EUR", "Euro", "?", 100, 100); QVERIFY(m->currencyList().count() == 0); m->setDirty(); try { m->addCurrency(curr); QVERIFY(m->currencyList().count() == 1); QVERIFY((*(m->currencyList().begin())).name() == "Euro"); QVERIFY((*(m->currencyList().begin())).id() == "EUR"); } catch (const MyMoneyException &e) { unexpectedException(e); } m->setDirty(); try { m->addCurrency(curr); QFAIL("Expected exception missing"); } catch (const MyMoneyException &) { QVERIFY(m->dirty() == false); } } void MyMoneyDatabaseMgrTest::testModifyCurrency() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); MyMoneySecurity curr("EUR", "Euro", "?", 100, 100); testAddCurrency(); m->setDirty(); curr.setName("EURO"); try { m->modifyCurrency(curr); QVERIFY(m->currencyList().count() == 1); QVERIFY((*(m->currencyList().begin())).name() == "EURO"); QVERIFY((*(m->currencyList().begin())).id() == "EUR"); } catch (const MyMoneyException &e) { unexpectedException(e); } m->setDirty(); MyMoneySecurity unknownCurr("DEM", "Deutsche Mark", "DM", 100, 100); try { m->modifyCurrency(unknownCurr); QFAIL("Expected exception missing"); } catch (const MyMoneyException &) { QVERIFY(m->dirty() == false); } } void MyMoneyDatabaseMgrTest::testRemoveCurrency() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); MyMoneySecurity curr("EUR", "Euro", "?", 100, 100); testAddCurrency(); m->setDirty(); try { m->removeCurrency(curr); QVERIFY(m->currencyList().count() == 0); } catch (const MyMoneyException &e) { unexpectedException(e); } m->setDirty(); MyMoneySecurity unknownCurr("DEM", "Deutsche Mark", "DM", 100, 100); try { m->removeCurrency(unknownCurr); QFAIL("Expected exception missing"); } catch (const MyMoneyException &) { QVERIFY(m->dirty() == false); } } void MyMoneyDatabaseMgrTest::testCurrency() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); MyMoneySecurity curr("EUR", "Euro", "?", 100, 100); MyMoneySecurity newCurr; testAddCurrency(); m->setDirty(); try { newCurr = m->currency("EUR"); QVERIFY(m->dirty() == false); QVERIFY(newCurr.id() == curr.id()); QVERIFY(newCurr.name() == curr.name()); } catch (const MyMoneyException &e) { unexpectedException(e); } try { m->currency("DEM"); QFAIL("Expected exception missing"); } catch (const MyMoneyException &) { QVERIFY(m->dirty() == false); } } void MyMoneyDatabaseMgrTest::testCurrencyList() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); QVERIFY(m->currencyList().count() == 0); testAddCurrency(); QVERIFY(m->currencyList().count() == 1); MyMoneySecurity unknownCurr("DEM", "Deutsche Mark", "DM", 100, 100); try { m->addCurrency(unknownCurr); m->setDirty(); QVERIFY(m->currencyList().count() == 2); QVERIFY(m->currencyList().count() == 2); QVERIFY(m->dirty() == false); } catch (const MyMoneyException &e) { unexpectedException(e); } } void MyMoneyDatabaseMgrTest::testAccountList() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); QList accounts; m->accountList(accounts); QVERIFY(accounts.count() == 0); testAddNewAccount(); accounts.clear(); m->accountList(accounts); QVERIFY(accounts.count() == 2); MyMoneyAccount a = m->account("A000001"); MyMoneyAccount b = m->account("A000002"); m->reparentAccount(b, a); accounts.clear(); m->accountList(accounts); QVERIFY(accounts.count() == 2); } void MyMoneyDatabaseMgrTest::testAddOnlineJob() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); // Add a onlineJob onlineJob job(new dummyTask()); QCOMPARE(m->onlineJobList().count(), 0); m->setDirty(); QSKIP("Test not fully implemented, yet.", SkipAll); try { m->addOnlineJob(job); QCOMPARE(m->onlineJobList().count(), 1); QCOMPARE((*(m->onlineJobList().begin())).id(), QLatin1String("O00000001")); } catch (const MyMoneyException &e) { unexpectedException(e); } // Try to re-add the same job. It should fail. m->setDirty(); try { m->addOnlineJob(job); QFAIL("Expected exception missing"); } catch (const MyMoneyException &) { QCOMPARE(m->dirty(), false); } } void MyMoneyDatabaseMgrTest::testModifyOnlineJob() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); onlineJob job(new dummyTask()); testAddOnlineJob(); m->setDirty(); QSKIP("Test not fully implemented, yet.", SkipAll); // update online job try { m->modifyOnlineJob(job); QVERIFY(m->onlineJobList().count() == 1); //QVERIFY((*(m->onlineJobList().begin())).name() == "EURO"); QVERIFY((*(m->onlineJobList().begin())).id() == "O00000001"); } catch (const MyMoneyException &e) { unexpectedException(e); } m->setDirty(); onlineJob unknownJob(new dummyTask()); try { m->modifyOnlineJob(unknownJob); QFAIL("Expected exception missing"); } catch (const MyMoneyException &) { QVERIFY(m->dirty() == false); } } void MyMoneyDatabaseMgrTest::testRemoveOnlineJob() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); onlineJob job(new dummyTask()); testAddOnlineJob(); m->setDirty(); QSKIP("Test not fully implemented, yet.", SkipAll); try { m->removeOnlineJob(job); QVERIFY(m->onlineJobList().count() == 0); } catch (const MyMoneyException &e) { unexpectedException(e); } m->setDirty(); onlineJob unknownJob(new dummyTask()); try { m->removeOnlineJob(unknownJob); QFAIL("Expected exception missing"); } catch (const MyMoneyException &) { QVERIFY(m->dirty() == false); } } void MyMoneyDatabaseMgrTest::testHighestNumberFromIdString() { testAttachDb(); if (!m_canOpen) QSKIP("Database test skipped because no database could be opened.", SkipAll); testAddTransactions(); QCOMPARE(m->m_sql->highestNumberFromIdString(QLatin1String("kmmTransactions"), QLatin1String("id"), 1), 2ul); QCOMPARE(m->m_sql->highestNumberFromIdString(QLatin1String("kmmAccounts"), QLatin1String("id"), 1), 6ul); } diff --git a/kmymoney/mymoney/storage/tests/mymoneydatabasemgr-test.h b/kmymoney/mymoney/storage/tests/mymoneydatabasemgr-test.h index 4f6a3188c..690274e4f 100644 --- a/kmymoney/mymoney/storage/tests/mymoneydatabasemgr-test.h +++ b/kmymoney/mymoney/storage/tests/mymoneydatabasemgr-test.h @@ -1,116 +1,116 @@ /*************************************************************************** mymoneydatabasemgrtest.h ------------------- copyright : (C) 2008 by Fernando Vilas email : fvilas@iname.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. * * * ***************************************************************************/ #ifndef MYMONEYDATABASEMGRTEST_H #define MYMONEYDATABASEMGRTEST_H -#include +#include #include #include #define KMM_MYMONEY_UNIT_TESTABLE friend class MyMoneyDatabaseMgrTest; #include "../mymoneyobject.h" #include "mymoneydatabasemgr.h" class MyMoneyDatabaseMgrTest : public QObject { Q_OBJECT protected: MyMoneyDatabaseMgr *m; bool m_dbAttached; bool m_canOpen; bool m_haveEmptyDataBase; QUrl m_url; QTemporaryFile m_file; QTemporaryFile m_emptyFile; private: QElapsedTimer testStepTimer; QElapsedTimer testCaseTimer; public: MyMoneyDatabaseMgrTest(); private: void setupUrl(const QString& fname); void testEquality(const MyMoneyDatabaseMgr* t); void copyDatabaseFile(QFile& src, QFile& dest); private slots: void init(); void cleanup(); void testEmptyConstructor(); void testBadConnections(); void testCreateDb(); void testAttachDb(); void testDisconnection(); void testSetFunctions(); void testIsStandardAccount(); void testNewAccount(); void testAccount(); void testAddNewAccount(); void testAddInstitution(); void testInstitution(); void testAccount2Institution(); void testModifyAccount(); void testModifyInstitution(); void testReparentAccount(); void testAddTransactions(); void testTransactionCount(); void testAddBudget(); void testCopyBudget(); void testModifyBudget(); void testRemoveBudget(); void testBalance(); void testModifyTransaction(); void testRemoveUnusedAccount(); void testRemoveUsedAccount(); void testRemoveInstitution(); void testRemoveTransaction(); void testTransactionList(); void testAddPayee(); void testSetAccountName(); void testModifyPayee(); void testPayeeName(); void testRemovePayee(); void testAddTag(); void testModifyTag(); void testTagName(); void testRemoveTag(); void testRemoveAccountFromTree(); void testAssignment(); void testDuplicate(); void testAddSchedule(); void testSchedule(); void testModifySchedule(); void testRemoveSchedule(); void testSupportFunctions(); void testScheduleList(); void testAddCurrency(); void testModifyCurrency(); void testRemoveCurrency(); void testCurrency(); void testCurrencyList(); void testAccountList(); void testAddOnlineJob(); void testModifyOnlineJob(); void testRemoveOnlineJob(); void testHighestNumberFromIdString(); }; #endif diff --git a/kmymoney/mymoney/storage/tests/mymoneymap-test.cpp b/kmymoney/mymoney/storage/tests/mymoneymap-test.cpp index 3c5e48c52..2f867c2e4 100644 --- a/kmymoney/mymoney/storage/tests/mymoneymap-test.cpp +++ b/kmymoney/mymoney/storage/tests/mymoneymap-test.cpp @@ -1,91 +1,91 @@ /*************************************************************************** mymoneymaptest.cpp ------------------- copyright : (C) 2007 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 "mymoneymap-test.h" #include -#include +#include QTEST_GUILESS_MAIN(MyMoneyMapTest) void MyMoneyMapTest::init() { m = new MyMoneyMap; } void MyMoneyMapTest::cleanup() { delete m; } void MyMoneyMapTest::testArrayOperator() { QSKIP("Test not implemented yet", SkipAll); } void MyMoneyMapTest::testModifyKey() { // setup m->startTransaction(); m->insert("a", "a"); m->commitTransaction(); QVERIFY((*m)["a"] == "a"); // commit m->startTransaction(); m->modify("a", "b"); QVERIFY((*m)["a"] == "b"); m->commitTransaction(); QVERIFY((*m)["a"] == "b"); // rollback m->startTransaction(); m->modify("a", "c"); QVERIFY((*m)["a"] == "c"); m->rollbackTransaction(); QVERIFY((*m)["a"] == "b"); } void MyMoneyMapTest::testModifyKeyTwice() { m->startTransaction(); m->insert("a", "a"); QVERIFY((*m)["a"] == "a"); m->insert("b", "b"); QVERIFY((*m)["a"] == "a"); QVERIFY((*m)["b"] == "b"); m->modify("a", "b"); QVERIFY((*m)["a"] == "b"); m->rollbackTransaction(); QVERIFY(m->count() == 0); m->startTransaction(); m->insert("a", "a"); m->insert("b", "b"); m->commitTransaction(); QVERIFY((*m)["a"] == "a"); QVERIFY((*m)["b"] == "b"); m->startTransaction(); m->modify("a", "b"); m->modify("a", "c"); QVERIFY((*m)["a"] == "c"); m->rollbackTransaction(); QVERIFY((*m)["a"] == "a"); } diff --git a/kmymoney/mymoney/storage/tests/mymoneymap-test.h b/kmymoney/mymoney/storage/tests/mymoneymap-test.h index 961593607..cde9e63f6 100644 --- a/kmymoney/mymoney/storage/tests/mymoneymap-test.h +++ b/kmymoney/mymoney/storage/tests/mymoneymap-test.h @@ -1,40 +1,40 @@ /*************************************************************************** mymoneymaptest.h ------------------- copyright : (C) 2007 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 MYMONEYMAPTEST_H #define MYMONEYMAPTEST_H -#include +#include #include "mymoneytestutils.h" #include "mymoneyseqaccessmgr.h" class MyMoneyMapTest : public QObject { Q_OBJECT protected: MyMoneyMap *m; private slots: void init(); void cleanup(); void testArrayOperator(); void testModifyKey(); void testModifyKeyTwice(); }; #endif diff --git a/kmymoney/mymoney/storage/tests/mymoneyseqaccessmgr-test.cpp b/kmymoney/mymoney/storage/tests/mymoneyseqaccessmgr-test.cpp index ae5d204dc..fb8dd7825 100644 --- a/kmymoney/mymoney/storage/tests/mymoneyseqaccessmgr-test.cpp +++ b/kmymoney/mymoney/storage/tests/mymoneyseqaccessmgr-test.cpp @@ -1,1820 +1,1820 @@ /*************************************************************************** mymoneyseqaccessmgrtest.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 "mymoneyseqaccessmgr-test.h" #include #include -#include +#include #include "mymoneytestutils.h" #include "mymoneymoney.h" #include "mymoneyfile.h" #include "mymoneyinstitution.h" #include "mymoneyaccount.h" #include "mymoneysecurity.h" #include "mymoneytag.h" #include "mymoneypayee.h" #include "mymoneyschedule.h" #include "mymoneyreport.h" #include "mymoneysplit.h" #include "mymoneytransaction.h" #include "mymoneybudget.h" #include "mymoneyprice.h" #include "onlinetasks/dummy/tasks/dummytask.h" #include "mymoneyenums.h" using namespace eMyMoney; QTEST_GUILESS_MAIN(MyMoneySeqAccessMgrTest) void MyMoneySeqAccessMgrTest::init() { m = new MyMoneySeqAccessMgr; MyMoneyFile* file = MyMoneyFile::instance(); file->attachStorage(m); m->startTransaction(); } void MyMoneySeqAccessMgrTest::cleanup() { m->commitTransaction(); MyMoneyFile* file = MyMoneyFile::instance(); file->detachStorage(m); delete m; } void MyMoneySeqAccessMgrTest::testEmptyConstructor() { MyMoneyPayee user = m->user(); QVERIFY(user.name().isEmpty()); QVERIFY(user.address().isEmpty()); QVERIFY(user.city().isEmpty()); QVERIFY(user.state().isEmpty()); QVERIFY(user.postcode().isEmpty()); QVERIFY(user.telephone().isEmpty()); QVERIFY(user.email().isEmpty()); QCOMPARE(m->m_nextInstitutionID, 0ul); QCOMPARE(m->m_nextAccountID, 0ul); QCOMPARE(m->m_nextTransactionID, 0ul); QCOMPARE(m->m_nextPayeeID, 0ul); QCOMPARE(m->m_nextScheduleID, 0ul); QCOMPARE(m->m_nextReportID, 0ul); QCOMPARE(m->m_institutionList.count(), 0); QCOMPARE(m->m_accountList.count(), 5); QCOMPARE(m->m_transactionList.count(), 0); QCOMPARE(m->m_transactionKeys.count(), 0); QCOMPARE(m->m_payeeList.count(), 0); QCOMPARE(m->m_tagList.count(), 0); QCOMPARE(m->m_scheduleList.count(), 0); QCOMPARE(m->m_dirty, false); QCOMPARE(m->m_creationDate, QDate::currentDate()); QCOMPARE(m->liability().name(), QLatin1String("Liability")); QCOMPARE(m->asset().name(), QLatin1String("Asset")); QCOMPARE(m->expense().name(), QLatin1String("Expense")); QCOMPARE(m->income().name(), QLatin1String("Income")); QCOMPARE(m->equity().name(), QLatin1String("Equity")); } void MyMoneySeqAccessMgrTest::testSetFunctions() { MyMoneyPayee user = m->user(); m->m_dirty = false; user.setName("Name"); m->setUser(user); m->commitTransaction(); m->startTransaction(); QCOMPARE(m->dirty(), true); m->m_dirty = false; user.setAddress("Street"); m->setUser(user); m->commitTransaction(); m->startTransaction(); QCOMPARE(m->dirty(), true); m->m_dirty = false; user.setCity("Town"); m->setUser(user); m->commitTransaction(); m->startTransaction(); QCOMPARE(m->dirty(), true); m->m_dirty = false; user.setState("County"); m->setUser(user); m->commitTransaction(); m->startTransaction(); QCOMPARE(m->dirty(), true); m->m_dirty = false; user.setPostcode("Postcode"); m->setUser(user); m->commitTransaction(); m->startTransaction(); QCOMPARE(m->dirty(), true); m->m_dirty = false; user.setTelephone("Telephone"); m->setUser(user); m->commitTransaction(); m->startTransaction(); QCOMPARE(m->dirty(), true); m->m_dirty = false; user.setEmail("Email"); m->setUser(user); m->commitTransaction(); m->startTransaction(); QCOMPARE(m->dirty(), true); m->m_dirty = false; m->setValue("key", "value"); m->commitTransaction(); m->startTransaction(); QCOMPARE(m->dirty(), true); 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")); QCOMPARE(m->value("key"), QLatin1String("value")); m->m_dirty = false; m->deletePair("key"); m->commitTransaction(); m->startTransaction(); QCOMPARE(m->dirty(), true); } void MyMoneySeqAccessMgrTest::testSupportFunctions() { QCOMPARE(m->nextInstitutionID(), QLatin1String("I000001")); QCOMPARE(m->m_nextInstitutionID, 1ul); QCOMPARE(m->nextAccountID(), QLatin1String("A000001")); QCOMPARE(m->m_nextAccountID, 1ul); QCOMPARE(m->nextTransactionID(), QLatin1String("T000000000000000001")); QCOMPARE(m->m_nextTransactionID, 1ul); QCOMPARE(m->nextPayeeID(), QLatin1String("P000001")); QCOMPARE(m->m_nextPayeeID, 1ul); QCOMPARE(m->nextTagID(), QLatin1String("G000001")); QCOMPARE(m->m_nextTagID, 1ul); QCOMPARE(m->nextScheduleID(), QLatin1String("SCH000001")); QCOMPARE(m->m_nextScheduleID, 1ul); QCOMPARE(m->nextReportID(), QLatin1String("R000001")); QCOMPARE(m->m_nextReportID, 1ul); QCOMPARE(m->nextOnlineJobID(), QLatin1String("O000001")); QCOMPARE(m->m_nextOnlineJobID, 1ul); } void MyMoneySeqAccessMgrTest::testIsStandardAccount() { QCOMPARE(m->isStandardAccount(STD_ACC_LIABILITY), true); QCOMPARE(m->isStandardAccount(STD_ACC_ASSET), true); QCOMPARE(m->isStandardAccount(STD_ACC_EXPENSE), true); QCOMPARE(m->isStandardAccount(STD_ACC_INCOME), true); QCOMPARE(m->isStandardAccount("A0002"), false); } void MyMoneySeqAccessMgrTest::testNewAccount() { MyMoneyAccount a; a.setName("AccountName"); a.setNumber("AccountNumber"); m->addAccount(a); m->commitTransaction(); m->startTransaction(); QCOMPARE(m->m_nextAccountID, 1ul); QCOMPARE(m->dirty(), true); QCOMPARE(m->m_accountList.count(), 6); QCOMPARE(m->m_accountList["A000001"].name(), QLatin1String("AccountName")); } void MyMoneySeqAccessMgrTest::testAccount() { testNewAccount(); m->m_dirty = false; MyMoneyAccount a; // make sure that an invalid ID causes an exception try { a = m->account("Unknown ID"); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } m->commitTransaction(); m->startTransaction(); QCOMPARE(m->dirty(), false); // now make sure, that a real ID works try { a = m->account("A000001"); m->commitTransaction(); m->startTransaction(); QCOMPARE(a.name(), QLatin1String("AccountName")); QCOMPARE(a.id(), QLatin1String("A000001")); QCOMPARE(m->dirty(), true); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } } void MyMoneySeqAccessMgrTest::testAddNewAccount() { testNewAccount(); MyMoneyAccount a, b; b.setName("Account2"); b.setNumber("Acc2"); m->addAccount(b); m->commitTransaction(); m->startTransaction(); m->m_dirty = false; QCOMPARE(m->m_nextAccountID, 2ul); QCOMPARE(m->m_accountList.count(), 7); // try to add account to undefined account try { MyMoneyAccount c("UnknownID", b); m->addAccount(c, a); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } m->commitTransaction(); m->startTransaction(); QCOMPARE(m->dirty(), false); // now try to add account 1 as sub-account to account 2 a = m->account("A000001"); try { QCOMPARE(m->m_accountList[STD_ACC_ASSET].accountList().count(), 0); m->addAccount(b, a); m->commitTransaction(); m->startTransaction(); QCOMPARE(m->m_accountList["A000002"].accountList()[0], QLatin1String("A000001")); QCOMPARE(m->m_accountList["A000002"].accountList().count(), 1); QCOMPARE(m->m_accountList[STD_ACC_ASSET].accountList().count(), 0); QCOMPARE(m->dirty(), true); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } } void MyMoneySeqAccessMgrTest::testAddInstitution() { MyMoneyInstitution i; i.setName("Inst Name"); m->addInstitution(i); QCOMPARE(m->m_institutionList.count(), 1); QCOMPARE(m->m_nextInstitutionID, 1ul); QCOMPARE(m->m_institutionList["I000001"].name(), QLatin1String("Inst Name")); } void MyMoneySeqAccessMgrTest::testInstitution() { testAddInstitution(); MyMoneyInstitution i; m->m_dirty = false; // try to find unknown institution try { i = m->institution("Unknown ID"); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } QCOMPARE(m->dirty(), false); // now try to find real institution try { i = m->institution("I000001"); QCOMPARE(i.name(), QLatin1String("Inst Name")); QCOMPARE(m->dirty(), false); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } } void MyMoneySeqAccessMgrTest::testAccount2Institution() { testAddInstitution(); testAddNewAccount(); MyMoneyInstitution i; MyMoneyAccount a, b; try { i = m->institution("I000001"); a = m->account("A000001"); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } m->m_dirty = false; // try to add to a false institution MyMoneyInstitution fake("Unknown ID", i); a.setInstitutionId(fake.id()); try { m->modifyAccount(a); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } m->commitTransaction(); m->startTransaction(); QCOMPARE(m->dirty(), false); // now try to do it with a real institution try { QCOMPARE(i.accountList().count(), 0); a.setInstitutionId(i.id()); m->modifyAccount(a); m->commitTransaction(); m->startTransaction(); QCOMPARE(m->dirty(), true); QCOMPARE(a.institutionId(), i.id()); b = m->account("A000001"); QCOMPARE(b.institutionId(), i.id()); QCOMPARE(i.accountList().count(), 0); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } } void MyMoneySeqAccessMgrTest::testModifyAccount() { testAccount2Institution(); // test the OK case MyMoneyAccount a = m->account("A000001"); a.setName("New account name"); m->m_dirty = false; try { m->modifyAccount(a); m->commitTransaction(); m->startTransaction(); MyMoneyAccount b = m->account("A000001"); QCOMPARE(b.parentAccountId(), a.parentAccountId()); QCOMPARE(b.name(), QLatin1String("New account name")); QCOMPARE(m->dirty(), true); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } // modify institution to unknown id MyMoneyAccount c("Unknown ID", a); m->m_dirty = false; try { m->modifyAccount(c); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } // use different account type MyMoneyAccount d; d.setAccountType(Account::CreditCard); MyMoneyAccount f("A000001", d); try { m->modifyAccount(f); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } // use different parent a.setParentAccountId("A000002"); try { m->modifyAccount(c); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } } void MyMoneySeqAccessMgrTest::testModifyInstitution() { testAddInstitution(); MyMoneyInstitution i = m->institution("I000001"); m->m_dirty = false; i.setName("New inst name"); try { m->modifyInstitution(i); m->commitTransaction(); m->startTransaction(); QCOMPARE(m->dirty(), true); i = m->institution("I000001"); QCOMPARE(i.name(), QLatin1String("New inst name")); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } // try to modify an institution that does not exist MyMoneyInstitution f("Unknown ID", i); try { m->modifyInstitution(f); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } } void MyMoneySeqAccessMgrTest::testReparentAccount() { // this one adds some accounts to the database MyMoneyAccount ex1; ex1.setAccountType(Account::Expense); MyMoneyAccount ex2; ex2.setAccountType(Account::Expense); MyMoneyAccount ex3; ex3.setAccountType(Account::Expense); MyMoneyAccount ex4; ex4.setAccountType(Account::Expense); MyMoneyAccount in; in.setAccountType(Account::Income); MyMoneyAccount ch; ch.setAccountType(Account::Checkings); ex1.setName("Sales Tax"); ex2.setName("Sales Tax 16%"); ex3.setName("Sales Tax 7%"); ex4.setName("Grosseries"); in.setName("Salary"); ch.setName("My checkings account"); try { m->addAccount(ex1); m->addAccount(ex2); m->addAccount(ex3); m->addAccount(ex4); m->addAccount(in); m->addAccount(ch); QCOMPARE(ex1.id(), QLatin1String("A000001")); QCOMPARE(ex2.id(), QLatin1String("A000002")); QCOMPARE(ex3.id(), QLatin1String("A000003")); QCOMPARE(ex4.id(), QLatin1String("A000004")); QCOMPARE(in.id(), QLatin1String("A000005")); QCOMPARE(ch.id(), QLatin1String("A000006")); MyMoneyAccount parent = m->expense(); m->addAccount(parent, ex1); m->addAccount(ex1, ex2); m->addAccount(parent, ex3); m->addAccount(parent, ex4); parent = m->income(); m->addAccount(parent, in); parent = m->asset(); m->addAccount(parent, ch); QCOMPARE(m->expense().accountCount(), 3); QCOMPARE(m->account(ex1.id()).accountCount(), 1); QCOMPARE(ex3.parentAccountId(), QLatin1String(STD_ACC_EXPENSE)); m->reparentAccount(ex3, ex1); QCOMPARE(m->expense().accountCount(), 2); QCOMPARE(m->account(ex1.id()).accountCount(), 2); QCOMPARE(ex3.parentAccountId(), ex1.id()); } catch (const MyMoneyException &e) { std::cout << std::endl << qPrintable(e.what()) << std::endl; QFAIL("Unexpected exception"); } } void MyMoneySeqAccessMgrTest::testAddTransactions() { testReparentAccount(); MyMoneyAccount ch; MyMoneyTransaction t1, t2; MyMoneySplit s; try { // I made some money, great s.setAccountId("A000006"); // Checkings s.setShares(MyMoneyMoney(100000, 100)); s.setValue(MyMoneyMoney(100000, 100)); QVERIFY(s.id().isEmpty()); t1.addSplit(s); s.setId(QString()); // enable re-usage of split variable s.setAccountId("A000005"); // Salary s.setShares(MyMoneyMoney(-100000, 100)); s.setValue(MyMoneyMoney(-100000, 100)); QVERIFY(s.id().isEmpty()); t1.addSplit(s); t1.setPostDate(QDate(2002, 5, 10)); } catch (const MyMoneyException &e) { unexpectedException(e); } m->m_dirty = false; try { m->addTransaction(t1); m->commitTransaction(); m->startTransaction(); QCOMPARE(m->dirty(), true); QCOMPARE(t1.id(), QLatin1String("T000000000000000001")); QCOMPARE(t1.splitCount(), 2u); QCOMPARE(m->transactionCount(), 1u); } catch (const MyMoneyException &e) { unexpectedException(e); } try { // I spent some money, not so great s.setId(QString()); // enable re-usage of split variable s.setAccountId("A000004"); // Grosseries s.setShares(MyMoneyMoney(10000, 100)); s.setValue(MyMoneyMoney(10000, 100)); QVERIFY(s.id().isEmpty()); t2.addSplit(s); s.setId(QString()); // enable re-usage of split variable s.setAccountId("A000002"); // 16% sales tax s.setShares(MyMoneyMoney(1200, 100)); s.setValue(MyMoneyMoney(1200, 100)); QVERIFY(s.id().isEmpty()); t2.addSplit(s); s.setId(QString()); // enable re-usage of split variable s.setAccountId("A000003"); // 7% sales tax s.setShares(MyMoneyMoney(400, 100)); s.setValue(MyMoneyMoney(400, 100)); QVERIFY(s.id().isEmpty()); t2.addSplit(s); s.setId(QString()); // enable re-usage of split variable s.setAccountId("A000006"); // Checkings account s.setShares(MyMoneyMoney(-11600, 100)); s.setValue(MyMoneyMoney(-11600, 100)); QVERIFY(s.id().isEmpty()); t2.addSplit(s); t2.setPostDate(QDate(2002, 5, 9)); } catch (const MyMoneyException &e) { unexpectedException(e); } m->m_dirty = false; try { m->addTransaction(t2); m->commitTransaction(); m->startTransaction(); QCOMPARE(m->dirty(), true); QCOMPARE(t2.id(), QLatin1String("T000000000000000002")); QCOMPARE(t2.splitCount(), 4u); QCOMPARE(m->transactionCount(), 2u); QMap::ConstIterator it_k; QMap::ConstIterator it_t; it_k = m->m_transactionKeys.begin(); it_t = m->m_transactionList.begin(); QCOMPARE((*it_k), QLatin1String("2002-05-10-T000000000000000001")); QCOMPARE((*it_t).id(), QLatin1String("T000000000000000002")); ++it_k; ++it_t; QCOMPARE((*it_k), QLatin1String("2002-05-09-T000000000000000002")); QCOMPARE((*it_t).id(), QLatin1String("T000000000000000001")); ++it_k; ++it_t; QCOMPARE(it_k, m->m_transactionKeys.end()); QCOMPARE(it_t, m->m_transactionList.end()); ch = m->account("A000006"); // check that the account's transaction list is updated QList list; MyMoneyTransactionFilter filter("A000006"); list = m->transactionList(filter); QCOMPARE(list.size(), 2); QList::ConstIterator it; it = list.constBegin(); QCOMPARE((*it).id(), QLatin1String("T000000000000000002")); ++it; QCOMPARE((*it).id(), QLatin1String("T000000000000000001")); ++it; QCOMPARE(it, list.constEnd()); } catch (const MyMoneyException &e) { unexpectedException(e); } } void MyMoneySeqAccessMgrTest::testTransactionCount() { testAddTransactions(); QCOMPARE(m->transactionCount("A000001"), 0u); QCOMPARE(m->transactionCount("A000002"), 1u); QCOMPARE(m->transactionCount("A000003"), 1u); QCOMPARE(m->transactionCount("A000004"), 1u); QCOMPARE(m->transactionCount("A000005"), 1u); QCOMPARE(m->transactionCount("A000006"), 2u); } void MyMoneySeqAccessMgrTest::testBalance() { testAddTransactions(); QVERIFY(m->balance("A000001").isZero()); QCOMPARE(m->balance("A000002"), MyMoneyMoney(1200, 100)); QCOMPARE(m->balance("A000003"), MyMoneyMoney(400, 100)); QCOMPARE(m->totalBalance("A000001"), MyMoneyMoney(1600, 100)); QCOMPARE(m->balance("A000006", QDate(2002, 5, 9)), MyMoneyMoney(-11600, 100)); QCOMPARE(m->balance("A000005", QDate(2002, 5, 10)), MyMoneyMoney(-100000, 100)); QCOMPARE(m->balance("A000006", QDate(2002, 5, 10)), MyMoneyMoney(88400, 100)); } void MyMoneySeqAccessMgrTest::testModifyTransaction() { testAddTransactions(); MyMoneyTransaction t = m->transaction("T000000000000000002"); MyMoneySplit s; MyMoneyAccount ch; // just modify simple stuff (splits) QCOMPARE(t.splitCount(), 4u); s = t.splits()[0]; s.setShares(MyMoneyMoney(11000, 100)); s.setValue(MyMoneyMoney(11000, 100)); t.modifySplit(s); QCOMPARE(t.splitCount(), 4u); s = t.splits()[3]; s.setShares(MyMoneyMoney(-12600, 100)); s.setValue(MyMoneyMoney(-12600, 100)); t.modifySplit(s); try { QCOMPARE(m->balance("A000004"), MyMoneyMoney(10000, 100)); QCOMPARE(m->balance("A000006"), MyMoneyMoney(100000 - 11600, 100)); QCOMPARE(m->totalBalance("A000001"), MyMoneyMoney(1600, 100)); m->modifyTransaction(t); QCOMPARE(m->balance("A000004"), MyMoneyMoney(11000, 100)); QCOMPARE(m->balance("A000006"), MyMoneyMoney(100000 - 12600, 100)); QCOMPARE(m->totalBalance("A000001"), MyMoneyMoney(1600, 100)); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } // now modify the date t.setPostDate(QDate(2002, 5, 11)); try { m->modifyTransaction(t); QCOMPARE(m->balance("A000004"), MyMoneyMoney(11000, 100)); QCOMPARE(m->balance("A000006"), MyMoneyMoney(100000 - 12600, 100)); QCOMPARE(m->totalBalance("A000001"), MyMoneyMoney(1600, 100)); QMap::ConstIterator it_k; QMap::ConstIterator it_t; it_k = m->m_transactionKeys.begin(); it_t = m->m_transactionList.begin(); QCOMPARE((*it_k), QLatin1String("2002-05-10-T000000000000000001")); QCOMPARE((*it_t).id(), QLatin1String("T000000000000000001")); ++it_k; ++it_t; QCOMPARE((*it_k), QLatin1String("2002-05-11-T000000000000000002")); QCOMPARE((*it_t).id(), QLatin1String("T000000000000000002")); ++it_k; ++it_t; QCOMPARE(it_k, m->m_transactionKeys.end()); QCOMPARE(it_t, m->m_transactionList.end()); ch = m->account("A000006"); // check that the account's transaction list is updated QList list; MyMoneyTransactionFilter filter("A000006"); list = m->transactionList(filter); QCOMPARE(list.size(), 2); QList::ConstIterator it; it = list.constBegin(); QCOMPARE((*it).id(), QLatin1String("T000000000000000001")); ++it; QCOMPARE((*it).id(), QLatin1String("T000000000000000002")); ++it; QCOMPARE(it, list.constEnd()); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } } void MyMoneySeqAccessMgrTest::testRemoveUnusedAccount() { testAccount2Institution(); MyMoneyAccount a = m->account("A000001"); MyMoneyInstitution i = m->institution("I000001"); m->m_dirty = false; // make sure, we cannot remove the standard account groups try { m->removeAccount(m->liability()); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } try { m->removeAccount(m->asset()); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } try { m->removeAccount(m->expense()); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } try { m->removeAccount(m->income()); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } // try to remove the account still attached to the institution try { m->removeAccount(a); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } // now really remove an account try { QCOMPARE(i.accountCount(), 0u); QCOMPARE(m->accountCount(), 7u); a.setInstitutionId(QString()); m->modifyAccount(a); m->removeAccount(a); m->commitTransaction(); m->startTransaction(); QCOMPARE(m->accountCount(), 6u); QCOMPARE(m->dirty(), true); i = m->institution("I000001"); QCOMPARE(i.accountCount(), 0u); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } } void MyMoneySeqAccessMgrTest::testRemoveUsedAccount() { testAddTransactions(); MyMoneyAccount a = m->account("A000006"); try { m->removeAccount(a); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } } void MyMoneySeqAccessMgrTest::testRemoveInstitution() { testModifyInstitution(); testReparentAccount(); MyMoneyInstitution i; MyMoneyAccount a; // assign the checkings account to the institution try { i = m->institution("I000001"); a = m->account("A000006"); a.setInstitutionId(i.id()); m->modifyAccount(a); QCOMPARE(i.accountCount(), 0u); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } m->m_dirty = false; // now remove the institution and see if the account survived ;-) try { m->removeInstitution(i); a.setInstitutionId(QString()); m->modifyAccount(a); m->commitTransaction(); m->startTransaction(); a = m->account("A000006"); QCOMPARE(m->dirty(), true); QVERIFY(a.institutionId().isEmpty()); QCOMPARE(m->institutionCount(), 0u); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } } void MyMoneySeqAccessMgrTest::testRemoveTransaction() { testAddTransactions(); MyMoneyTransaction t = m->transaction("T000000000000000002"); m->m_dirty = false; try { m->removeTransaction(t); m->commitTransaction(); m->startTransaction(); QCOMPARE(m->dirty(), true); QCOMPARE(m->transactionCount(), 1u); /* removed with MyMoneyAccount::Transaction QCOMPARE(m->account("A000006").transactionCount(), 1); */ } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } } void MyMoneySeqAccessMgrTest::testTransactionList() { testAddTransactions(); QList list; MyMoneyTransactionFilter filter("A000006"); list = m->transactionList(filter); QCOMPARE(list.count(), 2); QCOMPARE(list.at(0).id(), QLatin1String("T000000000000000002")); QCOMPARE(list.at(1).id(), QLatin1String("T000000000000000001")); filter.clear(); filter.addAccount(QString("A000003")); list = m->transactionList(filter); QCOMPARE(list.count(), 1); QCOMPARE(list.at(0).id(), QLatin1String("T000000000000000002")); filter.clear(); list = m->transactionList(filter); QCOMPARE(list.count(), 2); QCOMPARE(list.at(0).id(), QLatin1String("T000000000000000002")); QCOMPARE(list.at(1).id(), QLatin1String("T000000000000000001")); } void MyMoneySeqAccessMgrTest::testAddPayee() { MyMoneyPayee p; p.setName("THB"); m->m_dirty = false; try { QCOMPARE(m->m_nextPayeeID, 0ul); m->addPayee(p); m->commitTransaction(); m->startTransaction(); QCOMPARE(m->dirty(), true); QCOMPARE(m->m_nextPayeeID, 1ul); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } } void MyMoneySeqAccessMgrTest::testSetAccountName() { try { m->setAccountName(STD_ACC_LIABILITY, "Verbindlichkeiten"); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } try { m->setAccountName(STD_ACC_ASSET, QString("Vermögen")); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } try { m->setAccountName(STD_ACC_EXPENSE, "Ausgaben"); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } try { m->setAccountName(STD_ACC_INCOME, "Einnahmen"); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } QCOMPARE(m->liability().name(), QLatin1String("Verbindlichkeiten")); QCOMPARE(m->asset().name(), QString("Vermögen")); QCOMPARE(m->expense().name(), QLatin1String("Ausgaben")); QCOMPARE(m->income().name(), QLatin1String("Einnahmen")); try { m->setAccountName("A000001", "New account name"); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } } void MyMoneySeqAccessMgrTest::testModifyPayee() { MyMoneyPayee p; testAddPayee(); p = m->payee("P000001"); p.setName("New name"); m->m_dirty = false; try { m->modifyPayee(p); m->commitTransaction(); m->startTransaction(); p = m->payee("P000001"); QCOMPARE(p.name(), QLatin1String("New name")); QCOMPARE(m->dirty(), true); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } } void MyMoneySeqAccessMgrTest::testRemovePayee() { testAddPayee(); m->m_dirty = false; // check that we can remove an unreferenced payee MyMoneyPayee p = m->payee("P000001"); try { QCOMPARE(m->m_payeeList.count(), 1); m->removePayee(p); m->commitTransaction(); m->startTransaction(); QCOMPARE(m->m_payeeList.count(), 0); QCOMPARE(m->dirty(), true); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } // add transaction testAddTransactions(); MyMoneyTransaction tr = m->transaction("T000000000000000001"); MyMoneySplit sp; sp = tr.splits()[0]; sp.setPayeeId("P000001"); tr.modifySplit(sp); // check that we cannot add a transaction referencing // an unknown payee try { m->modifyTransaction(tr); QFAIL("Expected exception"); } catch (const MyMoneyException &) { } m->m_nextPayeeID = 0; // reset here, so that the // testAddPayee will not fail testAddPayee(); // check that it works when the payee exists try { m->modifyTransaction(tr); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } m->m_dirty = false; // now check, that we cannot remove the payee try { m->removePayee(p); QFAIL("Expected exception"); } catch (const MyMoneyException &) { } QCOMPARE(m->m_payeeList.count(), 1); } void MyMoneySeqAccessMgrTest::testAddTag() { MyMoneyTag ta; ta.setName("THB"); m->m_dirty = false; try { QCOMPARE(m->m_nextTagID, 0ul); m->addTag(ta); m->commitTransaction(); m->startTransaction(); QCOMPARE(m->dirty(), true); QCOMPARE(m->m_nextTagID, 1ul); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } } void MyMoneySeqAccessMgrTest::testModifyTag() { MyMoneyTag ta; testAddTag(); ta = m->tag("G000001"); ta.setName("New name"); m->m_dirty = false; try { m->modifyTag(ta); m->commitTransaction(); m->startTransaction(); ta = m->tag("G000001"); QCOMPARE(ta.name(), QLatin1String("New name")); QCOMPARE(m->dirty(), true); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } } void MyMoneySeqAccessMgrTest::testRemoveTag() { testAddTag(); m->m_dirty = false; // check that we can remove an unreferenced tag MyMoneyTag ta = m->tag("G000001"); try { QCOMPARE(m->m_tagList.count(), 1); m->removeTag(ta); m->commitTransaction(); m->startTransaction(); QCOMPARE(m->m_tagList.count(), 0); QCOMPARE(m->dirty(), true); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } // add transaction testAddTransactions(); MyMoneyTransaction tr = m->transaction("T000000000000000001"); MyMoneySplit sp; sp = tr.splits()[0]; QList tagIdList; tagIdList << "G000001"; sp.setTagIdList(tagIdList); tr.modifySplit(sp); // check that we cannot add a transaction referencing // an unknown tag try { m->modifyTransaction(tr); QFAIL("Expected exception"); } catch (const MyMoneyException &) { } m->m_nextTagID = 0; // reset here, so that the // testAddTag will not fail testAddTag(); // check that it works when the tag exists try { m->modifyTransaction(tr); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } m->m_dirty = false; // now check, that we cannot remove the tag try { m->removeTag(ta); QFAIL("Expected exception"); } catch (const MyMoneyException &) { } QCOMPARE(m->m_tagList.count(), 1); } void MyMoneySeqAccessMgrTest::testRemoveAccountFromTree() { MyMoneyAccount a, b, c; a.setName("Acc A"); b.setName("Acc B"); c.setName("Acc C"); // build a tree A -> B -> C, remove B and see if A -> C // remains in the storag manager try { m->addAccount(a); m->addAccount(b); m->addAccount(c); m->reparentAccount(b, a); m->reparentAccount(c, b); QCOMPARE(a.accountList().count(), 1); QCOMPARE(m->account(a.accountList()[0]).name(), QLatin1String("Acc B")); QCOMPARE(b.accountList().count(), 1); QCOMPARE(m->account(b.accountList()[0]).name(), QLatin1String("Acc C")); QCOMPARE(c.accountList().count(), 0); m->removeAccount(b); // reload account info from titutionIDtorage a = m->account(a.id()); c = m->account(c.id()); try { b = m->account(b.id()); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } QCOMPARE(a.accountList().count(), 1); QCOMPARE(m->account(a.accountList()[0]).name(), QLatin1String("Acc C")); QCOMPARE(c.accountList().count(), 0); } catch (const MyMoneyException &e) { unexpectedException(e); } } void MyMoneySeqAccessMgrTest::testPayeeName() { testAddPayee(); MyMoneyPayee p; QString name("THB"); // OK case try { p = m->payeeByName(name); QCOMPARE(p.name(), QLatin1String("THB")); QCOMPARE(p.id(), QLatin1String("P000001")); } catch (const MyMoneyException &e) { unexpectedException(e); } // Not OK case name = "Thb"; try { p = m->payeeByName(name); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } } void MyMoneySeqAccessMgrTest::testTagName() { testAddTag(); MyMoneyTag ta; QString name("THB"); // OK case try { ta = m->tagByName(name); QCOMPARE(ta.name(), QLatin1String("THB")); QCOMPARE(ta.id(), QLatin1String("G000001")); } catch (const MyMoneyException &e) { unexpectedException(e); } // Not OK case name = "Thb"; try { ta = m->tagByName(name); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } } void MyMoneySeqAccessMgrTest::testAssignment() { testAddTransactions(); MyMoneyPayee user; user.setName("Thomas"); m->setUser(user); MyMoneySeqAccessMgr test = *m; testEquality(&test); } void MyMoneySeqAccessMgrTest::testEquality(const MyMoneySeqAccessMgr *t) { QCOMPARE(m->user().name(), t->user().name()); QCOMPARE(m->user().address(), t->user().address()); QCOMPARE(m->user().city(), t->user().city()); QCOMPARE(m->user().state(), t->user().state()); QCOMPARE(m->user().postcode(), t->user().postcode()); QCOMPARE(m->user().telephone(), t->user().telephone()); QCOMPARE(m->user().email(), t->user().email()); QCOMPARE(m->m_nextInstitutionID, t->m_nextInstitutionID); QCOMPARE(m->m_nextAccountID, t->m_nextAccountID); QCOMPARE(m->m_nextTransactionID, t->m_nextTransactionID); QCOMPARE(m->m_nextPayeeID, t->m_nextPayeeID); QCOMPARE(m->m_nextTagID, t->m_nextTagID); QCOMPARE(m->m_nextScheduleID, t->m_nextScheduleID); QCOMPARE(m->m_dirty, t->m_dirty); QCOMPARE(m->m_creationDate, t->m_creationDate); QCOMPARE(m->m_lastModificationDate, t->m_lastModificationDate); /* * make sure, that the keys and values are the same * on the left and the right side */ QCOMPARE(m->m_payeeList.keys(), t->m_payeeList.keys()); QCOMPARE(m->m_payeeList.values(), t->m_payeeList.values()); QCOMPARE(m->m_tagList.keys(), t->m_tagList.keys()); QCOMPARE(m->m_tagList.values(), t->m_tagList.values()); QCOMPARE(m->m_transactionKeys.keys(), t->m_transactionKeys.keys()); QCOMPARE(m->m_transactionKeys.values(), t->m_transactionKeys.values()); QCOMPARE(m->m_institutionList.keys(), t->m_institutionList.keys()); QCOMPARE(m->m_institutionList.values(), t->m_institutionList.values()); QCOMPARE(m->m_accountList.keys(), t->m_accountList.keys()); QCOMPARE(m->m_accountList.values(), t->m_accountList.values()); QCOMPARE(m->m_transactionList.keys(), t->m_transactionList.keys()); QCOMPARE(m->m_transactionList.values(), t->m_transactionList.values()); // QCOMPARE(m->m_scheduleList.keys(), t->m_scheduleList.keys()); // QCOMPARE(m->m_scheduleList.values(), t->m_scheduleList.values()); } void MyMoneySeqAccessMgrTest::testDuplicate() { const MyMoneySeqAccessMgr* t; testModifyTransaction(); t = m->duplicate(); testEquality(t); delete t; } void MyMoneySeqAccessMgrTest::testAddSchedule() { /* Note addSchedule() now calls validate as it should * so we need an account id. Later this will * be checked to make sure its a valid account id. The * tests currently fail because no splits are defined * for the schedules transaction. */ try { QCOMPARE(m->m_scheduleList.count(), 0); MyMoneyTransaction t1; MyMoneySplit s1, s2; s1.setAccountId("A000001"); t1.addSplit(s1); s2.setAccountId("A000002"); t1.addSplit(s2); MyMoneySchedule schedule("Sched-Name", Schedule::Type::Deposit, Schedule::Occurrence::Daily, 1, Schedule::PaymentType::ManualDeposit, QDate(), QDate(), true, false); t1.setPostDate(QDate(2003, 7, 10)); schedule.setTransaction(t1); m->addSchedule(schedule); QCOMPARE(m->m_scheduleList.count(), 1); QCOMPARE(schedule.id(), QLatin1String("SCH000001")); QCOMPARE(m->m_scheduleList["SCH000001"].id(), QLatin1String("SCH000001")); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } try { MyMoneySchedule schedule("Sched-Name", Schedule::Type::Deposit, Schedule::Occurrence::Daily, 1, Schedule::PaymentType::ManualDeposit, QDate(), QDate(), true, false); m->addSchedule(schedule); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } } void MyMoneySeqAccessMgrTest::testSchedule() { testAddSchedule(); MyMoneySchedule sched; sched = m->schedule("SCH000001"); QCOMPARE(sched.name(), QLatin1String("Sched-Name")); QCOMPARE(sched.id(), QLatin1String("SCH000001")); try { m->schedule("SCH000002"); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } } void MyMoneySeqAccessMgrTest::testModifySchedule() { testAddSchedule(); MyMoneySchedule sched; sched = m->schedule("SCH000001"); sched.setId("SCH000002"); try { m->modifySchedule(sched); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } sched = m->schedule("SCH000001"); sched.setName("New Sched-Name"); try { m->modifySchedule(sched); QCOMPARE(m->m_scheduleList.count(), 1); QCOMPARE(m->m_scheduleList["SCH000001"].name(), QLatin1String("New Sched-Name")); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } } void MyMoneySeqAccessMgrTest::testRemoveSchedule() { testAddSchedule(); m->commitTransaction(); m->startTransaction(); MyMoneySchedule sched; sched = m->schedule("SCH000001"); sched.setId("SCH000002"); try { m->removeSchedule(sched); m->commitTransaction(); QFAIL("Exception expected"); } catch (const MyMoneyException &) { m->rollbackTransaction(); } m->startTransaction(); sched = m->schedule("SCH000001"); try { m->removeSchedule(sched); m->commitTransaction(); QCOMPARE(m->m_scheduleList.count(), 0); } catch (const MyMoneyException &) { m->rollbackTransaction(); QFAIL("Unexpected exception"); } m->startTransaction(); } void MyMoneySeqAccessMgrTest::testScheduleList() { QDate testDate = QDate::currentDate(); QDate notOverdue = testDate.addDays(2); QDate overdue = testDate.addDays(-2); MyMoneyTransaction t1; MyMoneySplit s1, s2; s1.setAccountId("A000001"); t1.addSplit(s1); s2.setAccountId("A000002"); t1.addSplit(s2); MyMoneySchedule schedule1("Schedule 1", Schedule::Type::Bill, Schedule::Occurrence::Once, 1, Schedule::PaymentType::DirectDebit, QDate(), QDate(), false, false); t1.setPostDate(notOverdue); schedule1.setTransaction(t1); schedule1.setLastPayment(notOverdue); MyMoneyTransaction t2; MyMoneySplit s3, s4; s3.setAccountId("A000001"); t2.addSplit(s3); s4.setAccountId("A000003"); t2.addSplit(s4); MyMoneySchedule schedule2("Schedule 2", Schedule::Type::Deposit, Schedule::Occurrence::Daily, 1, Schedule::PaymentType::DirectDeposit, QDate(), QDate(), false, false); t2.setPostDate(notOverdue.addDays(1)); schedule2.setTransaction(t2); schedule2.setLastPayment(notOverdue.addDays(1)); MyMoneyTransaction t3; MyMoneySplit s5, s6; s5.setAccountId("A000005"); t3.addSplit(s5); s6.setAccountId("A000006"); t3.addSplit(s6); MyMoneySchedule schedule3("Schedule 3", Schedule::Type::Transfer, Schedule::Occurrence::Weekly, 1, Schedule::PaymentType::Other, QDate(), QDate(), false, false); t3.setPostDate(notOverdue.addDays(2)); schedule3.setTransaction(t3); schedule3.setLastPayment(notOverdue.addDays(2)); MyMoneyTransaction t4; MyMoneySplit s7, s8; s7.setAccountId("A000005"); t4.addSplit(s7); s8.setAccountId("A000006"); t4.addSplit(s8); MyMoneySchedule schedule4("Schedule 4", Schedule::Type::Bill, Schedule::Occurrence::Weekly, 1, Schedule::PaymentType::WriteChecque, QDate(), notOverdue.addDays(31), false, false); t4.setPostDate(overdue.addDays(-7)); schedule4.setTransaction(t4); try { m->addSchedule(schedule1); m->addSchedule(schedule2); m->addSchedule(schedule3); m->addSchedule(schedule4); } catch (const MyMoneyException &e) { qDebug("Error: %s", qPrintable(e.what())); QFAIL("Unexpected exception"); } QList list; // no filter list = m->scheduleList(); QCOMPARE(list.count(), 4); // filter by type list = m->scheduleList("", Schedule::Type::Bill); QCOMPARE(list.count(), 2); QCOMPARE(list[0].name(), QLatin1String("Schedule 1")); QCOMPARE(list[1].name(), QLatin1String("Schedule 4")); // filter by occurrence list = m->scheduleList("", Schedule::Type::Any, Schedule::Occurrence::Daily); QCOMPARE(list.count(), 1); QCOMPARE(list[0].name(), QLatin1String("Schedule 2")); // filter by payment type list = m->scheduleList("", Schedule::Type::Any, Schedule::Occurrence::Any, Schedule::PaymentType::DirectDeposit); QCOMPARE(list.count(), 1); QCOMPARE(list[0].name(), QLatin1String("Schedule 2")); // filter by account list = m->scheduleList("A01"); QCOMPARE(list.count(), 0); list = m->scheduleList("A000001"); QCOMPARE(list.count(), 2); list = m->scheduleList("A000002"); QCOMPARE(list.count(), 1); // filter by start date list = m->scheduleList("", Schedule::Type::Any, Schedule::Occurrence::Any, Schedule::PaymentType::Any, notOverdue.addDays(31)); QCOMPARE(list.count(), 3); QCOMPARE(list[0].name(), QLatin1String("Schedule 2")); QCOMPARE(list[1].name(), QLatin1String("Schedule 3")); QCOMPARE(list[2].name(), QLatin1String("Schedule 4")); // filter by end date list = m->scheduleList("", Schedule::Type::Any, Schedule::Occurrence::Any, Schedule::PaymentType::Any, QDate(), notOverdue.addDays(1)); QCOMPARE(list.count(), 3); QCOMPARE(list[0].name(), QLatin1String("Schedule 1")); QCOMPARE(list[1].name(), QLatin1String("Schedule 2")); QCOMPARE(list[2].name(), QLatin1String("Schedule 4")); // filter by start and end date list = m->scheduleList("", Schedule::Type::Any, Schedule::Occurrence::Any, Schedule::PaymentType::Any, notOverdue.addDays(-1), notOverdue.addDays(1)); QCOMPARE(list.count(), 2); QCOMPARE(list[0].name(), QLatin1String("Schedule 1")); QCOMPARE(list[1].name(), QLatin1String("Schedule 2")); // filter by overdue status list = m->scheduleList("", Schedule::Type::Any, Schedule::Occurrence::Any, Schedule::PaymentType::Any, QDate(), QDate(), true); QCOMPARE(list.count(), 1); QCOMPARE(list[0].name(), QLatin1String("Schedule 4")); } void MyMoneySeqAccessMgrTest::testAddCurrency() { MyMoneySecurity curr("EUR", "Euro", "?", 100, 100); QCOMPARE(m->m_currencyList.count(), 0); m->m_dirty = false; try { m->addCurrency(curr); m->commitTransaction(); m->startTransaction(); QCOMPARE(m->m_currencyList.count(), 1); QCOMPARE(m->m_currencyList["EUR"].name(), QLatin1String("Euro")); QCOMPARE(m->dirty(), true); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } m->m_dirty = false; try { m->addCurrency(curr); QFAIL("Expected exception missing"); } catch (const MyMoneyException &) { m->commitTransaction(); m->startTransaction(); QCOMPARE(m->dirty(), false); } } void MyMoneySeqAccessMgrTest::testModifyCurrency() { MyMoneySecurity curr("EUR", "Euro", "?", 100, 100); testAddCurrency(); m->m_dirty = false; curr.setName("EURO"); try { m->modifyCurrency(curr); m->commitTransaction(); m->startTransaction(); QCOMPARE(m->m_currencyList.count(), 1); QCOMPARE(m->m_currencyList["EUR"].name(), QLatin1String("EURO")); QCOMPARE(m->dirty(), true); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } m->m_dirty = false; MyMoneySecurity unknownCurr("DEM", "Deutsche Mark", "DM", 100, 100); try { m->modifyCurrency(unknownCurr); QFAIL("Expected exception missing"); } catch (const MyMoneyException &) { m->commitTransaction(); m->startTransaction(); QCOMPARE(m->dirty(), false); } } void MyMoneySeqAccessMgrTest::testRemoveCurrency() { MyMoneySecurity curr("EUR", "Euro", "?", 100, 100); testAddCurrency(); m->m_dirty = false; try { m->removeCurrency(curr); m->commitTransaction(); m->startTransaction(); QCOMPARE(m->m_currencyList.count(), 0); QCOMPARE(m->dirty(), true); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } m->m_dirty = false; MyMoneySecurity unknownCurr("DEM", "Deutsche Mark", "DM", 100, 100); try { m->removeCurrency(unknownCurr); QFAIL("Expected exception missing"); } catch (const MyMoneyException &) { m->commitTransaction(); m->startTransaction(); QCOMPARE(m->dirty(), false); } } void MyMoneySeqAccessMgrTest::testCurrency() { MyMoneySecurity curr("EUR", "Euro", "?", 100, 100); MyMoneySecurity newCurr; testAddCurrency(); m->m_dirty = false; try { newCurr = m->currency("EUR"); m->commitTransaction(); m->startTransaction(); QCOMPARE(m->dirty(), false); QCOMPARE(newCurr.id(), curr.id()); QCOMPARE(newCurr.name(), curr.name()); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } try { m->currency("DEM"); QFAIL("Expected exception missing"); } catch (const MyMoneyException &) { m->commitTransaction(); m->startTransaction(); QCOMPARE(m->dirty(), false); } } void MyMoneySeqAccessMgrTest::testCurrencyList() { QCOMPARE(m->currencyList().count(), 0); testAddCurrency(); QCOMPARE(m->currencyList().count(), 1); MyMoneySecurity unknownCurr("DEM", "Deutsche Mark", "DM", 100, 100); try { m->addCurrency(unknownCurr); m->m_dirty = false; QCOMPARE(m->m_currencyList.count(), 2); QCOMPARE(m->currencyList().count(), 2); QCOMPARE(m->dirty(), false); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } } void MyMoneySeqAccessMgrTest::testAccountList() { QList accounts; m->accountList(accounts); QCOMPARE(accounts.count(), 0); testAddNewAccount(); accounts.clear(); m->accountList(accounts); QCOMPARE(accounts.count(), 2); MyMoneyAccount a = m->account("A000001"); MyMoneyAccount b = m->account("A000002"); m->reparentAccount(b, a); accounts.clear(); m->accountList(accounts); QCOMPARE(accounts.count(), 2); } void MyMoneySeqAccessMgrTest::testLoaderFunctions() { // we don't need the transaction started by setup() here m->rollbackTransaction(); // account loader QMap amap; MyMoneyAccount acc("A0000176", MyMoneyAccount()); amap[acc.id()] = acc; m->loadAccounts(amap); QCOMPARE(m->m_accountList.values(), amap.values()); QCOMPARE(m->m_accountList.keys(), amap.keys()); QCOMPARE(m->m_nextAccountID, 176ul); // transaction loader QMap tmap; MyMoneyTransaction t("T000000108", MyMoneyTransaction()); tmap[t.id()] = t; m->loadTransactions(tmap); QCOMPARE(m->m_transactionList.values(), tmap.values()); QCOMPARE(m->m_transactionList.keys(), tmap.keys()); QCOMPARE(m->m_nextTransactionID, 108ul); // institution loader QMap imap; MyMoneyInstitution inst("I000028", MyMoneyInstitution()); imap[inst.id()] = inst; m->loadInstitutions(imap); QCOMPARE(m->m_institutionList.values(), imap.values()); QCOMPARE(m->m_institutionList.keys(), imap.keys()); QCOMPARE(m->m_nextInstitutionID, 28ul); // payee loader QMap pmap; MyMoneyPayee p("P1234", MyMoneyPayee()); pmap[p.id()] = p; m->loadPayees(pmap); QCOMPARE(m->m_payeeList.values(), pmap.values()); QCOMPARE(m->m_payeeList.keys(), pmap.keys()); QCOMPARE(m->m_nextPayeeID, 1234ul); // tag loader QMap tamap; MyMoneyTag ta("G1234", MyMoneyTag()); tamap[ta.id()] = ta; m->loadTags(tamap); QCOMPARE(m->m_tagList.values(), tamap.values()); QCOMPARE(m->m_tagList.keys(), tamap.keys()); QCOMPARE(m->m_nextTagID, 1234ul); // security loader QMap smap; MyMoneySecurity s("S54321", MyMoneySecurity()); smap[s.id()] = s; m->loadSecurities(smap); QCOMPARE(m->m_securitiesList.values(), smap.values()); QCOMPARE(m->m_securitiesList.keys(), smap.keys()); QCOMPARE(m->m_nextSecurityID, 54321ul); // schedule loader QMap schmap; MyMoneySchedule sch("SCH6789", MyMoneySchedule()); schmap[sch.id()] = sch; m->loadSchedules(schmap); QCOMPARE(m->m_scheduleList.values(), schmap.values()); QCOMPARE(m->m_scheduleList.keys(), schmap.keys()); QCOMPARE(m->m_nextScheduleID, 6789ul); // report loader QMap rmap; MyMoneyReport r("R1298", MyMoneyReport()); rmap[r.id()] = r; m->loadReports(rmap); QCOMPARE(m->m_reportList.values(), rmap.values()); QCOMPARE(m->m_reportList.keys(), rmap.keys()); QCOMPARE(m->m_nextReportID, 1298ul); // budget loader QMap bmap; MyMoneyBudget b("B89765", MyMoneyBudget()); bmap[b.id()] = b; m->loadBudgets(bmap); QCOMPARE(m->m_budgetList.values(), bmap.values()); QCOMPARE(m->m_budgetList.keys(), bmap.keys()); QCOMPARE(m->m_nextBudgetID, 89765ul); // restart a transaction so that teardown() is happy m->startTransaction(); } void MyMoneySeqAccessMgrTest::testAddOnlineJob() { // Add a onlineJob onlineJob job(new dummyTask()); m->addOnlineJob(job); QCOMPARE(job.id(), QString("O000001")); m->commitTransaction(); m->startTransaction(); QCOMPARE(m->m_nextOnlineJobID, 1ul); QCOMPARE(m->dirty(), true); QCOMPARE(m->m_onlineJobList.count(), 1); QVERIFY(! m->m_onlineJobList["O000001"].isNull()); } diff --git a/kmymoney/mymoney/storage/tests/mymoneyseqaccessmgr-test.h b/kmymoney/mymoney/storage/tests/mymoneyseqaccessmgr-test.h index 5879f5380..77a7b4c3f 100644 --- a/kmymoney/mymoney/storage/tests/mymoneyseqaccessmgr-test.h +++ b/kmymoney/mymoney/storage/tests/mymoneyseqaccessmgr-test.h @@ -1,87 +1,87 @@ /*************************************************************************** mymoneyseqaccessmgrtest.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 MYMONEYSEQACCESSMGRTEST_H #define MYMONEYSEQACCESSMGRTEST_H -#include +#include #define KMM_MYMONEY_UNIT_TESTABLE friend class MyMoneySeqAccessMgrTest; #include "mymoneyobject.h" #include "mymoneyseqaccessmgr.h" class MyMoneySeqAccessMgrTest : public QObject { Q_OBJECT public: void testAccount(); protected: MyMoneySeqAccessMgr *m; private slots: void init(); void cleanup(); void testEmptyConstructor(); void testSetFunctions(); void testIsStandardAccount(); void testNewAccount(); void testAddNewAccount(); void testAddInstitution(); void testInstitution(); void testAccount2Institution(); void testModifyAccount(); void testModifyInstitution(); void testReparentAccount(); void testAddTransactions(); void testTransactionCount(); void testBalance(); void testModifyTransaction(); void testRemoveUnusedAccount(); void testRemoveUsedAccount(); void testRemoveInstitution(); void testRemoveTransaction(); void testTransactionList(); void testAddPayee(); void testSetAccountName(); void testModifyPayee(); void testPayeeName(); void testRemovePayee(); void testAddTag(); void testModifyTag(); void testTagName(); void testRemoveTag(); void testRemoveAccountFromTree(); void testAssignment(); void testEquality(const MyMoneySeqAccessMgr* t); void testDuplicate(); void testAddSchedule(); void testSchedule(); void testModifySchedule(); void testRemoveSchedule(); void testSupportFunctions(); void testScheduleList(); void testAddCurrency(); void testModifyCurrency(); void testRemoveCurrency(); void testCurrency(); void testCurrencyList(); void testAccountList(); void testLoaderFunctions(); void testAddOnlineJob(); }; #endif diff --git a/kmymoney/mymoney/tests/mymoneyaccount-test.cpp b/kmymoney/mymoney/tests/mymoneyaccount-test.cpp index e1c58314e..3d11583c1 100644 --- a/kmymoney/mymoney/tests/mymoneyaccount-test.cpp +++ b/kmymoney/mymoney/tests/mymoneyaccount-test.cpp @@ -1,566 +1,566 @@ /*************************************************************************** mymoneyaccounttest.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 "mymoneyaccount-test.h" -#include +#include #define KMM_MYMONEY_UNIT_TESTABLE friend class MyMoneyAccountTest; #include "mymoneymoney.h" #include "mymoneyaccount.h" #include "mymoneysplit.h" #include "mymoneyexception.h" QTEST_GUILESS_MAIN(MyMoneyAccountTest) void MyMoneyAccountTest::init() { } void MyMoneyAccountTest::cleanup() { } void MyMoneyAccountTest::testEmptyConstructor() { MyMoneyAccount a; QVERIFY(a.id().isEmpty()); QVERIFY(a.name().isEmpty()); QVERIFY(a.accountType() == eMyMoney::Account::Unknown); QVERIFY(a.openingDate() == QDate()); QVERIFY(a.lastModified() == QDate()); QVERIFY(a.lastReconciliationDate() == QDate()); QVERIFY(a.accountList().count() == 0); QVERIFY(a.balance().isZero()); } void MyMoneyAccountTest::testConstructor() { QString id = "A000001"; QString institutionid = "B000001"; QString parent = "Parent"; MyMoneyAccount r; MyMoneySplit s; r.setAccountType(eMyMoney::Account::Asset); r.setOpeningDate(QDate::currentDate()); r.setLastModified(QDate::currentDate()); r.setDescription("Desc"); r.setNumber("465500"); r.setParentAccountId(parent); r.setValue(QString("key"), "value"); s.setShares(MyMoneyMoney::ONE); r.adjustBalance(s); QVERIFY(r.m_kvp.count() == 1); QVERIFY(r.value("key") == "value"); MyMoneyAccount a(id, r); QVERIFY(a.id() == id); QVERIFY(a.institutionId().isEmpty()); QVERIFY(a.accountType() == eMyMoney::Account::Asset); QVERIFY(a.openingDate() == QDate::currentDate()); QVERIFY(a.lastModified() == QDate::currentDate()); QVERIFY(a.number() == "465500"); QVERIFY(a.description() == "Desc"); QVERIFY(a.accountList().count() == 0); QVERIFY(a.parentAccountId() == "Parent"); QVERIFY(a.balance() == MyMoneyMoney::ONE); QMap copy; copy = r.pairs(); QVERIFY(copy.count() == 1); QVERIFY(copy[QString("key")] == "value"); } void MyMoneyAccountTest::testSetFunctions() { MyMoneyAccount a; QDate today(QDate::currentDate()); QVERIFY(a.name().isEmpty()); QVERIFY(a.lastModified() == QDate()); QVERIFY(a.description().isEmpty()); a.setName("Account"); a.setInstitutionId("Institution1"); a.setLastModified(today); a.setDescription("Desc"); a.setNumber("123456"); a.setAccountType(eMyMoney::Account::MoneyMarket); QVERIFY(a.name() == "Account"); QVERIFY(a.institutionId() == "Institution1"); QVERIFY(a.lastModified() == today); QVERIFY(a.description() == "Desc"); QVERIFY(a.number() == "123456"); QVERIFY(a.accountType() == eMyMoney::Account::MoneyMarket); } void MyMoneyAccountTest::testCopyConstructor() { QString id = "A000001"; QString institutionid = "B000001"; QString parent = "ParentAccount"; MyMoneyAccount r; r.setAccountType(eMyMoney::Account::Expense); r.setOpeningDate(QDate::currentDate()); r.setLastModified(QDate::currentDate()); r.setName("Account"); r.setInstitutionId("Inst1"); r.setDescription("Desc1"); r.setNumber("Number"); r.setParentAccountId(parent); r.setValue("Key", "Value"); MyMoneyAccount a(id, r); a.setInstitutionId(institutionid); MyMoneyAccount b(a); QVERIFY(b.name() == "Account"); QVERIFY(b.institutionId() == institutionid); QVERIFY(b.accountType() == eMyMoney::Account::Expense); QVERIFY(b.lastModified() == QDate::currentDate()); QVERIFY(b.openingDate() == QDate::currentDate()); QVERIFY(b.description() == "Desc1"); QVERIFY(b.number() == "Number"); QVERIFY(b.parentAccountId() == "ParentAccount"); QVERIFY(b.value("Key") == "Value"); } void MyMoneyAccountTest::testAssignmentConstructor() { MyMoneyAccount a; a.setAccountType(eMyMoney::Account::Checkings); a.setName("Account"); a.setInstitutionId("Inst1"); a.setDescription("Bla"); a.setNumber("assigned Number"); a.setValue("Key", "Value"); a.addAccountId("ChildAccount"); MyMoneyAccount b; b.setLastModified(QDate::currentDate()); b = a; QVERIFY(b.name() == "Account"); QVERIFY(b.institutionId() == "Inst1"); QVERIFY(b.accountType() == eMyMoney::Account::Checkings); QVERIFY(b.lastModified() == QDate()); QVERIFY(b.openingDate() == a.openingDate()); QVERIFY(b.description() == "Bla"); QVERIFY(b.number() == "assigned Number"); QVERIFY(b.value("Key") == "Value"); QVERIFY(b.accountList().count() == 1); QVERIFY(b.accountList()[0] == "ChildAccount"); } void MyMoneyAccountTest::testAdjustBalance() { MyMoneyAccount a; MyMoneySplit s; s.setShares(MyMoneyMoney(3, 1)); a.adjustBalance(s); QVERIFY(a.balance() == MyMoneyMoney(3, 1)); s.setShares(MyMoneyMoney(5, 1)); a.adjustBalance(s, true); QVERIFY(a.balance() == MyMoneyMoney(-2, 1)); s.setShares(MyMoneyMoney(2, 1)); s.setAction(MyMoneySplit::ActionSplitShares); a.adjustBalance(s); QVERIFY(a.balance() == MyMoneyMoney(-4, 1)); s.setShares(MyMoneyMoney(4, 1)); s.setAction(QString()); a.adjustBalance(s); QVERIFY(a.balance().isZero()); } void MyMoneyAccountTest::testSubAccounts() { MyMoneyAccount a; a.setAccountType(eMyMoney::Account::Checkings); a.addAccountId("Subaccount1"); QVERIFY(a.accountList().count() == 1); a.addAccountId("Subaccount1"); QVERIFY(a.accountList().count() == 1); a.addAccountId("Subaccount2"); QVERIFY(a.accountList().count() == 2); } void MyMoneyAccountTest::testEquality() { MyMoneyAccount a; a.setLastModified(QDate::currentDate()); a.setName("Name"); a.setNumber("Number"); a.setDescription("Desc"); a.setInstitutionId("I-ID"); a.setOpeningDate(QDate::currentDate()); a.setLastReconciliationDate(QDate::currentDate()); a.setAccountType(eMyMoney::Account::Asset); a.setParentAccountId("P-ID"); a.setId("A-ID"); a.setCurrencyId("C-ID"); a.setValue("Key", "Value"); MyMoneyAccount b; b = a; QVERIFY(b == a); a.setName("Noname"); QVERIFY(!(b == a)); b = a; a.setLastModified(QDate::currentDate().addDays(-1)); QVERIFY(!(b == a)); b = a; a.setNumber("Nonumber"); QVERIFY(!(b == a)); b = a; a.setDescription("NoDesc"); QVERIFY(!(b == a)); b = a; a.setInstitutionId("I-noID"); QVERIFY(!(b == a)); b = a; a.setOpeningDate(QDate::currentDate().addDays(-1)); QVERIFY(!(b == a)); b = a; a.setLastReconciliationDate(QDate::currentDate().addDays(-1)); QVERIFY(!(b == a)); b = a; a.setAccountType(eMyMoney::Account::Liability); QVERIFY(!(b == a)); b = a; a.setParentAccountId("P-noID"); QVERIFY(!(b == a)); b = a; a.setId("A-noID"); QVERIFY(!(b == a)); b = a; a.setCurrencyId("C-noID"); QVERIFY(!(b == a)); b = a; a.setValue("Key", "noValue"); QVERIFY(!(b == a)); b = a; a.setValue("noKey", "Value"); QVERIFY(!(b == a)); b = a; } void MyMoneyAccountTest::testWriteXML() { QString id = "A000001"; QString institutionid = "B000001"; QString parent = "Parent"; MyMoneyAccount r; r.setAccountType(eMyMoney::Account::Asset); r.setOpeningDate(QDate::currentDate()); r.setLastModified(QDate::currentDate()); r.setDescription("Desc"); r.setName("AccountName"); r.setNumber("465500"); r.setParentAccountId(parent); r.setInstitutionId(institutionid); r.setValue(QString("key"), "value"); r.addAccountId("A000002"); r.addReconciliation(QDate(2011, 1, 1), MyMoneyMoney(123, 100)); r.addReconciliation(QDate(2011, 2, 1), MyMoneyMoney(456, 100)); QCOMPARE(r.m_kvp.count(), 2); QCOMPARE(r.value("key"), QLatin1String("value")); QCOMPARE(r.value("reconciliationHistory"), QLatin1String("2011-01-01:123/100;2011-02-01:114/25")); MyMoneyAccount a(id, r); QDomDocument doc("TEST"); QDomElement el = doc.createElement("ACCOUNT-CONTAINER"); doc.appendChild(el); a.writeXML(doc, el); QCOMPARE(doc.doctype().name(), QLatin1String("TEST")); QDomElement accountContainer = doc.documentElement(); QVERIFY(accountContainer.isElement()); QCOMPARE(accountContainer.tagName(), QLatin1String("ACCOUNT-CONTAINER")); QVERIFY(accountContainer.childNodes().size() == 1); QVERIFY(accountContainer.childNodes().at(0).isElement()); QDomElement account = accountContainer.childNodes().at(0).toElement(); QCOMPARE(account.tagName(), QLatin1String("ACCOUNT")); QCOMPARE(account.attribute("id"), QLatin1String("A000001")); QCOMPARE(account.attribute("lastreconciled"), QString()); QCOMPARE(account.attribute("institution"), QLatin1String("B000001")); QCOMPARE(account.attribute("name"), QLatin1String("AccountName")); QCOMPARE(account.attribute("number"), QLatin1String("465500")); QCOMPARE(account.attribute("description"), QLatin1String("Desc")); QCOMPARE(account.attribute("parentaccount"), QLatin1String("Parent")); QCOMPARE(account.attribute("opened"), QDate::currentDate().toString(Qt::ISODate)); QCOMPARE(account.attribute("type"), QLatin1String("9")); QCOMPARE(account.attribute("lastmodified"), QDate::currentDate().toString(Qt::ISODate)); QCOMPARE(account.attribute("id"), QLatin1String("A000001")); QCOMPARE(account.childNodes().size(), 2); QVERIFY(account.childNodes().at(0).isElement()); QDomElement subAccounts = account.childNodes().at(0).toElement(); QCOMPARE(subAccounts.tagName(), QLatin1String("SUBACCOUNTS")); QCOMPARE(subAccounts.childNodes().size(), 1); QVERIFY(subAccounts.childNodes().at(0).isElement()); QDomElement subAccount = subAccounts.childNodes().at(0).toElement(); QCOMPARE(subAccount.tagName(), QLatin1String("SUBACCOUNT")); QCOMPARE(subAccount.attribute("id"), QLatin1String("A000002")); QCOMPARE(subAccount.childNodes().size(), 0); QDomElement keyValuePairs = account.childNodes().at(1).toElement(); QCOMPARE(keyValuePairs.tagName(), QLatin1String("KEYVALUEPAIRS")); QCOMPARE(keyValuePairs.childNodes().size(), 2); QVERIFY(keyValuePairs.childNodes().at(0).isElement()); QDomElement keyValuePair1 = keyValuePairs.childNodes().at(0).toElement(); QCOMPARE(keyValuePair1.tagName(), QLatin1String("PAIR")); QCOMPARE(keyValuePair1.attribute("key"), QLatin1String("key")); QCOMPARE(keyValuePair1.attribute("value"), QLatin1String("value")); QCOMPARE(keyValuePair1.childNodes().size(), 0); QVERIFY(keyValuePairs.childNodes().at(1).isElement()); QDomElement keyValuePair2 = keyValuePairs.childNodes().at(1).toElement(); QCOMPARE(keyValuePair2.tagName(), QLatin1String("PAIR")); QCOMPARE(keyValuePair2.attribute("key"), QLatin1String("reconciliationHistory")); QCOMPARE(keyValuePair2.attribute("value"), QLatin1String("2011-01-01:123/100;2011-02-01:114/25")); QCOMPARE(keyValuePair2.childNodes().size(), 0); } void MyMoneyAccountTest::testReadXML() { MyMoneyAccount a; QString ref_ok = QString( "\n" "\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "\n"). arg(QDate::currentDate().toString(Qt::ISODate)).arg(QDate::currentDate().toString(Qt::ISODate)); QString ref_false = QString( "\n" "\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "\n"). arg(QDate::currentDate().toString(Qt::ISODate)).arg(QDate::currentDate().toString(Qt::ISODate)); QDomDocument doc; QDomElement node; doc.setContent(ref_false); node = doc.documentElement().firstChild().toElement(); try { a = MyMoneyAccount(node); QFAIL("Missing expected exception"); } catch (const MyMoneyException &) { } doc.setContent(ref_ok); node = doc.documentElement().firstChild().toElement(); a.addAccountId("TEST"); a.setValue("KEY", "VALUE"); try { a = MyMoneyAccount(node); QVERIFY(a.id() == "A000001"); QVERIFY(a.name() == "AccountName"); QVERIFY(a.parentAccountId() == "Parent"); QVERIFY(a.lastModified() == QDate::currentDate()); QVERIFY(a.lastReconciliationDate() == QDate()); QVERIFY(a.institutionId() == "B000001"); QVERIFY(a.number() == "465500"); QVERIFY(a.openingDate() == QDate::currentDate()); QVERIFY(a.accountType() == eMyMoney::Account::Asset); QVERIFY(a.description() == "Desc"); QVERIFY(a.accountList().count() == 2); QVERIFY(a.accountList()[0] == "A000002"); QVERIFY(a.accountList()[1] == "A000003"); QVERIFY(a.pairs().count() == 4); QVERIFY(a.value("key") == "value"); QVERIFY(a.value("Key") == "Value"); QVERIFY(a.value("lastStatementDate").isEmpty()); QVERIFY(a.reconciliationHistory().count() == 2); QVERIFY(a.reconciliationHistory()[QDate(2011, 1, 1)] == MyMoneyMoney(123, 100)); QVERIFY(a.reconciliationHistory()[QDate(2011, 2, 1)] == MyMoneyMoney(456, 100)); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } } void MyMoneyAccountTest::testHasReferenceTo() { MyMoneyAccount a; a.setInstitutionId("I0001"); a.addAccountId("A_001"); a.addAccountId("A_002"); a.setParentAccountId("A_Parent"); a.setCurrencyId("Currency"); QVERIFY(a.hasReferenceTo("I0001") == true); QVERIFY(a.hasReferenceTo("I0002") == false); QVERIFY(a.hasReferenceTo("A_001") == false); QVERIFY(a.hasReferenceTo("A_Parent") == true); QVERIFY(a.hasReferenceTo("Currency") == true); } void MyMoneyAccountTest::testSetClosed() { MyMoneyAccount a; QVERIFY(a.isClosed() == false); a.setClosed(true); QVERIFY(a.isClosed() == true); a.setClosed(false); QVERIFY(a.isClosed() == false); } void MyMoneyAccountTest::specialAccountTypes_data() { QTest::addColumn("accountType"); QTest::addColumn("incomeExpense"); QTest::addColumn("assetLibility"); QTest::addColumn("loan"); // positive and null is debit QTest::newRow("unknown") << eMyMoney::Account::Unknown << false << false << false; QTest::newRow("checking") << eMyMoney::Account::Checkings << false << true << false; QTest::newRow("savings") << eMyMoney::Account::Savings << false << true << false; QTest::newRow("cash") << eMyMoney::Account::Cash << false << true << false; QTest::newRow("investment") << eMyMoney::Account::Investment << false << true << false; QTest::newRow("asset") << eMyMoney::Account::Asset << false << true << false; QTest::newRow("currency") << eMyMoney::Account::Currency << false << true << false; QTest::newRow("expense") << eMyMoney::Account::Expense << true << false << false; QTest::newRow("moneymarket") << eMyMoney::Account::MoneyMarket << false << true << false; QTest::newRow("certificatedeposit") << eMyMoney::Account::CertificateDep << false << true << false; QTest::newRow("assetloan") << eMyMoney::Account::AssetLoan << false << true << true; QTest::newRow("stock") << eMyMoney::Account::Stock << false << true << false; QTest::newRow("creditcard") << eMyMoney::Account::CreditCard << false << true << false; QTest::newRow("loan") << eMyMoney::Account::Loan << false << true << true; QTest::newRow("liability") << eMyMoney::Account::Liability << false << true << false; QTest::newRow("income") << eMyMoney::Account::Income << true << false << false; QTest::newRow("equity") << eMyMoney::Account::Equity << false << false << false; } void MyMoneyAccountTest::specialAccountTypes() { QFETCH(eMyMoney::Account, accountType); QFETCH(bool, incomeExpense); QFETCH(bool, assetLibility); QFETCH(bool, loan); MyMoneyAccount a; a.setAccountType(accountType); QCOMPARE(a.isIncomeExpense(), incomeExpense); QCOMPARE(a.isAssetLiability(), assetLibility); QCOMPARE(a.isLoan(), loan); } void MyMoneyAccountTest::addReconciliation() { MyMoneyAccount a; QVERIFY(a.addReconciliation(QDate(2011, 1, 2), MyMoneyMoney(123, 100)) == true); QVERIFY(a.reconciliationHistory().count() == 1); QVERIFY(a.addReconciliation(QDate(2011, 2, 1), MyMoneyMoney(456, 100)) == true); QVERIFY(a.reconciliationHistory().count() == 2); QVERIFY(a.addReconciliation(QDate(2011, 2, 1), MyMoneyMoney(789, 100)) == true); QVERIFY(a.reconciliationHistory().count() == 2); QVERIFY(a.reconciliationHistory().values().last() == MyMoneyMoney(789, 100)); } void MyMoneyAccountTest::reconciliationHistory() { MyMoneyAccount a; QVERIFY(a.reconciliationHistory().isEmpty() == true); QVERIFY(a.addReconciliation(QDate(2011, 1, 2), MyMoneyMoney(123, 100)) == true); QVERIFY(a.reconciliationHistory()[QDate(2011, 1, 2)] == MyMoneyMoney(123, 100)); QVERIFY(a.reconciliationHistory()[QDate(2011, 1, 1)] == MyMoneyMoney()); QVERIFY(a.reconciliationHistory()[QDate(2011, 1, 3)] == MyMoneyMoney()); QVERIFY(a.addReconciliation(QDate(2011, 2, 1), MyMoneyMoney(456, 100)) == true); QVERIFY(a.reconciliationHistory()[QDate(2011, 1, 2)] == MyMoneyMoney(123, 100)); QVERIFY(a.reconciliationHistory()[QDate(2011, 1, 1)] == MyMoneyMoney()); QVERIFY(a.reconciliationHistory()[QDate(2011, 1, 3)] == MyMoneyMoney()); QVERIFY(a.reconciliationHistory()[QDate(2011, 2, 1)] == MyMoneyMoney(456, 100)); QVERIFY(a.reconciliationHistory().count() == 2); } void MyMoneyAccountTest::testElementNames() { for (auto i = (int)MyMoneyAccount::Element::SubAccount; i <= (int)MyMoneyAccount::Element::OnlineBanking; ++i) { auto isEmpty = MyMoneyAccount::getElName(static_cast(i)).isEmpty(); if (isEmpty) qWarning() << "Empty element's name " << i; QVERIFY(!isEmpty); } } void MyMoneyAccountTest::testAttributeNames() { for (auto i = (int)MyMoneyAccount::Attribute::ID; i < (int)MyMoneyAccount::Attribute::LastAttribute; ++i) { auto isEmpty = MyMoneyAccount::getAttrName(static_cast(i)).isEmpty(); if (isEmpty) qWarning() << "Empty attribute's name " << i; QVERIFY(!isEmpty); } } diff --git a/kmymoney/mymoney/tests/mymoneyaccount-test.h b/kmymoney/mymoney/tests/mymoneyaccount-test.h index c9aad9eaf..682ae1568 100644 --- a/kmymoney/mymoney/tests/mymoneyaccount-test.h +++ b/kmymoney/mymoney/tests/mymoneyaccount-test.h @@ -1,54 +1,54 @@ /*************************************************************************** mymoneyaccounttest.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 MYMONEYACCOUNTTEST_H #define MYMONEYACCOUNTTEST_H -#include +#include class MyMoneyAccount; class MyMoneyAccountTest : public QObject { Q_OBJECT protected: MyMoneyAccount *m; private slots: void init(); void cleanup(); void testEmptyConstructor(); void testConstructor(); void testSetFunctions(); void testCopyConstructor(); void testAssignmentConstructor(); void testSubAccounts(); void testEquality(); void testWriteXML(); void testReadXML(); void testHasReferenceTo(); void testAdjustBalance(); void testSetClosed(); void specialAccountTypes(); void specialAccountTypes_data(); void addReconciliation(); void reconciliationHistory(); void testElementNames(); void testAttributeNames(); }; #endif diff --git a/kmymoney/mymoney/tests/mymoneybalancecache-test.cpp b/kmymoney/mymoney/tests/mymoneybalancecache-test.cpp index 33bcb0b8e..8c39cb7a4 100644 --- a/kmymoney/mymoney/tests/mymoneybalancecache-test.cpp +++ b/kmymoney/mymoney/tests/mymoneybalancecache-test.cpp @@ -1,165 +1,165 @@ /*************************************************************************** mymoneybalancecachetest - description ------------------- begin : Tue Sep 21 2010 copyright : (C) 2010 by Fernando Vilas email : kmymoney-devel@kde.org ***************************************************************************/ /*************************************************************************** * * * 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 "mymoneybalancecache-test.h" -#include +#include -#include +#include #include "mymoneytestutils.h" #include "mymoneybalancecache.h" QTEST_GUILESS_MAIN(MyMoneyBalanceCacheTest) void MyMoneyBalanceCacheTest::init() { m = new MyMoneyBalanceCache(); } void MyMoneyBalanceCacheTest::cleanup() { delete m; } void MyMoneyBalanceCacheTest::testCacheItem() { MyMoneyBalanceCacheItem item(MyMoneyMoney(10, 100), QDate(2010, 9, 18)); MyMoneyBalanceCacheItem invalid(MyMoneyMoney::minValue, QDate()); //MyMoneyBalanceCacheItem noarg; QVERIFY(item.balance() == MyMoneyMoney(10, 100)); QVERIFY(item.date() == QDate(2010, 9, 18)); QVERIFY(item.isValid()); QVERIFY(! invalid.isValid()); //QVERIFY(! noarg.isValid()); } void MyMoneyBalanceCacheTest::testEmpty() { QVERIFY(m->isEmpty()); testInsert(); QVERIFY(! m->isEmpty()); } void MyMoneyBalanceCacheTest::testInsert() { m->insert("A000001", QDate(2010, 9, 16), MyMoneyMoney(10, 100)); // The next 2 lines have the same date and account. // This is intentional to see that the balance for that // account and date gets overwritten. m->insert("A000001", QDate(2010, 9, 18), MyMoneyMoney(15, 100)); m->insert("A000001", QDate(2010, 9, 18), MyMoneyMoney(20, 100)); m->insert("A000002", QDate(2010, 9, 17), MyMoneyMoney(30, 100)); m->insert("A000002", QDate(2010, 9, 19), MyMoneyMoney(40, 100)); } void MyMoneyBalanceCacheTest::testClear() { QVERIFY(m->size() == 0); testInsert(); QVERIFY(m->size() == 4); // Delete an item that is not in the cache. The cache should // be unaffected. m->clear("A000003", QDate(2010, 9, 17)); QVERIFY(m->size() == 4); // Now delete a value before the last one in the account. // All values after it should also be gone. m->clear("A000001", QDate(2010, 9, 17)); QVERIFY(m->size() == 3); // Verify that the items not deleted still exist m->clear("A000001"); QVERIFY(m->size() == 2); m->clear(); QVERIFY(m->size() == 0); // Verify that searching for something not in the list is safe try { m->clear("A000001"); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } } void MyMoneyBalanceCacheTest::testSize() { QVERIFY(m->size() == 0); testInsert(); QVERIFY(m->size() == 4); } void MyMoneyBalanceCacheTest::testRetrieve() { testInsert(); MyMoneyBalanceCacheItem item = m->balance("A000003", QDate(2010, 9, 17)); QVERIFY(! item.isValid()); item = m->balance("A000001", QDate(2010, 9, 16)); QVERIFY(item.isValid()); QVERIFY(item.balance() == MyMoneyMoney(10, 100)); QVERIFY(item.date() == QDate(2010, 9, 16)); item = m->balance("A000001", QDate(2010, 9, 17)); QVERIFY(! item.isValid()); item = m->balance("A000001", QDate(2010, 9, 18)); QVERIFY(item.isValid()); QVERIFY(item.balance() == MyMoneyMoney(20, 100)); QVERIFY(item.date() == QDate(2010, 9, 18)); // Test bad acct item = m->mostRecentBalance("A000003", QDate(2010, 9, 17)); QVERIFY(! item.isValid()); // Test date too old item = m->mostRecentBalance("A000001", QDate(2010, 9, 15)); QVERIFY(!item.isValid()); // Test date found item = m->mostRecentBalance("A000001", QDate(2010, 9, 16)); QVERIFY(item.isValid()); QVERIFY(item.balance() == MyMoneyMoney(10, 100)); QVERIFY(item.date() == QDate(2010, 9, 16)); // Test date in between item = m->mostRecentBalance("A000001", QDate(2010, 9, 17)); QVERIFY(item.isValid()); QVERIFY(item.balance() == MyMoneyMoney(10, 100)); QVERIFY(item.date() == QDate(2010, 9, 16)); // Test date found item = m->mostRecentBalance("A000001", QDate(2010, 9, 18)); QVERIFY(item.isValid()); QVERIFY(item.balance() == MyMoneyMoney(20, 100)); QVERIFY(item.date() == QDate(2010, 9, 18)); // Test date later than all entries item = m->mostRecentBalance("A000001", QDate(2010, 9, 19)); QVERIFY(item.isValid()); QVERIFY(item.balance() == MyMoneyMoney(20, 100)); QVERIFY(item.date() == QDate(2010, 9, 18)); } diff --git a/kmymoney/mymoney/tests/mymoneybalancecache-test.h b/kmymoney/mymoney/tests/mymoneybalancecache-test.h index d744c0b6e..d36b6c598 100644 --- a/kmymoney/mymoney/tests/mymoneybalancecache-test.h +++ b/kmymoney/mymoney/tests/mymoneybalancecache-test.h @@ -1,43 +1,43 @@ /*************************************************************************** mymoneybalancecachetest - description ------------------- begin : Tue Sep 21 2010 copyright : (C) 2010 by Fernando Vilas email : kmymoney-devel@kde.org ***************************************************************************/ /*************************************************************************** * * * 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 MYMONEYBALANCECACHETEST_H #define MYMONEYBALANCECACHETEST_H -#include +#include #include "mymoneybalancecache.h" class MyMoneyBalanceCacheTest : public QObject { Q_OBJECT protected: MyMoneyBalanceCache* m; private slots: void init(); void cleanup(); void testCacheItem(); void testEmpty(); void testInsert(); void testClear(); void testSize(); void testRetrieve(); }; #endif diff --git a/kmymoney/mymoney/tests/mymoneybudget-test.cpp b/kmymoney/mymoney/tests/mymoneybudget-test.cpp index 59491205d..772d5bac1 100644 --- a/kmymoney/mymoney/tests/mymoneybudget-test.cpp +++ b/kmymoney/mymoney/tests/mymoneybudget-test.cpp @@ -1,294 +1,294 @@ /*************************************************************************** mymoneybudgettest.cpp ------------------- copyright : (C) 2010 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 "mymoneybudget-test.h" -#include +#include #define KMM_MYMONEY_UNIT_TESTABLE friend class MyMoneyBudgetTest; #include "mymoneymoney.h" #include "mymoneybudget.h" QTEST_GUILESS_MAIN(MyMoneyBudgetTest) void MyMoneyBudgetTest::init() { } void MyMoneyBudgetTest::cleanup() { } void MyMoneyBudgetTest::addMonthlyToMonthly() { MyMoneyBudget::AccountGroup a0, a1; a0.setBudgetLevel(MyMoneyBudget::AccountGroup::eMonthly); a1.setBudgetLevel(MyMoneyBudget::AccountGroup::eMonthly); MyMoneyBudget::PeriodGroup period; period.setStartDate(QDate(2010, 1, 1)); period.setAmount(MyMoneyMoney(100, 1)); a0.addPeriod(QDate(2010, 1, 1), period); a1.addPeriod(QDate(2010, 1, 1), period); a0 += a1; QVERIFY(a0.budgetLevel() == MyMoneyBudget::AccountGroup::eMonthly); QVERIFY(a1.budgetLevel() == MyMoneyBudget::AccountGroup::eMonthly); QVERIFY(a0.getPeriods().count() == 1); QVERIFY(a1.getPeriods().count() == 1); QVERIFY(a0.balance() == MyMoneyMoney(200, 1)); QVERIFY(a1.balance() == MyMoneyMoney(100, 1)); } void MyMoneyBudgetTest::addMonthlyToYearly() { MyMoneyBudget::AccountGroup a0, a1; a0.setBudgetLevel(MyMoneyBudget::AccountGroup::eYearly); a1.setBudgetLevel(MyMoneyBudget::AccountGroup::eMonthly); MyMoneyBudget::PeriodGroup period; period.setStartDate(QDate(2010, 1, 1)); period.setAmount(MyMoneyMoney(100, 1)); a0.addPeriod(QDate(2010, 1, 1), period); a1.addPeriod(QDate(2010, 1, 1), period); QVERIFY(a0.totalBalance() == MyMoneyMoney(100, 1)); QVERIFY(a1.totalBalance() == MyMoneyMoney(1200, 1)); a0 += a1; QVERIFY(a0.budgetLevel() == MyMoneyBudget::AccountGroup::eYearly); QVERIFY(a1.budgetLevel() == MyMoneyBudget::AccountGroup::eMonthly); QVERIFY(a0.getPeriods().count() == 1); QVERIFY(a1.getPeriods().count() == 1); QVERIFY(a0.totalBalance() == MyMoneyMoney(1300, 1)); QVERIFY(a1.totalBalance() == MyMoneyMoney(1200, 1)); } void MyMoneyBudgetTest::addMonthlyToMonthByMonth() { MyMoneyBudget::AccountGroup a0, a1; a0.setBudgetLevel(MyMoneyBudget::AccountGroup::eMonthByMonth); a1.setBudgetLevel(MyMoneyBudget::AccountGroup::eMonthly); MyMoneyBudget::PeriodGroup period; period.setStartDate(QDate(2010, 1, 1)); period.setAmount(MyMoneyMoney(100, 1)); a1.addPeriod(QDate(2010, 1, 1), period); QDate date(2010, 1, 1); for (int i = 0; i < 12; ++i) { period.setAmount(MyMoneyMoney((i + 1) * 100, 1)); a0.addPeriod(date, period); date = date.addMonths(1); period.setStartDate(date); } QVERIFY(a0.getPeriods().count() == 12); QVERIFY(a0.totalBalance() == MyMoneyMoney(7800, 1)); QVERIFY(a1.totalBalance() == MyMoneyMoney(1200, 1)); a0 += a1; QVERIFY(a0.budgetLevel() == MyMoneyBudget::AccountGroup::eMonthByMonth); QVERIFY(a1.budgetLevel() == MyMoneyBudget::AccountGroup::eMonthly); QVERIFY(a0.getPeriods().count() == 12); QVERIFY(a1.getPeriods().count() == 1); QVERIFY(a0.totalBalance() == MyMoneyMoney(9000, 1)); QVERIFY(a1.totalBalance() == MyMoneyMoney(1200, 1)); } void MyMoneyBudgetTest::addYearlyToMonthly() { MyMoneyBudget::AccountGroup a0, a1; a0.setBudgetLevel(MyMoneyBudget::AccountGroup::eYearly); a1.setBudgetLevel(MyMoneyBudget::AccountGroup::eMonthly); MyMoneyBudget::PeriodGroup period; period.setStartDate(QDate(2010, 1, 1)); period.setAmount(MyMoneyMoney(100, 1)); a0.addPeriod(QDate(2010, 1, 1), period); a1.addPeriod(QDate(2010, 1, 1), period); QVERIFY(a0.totalBalance() == MyMoneyMoney(100, 1)); QVERIFY(a1.totalBalance() == MyMoneyMoney(1200, 1)); a1 += a0; QVERIFY(a0.budgetLevel() == MyMoneyBudget::AccountGroup::eYearly); QVERIFY(a1.budgetLevel() == MyMoneyBudget::AccountGroup::eMonthly); QVERIFY(a0.getPeriods().count() == 1); QVERIFY(a1.getPeriods().count() == 1); QVERIFY(a0.totalBalance() == MyMoneyMoney(100, 1)); QVERIFY(a1.totalBalance() == MyMoneyMoney(1300, 1)); } void MyMoneyBudgetTest::addYearlyToYearly() { MyMoneyBudget::AccountGroup a0, a1; a0.setBudgetLevel(MyMoneyBudget::AccountGroup::eYearly); a1.setBudgetLevel(MyMoneyBudget::AccountGroup::eYearly); MyMoneyBudget::PeriodGroup period; period.setStartDate(QDate(2010, 1, 1)); period.setAmount(MyMoneyMoney(100, 1)); a0.addPeriod(QDate(2010, 1, 1), period); a1.addPeriod(QDate(2010, 1, 1), period); a0 += a1; QVERIFY(a0.budgetLevel() == MyMoneyBudget::AccountGroup::eYearly); QVERIFY(a1.budgetLevel() == MyMoneyBudget::AccountGroup::eYearly); QVERIFY(a0.getPeriods().count() == 1); QVERIFY(a1.getPeriods().count() == 1); QVERIFY(a0.balance() == MyMoneyMoney(200, 1)); QVERIFY(a1.balance() == MyMoneyMoney(100, 1)); } void MyMoneyBudgetTest::addYearlyToMonthByMonth() { MyMoneyBudget::AccountGroup a0, a1; a0.setBudgetLevel(MyMoneyBudget::AccountGroup::eMonthByMonth); a1.setBudgetLevel(MyMoneyBudget::AccountGroup::eYearly); MyMoneyBudget::PeriodGroup period; period.setStartDate(QDate(2010, 1, 1)); period.setAmount(MyMoneyMoney(100, 1)); a1.addPeriod(QDate(2010, 1, 1), period); QDate date(2010, 1, 1); for (int i = 0; i < 12; ++i) { period.setAmount(MyMoneyMoney((i + 1) * 100, 1)); a0.addPeriod(date, period); date = date.addMonths(1); period.setStartDate(date); } QVERIFY(a0.getPeriods().count() == 12); QVERIFY(a0.totalBalance() == MyMoneyMoney(7800, 1)); QVERIFY(a1.totalBalance() == MyMoneyMoney(100, 1)); a0 += a1; QVERIFY(a0.budgetLevel() == MyMoneyBudget::AccountGroup::eMonthByMonth); QVERIFY(a1.budgetLevel() == MyMoneyBudget::AccountGroup::eYearly); QVERIFY(a0.getPeriods().count() == 12); QVERIFY(a1.getPeriods().count() == 1); QVERIFY(a0.totalBalance() == MyMoneyMoney(7900, 1)); QVERIFY(a1.totalBalance() == MyMoneyMoney(100, 1)); } void MyMoneyBudgetTest::addMonthByMonthToMonthly() { MyMoneyBudget::AccountGroup a0, a1; a0.setBudgetLevel(MyMoneyBudget::AccountGroup::eMonthByMonth); a1.setBudgetLevel(MyMoneyBudget::AccountGroup::eMonthly); MyMoneyBudget::PeriodGroup period; period.setStartDate(QDate(2010, 1, 1)); period.setAmount(MyMoneyMoney(100, 1)); a1.addPeriod(QDate(2010, 1, 1), period); QDate date(2010, 1, 1); for (int i = 0; i < 12; ++i) { period.setAmount(MyMoneyMoney((i + 1) * 100, 1)); a0.addPeriod(date, period); date = date.addMonths(1); period.setStartDate(date); } QVERIFY(a0.getPeriods().count() == 12); QVERIFY(a0.totalBalance() == MyMoneyMoney(7800, 1)); QVERIFY(a1.totalBalance() == MyMoneyMoney(1200, 1)); a1 += a0; QVERIFY(a0.budgetLevel() == MyMoneyBudget::AccountGroup::eMonthByMonth); QVERIFY(a1.budgetLevel() == MyMoneyBudget::AccountGroup::eMonthByMonth); QVERIFY(a0.getPeriods().count() == 12); QVERIFY(a1.getPeriods().count() == 12); QVERIFY(a0.totalBalance() == MyMoneyMoney(7800, 1)); QVERIFY(a1.totalBalance() == MyMoneyMoney(9000, 1)); } void MyMoneyBudgetTest::addMonthByMonthToYearly() { MyMoneyBudget::AccountGroup a0, a1; a0.setBudgetLevel(MyMoneyBudget::AccountGroup::eMonthByMonth); a1.setBudgetLevel(MyMoneyBudget::AccountGroup::eYearly); MyMoneyBudget::PeriodGroup period; period.setStartDate(QDate(2010, 1, 1)); period.setAmount(MyMoneyMoney(100, 1)); a1.addPeriod(QDate(2010, 1, 1), period); QDate date(2010, 1, 1); for (int i = 0; i < 12; ++i) { period.setAmount(MyMoneyMoney((i + 1) * 100, 1)); a0.addPeriod(date, period); date = date.addMonths(1); period.setStartDate(date); } QVERIFY(a0.getPeriods().count() == 12); QVERIFY(a0.totalBalance() == MyMoneyMoney(7800, 1)); QVERIFY(a1.totalBalance() == MyMoneyMoney(100, 1)); a1 += a0; QVERIFY(a0.budgetLevel() == MyMoneyBudget::AccountGroup::eMonthByMonth); QVERIFY(a1.budgetLevel() == MyMoneyBudget::AccountGroup::eMonthByMonth); QVERIFY(a0.getPeriods().count() == 12); QVERIFY(a1.getPeriods().count() == 12); QVERIFY(a0.totalBalance() == MyMoneyMoney(7800, 1)); QVERIFY(a1.totalBalance() == MyMoneyMoney(7900, 1)); } void MyMoneyBudgetTest::addMonthByMonthToMonthByMonth() { MyMoneyBudget::AccountGroup a0, a1; a0.setBudgetLevel(MyMoneyBudget::AccountGroup::eMonthByMonth); a1.setBudgetLevel(MyMoneyBudget::AccountGroup::eMonthByMonth); MyMoneyBudget::PeriodGroup period; QDate date(2010, 1, 1); for (int i = 0; i < 12; ++i) { period.setStartDate(date); period.setAmount(MyMoneyMoney((i + 1) * 100, 1)); a0.addPeriod(date, period); period.setAmount(MyMoneyMoney((i + 1) * 200, 1)); a1.addPeriod(date, period); date = date.addMonths(1); } QVERIFY(a0.getPeriods().count() == 12); QVERIFY(a1.getPeriods().count() == 12); QVERIFY(a0.totalBalance() == MyMoneyMoney(7800, 1)); QVERIFY(a1.totalBalance() == MyMoneyMoney(15600, 1)); a0 += a1; QVERIFY(a0.budgetLevel() == MyMoneyBudget::AccountGroup::eMonthByMonth); QVERIFY(a1.budgetLevel() == MyMoneyBudget::AccountGroup::eMonthByMonth); QVERIFY(a0.getPeriods().count() == 12); QVERIFY(a1.getPeriods().count() == 12); QVERIFY(a0.totalBalance() == MyMoneyMoney(23400, 1)); QVERIFY(a1.totalBalance() == MyMoneyMoney(15600, 1)); } void MyMoneyBudgetTest::testElementNames() { for (auto i = (int)MyMoneyBudget::Element::Budget; i <= (int)MyMoneyBudget::Element::Period; ++i) { auto isEmpty = MyMoneyBudget::getElName(static_cast(i)).isEmpty(); if (isEmpty) qWarning() << "Empty element's name " << i; QVERIFY(!isEmpty); } } void MyMoneyBudgetTest::testAttributeNames() { for (auto i = (int)MyMoneyBudget::Attribute::ID; i < (int)MyMoneyBudget::Attribute::LastAttribute; ++i) { auto isEmpty = MyMoneyBudget::getAttrName(static_cast(i)).isEmpty(); if (isEmpty) qWarning() << "Empty attribute's name " << i; QVERIFY(!isEmpty); } } diff --git a/kmymoney/mymoney/tests/mymoneybudget-test.h b/kmymoney/mymoney/tests/mymoneybudget-test.h index e74f2f7ac..3ec2f4b84 100644 --- a/kmymoney/mymoney/tests/mymoneybudget-test.h +++ b/kmymoney/mymoney/tests/mymoneybudget-test.h @@ -1,43 +1,43 @@ /*************************************************************************** mymoneybudgettest.h ------------------- copyright : (C) 2010 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 MYMONEYBUDGETTEST_H #define MYMONEYBUDGETTEST_H -#include +#include class MyMoneyBudgetTest : public QObject { Q_OBJECT protected: private slots: void init(); void addMonthlyToMonthly(); void addMonthlyToYearly(); void addMonthlyToMonthByMonth(); void addYearlyToMonthly(); void addYearlyToYearly(); void addYearlyToMonthByMonth(); void addMonthByMonthToMonthly(); void addMonthByMonthToYearly(); void addMonthByMonthToMonthByMonth(); void cleanup(); void testElementNames(); void testAttributeNames(); }; #endif diff --git a/kmymoney/mymoney/tests/mymoneyexception-test.cpp b/kmymoney/mymoney/tests/mymoneyexception-test.cpp index db588dd36..768e36b54 100644 --- a/kmymoney/mymoney/tests/mymoneyexception-test.cpp +++ b/kmymoney/mymoney/tests/mymoneyexception-test.cpp @@ -1,46 +1,46 @@ /*************************************************************************** mymoneyexceptiontest.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 "mymoneyexception-test.h" -#include +#include QTEST_GUILESS_MAIN(MyMoneyExceptionTest) void MyMoneyExceptionTest::init() { } void MyMoneyExceptionTest::cleanup() { } void MyMoneyExceptionTest::testDefaultConstructor() { const MyMoneyException &e = MYMONEYEXCEPTION("Message"); QVERIFY(e.what() == "Message"); QVERIFY(e.line() == __LINE__ - 2); QVERIFY(e.file() == __FILE__); } void MyMoneyExceptionTest::testConstructor() { MyMoneyException e("New message", "Joe's file", 1234); QVERIFY(e.what() == "New message"); QVERIFY(e.line() == 1234); QVERIFY(e.file() == "Joe's file"); } diff --git a/kmymoney/mymoney/tests/mymoneyexception-test.h b/kmymoney/mymoney/tests/mymoneyexception-test.h index 999fa406e..f74e62255 100644 --- a/kmymoney/mymoney/tests/mymoneyexception-test.h +++ b/kmymoney/mymoney/tests/mymoneyexception-test.h @@ -1,38 +1,38 @@ /*************************************************************************** mymoneyexceptiontest.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 MYMONEYEXCEPTIONTEST_H #define MYMONEYEXCEPTIONTEST_H -#include +#include #include "mymoneyutils.h" #include "mymoneyexception.h" class MyMoneyExceptionTest : public QObject { Q_OBJECT private slots: void init(); void cleanup(); void testDefaultConstructor(); void testConstructor(); }; #endif diff --git a/kmymoney/mymoney/tests/mymoneyfile-test.cpp b/kmymoney/mymoney/tests/mymoneyfile-test.cpp index 3fd1eba0f..ae6977c15 100644 --- a/kmymoney/mymoney/tests/mymoneyfile-test.cpp +++ b/kmymoney/mymoney/tests/mymoneyfile-test.cpp @@ -1,2758 +1,2758 @@ /*************************************************************************** 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 #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 "payeeidentifier/ibanandbic/ibanbic.h" #include "payeeidentifier/payeeidentifierloader.h" #include "payeeidentifiertyped.h" QTEST_GUILESS_MAIN(MyMoneyFileTest) void MyMoneyFileTest::objectAdded(eMyMoney::File::Object type, const MyMoneyObject * const obj) { Q_UNUSED(type); m_objectsAdded += obj->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 MyMoneyObject * const obj) { Q_UNUSED(type); m_objectsModified += obj->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, SIGNAL(objectAdded(eMyMoney::File::Object,MyMoneyObject*const)), this, SLOT(objectAdded(eMyMoney::File::Object,MyMoneyObject*const))); connect(m, SIGNAL(objectRemoved(eMyMoney::File::Object,QString)), this, SLOT(objectRemoved(eMyMoney::File::Object,QString))); connect(m, SIGNAL(objectModified(eMyMoney::File::Object,MyMoneyObject*const)), this, SLOT(objectModified(eMyMoney::File::Object,MyMoneyObject*const))); connect(m, SIGNAL(balanceChanged(MyMoneyAccount)), this, SLOT(balanceChanged(MyMoneyAccount))); connect(m, SIGNAL(valueChanged(MyMoneyAccount)), this, SLOT(valueChanged(MyMoneyAccount))); } // this method will be called before each testfunction void MyMoneyFileTest::init() { storage = new MyMoneySeqAccessMgr; 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->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->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->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->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->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->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->m_dirty = false; list = m->institutionList(); QCOMPARE(m->dirty(), false); QCOMPARE(list.count(), 0); testAddTwoInstitutions(); storage->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->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->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->m_dirty = false; user.setName("Name"); m->setUser(user); QCOMPARE(m->dirty(), true); storage->m_dirty = false; user.setAddress("Street"); m->setUser(user); QCOMPARE(m->dirty(), true); storage->m_dirty = false; user.setCity("Town"); m->setUser(user); QCOMPARE(m->dirty(), true); storage->m_dirty = false; user.setState("County"); m->setUser(user); QCOMPARE(m->dirty(), true); storage->m_dirty = false; user.setPostcode("Postcode"); m->setUser(user); QCOMPARE(m->dirty(), true); storage->m_dirty = false; user.setTelephone("Telephone"); m->setUser(user); QCOMPARE(m->dirty(), true); storage->m_dirty = false; user.setEmail("Email"); m->setUser(user); QCOMPARE(m->dirty(), true); storage->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::Checkings); b.setAccountType(eMyMoney::Account::Checkings); MyMoneyInstitution institution; storage->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->m_dirty = false; // check if we can get the same info to a different object c = m->account("A000001"); QCOMPARE(c.accountType(), eMyMoney::Account::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::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::Income); a.setOpeningDate(QDate::currentDate()); b.setAccountType(eMyMoney::Account::Expense); storage->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->m_dirty = false; MyMoneyAccount p = m->account("A000001"); MyMoneyInstitution institution; QCOMPARE(p.accountType(), eMyMoney::Account::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::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->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::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->m_dirty = false; // try to change to an account type that is allowed p.setAccountType(eMyMoney::Account::Savings); ft.restart(); try { m->modifyAccount(p); ft.commit(); QCOMPARE(m->dirty(), true); QCOMPARE(m->accountCount(), static_cast(7)); QCOMPARE(p.accountType(), eMyMoney::Account::Savings); QCOMPARE(p.name(), QLatin1String("New account name")); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } storage->m_dirty = false; // try to change to an account type that is not allowed p.setAccountType(eMyMoney::Account::CreditCard); ft.restart(); try { m->modifyAccount(p); QFAIL("Expecting exception!"); } catch (const MyMoneyException &) { ft.commit(); } storage->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->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->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->m_dirty = false; m->accountList(list); QCOMPARE(m->dirty(), false); QCOMPARE(list.count(), 0); testAddAccounts(); storage->m_dirty = false; list.clear(); m->accountList(list); QCOMPARE(m->dirty(), false); QCOMPARE(list.count(), 2); QCOMPARE(list[0].accountType(), eMyMoney::Account::Checkings); QCOMPARE(list[1].accountType(), eMyMoney::Account::Checkings); } void MyMoneyFileTest::testAddTransaction() { testAddAccounts(); MyMoneyTransaction t, p; MyMoneyAccount exp1; exp1.setAccountType(eMyMoney::Account::Expense); exp1.setName("Expense1"); MyMoneyAccount exp2; exp2.setAccountType(eMyMoney::Account::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->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->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->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->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->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->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(STD_ACC_LIABILITY, "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(STD_ACC_ASSET, 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(STD_ACC_EXPENSE, "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(STD_ACC_INCOME, "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(STD_ACC_EXPENSE); 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->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() { IMyMoneyStorage *store = new MyMoneySeqAccessMgr; 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); IMyMoneyStorage *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::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::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::Checkings; list << eMyMoney::Account::Savings; list << eMyMoney::Account::Cash; list << eMyMoney::Account::CreditCard; list << eMyMoney::Account::Loan; list << eMyMoney::Account::CertificateDep; list << eMyMoney::Account::Investment; list << eMyMoney::Account::MoneyMarket; list << eMyMoney::Account::Asset; list << eMyMoney::Account::Liability; list << eMyMoney::Account::Currency; list << eMyMoney::Account::Income; list << eMyMoney::Account::Expense; list << eMyMoney::Account::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::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::Checkings; list << eMyMoney::Account::Savings; list << eMyMoney::Account::Cash; list << eMyMoney::Account::CertificateDep; list << eMyMoney::Account::MoneyMarket; list << eMyMoney::Account::Asset; list << eMyMoney::Account::AssetLoan; list << eMyMoney::Account::Currency; parent = m->asset(); testReparentEquity(list, parent); list.clear(); list << eMyMoney::Account::CreditCard; list << eMyMoney::Account::Loan; list << eMyMoney::Account::Liability; parent = m->liability(); testReparentEquity(list, parent); list.clear(); list << eMyMoney::Account::Income; parent = m->income(); testReparentEquity(list, parent); list.clear(); list << eMyMoney::Account::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); MyMoneySeqAccessMgr* newStorage = new MyMoneySeqAccessMgr; 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::Checkings); MyMoneyInstitution institution; storage->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::Checkings); storage->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::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::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::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()); } diff --git a/kmymoney/mymoney/tests/mymoneyfile-test.h b/kmymoney/mymoney/tests/mymoneyfile-test.h index d263c70ef..14c8eda9f 100644 --- a/kmymoney/mymoney/tests/mymoneyfile-test.h +++ b/kmymoney/mymoney/tests/mymoneyfile-test.h @@ -1,129 +1,129 @@ /*************************************************************************** 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 #include #define KMM_MYMONEY_UNIT_TESTABLE friend class MyMoneyFileTest; #include "mymoneyfile.h" #include "mymoneyaccount.h" #include "storage/mymoneyseqaccessmgr.h" class MyMoneyFileTest : public QObject { Q_OBJECT protected: MyMoneyFile *m; MyMoneySeqAccessMgr* storage; MyMoneyAccount m_inv; private 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(); private slots: void objectAdded(eMyMoney::File::Object type, const MyMoneyObject * const obj); void objectModified(eMyMoney::File::Object type, const MyMoneyObject * const obj); 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 diff --git a/kmymoney/mymoney/tests/mymoneyfinancialcalculator-test.cpp b/kmymoney/mymoney/tests/mymoneyfinancialcalculator-test.cpp index ee20773a7..9caa98bb0 100644 --- a/kmymoney/mymoney/tests/mymoneyfinancialcalculator-test.cpp +++ b/kmymoney/mymoney/tests/mymoneyfinancialcalculator-test.cpp @@ -1,205 +1,205 @@ /*************************************************************************** mymoneyfinancialcalculatortest.cpp ------------------- copyright : (C) 2003 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 "mymoneyfinancialcalculator-test.h" -#include +#include #define KMM_MYMONEY_UNIT_TESTABLE friend class MyMoneyFinancialCalculatorTest; #include "mymoneymoney.h" #include "mymoneyfinancialcalculator.h" #include "mymoneyfinancialcalculator_p.h" QTEST_GUILESS_MAIN(MyMoneyFinancialCalculatorTest) void MyMoneyFinancialCalculatorTest::init() { m = new MyMoneyFinancialCalculator; } void MyMoneyFinancialCalculatorTest::cleanup() { delete m; } void MyMoneyFinancialCalculatorTest::testEmptyConstructor() { QVERIFY(m->d_func()->m_ir == 0.0); QVERIFY(m->d_func()->m_pv == 0.0); QVERIFY(m->d_func()->m_pmt == 0.0); QVERIFY(m->d_func()->m_fv == 0.0); QVERIFY(m->d_func()->m_npp == 0); QVERIFY(m->d_func()->m_CF == 12); QVERIFY(m->d_func()->m_PF == 12); QVERIFY(m->d_func()->m_prec == 2); QVERIFY(m->d_func()->m_bep == false); QVERIFY(m->d_func()->m_disc == true); QVERIFY(m->d_func()->m_mask == 0); } void MyMoneyFinancialCalculatorTest::testSetPrec() { m->setPrec(3); QVERIFY(m->d_func()->m_prec == 3); } void MyMoneyFinancialCalculatorTest::testSetNpp() { m->setNpp(20); QVERIFY(m->d_func()->m_npp == 20); QVERIFY(m->d_func()->m_mask == NPP_SET); } void MyMoneyFinancialCalculatorTest::testSetPF() { m->setPF(1); QVERIFY(m->d_func()->m_PF == 1); m->setPF(); QVERIFY(m->d_func()->m_PF == 12); } void MyMoneyFinancialCalculatorTest::testSetCF() { m->setCF(1); QVERIFY(m->d_func()->m_CF == 1); m->setCF(); QVERIFY(m->d_func()->m_CF == 12); } void MyMoneyFinancialCalculatorTest::testSetBep() { m->setBep(true); QVERIFY(m->d_func()->m_bep == true); m->setBep(); QVERIFY(m->d_func()->m_bep == false); } void MyMoneyFinancialCalculatorTest::testSetDisc() { m->setDisc(false); QVERIFY(m->d_func()->m_disc == false); m->setDisc(); QVERIFY(m->d_func()->m_disc == true); } void MyMoneyFinancialCalculatorTest::testSetIr() { m->setIr(12.3); QVERIFY(m->d_func()->m_ir == 12.3); QVERIFY(m->d_func()->m_mask == IR_SET); } void MyMoneyFinancialCalculatorTest::testSetPv() { m->setPv(23.4); QVERIFY(m->d_func()->m_pv == 23.4); QVERIFY(m->d_func()->m_mask == PV_SET); } void MyMoneyFinancialCalculatorTest::testSetPmt() { m->setPmt(34.5); QVERIFY(m->d_func()->m_pmt == 34.5); QVERIFY(m->d_func()->m_mask == PMT_SET); } void MyMoneyFinancialCalculatorTest::testSetFv() { m->setFv(45.6); QVERIFY(m->d_func()->m_fv == 45.6); QVERIFY(m->d_func()->m_mask == FV_SET); } void MyMoneyFinancialCalculatorTest::testCombinedSet() { m->setNpp(20); m->setIr(12.3); m->setPv(23.4); m->setPmt(34.5); m->setFv(45.6); QVERIFY(m->d_func()->m_mask == (NPP_SET | PV_SET | IR_SET | PMT_SET | FV_SET)); } void MyMoneyFinancialCalculatorTest::testNumPayments() { m->setPF(12); m->setCF(12); try { m->numPayments(); QFAIL("Missing expected exception"); } catch (const MyMoneyException &) { } try { m->setPv(-80000.0); m->numPayments(); QFAIL("Missing expected exception"); } catch (const MyMoneyException &) { } try { m->setIr(12.0); m->numPayments(); QFAIL("Missing expected exception"); } catch (const MyMoneyException &) { } try { m->setPmt(7108.0); m->numPayments(); QFAIL("Missing expected exception"); } catch (const MyMoneyException &) { } try { m->setFv(0.0); m->numPayments(); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } QVERIFY(qRound(m->d_func()->m_npp) == 12); } void MyMoneyFinancialCalculatorTest::testUseCase1() { m->setPv(-300000.0); m->setIr(5.0); m->setNpp(360); m->setFv(0.0); m->setPF(12); MyMoneyMoney res(m->payment()); QVERIFY(res == MyMoneyMoney(161046, 100)); res = MyMoneyMoney(m->futureValue()); QVERIFY(res == MyMoneyMoney(405, 100)); } void MyMoneyFinancialCalculatorTest::testUseCase2() { m->setPv(-320000.0); m->setIr(5.0); m->setNpp(360); m->setFv(0.0); m->setPF(12); MyMoneyMoney res(m->payment()); QVERIFY(res == MyMoneyMoney(171783, 100)); res = MyMoneyMoney(m->futureValue()); QVERIFY(res == MyMoneyMoney(-67, 100)); } diff --git a/kmymoney/mymoney/tests/mymoneyfinancialcalculator-test.h b/kmymoney/mymoney/tests/mymoneyfinancialcalculator-test.h index f0ca26dbc..e09078375 100644 --- a/kmymoney/mymoney/tests/mymoneyfinancialcalculator-test.h +++ b/kmymoney/mymoney/tests/mymoneyfinancialcalculator-test.h @@ -1,51 +1,51 @@ /*************************************************************************** mymoneyfinancialcalculatortest.h ------------------- copyright : (C) 2003 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 MYMONEYFINANCIALCALCULATORTEST_H #define MYMONEYFINANCIALCALCULATORTEST_H -#include +#include class MyMoneyFinancialCalculator; class MyMoneyFinancialCalculatorTest : public QObject { Q_OBJECT protected: MyMoneyFinancialCalculator *m; private slots: void init(); void cleanup(); void testEmptyConstructor(); void testSetPrec(); void testSetNpp(); void testSetPF(); void testSetCF(); void testSetBep(); void testSetDisc(); void testSetIr(); void testSetPv(); void testSetPmt(); void testSetFv(); void testCombinedSet(); void testNumPayments(); void testUseCase1(); void testUseCase2(); }; #endif diff --git a/kmymoney/mymoney/tests/mymoneyforecast-test.cpp b/kmymoney/mymoney/tests/mymoneyforecast-test.cpp index 7a91f7255..8cd208546 100644 --- a/kmymoney/mymoney/tests/mymoneyforecast-test.cpp +++ b/kmymoney/mymoney/tests/mymoneyforecast-test.cpp @@ -1,981 +1,981 @@ /*************************************************************************** mymoneyforecasttest.cpp ------------------- copyright : (C) 2007 by Alvaro Soliverez email : asoliverez@gmail.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 "mymoneyforecast-test.h" #include #include -#include +#include #include "mymoneybudget.h" #include "mymoneyexception.h" #include "mymoneystoragedump.h" #include "mymoneystoragexml.h" #include "reportstestcommon.h" #include "mymoneyinstitution.h" #include "mymoneysecurity.h" #include "mymoneymoney.h" #include "mymoneysplit.h" #include "mymoneyschedule.h" #include "mymoneyenums.h" using namespace eMyMoney; using namespace test; QTEST_GUILESS_MAIN(MyMoneyForecastTest) MyMoneyForecastTest::MyMoneyForecastTest() { this->moT1 = MyMoneyMoney(57, 1); this->moT2 = MyMoneyMoney(63, 1); this->moT3 = MyMoneyMoney(84, 1); this->moT4 = MyMoneyMoney(62, 1); this->moT5 = MyMoneyMoney(104, 1); } void MyMoneyForecastTest::init() { //all this has been taken from pivottabletest.cpp, by Thomas Baumgart and Ace Jones storage = new MyMoneySeqAccessMgr; file = MyMoneyFile::instance(); file->attachStorage(storage); MyMoneyFileTransaction ft; file->addCurrency(MyMoneySecurity("CAD", "Canadian Dollar", "C$")); file->addCurrency(MyMoneySecurity("USD", "US Dollar", "$")); file->addCurrency(MyMoneySecurity("JPY", "Japanese Yen", QChar(0x00A5), 1)); file->addCurrency(MyMoneySecurity("GBP", "British Pound", "#")); file->setBaseCurrency(file->currency("USD")); MyMoneyPayee payeeTest("Test Payee"); file->addPayee(payeeTest); MyMoneyPayee payeeTest2("Alvaro Soliverez"); file->addPayee(payeeTest2); acAsset = (MyMoneyFile::instance()->asset().id()); acLiability = (MyMoneyFile::instance()->liability().id()); acExpense = (MyMoneyFile::instance()->expense().id()); acIncome = (MyMoneyFile::instance()->income().id()); acChecking = makeAccount(QString("Checking Account"), Account::Checkings, moCheckingOpen, QDate(2004, 5, 15), acAsset, "USD"); acCredit = makeAccount(QString("Credit Card"), Account::CreditCard, moCreditOpen, QDate(2004, 7, 15), acLiability, "USD"); acSolo = makeAccount(QString("Solo"), Account::Expense, MyMoneyMoney(), QDate(2004, 1, 11), acExpense, "USD"); acParent = makeAccount(QString("Parent"), Account::Expense, MyMoneyMoney(), QDate(2004, 1, 11), acExpense, "USD"); acChild = makeAccount(QString("Child"), Account::Expense, MyMoneyMoney(), QDate(2004, 2, 11), acParent, "USD"); acForeign = makeAccount(QString("Foreign"), Account::Expense, MyMoneyMoney(), QDate(2004, 1, 11), acExpense, "USD"); acInvestment = makeAccount("Investment", Account::Investment, moZero, QDate(2004, 1, 1), acAsset, "USD"); acSecondChild = makeAccount(QString("Second Child"), Account::Expense, MyMoneyMoney(), QDate(2004, 2, 11), acParent, "USD"); acGrandChild1 = makeAccount(QString("Grand Child 1"), Account::Expense, MyMoneyMoney(), QDate(2004, 2, 11), acChild, "USD"); acGrandChild2 = makeAccount(QString("Grand Child 2"), Account::Expense, MyMoneyMoney(), QDate(2004, 2, 11), acChild, "USD"); //this account added to have an account to test opening date calculations acCash = makeAccount(QString("Cash"), Account::Cash, moCreditOpen, QDate::currentDate().addDays(-2), acAsset, "USD"); MyMoneyInstitution i("Bank of the World", "", "", "", "", "", ""); file->addInstitution(i); inBank = i.id(); ft.commit(); } void MyMoneyForecastTest::cleanup() { file->detachStorage(storage); delete storage; } void MyMoneyForecastTest::testEmptyConstructor() { MyMoneyForecast a; MyMoneyAccount b; QVERIFY(a.forecastBalance(b, QDate::currentDate()).isZero()); QVERIFY(!a.isForecastAccount(b)); QVERIFY(a.forecastBalance(b, QDate::currentDate()) == MyMoneyMoney()); QVERIFY(a.daysToMinimumBalance(b) == -1); QVERIFY(a.daysToZeroBalance(b) == -2); QVERIFY(a.forecastDays() == 90); QVERIFY(a.accountsCycle() == 30); QVERIFY(a.forecastCycles() == 3); QVERIFY(a.historyStartDate() == QDate::currentDate().addDays(-3*30)); QVERIFY(a.historyEndDate() == QDate::currentDate().addDays(-1)); QVERIFY(a.historyDays() == 30 * 3); } void MyMoneyForecastTest::testDoForecastInit() { MyMoneyForecast a; a.doForecast(); /* //check the illegal argument validation try { KMyMoneyGlobalSettings::setForecastDays(-10); a.doForecast(); } catch (const MyMoneyException &e) { QFAIL("Unexpected exception"); } try { KMyMoneyGlobalSettings::setForecastAccountCycle(-20); a.doForecast(); } catch (const MyMoneyException &e) { QFAIL("Unexpected exception"); } try { KMyMoneyGlobalSettings::setForecastCycles(-10); a.doForecast(); } catch (const MyMoneyException &e) { QFAIL("Unexpected exception"); } try { KMyMoneyGlobalSettings::setForecastAccountCycle(0); a.doForecast(); } catch (const MyMoneyException &e) { QFAIL("Unexpected exception"); } try { KMyMoneyGlobalSettings::setForecastDays(0); KMyMoneyGlobalSettings::setForecastCycles(0); KMyMoneyGlobalSettings::setForecastAccountCycle(0); a.doForecast(); } catch (const MyMoneyException &e) { QVERIFY("Unexpected exception"); }*/ } //test that it forecasts correctly with transactions in the period of forecast void MyMoneyForecastTest::testDoForecast() { //set up environment MyMoneyForecast a; MyMoneyAccount a_checking = file->account(acChecking); MyMoneyAccount a_credit = file->account(acCredit); //test empty forecast a.doForecast(); //this is just to check nothing goes wrong if forecast is run agains an empty template //setup some transactions TransactionHelper t1(QDate::currentDate().addDays(-1), MyMoneySplit::ActionWithdrawal, this->moT1, acChecking, acSolo); TransactionHelper t2(QDate::currentDate().addDays(-1), MyMoneySplit::ActionDeposit, -(this->moT2), acCredit, acParent); TransactionHelper t3(QDate::currentDate().addDays(-1), MyMoneySplit::ActionTransfer, this->moT1, acCredit, acChecking); a.setForecastMethod(1); a.setForecastDays(3); a.setAccountsCycle(1); a.setForecastCycles(1); a.setBeginForecastDay(0); a.setHistoryMethod(0); //moving average a.doForecast(); //checking didn't have balance variations, so the forecast should be equal to the current balance MyMoneyMoney b_checking = file->balance(a_checking.id(), QDate::currentDate()); QVERIFY(a.forecastBalance(a_checking, QDate::currentDate().addDays(1)) == b_checking); QVERIFY(a.forecastBalance(a_checking, QDate::currentDate().addDays(2)) == b_checking); QVERIFY(a.forecastBalance(a_checking, QDate::currentDate().addDays(3)) == b_checking); QVERIFY(a.forecastBalance(a_checking, QDate::currentDate()) == b_checking); //credit had a variation so the forecast should be different for each day MyMoneyMoney b_credit = file->balance(a_credit.id(), QDate::currentDate()); QVERIFY(a.forecastBalance(a_credit, 0) == b_credit); QVERIFY(a.forecastBalance(a_credit, QDate::currentDate().addDays(1)) == (b_credit + (moT2 - moT1))); QVERIFY(a.forecastBalance(a_credit, QDate::currentDate().addDays(2)) == (b_credit + ((moT2 - moT1)*2))); QVERIFY(a.forecastBalance(a_credit, QDate::currentDate().addDays(3)) == b_credit + ((moT2 - moT1)*3)); a.setHistoryMethod(1); //weighted moving average a.doForecast(); QVERIFY(a.forecastBalance(a_credit, 0) == b_credit); QVERIFY(a.forecastBalance(a_credit, QDate::currentDate().addDays(1)) == (b_credit + (moT2 - moT1))); QVERIFY(a.forecastBalance(a_credit, QDate::currentDate().addDays(2)) == (b_credit + ((moT2 - moT1)*2))); QVERIFY(a.forecastBalance(a_credit, QDate::currentDate().addDays(3)) == b_credit + ((moT2 - moT1)*3)); //insert transactions outside the forecast period. The calculation should be the same. TransactionHelper t4(QDate::currentDate().addDays(-2), MyMoneySplit::ActionDeposit, -moT2, acCredit, acParent); TransactionHelper t5(QDate::currentDate().addDays(-10), MyMoneySplit::ActionDeposit, -moT2, acCredit, acParent); TransactionHelper t6(QDate::currentDate().addDays(-3), MyMoneySplit::ActionDeposit, -moT2, acCredit, acParent); a.setForecastMethod(1); a.setForecastDays(3); a.setAccountsCycle(1); a.setForecastCycles(1); a.setBeginForecastDay(0); a.setHistoryMethod(0); //moving average a.doForecast(); //check forecast b_credit = file->balance(a_credit.id(), QDate::currentDate()); MyMoneyMoney b_credit_1_exp = (b_credit + ((moT2 - moT1))); MyMoneyMoney b_credit_2 = a.forecastBalance(a_credit, QDate::currentDate().addDays(2)); MyMoneyMoney b_credit_2_exp = (b_credit + ((moT2 - moT1) * 2)); QVERIFY(a.forecastBalance(a_credit, QDate::currentDate()) == file->balance(a_credit.id(), QDate::currentDate())); QVERIFY(a.forecastBalance(a_credit, QDate::currentDate().addDays(1)) == b_credit + (moT2 - moT1)); QVERIFY(a.forecastBalance(a_credit, QDate::currentDate().addDays(2)) == b_credit + ((moT2 - moT1)*2)); QVERIFY(a.forecastBalance(a_credit, QDate::currentDate().addDays(3)) == b_credit + ((moT2 - moT1)*3)); //test weighted moving average a.setForecastMethod(1); a.setForecastDays(3); a.setAccountsCycle(1); a.setForecastCycles(3); a.setBeginForecastDay(0); a.setHistoryMethod(1); a.doForecast(); QVERIFY(a.forecastBalance(a_credit, 0) == b_credit); QVERIFY(a.forecastBalance(a_credit, QDate::currentDate().addDays(1)) == (b_credit + (((moT2 - moT1)*3 + moT2*2 + moT2) / MyMoneyMoney(6, 1)))); } void MyMoneyForecastTest::testGetForecastAccountList() { MyMoneyForecast a; MyMoneyAccount a_checking = file->account(acChecking); MyMoneyAccount a_parent = file->account(acParent); QList b; b = a.forecastAccountList(); //check that it contains asset account, but not expense accounts QVERIFY(b.contains(a_checking)); QVERIFY(!b.contains(a_parent)); } void MyMoneyForecastTest::testCalculateAccountTrend() { //set up environment TransactionHelper t1(QDate::currentDate().addDays(-3), MyMoneySplit::ActionDeposit, -moT2, acChecking, acSolo); MyMoneyAccount a_checking = file->account(acChecking); //test invalid arguments try { MyMoneyForecast::calculateAccountTrend(a_checking, 0); } catch (const MyMoneyException &e) { QVERIFY(e.what().compare("Illegal arguments when calling calculateAccountTrend. trendDays must be higher than 0") == 0); } try { MyMoneyForecast::calculateAccountTrend(a_checking, -10); } catch (const MyMoneyException &e) { QVERIFY(e.what().compare("Illegal arguments when calling calculateAccountTrend. trendDays must be higher than 0") == 0); } //test that it calculates correctly QVERIFY(MyMoneyForecast::calculateAccountTrend(a_checking , 3) == moT2 / MyMoneyMoney(3, 1)); //test that it works for all kind of accounts MyMoneyAccount a_solo = file->account(acSolo); MyMoneyMoney soloTrend = MyMoneyForecast::calculateAccountTrend(a_solo, 3); MyMoneyMoney soloTrendExp = -moT2 / MyMoneyMoney(3, 1); QVERIFY(MyMoneyForecast::calculateAccountTrend(a_solo, 3) == -moT2 / MyMoneyMoney(3, 1)); //test that it does not take into account the transactions of the opening date of the account MyMoneyAccount a_cash = file->account(acCash); TransactionHelper t2(QDate::currentDate().addDays(-2), MyMoneySplit::ActionDeposit, moT2, acCash, acParent); TransactionHelper t3(QDate::currentDate().addDays(-1), MyMoneySplit::ActionDeposit, moT1, acCash, acParent); QVERIFY(MyMoneyForecast::calculateAccountTrend(a_cash, 3) == -moT1); } void MyMoneyForecastTest::testGetForecastBalance() { //set up environment MyMoneyForecast a; TransactionHelper t1(QDate::currentDate().addDays(-1), MyMoneySplit::ActionWithdrawal, this->moT1, acChecking, acSolo); TransactionHelper t2(QDate::currentDate().addDays(-1), MyMoneySplit::ActionDeposit, -(this->moT2), acCredit, acParent); TransactionHelper t3(QDate::currentDate().addDays(-1), MyMoneySplit::ActionTransfer, this->moT1, acCredit, acChecking); a.setForecastMethod(1); a.setForecastDays(3); a.setAccountsCycle(1); a.setForecastCycles(1); a.setHistoryMethod(0); a.doForecast(); MyMoneyAccount a_checking = file->account(acChecking); MyMoneyAccount a_credit = file->account(acCredit); //test invalid arguments QVERIFY(a.forecastBalance(a_checking, QDate::currentDate().addDays(-1)) == MyMoneyMoney()); QVERIFY(a.forecastBalance(a_checking, QDate::currentDate().addDays(-10)) == MyMoneyMoney()); QVERIFY(a.forecastBalance(a_checking, -1) == MyMoneyMoney()); QVERIFY(a.forecastBalance(a_checking, -100) == MyMoneyMoney()); //test a date outside the forecast days QVERIFY(a.forecastBalance(a_checking, QDate::currentDate().addDays(4)) == MyMoneyMoney()); QVERIFY(a.forecastBalance(a_checking, 4) == MyMoneyMoney()); QVERIFY(a.forecastBalance(a_checking, QDate::currentDate().addDays(10)) == MyMoneyMoney()); QVERIFY(a.forecastBalance(a_checking, 10) == MyMoneyMoney()); //test it returns valid results MyMoneyMoney b_credit = file->balance(a_credit.id(), QDate::currentDate()); QVERIFY(a.forecastBalance(a_credit, QDate::currentDate()) == file->balance(a_credit.id(), QDate::currentDate())); QVERIFY(a.forecastBalance(a_credit, QDate::currentDate().addDays(1)) == b_credit + (moT2 - moT1)); QVERIFY(a.forecastBalance(a_credit, QDate::currentDate().addDays(2)) == b_credit + ((moT2 - moT1)*2)); QVERIFY(a.forecastBalance(a_credit, QDate::currentDate().addDays(3)) == b_credit + ((moT2 - moT1)*3)); } void MyMoneyForecastTest::testIsForecastAccount() { MyMoneyForecast a; MyMoneyAccount a_checking = file->account(acChecking); MyMoneyAccount a_solo = file->account(acSolo); MyMoneyAccount a_investment = file->account(acInvestment); //test an invalid account QVERIFY(a.isForecastAccount(a_solo) == false); QVERIFY(a.isForecastAccount(a_investment) == true); //test a valid account QVERIFY(a.isForecastAccount(a_checking) == true); } void MyMoneyForecastTest::testDoFutureScheduledForecast() { //set up future transactions MyMoneyForecast a; MyMoneyAccount a_cash = file->account(acCash); TransactionHelper t1(QDate::currentDate().addDays(1), MyMoneySplit::ActionDeposit, -moT1, acCash, acParent); TransactionHelper t2(QDate::currentDate().addDays(2), MyMoneySplit::ActionDeposit, -moT2, acCash, acParent); TransactionHelper t3(QDate::currentDate().addDays(3), MyMoneySplit::ActionDeposit, -moT3, acCash, acParent); TransactionHelper t4(QDate::currentDate().addDays(10), MyMoneySplit::ActionDeposit, -moT4, acCash, acParent); a.setForecastMethod(0); a.setForecastDays(3); a.setAccountsCycle(1); a.setForecastCycles(1); a.doForecast(); MyMoneyMoney b_cash = file->balance(a_cash.id(), QDate::currentDate()); //test valid results QVERIFY(a.forecastBalance(a_cash, QDate::currentDate()) == b_cash); QVERIFY(a.forecastBalance(a_cash, QDate::currentDate().addDays(1)) == b_cash + moT1); QVERIFY(a.forecastBalance(a_cash, QDate::currentDate().addDays(2)) == b_cash + moT1 + moT2); QVERIFY(a.forecastBalance(a_cash, QDate::currentDate().addDays(3)) == b_cash + moT1 + moT2 + moT3); } void MyMoneyForecastTest::testScheduleForecast() { //set up schedule environment for testing MyMoneyAccount a_cash = file->account(acCash); MyMoneyAccount a_parent = file->account(acParent); MyMoneyFileTransaction ft; MyMoneySchedule sch("A Name", Schedule::Type::Bill, Schedule::Occurrence::Weekly, 1, Schedule::PaymentType::DirectDebit, QDate::currentDate().addDays(1), QDate(), true, true); MyMoneyTransaction t; t.setPostDate(QDate::currentDate().addDays(1)); t.setEntryDate(QDate::currentDate().addDays(1)); //t.setId("T000000000000000001"); t.setBankID("BID"); t.setMemo("Wohnung:Miete"); t.setCommodity("USD"); t.setValue("key", "value"); MyMoneySplit s; s.setPayeeId("P000001"); s.setShares(moT2); s.setValue(moT2); s.setAccountId(a_parent.id()); s.setBankID("SPID1"); s.setReconcileFlag(eMyMoney::Split::State::Reconciled); t.addSplit(s); s.setPayeeId("P000001"); s.setShares(-moT2); s.setValue(-moT2); s.setAccountId(a_cash.id()); s.setBankID("SPID2"); s.setReconcileFlag(eMyMoney::Split::State::Cleared); s.clearId(); t.addSplit(s); sch.setTransaction(t); file->addSchedule(sch); ft.commit(); MyMoneyFileTransaction ft3; MyMoneySchedule sch3("A Name1", Schedule::Type::Bill, Schedule::Occurrence::Weekly, 1, Schedule::PaymentType::DirectDebit, QDate::currentDate().addDays(5), QDate(), true, true); //sch.setLastPayment(QDate::currentDate()); //sch.recordPayment(QDate::currentDate().addDays(1)); //sch.setId("SCH0001"); MyMoneyTransaction t3; t3.setPostDate(QDate::currentDate().addDays(5)); t3.setEntryDate(QDate::currentDate().addDays(5)); //t.setId("T000000000000000001"); t3.setBankID("BID"); t3.setMemo("Wohnung:Miete"); t3.setCommodity("USD"); t3.setValue("key", "value"); MyMoneySplit s3; s3.setPayeeId("P000001"); s3.setShares(moT2); s3.setValue(moT2); s3.setAccountId(a_parent.id()); s3.setBankID("SPID1"); s3.setReconcileFlag(eMyMoney::Split::State::Reconciled); t3.addSplit(s3); s3.setPayeeId("P000001"); s3.setShares(-moT2); s3.setValue(-moT2); s3.setAccountId(a_cash.id()); s3.setBankID("SPID2"); s3.setReconcileFlag(eMyMoney::Split::State::Cleared); s3.clearId(); t3.addSplit(s3); sch3.setTransaction(t3); file->addSchedule(sch3); ft3.commit(); MyMoneyFileTransaction ft2; MyMoneySchedule sch2("A Name2", Schedule::Type::Bill, Schedule::Occurrence::Weekly, 1, Schedule::PaymentType::DirectDebit, QDate::currentDate().addDays(2), QDate(), true, true); //sch.setLastPayment(QDate::currentDate()); //sch.recordPayment(QDate::currentDate().addDays(1)); //sch.setId("SCH0001"); MyMoneyTransaction t2; t2.setPostDate(QDate::currentDate().addDays(2)); t2.setEntryDate(QDate::currentDate().addDays(2)); //t.setId("T000000000000000001"); t2.setBankID("BID"); t2.setMemo("Wohnung:Miete"); t2.setCommodity("USD"); t2.setValue("key", "value"); MyMoneySplit s2; s2.setPayeeId("P000001"); s2.setShares(moT1); s2.setValue(moT1); s2.setAccountId(a_parent.id()); s2.setBankID("SPID1"); s2.setReconcileFlag(eMyMoney::Split::State::Reconciled); t2.addSplit(s2); s2.setPayeeId("P000001"); s2.setShares(-moT1); s2.setValue(-moT1); s2.setAccountId(a_cash.id()); s2.setBankID("SPID2"); s2.setReconcileFlag(eMyMoney::Split::State::Cleared); s2.clearId(); t2.addSplit(s2); sch2.setTransaction(t2); file->addSchedule(sch2); ft2.commit(); //run forecast MyMoneyForecast a; a.setForecastMethod(0); a.setForecastDays(3); a.setAccountsCycle(1); a.setForecastCycles(1); a.doForecast(); //check result for single schedule MyMoneyMoney b_cash = file->balance(a_cash.id(), QDate::currentDate()); MyMoneyMoney b_cash1 = a.forecastBalance(a_cash, QDate::currentDate().addDays(1)); //test valid results QVERIFY(a.forecastBalance(a_cash, QDate::currentDate()) == b_cash); QVERIFY(a.forecastBalance(a_cash, QDate::currentDate().addDays(1)) == b_cash - moT2); QVERIFY(a.forecastBalance(a_cash, QDate::currentDate().addDays(2)) == b_cash - moT2 - moT1); } void MyMoneyForecastTest::testDaysToMinimumBalance() { //setup environment MyMoneyForecast a; MyMoneyAccount a_cash = file->account(acCash); MyMoneyAccount a_credit = file->account(acCredit); MyMoneyAccount a_parent = file->account(acParent); a_cash.setValue("minBalanceAbsolute", "50"); a_credit.setValue("minBalanceAbsolute", "50"); TransactionHelper t1(QDate::currentDate().addDays(-1), MyMoneySplit::ActionDeposit, -moT1, acCash, acParent); TransactionHelper t2(QDate::currentDate().addDays(2), MyMoneySplit::ActionDeposit, moT2, acCash, acParent); TransactionHelper t3(QDate::currentDate().addDays(-1), MyMoneySplit::ActionWithdrawal, -moT1, acCredit, acParent); TransactionHelper t4(QDate::currentDate().addDays(4), MyMoneySplit::ActionWithdrawal, moT5, acCredit, acParent); a.setForecastMethod(0); a.setForecastDays(3); a.setAccountsCycle(1); a.setForecastCycles(1); a.setBeginForecastDay(0); a.doForecast(); //test invalid arguments MyMoneyAccount nullAcc; QVERIFY(a.daysToMinimumBalance(nullAcc) == -1); //test when not a forecast account QVERIFY(a.daysToMinimumBalance(a_parent) == -1); //test it warns when inside the forecast period QVERIFY(a.daysToMinimumBalance(a_cash) == 2); //test it does not warn when it will be outside of the forecast period QVERIFY(a.daysToMinimumBalance(a_credit) == -1); } void MyMoneyForecastTest::testDaysToZeroBalance() { //set up environment MyMoneyAccount a_Solo = file->account(acSolo); MyMoneyAccount a_Cash = file->account(acCash); MyMoneyAccount a_Credit = file->account(acCredit); //MyMoneyFileTransaction ft; TransactionHelper t1(QDate::currentDate().addDays(2), MyMoneySplit::ActionWithdrawal, -moT1, acChecking, acSolo); TransactionHelper t2(QDate::currentDate().addDays(2), MyMoneySplit::ActionTransfer, (moT5), acCash, acCredit); TransactionHelper t3(QDate::currentDate().addDays(2), MyMoneySplit::ActionWithdrawal, (moT5*100), acCredit, acParent); //ft.commit(); MyMoneyForecast a; a.setForecastMethod(0); a.setForecastDays(30); a.setAccountsCycle(1); a.setForecastCycles(3); a.doForecast(); //test invalid arguments MyMoneyAccount nullAcc; try { a.daysToZeroBalance(nullAcc); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } //test when not a forecast account MyMoneyAccount a_solo = file->account(acSolo); int iSolo = a.daysToZeroBalance(a_Solo); QVERIFY(iSolo == -2); //test it warns when inside the forecast period MyMoneyMoney fCash = a.forecastBalance(a_Cash, QDate::currentDate().addDays(2)); QVERIFY(a.daysToZeroBalance(a_Cash) == 2); //test it does not warn when it will be outside of the forecast period } void MyMoneyForecastTest::testSkipOpeningDate() { //set up environment MyMoneyForecast a; TransactionHelper t1(QDate::currentDate().addDays(-2), MyMoneySplit::ActionWithdrawal, this->moT1, acCash, acSolo); TransactionHelper t2(QDate::currentDate().addDays(-1), MyMoneySplit::ActionWithdrawal, this->moT2, acCash, acSolo); a.setForecastMethod(1); a.setForecastDays(3); a.setAccountsCycle(2); a.setForecastCycles(1); a.setHistoryMethod(0); a.doForecast(); MyMoneyAccount a_cash = file->account(acCash); //test it has no variation because it skipped the variation of the opening date MyMoneyMoney b_cash = file->balance(a_cash.id(), QDate::currentDate()); QVERIFY(a.skipOpeningDate() == true); QVERIFY(a.forecastBalance(a_cash, QDate::currentDate()) == b_cash); QVERIFY(a.forecastBalance(a_cash, QDate::currentDate().addDays(1)) == b_cash); QVERIFY(a.forecastBalance(a_cash, QDate::currentDate().addDays(2)) == b_cash - moT2); QVERIFY(a.forecastBalance(a_cash, QDate::currentDate().addDays(3)) == b_cash - moT2); } void MyMoneyForecastTest::testAccountMinimumBalanceDateList() { //set up environment MyMoneyForecast a; TransactionHelper t1(QDate::currentDate().addDays(-2), MyMoneySplit::ActionWithdrawal, this->moT1, acCash, acSolo); TransactionHelper t2(QDate::currentDate().addDays(-1), MyMoneySplit::ActionWithdrawal, this->moT2, acCash, acSolo); a.setForecastMethod(1); a.setForecastDays(6); a.setAccountsCycle(2); a.setForecastCycles(3); a.setHistoryMethod(0); a.setBeginForecastDay(QDate::currentDate().addDays(1).day()); a.doForecast(); MyMoneyAccount a_cash = file->account(acCash); //test QList dateList; dateList = a.accountMinimumBalanceDateList(a_cash); QList::iterator it = dateList.begin(); QDate minDate = *it; QVERIFY(minDate == QDate::currentDate().addDays(2)); it++; minDate = *it; QVERIFY(minDate == QDate::currentDate().addDays(4)); it++; minDate = *it; QVERIFY(minDate == QDate::currentDate().addDays(6)); } void MyMoneyForecastTest::testAccountMaximumBalanceDateList() { //set up environment MyMoneyForecast a; TransactionHelper t1(QDate::currentDate().addDays(-2), MyMoneySplit::ActionWithdrawal, this->moT1, acCash, acSolo); TransactionHelper t2(QDate::currentDate().addDays(-1), MyMoneySplit::ActionWithdrawal, this->moT2, acCash, acSolo); a.setForecastMethod(1); a.setForecastDays(6); a.setAccountsCycle(2); a.setForecastCycles(3); a.setHistoryMethod(0); a.setBeginForecastDay(QDate::currentDate().addDays(1).day()); a.doForecast(); MyMoneyAccount a_cash = file->account(acCash); //test QList dateList; dateList = a.accountMaximumBalanceDateList(a_cash); QList::iterator it = dateList.begin(); QDate maxDate = *it; QVERIFY(maxDate == QDate::currentDate().addDays(1)); it++; maxDate = *it; QVERIFY(maxDate == QDate::currentDate().addDays(3)); it++; maxDate = *it; QVERIFY(maxDate == QDate::currentDate().addDays(5)); } void MyMoneyForecastTest::testAccountAverageBalance() { //set up environment MyMoneyForecast a; TransactionHelper t1(QDate::currentDate().addDays(-2), MyMoneySplit::ActionWithdrawal, this->moT1, acCash, acSolo); TransactionHelper t2(QDate::currentDate().addDays(-1), MyMoneySplit::ActionWithdrawal, this->moT2, acCash, acSolo); a.setForecastMethod(1); a.setForecastDays(3); a.setAccountsCycle(2); a.setForecastCycles(1); a.setBeginForecastDay(0); a.doForecast(); MyMoneyAccount a_cash = file->account(acCash); //test MyMoneyMoney b_cash1 = a.forecastBalance(a_cash, QDate::currentDate().addDays(1)); MyMoneyMoney b_cash2 = a.forecastBalance(a_cash, QDate::currentDate().addDays(2)); MyMoneyMoney b_cash3 = a.forecastBalance(a_cash, QDate::currentDate().addDays(3)); MyMoneyMoney average = (b_cash1 + b_cash2 + b_cash3) / MyMoneyMoney(3, 1); QVERIFY(a.accountAverageBalance(a_cash) == average); } void MyMoneyForecastTest::testBeginForecastDate() { //set up environment MyMoneyForecast a; QDate beginDate; int beginDay; a.setForecastMethod(1); a.setForecastDays(90); a.setAccountsCycle(14); a.setForecastCycles(3); a.setBeginForecastDay(0); a.doForecast(); //test when using old method without begin day QVERIFY(QDate::currentDate() == a.beginForecastDate()); //setup begin to last day of month a.setBeginForecastDay(31); beginDay = a.beginForecastDay(); a.doForecast(); //test if (QDate::currentDate().day() < beginDay) { if (QDate::currentDate().daysInMonth() < beginDay) beginDay = QDate::currentDate().daysInMonth(); beginDate = QDate(QDate::currentDate().year(), QDate::currentDate().month(), beginDay); QVERIFY(beginDate == a.beginForecastDate()); } //setup begin day to same date a.setBeginForecastDay(QDate::currentDate().day()); beginDay = a.beginForecastDay(); a.doForecast(); QVERIFY(QDate::currentDate() == a.beginForecastDate()); //setup to first day of month with small interval a.setBeginForecastDay(1); a.setAccountsCycle(1); beginDay = a.beginForecastDay(); a.doForecast(); //test if (QDate::currentDate() == a.beginForecastDate()) { QVERIFY(QDate::currentDate() == a.beginForecastDate()); } else { beginDay = ((((QDate::currentDate().day() - beginDay) / a.accountsCycle()) + 1) * a.accountsCycle()) + beginDay; if (beginDay > QDate::currentDate().daysInMonth()) beginDay = QDate::currentDate().daysInMonth(); beginDate = QDate(QDate::currentDate().year(), QDate::currentDate().month(), beginDay); if (QDate::currentDate().day() == QDate::currentDate().daysInMonth()) { std::cout << std::endl << "testBeginForecastDate(): test of first day of month with small interval skipped because it is the last day of month" << std::endl; } else { QVERIFY(beginDate == a.beginForecastDate()); } } //setup to test when current date plus cycle equals begin day a.setAccountsCycle(14); beginDay = QDate::currentDate().addDays(14).day(); a.setBeginForecastDay(beginDay); beginDate = QDate::currentDate().addDays(14); a.doForecast(); //test QVERIFY(beginDate == a.beginForecastDate()); //setup to test when the begin day will be next month a.setBeginForecastDay(1); a.setAccountsCycle(40); a.doForecast(); beginDate = QDate(QDate::currentDate().addMonths(1).year(), QDate::currentDate().addMonths(1).month(), 1); //test if (QDate::currentDate().day() > 1) { QVERIFY(beginDate == a.beginForecastDate()); } else { //test is not valid if today is 1st of month std::cout << std::endl << "testBeginForecastDate(): test of first day of month skipped because current day is 1st of month" << std::endl; } } void MyMoneyForecastTest::testHistoryDays() { MyMoneyForecast a; QVERIFY(a.historyStartDate() == QDate::currentDate().addDays(-a.forecastCycles()*a.accountsCycle())); QVERIFY(a.historyEndDate() == QDate::currentDate().addDays(-1)); QVERIFY(a.historyDays() == a.forecastCycles()*a.accountsCycle()); a.setForecastMethod(1); a.setForecastDays(90); a.setAccountsCycle(14); a.setForecastCycles(3); a.setBeginForecastDay(0); a.doForecast(); QVERIFY(a.historyStartDate() == QDate::currentDate().addDays(-14*3)); QVERIFY(a.historyDays() == (14*3)); QVERIFY(a.historyEndDate() == (QDate::currentDate().addDays(-1))); } void MyMoneyForecastTest::testCreateBudget() { //set up environment MyMoneyForecast a; MyMoneyForecast b; MyMoneyBudget budget; TransactionHelper t1(QDate(2005, 1, 3), MyMoneySplit::ActionWithdrawal, this->moT1, acCash, acSolo); TransactionHelper t2(QDate(2005, 1, 15), MyMoneySplit::ActionWithdrawal, this->moT2, acCash, acParent); TransactionHelper t3(QDate(2005, 1, 30), MyMoneySplit::ActionWithdrawal, this->moT3, acCash, acSolo); TransactionHelper t4(QDate(2006, 1, 25), MyMoneySplit::ActionWithdrawal, this->moT4, acCash, acParent); TransactionHelper t5(QDate(2005, 4, 3), MyMoneySplit::ActionWithdrawal, this->moT1, acCash, acSolo); TransactionHelper t6(QDate(2006, 5, 15), MyMoneySplit::ActionWithdrawal, this->moT2, acCash, acParent); TransactionHelper t7(QDate(2005, 8, 3), MyMoneySplit::ActionWithdrawal, this->moT3, acCash, acSolo); TransactionHelper t8(QDate(2006, 9, 15), MyMoneySplit::ActionWithdrawal, this->moT4, acCash, acParent); a.setHistoryMethod(0); a.setForecastMethod(1); a.createBudget(budget, QDate(2005, 1, 1), QDate(2006, 12, 31), QDate(2007, 1, 1), QDate(2007, 12, 31), true); //test MyMoneyAccount a_solo = file->account(acSolo); MyMoneyAccount a_parent = file->account(acParent); //test it has no variation because it skipped the variation of the opening date QVERIFY(a.forecastBalance(a_solo, QDate(2007, 1, 1)) == ((moT1 + moT3) / MyMoneyMoney(2, 1))); QVERIFY(a.forecastBalance(a_parent, QDate(2007, 1, 1)) == ((moT2 + moT4) / MyMoneyMoney(2, 1))); QVERIFY(a.forecastBalance(a_solo, QDate(2007, 4, 1)) == ((moT1) / MyMoneyMoney(2, 1))); QVERIFY(a.forecastBalance(a_parent, QDate(2007, 5, 1)) == ((moT2) / MyMoneyMoney(2, 1))); QVERIFY(a.forecastBalance(a_solo, QDate(2007, 8, 1)) == ((moT3) / MyMoneyMoney(2, 1))); QVERIFY(a.forecastBalance(a_parent, QDate(2007, 9, 1)) == ((moT4) / MyMoneyMoney(2, 1))); //test the budget object returned by the method QVERIFY(budget.account(a_parent.id()).period(QDate(2007, 9, 1)).amount() == ((moT4) / MyMoneyMoney(2, 1))); //setup test for a length lower than a year b.setForecastMethod(1); b.setHistoryMethod(0); b.createBudget(budget, QDate(2005, 1, 1), QDate(2005, 6, 30), QDate(2007, 1, 1), QDate(2007, 6, 30), true); //test QVERIFY(b.forecastBalance(a_solo, QDate(2007, 1, 1)) == (moT1 + moT3)); QVERIFY(b.forecastBalance(a_parent, QDate(2007, 1, 1)) == (moT2)); QVERIFY(b.forecastBalance(a_solo, QDate(2007, 4, 1)) == (moT1)); QVERIFY(b.forecastBalance(a_parent, QDate(2007, 5, 1)) == (MyMoneyMoney())); //set up schedule environment for testing MyMoneyAccount a_cash = file->account(acCash); MyMoneyFileTransaction ft; MyMoneySchedule sch("A Name", Schedule::Type::Bill, Schedule::Occurrence::Monthly, 1, Schedule::PaymentType::DirectDebit, QDate::currentDate(), QDate(), true, true); MyMoneyTransaction t10; t10.setPostDate(QDate::currentDate().addMonths(1)); t10.setEntryDate(QDate::currentDate().addMonths(1)); //t.setId("T000000000000000001"); t10.setBankID("BID"); t10.setMemo("Wohnung:Miete"); t10.setCommodity("USD"); t10.setValue("key", "value"); MyMoneySplit s; s.setPayeeId("P000001"); s.setShares(moT2); s.setValue(moT2); s.setAccountId(a_parent.id()); s.setBankID("SPID1"); s.setReconcileFlag(eMyMoney::Split::State::Reconciled); t10.addSplit(s); s.setPayeeId("P000001"); s.setShares(-moT2); s.setValue(-moT2); s.setAccountId(a_cash.id()); s.setBankID("SPID2"); s.setReconcileFlag(eMyMoney::Split::State::Cleared); s.clearId(); t10.addSplit(s); sch.setTransaction(t10); file->addSchedule(sch); ft.commit(); //run forecast MyMoneyForecast c; c.setForecastMethod(0); c.setForecastCycles(1); c.createBudget(budget, QDate::currentDate().addYears(-2), QDate::currentDate().addYears(-1), QDate::currentDate().addMonths(-2), QDate::currentDate().addMonths(6), true); MyMoneyMoney c_parent = c.forecastBalance(a_parent, QDate(QDate::currentDate().addMonths(1).year(), QDate::currentDate().addMonths(1).month(), 1)); //test valid results QVERIFY(c.forecastBalance(a_parent, QDate(QDate::currentDate().addMonths(1).year(), QDate::currentDate().addMonths(1).month(), 1)) == (moT2)); } void MyMoneyForecastTest::testLinearRegression() { //set up environment MyMoneyForecast a; MyMoneyAccount a_checking = file->account(acChecking); MyMoneyAccount a_credit = file->account(acCredit); //setup some transactions TransactionHelper t1(QDate::currentDate().addDays(-1), MyMoneySplit::ActionWithdrawal, this->moT1, acChecking, acSolo); TransactionHelper t2(QDate::currentDate().addDays(-1), MyMoneySplit::ActionDeposit, -(this->moT2), acCredit, acParent); TransactionHelper t3(QDate::currentDate().addDays(-1), MyMoneySplit::ActionTransfer, this->moT1, acCredit, acChecking); //TODO Add tests specific for linear regression } diff --git a/kmymoney/mymoney/tests/mymoneyforecast-test.h b/kmymoney/mymoney/tests/mymoneyforecast-test.h index ea0271745..7f239dd72 100644 --- a/kmymoney/mymoney/tests/mymoneyforecast-test.h +++ b/kmymoney/mymoney/tests/mymoneyforecast-test.h @@ -1,73 +1,73 @@ /*************************************************************************** mymoneyforecasttest.h ------------------- copyright : (C) 2007 by Alvaro Soliverez email : asoliverez@gmail.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. * * * ***************************************************************************/ #ifndef MYMONEYFORECASTTEST_H #define MYMONEYFORECASTTEST_H -#include +#include #define KMM_MYMONEY_UNIT_TESTABLE friend class MyMoneyForecastTest; #include "mymoneyfile.h" #include "mymoneymoney.h" #include "mymoneyseqaccessmgr.h" #include "mymoneyforecast.h" class MyMoneyForecastTest : public QObject { Q_OBJECT public: MyMoneyForecastTest(); private slots: void init(); void cleanup(); void testEmptyConstructor(); void testDoForecast(); void testDoForecastInit(); void testGetForecastAccountList(); void testCalculateAccountTrend(); void testGetForecastBalance(); void testIsForecastAccount(); void testDoFutureScheduledForecast(); void testDaysToMinimumBalance(); void testDaysToZeroBalance(); void testScheduleForecast(); void testSkipOpeningDate(); void testAccountMinimumBalanceDateList(); void testAccountMaximumBalanceDateList(); void testAccountAverageBalance(); void testBeginForecastDate(); void testHistoryDays(); void testCreateBudget(); void testLinearRegression(); protected: MyMoneyForecast *m; private: MyMoneySeqAccessMgr* storage; MyMoneyFile* file; MyMoneyMoney moT1; MyMoneyMoney moT2; MyMoneyMoney moT3; MyMoneyMoney moT4; MyMoneyMoney moT5; }; #endif diff --git a/kmymoney/mymoney/tests/mymoneyinstitution-test.cpp b/kmymoney/mymoney/tests/mymoneyinstitution-test.cpp index 2dba764ed..405534880 100644 --- a/kmymoney/mymoney/tests/mymoneyinstitution-test.cpp +++ b/kmymoney/mymoney/tests/mymoneyinstitution-test.cpp @@ -1,366 +1,366 @@ /*************************************************************************** mymoneyinstitutiontest.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 "mymoneyinstitution-test.h" -#include +#include #define KMM_MYMONEY_UNIT_TESTABLE friend class MyMoneyInstitutionTest; #include "mymoneyexception.h" #include "mymoneyinstitution.h" QTEST_GUILESS_MAIN(MyMoneyInstitutionTest) void MyMoneyInstitutionTest::init() { m = new MyMoneyInstitution(); n = new MyMoneyInstitution("name", "town", "street", "postcode", "telephone", "manager", "sortcode"); } void MyMoneyInstitutionTest::cleanup() { delete m; delete n; } void MyMoneyInstitutionTest::testEmptyConstructor() { QVERIFY(m->id().isEmpty()); QVERIFY(m->street().isEmpty()); QVERIFY(m->town().isEmpty()); QVERIFY(m->postcode().isEmpty()); QVERIFY(m->telephone().isEmpty()); QVERIFY(m->manager().isEmpty()); QVERIFY(m->accountCount() == 0); } void MyMoneyInstitutionTest::testSetFunctions() { m->setStreet("street"); m->setTown("town"); m->setPostcode("postcode"); m->setTelephone("telephone"); m->setManager("manager"); m->setName("name"); QVERIFY(m->id().isEmpty()); QVERIFY(m->street() == "street"); QVERIFY(m->town() == "town"); QVERIFY(m->postcode() == "postcode"); QVERIFY(m->telephone() == "telephone"); QVERIFY(m->manager() == "manager"); QVERIFY(m->name() == "name"); } void MyMoneyInstitutionTest::testNonemptyConstructor() { QVERIFY(n->id().isEmpty()); QVERIFY(n->street() == "street"); QVERIFY(n->town() == "town"); QVERIFY(n->postcode() == "postcode"); QVERIFY(n->telephone() == "telephone"); QVERIFY(n->manager() == "manager"); QVERIFY(n->name() == "name"); QVERIFY(n->sortcode() == "sortcode"); } void MyMoneyInstitutionTest::testCopyConstructor() { MyMoneyInstitution* n1 = new MyMoneyInstitution("GUID1", *n); MyMoneyInstitution n2(*n1); QVERIFY(*n1 == n2); delete n1; } void MyMoneyInstitutionTest::testMyMoneyFileConstructor() { MyMoneyInstitution *t = new MyMoneyInstitution("GUID", *n); QVERIFY(t->id() == "GUID"); QVERIFY(t->street() == "street"); QVERIFY(t->town() == "town"); QVERIFY(t->postcode() == "postcode"); QVERIFY(t->telephone() == "telephone"); QVERIFY(t->manager() == "manager"); QVERIFY(t->name() == "name"); QVERIFY(t->sortcode() == "sortcode"); delete t; } void MyMoneyInstitutionTest::testEquality() { MyMoneyInstitution t("name", "town", "street", "postcode", "telephone", "manager", "sortcode"); QVERIFY(t == *n); t.setStreet("x"); QVERIFY(!(t == *n)); t.setStreet("street"); QVERIFY(t == *n); t.setName("x"); QVERIFY(!(t == *n)); t.setName("name"); QVERIFY(t == *n); t.setTown("x"); QVERIFY(!(t == *n)); t.setTown("town"); QVERIFY(t == *n); t.setPostcode("x"); QVERIFY(!(t == *n)); t.setPostcode("postcode"); QVERIFY(t == *n); t.setTelephone("x"); QVERIFY(!(t == *n)); t.setTelephone("telephone"); QVERIFY(t == *n); t.setManager("x"); QVERIFY(!(t == *n)); t.setManager("manager"); QVERIFY(t == *n); MyMoneyInstitution* n1 = new MyMoneyInstitution("GUID1", *n); MyMoneyInstitution* n2 = new MyMoneyInstitution("GUID1", *n); n1->addAccountId("A000001"); n2->addAccountId("A000001"); QVERIFY(*n1 == *n2); delete n1; delete n2; } void MyMoneyInstitutionTest::testInequality() { MyMoneyInstitution* n1 = new MyMoneyInstitution("GUID0", *n); MyMoneyInstitution* n2 = new MyMoneyInstitution("GUID1", *n); MyMoneyInstitution* n3 = new MyMoneyInstitution("GUID2", *n); MyMoneyInstitution* n4 = new MyMoneyInstitution("GUID2", *n); QVERIFY(!(*n1 == *n2)); QVERIFY(!(*n1 == *n3)); QVERIFY(*n3 == *n4); n3->addAccountId("A000001"); n4->addAccountId("A000002"); QVERIFY(!(*n3 == *n4)); delete n1; delete n2; delete n3; delete n4; } void MyMoneyInstitutionTest::testAccountIDList() { MyMoneyInstitution institution; QStringList list; QString id; // list must be empty list = institution.accountList(); QVERIFY(list.count() == 0); // add one account institution.addAccountId("A000002"); list = institution.accountList(); QVERIFY(list.count() == 1); QVERIFY(list.contains("A000002") == 1); // adding same account shouldn't make a difference institution.addAccountId("A000002"); list = institution.accountList(); QVERIFY(list.count() == 1); QVERIFY(list.contains("A000002") == 1); // now add another account institution.addAccountId("A000001"); list = institution.accountList(); QVERIFY(list.count() == 2); QVERIFY(list.contains("A000002") == 1); QVERIFY(list.contains("A000001") == 1); id = institution.removeAccountId("A000001"); QVERIFY(id == "A000001"); list = institution.accountList(); QVERIFY(list.count() == 1); QVERIFY(list.contains("A000002") == 1); } void MyMoneyInstitutionTest::testWriteXML() { MyMoneyKeyValueContainer kvp; n->addAccountId("A000001"); n->addAccountId("A000003"); n->setValue(QString("key"), "value"); QDomDocument doc("TEST"); QDomElement el = doc.createElement("INSTITUTION-CONTAINER"); doc.appendChild(el); MyMoneyInstitution i("I00001", *n); i.writeXML(doc, el); QCOMPARE(doc.doctype().name(), QLatin1String("TEST")); QDomElement institutionContainer = doc.documentElement(); QVERIFY(institutionContainer.isElement()); QCOMPARE(institutionContainer.tagName(), QLatin1String("INSTITUTION-CONTAINER")); QVERIFY(institutionContainer.childNodes().size() == 1); QVERIFY(institutionContainer.elementsByTagName("INSTITUTION").at(0).isElement()); QDomElement institution = institutionContainer.elementsByTagName("INSTITUTION").at(0).toElement(); QCOMPARE(institution.tagName(), QLatin1String("INSTITUTION")); QCOMPARE(institution.attribute("id"), QLatin1String("I00001")); QCOMPARE(institution.attribute("manager"), QLatin1String("manager")); QCOMPARE(institution.attribute("name"), QLatin1String("name")); QCOMPARE(institution.attribute("sortcode"), QLatin1String("sortcode")); QCOMPARE(institution.childNodes().size(), 3); QVERIFY(institution.childNodes().at(0).isElement()); QDomElement address = institution.childNodes().at(0).toElement(); QCOMPARE(address.tagName(), QLatin1String("ADDRESS")); QCOMPARE(address.attribute("street"), QLatin1String("street")); QCOMPARE(address.attribute("telephone"), QLatin1String("telephone")); QCOMPARE(address.attribute("zip"), QLatin1String("postcode")); QCOMPARE(address.attribute("city"), QLatin1String("town")); QCOMPARE(address.childNodes().size(), 0); QVERIFY(institution.childNodes().at(1).isElement()); QDomElement accountIds = institution.childNodes().at(1).toElement(); QCOMPARE(accountIds.tagName(), QLatin1String("ACCOUNTIDS")); QCOMPARE(accountIds.childNodes().size(), 2); QVERIFY(accountIds.childNodes().at(0).isElement()); QDomElement account1 = accountIds.childNodes().at(0).toElement(); QCOMPARE(account1.tagName(), QLatin1String("ACCOUNTID")); QCOMPARE(account1.attribute("id"), QLatin1String("A000001")); QCOMPARE(account1.childNodes().size(), 0); QVERIFY(accountIds.childNodes().at(1).isElement()); QDomElement account2 = accountIds.childNodes().at(1).toElement(); QCOMPARE(account2.tagName(), QLatin1String("ACCOUNTID")); QCOMPARE(account2.attribute("id"), QLatin1String("A000003")); QCOMPARE(account2.childNodes().size(), 0); QVERIFY(institution.childNodes().at(2).isElement()); QDomElement keyValuePairs = institution.childNodes().at(2).toElement(); QCOMPARE(keyValuePairs.tagName(), QLatin1String("KEYVALUEPAIRS")); QCOMPARE(keyValuePairs.childNodes().size(), 1); QVERIFY(keyValuePairs.childNodes().at(0).isElement()); QDomElement keyValuePair1 = keyValuePairs.childNodes().at(0).toElement(); QCOMPARE(keyValuePair1.tagName(), QLatin1String("PAIR")); QCOMPARE(keyValuePair1.attribute("key"), QLatin1String("key")); QCOMPARE(keyValuePair1.attribute("value"), QLatin1String("value")); QCOMPARE(keyValuePair1.childNodes().size(), 0); } void MyMoneyInstitutionTest::testReadXML() { MyMoneyInstitution i; QString ref_ok = QString( "\n" "\n" " \n" "
\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "\n"); QString ref_false = QString( "\n" "\n" " \n" "
\n" " \n" " \n" " \n" " \n" " \n" "\n"); QDomDocument doc; QDomElement node; doc.setContent(ref_false); node = doc.documentElement().firstChild().toElement(); try { i = MyMoneyInstitution(node); QFAIL("Missing expected exception"); } catch (const MyMoneyException &) { } i.addAccountId("TEST"); doc.setContent(ref_ok); node = doc.documentElement().firstChild().toElement(); try { QStringList alist; alist << "A000001" << "A000003"; i = MyMoneyInstitution(node); QVERIFY(i.sortcode() == "sortcode"); QVERIFY(i.id() == "I00001"); QVERIFY(i.manager() == "manager"); QVERIFY(i.name() == "name"); QVERIFY(i.street() == "street"); QVERIFY(i.postcode() == "postcode"); QVERIFY(i.city() == "town"); QVERIFY(i.telephone() == "telephone"); QVERIFY(i.accountList() == alist); QVERIFY(i.value(QString("key")) == "value"); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } } void MyMoneyInstitutionTest::testElementNames() { for (auto i = (int)MyMoneyInstitution::Element::AccountID; i <= (int)MyMoneyInstitution::Element::Address; ++i) { auto isEmpty = MyMoneyInstitution::getElName(static_cast(i)).isEmpty(); if (isEmpty) qWarning() << "Empty element's name " << i; QVERIFY(!isEmpty); } } void MyMoneyInstitutionTest::testAttributeNames() { for (auto i = (int)MyMoneyInstitution::Attribute::ID; i < (int)MyMoneyInstitution::Attribute::LastAttribute; ++i) { auto isEmpty = MyMoneyInstitution::getAttrName(static_cast(i)).isEmpty(); if (isEmpty) qWarning() << "Empty attribute's name " << i; QVERIFY(!isEmpty); } } diff --git a/kmymoney/mymoney/tests/mymoneyinstitution-test.h b/kmymoney/mymoney/tests/mymoneyinstitution-test.h index 0dfb18382..03e9441a9 100644 --- a/kmymoney/mymoney/tests/mymoneyinstitution-test.h +++ b/kmymoney/mymoney/tests/mymoneyinstitution-test.h @@ -1,49 +1,49 @@ /*************************************************************************** mymoneyinstitutiontest.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 MYMONEYINSTITUTIONTEST_H #define MYMONEYINSTITUTIONTEST_H -#include +#include class MyMoneyInstitution; class MyMoneyInstitutionTest : public QObject { Q_OBJECT protected: MyMoneyInstitution *m, *n; private slots: void init(); void cleanup(); void testEmptyConstructor(); void testSetFunctions(); void testNonemptyConstructor(); void testCopyConstructor(); void testMyMoneyFileConstructor(); void testEquality(); void testInequality(); void testAccountIDList(); void testWriteXML(); void testReadXML(); void testElementNames(); void testAttributeNames(); }; #endif diff --git a/kmymoney/mymoney/tests/mymoneykeyvaluecontainer-test.cpp b/kmymoney/mymoney/tests/mymoneykeyvaluecontainer-test.cpp index 8b1ab6897..014a81724 100644 --- a/kmymoney/mymoney/tests/mymoneykeyvaluecontainer-test.cpp +++ b/kmymoney/mymoney/tests/mymoneykeyvaluecontainer-test.cpp @@ -1,235 +1,235 @@ /*************************************************************************** mymoneykeyvaluecontainertest.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 "mymoneykeyvaluecontainer-test.h" -#include +#include #define KMM_MYMONEY_UNIT_TESTABLE friend class MyMoneyKeyValueContainerTest; #include "mymoneyexception.h" #include "mymoneykeyvaluecontainer.h" QTEST_GUILESS_MAIN(MyMoneyKeyValueContainerTest) void MyMoneyKeyValueContainerTest::init() { m = new MyMoneyKeyValueContainer; } void MyMoneyKeyValueContainerTest::cleanup() { delete m; } void MyMoneyKeyValueContainerTest::testEmptyConstructor() { QVERIFY(m->m_kvp.count() == 0); } void MyMoneyKeyValueContainerTest::testRetrieveValue() { // load a value into the container m->m_kvp["Key"] = "Value"; // make sure it's there QVERIFY(m->m_kvp.count() == 1); QVERIFY(m->m_kvp["Key"] == "Value"); // now check that the access function works QVERIFY(m->value("Key") == "Value"); QVERIFY(m->value("key").isEmpty()); } void MyMoneyKeyValueContainerTest::testSetValue() { m->setValue("Key", "Value"); QVERIFY(m->m_kvp.count() == 1); QVERIFY(m->m_kvp["Key"] == "Value"); } void MyMoneyKeyValueContainerTest::testDeletePair() { m->setValue("Key", "Value"); m->setValue("key", "value"); QVERIFY(m->m_kvp.count() == 2); m->deletePair("Key"); QVERIFY(m->m_kvp.count() == 1); QVERIFY(m->value("Key").isEmpty()); QVERIFY(m->value("key") == "value"); } void MyMoneyKeyValueContainerTest::testClear() { m->setValue("Key", "Value"); m->setValue("key", "value"); QVERIFY(m->m_kvp.count() == 2); m->clear(); QVERIFY(m->m_kvp.count() == 0); } void MyMoneyKeyValueContainerTest::testRetrieveList() { QMap copy; copy = m->pairs(); QVERIFY(copy.count() == 0); m->setValue("Key", "Value"); m->setValue("key", "value"); copy = m->pairs(); QVERIFY(copy.count() == 2); QVERIFY(copy["Key"] == "Value"); QVERIFY(copy["key"] == "value"); } void MyMoneyKeyValueContainerTest::testLoadList() { m->setValue("Key", "Value"); m->setValue("key", "value"); QVERIFY(m->m_kvp.count() == 2); QVERIFY(m->m_kvp["Key"] == "Value"); QVERIFY(m->m_kvp["key"] == "value"); } void MyMoneyKeyValueContainerTest::testWriteXML() { m->setValue("Key", "Value"); m->setValue("key", "value"); QDomDocument doc("TEST"); QDomElement el = doc.createElement("KVP-CONTAINER"); doc.appendChild(el); m->writeXML(doc, el); QCOMPARE(doc.doctype().name(), QLatin1String("TEST")); QDomElement kvpContainer = doc.documentElement(); QCOMPARE(kvpContainer.tagName(), QLatin1String("KVP-CONTAINER")); QCOMPARE(kvpContainer.childNodes().size(), 1); QVERIFY(kvpContainer.childNodes().at(0).isElement()); QDomElement keyValuePairs = kvpContainer.childNodes().at(0).toElement(); QCOMPARE(keyValuePairs.tagName(), QLatin1String("KEYVALUEPAIRS")); QCOMPARE(keyValuePairs.childNodes().size(), 2); QVERIFY(keyValuePairs.childNodes().at(0).isElement()); QDomElement keyValuePair1 = keyValuePairs.childNodes().at(0).toElement(); QCOMPARE(keyValuePair1.tagName(), QLatin1String("PAIR")); QCOMPARE(keyValuePair1.attribute("key"), QLatin1String("Key")); QCOMPARE(keyValuePair1.attribute("value"), QLatin1String("Value")); QCOMPARE(keyValuePair1.childNodes().size(), 0); QVERIFY(keyValuePairs.childNodes().at(1).isElement()); QDomElement keyValuePair2 = keyValuePairs.childNodes().at(1).toElement(); QCOMPARE(keyValuePair2.tagName(), QLatin1String("PAIR")); QCOMPARE(keyValuePair2.attribute("key"), QLatin1String("key")); QCOMPARE(keyValuePair2.attribute("value"), QLatin1String("value")); QCOMPARE(keyValuePair2.childNodes().size(), 0); } void MyMoneyKeyValueContainerTest::testReadXML() { m->setValue("Key", "Value"); m->setValue("key", "value"); QString ref_ok( "\n" "\n" " \n" " \n" " \n" " \n" "\n"); QString ref_false( "\n" "\n" " \n" " \n" " \n" " \n" "\n"); QDomDocument doc; QDomElement node; doc.setContent(ref_false); node = doc.documentElement().firstChild().toElement(); // make sure, an empty node does not trigger an exception try { QDomElement e; MyMoneyKeyValueContainer k(e); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } try { MyMoneyKeyValueContainer k(node); QFAIL("Missing expected exception"); } catch (const MyMoneyException &) { } doc.setContent(ref_ok); node = doc.documentElement().firstChild().toElement(); try { MyMoneyKeyValueContainer k(node); QVERIFY(k.m_kvp.count() == 2); QVERIFY(k.value("key") == "Value"); QVERIFY(k.value("Key") == "value"); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } } void MyMoneyKeyValueContainerTest::testArrayRead() { MyMoneyKeyValueContainer kvp; const MyMoneyKeyValueContainer& ckvp = kvp; QVERIFY(kvp.pairs().count() == 0); QVERIFY(ckvp["Key"].isEmpty()); QVERIFY(kvp.pairs().count() == 0); kvp.setValue("Key", "Value"); QVERIFY(kvp["Key"] == "Value"); } void MyMoneyKeyValueContainerTest::testArrayWrite() { MyMoneyKeyValueContainer kvp; kvp["Key"] = "Value"; QVERIFY(kvp.pairs().count() == 1); QVERIFY(kvp.value("Key") == "Value"); } void MyMoneyKeyValueContainerTest::testElementNames() { QMetaEnum e = QMetaEnum::fromType(); for (int i = 0; i < e.keyCount(); ++i) { bool isEmpty = MyMoneyKeyValueContainer::getElName(static_cast(e.value(i))).isEmpty(); if (isEmpty) qWarning() << "Empty element's name" << e.key(i); QVERIFY(!isEmpty); } } void MyMoneyKeyValueContainerTest::testAttributeNames() { QMetaEnum e = QMetaEnum::fromType(); for (int i = 0; i < e.keyCount(); ++i) { bool isEmpty = MyMoneyKeyValueContainer::getAttrName(static_cast(e.value(i))).isEmpty(); if (isEmpty) qWarning() << "Empty attribute's name" << e.key(i); QVERIFY(!isEmpty); } } diff --git a/kmymoney/mymoney/tests/mymoneykeyvaluecontainer-test.h b/kmymoney/mymoney/tests/mymoneykeyvaluecontainer-test.h index aaed0d3c0..92c589322 100644 --- a/kmymoney/mymoney/tests/mymoneykeyvaluecontainer-test.h +++ b/kmymoney/mymoney/tests/mymoneykeyvaluecontainer-test.h @@ -1,48 +1,48 @@ /*************************************************************************** mymoneykeyvaluecontainertest.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 MYMONEYKEYVALUECONTAINERTEST_H #define MYMONEYKEYVALUECONTAINERTEST_H -#include +#include class MyMoneyKeyValueContainer; class MyMoneyKeyValueContainerTest : public QObject { Q_OBJECT protected: MyMoneyKeyValueContainer *m; private slots: void init(); void cleanup(); void testEmptyConstructor(); void testRetrieveValue(); void testSetValue(); void testDeletePair(); void testClear(); void testRetrieveList(); void testLoadList(); void testArrayRead(); void testArrayWrite(); void testWriteXML(); void testReadXML(); void testElementNames(); void testAttributeNames(); }; #endif diff --git a/kmymoney/mymoney/tests/mymoneymoney-test.cpp b/kmymoney/mymoney/tests/mymoneymoney-test.cpp index 8f866ec27..eda329f02 100644 --- a/kmymoney/mymoney/tests/mymoneymoney-test.cpp +++ b/kmymoney/mymoney/tests/mymoneymoney-test.cpp @@ -1,707 +1,707 @@ /*************************************************************************** mymoneymoneytest.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 "mymoneymoney-test.h" #include #include -#include +#include #define KMM_MYMONEY_UNIT_TESTABLE friend class MyMoneyMoneyTest; #include #include "mymoneyexception.h" #include "mymoneymoney.h" QTEST_GUILESS_MAIN(MyMoneyMoneyTest) void MyMoneyMoneyTest::init() { m_0 = new MyMoneyMoney(12, 100); m_1 = new MyMoneyMoney(-10, 100); m_2 = new MyMoneyMoney(2, 100); m_3 = new MyMoneyMoney(123, 1); m_4 = new MyMoneyMoney(1234, 1000); m_5 = new MyMoneyMoney(195883, 100000); m_6 = new MyMoneyMoney(1.247658435, 1000000000); MyMoneyMoney::setDecimalSeparator('.'); MyMoneyMoney::setThousandSeparator(','); MyMoneyMoney::setNegativeMonetarySignPosition(MyMoneyMoney::BeforeQuantityMoney); } void MyMoneyMoneyTest::cleanup() { delete m_0; delete m_1; delete m_2; delete m_3; delete m_4; delete m_5; delete m_6; } void MyMoneyMoneyTest::testEmptyConstructor() { //qDebug("testing %s", qPrintable(m_0->toString())); MyMoneyMoney *m = new MyMoneyMoney(); QVERIFY(m->valueRef() == 0); QVERIFY(m->toString() == QString("0/1")); QVERIFY(m->valueRef().get_den() == 1); delete m; } void MyMoneyMoneyTest::testIntConstructor() { //qDebug("Current value: %s",qPrintable( m_0->toString()) ); //QVERIFY(m_0->valueRef().get_num() == 12); //QVERIFY(m_0->valueRef().get_den() == 100); QVERIFY(m_0->valueRef().get_num() == 3); QVERIFY(m_0->valueRef().get_den() == 25); MyMoneyMoney a(123, 10000); QVERIFY(a.valueRef().get_num() == 123); QVERIFY(a.valueRef().get_den() == 10000); } void MyMoneyMoneyTest::testAssignment() { MyMoneyMoney *m = new MyMoneyMoney(); *m = *m_1; //qDebug() << "Current value: "<< qPrintable( m->toString()) ; QVERIFY(m->valueRef().get_num() == -1); QVERIFY(m->valueRef().get_den() == 10); //QVERIFY(m->valueRef().get_num() == -10); //QVERIFY(m->valueRef().get_den() == 100); #if 0 *m = 0; QVERIFY(m->valueRef().get_num() == 0); QVERIFY(m->valueRef().get_den() == 100); *m = 777888999; QVERIFY(m->valueRef().get_num() == 777888999); QVERIFY(m->valueRef().get_den() == 100); *m = (int) - 5678; QVERIFY(m->valueRef().get_num() == -5678); QVERIFY(m->valueRef().get_den() == 100); *m = QString("-987"); QVERIFY(m->valueRef().get_num() == -987); QVERIFY(m->valueRef().get_den() == 1); *m = QString("9998887776665554.44"); QVERIFY(m->valueRef().get_num() == 999888777666555444LL); QVERIFY(m->valueRef().get_den() == 100); *m = QString("-99988877766655.444"); QVERIFY(m->valueRef().get_num() == -99988877766655444LL); QVERIFY(m->valueRef().get_den() == 1000); *m = -666555444333222111LL; QVERIFY(m->valueRef().get_num() == -666555444333222111LL); QVERIFY(m->valueRef().get_den() == 100); #endif delete m; } void MyMoneyMoneyTest::testStringConstructor() { MyMoneyMoney *m1 = new MyMoneyMoney("-999666555444"); mpz_class testnum = mpz_class("-999666555444"); //qDebug("Created %s", qPrintable(m1->toString())); QVERIFY(m1->valueRef().get_num() == testnum); QVERIFY(m1->valueRef().get_den() == 1); testnum = mpz_class("444555666999"); MyMoneyMoney *m2 = new MyMoneyMoney("4445556669.99"); QVERIFY(m2->valueRef().get_num() == testnum); QVERIFY(m2->valueRef().get_den() == 100); delete m1; delete m2; //new tests m1 = new MyMoneyMoney("0.01"); QVERIFY(m1->valueRef().get_num() == 1); QVERIFY(m1->valueRef().get_den() == 100); delete m1; m1 = new MyMoneyMoney("0.07"); QVERIFY(m1->valueRef().get_num() == 7); QVERIFY(m1->valueRef().get_den() == 100); delete m1; m1 = new MyMoneyMoney("0.08"); QVERIFY(m1->valueRef().get_num() == 2); QVERIFY(m1->valueRef().get_den() == 25); delete m1; m1 = new MyMoneyMoney("."); //qDebug("Created %s", qPrintable(m1->toString())); QVERIFY(m1->valueRef().get_num() == 0); QVERIFY(m1->valueRef().get_den() == 1); delete m1; m1 = new MyMoneyMoney(""); QVERIFY(m1->valueRef().get_num() == 0); QVERIFY(m1->valueRef().get_den() == 1); delete m1; m1 = new MyMoneyMoney("1,123."); QVERIFY(m1->valueRef().get_num() == (1123)); QVERIFY(m1->valueRef().get_den() == 1); delete m1; m1 = new MyMoneyMoney("123.1"); QVERIFY(m1->valueRef().get_num() == (1231)); QVERIFY(m1->valueRef().get_den() == 10); delete m1; m1 = new MyMoneyMoney("123.456"); //qDebug("Created: %s", m1->valueRef().get_str().c_str()); QVERIFY(m1->valueRef().get_num() == 15432); QVERIFY(m1->valueRef().get_den() == 125); //QVERIFY(m1->valueRef().get_num() == 123456); //QVERIFY(m1->valueRef().get_den() == 1000); delete m1; m1 = new MyMoneyMoney("12345/100"); //qDebug("Created: %s", m1->valueRef().get_str().c_str()); QVERIFY(m1->valueRef().get_num() == 2469); QVERIFY(m1->valueRef().get_den() == 20); // QVERIFY(m1->valueRef().get_num() == (12345)); // QVERIFY(m1->valueRef().get_den() == 100); delete m1; m1 = new MyMoneyMoney("-54321/100"); // qDebug("Created: %s", m1->valueRef().get_str().c_str()); QVERIFY(m1->valueRef().get_num() == (-54321)); QVERIFY(m1->valueRef().get_den() == 100); delete m1; MyMoneyMoney::setDecimalSeparator(','); MyMoneyMoney::setThousandSeparator('.'); MyMoneyMoney::setNegativeMonetarySignPosition(MyMoneyMoney::ParensAround); m1 = new MyMoneyMoney("x1.234,567 EUR"); QVERIFY(m1->valueRef().get_num() == (1234567)); QVERIFY(m1->valueRef().get_den() == 1000); delete m1; m1 = new MyMoneyMoney("x(1.234,567) EUR"); QVERIFY(m1->valueRef().get_num() == (-1234567)); QVERIFY(m1->valueRef().get_den() == 1000); delete m1; m1 = new MyMoneyMoney("1 5/8"); QVERIFY(m1->valueRef().get_num() == (13)); QVERIFY(m1->valueRef().get_den() == 8); delete m1; m1 = new MyMoneyMoney("09"); QVERIFY(m1->valueRef().get_num() == (9)); QVERIFY(m1->valueRef().get_den() == 1); delete m1; } void MyMoneyMoneyTest::testConvert() { MyMoneyMoney a(123.456); MyMoneyMoney b = a.convertDenominator(100); QVERIFY(b == MyMoneyMoney(12346 , 100)); a = QString("-123.456"); b = a.convert(100); QVERIFY(b == MyMoneyMoney(-12346 , 100)); a = QString("123.1"); b = a.convert(100); QVERIFY(b == MyMoneyMoney(12310, 100)); a = QString("-73010.28"); b = QString("1.95583"); QVERIFY((a * b).convert(100) == QString("-142795.70")); QVERIFY((a * b).convert(100) == QString("-14279570/100")); // QVERIFY((a * b).convert(100).toString() == QString("-14279570/100")); a = QString("-142795.69"); QVERIFY((a / b).convert(100) == QString("-73010.28")); //QVERIFY((a / b).convert(100).toString() == QString("-7301028/100")); } void MyMoneyMoneyTest::testEquality() { QVERIFY(*m_1 == *m_1); QVERIFY(!(*m_1 == *m_0)); MyMoneyMoney m1(std::int64_t(999666555444), 100); MyMoneyMoney m2(std::int64_t(999666555444), 100); QVERIFY(m1 == m2); MyMoneyMoney m3(std::int64_t(-999666555444), 100); MyMoneyMoney m4(std::int64_t(-999666555444), 100); QVERIFY(m3 == m4); MyMoneyMoney m5(1230, 100); MyMoneyMoney m6(123, 10); MyMoneyMoney m7(246, 20); QVERIFY(m5 == m6); QVERIFY(m5 == m7); QVERIFY(m5 == QString("369/30")); QVERIFY(MyMoneyMoney::autoCalc == MyMoneyMoney::autoCalc); MyMoneyMoney mm1, mm2; mm1 = QLatin1String("-14279570/100"); mm2 = QLatin1String("-1427957/10"); QVERIFY(mm1 == mm2); QVERIFY(mm1 == QLatin1String("-14279570/100")); mm1 = QLatin1String("-7301028/100"); mm2 = QLatin1String("-1825257/25"); QVERIFY(mm1 == mm2); } void MyMoneyMoneyTest::testInequality() { QVERIFY(*m_1 != *m_0); QVERIFY(!(*m_1 != *m_1)); MyMoneyMoney m1(std::int64_t(999666555444), 100); MyMoneyMoney m2(std::int64_t(-999666555444), 100); QVERIFY(m1 != m2); MyMoneyMoney m3(std::int64_t(-999666555444), 100); MyMoneyMoney m4(std::int64_t(999666555444), 100); QVERIFY(m3 != m4); QVERIFY(m4 != QString("999666555444")); QVERIFY(MyMoneyMoney::autoCalc != MyMoneyMoney(1, 100)); QVERIFY(MyMoneyMoney(1, 100) != MyMoneyMoney::autoCalc); } void MyMoneyMoneyTest::testAddition() { QVERIFY(*m_0 + *m_1 == *m_2); MyMoneyMoney m1(100, 100); // QVERIFY((m1 + 50) == MyMoneyMoney(51,1)); // QVERIFY((m1 + 1000000000) == MyMoneyMoney(1000000001,1)); // QVERIFY((m1 + -50) == MyMoneyMoney(-49,1)); QVERIFY((m1 += *m_0) == MyMoneyMoney(112, 100)); // QVERIFY((m1 += -12) == MyMoneyMoney(100)); // m1++; // QVERIFY(m1 == MyMoneyMoney(101)); // QVERIFY((++m1) == MyMoneyMoney(102)); m1 = QString("123.20"); MyMoneyMoney m2(40, 1000); QVERIFY((m1 + m2) == QString("123.24")); m1 += m2; //FIXME check after deciding about normalization QVERIFY(m1.valueRef().get_num() == 3081); QVERIFY(m1.valueRef().get_den() == 25); //QVERIFY(m1.valueRef().get_num() == 123240); //QVERIFY(m1.valueRef().get_den() == 1000); } void MyMoneyMoneyTest::testSubtraction() { QVERIFY(*m_2 - *m_1 == *m_0); MyMoneyMoney m1(100, 100); // QVERIFY((m1-50) == MyMoneyMoney(-49,1)); // QVERIFY((m1-1000000000) == MyMoneyMoney(-999999999,1)); // QVERIFY((m1 - -50) == MyMoneyMoney(51,1)); QVERIFY((m1 -= *m_0) == MyMoneyMoney(88, 100)); // QVERIFY((m1 -= -12) == MyMoneyMoney(100)); // m1--; // QVERIFY(m1 == MyMoneyMoney(99)); // QVERIFY((--m1) == MyMoneyMoney(98)); m1 = QString("123.20"); MyMoneyMoney m2(1, 5); QVERIFY((m1 - m2) == MyMoneyMoney(123, 1)); m1 -= m2; //FIXME check after deciding about normalization QVERIFY(m1.valueRef().get_num() == 123); QVERIFY(m1.valueRef().get_den() == 1); //QVERIFY(m1.valueRef().get_num() == 12300); //QVERIFY(m1.valueRef().get_den() == 100); } void MyMoneyMoneyTest::testMultiplication() { MyMoneyMoney m1(100, 1); QVERIFY((m1 * MyMoneyMoney(50, 1)) == MyMoneyMoney(5000, 1)); QVERIFY((m1 * MyMoneyMoney(10000000, 1)) == MyMoneyMoney(1000000000, 1)); QVERIFY((m1 *(*m_0)) == MyMoneyMoney(1200, 100)); MyMoneyMoney m2(QString("-73010.28")); m1 = QString("1.95583"); QVERIFY((m1 * m2) == QString("-142795.6959324")); MyMoneyMoney m3(100, 1); QVERIFY((m3 * 10) == MyMoneyMoney(1000, 1)); //QVERIFY( (m3 *= (*m_0)) == MyMoneyMoney(1200)); QVERIFY((m3 *= (*m_0)) == MyMoneyMoney(1200, 100)); } void MyMoneyMoneyTest::testDivision() { MyMoneyMoney m1(100, 100); QVERIFY((m1 / MyMoneyMoney(50, 100)) == MyMoneyMoney(2, 1)); MyMoneyMoney m2(QString("-142795.69")); m1 = QString("1.95583"); QVERIFY((m2 / m1).convert(100000000) == QString("-73010.27696681")); MyMoneyMoney m3 = MyMoneyMoney() / MyMoneyMoney(100, 100); QVERIFY(m3.valueRef().get_num() == 0); QVERIFY(m3.valueRef().get_den() != 0); } void MyMoneyMoneyTest::testSetDecimalSeparator() { MyMoneyMoney m1(100000, 100); MyMoneyMoney m2(200000, 100); QVERIFY(m1.formatMoney("", 2) == QString("1,000.00")); QVERIFY(MyMoneyMoney::decimalSeparator() == '.'); MyMoneyMoney::setDecimalSeparator(':'); QVERIFY(m1.formatMoney("", 2) == QString("1,000:00")); QVERIFY(m2.formatMoney("", 2) == QString("2,000:00")); QVERIFY(MyMoneyMoney::decimalSeparator() == ':'); } void MyMoneyMoneyTest::testSetThousandSeparator() { MyMoneyMoney m1(100000, 100); MyMoneyMoney m2(200000, 100); QVERIFY(m1.formatMoney("", 2) == QString("1,000.00")); QVERIFY(MyMoneyMoney::thousandSeparator() == ','); MyMoneyMoney::setThousandSeparator(':'); QVERIFY(m1.formatMoney("", 2) == QString("1:000.00")); QVERIFY(m2.formatMoney("", 2) == QString("2:000.00")); QVERIFY(MyMoneyMoney::thousandSeparator() == ':'); } void MyMoneyMoneyTest::testFormatMoney() { qDebug() << "Value:" << qPrintable(m_0->toString()); qDebug() << "Converted: " << qPrintable(m_0->convert(100).toString()); qDebug() << " Formatted: " << qPrintable(m_0->formatMoney("", 2)); QVERIFY(m_0->formatMoney("", 2) == QString("0.12")); QVERIFY(m_1->formatMoney("", 2) == QString("-0.10")); MyMoneyMoney m1(10099, 100); qDebug() << "Value:" << qPrintable(m1.toString()); qDebug() << "Converted: " << qPrintable(m1.convert(100).toString()); qDebug() << " Formatted: " << qPrintable(m1.formatMoney("", 2)); QVERIFY(m1.formatMoney("", 2) == QString("100.99")); m1 = MyMoneyMoney(100, 1); qDebug() << "Value:" << qPrintable(m1.toString()); qDebug() << "Converted: " << qPrintable(m1.convert(100).toString()); qDebug() << " Formatted: " << qPrintable(m1.formatMoney("", 2)); QVERIFY(m1.formatMoney("", 2) == QString("100.00")); QVERIFY(m1.formatMoney("", -1) == QString("100")); MyMoneyMoney mTemp(100099, 100); m1 = m1 * MyMoneyMoney(10, 1); QVERIFY(m1 == MyMoneyMoney(1000, 1)); QVERIFY(m1.formatMoney("", 2) == QString("1,000.00")); QVERIFY(m1.formatMoney("", -1) == QString("1,000")); QVERIFY(m1.formatMoney("", -1, false) == QString("1000")); QVERIFY(m1.formatMoney("", 3, false) == QString("1000.000")); m1 = MyMoneyMoney(std::numeric_limits::max(), 100); QVERIFY(m1.formatMoney("", 2) == QString("92,233,720,368,547,758.07")); QVERIFY(m1.formatMoney(100) == QString("92,233,720,368,547,758.07")); QVERIFY(m1.formatMoney("", 2, false) == QString("92233720368547758.07")); QVERIFY(m1.formatMoney(100, false) == QString("92233720368547758.07")); m1 = MyMoneyMoney(std::numeric_limits::min(), 100); QVERIFY(m1.formatMoney("", 2) == QString("-92,233,720,368,547,758.08")); QVERIFY(m1.formatMoney(100) == QString("-92,233,720,368,547,758.08")); QVERIFY(m1.formatMoney("", 2, false) == QString("-92233720368547758.08")); QVERIFY(m1.formatMoney(100, false) == QString("-92233720368547758.08")); // make sure we support numbers that need more than 64 bit m1 = MyMoneyMoney(321, 100) * MyMoneyMoney(std::numeric_limits::max(), 100); QVERIFY(m1.formatMoney("", 2) == QString("296,070,242,383,038,303.40")); QVERIFY(m1.formatMoney("", 4) == QString("296,070,242,383,038,303.4047")); QVERIFY(m1.formatMoney("", 6) == QString("296,070,242,383,038,303.404700")); m1 = MyMoneyMoney(1, 5); QVERIFY(m1.formatMoney("", 2) == QString("0.20")); QVERIFY(m1.formatMoney(1000) == QString("0.200")); QVERIFY(m1.formatMoney(100) == QString("0.20")); QVERIFY(m1.formatMoney(10) == QString("0.2")); m1 = MyMoneyMoney(13333, 5000); QVERIFY(m1.formatMoney("", 10) == QString("2.6666000000")); m1 = MyMoneyMoney(-1404, 100); QVERIFY(m1.formatMoney("", -1) == QString("-14.04")); } void MyMoneyMoneyTest::testRelation() { MyMoneyMoney m1(100, 100); MyMoneyMoney m2(50, 100); MyMoneyMoney m3(100, 100); // tests with same denominator QVERIFY(m1 > m2); QVERIFY(m2 < m1); QVERIFY(m1 <= m3); QVERIFY(m3 >= m1); QVERIFY(m1 <= m1); QVERIFY(m3 >= m3); // tests with different denominator m1 = QString("1/8"); m2 = QString("1/7"); QVERIFY(m1 < m2); QVERIFY(m2 > m1); m2 = QString("-1/7"); QVERIFY(m2 < m1); QVERIFY(m1 > m2); QVERIFY(m1 >= m2); QVERIFY(m2 <= m1); m1 = QString("-2/14"); QVERIFY(m1 >= m2); QVERIFY(m1 <= m2); } void MyMoneyMoneyTest::testUnaryMinus() { MyMoneyMoney m1(100, 100); MyMoneyMoney m2; m2 = -m1; QVERIFY(m1 == MyMoneyMoney(100, 100)); QVERIFY(m2 == MyMoneyMoney(-100, 100)); } void MyMoneyMoneyTest::testDoubleConstructor() { for (int i = -123456; i < 123456; ++i) { // int i = -123456; double d = i; MyMoneyMoney r(i, 100); d /= 100; MyMoneyMoney t(d, 100); MyMoneyMoney s(i); QVERIFY(t == r); QVERIFY(i == s.toDouble()); } } void MyMoneyMoneyTest::testAbsoluteFunction() { MyMoneyMoney m1(-100, 100); MyMoneyMoney m2(100, 100); QVERIFY(m2.abs() == MyMoneyMoney(100, 100)); QVERIFY(m1.abs() == MyMoneyMoney(100, 100)); } void MyMoneyMoneyTest::testToString() { MyMoneyMoney m1(-100, 100); MyMoneyMoney m2(1234, 100); MyMoneyMoney m3; //qDebug("Created: %s", m3.valueRef().get_str().c_str()); //QVERIFY(m1.toString() == QString("-100/100")); QVERIFY(m1.toString() == QString("-1/1")); // qDebug("Current value: %s",qPrintable( m2.toString()) ); //QVERIFY(m2.toString() == QString("1234/100")); QVERIFY(m2.toString() == QString("617/50")); QVERIFY(m3.toString() == QString("0/1")); //FIXME check the impact of the canonicalize in the whole code //QVERIFY(m3.toString() == QString("0")); } void MyMoneyMoneyTest::testNegativeSignPos() { MyMoneyMoney m("-123456/100"); MyMoneyMoney::signPosition pos = MyMoneyMoney::negativeMonetarySignPosition(); MyMoneyMoney::setNegativePrefixCurrencySymbol(false); MyMoneyMoney::setNegativeMonetarySignPosition(MyMoneyMoney::ParensAround); QVERIFY(m.formatMoney("CUR", 2) == "(1,234.56) CUR"); MyMoneyMoney::setNegativeMonetarySignPosition(MyMoneyMoney::BeforeQuantityMoney); QVERIFY(m.formatMoney("CUR", 2) == "-1,234.56 CUR"); MyMoneyMoney::setNegativeMonetarySignPosition(MyMoneyMoney::AfterQuantityMoney); QVERIFY(m.formatMoney("CUR", 2) == "1,234.56- CUR"); MyMoneyMoney::setNegativeMonetarySignPosition(MyMoneyMoney::BeforeMoney); QVERIFY(m.formatMoney("CUR", 2) == "1,234.56 -CUR"); MyMoneyMoney::setNegativeMonetarySignPosition(MyMoneyMoney::AfterMoney); QVERIFY(m.formatMoney("CUR", 2) == "1,234.56 CUR-"); MyMoneyMoney::setNegativePrefixCurrencySymbol(true); MyMoneyMoney::setNegativeMonetarySignPosition(MyMoneyMoney::ParensAround); QVERIFY(m.formatMoney("CUR", 2) == "CUR (1,234.56)"); MyMoneyMoney::setNegativeMonetarySignPosition(MyMoneyMoney::BeforeQuantityMoney); QVERIFY(m.formatMoney("CUR", 2) == "CUR -1,234.56"); MyMoneyMoney::setNegativeMonetarySignPosition(MyMoneyMoney::AfterQuantityMoney); QVERIFY(m.formatMoney("CUR", 2) == "CUR 1,234.56-"); MyMoneyMoney::setNegativeMonetarySignPosition(MyMoneyMoney::BeforeMoney); QVERIFY(m.formatMoney("CUR", 2) == "-CUR 1,234.56"); MyMoneyMoney::setNegativeMonetarySignPosition(MyMoneyMoney::AfterMoney); QVERIFY(m.formatMoney("CUR", 2) == "CUR- 1,234.56"); MyMoneyMoney::setNegativeMonetarySignPosition(pos); } void MyMoneyMoneyTest::testPositiveSignPos() { MyMoneyMoney m("123456/100"); MyMoneyMoney::signPosition pos = MyMoneyMoney::positiveMonetarySignPosition(); MyMoneyMoney::setPositivePrefixCurrencySymbol(false); MyMoneyMoney::setPositiveMonetarySignPosition(MyMoneyMoney::ParensAround); QVERIFY(m.formatMoney("CUR", 2) == "(1,234.56) CUR"); MyMoneyMoney::setPositiveMonetarySignPosition(MyMoneyMoney::BeforeQuantityMoney); QVERIFY(m.formatMoney("CUR", 2) == "1,234.56 CUR"); MyMoneyMoney::setPositiveMonetarySignPosition(MyMoneyMoney::AfterQuantityMoney); QVERIFY(m.formatMoney("CUR", 2) == "1,234.56 CUR"); MyMoneyMoney::setPositiveMonetarySignPosition(MyMoneyMoney::BeforeMoney); QVERIFY(m.formatMoney("CUR", 2) == "1,234.56 CUR"); MyMoneyMoney::setPositiveMonetarySignPosition(MyMoneyMoney::AfterMoney); QVERIFY(m.formatMoney("CUR", 2) == "1,234.56 CUR"); MyMoneyMoney::setPositivePrefixCurrencySymbol(true); MyMoneyMoney::setPositiveMonetarySignPosition(MyMoneyMoney::ParensAround); QVERIFY(m.formatMoney("CUR", 2) == "CUR (1,234.56)"); MyMoneyMoney::setPositiveMonetarySignPosition(MyMoneyMoney::BeforeQuantityMoney); QVERIFY(m.formatMoney("CUR", 2) == "CUR 1,234.56"); MyMoneyMoney::setPositiveMonetarySignPosition(MyMoneyMoney::AfterQuantityMoney); QVERIFY(m.formatMoney("CUR", 2) == "CUR 1,234.56"); MyMoneyMoney::setPositiveMonetarySignPosition(MyMoneyMoney::BeforeMoney); QVERIFY(m.formatMoney("CUR", 2) == "CUR 1,234.56"); MyMoneyMoney::setPositiveMonetarySignPosition(MyMoneyMoney::AfterMoney); QVERIFY(m.formatMoney("CUR", 2) == "CUR 1,234.56"); MyMoneyMoney::setPositiveMonetarySignPosition(pos); } void MyMoneyMoneyTest::testNegativeStringConstructor() { MyMoneyMoney *m1; MyMoneyMoney::setDecimalSeparator(','); MyMoneyMoney::setThousandSeparator('.'); MyMoneyMoney::setNegativeMonetarySignPosition(MyMoneyMoney::ParensAround); m1 = new MyMoneyMoney("x(1.234,567) EUR"); QVERIFY(m1->valueRef().get_num() == (-1234567)); QVERIFY(m1->valueRef().get_den() == 1000); delete m1; MyMoneyMoney::setNegativeMonetarySignPosition(MyMoneyMoney::BeforeQuantityMoney); m1 = new MyMoneyMoney("x1.234,567- EUR"); //qDebug("Created: %s", m1->valueRef().get_str().c_str()); QVERIFY(m1->valueRef().get_num() == (-1234567)); QVERIFY(m1->valueRef().get_den() == 1000); delete m1; m1 = new MyMoneyMoney("x1.234,567 -EUR"); QVERIFY(m1->valueRef().get_num() == (-1234567)); QVERIFY(m1->valueRef().get_den() == 1000); delete m1; m1 = new MyMoneyMoney("-1.234,567 EUR"); QVERIFY(m1->valueRef().get_num() == (-1234567)); QVERIFY(m1->valueRef().get_den() == 1000); delete m1; } void MyMoneyMoneyTest::testReduce() { MyMoneyMoney a(36488100, 1267390000); MyMoneyMoney b(-a); a = a.reduce(); QVERIFY(a.valueRef().get_num() == 364881); QVERIFY(a.valueRef().get_den() == 12673900); b = b.reduce(); QVERIFY(b.valueRef().get_num() == -364881); QVERIFY(b.valueRef().get_den() == 12673900); } void MyMoneyMoneyTest::testZeroDenominator() { try { MyMoneyMoney m((int)1, 0); QFAIL("Missing expected exception"); } catch (const MyMoneyException &) { } try { MyMoneyMoney m((signed64)1, 0); QFAIL("Missing expected exception"); } catch (const MyMoneyException &) { } } diff --git a/kmymoney/mymoney/tests/mymoneymoney-test.h b/kmymoney/mymoney/tests/mymoneymoney-test.h index a4deb470c..b87619b95 100644 --- a/kmymoney/mymoney/tests/mymoneymoney-test.h +++ b/kmymoney/mymoney/tests/mymoneymoney-test.h @@ -1,59 +1,59 @@ /*************************************************************************** mymoneymoneytest.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 MYMONEYMONEYTEST_H #define MYMONEYMONEYTEST_H -#include +#include class MyMoneyMoney; class MyMoneyMoneyTest : public QObject { Q_OBJECT protected: MyMoneyMoney *m_0, *m_1, *m_2, *m_3, *m_4, *m_5, *m_6; private slots: void init(); void cleanup(); void testEmptyConstructor(); void testIntConstructor(); void testStringConstructor(); void testAssignment(); void testConvert(); void testEquality(); void testInequality(); void testAddition(); void testSubtraction(); void testMultiplication(); void testDivision(); void testFormatMoney(); void testSetDecimalSeparator(); void testSetThousandSeparator(); void testRelation(); void testUnaryMinus(); void testDoubleConstructor(); void testAbsoluteFunction(); void testToString(); void testNegativeSignPos(); void testPositiveSignPos(); void testNegativeStringConstructor(); void testReduce(); void testZeroDenominator(); }; #endif diff --git a/kmymoney/mymoney/tests/mymoneyobject-test.cpp b/kmymoney/mymoney/tests/mymoneyobject-test.cpp index d664bbf55..603acd1d7 100644 --- a/kmymoney/mymoney/tests/mymoneyobject-test.cpp +++ b/kmymoney/mymoney/tests/mymoneyobject-test.cpp @@ -1,159 +1,159 @@ /*************************************************************************** mymoneyobjecttest.cpp ------------------- copyright : (C) 2005 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 "mymoneyobject-test.h" -#include +#include #include "mymoneyexception.h" #include "mymoneyaccount.h" class TestMyMoneyObject : public MyMoneyObject { public: TestMyMoneyObject() : MyMoneyObject() {} TestMyMoneyObject(const QDomElement& node, const bool forceId = true) : MyMoneyObject(node, forceId) {} virtual bool hasReferenceTo(const QString&) const { return false; } virtual void writeXML(QDomDocument&, QDomElement&) const {} }; QTEST_GUILESS_MAIN(MyMoneyObjectTest) void MyMoneyObjectTest::testEmptyConstructor() { MyMoneyAccount a; QVERIFY(a.id().isEmpty()); } void MyMoneyObjectTest::testConstructor() { MyMoneyAccount a(QString("thb"), MyMoneyAccount()); QVERIFY(!a.id().isEmpty()); QVERIFY(a.id() == QString("thb")); } void MyMoneyObjectTest::testClearId() { MyMoneyAccount a(QString("thb"), MyMoneyAccount()); QVERIFY(!a.id().isEmpty()); a.clearId(); QVERIFY(a.id().isEmpty()); } void MyMoneyObjectTest::testCopyConstructor() { MyMoneyAccount a(QString("thb"), MyMoneyAccount()); MyMoneyAccount b(a); QVERIFY(a.MyMoneyObject::operator==(b)); } void MyMoneyObjectTest::testAssignmentConstructor() { MyMoneyAccount a(QString("thb"), MyMoneyAccount()); MyMoneyAccount b = a; QVERIFY(a.MyMoneyObject::operator==(b)); } void MyMoneyObjectTest::testEquality() { MyMoneyAccount a(QString("thb"), MyMoneyAccount()); MyMoneyAccount b(QString("thb"), MyMoneyAccount()); MyMoneyAccount c(QString("ace"), MyMoneyAccount()); QVERIFY(a.MyMoneyObject::operator==(b)); QVERIFY(!(a.MyMoneyObject::operator==(c))); } void MyMoneyObjectTest::testReadXML() { TestMyMoneyObject t; QString ref_ok = QString( "\n" "\n" " \n" " \n" "\n" ); QString ref_false1 = QString( "\n" "\n" " \n" " \n" "\n" ); QString ref_false2 = QString( "\n" "\n" " \n" " \n" "\n" ); QDomDocument doc; QDomElement node; // id="" but required doc.setContent(ref_false1); node = doc.documentElement().firstChild().toElement(); try { t = TestMyMoneyObject(node); QFAIL("Missing expected exception"); } catch (const MyMoneyException &) { } // id attribute missing but required doc.setContent(ref_false2); node = doc.documentElement().firstChild().toElement(); try { t = TestMyMoneyObject(node); QFAIL("Missing expected exception"); } catch (const MyMoneyException &) { } // id present doc.setContent(ref_ok); node = doc.documentElement().firstChild().toElement(); try { t = TestMyMoneyObject(node); QVERIFY(t.id() == "T000000000000000001"); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } // id="" but not required doc.setContent(ref_false1); node = doc.documentElement().firstChild().toElement(); try { t = TestMyMoneyObject(node, false); QVERIFY(t.id().isEmpty()); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } } diff --git a/kmymoney/mymoney/tests/mymoneyobject-test.h b/kmymoney/mymoney/tests/mymoneyobject-test.h index 62e512c17..b89e99d0a 100644 --- a/kmymoney/mymoney/tests/mymoneyobject-test.h +++ b/kmymoney/mymoney/tests/mymoneyobject-test.h @@ -1,37 +1,37 @@ /*************************************************************************** mymoneyobjecttest.h ------------------- copyright : (C) 2005 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 MYMONEYOBJECTTEST_H #define MYMONEYOBJECTTEST_H -#include +#include #include "mymoneyobject.h" class MyMoneyObjectTest : public QObject { Q_OBJECT private slots: void testEmptyConstructor(); void testConstructor(); void testClearId(); void testCopyConstructor(); void testAssignmentConstructor(); void testEquality(); void testReadXML(); }; #endif diff --git a/kmymoney/mymoney/tests/mymoneypayee-test.cpp b/kmymoney/mymoney/tests/mymoneypayee-test.cpp index 313efdfc1..54b8c2eba 100644 --- a/kmymoney/mymoney/tests/mymoneypayee-test.cpp +++ b/kmymoney/mymoney/tests/mymoneypayee-test.cpp @@ -1,228 +1,228 @@ /*************************************************************************** mymoneypayeetest.cpp ***************************************************************************/ /*************************************************************************** * * * 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 "mymoneypayee-test.h" #include #include -#include +#include #define KMM_MYMONEY_UNIT_TESTABLE friend class MyMoneyPayeeTest; #include "mymoneypayee.h" using namespace std; QTEST_GUILESS_MAIN(MyMoneyPayeeTest) void MyMoneyPayeeTest::testXml() { QDomDocument doc; QDomElement parent = doc.createElement("Test"); doc.appendChild(parent); MyMoneyPayee payee1; payee1.m_id = "some random id";//if the ID isn't set, w ethrow an exception payee1.writeXML(doc, parent); QString temp1 = "Account1"; payee1.setDefaultAccountId(temp1); payee1.writeXML(doc, parent); QString temp2 = "Account2"; payee1.setDefaultAccountId(temp2); payee1.writeXML(doc, parent); payee1.setDefaultAccountId(); payee1.writeXML(doc, parent); QDomElement el = parent.firstChild().toElement(); QVERIFY(!el.isNull()); MyMoneyPayee payee2(el); QVERIFY(!payee2.defaultAccountEnabled()); QVERIFY(payee2.defaultAccountId().isEmpty()); el = el.nextSibling().toElement(); QVERIFY(!el.isNull()); MyMoneyPayee payee3(el); QVERIFY(payee3.defaultAccountEnabled()); QVERIFY(payee3.defaultAccountId() == temp1); el = el.nextSibling().toElement(); QVERIFY(!el.isNull()); MyMoneyPayee payee4(el); QVERIFY(payee4.defaultAccountEnabled()); QVERIFY(payee4.defaultAccountId() == temp2); el = el.nextSibling().toElement(); QVERIFY(!el.isNull()); MyMoneyPayee payee5(el); QVERIFY(!payee5.defaultAccountEnabled()); QVERIFY(payee5.defaultAccountId().isEmpty()); } void MyMoneyPayeeTest::testDefaultAccount() { MyMoneyPayee payee; QVERIFY(!payee.defaultAccountEnabled()); QVERIFY(payee.defaultAccountId().isEmpty()); QString temp = "Account1"; payee.setDefaultAccountId(temp); QVERIFY(payee.defaultAccountEnabled()); QVERIFY(payee.defaultAccountId() == temp); payee.setDefaultAccountId(); QVERIFY(!payee.defaultAccountEnabled()); QVERIFY(payee.defaultAccountId().isEmpty()); } void MyMoneyPayeeTest::testEmptyMatchKeyBegin() { MyMoneyPayee payee; QString keys; bool ignoreCase; payee.setMatchData(MyMoneyPayee::matchKey, false, "\ntest1\ntest2"); QVERIFY(payee.matchData(ignoreCase, keys) == MyMoneyPayee::matchKey); QVERIFY(ignoreCase == false); QVERIFY(keys == QLatin1String("test1\ntest2")); payee.setMatchData(MyMoneyPayee::matchKey, false, "\n\ntest1\ntest2"); QVERIFY(payee.matchData(ignoreCase, keys) == MyMoneyPayee::matchKey); QVERIFY(ignoreCase == false); QVERIFY(keys == QLatin1String("test1\ntest2")); } void MyMoneyPayeeTest::testEmptyMatchKeyEnd() { MyMoneyPayee payee; QString keys; bool ignoreCase; payee.setMatchData(MyMoneyPayee::matchKey, false, "test1\ntest2\n"); QVERIFY(payee.matchData(ignoreCase, keys) == MyMoneyPayee::matchKey); QVERIFY(ignoreCase == false); QVERIFY(keys == QLatin1String("test1\ntest2")); payee.setMatchData(MyMoneyPayee::matchKey, false, "test1\ntest2\n\n"); QVERIFY(payee.matchData(ignoreCase, keys) == MyMoneyPayee::matchKey); QVERIFY(ignoreCase == false); QVERIFY(keys == QLatin1String("test1\ntest2")); } void MyMoneyPayeeTest::testEmptyMatchKeyMiddle() { MyMoneyPayee payee; QString keys; bool ignoreCase; payee.setMatchData(MyMoneyPayee::matchKey, false, "test1\n\ntest2"); QVERIFY(payee.matchData(ignoreCase, keys) == MyMoneyPayee::matchKey); QVERIFY(ignoreCase == false); QVERIFY(keys == QLatin1String("test1\ntest2")); payee.setMatchData(MyMoneyPayee::matchKey, false, "test1\n\n\ntest2"); QVERIFY(payee.matchData(ignoreCase, keys) == MyMoneyPayee::matchKey); QVERIFY(ignoreCase == false); QVERIFY(keys == QLatin1String("test1\ntest2")); } void MyMoneyPayeeTest::testEmptyMatchKeyMix() { MyMoneyPayee payee; QString keys; bool ignoreCase; payee.setMatchData(MyMoneyPayee::matchKey, false, "\ntest1\n\ntest2\n"); QVERIFY(payee.matchData(ignoreCase, keys) == MyMoneyPayee::matchKey); QVERIFY(ignoreCase == false); QVERIFY(keys == QLatin1String("test1\ntest2")); payee.setMatchData(MyMoneyPayee::matchKey, false, "\n\ntest1\n\n\ntest2\n\n"); QVERIFY(payee.matchData(ignoreCase, keys) == MyMoneyPayee::matchKey); QVERIFY(ignoreCase == false); QVERIFY(keys == QLatin1String("test1\ntest2")); } void MyMoneyPayeeTest::testMatchKeyDisallowSingleSpace() { MyMoneyPayee payee; QString keys; bool ignoreCase; payee.setMatchData(MyMoneyPayee::matchKey, false, " "); QVERIFY(payee.matchData(ignoreCase, keys) == MyMoneyPayee::matchKey); QVERIFY(ignoreCase == false); QVERIFY(keys == QLatin1String("")); } void MyMoneyPayeeTest::testMatchKeyDisallowMultipleSpace() { MyMoneyPayee payee; QString keys; bool ignoreCase; payee.setMatchData(MyMoneyPayee::matchKey, false, " "); QVERIFY(payee.matchData(ignoreCase, keys) == MyMoneyPayee::matchKey); QVERIFY(ignoreCase == false); QVERIFY(keys == QLatin1String("")); } void MyMoneyPayeeTest::testMatchKeyAllowSpaceAtStart() { MyMoneyPayee payee; QString keys; bool ignoreCase; payee.setMatchData(MyMoneyPayee::matchKey, false, " payee"); QVERIFY(payee.matchData(ignoreCase, keys) == MyMoneyPayee::matchKey); QVERIFY(ignoreCase == false); QVERIFY(keys == QLatin1String(" payee")); } void MyMoneyPayeeTest::testMatchKeyAllowSpaceAtEnd() { MyMoneyPayee payee; QString keys; bool ignoreCase; payee.setMatchData(MyMoneyPayee::matchKey, false, "payee "); QVERIFY(payee.matchData(ignoreCase, keys) == MyMoneyPayee::matchKey); QVERIFY(ignoreCase == false); QVERIFY(keys == QLatin1String("payee ")); } void MyMoneyPayeeTest::testMatchNameExact() { MyMoneyPayee payee; QString keys; bool ignoreCase; payee.setMatchData(MyMoneyPayee::matchNameExact, false, keys); keys = QLatin1String("payee "); QCOMPARE(payee.matchData(ignoreCase, keys), MyMoneyPayee::matchNameExact); QCOMPARE(ignoreCase, false); QVERIFY(keys.isEmpty()); } void MyMoneyPayeeTest::testElementNames() { for (auto i = (int)MyMoneyPayee::Element::Address; i <= (int)MyMoneyPayee::Element::Address; ++i) { auto isEmpty = MyMoneyPayee::getElName(static_cast(i)).isEmpty(); if (isEmpty) qWarning() << "Empty element's name " << i; QVERIFY(!isEmpty); } } void MyMoneyPayeeTest::testAttributeNames() { for (auto i = (int)MyMoneyPayee::Attribute::Name; i < (int)MyMoneyPayee::Attribute::LastAttribute; ++i) { auto isEmpty = MyMoneyPayee::getAttrName(static_cast(i)).isEmpty(); if (isEmpty) qWarning() << "Empty attribute's name " << i; QVERIFY(!isEmpty); } } diff --git a/kmymoney/mymoney/tests/mymoneypayee-test.h b/kmymoney/mymoney/tests/mymoneypayee-test.h index 5082ad8a3..5b057e58e 100644 --- a/kmymoney/mymoney/tests/mymoneypayee-test.h +++ b/kmymoney/mymoney/tests/mymoneypayee-test.h @@ -1,38 +1,38 @@ /*************************************************************************** mymoneypayeetest.h ***************************************************************************/ /*************************************************************************** * * * 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 MYMONEYPAYEETEST_H #define MYMONEYPAYEETEST_H -#include +#include class MyMoneyPayeeTest : public QObject { Q_OBJECT private slots: void testXml(); void testDefaultAccount(); void testEmptyMatchKeyBegin(); void testEmptyMatchKeyEnd(); void testEmptyMatchKeyMiddle(); void testEmptyMatchKeyMix(); void testMatchKeyDisallowSingleSpace(); void testMatchKeyDisallowMultipleSpace(); void testMatchKeyAllowSpaceAtStart(); void testMatchKeyAllowSpaceAtEnd(); void testMatchNameExact(); void testElementNames(); void testAttributeNames(); }; #endif diff --git a/kmymoney/mymoney/tests/mymoneyprice-test.cpp b/kmymoney/mymoney/tests/mymoneyprice-test.cpp index 3dd168db2..d5a45edab 100644 --- a/kmymoney/mymoney/tests/mymoneyprice-test.cpp +++ b/kmymoney/mymoney/tests/mymoneyprice-test.cpp @@ -1,88 +1,88 @@ /*************************************************************************** mymoneypricetest.cpp ------------------- copyright : (C) 2005 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 "mymoneyprice-test.h" -#include +#include #include "mymoneyexception.h" #include "mymoneymoney.h" QTEST_GUILESS_MAIN(MyMoneyPriceTest) void MyMoneyPriceTest::init() { m = new MyMoneyPrice(); } void MyMoneyPriceTest::cleanup() { delete m; } void MyMoneyPriceTest::testDefaultConstructor() { QVERIFY(m->isValid() == false); } void MyMoneyPriceTest::testConstructor() { MyMoneyPrice n(QString("from"), QString("to"), QDate(2005, 9, 23), MyMoneyMoney(1, 3), QString("MySource")); QVERIFY(n.isValid() == true); QVERIFY(n.from() == QString("from")); QVERIFY(n.to() == QString("to")); QVERIFY(n.date() == QDate(2005, 9, 23)); QVERIFY(n.source() == QString("MySource")); QVERIFY(n.rate("to") == MyMoneyMoney(1, 3)); } void MyMoneyPriceTest::testValidity() { QString emptyId; MyMoneyPrice n1(emptyId, QString("to"), QDate(2005, 9, 23), MyMoneyMoney(1, 3), QString("MySource")); MyMoneyPrice n2(QString("from"), emptyId, QDate(2005, 9, 23), MyMoneyMoney(1, 3), QString("MySource")); MyMoneyPrice n3(QString("from"), QString("to"), QDate(), MyMoneyMoney(1, 3), QString("MySource")); MyMoneyPrice n4(QString("from"), QString("to"), QDate(2005, 9, 23), MyMoneyMoney(1, 3), QString("MySource")); QVERIFY(n1.isValid() == false); QVERIFY(n2.isValid() == false); QVERIFY(n3.isValid() == false); QVERIFY(n4.isValid() == true); } void MyMoneyPriceTest::testRate() { MyMoneyPrice n1(QString("from"), QString("to"), QDate(2005, 9, 23), MyMoneyMoney(1, 3), QString("MySource")); MyMoneyPrice n2(QString("from"), QString("to"), QDate(), MyMoneyMoney(1, 3), QString("MySource")); try { QVERIFY(n1.rate("to") == MyMoneyMoney(1, 3)); QVERIFY(n1.rate("from") == MyMoneyMoney(3, 1)); QVERIFY(n1.rate(QString()) == MyMoneyMoney(1, 3)); QVERIFY(n2.isValid() == false); QVERIFY(n2.rate("to") == MyMoneyMoney::ONE); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } try { n1.rate("unknown"); QFAIL("Missing expected exception"); } catch (const MyMoneyException &) { } } diff --git a/kmymoney/mymoney/tests/mymoneyprice-test.h b/kmymoney/mymoney/tests/mymoneyprice-test.h index 5333d137d..675764ec4 100644 --- a/kmymoney/mymoney/tests/mymoneyprice-test.h +++ b/kmymoney/mymoney/tests/mymoneyprice-test.h @@ -1,41 +1,41 @@ /*************************************************************************** mymoneypricetest.h ------------------- copyright : (C) 2005 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 MYMONEYPRICETEST_H #define MYMONEYPRICETEST_H -#include +#include #include "mymoneyprice.h" class MyMoneyPriceTest : public QObject { Q_OBJECT protected: MyMoneyPrice* m; private slots: void init(); void cleanup(); void testDefaultConstructor(); void testConstructor(); void testValidity(); void testRate(); }; #endif diff --git a/kmymoney/mymoney/tests/mymoneyreport-test.cpp b/kmymoney/mymoney/tests/mymoneyreport-test.cpp index d8db9695d..72a54a4e1 100644 --- a/kmymoney/mymoney/tests/mymoneyreport-test.cpp +++ b/kmymoney/mymoney/tests/mymoneyreport-test.cpp @@ -1,55 +1,55 @@ /*************************************************************************** mymoneyreporttest.cpp ------------------- copyright : (C) 2017 by Łukasz Wojniłowicz email : lukasz.wojnilowicz@gmail.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 "mymoneyreport-test.h" -#include +#include -#include +#include #include QTEST_GUILESS_MAIN(MyMoneyReportTest) void MyMoneyReportTest::init() { m = new MyMoneyReport(); } void MyMoneyReportTest::cleanup() { delete m; } void MyMoneyReportTest::testElementNames() { for (auto i = (int)MyMoneyReport::Element::Payee; i <= (int)MyMoneyReport::Element::AccountGroup; ++i) { auto isEmpty = MyMoneyReport::getElName(static_cast(i)).isEmpty(); if (isEmpty) qWarning() << "Empty element's name " << i; QVERIFY(!isEmpty); } } void MyMoneyReportTest::testAttributeNames() { for (auto i = (int)MyMoneyReport::Attribute::ID; i < (int)MyMoneyReport::Attribute::LastAttribute; ++i) { auto isEmpty = MyMoneyReport::getAttrName(static_cast(i)).isEmpty(); if (isEmpty) qWarning() << "Empty attribute's name " << i; QVERIFY(!isEmpty); } } diff --git a/kmymoney/mymoney/tests/mymoneyreport-test.h b/kmymoney/mymoney/tests/mymoneyreport-test.h index 9602ebd54..854200e34 100644 --- a/kmymoney/mymoney/tests/mymoneyreport-test.h +++ b/kmymoney/mymoney/tests/mymoneyreport-test.h @@ -1,39 +1,39 @@ /*************************************************************************** mymoneyreporttest.h ------------------- copyright : (C) 2017 by Łukasz Wojniłowicz email : lukasz.wojnilowicz@gmail.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. * * * ***************************************************************************/ #ifndef MYMONEYREPORTTEST_H #define MYMONEYREPORTTEST_H -#include +#include #define KMM_MYMONEY_UNIT_TESTABLE friend class MyMoneyReportTest; #include "mymoneyreport.h" class MyMoneyReportTest : public QObject { Q_OBJECT protected: MyMoneyReport *m; private slots: void init(); void cleanup(); void testElementNames(); void testAttributeNames(); }; #endif diff --git a/kmymoney/mymoney/tests/mymoneyschedule-test.cpp b/kmymoney/mymoney/tests/mymoneyschedule-test.cpp index e8ff2b238..f0addfe45 100644 --- a/kmymoney/mymoney/tests/mymoneyschedule-test.cpp +++ b/kmymoney/mymoney/tests/mymoneyschedule-test.cpp @@ -1,1774 +1,1774 @@ /*************************************************************************** mymoneyscheduletest.cpp ------------------- copyright : (C) 2002 by Michael Edwardes email : mte@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 "mymoneyschedule-test.h" #include -#include +#include #define KMM_MYMONEY_UNIT_TESTABLE friend class MyMoneyScheduleTest; #include "mymoneysplit.h" #include "mymoneymoney.h" #include "mymoneyschedule.h" #include "mymoneyfile.h" #include "mymoneytransaction.h" #include "storage/mymoneyseqaccessmgr.h" QTEST_GUILESS_MAIN(MyMoneyScheduleTest) using namespace eMyMoney; void MyMoneyScheduleTest::testEmptyConstructor() { MyMoneySchedule s; QCOMPARE(s.id().isEmpty(), true); QCOMPARE(s.occurrence(), Schedule::Occurrence::Any); QCOMPARE(s.type(), Schedule::Type::Any); QCOMPARE(s.paymentType(), Schedule::PaymentType::Any); QCOMPARE(s.isFinished(), false); QCOMPARE(!s.startDate().isValid(), true); QCOMPARE(!s.endDate().isValid(), true); QCOMPARE(!s.lastPayment().isValid(), true); QCOMPARE(s.autoEnter(), false); QCOMPARE(s.name().isEmpty(), true); QCOMPARE(s.willEnd(), false); QCOMPARE(s.lastDayInMonth(), false); } void MyMoneyScheduleTest::testConstructor() { MyMoneySchedule s("A Name", Schedule::Type::Bill, Schedule::Occurrence::Weekly, 1, Schedule::PaymentType::DirectDebit, QDate::currentDate(), QDate(), true, true); QCOMPARE(s.type(), Schedule::Type::Bill); QCOMPARE(s.occurrence(), Schedule::Occurrence::Weekly); QCOMPARE(s.occurrenceMultiplier(), 1); QCOMPARE(s.paymentType(), Schedule::PaymentType::DirectDebit); QCOMPARE(s.startDate(), QDate()); QCOMPARE(s.willEnd(), false); QCOMPARE(s.isFixed(), true); QCOMPARE(s.autoEnter(), true); QCOMPARE(s.name(), QLatin1String("A Name")); QCOMPARE(!s.endDate().isValid(), true); QCOMPARE(!s.lastPayment().isValid(), true); } void MyMoneyScheduleTest::testSetFunctions() { MyMoneySchedule s; s.setId("SCHED001"); QCOMPARE(s.id(), QLatin1String("SCHED001")); s.setType(Schedule::Type::Bill); QCOMPARE(s.type(), Schedule::Type::Bill); s.setEndDate(QDate::currentDate()); QCOMPARE(s.endDate(), QDate::currentDate()); QCOMPARE(s.willEnd(), true); } void MyMoneyScheduleTest::testCopyConstructor() { MyMoneySchedule s; s.setId("SCHED001"); s.setType(Schedule::Type::Bill); MyMoneySchedule s2(s); QCOMPARE(s.id(), s2.id()); QCOMPARE(s.type(), s2.type()); } void MyMoneyScheduleTest::testAssignmentConstructor() { MyMoneySchedule s; s.setId("SCHED001"); s.setType(Schedule::Type::Bill); MyMoneySchedule s2 = s; QCOMPARE(s.id(), s2.id()); QCOMPARE(s.type(), s2.type()); } void MyMoneyScheduleTest::testOverdue() { MyMoneySchedule sch_overdue; MyMoneySchedule sch_intime; // the following checks only work correctly, if currentDate() is // between the 1st and 27th. If it is between 28th and 31st // we don't perform them. Note: this should be fixed. if (QDate::currentDate().day() > 27 || QDate::currentDate().day() == 1) { qDebug() << "testOverdue() skipped because current day is between 28th and 2nd"; return; } QDate startDate = QDate::currentDate().addDays(-1).addMonths(-23); QDate lastPaymentDate = QDate::currentDate().addDays(-1).addMonths(-1); QString ref = QString( "\n" "\n" " \n" // krazy:exclude=spelling " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "\n"); QString ref_overdue = ref.arg(startDate.toString(Qt::ISODate)) .arg(lastPaymentDate.toString(Qt::ISODate)) .arg(lastPaymentDate.toString(Qt::ISODate)); QString ref_intime = ref.arg(startDate.addDays(1).toString(Qt::ISODate)) .arg(lastPaymentDate.addDays(1).toString(Qt::ISODate)) .arg(lastPaymentDate.addDays(1).toString(Qt::ISODate)); QDomDocument doc; QDomElement node; // std::cout << ref_intime << std::endl; try { doc.setContent(ref_overdue); node = doc.documentElement().firstChild().toElement(); sch_overdue = MyMoneySchedule(node); doc.setContent(ref_intime); node = doc.documentElement().firstChild().toElement(); sch_intime = MyMoneySchedule(node); QCOMPARE(sch_overdue.isOverdue(), true); QCOMPARE(sch_intime.isOverdue(), false); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } } void MyMoneyScheduleTest::testNextPayment() /* * Test for a schedule where a payment hasn't yet been made. * First payment is in the future. */ { MyMoneySchedule sch; QString future_sched = QString( "\n" "\n" "\n" // krazy:exclude=spelling " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "\n" "\n" ); QDomDocument doc; QDomElement node; doc.setContent(future_sched); node = doc.documentElement().firstChild().toElement(); try { sch = MyMoneySchedule(node); QCOMPARE(sch.nextPayment(QDate(2007, 2, 14)), QDate(2007, 2, 17)); QCOMPARE(sch.nextPayment(QDate(2007, 2, 17)), QDate(2008, 2, 17)); QCOMPARE(sch.nextPayment(QDate(2007, 2, 18)), QDate(2008, 2, 17)); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } } void MyMoneyScheduleTest::testNextPaymentOnLastDayOfMonth() { MyMoneySchedule sch; QString future_sched = QString( "\n" "\n" "\n" // krazy:exclude=spelling " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "\n" "\n" ); QDomDocument doc; QDomElement node; doc.setContent(future_sched); node = doc.documentElement().firstChild().toElement(); try { sch = MyMoneySchedule(node); QDate nextPayment; // check for the first payment to happen nextPayment = sch.nextPayment(QDate(2014, 10, 1)); QCOMPARE(nextPayment, QDate(2014, 10, 31)); sch.setLastPayment(nextPayment); QCOMPARE(sch.nextPayment(QDate(2014, 11, 1)), QDate(2014, 11, 30)); QCOMPARE(sch.nextPayment(QDate(2014, 12, 1)), QDate(2014, 12, 31)); QCOMPARE(sch.nextPayment(QDate(2015, 1, 1)), QDate(2015, 1, 31)); QCOMPARE(sch.nextPayment(QDate(2015, 2, 1)), QDate(2015, 2, 28)); QCOMPARE(sch.nextPayment(QDate(2015, 3, 1)), QDate(2015, 3, 31)); // now check that we also cover leap years QCOMPARE(sch.nextPayment(QDate(2016, 2, 1)), QDate(2016, 2, 29)); QCOMPARE(sch.nextPayment(QDate(2016, 3, 1)), QDate(2016, 3, 31)); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } } void MyMoneyScheduleTest::testAddHalfMonths() { // addHalfMonths is private // Test a Schedule with occurrence EveryHalfMonth using nextPayment MyMoneySchedule s; s.setStartDate(QDate(2007, 1, 1)); s.setOccurrence(Schedule::Occurrence::EveryHalfMonth); s.setNextDueDate(s.startDate()); s.setLastPayment(s.startDate()); QString format("yyyy-MM-dd"); QCOMPARE(s.nextPayment(s.nextDueDate()).toString(format), QLatin1String("2007-01-16")); s.setNextDueDate(QDate(2007, 1, 2)); QCOMPARE(s.nextPayment(s.nextDueDate()).toString(format), QLatin1String("2007-01-17")); s.setNextDueDate(QDate(2007, 1, 3)); QCOMPARE(s.nextPayment(s.nextDueDate()).toString(format), QLatin1String("2007-01-18")); s.setNextDueDate(QDate(2007, 1, 4)); QCOMPARE(s.nextPayment(s.nextDueDate()).toString(format), QLatin1String("2007-01-19")); s.setNextDueDate(QDate(2007, 1, 5)); QCOMPARE(s.nextPayment(s.nextDueDate()).toString(format), QLatin1String("2007-01-20")); s.setNextDueDate(QDate(2007, 1, 6)); QCOMPARE(s.nextPayment(s.nextDueDate()).toString(format), QLatin1String("2007-01-21")); s.setNextDueDate(QDate(2007, 1, 7)); QCOMPARE(s.nextPayment(s.nextDueDate()).toString(format), QLatin1String("2007-01-22")); s.setNextDueDate(QDate(2007, 1, 8)); QCOMPARE(s.nextPayment(s.nextDueDate()).toString(format), QLatin1String("2007-01-23")); s.setNextDueDate(QDate(2007, 1, 9)); QCOMPARE(s.nextPayment(s.nextDueDate()).toString(format), QLatin1String("2007-01-24")); s.setNextDueDate(QDate(2007, 1, 10)); QCOMPARE(s.nextPayment(s.nextDueDate()).toString(format), QLatin1String("2007-01-25")); s.setNextDueDate(QDate(2007, 1, 11)); QCOMPARE(s.nextPayment(s.nextDueDate()).toString(format), QLatin1String("2007-01-26")); s.setNextDueDate(QDate(2007, 1, 12)); QCOMPARE(s.nextPayment(s.nextDueDate()).toString(format), QLatin1String("2007-01-27")); s.setNextDueDate(QDate(2007, 1, 13)); QCOMPARE(s.nextPayment(s.nextDueDate()).toString(format), QLatin1String("2007-01-28")); s.setNextDueDate(QDate(2007, 1, 14)); QCOMPARE(s.nextPayment(s.nextDueDate()).toString(format), QLatin1String("2007-01-29")); // 15 -> Last Day s.setNextDueDate(QDate(2007, 1, 15)); QCOMPARE(s.nextPayment(s.nextDueDate()).toString(format), QLatin1String("2007-01-31")); s.setNextDueDate(QDate(2007, 1, 16)); QCOMPARE(s.nextPayment(s.nextDueDate()).toString(format), QLatin1String("2007-02-01")); s.setNextDueDate(QDate(2007, 1, 17)); QCOMPARE(s.nextPayment(s.nextDueDate()).toString(format), QLatin1String("2007-02-02")); s.setNextDueDate(QDate(2007, 1, 18)); QCOMPARE(s.nextPayment(s.nextDueDate()).toString(format), QLatin1String("2007-02-03")); s.setNextDueDate(QDate(2007, 1, 19)); QCOMPARE(s.nextPayment(s.nextDueDate()).toString(format), QLatin1String("2007-02-04")); s.setNextDueDate(QDate(2007, 1, 20)); QCOMPARE(s.nextPayment(s.nextDueDate()).toString(format), QLatin1String("2007-02-05")); s.setNextDueDate(QDate(2007, 1, 21)); QCOMPARE(s.nextPayment(s.nextDueDate()).toString(format), QLatin1String("2007-02-06")); s.setNextDueDate(QDate(2007, 1, 22)); QCOMPARE(s.nextPayment(s.nextDueDate()).toString(format), QLatin1String("2007-02-07")); s.setNextDueDate(QDate(2007, 1, 23)); QCOMPARE(s.nextPayment(s.nextDueDate()).toString(format), QLatin1String("2007-02-08")); s.setNextDueDate(QDate(2007, 1, 24)); QCOMPARE(s.nextPayment(s.nextDueDate()).toString(format), QLatin1String("2007-02-09")); s.setNextDueDate(QDate(2007, 1, 25)); QCOMPARE(s.nextPayment(s.nextDueDate()).toString(format), QLatin1String("2007-02-10")); s.setNextDueDate(QDate(2007, 1, 26)); QCOMPARE(s.nextPayment(s.nextDueDate()).toString(format), QLatin1String("2007-02-11")); s.setNextDueDate(QDate(2007, 1, 27)); QCOMPARE(s.nextPayment(s.nextDueDate()).toString(format), QLatin1String("2007-02-12")); s.setNextDueDate(QDate(2007, 1, 28)); QCOMPARE(s.nextPayment(s.nextDueDate()).toString(format), QLatin1String("2007-02-13")); s.setNextDueDate(QDate(2007, 1, 29)); QCOMPARE(s.nextPayment(s.nextDueDate()).toString(format), QLatin1String("2007-02-14")); // 30th,31st -> 15th s.setNextDueDate(QDate(2007, 1, 30)); QCOMPARE(s.nextPayment(s.nextDueDate()).toString(format), QLatin1String("2007-02-15")); s.setNextDueDate(QDate(2007, 1, 31)); QCOMPARE(s.nextPayment(s.nextDueDate()).toString(format), QLatin1String("2007-02-15")); // 30th (last day) s.setNextDueDate(QDate(2007, 4, 30)); QCOMPARE(s.nextPayment(s.nextDueDate()).toString(format), QLatin1String("2007-05-15")); // 28th of February (Last day): to 15th s.setNextDueDate(QDate(1900, 2, 28)); QCOMPARE(s.nextPayment(s.nextDueDate()).toString(format), QLatin1String("1900-03-15")); // 28th of February (Leap year): to 13th s.setNextDueDate(QDate(2000, 2, 28)); QCOMPARE(s.nextPayment(s.nextDueDate()).toString(format), QLatin1String("2000-03-13")); // 29th of February (Leap year) s.setNextDueDate(QDate(2000, 2, 29)); QCOMPARE(s.nextPayment(s.nextDueDate()).toString(format), QLatin1String("2000-03-15")); // Add multiple transactions s.setStartDate(QDate(2007, 1, 1)); QCOMPARE(s.dateAfter(2).toString(format), QLatin1String("2007-01-16")); QCOMPARE(s.dateAfter(3).toString(format), QLatin1String("2007-02-01")); QCOMPARE(s.dateAfter(4).toString(format), QLatin1String("2007-02-16")); s.setStartDate(QDate(2007, 1, 12)); QCOMPARE(s.dateAfter(2).toString(format), QLatin1String("2007-01-27")); QCOMPARE(s.dateAfter(3).toString(format), QLatin1String("2007-02-12")); QCOMPARE(s.dateAfter(4).toString(format), QLatin1String("2007-02-27")); QCOMPARE(s.dateAfter(5).toString(format), QLatin1String("2007-03-12")); s.setStartDate(QDate(2007, 1, 13)); QCOMPARE(s.dateAfter(2).toString(format), QLatin1String("2007-01-28")); QCOMPARE(s.dateAfter(3).toString(format), QLatin1String("2007-02-13")); QCOMPARE(s.dateAfter(4).toString(format), QLatin1String("2007-02-28")); QCOMPARE(s.dateAfter(5).toString(format), QLatin1String("2007-03-15")); s.setStartDate(QDate(2007, 1, 14)); QCOMPARE(s.dateAfter(2).toString(format), QLatin1String("2007-01-29")); QCOMPARE(s.dateAfter(3).toString(format), QLatin1String("2007-02-14")); QCOMPARE(s.dateAfter(4).toString(format), QLatin1String("2007-02-28")); QCOMPARE(s.dateAfter(5).toString(format), QLatin1String("2007-03-15")); s.setStartDate(QDate(2007, 1, 15)); QCOMPARE(s.dateAfter(2).toString(format), QLatin1String("2007-01-31")); QCOMPARE(s.dateAfter(3).toString(format), QLatin1String("2007-02-15")); QCOMPARE(s.dateAfter(4).toString(format), QLatin1String("2007-02-28")); QCOMPARE(s.dateAfter(5).toString(format), QLatin1String("2007-03-15")); s.setStartDate(QDate(2007, 1, 16)); QCOMPARE(s.dateAfter(2).toString(format), QLatin1String("2007-02-01")); QCOMPARE(s.dateAfter(3).toString(format), QLatin1String("2007-02-16")); QCOMPARE(s.dateAfter(4).toString(format), QLatin1String("2007-03-01")); QCOMPARE(s.dateAfter(5).toString(format), QLatin1String("2007-03-16")); s.setStartDate(QDate(2007, 1, 27)); QCOMPARE(s.dateAfter(2).toString(format), QLatin1String("2007-02-12")); QCOMPARE(s.dateAfter(3).toString(format), QLatin1String("2007-02-27")); QCOMPARE(s.dateAfter(4).toString(format), QLatin1String("2007-03-12")); QCOMPARE(s.dateAfter(5).toString(format), QLatin1String("2007-03-27")); s.setStartDate(QDate(2007, 1, 28)); QCOMPARE(s.dateAfter(2).toString(format), QLatin1String("2007-02-13")); QCOMPARE(s.dateAfter(3).toString(format), QLatin1String("2007-02-28")); QCOMPARE(s.dateAfter(4).toString(format), QLatin1String("2007-03-15")); QCOMPARE(s.dateAfter(5).toString(format), QLatin1String("2007-03-31")); s.setStartDate(QDate(2007, 1, 29)); QCOMPARE(s.dateAfter(2).toString(format), QLatin1String("2007-02-14")); QCOMPARE(s.dateAfter(3).toString(format), QLatin1String("2007-02-28")); QCOMPARE(s.dateAfter(4).toString(format), QLatin1String("2007-03-15")); QCOMPARE(s.dateAfter(5).toString(format), QLatin1String("2007-03-31")); s.setStartDate(QDate(2007, 1, 30)); QCOMPARE(s.dateAfter(2).toString(format), QLatin1String("2007-02-15")); QCOMPARE(s.dateAfter(3).toString(format), QLatin1String("2007-02-28")); QCOMPARE(s.dateAfter(4).toString(format), QLatin1String("2007-03-15")); QCOMPARE(s.dateAfter(5).toString(format), QLatin1String("2007-03-31")); s.setStartDate(QDate(2007, 1, 31)); QCOMPARE(s.dateAfter(2).toString(format), QLatin1String("2007-02-15")); QCOMPARE(s.dateAfter(3).toString(format), QLatin1String("2007-02-28")); QCOMPARE(s.dateAfter(4).toString(format), QLatin1String("2007-03-15")); QCOMPARE(s.dateAfter(5).toString(format), QLatin1String("2007-03-31")); s.setStartDate(QDate(2007, 4, 29)); QCOMPARE(s.dateAfter(2).toString(format), QLatin1String("2007-05-14")); QCOMPARE(s.dateAfter(3).toString(format), QLatin1String("2007-05-29")); QCOMPARE(s.dateAfter(4).toString(format), QLatin1String("2007-06-14")); QCOMPARE(s.dateAfter(5).toString(format), QLatin1String("2007-06-29")); s.setStartDate(QDate(2007, 4, 30)); QCOMPARE(s.dateAfter(2).toString(format), QLatin1String("2007-05-15")); QCOMPARE(s.dateAfter(3).toString(format), QLatin1String("2007-05-31")); QCOMPARE(s.dateAfter(4).toString(format), QLatin1String("2007-06-15")); QCOMPARE(s.dateAfter(5).toString(format), QLatin1String("2007-06-30")); } void MyMoneyScheduleTest::testPaymentDates() { MyMoneySchedule sch; QString ref_ok = QString( "\n" "\n" "\n" // krazy:exclude=spelling " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "\n" "\n" ); QDomDocument doc; QDomElement node; doc.setContent(ref_ok); node = doc.documentElement().firstChild().toElement(); QDate startDate(2006, 1, 28); QDate endDate(2006, 5, 30); try { sch = MyMoneySchedule(node); QDate nextPayment = sch.nextPayment(startDate); QList list = sch.paymentDates(nextPayment, endDate); QCOMPARE(list.count(), 3); QCOMPARE(list[0], QDate(2006, 2, 28)); QCOMPARE(list[1], QDate(2006, 3, 31)); // Would fall on a Sunday so gets moved back to 28th. QCOMPARE(list[2], QDate(2006, 4, 28)); // Add tests for each possible occurrence. // Check how paymentDates is meant to work // Build a list of expected dates and compare // Schedule::Occurrence::Once sch.setOccurrence(Schedule::Occurrence::Once); startDate.setDate(2009, 1, 1); endDate.setDate(2009, 12, 31); sch.setStartDate(startDate); sch.setNextDueDate(startDate); list = sch.paymentDates(startDate, endDate); QCOMPARE(list.count(), 1); QCOMPARE(list[0], QDate(2009, 1, 1)); // Schedule::Occurrence::Daily sch.setOccurrence(Schedule::Occurrence::Daily); startDate.setDate(2009, 1, 1); endDate.setDate(2009, 1, 5); sch.setStartDate(startDate); sch.setNextDueDate(startDate); list = sch.paymentDates(startDate, endDate); QCOMPARE(list.count(), 5); QCOMPARE(list[0], QDate(2009, 1, 1)); QCOMPARE(list[1], QDate(2009, 1, 2)); // Would fall on Saturday so gets moved to 2nd. QCOMPARE(list[2], QDate(2009, 1, 2)); // Would fall on Sunday so gets moved to 2nd. QCOMPARE(list[3], QDate(2009, 1, 2)); QCOMPARE(list[4], QDate(2009, 1, 5)); // Schedule::Occurrence::Daily with multiplier 2 sch.setOccurrenceMultiplier(2); list = sch.paymentDates(startDate.addDays(1), endDate); QCOMPARE(list.count(), 2); // Would fall on Sunday so gets moved to 2nd. QCOMPARE(list[0], QDate(2009, 1, 2)); QCOMPARE(list[1], QDate(2009, 1, 5)); sch.setOccurrenceMultiplier(1); // Schedule::Occurrence::Weekly sch.setOccurrence(Schedule::Occurrence::Weekly); startDate.setDate(2009, 1, 6); endDate.setDate(2009, 2, 4); sch.setStartDate(startDate); sch.setNextDueDate(startDate); list = sch.paymentDates(startDate, endDate); QCOMPARE(list.count(), 5); QCOMPARE(list[0], QDate(2009, 1, 6)); QCOMPARE(list[1], QDate(2009, 1, 13)); QCOMPARE(list[2], QDate(2009, 1, 20)); QCOMPARE(list[3], QDate(2009, 1, 27)); QCOMPARE(list[4], QDate(2009, 2, 3)); // Schedule::Occurrence::EveryOtherWeek sch.setOccurrence(Schedule::Occurrence::EveryOtherWeek); startDate.setDate(2009, 2, 5); endDate.setDate(2009, 4, 3); sch.setStartDate(startDate); sch.setNextDueDate(startDate); list = sch.paymentDates(startDate, endDate); QCOMPARE(list.count(), 5); QCOMPARE(list[0], QDate(2009, 2, 5)); QCOMPARE(list[1], QDate(2009, 2, 19)); QCOMPARE(list[2], QDate(2009, 3, 5)); QCOMPARE(list[3], QDate(2009, 3, 19)); QCOMPARE(list[4], QDate(2009, 4, 2)); // Schedule::Occurrence::Fortnightly sch.setOccurrence(Schedule::Occurrence::Fortnightly); startDate.setDate(2009, 4, 4); endDate.setDate(2009, 5, 31); sch.setStartDate(startDate); sch.setNextDueDate(startDate); list = sch.paymentDates(startDate, endDate); QCOMPARE(list.count(), 4); // First one would fall on a Saturday and would get moved // to 3rd which is before start date so is not in list. // Would fall on a Saturday so gets moved to 17th. QCOMPARE(list[0], QDate(2009, 4, 17)); // Would fall on a Saturday so gets moved to 1st. QCOMPARE(list[1], QDate(2009, 5, 1)); // Would fall on a Saturday so gets moved to 15th. QCOMPARE(list[2], QDate(2009, 5, 15)); // Would fall on a Saturday so gets moved to 29th. QCOMPARE(list[3], QDate(2009, 5, 29)); // Schedule::Occurrence::EveryHalfMonth sch.setOccurrence(Schedule::Occurrence::EveryHalfMonth); startDate.setDate(2009, 6, 1); endDate.setDate(2009, 8, 11); sch.setStartDate(startDate); sch.setNextDueDate(startDate); list = sch.paymentDates(startDate, endDate); QCOMPARE(list.count(), 5); QCOMPARE(list[0], QDate(2009, 6, 1)); QCOMPARE(list[1], QDate(2009, 6, 16)); QCOMPARE(list[2], QDate(2009, 7, 1)); QCOMPARE(list[3], QDate(2009, 7, 16)); // Would fall on a Saturday so gets moved to 31st. QCOMPARE(list[4], QDate(2009, 7, 31)); // Schedule::Occurrence::EveryThreeWeeks sch.setOccurrence(Schedule::Occurrence::EveryThreeWeeks); startDate.setDate(2009, 8, 12); endDate.setDate(2009, 11, 12); sch.setStartDate(startDate); sch.setNextDueDate(startDate); list = sch.paymentDates(startDate, endDate); QCOMPARE(list.count(), 5); QCOMPARE(list[0], QDate(2009, 8, 12)); QCOMPARE(list[1], QDate(2009, 9, 2)); QCOMPARE(list[2], QDate(2009, 9, 23)); QCOMPARE(list[3], QDate(2009, 10, 14)); QCOMPARE(list[4], QDate(2009, 11, 4)); // Schedule::Occurrence::EveryFourWeeks sch.setOccurrence(Schedule::Occurrence::EveryFourWeeks); startDate.setDate(2009, 11, 13); endDate.setDate(2010, 3, 13); sch.setStartDate(startDate); sch.setNextDueDate(startDate); list = sch.paymentDates(startDate, endDate); QCOMPARE(list.count(), 5); QCOMPARE(list[0], QDate(2009, 11, 13)); QCOMPARE(list[1], QDate(2009, 12, 11)); QCOMPARE(list[2], QDate(2010, 1, 8)); QCOMPARE(list[3], QDate(2010, 2, 5)); QCOMPARE(list[4], QDate(2010, 3, 5)); // Schedule::Occurrence::EveryThirtyDays sch.setOccurrence(Schedule::Occurrence::EveryThirtyDays); startDate.setDate(2010, 3, 19); endDate.setDate(2010, 7, 19); sch.setStartDate(startDate); sch.setNextDueDate(startDate); list = sch.paymentDates(startDate, endDate); QCOMPARE(list.count(), 5); QCOMPARE(list[0], QDate(2010, 3, 19)); // Would fall on a Sunday so gets moved to 16th. QCOMPARE(list[1], QDate(2010, 4, 16)); QCOMPARE(list[2], QDate(2010, 5, 18)); QCOMPARE(list[3], QDate(2010, 6, 17)); // Would fall on a Saturday so gets moved to 16th. QCOMPARE(list[4], QDate(2010, 7, 16)); // Schedule::Occurrence::EveryEightWeeks sch.setOccurrence(Schedule::Occurrence::EveryEightWeeks); startDate.setDate(2010, 7, 26); endDate.setDate(2011, 3, 26); sch.setStartDate(startDate); sch.setNextDueDate(startDate); list = sch.paymentDates(startDate, endDate); QCOMPARE(list.count(), 5); QCOMPARE(list[0], QDate(2010, 7, 26)); QCOMPARE(list[1], QDate(2010, 9, 20)); QCOMPARE(list[2], QDate(2010, 11, 15)); QCOMPARE(list[3], QDate(2011, 1, 10)); QCOMPARE(list[4], QDate(2011, 3, 7)); // Schedule::Occurrence::EveryOtherMonth sch.setOccurrence(Schedule::Occurrence::EveryOtherMonth); startDate.setDate(2011, 3, 14); endDate.setDate(2011, 11, 20); sch.setStartDate(startDate); sch.setNextDueDate(startDate); list = sch.paymentDates(startDate, endDate); QCOMPARE(list.count(), 5); QCOMPARE(list[0], QDate(2011, 3, 14)); // Would fall on a Saturday so gets moved to 13th. QCOMPARE(list[1], QDate(2011, 5, 13)); QCOMPARE(list[2], QDate(2011, 7, 14)); QCOMPARE(list[3], QDate(2011, 9, 14)); QCOMPARE(list[4], QDate(2011, 11, 14)); // Schedule::Occurrence::EveryThreeMonths sch.setOccurrence(Schedule::Occurrence::EveryThreeMonths); startDate.setDate(2011, 11, 15); endDate.setDate(2012, 11, 19); sch.setStartDate(startDate); sch.setNextDueDate(startDate); list = sch.paymentDates(startDate, endDate); QCOMPARE(list.count(), 5); QCOMPARE(list[0], QDate(2011, 11, 15)); QCOMPARE(list[1], QDate(2012, 2, 15)); QCOMPARE(list[2], QDate(2012, 5, 15)); QCOMPARE(list[3], QDate(2012, 8, 15)); QCOMPARE(list[4], QDate(2012, 11, 15)); // Schedule::Occurrence::Quarterly sch.setOccurrence(Schedule::Occurrence::Quarterly); startDate.setDate(2012, 11, 20); endDate.setDate(2013, 11, 23); sch.setStartDate(startDate); sch.setNextDueDate(startDate); list = sch.paymentDates(startDate, endDate); QCOMPARE(list.count(), 5); QCOMPARE(list[0], QDate(2012, 11, 20)); QCOMPARE(list[1], QDate(2013, 2, 20)); QCOMPARE(list[2], QDate(2013, 5, 20)); QCOMPARE(list[3], QDate(2013, 8, 20)); QCOMPARE(list[4], QDate(2013, 11, 20)); // Schedule::Occurrence::EveryFourMonths sch.setOccurrence(Schedule::Occurrence::EveryFourMonths); startDate.setDate(2013, 11, 21); endDate.setDate(2015, 3, 23); sch.setStartDate(startDate); sch.setNextDueDate(startDate); list = sch.paymentDates(startDate, endDate); QCOMPARE(list.count(), 5); QCOMPARE(list[0], QDate(2013, 11, 21)); QCOMPARE(list[1], QDate(2014, 3, 21)); QCOMPARE(list[2], QDate(2014, 7, 21)); QCOMPARE(list[3], QDate(2014, 11, 21)); // Would fall on a Saturday so gets moved to 20th. QCOMPARE(list[4], QDate(2015, 3, 20)); // Schedule::Occurrence::TwiceYearly sch.setOccurrence(Schedule::Occurrence::TwiceYearly); startDate.setDate(2015, 3, 22); endDate.setDate(2017, 3, 29); sch.setStartDate(startDate); sch.setNextDueDate(startDate); list = sch.paymentDates(startDate, endDate); QCOMPARE(list.count(), 4); // First date would fall on a Sunday which would get moved // to 20th which is before start date so not in list. QCOMPARE(list[0], QDate(2015, 9, 22)); QCOMPARE(list[1], QDate(2016, 3, 22)); QCOMPARE(list[2], QDate(2016, 9, 22)); QCOMPARE(list[3], QDate(2017, 3, 22)); // Schedule::Occurrence::Yearly sch.setOccurrence(Schedule::Occurrence::Yearly); startDate.setDate(2017, 3, 23); endDate.setDate(2021, 3, 29); sch.setStartDate(startDate); sch.setNextDueDate(startDate); list = sch.paymentDates(startDate, endDate); QCOMPARE(list.count(), 5); QCOMPARE(list[0], QDate(2017, 3, 23)); QCOMPARE(list[1], QDate(2018, 3, 23)); // Would fall on a Saturday so gets moved to 22nd. QCOMPARE(list[2], QDate(2019, 3, 22)); QCOMPARE(list[3], QDate(2020, 3, 23)); QCOMPARE(list[4], QDate(2021, 3, 23)); // Schedule::Occurrence::EveryOtherYear sch.setOccurrence(Schedule::Occurrence::EveryOtherYear); startDate.setDate(2021, 3, 24); endDate.setDate(2029, 3, 30); sch.setStartDate(startDate); sch.setNextDueDate(startDate); list = sch.paymentDates(startDate, endDate); QCOMPARE(list.count(), 5); QCOMPARE(list[0], QDate(2021, 3, 24)); QCOMPARE(list[1], QDate(2023, 3, 24)); QCOMPARE(list[2], QDate(2025, 3, 24)); QCOMPARE(list[3], QDate(2027, 3, 24)); // Would fall on a Saturday so gets moved to 23rd. QCOMPARE(list[4], QDate(2029, 3, 23)); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } } void MyMoneyScheduleTest::testWriteXML() { MyMoneySchedule sch("A Name", Schedule::Type::Bill, Schedule::Occurrence::Weekly, 123, Schedule::PaymentType::DirectDebit, QDate::currentDate(), QDate(), true, true); sch.setLastPayment(QDate::currentDate()); sch.recordPayment(QDate::currentDate()); sch.setId("SCH0001"); MyMoneyTransaction t; t.setPostDate(QDate(2001, 12, 28)); t.setEntryDate(QDate(2003, 9, 29)); t.setId("T000000000000000001"); t.setMemo("Wohnung:Miete"); t.setCommodity("EUR"); t.setValue("key", "value"); MyMoneySplit s; s.setPayeeId("P000001"); s.setShares(MyMoneyMoney(96379, 100)); s.setValue(MyMoneyMoney(96379, 100)); s.setAccountId("A000076"); s.setBankID("SPID1"); s.setReconcileFlag(eMyMoney::Split::State::Reconciled); t.addSplit(s); s.setPayeeId("P000001"); s.setShares(MyMoneyMoney(-96379, 100)); s.setValue(MyMoneyMoney(-96379, 100)); s.setAccountId("A000276"); s.setBankID("SPID2"); s.setReconcileFlag(eMyMoney::Split::State::Cleared); s.clearId(); t.addSplit(s); sch.setTransaction(t); QDomDocument doc("TEST"); QDomElement el = doc.createElement("SCHEDULE-CONTAINER"); doc.appendChild(el); sch.writeXML(doc, el); QCOMPARE(doc.doctype().name(), QLatin1String("TEST")); QDomElement scheduleContainer = doc.documentElement(); QVERIFY(scheduleContainer.isElement()); QCOMPARE(scheduleContainer.tagName(), QLatin1String("SCHEDULE-CONTAINER")); QCOMPARE(scheduleContainer.childNodes().size(), 1); QVERIFY(scheduleContainer.childNodes().at(0).isElement()); QDomElement schedule = scheduleContainer.childNodes().at(0).toElement(); QCOMPARE(schedule.tagName(), QLatin1String("SCHEDULED_TX")); QCOMPARE(schedule.attribute("id"), QLatin1String("SCH0001")); QCOMPARE(schedule.attribute("paymentType"), QLatin1String("1")); QCOMPARE(schedule.attribute("autoEnter"), QLatin1String("1")); QCOMPARE(schedule.attribute("occurenceMultiplier"), QLatin1String("123")); QCOMPARE(schedule.attribute("startDate"), QDate::currentDate().toString(Qt::ISODate)); QCOMPARE(schedule.attribute("lastPayment"), QDate::currentDate().toString(Qt::ISODate)); QCOMPARE(schedule.attribute("occurenceMultiplier"), QLatin1String("123")); QCOMPARE(schedule.attribute("occurence"), QLatin1String("4")); QCOMPARE(schedule.attribute("type"), QLatin1String("1")); QCOMPARE(schedule.attribute("name"), QLatin1String("A Name")); QCOMPARE(schedule.attribute("fixed"), QLatin1String("1")); QCOMPARE(schedule.attribute("endDate"), QString()); QCOMPARE(schedule.childNodes().size(), 2); QVERIFY(schedule.childNodes().at(0).isElement()); QDomElement payments = schedule.childNodes().at(0).toElement(); QVERIFY(schedule.childNodes().at(1).isElement()); QDomElement transaction = schedule.childNodes().at(1).toElement(); QCOMPARE(transaction.tagName(), QLatin1String("TRANSACTION")); QCOMPARE(transaction.attribute("id"), QString()); QCOMPARE(transaction.attribute("postdate"), QLatin1String("2001-12-28")); QCOMPARE(transaction.attribute("commodity"), QLatin1String("EUR")); QCOMPARE(transaction.attribute("memo"), QLatin1String("Wohnung:Miete")); QCOMPARE(transaction.attribute("entrydate"), QLatin1String("2003-09-29")); QCOMPARE(transaction.childNodes().size(), 2); QVERIFY(transaction.childNodes().at(0).isElement()); QDomElement splits = transaction.childNodes().at(0).toElement(); QCOMPARE(splits.tagName(), QLatin1String("SPLITS")); QCOMPARE(splits.childNodes().size(), 2); QVERIFY(splits.childNodes().at(0).isElement()); QDomElement split1 = splits.childNodes().at(0).toElement(); QCOMPARE(split1.tagName(), QLatin1String("SPLIT")); QCOMPARE(split1.attribute("id"), QLatin1String("S0001")); QCOMPARE(split1.attribute("payee"), QLatin1String("P000001")); QCOMPARE(split1.attribute("reconcileflag"), QLatin1String("2")); QCOMPARE(split1.attribute("shares"), QLatin1String("96379/100")); QCOMPARE(split1.attribute("reconciledate"), QString()); QCOMPARE(split1.attribute("action"), QString()); QCOMPARE(split1.attribute("bankid"), QString()); QCOMPARE(split1.attribute("account"), QLatin1String("A000076")); QCOMPARE(split1.attribute("number"), QString()); QCOMPARE(split1.attribute("value"), QLatin1String("96379/100")); QCOMPARE(split1.attribute("memo"), QString()); QCOMPARE(split1.childNodes().size(), 0); QVERIFY(splits.childNodes().at(1).isElement()); QDomElement split2 = splits.childNodes().at(1).toElement(); QCOMPARE(split2.tagName(), QLatin1String("SPLIT")); QCOMPARE(split2.attribute("id"), QLatin1String("S0002")); QCOMPARE(split2.attribute("payee"), QLatin1String("P000001")); QCOMPARE(split2.attribute("reconcileflag"), QLatin1String("1")); QCOMPARE(split2.attribute("shares"), QLatin1String("-96379/100")); QCOMPARE(split2.attribute("reconciledate"), QString()); QCOMPARE(split2.attribute("action"), QString()); QCOMPARE(split2.attribute("bankid"), QString()); QCOMPARE(split2.attribute("account"), QLatin1String("A000276")); QCOMPARE(split2.attribute("number"), QString()); QCOMPARE(split2.attribute("value"), QLatin1String("-96379/100")); QCOMPARE(split2.attribute("memo"), QString()); QCOMPARE(split2.childNodes().size(), 0); QDomElement keyValuePairs = transaction.childNodes().at(1).toElement(); QCOMPARE(keyValuePairs.tagName(), QLatin1String("KEYVALUEPAIRS")); QCOMPARE(keyValuePairs.childNodes().size(), 1); QVERIFY(keyValuePairs.childNodes().at(0).isElement()); QDomElement keyValuePair1 = keyValuePairs.childNodes().at(0).toElement(); QCOMPARE(keyValuePair1.tagName(), QLatin1String("PAIR")); QCOMPARE(keyValuePair1.attribute("key"), QLatin1String("key")); QCOMPARE(keyValuePair1.attribute("value"), QLatin1String("value")); QCOMPARE(keyValuePair1.childNodes().size(), 0); } void MyMoneyScheduleTest::testReadXML() { MyMoneySchedule sch; QString ref_ok1 = QString( "\n" "\n" " \n" // krazy:exclude=spelling " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "\n" ).arg(QDate::currentDate().toString(Qt::ISODate)) .arg(QDate::currentDate().toString(Qt::ISODate)) .arg(QDate::currentDate().toString(Qt::ISODate)); // diff to ref_ok1 is that we now have an empty entrydate // in the transaction parameters QString ref_ok2 = QString( "\n" "\n" " \n" // krazy:exclude=spelling " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "\n" ).arg(QDate::currentDate().toString(Qt::ISODate)) .arg(QDate::currentDate().toString(Qt::ISODate)) .arg(QDate::currentDate().toString(Qt::ISODate)); QString ref_false = QString( "\n" "\n" " \n" // krazy:exclude=spelling " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "\n" ).arg(QDate::currentDate().toString(Qt::ISODate)) .arg(QDate::currentDate().toString(Qt::ISODate)) .arg(QDate::currentDate().toString(Qt::ISODate)); QDomDocument doc; QDomElement node; doc.setContent(ref_false); node = doc.documentElement().firstChild().toElement(); try { sch = MyMoneySchedule(node); QFAIL("Missing expected exception"); } catch (const MyMoneyException &) { } doc.setContent(ref_ok1); node = doc.documentElement().firstChild().toElement(); try { sch = MyMoneySchedule(node); QCOMPARE(sch.id(), QLatin1String("SCH0002")); QCOMPARE(sch.nextDueDate(), QDate::currentDate().addDays(7)); QCOMPARE(sch.startDate(), QDate::currentDate()); QCOMPARE(sch.endDate(), QDate()); QCOMPARE(sch.autoEnter(), true); QCOMPARE(sch.isFixed(), true); QCOMPARE(sch.weekendOption(), Schedule::WeekendOption::MoveNothing); QCOMPARE(sch.lastPayment(), QDate::currentDate()); QCOMPARE(sch.paymentType(), Schedule::PaymentType::DirectDebit); QCOMPARE(sch.type(), Schedule::Type::Bill); QCOMPARE(sch.name(), QLatin1String("A Name")); QCOMPARE(sch.occurrence(), Schedule::Occurrence::Weekly); QCOMPARE(sch.occurrenceMultiplier(), 1); QCOMPARE(sch.nextDueDate(), sch.lastPayment().addDays(7)); QCOMPARE(sch.recordedPayments().count(), 1); QCOMPARE(sch.recordedPayments()[0], QDate::currentDate()); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } doc.setContent(ref_ok2); node = doc.documentElement().firstChild().toElement(); try { sch = MyMoneySchedule(node); QCOMPARE(sch.id(), QLatin1String("SCH0002")); QCOMPARE(sch.nextDueDate(), QDate::currentDate().addDays(7)); QCOMPARE(sch.startDate(), QDate::currentDate()); QCOMPARE(sch.endDate(), QDate()); QCOMPARE(sch.autoEnter(), true); QCOMPARE(sch.isFixed(), true); QCOMPARE(sch.weekendOption(), Schedule::WeekendOption::MoveNothing); QCOMPARE(sch.lastPayment(), QDate::currentDate()); QCOMPARE(sch.paymentType(), Schedule::PaymentType::DirectDebit); QCOMPARE(sch.type(), Schedule::Type::Bill); QCOMPARE(sch.name(), QLatin1String("A Name")); QCOMPARE(sch.occurrence(), Schedule::Occurrence::Weekly); QCOMPARE(sch.occurrenceMultiplier(), 1); QCOMPARE(sch.nextDueDate(), sch.lastPayment().addDays(7)); QCOMPARE(sch.recordedPayments().count(), 1); QCOMPARE(sch.recordedPayments()[0], QDate::currentDate()); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } } void MyMoneyScheduleTest::testHasReferenceTo() { MyMoneySchedule sch; QString ref_ok = QString( "\n" "\n" " \n" // krazy:exclude=spelling " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "\n" ).arg(QDate::currentDate().toString(Qt::ISODate)) .arg(QDate::currentDate().toString(Qt::ISODate)) .arg(QDate::currentDate().toString(Qt::ISODate)); QDomDocument doc; QDomElement node; doc.setContent(ref_ok); node = doc.documentElement().firstChild().toElement(); try { sch = MyMoneySchedule(node); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } QCOMPARE(sch.hasReferenceTo(QLatin1String("P000001")), true); QCOMPARE(sch.hasReferenceTo(QLatin1String("A000276")), true); QCOMPARE(sch.hasReferenceTo(QLatin1String("A000076")), true); QCOMPARE(sch.hasReferenceTo(QLatin1String("EUR")), true); } void MyMoneyScheduleTest::testAdjustedNextDueDate() { MyMoneySchedule s; QDate dueDate(2007, 9, 3); // start on a Monday for (int i = 0; i < 7; ++i) { s.setNextDueDate(dueDate); s.setWeekendOption(Schedule::WeekendOption::MoveNothing); QCOMPARE(s.adjustedNextDueDate(), dueDate); s.setWeekendOption(Schedule::WeekendOption::MoveBefore); switch (i) { case 5: // Saturday case 6: // Sunday QCOMPARE(s.adjustedNextDueDate(), QDate(2007, 9, 7)); break; default: QCOMPARE(s.adjustedNextDueDate(), dueDate); break; } s.setWeekendOption(Schedule::WeekendOption::MoveAfter); switch (i) { case 5: // Saturday case 6: // Sunday QCOMPARE(s.adjustedNextDueDate(), QDate(2007, 9, 10)); break; default: QCOMPARE(s.adjustedNextDueDate(), dueDate); break; } dueDate = dueDate.addDays(1); } } void MyMoneyScheduleTest::testModifyNextDueDate() { MyMoneySchedule s; s.setStartDate(QDate(2007, 1, 2)); s.setOccurrence(Schedule::Occurrence::Monthly); s.setNextDueDate(s.startDate().addMonths(1)); s.setLastPayment(s.startDate()); QList dates; dates = s.paymentDates(QDate(2007, 2, 2), QDate(2007, 2, 2)); QCOMPARE(s.nextDueDate(), QDate(2007, 2, 2)); QCOMPARE(dates.count(), 1); QCOMPARE(dates[0], QDate(2007, 2, 2)); s.setNextDueDate(QDate(2007, 1, 24)); dates = s.paymentDates(QDate(2007, 2, 1), QDate(2007, 2, 1)); QCOMPARE(s.nextDueDate(), QDate(2007, 1, 24)); QCOMPARE(dates.count(), 0); dates = s.paymentDates(QDate(2007, 1, 24), QDate(2007, 1, 24)); QCOMPARE(dates.count(), 1); dates = s.paymentDates(QDate(2007, 1, 24), QDate(2007, 2, 24)); QCOMPARE(dates.count(), 2); QCOMPARE(dates[0], QDate(2007, 1, 24)); QCOMPARE(dates[1], QDate(2007, 2, 2)); } void MyMoneyScheduleTest::testDaysBetweenEvents() { QCOMPARE(MyMoneySchedule::daysBetweenEvents(Schedule::Occurrence::Once), 0); QCOMPARE(MyMoneySchedule::daysBetweenEvents(Schedule::Occurrence::Daily), 1); QCOMPARE(MyMoneySchedule::daysBetweenEvents(Schedule::Occurrence::Weekly), 7); QCOMPARE(MyMoneySchedule::daysBetweenEvents(Schedule::Occurrence::EveryOtherWeek), 14); QCOMPARE(MyMoneySchedule::daysBetweenEvents(Schedule::Occurrence::Fortnightly), 14); QCOMPARE(MyMoneySchedule::daysBetweenEvents(Schedule::Occurrence::EveryHalfMonth), 15); QCOMPARE(MyMoneySchedule::daysBetweenEvents(Schedule::Occurrence::EveryThreeWeeks), 21); QCOMPARE(MyMoneySchedule::daysBetweenEvents(Schedule::Occurrence::EveryFourWeeks), 28); QCOMPARE(MyMoneySchedule::daysBetweenEvents(Schedule::Occurrence::EveryThirtyDays), 30); QCOMPARE(MyMoneySchedule::daysBetweenEvents(Schedule::Occurrence::Monthly), 30); QCOMPARE(MyMoneySchedule::daysBetweenEvents(Schedule::Occurrence::EveryEightWeeks), 56); QCOMPARE(MyMoneySchedule::daysBetweenEvents(Schedule::Occurrence::EveryOtherMonth), 60); QCOMPARE(MyMoneySchedule::daysBetweenEvents(Schedule::Occurrence::EveryThreeMonths), 90); QCOMPARE(MyMoneySchedule::daysBetweenEvents(Schedule::Occurrence::Quarterly), 90); QCOMPARE(MyMoneySchedule::daysBetweenEvents(Schedule::Occurrence::EveryFourMonths), 120); QCOMPARE(MyMoneySchedule::daysBetweenEvents(Schedule::Occurrence::TwiceYearly), 180); QCOMPARE(MyMoneySchedule::daysBetweenEvents(Schedule::Occurrence::Yearly), 360); QCOMPARE(MyMoneySchedule::daysBetweenEvents(Schedule::Occurrence::EveryOtherYear), 0); } void MyMoneyScheduleTest::testEventsPerYear() { QCOMPARE(MyMoneySchedule::eventsPerYear(Schedule::Occurrence::Once), 0); QCOMPARE(MyMoneySchedule::eventsPerYear(Schedule::Occurrence::Daily), 365); QCOMPARE(MyMoneySchedule::eventsPerYear(Schedule::Occurrence::Weekly), 52); QCOMPARE(MyMoneySchedule::eventsPerYear(Schedule::Occurrence::EveryOtherWeek), 26); QCOMPARE(MyMoneySchedule::eventsPerYear(Schedule::Occurrence::Fortnightly), 26); QCOMPARE(MyMoneySchedule::eventsPerYear(Schedule::Occurrence::EveryHalfMonth), 24); QCOMPARE(MyMoneySchedule::eventsPerYear(Schedule::Occurrence::EveryThreeWeeks), 17); QCOMPARE(MyMoneySchedule::eventsPerYear(Schedule::Occurrence::EveryFourWeeks), 13); QCOMPARE(MyMoneySchedule::eventsPerYear(Schedule::Occurrence::EveryThirtyDays), 12); QCOMPARE(MyMoneySchedule::eventsPerYear(Schedule::Occurrence::Monthly), 12); QCOMPARE(MyMoneySchedule::eventsPerYear(Schedule::Occurrence::EveryEightWeeks), 6); QCOMPARE(MyMoneySchedule::eventsPerYear(Schedule::Occurrence::EveryOtherMonth), 6); QCOMPARE(MyMoneySchedule::eventsPerYear(Schedule::Occurrence::EveryThreeMonths), 4); QCOMPARE(MyMoneySchedule::eventsPerYear(Schedule::Occurrence::Quarterly), 4); QCOMPARE(MyMoneySchedule::eventsPerYear(Schedule::Occurrence::EveryFourMonths), 3); QCOMPARE(MyMoneySchedule::eventsPerYear(Schedule::Occurrence::TwiceYearly), 2); QCOMPARE(MyMoneySchedule::eventsPerYear(Schedule::Occurrence::Yearly), 1); QCOMPARE(MyMoneySchedule::eventsPerYear(Schedule::Occurrence::EveryOtherYear), 0); } void MyMoneyScheduleTest::testOccurrenceToString() { // For each occurrenceE test MyMoneySchedule::occurrenceToString(occurrenceE) QCOMPARE(MyMoneySchedule::occurrenceToString(Schedule::Occurrence::Once), QLatin1String("Once")); QCOMPARE(MyMoneySchedule::occurrenceToString(Schedule::Occurrence::Daily), QLatin1String("Daily")); QCOMPARE(MyMoneySchedule::occurrenceToString(Schedule::Occurrence::Weekly), QLatin1String("Weekly")); QCOMPARE(MyMoneySchedule::occurrenceToString(Schedule::Occurrence::EveryOtherWeek), QLatin1String("Every other week")); QCOMPARE(MyMoneySchedule::occurrenceToString(Schedule::Occurrence::Fortnightly), QLatin1String("Fortnightly")); QCOMPARE(MyMoneySchedule::occurrenceToString(Schedule::Occurrence::EveryHalfMonth), QLatin1String("Every half month")); QCOMPARE(MyMoneySchedule::occurrenceToString(Schedule::Occurrence::EveryThreeWeeks), QLatin1String("Every three weeks")); QCOMPARE(MyMoneySchedule::occurrenceToString(Schedule::Occurrence::EveryFourWeeks), QLatin1String("Every four weeks")); QCOMPARE(MyMoneySchedule::occurrenceToString(Schedule::Occurrence::EveryThirtyDays), QLatin1String("Every thirty days")); QCOMPARE(MyMoneySchedule::occurrenceToString(Schedule::Occurrence::Monthly), QLatin1String("Monthly")); QCOMPARE(MyMoneySchedule::occurrenceToString(Schedule::Occurrence::EveryEightWeeks), QLatin1String("Every eight weeks")); QCOMPARE(MyMoneySchedule::occurrenceToString(Schedule::Occurrence::EveryOtherMonth), QLatin1String("Every two months")); QCOMPARE(MyMoneySchedule::occurrenceToString(Schedule::Occurrence::EveryThreeMonths), QLatin1String("Every three months")); QCOMPARE(MyMoneySchedule::occurrenceToString(Schedule::Occurrence::Quarterly), QLatin1String("Quarterly")); QCOMPARE(MyMoneySchedule::occurrenceToString(Schedule::Occurrence::EveryFourMonths), QLatin1String("Every four months")); QCOMPARE(MyMoneySchedule::occurrenceToString(Schedule::Occurrence::TwiceYearly), QLatin1String("Twice yearly")); QCOMPARE(MyMoneySchedule::occurrenceToString(Schedule::Occurrence::Yearly), QLatin1String("Yearly")); QCOMPARE(MyMoneySchedule::occurrenceToString(Schedule::Occurrence::EveryOtherYear), QLatin1String("Every other year")); // For each occurrenceE set occurrence and compare occurrenceToString() with oTS(occurrence()) MyMoneySchedule s; s.setStartDate(QDate(2007, 1, 1)); s.setNextDueDate(s.startDate()); s.setLastPayment(s.startDate()); s.setOccurrence(Schedule::Occurrence::Once); QCOMPARE(s.occurrenceToString(), QLatin1String("Once")); s.setOccurrence(Schedule::Occurrence::Daily); QCOMPARE(s.occurrenceToString(), QLatin1String("Daily")); s.setOccurrence(Schedule::Occurrence::Weekly); QCOMPARE(s.occurrenceToString(), QLatin1String("Weekly")); s.setOccurrence(Schedule::Occurrence::EveryOtherWeek); QCOMPARE(s.occurrenceToString(), QLatin1String("Every other week")); // Fortnightly no longer used: Every other week used instead s.setOccurrence(Schedule::Occurrence::Fortnightly); QCOMPARE(s.occurrenceToString(), QLatin1String("Every other week")); s.setOccurrence(Schedule::Occurrence::EveryHalfMonth); QCOMPARE(s.occurrenceToString(), QLatin1String("Every half month")); s.setOccurrence(Schedule::Occurrence::EveryThreeWeeks); QCOMPARE(s.occurrenceToString(), QLatin1String("Every three weeks")); s.setOccurrence(Schedule::Occurrence::EveryFourWeeks); QCOMPARE(s.occurrenceToString(), QLatin1String("Every four weeks")); s.setOccurrence(Schedule::Occurrence::EveryThirtyDays); QCOMPARE(s.occurrenceToString(), QLatin1String("Every thirty days")); s.setOccurrence(Schedule::Occurrence::Monthly); QCOMPARE(s.occurrenceToString(), QLatin1String("Monthly")); s.setOccurrence(Schedule::Occurrence::EveryEightWeeks); QCOMPARE(s.occurrenceToString(), QLatin1String("Every eight weeks")); s.setOccurrence(Schedule::Occurrence::EveryOtherMonth); QCOMPARE(s.occurrenceToString(), QLatin1String("Every two months")); s.setOccurrence(Schedule::Occurrence::EveryThreeMonths); QCOMPARE(s.occurrenceToString(), QLatin1String("Every three months")); // Quarterly no longer used. Every three months used instead s.setOccurrence(Schedule::Occurrence::Quarterly); QCOMPARE(s.occurrenceToString(), QLatin1String("Every three months")); s.setOccurrence(Schedule::Occurrence::EveryFourMonths); QCOMPARE(s.occurrenceToString(), QLatin1String("Every four months")); s.setOccurrence(Schedule::Occurrence::TwiceYearly); QCOMPARE(s.occurrenceToString(), QLatin1String("Twice yearly")); s.setOccurrence(Schedule::Occurrence::Yearly); QCOMPARE(s.occurrenceToString(), QLatin1String("Yearly")); s.setOccurrence(Schedule::Occurrence::EveryOtherYear); QCOMPARE(s.occurrenceToString(), QLatin1String("Every other year")); // Test occurrenceToString(mult,occ) // Test all pairs equivalent to simple occurrences: should return the same as occurrenceToString(simpleOcc) // TODO replace string with (mult,occ) call. QCOMPARE(MyMoneySchedule::occurrenceToString(Schedule::Occurrence::Once), MyMoneySchedule::occurrenceToString(1, Schedule::Occurrence::Once)); QCOMPARE(MyMoneySchedule::occurrenceToString(Schedule::Occurrence::Daily), MyMoneySchedule::occurrenceToString(1, Schedule::Occurrence::Daily)); QCOMPARE(MyMoneySchedule::occurrenceToString(Schedule::Occurrence::Weekly), MyMoneySchedule::occurrenceToString(1, Schedule::Occurrence::Weekly)); QCOMPARE(MyMoneySchedule::occurrenceToString(Schedule::Occurrence::EveryOtherWeek), MyMoneySchedule::occurrenceToString(2, Schedule::Occurrence::Weekly)); // Fortnightly will no longer be used: only Every Other Week QCOMPARE(MyMoneySchedule::occurrenceToString(Schedule::Occurrence::EveryHalfMonth), MyMoneySchedule::occurrenceToString(1, Schedule::Occurrence::EveryHalfMonth)); QCOMPARE(MyMoneySchedule::occurrenceToString(Schedule::Occurrence::EveryThreeWeeks), MyMoneySchedule::occurrenceToString(3, Schedule::Occurrence::Weekly)); QCOMPARE(MyMoneySchedule::occurrenceToString(Schedule::Occurrence::EveryFourWeeks), MyMoneySchedule::occurrenceToString(4, Schedule::Occurrence::Weekly)); QCOMPARE(MyMoneySchedule::occurrenceToString(Schedule::Occurrence::Monthly), MyMoneySchedule::occurrenceToString(1, Schedule::Occurrence::Monthly)); QCOMPARE(MyMoneySchedule::occurrenceToString(Schedule::Occurrence::EveryEightWeeks), MyMoneySchedule::occurrenceToString(8, Schedule::Occurrence::Weekly)); QCOMPARE(MyMoneySchedule::occurrenceToString(Schedule::Occurrence::EveryOtherMonth), MyMoneySchedule::occurrenceToString(2, Schedule::Occurrence::Monthly)); QCOMPARE(MyMoneySchedule::occurrenceToString(Schedule::Occurrence::EveryThreeMonths), MyMoneySchedule::occurrenceToString(3, Schedule::Occurrence::Monthly)); // Quarterly will no longer be used: only Every Three Months QCOMPARE(MyMoneySchedule::occurrenceToString(Schedule::Occurrence::EveryFourMonths), MyMoneySchedule::occurrenceToString(4, Schedule::Occurrence::Monthly)); QCOMPARE(MyMoneySchedule::occurrenceToString(Schedule::Occurrence::TwiceYearly), MyMoneySchedule::occurrenceToString(6, Schedule::Occurrence::Monthly)); QCOMPARE(MyMoneySchedule::occurrenceToString(Schedule::Occurrence::Yearly), MyMoneySchedule::occurrenceToString(1, Schedule::Occurrence::Yearly)); QCOMPARE(MyMoneySchedule::occurrenceToString(Schedule::Occurrence::EveryOtherYear), MyMoneySchedule::occurrenceToString(2, Schedule::Occurrence::Yearly)); // Test additional calls with other mult,occ QCOMPARE(MyMoneySchedule::occurrenceToString(2, Schedule::Occurrence::Once), QLatin1String("2 times")); QCOMPARE(MyMoneySchedule::occurrenceToString(2, Schedule::Occurrence::Daily), QLatin1String("Every 2 days")); QCOMPARE(MyMoneySchedule::occurrenceToString(5, Schedule::Occurrence::Weekly), QLatin1String("Every 5 weeks")); QCOMPARE(MyMoneySchedule::occurrenceToString(2, Schedule::Occurrence::EveryHalfMonth), QLatin1String("Every 2 half months")); QCOMPARE(MyMoneySchedule::occurrenceToString(5, Schedule::Occurrence::Monthly), QLatin1String("Every 5 months")); QCOMPARE(MyMoneySchedule::occurrenceToString(3, Schedule::Occurrence::Yearly), QLatin1String("Every 3 years")); QCOMPARE(MyMoneySchedule::occurrenceToString(37, Schedule::Occurrence::Once), QLatin1String("37 times")); QCOMPARE(MyMoneySchedule::occurrenceToString(43, Schedule::Occurrence::Daily), QLatin1String("Every 43 days")); QCOMPARE(MyMoneySchedule::occurrenceToString(61, Schedule::Occurrence::Weekly), QLatin1String("Every 61 weeks")); QCOMPARE(MyMoneySchedule::occurrenceToString(73, Schedule::Occurrence::EveryHalfMonth), QLatin1String("Every 73 half months")); QCOMPARE(MyMoneySchedule::occurrenceToString(83, Schedule::Occurrence::Monthly), QLatin1String("Every 83 months")); QCOMPARE(MyMoneySchedule::occurrenceToString(89, Schedule::Occurrence::Yearly), QLatin1String("Every 89 years")); // Test instance-level occurrenceToString method is using occurrencePeriod and multiplier // For each base occurrence set occurrencePeriod and multiplier s.setOccurrencePeriod(Schedule::Occurrence::Once); s.setOccurrenceMultiplier(1); s.setOccurrence(Schedule::Occurrence::Once); s.setOccurrenceMultiplier(1); QCOMPARE(s.occurrenceToString(), QLatin1String("Once")); s.setOccurrenceMultiplier(2); QCOMPARE(s.occurrenceToString(), QLatin1String("2 times")); s.setOccurrenceMultiplier(3); QCOMPARE(s.occurrenceToString(), QLatin1String("3 times")); s.setOccurrencePeriod(Schedule::Occurrence::Daily); s.setOccurrenceMultiplier(1); QCOMPARE(s.occurrenceToString(), QLatin1String("Daily")); s.setOccurrenceMultiplier(30); QCOMPARE(s.occurrenceToString(), QLatin1String("Every thirty days")); s.setOccurrenceMultiplier(3); QCOMPARE(s.occurrenceToString(), QLatin1String("Every 3 days")); s.setOccurrence(Schedule::Occurrence::Weekly); QCOMPARE(s.occurrenceToString(), QLatin1String("Weekly")); s.setOccurrenceMultiplier(2); QCOMPARE(s.occurrenceToString(), QLatin1String("Every other week")); s.setOccurrenceMultiplier(3); QCOMPARE(s.occurrenceToString(), QLatin1String("Every three weeks")); s.setOccurrenceMultiplier(4); QCOMPARE(s.occurrenceToString(), QLatin1String("Every four weeks")); s.setOccurrenceMultiplier(5); QCOMPARE(s.occurrenceToString(), QLatin1String("Every 5 weeks")); s.setOccurrenceMultiplier(7); QCOMPARE(s.occurrenceToString(), QLatin1String("Every 7 weeks")); s.setOccurrenceMultiplier(8); QCOMPARE(s.occurrenceToString(), QLatin1String("Every eight weeks")); s.setOccurrenceMultiplier(9); QCOMPARE(s.occurrenceToString(), QLatin1String("Every 9 weeks")); s.setOccurrence(Schedule::Occurrence::EveryHalfMonth); s.setOccurrenceMultiplier(1); QCOMPARE(s.occurrenceToString(), QLatin1String("Every half month")); s.setOccurrenceMultiplier(2); QCOMPARE(s.occurrenceToString(), QLatin1String("Every 2 half months")); s.setOccurrence(Schedule::Occurrence::Monthly); s.setOccurrenceMultiplier(1); QCOMPARE(s.occurrenceToString(), QLatin1String("Monthly")); s.setOccurrenceMultiplier(2); QCOMPARE(s.occurrenceToString(), QLatin1String("Every two months")); s.setOccurrenceMultiplier(3); QCOMPARE(s.occurrenceToString(), QLatin1String("Every three months")); s.setOccurrenceMultiplier(4); QCOMPARE(s.occurrenceToString(), QLatin1String("Every four months")); s.setOccurrenceMultiplier(5); QCOMPARE(s.occurrenceToString(), QLatin1String("Every 5 months")); s.setOccurrenceMultiplier(6); QCOMPARE(s.occurrenceToString(), QLatin1String("Twice yearly")); s.setOccurrenceMultiplier(7); QCOMPARE(s.occurrenceToString(), QLatin1String("Every 7 months")); s.setOccurrence(Schedule::Occurrence::Yearly); s.setOccurrenceMultiplier(1); QCOMPARE(s.occurrenceToString(), QLatin1String("Yearly")); s.setOccurrenceMultiplier(2); QCOMPARE(s.occurrenceToString(), QLatin1String("Every other year")); s.setOccurrenceMultiplier(3); QCOMPARE(s.occurrenceToString(), QLatin1String("Every 3 years")); } void MyMoneyScheduleTest::testOccurrencePeriodToString() { // For each occurrenceE test MyMoneySchedule::occurrencePeriodToString(occurrenceE) // Base occurrences are translated QCOMPARE(MyMoneySchedule::occurrencePeriodToString(Schedule::Occurrence::Once), QLatin1String("Once")); QCOMPARE(MyMoneySchedule::occurrencePeriodToString(Schedule::Occurrence::Daily), QLatin1String("Day")); QCOMPARE(MyMoneySchedule::occurrencePeriodToString(Schedule::Occurrence::Weekly), QLatin1String("Week")); QCOMPARE(MyMoneySchedule::occurrencePeriodToString(Schedule::Occurrence::EveryHalfMonth), QLatin1String("Half-month")); QCOMPARE(MyMoneySchedule::occurrencePeriodToString(Schedule::Occurrence::Monthly), QLatin1String("Month")); QCOMPARE(MyMoneySchedule::occurrencePeriodToString(Schedule::Occurrence::Yearly), QLatin1String("Year")); // All others are not translated so return Any QCOMPARE(MyMoneySchedule::occurrencePeriodToString(Schedule::Occurrence::EveryOtherWeek), QLatin1String("Any")); QCOMPARE(MyMoneySchedule::occurrencePeriodToString(Schedule::Occurrence::Fortnightly), QLatin1String("Any")); QCOMPARE(MyMoneySchedule::occurrencePeriodToString(Schedule::Occurrence::EveryThreeWeeks), QLatin1String("Any")); QCOMPARE(MyMoneySchedule::occurrencePeriodToString(Schedule::Occurrence::EveryFourWeeks), QLatin1String("Any")); QCOMPARE(MyMoneySchedule::occurrencePeriodToString(Schedule::Occurrence::EveryThirtyDays), QLatin1String("Any")); QCOMPARE(MyMoneySchedule::occurrencePeriodToString(Schedule::Occurrence::EveryEightWeeks), QLatin1String("Any")); QCOMPARE(MyMoneySchedule::occurrencePeriodToString(Schedule::Occurrence::EveryOtherMonth), QLatin1String("Any")); QCOMPARE(MyMoneySchedule::occurrencePeriodToString(Schedule::Occurrence::EveryThreeMonths), QLatin1String("Any")); QCOMPARE(MyMoneySchedule::occurrencePeriodToString(Schedule::Occurrence::Quarterly), QLatin1String("Any")); QCOMPARE(MyMoneySchedule::occurrencePeriodToString(Schedule::Occurrence::EveryFourMonths), QLatin1String("Any")); QCOMPARE(MyMoneySchedule::occurrencePeriodToString(Schedule::Occurrence::TwiceYearly), QLatin1String("Any")); QCOMPARE(MyMoneySchedule::occurrencePeriodToString(Schedule::Occurrence::EveryOtherYear), QLatin1String("Any")); } void MyMoneyScheduleTest::testOccurrencePeriod() { // Each occurrence: // Set occurrence using setOccurrencePeriod // occurrencePeriod should match what we set // occurrence depends on multiplier // TODO: // Once occurrence() and setOccurrence() are converting between compound and simple occurrences // we need to change the occurrence() check and add an occurrenceMultiplier() check MyMoneySchedule s; s.setStartDate(QDate(2007, 1, 1)); s.setNextDueDate(s.startDate()); s.setLastPayment(s.startDate()); // Set all base occurrences s.setOccurrencePeriod(Schedule::Occurrence::Once); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Once); s.setOccurrenceMultiplier(1); QCOMPARE(s.occurrenceMultiplier(), 1); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Once); QCOMPARE(s.occurrence(), Schedule::Occurrence::Once); s.setOccurrenceMultiplier(2); QCOMPARE(s.occurrenceMultiplier(), 2); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Once); QCOMPARE(s.occurrence(), Schedule::Occurrence::Once); s.setOccurrencePeriod(Schedule::Occurrence::Daily); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Daily); s.setOccurrenceMultiplier(1); QCOMPARE(s.occurrenceMultiplier(), 1); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Daily); QCOMPARE(s.occurrence(), Schedule::Occurrence::Daily); s.setOccurrenceMultiplier(30); QCOMPARE(s.occurrenceMultiplier(), 30); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Daily); QCOMPARE(s.occurrence(), Schedule::Occurrence::EveryThirtyDays); s.setOccurrenceMultiplier(2); QCOMPARE(s.occurrenceMultiplier(), 2); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Daily); QCOMPARE(s.occurrence(), Schedule::Occurrence::Daily); s.setOccurrencePeriod(Schedule::Occurrence::Weekly); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Weekly); s.setOccurrenceMultiplier(1); QCOMPARE(s.occurrenceMultiplier(), 1); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Weekly); QCOMPARE(s.occurrence(), Schedule::Occurrence::Weekly); s.setOccurrenceMultiplier(2); QCOMPARE(s.occurrenceMultiplier(), 2); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Weekly); QCOMPARE(s.occurrence(), Schedule::Occurrence::EveryOtherWeek); s.setOccurrenceMultiplier(3); QCOMPARE(s.occurrenceMultiplier(), 3); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Weekly); QCOMPARE(s.occurrence(), Schedule::Occurrence::EveryThreeWeeks); s.setOccurrenceMultiplier(4); QCOMPARE(s.occurrenceMultiplier(), 4); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Weekly); QCOMPARE(s.occurrence(), Schedule::Occurrence::EveryFourWeeks); s.setOccurrenceMultiplier(5); QCOMPARE(s.occurrenceMultiplier(), 5); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Weekly); QCOMPARE(s.occurrence(), Schedule::Occurrence::Weekly); s.setOccurrenceMultiplier(8); QCOMPARE(s.occurrenceMultiplier(), 8); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Weekly); QCOMPARE(s.occurrence(), Schedule::Occurrence::EveryEightWeeks); s.setOccurrencePeriod(Schedule::Occurrence::EveryHalfMonth); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::EveryHalfMonth); s.setOccurrenceMultiplier(1); QCOMPARE(s.occurrenceMultiplier(), 1); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::EveryHalfMonth); QCOMPARE(s.occurrence(), Schedule::Occurrence::EveryHalfMonth); s.setOccurrenceMultiplier(2); QCOMPARE(s.occurrenceMultiplier(), 2); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::EveryHalfMonth); QCOMPARE(s.occurrence(), Schedule::Occurrence::EveryHalfMonth); s.setOccurrencePeriod(Schedule::Occurrence::Monthly); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Monthly); s.setOccurrenceMultiplier(1); QCOMPARE(s.occurrenceMultiplier(), 1); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Monthly); QCOMPARE(s.occurrence(), Schedule::Occurrence::Monthly); s.setOccurrenceMultiplier(2); QCOMPARE(s.occurrenceMultiplier(), 2); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Monthly); QCOMPARE(s.occurrence(), Schedule::Occurrence::EveryOtherMonth); s.setOccurrenceMultiplier(3); QCOMPARE(s.occurrenceMultiplier(), 3); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Monthly); QCOMPARE(s.occurrence(), Schedule::Occurrence::EveryThreeMonths); s.setOccurrenceMultiplier(4); QCOMPARE(s.occurrenceMultiplier(), 4); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Monthly); QCOMPARE(s.occurrence(), Schedule::Occurrence::EveryFourMonths); s.setOccurrenceMultiplier(5); QCOMPARE(s.occurrenceMultiplier(), 5); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Monthly); QCOMPARE(s.occurrence(), Schedule::Occurrence::Monthly); s.setOccurrenceMultiplier(6); QCOMPARE(s.occurrenceMultiplier(), 6); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Monthly); QCOMPARE(s.occurrence(), Schedule::Occurrence::TwiceYearly); s.setOccurrencePeriod(Schedule::Occurrence::Yearly); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Yearly); s.setOccurrenceMultiplier(1); QCOMPARE(s.occurrenceMultiplier(), 1); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Yearly); QCOMPARE(s.occurrence(), Schedule::Occurrence::Yearly); s.setOccurrenceMultiplier(2); QCOMPARE(s.occurrenceMultiplier(), 2); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Yearly); QCOMPARE(s.occurrence(), Schedule::Occurrence::EveryOtherYear); s.setOccurrenceMultiplier(3); QCOMPARE(s.occurrenceMultiplier(), 3); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Yearly); QCOMPARE(s.occurrence(), Schedule::Occurrence::Yearly); // Set occurrence: check occurrence, Period and Multiplier s.setOccurrence(Schedule::Occurrence::Once); QCOMPARE(s.occurrence(), Schedule::Occurrence::Once); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Once); QCOMPARE(s.occurrenceMultiplier(), 1); s.setOccurrence(Schedule::Occurrence::Daily); QCOMPARE(s.occurrence(), Schedule::Occurrence::Daily); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Daily); QCOMPARE(s.occurrenceMultiplier(), 1); s.setOccurrence(Schedule::Occurrence::EveryThirtyDays); QCOMPARE(s.occurrence(), Schedule::Occurrence::EveryThirtyDays); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Daily); QCOMPARE(s.occurrenceMultiplier(), 30); s.setOccurrence(Schedule::Occurrence::Weekly); QCOMPARE(s.occurrence(), Schedule::Occurrence::Weekly); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Weekly); QCOMPARE(s.occurrenceMultiplier(), 1); s.setOccurrence(Schedule::Occurrence::EveryOtherWeek); QCOMPARE(s.occurrence(), Schedule::Occurrence::EveryOtherWeek); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Weekly); QCOMPARE(s.occurrenceMultiplier(), 2); // Fortnightly no longer used: Every other week used instead s.setOccurrence(Schedule::Occurrence::Fortnightly); QCOMPARE(s.occurrence(), Schedule::Occurrence::EveryOtherWeek); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Weekly); QCOMPARE(s.occurrenceMultiplier(), 2); s.setOccurrence(Schedule::Occurrence::EveryThreeWeeks); QCOMPARE(s.occurrence(), Schedule::Occurrence::EveryThreeWeeks); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Weekly); QCOMPARE(s.occurrenceMultiplier(), 3); s.setOccurrence(Schedule::Occurrence::EveryFourWeeks); QCOMPARE(s.occurrence(), Schedule::Occurrence::EveryFourWeeks); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Weekly); QCOMPARE(s.occurrenceMultiplier(), 4); s.setOccurrence(Schedule::Occurrence::EveryEightWeeks); QCOMPARE(s.occurrence(), Schedule::Occurrence::EveryEightWeeks); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Weekly); QCOMPARE(s.occurrenceMultiplier(), 8); s.setOccurrence(Schedule::Occurrence::EveryHalfMonth); QCOMPARE(s.occurrence(), Schedule::Occurrence::EveryHalfMonth); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::EveryHalfMonth); QCOMPARE(s.occurrenceMultiplier(), 1); s.setOccurrence(Schedule::Occurrence::Monthly); QCOMPARE(s.occurrence(), Schedule::Occurrence::Monthly); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Monthly); QCOMPARE(s.occurrenceMultiplier(), 1); s.setOccurrence(Schedule::Occurrence::EveryOtherMonth); QCOMPARE(s.occurrence(), Schedule::Occurrence::EveryOtherMonth); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Monthly); QCOMPARE(s.occurrenceMultiplier(), 2); s.setOccurrence(Schedule::Occurrence::EveryThreeMonths); QCOMPARE(s.occurrence(), Schedule::Occurrence::EveryThreeMonths); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Monthly); QCOMPARE(s.occurrenceMultiplier(), 3); // Quarterly no longer used. Every three months used instead s.setOccurrence(Schedule::Occurrence::Quarterly); QCOMPARE(s.occurrence(), Schedule::Occurrence::EveryThreeMonths); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Monthly); QCOMPARE(s.occurrenceMultiplier(), 3); s.setOccurrence(Schedule::Occurrence::EveryFourMonths); QCOMPARE(s.occurrence(), Schedule::Occurrence::EveryFourMonths); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Monthly); QCOMPARE(s.occurrenceMultiplier(), 4); s.setOccurrence(Schedule::Occurrence::TwiceYearly); QCOMPARE(s.occurrence(), Schedule::Occurrence::TwiceYearly); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Monthly); QCOMPARE(s.occurrenceMultiplier(), 6); s.setOccurrence(Schedule::Occurrence::Yearly); QCOMPARE(s.occurrence(), Schedule::Occurrence::Yearly); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Yearly); QCOMPARE(s.occurrenceMultiplier(), 1); s.setOccurrence(Schedule::Occurrence::EveryOtherYear); QCOMPARE(s.occurrence(), Schedule::Occurrence::EveryOtherYear); QCOMPARE(s.occurrencePeriod(), Schedule::Occurrence::Yearly); QCOMPARE(s.occurrenceMultiplier(), 2); } void MyMoneyScheduleTest::testSimpleToFromCompoundOccurrence() { // Conversion between Simple and Compound occurrences // Each simple occurrence to compound occurrence Schedule::Occurrence occ; int mult; occ = Schedule::Occurrence::Once; mult = 1; MyMoneySchedule::simpleToCompoundOccurrence(mult, occ); QVERIFY(occ == Schedule::Occurrence::Once && mult == 1); occ = Schedule::Occurrence::Daily; mult = 1; MyMoneySchedule::simpleToCompoundOccurrence(mult, occ); QVERIFY(occ == Schedule::Occurrence::Daily && mult == 1); occ = Schedule::Occurrence::Weekly; mult = 1; MyMoneySchedule::simpleToCompoundOccurrence(mult, occ); QVERIFY(occ == Schedule::Occurrence::Weekly && mult == 1); occ = Schedule::Occurrence::EveryOtherWeek; mult = 1; MyMoneySchedule::simpleToCompoundOccurrence(mult, occ); QVERIFY(occ == Schedule::Occurrence::Weekly && mult == 2); occ = Schedule::Occurrence::Fortnightly; mult = 1; MyMoneySchedule::simpleToCompoundOccurrence(mult, occ); QVERIFY(occ == Schedule::Occurrence::Weekly && mult == 2); occ = Schedule::Occurrence::EveryHalfMonth; mult = 1; MyMoneySchedule::simpleToCompoundOccurrence(mult, occ); QVERIFY(occ == Schedule::Occurrence::EveryHalfMonth && mult == 1); occ = Schedule::Occurrence::EveryThreeWeeks; mult = 1; MyMoneySchedule::simpleToCompoundOccurrence(mult, occ); QVERIFY(occ == Schedule::Occurrence::Weekly && mult == 3); occ = Schedule::Occurrence::EveryFourWeeks; mult = 1; MyMoneySchedule::simpleToCompoundOccurrence(mult, occ); QVERIFY(occ == Schedule::Occurrence::Weekly && mult == 4); occ = Schedule::Occurrence::EveryThirtyDays; mult = 1; MyMoneySchedule::simpleToCompoundOccurrence(mult, occ); QVERIFY(occ == Schedule::Occurrence::Daily && mult == 30); occ = Schedule::Occurrence::Monthly; mult = 1; MyMoneySchedule::simpleToCompoundOccurrence(mult, occ); QVERIFY(occ == Schedule::Occurrence::Monthly && mult == 1); occ = Schedule::Occurrence::EveryEightWeeks; mult = 1; MyMoneySchedule::simpleToCompoundOccurrence(mult, occ); QVERIFY(occ == Schedule::Occurrence::Weekly && mult == 8); occ = Schedule::Occurrence::EveryOtherMonth; mult = 1; MyMoneySchedule::simpleToCompoundOccurrence(mult, occ); QVERIFY(occ == Schedule::Occurrence::Monthly && mult == 2); occ = Schedule::Occurrence::EveryThreeMonths; mult = 1; MyMoneySchedule::simpleToCompoundOccurrence(mult, occ); QVERIFY(occ == Schedule::Occurrence::Monthly && mult == 3); occ = Schedule::Occurrence::Quarterly; mult = 1; MyMoneySchedule::simpleToCompoundOccurrence(mult, occ); QVERIFY(occ == Schedule::Occurrence::Monthly && mult == 3); occ = Schedule::Occurrence::EveryFourMonths; mult = 1; MyMoneySchedule::simpleToCompoundOccurrence(mult, occ); QVERIFY(occ == Schedule::Occurrence::Monthly && mult == 4); occ = Schedule::Occurrence::TwiceYearly; mult = 1; MyMoneySchedule::simpleToCompoundOccurrence(mult, occ); QVERIFY(occ == Schedule::Occurrence::Monthly && mult == 6); occ = Schedule::Occurrence::Yearly; mult = 1; MyMoneySchedule::simpleToCompoundOccurrence(mult, occ); QVERIFY(occ == Schedule::Occurrence::Yearly && mult == 1); occ = Schedule::Occurrence::EveryOtherYear; mult = 1; MyMoneySchedule::simpleToCompoundOccurrence(mult, occ); QVERIFY(occ == Schedule::Occurrence::Yearly && mult == 2); // Compound to Simple Occurrences occ = Schedule::Occurrence::Once; mult = 1; MyMoneySchedule::compoundToSimpleOccurrence(mult, occ); QVERIFY(occ == Schedule::Occurrence::Once && mult == 1); occ = Schedule::Occurrence::Daily; mult = 1; MyMoneySchedule::compoundToSimpleOccurrence(mult, occ); QVERIFY(occ == Schedule::Occurrence::Daily && mult == 1); occ = Schedule::Occurrence::Weekly; mult = 1; MyMoneySchedule::compoundToSimpleOccurrence(mult, occ); QVERIFY(occ == Schedule::Occurrence::Weekly && mult == 1); occ = Schedule::Occurrence::Weekly; mult = 2; MyMoneySchedule::compoundToSimpleOccurrence(mult, occ); QVERIFY(occ == Schedule::Occurrence::EveryOtherWeek && mult == 1); // Schedule::Occurrence::Fortnightly not converted back occ = Schedule::Occurrence::EveryHalfMonth; mult = 1; MyMoneySchedule::compoundToSimpleOccurrence(mult, occ); QVERIFY(occ == Schedule::Occurrence::EveryHalfMonth && mult == 1); occ = Schedule::Occurrence::Weekly; mult = 3; MyMoneySchedule::compoundToSimpleOccurrence(mult, occ); QVERIFY(occ == Schedule::Occurrence::EveryThreeWeeks && mult == 1); occ = Schedule::Occurrence::Weekly ; mult = 4; MyMoneySchedule::compoundToSimpleOccurrence(mult, occ); QVERIFY(occ == Schedule::Occurrence::EveryFourWeeks && mult == 1); occ = Schedule::Occurrence::Daily; mult = 30; MyMoneySchedule::compoundToSimpleOccurrence(mult, occ); QVERIFY(occ == Schedule::Occurrence::EveryThirtyDays && mult == 1); occ = Schedule::Occurrence::Monthly; mult = 1; MyMoneySchedule::compoundToSimpleOccurrence(mult, occ); QVERIFY(occ == Schedule::Occurrence::Monthly && mult == 1); occ = Schedule::Occurrence::Weekly; mult = 8; MyMoneySchedule::compoundToSimpleOccurrence(mult, occ); QVERIFY(occ == Schedule::Occurrence::EveryEightWeeks && mult == 1); occ = Schedule::Occurrence::Monthly; mult = 2; MyMoneySchedule::compoundToSimpleOccurrence(mult, occ); QVERIFY(occ == Schedule::Occurrence::EveryOtherMonth && mult == 1); occ = Schedule::Occurrence::Monthly; mult = 3; MyMoneySchedule::compoundToSimpleOccurrence(mult, occ); QVERIFY(occ == Schedule::Occurrence::EveryThreeMonths && mult == 1); // Schedule::Occurrence::Quarterly not converted back occ = Schedule::Occurrence::Monthly; mult = 4; MyMoneySchedule::compoundToSimpleOccurrence(mult, occ); QVERIFY(occ == Schedule::Occurrence::EveryFourMonths && mult == 1); occ = Schedule::Occurrence::Monthly; mult = 6; MyMoneySchedule::compoundToSimpleOccurrence(mult, occ); QVERIFY(occ == Schedule::Occurrence::TwiceYearly && mult == 1); occ = Schedule::Occurrence::Yearly; mult = 1; MyMoneySchedule::compoundToSimpleOccurrence(mult, occ); QVERIFY(occ == Schedule::Occurrence::Yearly && mult == 1); occ = Schedule::Occurrence::Yearly; mult = 2; MyMoneySchedule::compoundToSimpleOccurrence(mult, occ); QVERIFY(occ == Schedule::Occurrence::EveryOtherYear && mult == 1); } void MyMoneyScheduleTest::testProcessingDates() { // There should be no processing calendar defined so // make sure fall back works MyMoneySchedule s; // Check there is no processing caledar defined. QVERIFY(s.processingCalendar() == nullptr); // This should be a processing day. QCOMPARE(s.isProcessingDate(QDate(2009, 12, 31)), true); // This should be a processing day when there is no calendar. QCOMPARE(s.isProcessingDate(QDate(2010, 1, 1)), true); // This should be a non-processing day as it is on a weekend. QCOMPARE(s.isProcessingDate(QDate(2010, 1, 2)), false); } void MyMoneyScheduleTest::testPaidEarlyOneTime() { // this tries to figure out what's wrong with // https://bugs.kde.org/show_bug.cgi?id=231029 MyMoneySchedule sch; QDate paymentInFuture = QDate::currentDate().addDays(7); QString ref_ok = QString( "\n" "\n" " \n" // krazy:exclude=spelling " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "\n" ).arg(paymentInFuture.toString(Qt::ISODate)) .arg(paymentInFuture.toString(Qt::ISODate)) .arg(paymentInFuture.toString(Qt::ISODate)); QDomDocument doc; QDomElement node; doc.setContent(ref_ok); node = doc.documentElement().firstChild().toElement(); try { sch = MyMoneySchedule(node); QCOMPARE(sch.isFinished(), true); QCOMPARE(sch.occurrencePeriod(), Schedule::Occurrence::Monthly); QCOMPARE(sch.paymentDates(QDate::currentDate(), QDate::currentDate().addDays(21)).count(), 0); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } } void MyMoneyScheduleTest::testAdjustedNextPayment() { MyMoneySchedule s; QDate dueDate(2010, 5, 23); QDate adjustedDueDate(2010, 5, 21); s.setNextDueDate(dueDate); s.setOccurrence(Schedule::Occurrence::Monthly); s.setWeekendOption(Schedule::WeekendOption::MoveBefore); //if adjustedNextPayment works ok with adjusted date prior to the current date, it should return 2010-06-23 QDate nextDueDate(2010, 6, 23); //this is the current behaviour, and it is wrong //QCOMPARE(s.adjustedNextPayment(adjustedDueDate), adjustedDueDate); //this is the expected behaviour QCOMPARE(s.adjustedNextPayment(s.adjustedNextDueDate()), s.adjustedDate(nextDueDate, s.weekendOption())); } void MyMoneyScheduleTest::testReplaceId() { MyMoneySchedule sch; QDate paymentInFuture = QDate::currentDate().addDays(7); QString ref_ok = QString( "\n" "\n" " \n" // krazy:exclude=spelling " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "\n" ).arg(paymentInFuture.toString(Qt::ISODate)) .arg(paymentInFuture.toString(Qt::ISODate)) .arg(paymentInFuture.toString(Qt::ISODate)); QDomDocument doc; QDomElement node; doc.setContent(ref_ok); node = doc.documentElement().firstChild().toElement(); try { sch = MyMoneySchedule(node); QCOMPARE(sch.transaction().postDate().isValid(), false); QCOMPARE(sch.transaction().splits()[0].accountId(), QLatin1String("A000076")); QCOMPARE(sch.transaction().splits()[1].accountId(), QLatin1String("A000276")); QCOMPARE(sch.replaceId(QLatin1String("A000079"), QLatin1String("A000076")), true); QCOMPARE(sch.transaction().splits()[0].accountId(), QLatin1String("A000079")); QCOMPARE(sch.transaction().splits()[1].accountId(), QLatin1String("A000276")); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } } void MyMoneyScheduleTest::testAdjustedWhenItWillEnd() { MyMoneySchedule s; QDate endDate(2011, 8, 13); // this is a nonprocessing day because // it's a Saturday QDate refDate(2011, 8, 10); // just some ref date before the last payment s.setStartDate(endDate.addMonths(-1)); s.setOccurrence(Schedule::Occurrence::Monthly); s.setEndDate(endDate); // the next due date is on this day but the policy is to move the // schedule to the next processing day (Monday) s.setWeekendOption(Schedule::WeekendOption::MoveAfter); s.setNextDueDate(endDate); // the payment should be found between the respective date and one month after QCOMPARE(s.paymentDates(endDate, endDate.addMonths(1)).count(), 1); // the next payment must be the final one QCOMPARE(s.nextPayment(refDate), endDate); // and since it is on a Saturday, the adjusted one must be on the // following Monday QCOMPARE(s.adjustedNextPayment(refDate), endDate.addDays(2)); // reference for Sunday is still OK QCOMPARE(s.adjustedNextPayment(QDate(2011, 8, 14)), endDate.addDays(2)); // but it is finished on Monday (as reference date) QVERIFY(!s.adjustedNextPayment(QDate(2011, 8, 15)).isValid()); // check the # of remaining transactions s.setNextDueDate(endDate.addMonths(-1)); QCOMPARE(s.transactionsRemaining(), 2); } void MyMoneyScheduleTest::testElementNames() { for (auto i = (int)MyMoneySchedule::Element::Payment; i <= (int)MyMoneySchedule::Element::Payments; ++i) { auto isEmpty = MyMoneySchedule::getElName(static_cast(i)).isEmpty(); if (isEmpty) qWarning() << "Empty element's name " << i; QVERIFY(!isEmpty); } } void MyMoneyScheduleTest::testAttributeNames() { for (auto i = (int)MyMoneySchedule::Attribute::Name; i < (int)MyMoneySchedule::Attribute::LastAttribute; ++i) { auto isEmpty = MyMoneySchedule::getAttrName(static_cast(i)).isEmpty(); if (isEmpty) qWarning() << "Empty attribute's name " << i; QVERIFY(!isEmpty); } } void MyMoneyScheduleTest::testProcessLastDayInMonth() { MyMoneySchedule s; // occurence is unrelated s.setOccurrence(Schedule::Occurrence::Any); s.setLastDayInMonth(true); s.setNextDueDate(QDate(2010, 1, 1)); QCOMPARE(s.adjustedNextDueDate(), QDate(2010,1,31)); s.setNextDueDate(QDate(2010, 2, 1)); QCOMPARE(s.adjustedNextDueDate(), QDate(2010,2,28)); s.setNextDueDate(QDate(2016, 2, 1)); QCOMPARE(s.adjustedNextDueDate(), QDate(2016,2,29)); s.setNextDueDate(QDate(2016, 4, 1)); QCOMPARE(s.adjustedNextDueDate(), QDate(2016,4,30)); s.setLastDayInMonth(false); QCOMPARE(s.adjustedNextDueDate(), QDate(2016,4,1)); } diff --git a/kmymoney/mymoney/tests/mymoneyschedule-test.h b/kmymoney/mymoney/tests/mymoneyschedule-test.h index 164d67d3d..24dbc8e75 100644 --- a/kmymoney/mymoney/tests/mymoneyschedule-test.h +++ b/kmymoney/mymoney/tests/mymoneyschedule-test.h @@ -1,58 +1,58 @@ /*************************************************************************** mymoneyscheduletest.h ------------------- copyright : (C) 2002 by Michael Edwardes email : mte@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 MYMONEYSCHEDULETEST_H #define MYMONEYSCHEDULETEST_H -#include +#include class MyMoneyScheduleTest : public QObject { Q_OBJECT private slots: void testEmptyConstructor(); void testConstructor(); void testSetFunctions(); void testCopyConstructor(); void testAssignmentConstructor(); void testOverdue(); void testNextPayment(); void testAddHalfMonths(); void testPaymentDates(); void testWriteXML(); void testReadXML(); void testHasReferenceTo(); void testAdjustedNextDueDate(); void testModifyNextDueDate(); void testDaysBetweenEvents(); void testEventsPerYear(); void testOccurrenceToString(); void testOccurrencePeriodToString(); void testOccurrencePeriod(); void testSimpleToFromCompoundOccurrence(); void testProcessingDates(); void testPaidEarlyOneTime(); void testAdjustedNextPayment(); void testReplaceId(); void testAdjustedWhenItWillEnd(); void testProcessLastDayInMonth(); void testNextPaymentOnLastDayOfMonth(); void testElementNames(); void testAttributeNames(); }; #endif diff --git a/kmymoney/mymoney/tests/mymoneysecurity-test.cpp b/kmymoney/mymoney/tests/mymoneysecurity-test.cpp index 2bed4c0c2..fbc876fcd 100644 --- a/kmymoney/mymoney/tests/mymoneysecurity-test.cpp +++ b/kmymoney/mymoney/tests/mymoneysecurity-test.cpp @@ -1,222 +1,222 @@ /*************************************************************************** mymoneysecuritytest.cpp ------------------- copyright : (C) 2002 by Kevin Tambascio 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 "mymoneysecurity-test.h" -#include +#include #define KMM_MYMONEY_UNIT_TESTABLE friend class MyMoneySecurityTest; #include "mymoneysecurity.h" #include "mymoneymoney.h" QTEST_GUILESS_MAIN(MyMoneySecurityTest) void MyMoneySecurityTest::init() { m = new MyMoneySecurity(); } void MyMoneySecurityTest::cleanup() { delete m; } void MyMoneySecurityTest::testEmptyConstructor() { QVERIFY(m->id().isEmpty()); QVERIFY(m->name().isEmpty()); QVERIFY(m->tradingSymbol().isEmpty()); QVERIFY(m->securityType() == eMyMoney::Security::None); QVERIFY(m->tradingMarket().isEmpty()); QVERIFY(m->tradingCurrency().isEmpty()); QVERIFY(m->smallestCashFraction() == 100); QVERIFY(m->smallestAccountFraction() == 100); } void MyMoneySecurityTest::testCopyConstructor() { MyMoneySecurity* n1 = new MyMoneySecurity("GUID1", *m); MyMoneySecurity n2(*n1); // QVERIFY(*n1 == n2); delete n1; } void MyMoneySecurityTest::testNonemptyConstructor() { QDate date(2004, 4, 1); MyMoneyMoney val("1234/100"); m->setName("name"); m->setTradingSymbol("symbol"); m->setSecurityType(eMyMoney::Security::Currency); // m->addPriceHistory(date, val); MyMoneySecurity n("id", *m); QVERIFY(n.id() == QString("id")); QVERIFY(n.tradingSymbol() == QString("symbol")); QVERIFY(n.securityType() == eMyMoney::Security::Currency); // QVERIFY(n.priceHistory().count() == 1); } void MyMoneySecurityTest::testSetFunctions() { m->setName("Name"); m->setTradingSymbol("Symbol"); m->setTradingMarket("Market"); m->setTradingCurrency("Currency"); m->setSecurityType(eMyMoney::Security::Stock); m->setSmallestAccountFraction(50); m->setSmallestCashFraction(2); QVERIFY(m->name() == "Name"); QVERIFY(m->tradingSymbol() == "Symbol"); QVERIFY(m->tradingMarket() == "Market"); QVERIFY(m->tradingCurrency() == "Currency"); QVERIFY(m->securityType() == eMyMoney::Security::Stock); QVERIFY(m->smallestAccountFraction() == 50); QVERIFY(m->smallestCashFraction() == 2); } /* void MyMoneySecurityTest::testMyMoneyFileConstructor() { MyMoneySecurity *t = new MyMoneySecurity("GUID", *n); QVERIFY(t->id() == "GUID"); delete t; } */ void MyMoneySecurityTest::testEquality() { testSetFunctions(); m->setValue("Key", "Value"); MyMoneySecurity n; n = *m; QVERIFY(n == *m); n.setName("NewName"); QVERIFY(!(n == *m)); n = *m; n.setTradingSymbol("NewSymbol"); QVERIFY(!(n == *m)); n = *m; n.setTradingMarket("NewMarket"); QVERIFY(!(n == *m)); n = *m; n.setTradingCurrency("NewCurrency"); QVERIFY(!(n == *m)); n = *m; n.setSecurityType(eMyMoney::Security::Currency); QVERIFY(!(n == *m)); n = *m; n.setPricePrecision(8); QVERIFY(!(n == *m)); n = *m; n.setSmallestCashFraction(20); QVERIFY(!(n == *m)); n = *m; n.setValue("Key", "NewValue"); QVERIFY(!(n == *m)); } void MyMoneySecurityTest::testInequality() { testSetFunctions(); m->setValue("Key", "Value"); MyMoneySecurity n; n = *m; QVERIFY(!(n != *m)); n.setName("NewName"); QVERIFY(n != *m); n = *m; n.setTradingSymbol("NewSymbol"); QVERIFY(n != *m); n = *m; n.setTradingMarket("NewMarket"); QVERIFY(n != *m); n = *m; n.setTradingCurrency("NewCurrency"); QVERIFY(n != *m); n = *m; n.setSecurityType(eMyMoney::Security::Currency); QVERIFY(n != *m); n = *m; n.setSmallestAccountFraction(40); QVERIFY(n != *m); n = *m; n.setSmallestCashFraction(20); QVERIFY(n != *m); n = *m; n.setValue("Key", "NewValue"); QVERIFY(n != *m); } /* void MyMoneySecurityTest::testAccountIDList () { MyMoneySecurity equity; QStringList list; QString id; // list must be empty list = institution.accountList(); QVERIFY(list.count() == 0); // add one account institution.addAccountId("A000002"); list = institution.accountList(); QVERIFY(list.count() == 1); QVERIFY(list.contains("A000002") == 1); // adding same account shouldn't make a difference institution.addAccountId("A000002"); list = institution.accountList(); QVERIFY(list.count() == 1); QVERIFY(list.contains("A000002") == 1); // now add another account institution.addAccountId("A000001"); list = institution.accountList(); QVERIFY(list.count() == 2); QVERIFY(list.contains("A000002") == 1); QVERIFY(list.contains("A000001") == 1); id = institution.removeAccountId("A000001"); QVERIFY(id == "A000001"); list = institution.accountList(); QVERIFY(list.count() == 1); QVERIFY(list.contains("A000002") == 1); } */ void MyMoneySecurityTest::testAttributeNames() { for (auto i = (int)MyMoneySecurity::Attribute::Name; i < (int)MyMoneySecurity::Attribute::LastAttribute; ++i) { auto isEmpty = MyMoneySecurity::getAttrName(static_cast(i)).isEmpty(); if (isEmpty) qWarning() << "Empty attribute's name " << i; QVERIFY(!isEmpty); } } diff --git a/kmymoney/mymoney/tests/mymoneysecurity-test.h b/kmymoney/mymoney/tests/mymoneysecurity-test.h index cda1d708f..3d7ee75ed 100644 --- a/kmymoney/mymoney/tests/mymoneysecurity-test.h +++ b/kmymoney/mymoney/tests/mymoneysecurity-test.h @@ -1,46 +1,46 @@ /*************************************************************************** mymoneysecuritytest.h ------------------- copyright : (C) 2004 by Kevin Tambascio email : ktambascio@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 MYMONEYSECURITYTEST_H #define MYMONEYSECURITYTEST_H #include -#include +#include class MyMoneySecurity; class MyMoneySecurityTest : public QObject { Q_OBJECT protected: MyMoneySecurity *m; private slots: void init(); void cleanup(); void testEmptyConstructor(); void testNonemptyConstructor(); void testCopyConstructor(); void testSetFunctions(); void testEquality(); void testInequality(); // void testMyMoneyFileConstructor(); // void testAccountIDList (); void testAttributeNames(); }; #endif diff --git a/kmymoney/mymoney/tests/mymoneysplit-test.cpp b/kmymoney/mymoney/tests/mymoneysplit-test.cpp index e05224d15..d672116f5 100644 --- a/kmymoney/mymoney/tests/mymoneysplit-test.cpp +++ b/kmymoney/mymoney/tests/mymoneysplit-test.cpp @@ -1,511 +1,511 @@ /*************************************************************************** mymoneysplittest.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 "mymoneysplit-test.h" -#include +#include #define KMM_MYMONEY_UNIT_TESTABLE friend class MyMoneySplitTest; #include "mymoneymoney.h" #include "mymoneysplit.h" #include "mymoneytransaction.h" #include "mymoneyexception.h" QTEST_GUILESS_MAIN(MyMoneySplitTest) void MyMoneySplitTest::init() { m = new MyMoneySplit(); } void MyMoneySplitTest::cleanup() { delete m; } void MyMoneySplitTest::testEmptyConstructor() { QCOMPARE(m->accountId().isEmpty(), true); QCOMPARE(m->id().isEmpty(), true); QCOMPARE(m->memo().isEmpty(), true); QCOMPARE(m->action().isEmpty(), true); QCOMPARE(m->shares().isZero(), true); QCOMPARE(m->value().isZero(), true); QCOMPARE(m->reconcileFlag(), eMyMoney::Split::State::NotReconciled); QCOMPARE(m->reconcileDate(), QDate()); QCOMPARE(m->transactionId().isEmpty(), true); QCOMPARE(m->costCenterId().isEmpty(), true); } void MyMoneySplitTest::testSetFunctions() { m->setAccountId("Account"); m->setMemo("Memo"); m->setReconcileDate(QDate(1, 2, 3)); m->setReconcileFlag(eMyMoney::Split::State::Cleared); m->setShares(MyMoneyMoney(1234, 100)); m->setValue(MyMoneyMoney(3456, 100)); m->setId("MyID"); m->setPayeeId("Payee"); m->setCostCenterId("CostCenter"); QList tagIdList; tagIdList << "Tag"; m->setTagIdList(tagIdList); m->setAction("Action"); m->setTransactionId("TestTransaction"); m->setValue("Key", "Value"); QCOMPARE(m->accountId(), QLatin1String("Account")); QCOMPARE(m->memo(), QLatin1String("Memo")); QCOMPARE(m->reconcileDate(), QDate(1, 2, 3)); QCOMPARE(m->reconcileFlag(), eMyMoney::Split::State::Cleared); QCOMPARE(m->shares(), MyMoneyMoney(1234, 100)); QCOMPARE(m->value(), MyMoneyMoney(3456, 100)); QCOMPARE(m->id(), QLatin1String("MyID")); QCOMPARE(m->payeeId(), QLatin1String("Payee")); QCOMPARE(m->tagIdList(), tagIdList); QCOMPARE(m->action(), QLatin1String("Action")); QCOMPARE(m->transactionId(), QLatin1String("TestTransaction")); QCOMPARE(m->value("Key"), QLatin1String("Value")); QCOMPARE(m->costCenterId(), QLatin1String("CostCenter")); } void MyMoneySplitTest::testCopyConstructor() { testSetFunctions(); MyMoneySplit n(*m); QCOMPARE(n.accountId(), QLatin1String("Account")); QCOMPARE(n.memo(), QLatin1String("Memo")); QCOMPARE(n.reconcileDate(), QDate(1, 2, 3)); QCOMPARE(n.reconcileFlag(), eMyMoney::Split::State::Cleared); QCOMPARE(n.shares(), MyMoneyMoney(1234, 100)); QCOMPARE(n.value(), MyMoneyMoney(3456, 100)); QCOMPARE(n.id(), QLatin1String("MyID")); QCOMPARE(n.payeeId(), QLatin1String("Payee")); QList tagIdList; tagIdList << "Tag"; QCOMPARE(n.tagIdList(), tagIdList); QCOMPARE(n.action(), QLatin1String("Action")); QCOMPARE(n.transactionId(), QLatin1String("TestTransaction")); QCOMPARE(n.value("Key"), QLatin1String("Value")); QCOMPARE(n.costCenterId(), QLatin1String("CostCenter")); } void MyMoneySplitTest::testAssignmentConstructor() { testSetFunctions(); MyMoneySplit n; n = *m; QCOMPARE(n.accountId(), QLatin1String("Account")); QCOMPARE(n.memo(), QLatin1String("Memo")); QCOMPARE(n.reconcileDate(), QDate(1, 2, 3)); QCOMPARE(n.reconcileFlag(), eMyMoney::Split::State::Cleared); QCOMPARE(n.shares(), MyMoneyMoney(1234, 100)); QCOMPARE(n.value(), MyMoneyMoney(3456, 100)); QCOMPARE(n.id(), QLatin1String("MyID")); QCOMPARE(n.payeeId(), QLatin1String("Payee")); QList tagIdList; tagIdList << QLatin1String("Tag"); QCOMPARE(n.tagIdList(), tagIdList); QCOMPARE(n.action(), QLatin1String("Action")); QCOMPARE(n.transactionId(), QLatin1String("TestTransaction")); QCOMPARE(n.value("Key"), QLatin1String("Value")); QCOMPARE(n.costCenterId(), QLatin1String("CostCenter")); } void MyMoneySplitTest::testEquality() { testSetFunctions(); MyMoneySplit n(*m); QCOMPARE(n, *m); } void MyMoneySplitTest::testInequality() { testSetFunctions(); MyMoneySplit n(*m); n.setShares(MyMoneyMoney(3456, 100)); QVERIFY(!(n == *m)); n = *m; n.setId("Not My ID"); QVERIFY(!(n == *m)); n = *m; n.setPayeeId("No payee"); QVERIFY(!(n == *m)); n = *m; QList tagIdList; tagIdList << "No tag"; n.setTagIdList(tagIdList); QVERIFY(!(n == *m)); n = *m; n.setAction("No action"); QVERIFY(!(n == *m)); n = *m; n.setNumber("No number"); QVERIFY(!(n == *m)); n = *m; n.setAccountId("No account"); QVERIFY(!(n == *m)); n = *m; n.setMemo("No memo"); QVERIFY(!(n == *m)); n = *m; n.setReconcileDate(QDate(3, 4, 5)); QVERIFY(!(n == *m)); n = *m; n.setReconcileFlag(eMyMoney::Split::State::Frozen); QVERIFY(!(n == *m)); n = *m; n.setShares(MyMoneyMoney(4567, 100)); QVERIFY(!(n == *m)); n = *m; n.setValue(MyMoneyMoney(9876, 100)); QVERIFY(!(n == *m)); n = *m; n.setTransactionId("NoTransaction"); QVERIFY(!(n == *m)); n = *m; n.setValue("Key", "NoValue"); QVERIFY(!(n == *m)); n = *m; n.setCostCenterId("NoCostCenter"); QVERIFY(!(n == *m)); } void MyMoneySplitTest::testUnaryMinus() { testSetFunctions(); MyMoneySplit n = -*m; QCOMPARE(n.accountId(), QLatin1String("Account")); QCOMPARE(n.memo(), QLatin1String("Memo")); QCOMPARE(n.reconcileDate(), QDate(1, 2, 3)); QCOMPARE(n.reconcileFlag(), eMyMoney::Split::State::Cleared); QCOMPARE(n.shares(), MyMoneyMoney(-1234, 100)); QCOMPARE(n.value(), MyMoneyMoney(-3456, 100)); QCOMPARE(n.id(), QLatin1String("MyID")); QCOMPARE(n.payeeId(), QLatin1String("Payee")); QList tagIdList; tagIdList << "Tag"; QCOMPARE(n.tagIdList(), tagIdList); QCOMPARE(n.action(), QLatin1String("Action")); QCOMPARE(n.transactionId(), QLatin1String("TestTransaction")); QCOMPARE(n.value("Key"), QLatin1String("Value")); QCOMPARE(n.costCenterId(), QLatin1String("CostCenter")); } void MyMoneySplitTest::testAmortization() { QCOMPARE(m->isAmortizationSplit(), false); testSetFunctions(); QCOMPARE(m->isAmortizationSplit(), false); m->setAction(MyMoneySplit::ActionAmortization); QCOMPARE(m->isAmortizationSplit(), true); } void MyMoneySplitTest::testValue() { m->setValue(MyMoneyMoney(1, 100)); m->setShares(MyMoneyMoney(2, 100)); QCOMPARE(m->value("EUR", "EUR"), MyMoneyMoney(1, 100)); QCOMPARE(m->value("EUR", "USD"), MyMoneyMoney(2, 100)); } void MyMoneySplitTest::testSetValue() { QCOMPARE(m->value().isZero(), true); QCOMPARE(m->shares().isZero(), true); m->setValue(MyMoneyMoney(1, 100), "EUR", "EUR"); QCOMPARE(m->value(), MyMoneyMoney(1, 100)); QCOMPARE(m->shares().isZero(), true); m->setValue(MyMoneyMoney(3, 100), "EUR", "USD"); QCOMPARE(m->value(), MyMoneyMoney(1, 100)); QCOMPARE(m->shares(), MyMoneyMoney(3, 100)); } void MyMoneySplitTest::testSetAction() { QCOMPARE(m->action().isEmpty(), true); m->setAction(eMyMoney::Split::InvestmentTransactionType::BuyShares); QCOMPARE(m->action(), QLatin1String(MyMoneySplit::ActionBuyShares)); m->setAction(eMyMoney::Split::InvestmentTransactionType::SellShares); QCOMPARE(m->action(), QLatin1String(MyMoneySplit::ActionBuyShares)); m->setAction(eMyMoney::Split::InvestmentTransactionType::Dividend); QCOMPARE(m->action(), QLatin1String(MyMoneySplit::ActionDividend)); m->setAction(eMyMoney::Split::InvestmentTransactionType::Yield); QCOMPARE(m->action(), QLatin1String(MyMoneySplit::ActionYield)); m->setAction(eMyMoney::Split::InvestmentTransactionType::ReinvestDividend); QCOMPARE(m->action(), QLatin1String(MyMoneySplit::ActionReinvestDividend)); m->setAction(eMyMoney::Split::InvestmentTransactionType::AddShares); QCOMPARE(m->action(), QLatin1String(MyMoneySplit::ActionAddShares)); m->setAction(eMyMoney::Split::InvestmentTransactionType::RemoveShares); QCOMPARE(m->action(), QLatin1String(MyMoneySplit::ActionAddShares)); m->setAction(eMyMoney::Split::InvestmentTransactionType::SplitShares); QCOMPARE(m->action(), QLatin1String(MyMoneySplit::ActionSplitShares)); } void MyMoneySplitTest::testIsAutoCalc() { QCOMPARE(m->isAutoCalc(), false); m->setValue(MyMoneyMoney::autoCalc); QCOMPARE(m->isAutoCalc(), true); m->setShares(MyMoneyMoney::autoCalc); QCOMPARE(m->isAutoCalc(), true); m->setValue(MyMoneyMoney()); QCOMPARE(m->isAutoCalc(), true); m->setShares(MyMoneyMoney(1, 100)); QCOMPARE(m->isAutoCalc(), false); } void MyMoneySplitTest::testWriteXML() { MyMoneySplit s; s.setPayeeId("P000001"); QList tagIdList; tagIdList << "G000001"; s.setTagIdList(tagIdList); s.setShares(MyMoneyMoney(96379, 100)); s.setValue(MyMoneyMoney(96379, 1000)); s.setAccountId("A000076"); s.setCostCenterId("C000005"); s.setNumber("124"); s.setBankID("SPID"); s.setAction(MyMoneySplit::ActionDeposit); s.setReconcileFlag(eMyMoney::Split::State::Reconciled); QDomDocument doc("TEST"); QDomElement el = doc.createElement("SPLIT-CONTAINER"); doc.appendChild(el); s.writeXML(doc, el); QCOMPARE(doc.doctype().name(), QLatin1String("TEST")); QDomElement splitContainer = doc.documentElement(); QCOMPARE(splitContainer.tagName(), QLatin1String("SPLIT-CONTAINER")); QCOMPARE(splitContainer.childNodes().size(), 1); QCOMPARE(splitContainer.childNodes().at(0).isElement(), true); QDomElement split = splitContainer.childNodes().at(0).toElement(); QCOMPARE(split.tagName(), QLatin1String("SPLIT")); QCOMPARE(split.attribute("payee"), QLatin1String("P000001")); QCOMPARE(split.attribute("reconcileflag"), QLatin1String("2")); QCOMPARE(split.attribute("shares"), QLatin1String("96379/100")); QCOMPARE(split.attribute("reconciledate"), QString()); QCOMPARE(split.attribute("action"), QLatin1String("Deposit")); QCOMPARE(split.attribute("bankid"), QLatin1String("SPID")); QCOMPARE(split.attribute("account"), QLatin1String("A000076")); QCOMPARE(split.attribute("costcenter"), QLatin1String("C000005")); QCOMPARE(split.attribute("number"), QLatin1String("124")); QCOMPARE(split.attribute("value"), QLatin1String("96379/1000")); QCOMPARE(split.attribute("memo"), QString()); QCOMPARE(split.attribute("id"), QString()); QCOMPARE(split.childNodes().size(), 1); QCOMPARE(split.childNodes().at(0).isElement(), true); QDomElement tag = split.childNodes().at(0).toElement(); QCOMPARE(tag.tagName(), QLatin1String("TAG")); QCOMPARE(tag.attribute("id"), QLatin1String("G000001")); QCOMPARE(tag.childNodes().size(), 0); QString ref = QString( "\n" "\n" " \n" " \n" " \n" "\n"); } void MyMoneySplitTest::testReadXML() { MyMoneySplit s; QString ref_ok = QString( "\n" "\n" " \n" " \n" " \n" "\n"); QString ref_false = QString( "\n" "\n" " \n" " \n" "\n"); QDomDocument doc; QDomElement node; doc.setContent(ref_false); node = doc.documentElement().firstChild().toElement(); try { s = MyMoneySplit(node); QFAIL("Missing expected exception"); } catch (const MyMoneyException &) { } doc.setContent(ref_ok); node = doc.documentElement().firstChild().toElement(); try { s = MyMoneySplit(node); QCOMPARE(s.id().isEmpty(), true); QCOMPARE(s.payeeId(), QLatin1String("P000001")); QList tagIdList; tagIdList << QLatin1String("G000001"); QCOMPARE(s.tagIdList(), tagIdList); QCOMPARE(s.reconcileDate(), QDate()); QCOMPARE(s.shares(), MyMoneyMoney(96379, 100)); QCOMPARE(s.value(), MyMoneyMoney(96379, 1000)); QCOMPARE(s.number(), QLatin1String("124")); QCOMPARE(s.bankID(), QLatin1String("SPID")); QCOMPARE(s.reconcileFlag(), eMyMoney::Split::State::Reconciled); QCOMPARE(s.action(), QLatin1String(MyMoneySplit::ActionDeposit)); QCOMPARE(s.accountId(), QLatin1String("A000076")); QCOMPARE(s.costCenterId(), QLatin1String("C000005")); QCOMPARE(s.memo(), QLatin1String("MyMemo")); } catch (const MyMoneyException &) { } } void MyMoneySplitTest::testReplaceId() { MyMoneySplit s; bool changed; s.setPayeeId("P000001"); s.setAccountId("A000076"); s.setCostCenterId("C000005"); changed = s.replaceId("X0001", "Y00001"); QCOMPARE(changed, false); QCOMPARE(s.payeeId(), QLatin1String("P000001")); QCOMPARE(s.accountId(), QLatin1String("A000076")); QCOMPARE(s.costCenterId(), QLatin1String("C000005")); changed = s.replaceId("P000002", "P000001"); QCOMPARE(changed, true); QCOMPARE(s.payeeId(), QLatin1String("P000002")); QCOMPARE(s.accountId(), QLatin1String("A000076")); QCOMPARE(s.costCenterId(), QLatin1String("C000005")); changed = s.replaceId("A000079", "A000076"); QCOMPARE(changed, true); QCOMPARE(s.payeeId(), QLatin1String("P000002")); QCOMPARE(s.accountId(), QLatin1String("A000079")); QCOMPARE(s.costCenterId(), QLatin1String("C000005")); changed = s.replaceId("C000006", "C000005"); QCOMPARE(changed, true); QCOMPARE(s.payeeId(), QLatin1String("P000002")); QCOMPARE(s.accountId(), QLatin1String("A000079")); QCOMPARE(s.costCenterId(), QLatin1String("C000006")); QString ref_ok = QString( "\n" "\n" " \n" " \n" " \n" " \n" " &lt;CONTAINER>\n" " &lt;TRANSACTION postdate="2010-03-05" memo="UMBUCHUNG" id="" commodity="EUR" entrydate="2010-03-08" >\n" " &lt;SPLITS>\n" " &lt;SPLIT payee="P000010" reconciledate="" shares="125000/100" action="Transfer" bankid="" number="" reconcileflag="0" memo="UMBUCHUNG" value="125000/100" id="S0001" account="A000087" />\n" " &lt;SPLIT payee="P000011" reconciledate="" shares="-125000/100" action="" bankid="A000076-2010-03-05-b6850c0-1" number="" reconcileflag="0" memo="UMBUCHUNG" value="-125000/100" id="S0002" account="A000076" />\n" " &lt;/SPLITS>\n" " &lt;KEYVALUEPAIRS>\n" " &lt;PAIR key="Imported" value="true" />\n" " &lt;/KEYVALUEPAIRS>\n" " &lt;/TRANSACTION>\n" " &lt;/CONTAINER>\n" "\" />\n" " \n" " \n" " \n" "\n" ); QDomDocument doc; QDomElement node; doc.setContent(ref_ok); node = doc.documentElement().firstChild().toElement(); try { s = MyMoneySplit(node); QCOMPARE(s.payeeId(), QLatin1String("P000001")); QCOMPARE(s.replaceId("P2", "P1"), false); QCOMPARE(s.matchedTransaction().splits()[0].payeeId(), QLatin1String("P000010")); QCOMPARE(s.matchedTransaction().splits()[1].payeeId(), QLatin1String("P000011")); QCOMPARE(s.replaceId("P0010", "P000010"), true); QCOMPARE(s.matchedTransaction().splits()[0].payeeId(), QLatin1String("P0010")); QCOMPARE(s.matchedTransaction().splits()[1].payeeId(), QLatin1String("P000011")); QCOMPARE(s.replaceId("P0011", "P000011"), true); QCOMPARE(s.matchedTransaction().splits()[0].payeeId(), QLatin1String("P0010")); QCOMPARE(s.matchedTransaction().splits()[1].payeeId(), QLatin1String("P0011")); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } } void MyMoneySplitTest::testElementNames() { for (auto i = (int)MyMoneySplit::Element::Split; i <= (int)MyMoneySplit::Element::KeyValuePairs; ++i) { auto isEmpty = MyMoneySplit::getElName(static_cast(i)).isEmpty(); if (isEmpty) qWarning() << "Empty element's name " << i; QVERIFY(!isEmpty); } } void MyMoneySplitTest::testAttributeNames() { for (auto i = (int)MyMoneySplit::Attribute::ID; i < (int)MyMoneySplit::Attribute::LastAttribute; ++i) { auto isEmpty = MyMoneySplit::getAttrName(static_cast(i)).isEmpty(); if (isEmpty) qWarning() << "Empty attribute's name " << i; QVERIFY(!isEmpty); } } diff --git a/kmymoney/mymoney/tests/mymoneysplit-test.h b/kmymoney/mymoney/tests/mymoneysplit-test.h index b7f57cf55..d3d38acc0 100644 --- a/kmymoney/mymoney/tests/mymoneysplit-test.h +++ b/kmymoney/mymoney/tests/mymoneysplit-test.h @@ -1,53 +1,53 @@ /*************************************************************************** mymoneysplittest.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 MYMONEYSPLITTEST_H #define MYMONEYSPLITTEST_H -#include +#include class MyMoneySplit; class MyMoneySplitTest : public QObject { Q_OBJECT protected: MyMoneySplit *m; private slots: void init(); void cleanup(); void testEmptyConstructor(); void testSetFunctions(); void testCopyConstructor(); void testAssignmentConstructor(); void testEquality(); void testInequality(); void testAmortization(); void testValue(); void testSetValue(); void testSetAction(); void testIsAutoCalc(); void testWriteXML(); void testReadXML(); void testReplaceId(); void testUnaryMinus(); void testElementNames(); void testAttributeNames(); }; #endif diff --git a/kmymoney/mymoney/tests/mymoneytag-test.cpp b/kmymoney/mymoney/tests/mymoneytag-test.cpp index 36758d928..921c28b97 100644 --- a/kmymoney/mymoney/tests/mymoneytag-test.cpp +++ b/kmymoney/mymoney/tests/mymoneytag-test.cpp @@ -1,50 +1,50 @@ /*************************************************************************** mymoneytagtest.cpp ***************************************************************************/ /*************************************************************************** * * * 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 "mymoneytag-test.h" #include #include -#include +#include #define KMM_MYMONEY_UNIT_TESTABLE friend class MyMoneyTagTest; #include "mymoneytag.h" using namespace std; QTEST_GUILESS_MAIN(MyMoneyTagTest) void MyMoneyTagTest::testXml() { QDomDocument doc; QDomElement parent = doc.createElement("Test"); doc.appendChild(parent); MyMoneyTag tag1; tag1.m_id = "some random id";//if the ID isn't set, w ethrow an exception tag1.writeXML(doc, parent); QDomElement el = parent.firstChild().toElement(); QVERIFY(!el.isNull()); MyMoneyTag tag2(el); } void MyMoneyTagTest::testAttributeNames() { for (auto i = (int)MyMoneyTag::Attribute::Name; i < (int)MyMoneyTag::Attribute::LastAttribute; ++i) { auto isEmpty = MyMoneyTag::getAttrName(static_cast(i)).isEmpty(); if (isEmpty) qWarning() << "Empty attribute's name " << i; QVERIFY(!isEmpty); } } diff --git a/kmymoney/mymoney/tests/mymoneytag-test.h b/kmymoney/mymoney/tests/mymoneytag-test.h index 76d464f28..f198a8b4a 100644 --- a/kmymoney/mymoney/tests/mymoneytag-test.h +++ b/kmymoney/mymoney/tests/mymoneytag-test.h @@ -1,27 +1,27 @@ /*************************************************************************** mymoneytagtest.h ***************************************************************************/ /*************************************************************************** * * * 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 MYMONEYTAGTEST_H #define MYMONEYTAGTEST_H -#include +#include class MyMoneyTagTest : public QObject { Q_OBJECT private slots: void testXml(); void testAttributeNames(); }; #endif diff --git a/kmymoney/mymoney/tests/mymoneytransaction-test.cpp b/kmymoney/mymoney/tests/mymoneytransaction-test.cpp index 52aff8358..c69afd534 100644 --- a/kmymoney/mymoney/tests/mymoneytransaction-test.cpp +++ b/kmymoney/mymoney/tests/mymoneytransaction-test.cpp @@ -1,733 +1,733 @@ /*************************************************************************** mymoneytransactiontest.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 "mymoneytransaction-test.h" -#include +#include -#include +#include #include "mymoneytestutils.h" #include "mymoneymoney.h" #include "mymoneysplit.h" #include "mymoneytransaction.h" QTEST_GUILESS_MAIN(MyMoneyTransactionTest) void MyMoneyTransactionTest::init() { m = new MyMoneyTransaction(); } void MyMoneyTransactionTest::cleanup() { delete m; } void MyMoneyTransactionTest::testEmptyConstructor() { QVERIFY(m->id().isEmpty()); QVERIFY(m->entryDate() == QDate()); QVERIFY(m->memo().isEmpty()); QVERIFY(m->splits().count() == 0); } void MyMoneyTransactionTest::testSetFunctions() { m->setMemo("Memo"); m->setPostDate(QDate(1, 2, 3)); QVERIFY(m->postDate() == QDate(1, 2, 3)); QVERIFY(m->memo() == "Memo"); } void MyMoneyTransactionTest::testConstructor() { testSetFunctions(); MyMoneyTransaction a("ID", *m); QVERIFY(a.id() == "ID"); QVERIFY(a.entryDate() == QDate::currentDate()); QVERIFY(a.memo() == "Memo"); QVERIFY(a.postDate() == QDate(1, 2, 3)); } void MyMoneyTransactionTest::testCopyConstructor() { testConstructor(); MyMoneyTransaction a("ID", *m); a.setValue("Key", "Value"); MyMoneyTransaction n(a); QVERIFY(n.id() == "ID"); QVERIFY(n.entryDate() == QDate::currentDate()); QVERIFY(n.memo() == "Memo"); QVERIFY(n.postDate() == QDate(1, 2, 3)); QVERIFY(n.value("Key") == "Value"); } void MyMoneyTransactionTest::testAssignmentConstructor() { testConstructor(); MyMoneyTransaction a("ID", *m); a.setValue("Key", "Value"); MyMoneyTransaction n; n = a; QVERIFY(n.id() == "ID"); QVERIFY(n.entryDate() == QDate::currentDate()); QVERIFY(n.memo() == "Memo"); QVERIFY(n.postDate() == QDate(1, 2, 3)); QVERIFY(n.value("Key") == "Value"); } void MyMoneyTransactionTest::testEquality() { testConstructor(); MyMoneyTransaction n(*m); QVERIFY(n == *m); QVERIFY(!(n != *m)); } void MyMoneyTransactionTest::testInequality() { testConstructor(); MyMoneyTransaction n(*m); n.setPostDate(QDate(1, 1, 1)); QVERIFY(!(n == *m)); QVERIFY(n != *m); n = *m; n.setValue("key", "value"); QVERIFY(!(n == *m)); QVERIFY(n != *m); } void MyMoneyTransactionTest::testAddSplits() { m->setId("TestID"); MyMoneySplit split1, split2; split1.setAccountId("A000001"); split2.setAccountId("A000002"); split1.setValue(MyMoneyMoney(100, 100)); split2.setValue(MyMoneyMoney(200, 100)); try { QVERIFY(m->accountReferenced("A000001") == false); QVERIFY(m->accountReferenced("A000002") == false); m->addSplit(split1); m->addSplit(split2); QVERIFY(m->splitCount() == 2); QVERIFY(m->splits()[0].accountId() == "A000001"); QVERIFY(m->splits()[1].accountId() == "A000002"); QVERIFY(m->accountReferenced("A000001") == true); QVERIFY(m->accountReferenced("A000002") == true); QVERIFY(m->splits()[0].id() == "S0001"); QVERIFY(m->splits()[1].id() == "S0002"); QVERIFY(split1.id() == "S0001"); QVERIFY(split2.id() == "S0002"); QVERIFY(m->splits()[0].transactionId() == "TestID"); QVERIFY(m->splits()[1].transactionId() == "TestID"); QVERIFY(split1.transactionId() == "TestID"); QVERIFY(split2.transactionId() == "TestID"); } catch (const MyMoneyException &e) { unexpectedException(e); } // try to add split with assigned ID try { m->addSplit(split1); QFAIL("Exception expected!"); } catch (const MyMoneyException &) { } } void MyMoneyTransactionTest::testModifySplits() { testAddSplits(); MyMoneySplit split; split = m->splits()[0]; split.setAccountId("A000003"); split.setId("S00000000"); // this one should fail, because the ID is invalid try { m->modifySplit(split); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } // set id to correct value, and check that it worked split.setId("S0001"); try { m->modifySplit(split); QVERIFY(m->splitCount() == 2); QVERIFY(m->splits()[0].accountId() == "A000003"); QVERIFY(m->splits()[1].accountId() == "A000002"); QVERIFY(m->accountReferenced("A000001") == false); QVERIFY(m->accountReferenced("A000002") == true); QVERIFY(m->splits()[0].id() == "S0001"); QVERIFY(m->splits()[1].id() == "S0002"); QVERIFY(split.id() == "S0001"); QVERIFY(split.accountId() == "A000003"); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } } void MyMoneyTransactionTest::testDeleteSplits() { testAddSplits(); MyMoneySplit split; // add a third split split.setAccountId("A000003"); split.setValue(MyMoneyMoney(300, 100)); try { m->addSplit(split); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } split.setId("S00000000"); // this one should fail, because the ID is invalid try { m->modifySplit(split); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } // set id to correct value, and check that it worked split.setId("S0002"); try { m->removeSplit(split); QVERIFY(m->splitCount() == 2); QVERIFY(m->splits()[0].accountId() == "A000001"); QVERIFY(m->accountReferenced("A000002") == false); QVERIFY(m->accountReferenced("A000001") == true); QVERIFY(m->accountReferenced("A000003") == true); QVERIFY(m->splits()[0].id() == "S0001"); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } // set id to the other correct value, and check that it worked split.setId("S0003"); try { m->removeSplit(split); QVERIFY(m->splitCount() == 1); QVERIFY(m->accountReferenced("A000001") == true); QVERIFY(m->accountReferenced("A000003") == false); QVERIFY(m->splits()[0].id() == "S0001"); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } } void MyMoneyTransactionTest::testDeleteAllSplits() { testAddSplits(); try { m->removeSplits(); QVERIFY(m->splitCount() == 0); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } } void MyMoneyTransactionTest::testExtractSplit() { testAddSplits(); MyMoneySplit split; // this one should fail, as the account is not referenced by // any split in the transaction try { split = m->splitByAccount(QString("A000003")); QFAIL("Exception expected"); } catch (const MyMoneyException &) { } // this one should be found try { split = m->splitByAccount(QString("A000002")); QVERIFY(split.id() == "S0002"); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } // this one should be found also try { split = m->splitByAccount(QString("A000002"), false); QVERIFY(split.id() == "S0001"); } catch (const MyMoneyException &) { QFAIL("Unexpected exception!"); } } void MyMoneyTransactionTest::testSplitSum() { QVERIFY(m->splitSum().isZero()); testAddSplits(); MyMoneySplit s1, s2; s1 = m->splits()[0]; s1.setValue(MyMoneyMoney()); s2 = m->splits()[1]; s2.setValue(MyMoneyMoney()); m->modifySplit(s1); m->modifySplit(s2); QVERIFY(m->splitSum().isZero()); s1.setValue(MyMoneyMoney(1234, 100)); m->modifySplit(s1); QVERIFY(m->splitSum() == MyMoneyMoney(1234, 100)); s2.setValue(MyMoneyMoney(-1234, 100)); m->modifySplit(s2); QVERIFY(m->splitSum().isZero()); s1.setValue(MyMoneyMoney(5678, 100)); m->modifySplit(s1); QVERIFY(m->splitSum() == MyMoneyMoney(4444, 100)); } void MyMoneyTransactionTest::testIsLoanPayment() { testAddSplits(); QVERIFY(m->isLoanPayment() == false); MyMoneySplit s1, s2; s1 = m->splits()[0]; s2 = m->splits()[1]; s1.setAction(MyMoneySplit::ActionAmortization); m->modifySplit(s1); QVERIFY(m->isLoanPayment() == true); s1.setAction(MyMoneySplit::ActionWithdrawal); m->modifySplit(s1); QVERIFY(m->isLoanPayment() == false); s2.setAction(MyMoneySplit::ActionAmortization); m->modifySplit(s2); QVERIFY(m->isLoanPayment() == true); s2.setAction(MyMoneySplit::ActionWithdrawal); m->modifySplit(s2); QVERIFY(m->isLoanPayment() == false); } #if 0 void MyMoneyTransactionTest::testAddDuplicateAccount() { testAddSplits(); qDebug() << "Split count is" << m->splitCount(); MyMoneySplit split1, split2; split1.setAccountId("A000001"); split2.setAccountId("A000002"); split1.setValue(MyMoneyMoney(100)); split2.setValue(MyMoneyMoney(200)); try { QVERIFY(m->accountReferenced("A000001") == true); QVERIFY(m->accountReferenced("A000002") == true); m->addSplit(split1); m->addSplit(split2); qDebug() << "Split count is" << m->splitCount(); QVERIFY(m->splitCount() == 2); QVERIFY(m->splits()[0].accountId() == "A000001"); QVERIFY(m->splits()[1].accountId() == "A000002"); QVERIFY(m->accountReferenced("A000001") == true); QVERIFY(m->accountReferenced("A000002") == true); QVERIFY(m->splits()[0].id() == "S0001"); QVERIFY(m->splits()[1].id() == "S0002"); QVERIFY(split1.id() == "S0001"); QVERIFY(split2.id() == "S0002"); } catch (const MyMoneyException &e) { unexpectedException(e); } QVERIFY(m->splits()[0].value() == MyMoneyMoney(200)); QVERIFY(m->splits()[1].value() == MyMoneyMoney(400)); } void MyMoneyTransactionTest::testModifyDuplicateAccount() { testAddSplits(); MyMoneySplit split; split = m->splitByAccount(QString("A000002")); split.setAccountId("A000001"); try { m->modifySplit(split); QVERIFY(m->splitCount() == 1); QVERIFY(m->accountReferenced("A000001") == true); QVERIFY(m->splits()[0].value() == MyMoneyMoney(300)); } catch (const MyMoneyException &e) { unexpectedException(e); } } #endif void MyMoneyTransactionTest::testWriteXML() { MyMoneyTransaction t; t.setPostDate(QDate(2001, 12, 28)); t.setEntryDate(QDate(2003, 9, 29)); t.setId("T000000000000000001"); t.setMemo("Wohnung:Miete"); t.setCommodity("EUR"); t.setValue("key", "value"); MyMoneySplit s; s.setPayeeId("P000001"); QList tagIdList; tagIdList << "G000001"; s.setTagIdList(tagIdList); s.setShares(MyMoneyMoney(96379, 100)); s.setValue(MyMoneyMoney(96379, 100)); s.setAction(MyMoneySplit::ActionWithdrawal); s.setAccountId("A000076"); s.setReconcileFlag(eMyMoney::Split::State::Reconciled); s.setBankID("SPID"); t.addSplit(s); QDomDocument doc("TEST"); QDomElement el = doc.createElement("TRANSACTION-CONTAINER"); doc.appendChild(el); t.writeXML(doc, el); QCOMPARE(doc.doctype().name(), QLatin1String("TEST")); QDomElement transactionContainer = doc.documentElement(); QVERIFY(transactionContainer.isElement()); QCOMPARE(transactionContainer.tagName(), QLatin1String("TRANSACTION-CONTAINER")); QVERIFY(transactionContainer.childNodes().size() == 1); QVERIFY(transactionContainer.childNodes().at(0).isElement()); QDomElement transaction = transactionContainer.childNodes().at(0).toElement(); QCOMPARE(transaction.tagName(), QLatin1String("TRANSACTION")); QCOMPARE(transaction.attribute("id"), QLatin1String("T000000000000000001")); QCOMPARE(transaction.attribute("postdate"), QLatin1String("2001-12-28")); QCOMPARE(transaction.attribute("commodity"), QLatin1String("EUR")); QCOMPARE(transaction.attribute("memo"), QLatin1String("Wohnung:Miete")); QCOMPARE(transaction.attribute("entrydate"), QLatin1String("2003-09-29")); QCOMPARE(transaction.childNodes().size(), 2); QVERIFY(transaction.childNodes().at(0).isElement()); QDomElement splits = transaction.childNodes().at(0).toElement(); QCOMPARE(splits.tagName(), QLatin1String("SPLITS")); QCOMPARE(splits.childNodes().size(), 1); QVERIFY(splits.childNodes().at(0).isElement()); QDomElement split = splits.childNodes().at(0).toElement(); QCOMPARE(split.tagName(), QLatin1String("SPLIT")); QCOMPARE(split.attribute("id"), QLatin1String("S0001")); QCOMPARE(split.attribute("payee"), QLatin1String("P000001")); QCOMPARE(split.attribute("reconcileflag"), QLatin1String("2")); QCOMPARE(split.attribute("shares"), QLatin1String("96379/100")); QCOMPARE(split.attribute("reconciledate"), QString()); QCOMPARE(split.attribute("action"), QLatin1String("Withdrawal")); QCOMPARE(split.attribute("bankid"), QLatin1String("SPID")); QCOMPARE(split.attribute("account"), QLatin1String("A000076")); QCOMPARE(split.attribute("number"), QString()); QCOMPARE(split.attribute("value"), QLatin1String("96379/100")); QCOMPARE(split.attribute("memo"), QString()); QCOMPARE(split.childNodes().size(), 1); QVERIFY(split.childNodes().at(0).isElement()); QDomElement tag = split.childNodes().at(0).toElement(); QCOMPARE(tag.tagName(), QLatin1String("TAG")); QCOMPARE(tag.attribute("id"), QLatin1String("G000001")); QCOMPARE(tag.childNodes().size(), 0); QDomElement keyValuePairs = transaction.childNodes().at(1).toElement(); QCOMPARE(keyValuePairs.tagName(), QLatin1String("KEYVALUEPAIRS")); QCOMPARE(keyValuePairs.childNodes().size(), 1); QVERIFY(keyValuePairs.childNodes().at(0).isElement()); QDomElement keyValuePair1 = keyValuePairs.childNodes().at(0).toElement(); QCOMPARE(keyValuePair1.tagName(), QLatin1String("PAIR")); QCOMPARE(keyValuePair1.attribute("key"), QLatin1String("key")); QCOMPARE(keyValuePair1.attribute("value"), QLatin1String("value")); QCOMPARE(keyValuePair1.childNodes().size(), 0); } void MyMoneyTransactionTest::testReadXML() { MyMoneyTransaction t; QString ref_ok = QString( "\n" "\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "\n" ); QString ref_false = QString( "\n" "\n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" " \n" "\n" ); QDomDocument doc; QDomElement node; doc.setContent(ref_false); node = doc.documentElement().firstChild().toElement(); try { t = MyMoneyTransaction(node); QFAIL("Missing expected exception"); } catch (const MyMoneyException &) { } doc.setContent(ref_ok); node = doc.documentElement().firstChild().toElement(); t.setValue("key", "VALUE"); try { t = MyMoneyTransaction(node); QVERIFY(t.postDate() == QDate(2001, 12, 28)); QVERIFY(t.entryDate() == QDate(2003, 9, 29)); QVERIFY(t.id() == "T000000000000000001"); QVERIFY(t.memo() == "Wohnung:Miete"); QVERIFY(t.commodity() == "EUR"); QVERIFY(t.pairs().count() == 1); QVERIFY(t.value("key") == "value"); QVERIFY(t.splits().count() == 1); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } } void MyMoneyTransactionTest::testReadXMLEx() { MyMoneyTransaction t; QString ref_ok = QString( "\n" "\n" "\n" " \n" " \n" " \n" " \n" " \n" " &lt;CONTAINER>\n" " &lt;TRANSACTION postdate="2010-03-05" memo="UMBUCHUNG" id="" commodity="EUR" entrydate="2010-03-08" >\n" " &lt;SPLITS>\n" " &lt;SPLIT payee="P000010" reconciledate="" shares="125000/100" action="Transfer" bankid="" number="" reconcileflag="0" memo="UMBUCHUNG" value="125000/100" id="S0001" account="A000087" />\n" " &lt;SPLIT payee="P000010" reconciledate="" shares="-125000/100" action="" bankid="A000076-2010-03-05-b6850c0-1" number="" reconcileflag="0" memo="UMBUCHUNG" value="-125000/100" id="S0002" account="A000076" />\n" " &lt;/SPLITS>\n" " &lt;KEYVALUEPAIRS>\n" " &lt;PAIR key="Imported" value="true" />\n" " &lt;/KEYVALUEPAIRS>\n" " &lt;/TRANSACTION>\n" " &lt;/CONTAINER>\n" "\" />\n" " \n" " \n" " \n" " \n" " \n" "\n" "\n" ); QDomDocument doc; QDomElement node; doc.setContent(ref_ok); node = doc.documentElement().firstChild().toElement(); try { t = MyMoneyTransaction(node); QVERIFY(t.pairs().count() == 0); QVERIFY(t.splits().size() == 2); QVERIFY(t.splits()[0].pairs().count() == 3); QVERIFY(t.splits()[1].pairs().count() == 0); QVERIFY(t.splits()[0].isMatched()); MyMoneyTransaction ti = t.splits()[0].matchedTransaction(); QVERIFY(ti.pairs().count() == 1); QVERIFY(ti.isImported()); QVERIFY(ti.splits().count() == 2); } catch (const MyMoneyException &) { QFAIL("Unexpected exception"); } } void MyMoneyTransactionTest::testHasReferenceTo() { MyMoneyTransaction t; t.setPostDate(QDate(2001, 12, 28)); t.setEntryDate(QDate(2003, 9, 29)); t.setId("T000000000000000001"); t.setMemo("Wohnung:Miete"); t.setCommodity("EUR"); t.setValue("key", "value"); MyMoneySplit s; s.setPayeeId("P000001"); QList tagIdList; tagIdList << "G000001"; s.setTagIdList(tagIdList); s.setShares(MyMoneyMoney(96379, 100)); s.setValue(MyMoneyMoney(96379, 100)); s.setAction(MyMoneySplit::ActionWithdrawal); s.setAccountId("A000076"); s.setReconcileFlag(eMyMoney::Split::State::Reconciled); t.addSplit(s); QVERIFY(t.hasReferenceTo("EUR") == true); QVERIFY(t.hasReferenceTo("P000001") == true); QVERIFY(t.hasReferenceTo("G000001") == true); QVERIFY(t.hasReferenceTo("A000076") == true); } void MyMoneyTransactionTest::testAutoCalc() { QVERIFY(m->hasAutoCalcSplit() == false); testAddSplits(); QVERIFY(m->hasAutoCalcSplit() == false); MyMoneySplit split; split = m->splits()[0]; split.setShares(MyMoneyMoney::autoCalc); split.setValue(MyMoneyMoney::autoCalc); m->modifySplit(split); QVERIFY(m->hasAutoCalcSplit() == true); } void MyMoneyTransactionTest::testIsStockSplit() { QVERIFY(m->isStockSplit() == false); testAddSplits(); QVERIFY(m->isStockSplit() == false); m->removeSplits(); MyMoneySplit s; s.setShares(MyMoneyMoney(1, 2)); s.setAction(MyMoneySplit::ActionSplitShares); s.setAccountId("A0001"); m->addSplit(s); QVERIFY(m->isStockSplit() == true); } void MyMoneyTransactionTest::testAddMissingAccountId() { MyMoneySplit s; s.setShares(MyMoneyMoney(1, 2)); try { m->addSplit(s); QFAIL("Missing expected exception"); } catch (const MyMoneyException &) { } } void MyMoneyTransactionTest::testModifyMissingAccountId() { testAddSplits(); MyMoneySplit s = m->splits()[0]; s.setAccountId(QString()); try { m->modifySplit(s); QFAIL("Missing expected exception"); } catch (const MyMoneyException &) { } } void MyMoneyTransactionTest::testReplaceId() { testAddSplits(); bool changed; try { changed = m->replaceId("Joe", "Bla"); QVERIFY(changed == false); QVERIFY(m->splits()[0].accountId() == "A000001"); QVERIFY(m->splits()[1].accountId() == "A000002"); changed = m->replaceId("A000003", "A000001"); QVERIFY(changed == true); QVERIFY(m->splits()[0].accountId() == "A000003"); QVERIFY(m->splits()[1].accountId() == "A000002"); changed = m->replaceId("A000004", "A000002"); QVERIFY(changed == true); QVERIFY(m->splits()[0].accountId() == "A000003"); QVERIFY(m->splits()[1].accountId() == "A000004"); } catch (const MyMoneyException &e) { unexpectedException(e); } } void MyMoneyTransactionTest::testElementNames() { for (auto i = (int)MyMoneyTransaction::Element::Split; i <= (int)MyMoneyTransaction::Element::Splits; ++i) { auto isEmpty = MyMoneyTransaction::getElName(static_cast(i)).isEmpty(); if (isEmpty) qWarning() << "Empty element's name " << i; QVERIFY(!isEmpty); } } void MyMoneyTransactionTest::testAttributeNames() { for (auto i = (int)MyMoneyTransaction::Attribute::Name; i < (int)MyMoneyTransaction::Attribute::LastAttribute; ++i) { auto isEmpty = MyMoneyTransaction::getAttrName(static_cast(i)).isEmpty(); if (isEmpty) qWarning() << "Empty attribute's name " << i; QVERIFY(!isEmpty); } } diff --git a/kmymoney/mymoney/tests/mymoneytransaction-test.h b/kmymoney/mymoney/tests/mymoneytransaction-test.h index a403b81ee..8ca2f4964 100644 --- a/kmymoney/mymoney/tests/mymoneytransaction-test.h +++ b/kmymoney/mymoney/tests/mymoneytransaction-test.h @@ -1,64 +1,64 @@ /*************************************************************************** mymoneytransactiontest.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 MYMONEYTRANSACTIONTEST_H #define MYMONEYTRANSACTIONTEST_H -#include +#include #define KMM_MYMONEY_UNIT_TESTABLE friend class MyMoneyTransactionTest; #include "mymoneytransaction.h" class MyMoneyTransactionTest : public QObject { Q_OBJECT protected: MyMoneyTransaction *m; private slots: void init(); void cleanup(); void testEmptyConstructor(); void testSetFunctions(); void testConstructor(); void testCopyConstructor(); void testAssignmentConstructor(); void testEquality(); void testInequality(); void testAddSplits(); void testModifySplits(); void testDeleteSplits(); void testExtractSplit(); void testDeleteAllSplits(); void testSplitSum(); void testIsLoanPayment(); //void testAddDuplicateAccount(); //void testModifyDuplicateAccount(); void testWriteXML(); void testReadXML(); void testReadXMLEx(); void testAutoCalc(); void testHasReferenceTo(); void testIsStockSplit(); void testAddMissingAccountId(); void testModifyMissingAccountId(); void testReplaceId(); void testElementNames(); void testAttributeNames(); }; #endif diff --git a/kmymoney/mymoney/tests/onlinejob-test.h b/kmymoney/mymoney/tests/onlinejob-test.h index 45b261ccc..e8edfa421 100644 --- a/kmymoney/mymoney/tests/onlinejob-test.h +++ b/kmymoney/mymoney/tests/onlinejob-test.h @@ -1,41 +1,41 @@ /* * This file is part of KMyMoney, A Personal Finance Manager by KDE * Copyright (C) 2014 Christian Dávid * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef ONLINEJOBTEST_H #define ONLINEJOBTEST_H #include -#include +#include class onlineJobTest : public QObject { Q_OBJECT private slots: // void initTestCase(); // void cleanupTestCase(); void testDefaultConstructor(); void testCopyConstructor(); void testCopyAssignment(); void testCopyConstructorWithNewId(); void testElementNames(); void testAttributeNames(); }; #endif // ONLINEJOBTEST_H diff --git a/kmymoney/mymoney/tests/onlinejobadministration-test.h b/kmymoney/mymoney/tests/onlinejobadministration-test.h index d0d5b9fc2..1f4a6d2ec 100644 --- a/kmymoney/mymoney/tests/onlinejobadministration-test.h +++ b/kmymoney/mymoney/tests/onlinejobadministration-test.h @@ -1,45 +1,45 @@ /* * This file is part of KMyMoney, A Personal Finance Manager by KDE * Copyright (C) 2014 Christian Dávid * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef ONLINEJOBADMINISTRATIONTEST_H #define ONLINEJOBADMINISTRATIONTEST_H #include -#include +#include class MyMoneyFile; class IMyMoneyStorage; #define KMM_MYMONEY_UNIT_TESTABLE friend class onlineJobAdministrationTest; class onlineJobAdministrationTest : public QObject { Q_OBJECT IMyMoneyStorage* storage; MyMoneyFile* file; QString accountId; private slots: void initTestCase(); void cleanupTestCase(); void init(); void getSettings(); void registerOnlineTask(); }; #endif // ONLINEJOBADMINISTRATIONTEST_H diff --git a/kmymoney/payeeidentifier/ibanandbic/bicmodel.cpp b/kmymoney/payeeidentifier/ibanandbic/bicmodel.cpp index ed32e63a3..8fdacc75e 100644 --- a/kmymoney/payeeidentifier/ibanandbic/bicmodel.cpp +++ b/kmymoney/payeeidentifier/ibanandbic/bicmodel.cpp @@ -1,112 +1,112 @@ /* * This file is part of KMyMoney, A Personal Finance Manager by KDE * Copyright (C) 2014 Christian Dávid * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "bicmodel.h" #include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include /** * @warning At the moment the completion may fail if bicModel was created in more than one thread * (it uses a QSqlDatabase object over all instances of bicModel, so the first created bicModel defines * the thread) * * @todo Make thread safe. */ bicModel::bicModel(QObject* parent) : QSqlQueryModel(parent) { QSqlDatabase db = QSqlDatabase::database("bicModel", true); // Save if the database was opened before bool attachDatabases = false; if (!db.isValid()) { db = QSqlDatabase::addDatabase("QSQLITE", "bicModel"); db.setDatabaseName(":memory:"); db.setConnectOptions("QSQLITE_OPEN_READONLY=1;QSQLITE_ENABLE_SHARED_CACHE=1;"); db.open(); // Database was not opened before attachDatabases = true; } if (!db.isOpen()) { qWarning() << QString("Could not open in-memory database for bic data."); } QSqlQuery query(db); // Get services which support iban2bic and have a database entry KService::List services = KServiceTypeTrader::self()->query("KMyMoney/IbanBicData", QString("exist [X-KMyMoney-Bankdata-Database]") ); if (services.isEmpty()) { // Set a valid query query.exec("SELECT null;"); setQuery(query); return; } QStringList databases; QStringList dbNames; unsigned int databaseCount = 0; foreach (KService::Ptr service, services) { QString database = service->property(QLatin1String("X-KMyMoney-Bankdata-Database")).toString(); // Locate database QString path = QStandardPaths::locate(QStandardPaths::DataLocation, QLatin1String("kmymoney/ibanbicdata/") + database); if (path.isEmpty()) { qWarning() << QString("Could not locate database file \"%1\" to receive BIC data.").arg(database); } else { databases << path; dbNames << QString("db%1").arg(++databaseCount); } } if (attachDatabases) { query.prepare("ATTACH DATABASE ? AS ?"); query.addBindValue(databases); query.addBindValue(dbNames); if (!query.execBatch()) { qWarning() << "Could not init bic for bicModel, last error:" << query.lastError().text(); dbNames = QStringList(); // clear so no query will be set } } QStringList queries; foreach (QString dbName, dbNames) { queries.append(QString("SELECT bic, name FROM %1.institutions").arg(dbName)); } query.exec(queries.join(QLatin1String(" UNION "))); setQuery(query); } QVariant bicModel::data(const QModelIndex& item, int role) const { if (role == InstitutionNameRole) return QSqlQueryModel::data(createIndex(item.row(), 1), Qt::DisplayRole); return QSqlQueryModel::data(item, role); } diff --git a/kmymoney/payeeidentifier/ibanandbic/bicmodel.h b/kmymoney/payeeidentifier/ibanandbic/bicmodel.h index a85521ae5..b3acad876 100644 --- a/kmymoney/payeeidentifier/ibanandbic/bicmodel.h +++ b/kmymoney/payeeidentifier/ibanandbic/bicmodel.h @@ -1,40 +1,40 @@ /* * This file is part of KMyMoney, A Personal Finance Manager by KDE * Copyright (C) 2014 Christian Dávid * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef BICMODEL_H #define BICMODEL_H -#include +#include #include "iban_bic_identifier_export.h" class IBAN_BIC_IDENTIFIER_EXPORT bicModel : public QSqlQueryModel { Q_OBJECT public: enum DisplayRole { InstitutionNameRole = Qt::UserRole }; explicit bicModel(QObject* parent = 0); virtual QVariant data(const QModelIndex& item, int role = Qt::DisplayRole) const; }; #endif // BICMODEL_H diff --git a/kmymoney/payeeidentifier/ibanandbic/ibanbic.h b/kmymoney/payeeidentifier/ibanandbic/ibanbic.h index 653731fa0..5a23d6451 100644 --- a/kmymoney/payeeidentifier/ibanandbic/ibanbic.h +++ b/kmymoney/payeeidentifier/ibanandbic/ibanbic.h @@ -1,271 +1,271 @@ /* * This file is part of KMyMoney, A Personal Finance Manager by KDE * Copyright (C) 2014 Christian Dávid * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef PAYEEIDENTIFIER_IBANBIC_H #define PAYEEIDENTIFIER_IBANBIC_H -#include -#include +#include +#include #include "payeeidentifier/payeeidentifierdata.h" #include "mymoneyunittestable.h" #include "iban_bic_identifier_export.h" class ibanBicData; namespace payeeIdentifiers { /** * @brief Plugin to handle IBANs and BICs * * Can store a pair of an International Bank Account Number (ISO 13616) and Business Identifier Code (ISO 9362). * */ class IBAN_BIC_IDENTIFIER_EXPORT ibanBic : public payeeIdentifierData { KMM_MYMONEY_UNIT_TESTABLE public: PAYEEIDENTIFIER_IID(ibanBic, "org.kmymoney.payeeIdentifier.ibanbic"); enum bicAllocationStatus { bicAllocated = 0, bicNotAllocated, bicAllocationUncertain }; ibanBic(); ibanBic(const ibanBic& other); ibanBic* clone() const; ibanBic* createFromXml(const QDomElement& element) const; void writeXML(QDomDocument& document, QDomElement& parent) const; /** * @brief Set an owner name for this account */ void setOwnerName(const QString& ownerName) { m_ownerName = ownerName; } QString ownerName() const { return m_ownerName; } /** * @brief Set a IBAN * * The IBAN can contain spaces and other special chars. */ void setIban(const QString& iban); /** @copydoc m_iban * Use this method if you know that iban is in electronic format already. No futher checks are done. */ void setElectronicIban(const QString& iban) { Q_ASSERT(iban == ibanToElectronic(iban)); m_iban = iban; } /** @copydoc m_iban */ QString electronicIban() const { return m_iban; } /** * @brief Returns iban in human readable format * @see toPaperformatIban() */ QString paperformatIban(const QString& separator = QLatin1String(" ")) const; /** * @brief Set Business Identifier Code * * Call without parameter or QString() to remove bic * * @param bic will be normalized */ void setBic(const QString& bic = QString()); /** * @brief Business Identifier Code * According to ISO 9362 * * The returned bic is normalized: * A tailing XXX is omitted, all characters are uppercase. */ QString storedBic() const { return m_bic; } /** * @copydoc storedBic() * * Return a stored BIC (if there is any) or try to use the iban to get a BIC. */ QString bic() const; /** * @brief Business Identifier Code with tailing XXX * * Like @a bic() but always 11 characters long (if bic is invalid, it can have another length). */ QString fullBic() const; /** * @copydoc fullBic() * * This method will not try to use the iban to get a bic. */ QString fullStoredBic() const; /** * @brief Lookup institutions name * * Uses any available information to return an institutionName */ QString institutionName() const { return institutionNameByBic(bic()); } virtual bool operator==(const payeeIdentifierData& other) const; bool operator==(const ibanBic& other) const; virtual bool isValid() const; /** * @brief Extends a bic to 11 characters * * Also all characters are made upper case. */ static QString bicToFullFormat(QString bic); /** * @brief Converts an iban to canonical format for machines * * Will remove all white spaces. */ static QString ibanToElectronic(const QString& iban); /** * @brief Converts an iban to human readable format * * Grouped in four letters strings separated by a white space. * * @param iban an iban, not needed to be canonical, valid or completed * @param separator Overwrite the default separator (e.g. a smaller space) */ static QString ibanToPaperformat(const QString& iban, const QString& seperator = QLatin1String(" ")); /** * @brief Extract Basic Bank Account Number * * Returns the Basic Bank Account Number (BBAN) from the IBAN. * The BBAN is the IBAN without country code and the two digit checksum. */ static QString bban(const QString& iban); static int ibanLengthByCountry(const QString& countryCode); static QString institutionNameByBic(const QString& bic); static QString bicByIban(const QString& iban); static QString localBankCodeByIban(const QString& iban); /** * @brief Chech if IBAN is valid */ bool isIbanValid() const; /** * @brief Check if IBAN can be valid * * This method also checks if the given country code is valid. * * If also local aware checks are done (e.g. character set and length of BBAN). * * @todo Implement local aware checks */ static bool isIbanValid(const QString& iban); /** * @brief Check if this BIC is assigned to an bank * * This method does not check the given BIC but looks up in the database directly. * So it might be useful if time consumption is important but isBicAllocated() should * be your first option. * * @param bic BIC to test in canonical format (always 11 characters long, all characters uppercase) * @see isBicAllocated() */ static bicAllocationStatus isCanonicalBicAllocated(const QString& bic); /** @brief Check if this BIC is assigned to an bank * * @param bic BIC to test. */ static bicAllocationStatus isBicAllocated(const QString& bic); /** * @brief Check the checksum * * Test if the ISO 7064 mod 97-10 checksum of the iban is correct. * * @param iban An IBAN in electronic format (important!) */ static bool validateIbanChecksum(const QString& iban); static const int ibanMaxLength; QString storagePluginIid() const { return QLatin1String("org.kmymoney.payeeIdentifier.ibanbic.sqlStoragePlugin"); } bool sqlSave(QSqlDatabase databaseConnection, const QString& objectId) const; bool sqlModify(QSqlDatabase databaseConnection, const QString& objectId) const; bool sqlRemove(QSqlDatabase databaseConnection, const QString& objectId) const; private: /** * @brief Business Identifier Code * According to ISO 9362 * * A trailing XXX must be ommitted. All characters must be upper case. */ QString m_bic; /** * @brief International Bank Account Number * According to ISO 13616-1:2007 Part 1 * in normalized (electronic) format (no spaces etc.) */ QString m_iban; QString m_ownerName; static ::ibanBicData* getIbanBicData(); static ::ibanBicData* m_ibanBicData; bool writeQuery(QSqlQuery& query, const QString& id) const; payeeIdentifierData* createFromSqlDatabase(QSqlDatabase db, const QString& identId) const; static QString canonizeBic(const QString& bic); }; } // namespace payeeIdentifiers #endif // PAYEEIDENTIFIER_IBANBIC_H diff --git a/kmymoney/payeeidentifier/ibanandbic/ibanbicdata.cpp b/kmymoney/payeeidentifier/ibanandbic/ibanbicdata.cpp index 99ad4f95f..81b4daf4a 100644 --- a/kmymoney/payeeidentifier/ibanandbic/ibanbicdata.cpp +++ b/kmymoney/payeeidentifier/ibanandbic/ibanbicdata.cpp @@ -1,276 +1,276 @@ /* * This file is part of KMyMoney, A Personal Finance Manager by KDE * Copyright (C) 2014 Christian Dávid * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "ibanbicdata.h" #include -#include +#include #include -#include -#include +#include +#include #include "ibanbic.h" ibanBicData::~ibanBicData() { } int ibanBicData::bankIdentifierLength(const QString& countryCode) { const QVariant value = findPropertyByCountry(countryCode, QLatin1String("X-KMyMoney-BankIdentifier-Length"), QVariant::Int); if (value.isValid()) return value.toInt(); return 0; } int ibanBicData::bankIdentifierPosition(const QString& countryCode) { const QVariant value = findPropertyByCountry(countryCode, QLatin1String("X-KMyMoney-BankIdentifier-Position"), QVariant::Int); if (value.isValid()) return value.toInt(); return -1; } int ibanBicData::bbanLength(const QString& countryCode) { const QVariant value = findPropertyByCountry(countryCode, QLatin1String("X-KMyMoney-BBAN-Length"), QVariant::Int); if (value.isValid()) return value.toInt(); // Something went wrong, so return the allowed maximum return 30; } QString ibanBicData::iban2Bic(const QString& iban) { Q_ASSERT(iban.length() < 1 || iban.at(0).isLetterOrNumber()); Q_ASSERT(iban.length() < 2 || iban.at(1).isLetterOrNumber()); Q_ASSERT(iban == payeeIdentifiers::ibanBic::ibanToElectronic(iban)); if (iban.length() <= 4) // This iban is to short to extract a BIC return QString(""); // Get bank identifier const QString bankCode = extractBankIdentifier(iban); if (bankCode.isEmpty()) return bankCode; // keep .isEmpty() or .isNull() // Get countryCode const QString countryCode = iban.left(2); // Get services which support iban2bic and have a database entry KService::List services = KServiceTypeTrader::self()->query("KMyMoney/IbanBicData", QString("(\'%1' ~in [X-KMyMoney-CountryCodes] or '*' in [X-KMyMoney-CountryCodes]) and true == [X-KMyMoney-IBAN-2-BIC-supported] and exist [X-KMyMoney-Bankdata-Database]").arg(countryCode) ); if (services.isEmpty()) return QString(); QSqlDatabase db = createDatabaseConnection(services.first()->property(QLatin1String("X-KMyMoney-Bankdata-Database"), QVariant::String).toString()); if (!db.isOpen()) // This is an error return QString(); QSqlQuery query = QSqlQuery(db); query.prepare("SELECT bic FROM institutions WHERE bankcode=? and country=?"); query.bindValue(0, bankCode); query.bindValue(1, countryCode); if (!query.exec()) { qWarning() << QString("Could not execute query on \"%1\" to receive BIC. Error: %2").arg(db.databaseName()).arg(query.lastError().text()); return QString(); } if (query.next()) { return query.value(0).toString(); } return QString(""); } QString ibanBicData::bankNameByBic(QString bic) { if (bic.length() == 8) bic += QLatin1String("XXX"); else if (bic.length() != 11) return QString(); const QString countryCode = bic.mid(4, 2); // Get services which have a database entry KService::List services = KServiceTypeTrader::self()->query("KMyMoney/IbanBicData", QString("(\'%1' ~in [X-KMyMoney-CountryCodes] or '*' in [X-KMyMoney-CountryCodes]) and exist [X-KMyMoney-Bankdata-Database]").arg(countryCode) ); if (services.isEmpty()) return QString(); QSqlDatabase db = createDatabaseConnection(services.first()->property("X-KMyMoney-Bankdata-Database", QVariant::String).toString()); if (!db.isOpen()) // This is an error return QString(); QSqlQuery query = QSqlQuery(db); query.prepare("SELECT name FROM institutions WHERE bic=?"); query.bindValue(0, bic); if (!query.exec()) { qWarning() << QString("Could not execute query on \"%1\" to receive bank name. Error: %2").arg(db.databaseName()).arg(query.lastError().text()); return QString(); } if (query.next()) { return query.value(0).toString(); } return QString(""); } QPair< QString, QString > ibanBicData::bankNameAndBic(const QString& iban) { Q_ASSERT(iban.length() < 1 || iban.at(0).isLetterOrNumber()); Q_ASSERT(iban.length() < 2 || iban.at(1).isLetterOrNumber()); Q_ASSERT(iban == payeeIdentifiers::ibanBic::ibanToElectronic(iban)); if (iban.length() <= 4) // This iban is to short to extract a BIC return QPair(); // Get bank identifier const QString bankCode = extractBankIdentifier(iban); if (bankCode.isEmpty()) return QPair(bankCode, bankCode); // keep .isEmpty() or .isNull() // Get countryCode const QString countryCode = iban.left(2); // Get services which support iban2bic and have a database entry KService::List services = KServiceTypeTrader::self()->query("KMyMoney/IbanBicData", QString("(\'%1' ~in [X-KMyMoney-CountryCodes] or '*' in [X-KMyMoney-CountryCodes]) and true == [X-KMyMoney-IBAN-2-BIC-supported] and exist [X-KMyMoney-Bankdata-Database]").arg(countryCode) ); if (services.isEmpty()) return QPair(); QSqlDatabase db = createDatabaseConnection(services.first()->property(QLatin1String("X-KMyMoney-Bankdata-Database"), QVariant::String).toString()); if (!db.isOpen()) // This is an error return QPair(); QSqlQuery query(db); query.prepare("SELECT bic, name FROM institutions WHERE bankcode=? and country=?"); query.bindValue(0, bankCode); query.bindValue(1, countryCode); if (!query.exec()) { qWarning() << QString("Could not execute query on \"%1\" to receive BIC and name. Error: %2").arg(db.databaseName()).arg(query.lastError().text()); return QPair(); } if (query.next()) { return QPair(query.value(0).toString(), query.value(1).toString()); } return QPair(QString(""), QString("")); } ibanBicData::bicAllocationStatus ibanBicData::isBicAllocated(const QString& bic) { // Get countryCode const QString countryCode = bic.mid(4, 2); if (countryCode.length() != 2) return bicNotAllocated; // Get services which have a database entry KService::List services = KServiceTypeTrader::self()->query("KMyMoney/IbanBicData", QString("(\'%1' ~in [X-KMyMoney-CountryCodes] or '*' in [X-KMyMoney-CountryCodes]) and exist [X-KMyMoney-Bankdata-Database]").arg(countryCode) ); if (services.isEmpty()) return bicAllocationUncertain; QSqlDatabase db = createDatabaseConnection(services.first()->property(QLatin1String("X-KMyMoney-Bankdata-Database"), QVariant::String).toString()); if (!db.isOpen()) // This is an error return bicAllocationUncertain; QSqlQuery query(db); query.prepare("SELECT ? IN (SELECT bic FROM institutions)"); query.bindValue(0, bic); if (!query.exec() || !query.next()) { qWarning() << QString("Could not execute query on \"%1\" to check if bic exists. Error: %2").arg(db.databaseName()).arg(query.lastError().text()); return bicAllocationUncertain; } if (query.value(0).toBool()) // Bic found return bicAllocated; // Bic not found, test if database is complete if (services.first()->property(QLatin1String("X-KMyMoney-Bankdata-IsComplete"), QVariant::Bool).toBool()) return bicNotAllocated; return bicAllocationUncertain; } QVariant ibanBicData::findPropertyByCountry(const QString& countryCode, const QString& property, const QVariant::Type type) { const KService::List services = KServiceTypeTrader::self()->query("KMyMoney/IbanBicData", QString("'%1' ~in [X-KMyMoney-CountryCodes] and exist [%2]").arg(countryCode).arg(property) ); if (!services.isEmpty()) return services.first()->property(property, type); // Something went wrong return QVariant(); } QString ibanBicData::extractBankIdentifier(const QString& iban) { const QString countryCode = iban.left(2); // Extract bank code const int start = bankIdentifierPosition(countryCode); if (start == -1) return QString(""); return iban.mid(start + 4, bankIdentifierLength(countryCode)); } QSqlDatabase ibanBicData::createDatabaseConnection(const QString& database) { Q_ASSERT(QSqlDatabase::drivers().contains("QSQLITE")); // Try to use already created connection const QString connectionName = QLatin1String("ibanBicData/") + database; QSqlDatabase storedConnection = QSqlDatabase::database(connectionName); if (storedConnection.isValid() && storedConnection.isOpen()) return storedConnection; // Need to create new connection, locate database QString path = QStandardPaths::locate(QStandardPaths::DataLocation, QLatin1String("kmymoney/ibanbicdata/") + database); if (path.isEmpty()) { qWarning() << QString("Could not locate database file \"%1\" to receive IBAN and BIC data.").arg(database); return QSqlDatabase(); } // Connect QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", connectionName); db.setDatabaseName(path); db.setConnectOptions("QSQLITE_OPEN_READONLY=1;QSQLITE_ENABLE_SHARED_CACHE=1;"); const bool opened = db.open(); if (!opened) { qWarning() << QString("Could not open database \"%1\" to receive IBAN and BIC data.").arg(path); } return db; } diff --git a/kmymoney/payeeidentifier/ibanandbic/ibanbicdata.h b/kmymoney/payeeidentifier/ibanandbic/ibanbicdata.h index ac9e1557d..679f1f391 100644 --- a/kmymoney/payeeidentifier/ibanandbic/ibanbicdata.h +++ b/kmymoney/payeeidentifier/ibanandbic/ibanbicdata.h @@ -1,94 +1,94 @@ /* * This file is part of KMyMoney, A Personal Finance Manager by KDE * Copyright (C) 2014 Christian Dávid * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef IBANBICDATA_H #define IBANBICDATA_H #ifndef KMM_MYMONEY_UNIT_TESTABLE # define KMM_MYMONEY_UNIT_TESTABLE #endif -#include -#include -#include +#include +#include +#include /** * @brief This class implements everything that needs lookup * * Kind of a static private class of payeeIdentifier::ibanBic. It loads the iban/bic data and queries the * databases. * * @interal This class is made if a cache will be needed in future. */ class ibanBicData : public QObject { Q_OBJECT KMM_MYMONEY_UNIT_TESTABLE public: ~ibanBicData(); enum bicAllocationStatus { bicAllocated = 0, bicNotAllocated, bicAllocationUncertain }; int bbanLength(const QString& countryCode); int bankIdentifierPosition(const QString& countryCode); int bankIdentifierLength(const QString& countryCode); /** * @brief Create a BIC from a given IBAN * * The bic is always 11 characters long. * * @return QString::isNull() == true means an internal error occurred, QString::isEmpty() == true means there is no BIC */ QString iban2Bic(const QString& iban); QString bankNameByBic(QString bic); /** * @brief Create a BIC from a IBAN and get the institutes name * * first: bic, always 11 characters long. * second: instution name * * QString::isNull() == true means an internal error occurred, QString::isEmpty() == true means there is no data */ QPair bankNameAndBic(const QString& iban); QString extractBankIdentifier(const QString& iban); bicAllocationStatus isBicAllocated(const QString& bic); private: QVariant findPropertyByCountry(const QString& countryCode, const QString& property, const QVariant::Type type); /** * @brief Create/get QSqlDatabase * * Returns a QSqlDatabase. It is invalid if something went wrong. * * @param database This string is used to locate the database in the data dir */ QSqlDatabase createDatabaseConnection(const QString& database); }; #endif // IBANBICDATA_H diff --git a/kmymoney/payeeidentifier/ibanandbic/widgets/bicvalidator.h b/kmymoney/payeeidentifier/ibanandbic/widgets/bicvalidator.h index 2f16e7ab2..d8a1c9f76 100644 --- a/kmymoney/payeeidentifier/ibanandbic/widgets/bicvalidator.h +++ b/kmymoney/payeeidentifier/ibanandbic/widgets/bicvalidator.h @@ -1,39 +1,39 @@ /* * This file is part of KMyMoney, A Personal Finance Manager by KDE * Copyright (C) 2014 Christian David * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef BICVALIDATOR_H #define BICVALIDATOR_H -#include +#include #include "payeeidentifier_iban_bic_widgets_export.h" #include "kmymoneyvalidationfeedback.h" namespace eWidgets { namespace ValidationFeedback { enum class MessageType; } } class PAYEEIDENTIFIER_IBAN_BIC_WIDGETS_EXPORT bicValidator : public QValidator { Q_OBJECT public: explicit bicValidator(QObject* parent = 0); virtual QValidator::State validate(QString& , int&) const; static QPair validateWithMessage(const QString&); }; #endif // BICVALIDATOR_H diff --git a/kmymoney/payeeidentifier/ibanandbic/widgets/ibanvalidator.h b/kmymoney/payeeidentifier/ibanandbic/widgets/ibanvalidator.h index fa42e4cf0..a70bb566a 100644 --- a/kmymoney/payeeidentifier/ibanandbic/widgets/ibanvalidator.h +++ b/kmymoney/payeeidentifier/ibanandbic/widgets/ibanvalidator.h @@ -1,43 +1,43 @@ /* * This file is part of KMyMoney, A Personal Finance Manager by KDE * Copyright (C) 2014 Christian David * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef IBANVALIDATOR_H #define IBANVALIDATOR_H #include "payeeidentifier_iban_bic_widgets_export.h" -#include +#include #include "kmymoneyvalidationfeedback.h" namespace eWidgets { namespace ValidationFeedback { enum class MessageType; } } class PAYEEIDENTIFIER_IBAN_BIC_WIDGETS_EXPORT ibanValidator : public QValidator { Q_OBJECT public: explicit ibanValidator(QObject* parent = 0); virtual State validate(QString& , int&) const; State validate(const QString&) const; virtual void fixup(QString&) const; static QPair validateWithMessage(const QString&); }; #endif // IBANVALIDATOR_H diff --git a/kmymoney/payeeidentifier/ibanandbic/widgets/kbicedit.h b/kmymoney/payeeidentifier/ibanandbic/widgets/kbicedit.h index c4694db31..aa2cffb9d 100644 --- a/kmymoney/payeeidentifier/ibanandbic/widgets/kbicedit.h +++ b/kmymoney/payeeidentifier/ibanandbic/widgets/kbicedit.h @@ -1,41 +1,41 @@ /* * This file is part of KMyMoney, A Personal Finance Manager by KDE * Copyright (C) 2014 Christian Dávid * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef KBICEDIT_H #define KBICEDIT_H -#include +#include #include #include "payeeidentifier_iban_bic_widgets_export.h" class QAbstractItemDelegate; class PAYEEIDENTIFIER_IBAN_BIC_WIDGETS_EXPORT KBicEdit : public KLineEdit { Q_OBJECT public: explicit KBicEdit(QWidget* parent = 0); virtual ~KBicEdit(); private: QAbstractItemDelegate* m_popupDelegate; }; #endif // KBICEDIT_H diff --git a/kmymoney/plugins/csvimport/tests/csvdate-test.cpp b/kmymoney/plugins/csvimport/tests/csvdate-test.cpp index 4a2909cf4..110244f98 100644 --- a/kmymoney/plugins/csvimport/tests/csvdate-test.cpp +++ b/kmymoney/plugins/csvimport/tests/csvdate-test.cpp @@ -1,76 +1,76 @@ /*************************************************************************** csvdatetest.cpp ------------------- begin : Sat Jan 01 2010 copyright : (C) 2010 by Allan Anderson email : agander93@gmail.com copyright : (C) 2017 by Łukasz Wojniłowicz email : lukasz.wojnilowicz@gmail.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 "csvdate-test.h" -#include +#include #include "../convdate.h" QTEST_GUILESS_MAIN(CsvDateTest); void CsvDateTest::init() { m_convert = new ConvertDate; } void CsvDateTest::cleanup() { delete m_convert; } void CsvDateTest::testConvertDate() { m_convert->setDateFormatIndex(DateFormat::YearMonthDay); // ISO date format QVERIFY(m_convert->convertDate("2001-11-30") == QDate(2001, 11, 30)); QVERIFY(m_convert->convertDate("20011130") == QDate(2001, 11, 30)); QVERIFY(m_convert->convertDate("2001-11-30-09.32.35") == QDate(2001, 11, 30)); QVERIFY(m_convert->convertDate("08.00.00 2001-11-30") == QDate(2001, 11, 30)); QVERIFY(m_convert->convertDate("2001-11-30-14.52.10") == QDate(2001, 11, 30)); QVERIFY(m_convert->convertDate("2001-11-30 11:08:50") == QDate(2001, 11, 30)); QVERIFY(m_convert->convertDate("2001-11-30-07.03") == QDate(2001, 11, 30)); QVERIFY(m_convert->convertDate("2001-11-30:06.35 AM") == QDate(2001, 11, 30)); QVERIFY(m_convert->convertDate("20011130 020100") == QDate(2001, 11, 30)); QVERIFY(m_convert->convertDate("11-30-2001") == QDate()); QVERIFY(m_convert->convertDate("11302001") == QDate()); m_convert->setDateFormatIndex(DateFormat::MonthDayYear); // US date format QVERIFY(m_convert->convertDate("2001-11-30") == QDate()); QVERIFY(m_convert->convertDate("20011130") == QDate()); QVERIFY(m_convert->convertDate("11-30-2001") == QDate(2001, 11, 30)); QVERIFY(m_convert->convertDate("11302001") == QDate(2001, 11, 30)); m_convert->setDateFormatIndex(DateFormat::DayMonthYear); // UK/EU date format; QVERIFY(m_convert->convertDate("13/09/81") == QDate(1981, 9, 13)); QVERIFY(m_convert->convertDate("13/09/01") == QDate(2001, 9, 13)); QVERIFY(m_convert->convertDate("13-09-81") == QDate(1981, 9, 13)); QVERIFY(m_convert->convertDate("13-09-01") == QDate(2001, 9, 13)); QVERIFY(m_convert->convertDate(QString("25-" + QDate::longMonthName(12) + "-2000")) == QDate(2000, 12, 25)); QVERIFY(m_convert->convertDate(QString("25-" + QLocale().standaloneMonthName(12, QLocale::ShortFormat) + "-2000")) == QDate(2000, 12, 25)); QVERIFY(m_convert->convertDate("13.09.81") == QDate(1981, 9, 13)); QVERIFY(m_convert->convertDate("32/01/2000") == QDate()); // invalid day QVERIFY(m_convert->convertDate(QLatin1String("13-rubbishmonth-2000")) == QDate()); // invalid month QVERIFY(m_convert->convertDate("01/13/2000") == QDate()); // invalid month QVERIFY(m_convert->convertDate("01/12/200") == QDate()); // invalid year QVERIFY(m_convert->convertDate("") == QDate()); // empty date QVERIFY(m_convert->convertDate("31-1-2010") == QDate(2010, 1, 31)); // single digit month QVERIFY(m_convert->convertDate("13091981") == QDate(1981, 9, 13)); } diff --git a/kmymoney/plugins/csvimport/tests/csvdate-test.h b/kmymoney/plugins/csvimport/tests/csvdate-test.h index 733983b57..1d4401ad7 100644 --- a/kmymoney/plugins/csvimport/tests/csvdate-test.h +++ b/kmymoney/plugins/csvimport/tests/csvdate-test.h @@ -1,41 +1,41 @@ /*************************************************************************** csvdatetest.h ------------------- begin : Sat Jan 01 2010 copyright : (C) 2010 by Allan Anderson email : agander93@gmail.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. * * * ***************************************************************************/ #ifndef CSVDATETEST_H #define CSVDATETEST_H -#include +#include class ConvertDate; class CsvDateTest : public QObject { Q_OBJECT private slots: void init(); void cleanup(); /** * This method is used to test a series of valid and invalid dates, * including alpha month names, and different field separators. */ void testConvertDate(); private: ConvertDate* m_convert; }; #endif diff --git a/kmymoney/plugins/csvimport/tests/csvimporter-test.cpp b/kmymoney/plugins/csvimport/tests/csvimporter-test.cpp index fa8d91444..528722435 100644 --- a/kmymoney/plugins/csvimport/tests/csvimporter-test.cpp +++ b/kmymoney/plugins/csvimport/tests/csvimporter-test.cpp @@ -1,331 +1,331 @@ /*************************************************************************** csvimporter-test.cpp ------------------- copyright : (C) 2017 by Łukasz Wojniłowicz email : lukasz.wojnilowicz@gmail.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 "csvimporter-test.h" -#include +#include #include #include "mymoneyfile.h" #include "mymoneyaccount.h" #include #include "csvimporttestcommon.h" QTEST_GUILESS_MAIN(CsvImporterTest) void CsvImporterTest::initTestCase() { // setup the MyMoneyMoney locale settings according to the KDE settings MyMoneyMoney::setThousandSeparator(QLocale().groupSeparator()); MyMoneyMoney::setDecimalSeparator(QLocale().decimalPoint()); } void CsvImporterTest::init() { storage = new MyMoneySeqAccessMgr; file = MyMoneyFile::instance(); file->attachStorage(storage); csvImporter = new CSVImporter; csvImporter->m_mapSymbolName.insert("STK1", "Stock 1"); csvImporter->m_mapSymbolName.insert("STK2", "Stock 2"); csvImporter->m_mapSymbolName.insert("STK3", "Stock 3"); investmentProfile = new InvestmentProfile ("investment", 106, 1, 0, DateFormat::YearMonthDay, FieldDelimiter::Semicolon, TextDelimiter::DoubleQuote, DecimalSymbol::Dot, QMap {{Column::Date, 0}, {Column::Name, 1}, {Column::Type, 2}, {Column::Quantity, 3}, {Column::Price, 4}, {Column::Amount, 5}}, 2, QMap { {MyMoneyStatement::Transaction::eaBuy, QStringList {"buy"}}, {MyMoneyStatement::Transaction::eaSell, QStringList {"sell"}}} ); pricesProfile = new PricesProfile ("price source", 106, 1, 0, DateFormat::YearMonthDay, FieldDelimiter::Comma, TextDelimiter::DoubleQuote, DecimalSymbol::Dot, QMap{{Column::Date, 0}, {Column::Price, 4}}, 2, Profile::StockPrices); amountProfile = new BankingProfile ("amount", 106, 1, 0, DateFormat::MonthDayYear, FieldDelimiter::Comma, TextDelimiter::DoubleQuote, DecimalSymbol::Dot, QMap{{Column::Date, 1}, {Column::Memo, 2}, {Column::Amount, 3}, {Column::Category, 4}}, false); debitCreditProfile = new BankingProfile ("debit credit", 106, 1, 0, DateFormat::MonthDayYear, FieldDelimiter::Comma, TextDelimiter::DoubleQuote, DecimalSymbol::Dot, QMap{{Column::Date, 1}, {Column::Memo, 2}, {Column::Debit, 3}, {Column::Credit, 4}, {Column::Category, 5}}, false); } void CsvImporterTest::cleanup() { delete investmentProfile; delete pricesProfile; delete amountProfile; delete csvImporter; file->detachStorage(storage); delete storage; } void CsvImporterTest::testBasicPriceTable() { QString csvContent; csvContent += QLatin1String("Date,Open,High,Low,Close,Volume\n"); csvContent += QLatin1String("2017-08-01,1.23,2.34,3.45,4.56,2\n"); csvContent += QLatin1String("2017-08-02,5.67,6.78,7.89,9.10,2\n"); csvContent += QLatin1String("2017-08-03,2.23,3.34,4.45,5.56,2\n"); QString filename("basic-price-table.csv"); writeStatementToCSV(csvContent, filename); pricesProfile->m_securityName = QLatin1String("APPLE"); auto st = csvImporter->unattendedImport(filename, pricesProfile); QVERIFY(st.m_eType == MyMoneyStatement::etNone); QVERIFY(st.m_listPrices.count() == 3); QVERIFY(st.m_listPrices[2].m_date == QDate(2017, 8, 3)); QCOMPARE(st.m_listPrices[2].m_amount.toString(), MyMoneyMoney(5.56).toString()); QVERIFY(st.m_listPrices[2].m_sourceName == "price source"); QVERIFY(st.m_listPrices[2].m_strSecurity == pricesProfile->m_securityName); } void CsvImporterTest::testPriceFractionSetting() { QString csvContent; csvContent += QLatin1String("Date;Open;High;Low;Close;Volume\n"); csvContent += QLatin1String(";;;;;\n"); csvContent += QLatin1String("8/1/2017;1,234;2,345;3,456;4,567;2\n"); csvContent += QLatin1String("8/2/2017;5,679;6,789;7,891;9,101;2\n"); csvContent += QLatin1String("8/3/2017;2,234;3,345;4,456;5,567;2\n"); csvContent += QLatin1String("8/4/2017;3,456;4,567;5,678;6,789;2\n"); QString filename("price-fraction-setting.csv"); writeStatementToCSV(csvContent, filename); pricesProfile->m_securityName = QLatin1String("APPLE"); pricesProfile->m_dateFormat = DateFormat::MonthDayYear; pricesProfile->m_fieldDelimiter = FieldDelimiter::Semicolon; pricesProfile->m_decimalSymbol = DecimalSymbol::Comma; pricesProfile->m_priceFraction = 1; // price *= 0.1 pricesProfile->m_startLine = 2; pricesProfile->m_trailerLines = 1; auto st = csvImporter->unattendedImport(filename, pricesProfile); QVERIFY(st.m_listPrices.count() == 3); QVERIFY(st.m_listPrices[2].m_date == QDate(2017, 8, 3)); QVERIFY(st.m_listPrices[2].m_amount == MyMoneyMoney(0.5567, 10000)); // user reported that visible price (5.567) should be treated as a fraction of real price (0.5567) } void CsvImporterTest::testImportByDebitCredit() { QString csvContent; csvContent += QLatin1String("\"Trans Date\",\"Post Date\",\"Description\",\"Debit\",\"Credit\",\"Category\"\n"); csvContent += QLatin1String("05/16/2016,05/17/2016,FOO1,1.234,0.00,BAR\n"); // debit is intentionally positive here csvContent += QLatin1String("06/17/2016,06/18/2016,FOO2,0,90.12,BAR\n"); csvContent += QLatin1String("07/18/2016,07/19/2016,FOO3,-910.12,,BAR\n"); csvContent += QLatin1String("08/19/2016,08/20/2016,FOO4,,,BAR\n"); csvContent += QLatin1String("09/20/2016,09/21/2016,FOO5,0,0,BAR\n"); QString filename("import-by-debit-credit.csv"); writeStatementToCSV(csvContent, filename); auto st = csvImporter->unattendedImport(filename, debitCreditProfile); QVERIFY(st.m_listTransactions.count() == 5); QVERIFY(st.m_listTransactions[0].m_amount == MyMoneyMoney(-1.234, 1000)); QVERIFY(st.m_listTransactions[0].m_listSplits.count() == 1); QVERIFY(st.m_listTransactions[0].m_listSplits.first().m_amount == MyMoneyMoney(1.234, 1000)); QVERIFY(st.m_listTransactions[1].m_amount == MyMoneyMoney(90.12)); QVERIFY(st.m_listTransactions[2].m_amount == MyMoneyMoney(-910.12)); QVERIFY(st.m_listTransactions[3].m_amount == MyMoneyMoney()); QVERIFY(st.m_listTransactions[4].m_amount == MyMoneyMoney()); } void CsvImporterTest::testImportByAmount() { QString csvContent; csvContent += QLatin1String("\"Trans Date\",\"Post Date\",\"Description\",\"Amount\",\"Category\"\n"); csvContent += QLatin1String("05/16/2016,05/17/2016,FOO1,1.234,BAR\n"); csvContent += QLatin1String("06/17/2016,06/18/2016,FOO2,56.78,BAR\n"); csvContent += QLatin1String("07/18/2016,07/19/2016,FOO3,910.12,BAR\n"); QString filename("import-by-amount.csv"); writeStatementToCSV(csvContent, filename); auto st = csvImporter->unattendedImport(filename, amountProfile); QVERIFY(st.m_listTransactions.count() == 3); QVERIFY(st.m_listTransactions[1].m_datePosted == QDate(2016, 6, 18)); QVERIFY(st.m_listTransactions[1].m_strMemo == "FOO2"); QVERIFY(st.m_listTransactions[1].m_listSplits.count() == 1); QVERIFY(st.m_listTransactions[1].m_listSplits.first().m_strCategoryName == "BAR"); QVERIFY(st.m_listTransactions[1].m_listSplits.first().m_amount == MyMoneyMoney(-56.78)); QVERIFY(st.m_listTransactions[1].m_amount == MyMoneyMoney(56.78)); } void CsvImporterTest::testImportByName() { auto stockNames = csvImporter->m_mapSymbolName.values(); auto stockSymbols = csvImporter->m_mapSymbolName.keys(); auto csvContent = csvDataset(0); QString filename("import-by-name.csv"); writeStatementToCSV(csvContent, filename); auto st = csvImporter->unattendedImport(filename, investmentProfile); QVERIFY(st.m_eType == MyMoneyStatement::etInvestment); QVERIFY(st.m_listSecurities.count() == 3); QVERIFY(st.m_listSecurities[0].m_strName == stockNames.at(0)); QVERIFY(st.m_listSecurities[0].m_strSymbol == stockSymbols.at(0)); QVERIFY(st.m_listTransactions.count() == 3); QVERIFY(st.m_listTransactions[0].m_datePosted == QDate(2017, 8, 1)); QVERIFY(st.m_listTransactions[0].m_amount == MyMoneyMoney(-125)); // KMM handled correctly positive amount in buy transaction QVERIFY(st.m_listTransactions[0].m_shares == MyMoneyMoney(100)); QVERIFY(st.m_listTransactions[0].m_strSecurity == stockNames.at(0)); QVERIFY(st.m_listTransactions[0].m_strSymbol == stockSymbols.at(0)); } void CsvImporterTest::testImportBySymbol() { auto stockNames = csvImporter->m_mapSymbolName.values(); auto stockSymbols = csvImporter->m_mapSymbolName.keys(); auto csvContent = csvDataset(0); for (auto i = 0; i < stockNames.count(); ++i) csvContent.replace(stockNames.at(i), stockSymbols.at(i)); csvContent.replace("Name", "Symbol"); QString filename("import-by-symbol.csv"); writeStatementToCSV(csvContent, filename); investmentProfile->m_colTypeNum.remove(Column::Name); investmentProfile->m_colNumType.remove(1); investmentProfile->m_colTypeNum.insert(Column::Symbol, 1); investmentProfile->m_colNumType.insert(1, Column::Symbol); auto st = csvImporter->unattendedImport(filename, investmentProfile); QVERIFY(st.m_listSecurities.count() == 3); QVERIFY(st.m_listTransactions.count() == 3); QVERIFY(st.m_listTransactions[0].m_strSecurity == stockNames.at(0)); QVERIFY(st.m_listTransactions[0].m_strSymbol == stockSymbols.at(0)); } void CsvImporterTest::testFeeColumn() { auto csvContent = csvDataset(0); QString filename("fee-column.csv"); writeStatementToCSV(csvContent, filename); investmentProfile->m_colTypeNum.insert(Column::Fee, 6); investmentProfile->m_colNumType.insert(6, Column::Fee); auto st = csvImporter->unattendedImport(filename, investmentProfile); QVERIFY(st.m_listTransactions[0].m_amount == MyMoneyMoney(-129)); // new_amount = original_amount + fee QVERIFY(st.m_listTransactions[0].m_fees == MyMoneyMoney(4)); // fee taken literally QVERIFY(st.m_listTransactions[1].m_amount == MyMoneyMoney(450)); QVERIFY(st.m_listTransactions[1].m_fees == MyMoneyMoney(6)); investmentProfile->m_feeIsPercentage = true; st = csvImporter->unattendedImport(filename, investmentProfile); QVERIFY(st.m_listTransactions[0].m_amount == MyMoneyMoney(-130)); // new_amount = original_amount (1 + fee/100) QVERIFY(st.m_listTransactions[0].m_fees == MyMoneyMoney(5)); // new_fee = original_amount * fee/100 } void CsvImporterTest::testAutoDecimalSymbol() { auto csvContent = csvDataset(0); csvContent += QLatin1String("2017-08-04-12.02.10;Stock 1;sell;101;1.25;126,25;4\n"); // mixed decimal symbols are on purpose here QString filename("auto-decimal-symbol.csv"); writeStatementToCSV(csvContent, filename); investmentProfile->m_decimalSymbol = DecimalSymbol::Auto; auto st = csvImporter->unattendedImport(filename, investmentProfile); QVERIFY(st.m_listTransactions.count() == 4); QVERIFY(st.m_listTransactions[3].m_datePosted == QDate(2017, 8, 4)); QVERIFY(st.m_listTransactions[3].m_amount == MyMoneyMoney(126.25)); QVERIFY(st.m_listTransactions[3].m_shares == MyMoneyMoney(101)); } void CsvImporterTest::testInvAccountAutodetection() { MyMoneyFileTransaction ft; makeAccount("Eas", "123", eMyMoney::Account::Investment, QDate(2017, 8, 1), file->asset().id()); makeAccount("BigInvestments", "", eMyMoney::Account::Investment, QDate(2017, 8, 1), file->asset().id()); makeAccount("BigInvestments", "1234567890", eMyMoney::Account::Investment, QDate(2017, 8, 1), file->asset().id()); makeAccount("EasyAccount", "", eMyMoney::Account::Investment, QDate(2017, 8, 1), file->asset().id()); auto toBeClosedAccID = makeAccount("EasyAccount", "123456789", eMyMoney::Account::Investment, QDate(2017, 8, 1), file->asset().id()); // this account has the most characters matching the statement auto accID = makeAccount("Easy", "123456789", eMyMoney::Account::Investment, QDate(2017, 8, 1), file->asset().id()); makeAccount("EasyAccount", "123456789", eMyMoney::Account::Checkings, QDate(2017, 8, 1), file->asset().id()); ft.commit(); auto csvContent = csvDataset(0); csvContent.prepend("Bank name:;\n"); csvContent.prepend("BigInvestments;\n"); csvContent.prepend("Account number:;\n"); csvContent.prepend("123456789;\n"); csvContent.prepend("Account name:;\n"); csvContent.prepend("EasyAccount;\n"); QString filename("account-autodetection.csv"); writeStatementToCSV(csvContent, filename); investmentProfile->m_startLine = 7; csvImporter->m_autodetect[AutoAccountInvest] = true; auto st = csvImporter->unattendedImport(filename, investmentProfile); QVERIFY(st.m_listTransactions.count() == 3); QVERIFY(st.m_accountId == toBeClosedAccID); // closed account shouldn't be autodetected auto closedAcc = file->account(toBeClosedAccID); ft.restart(); closedAcc.setClosed(true); file->modifyAccount(closedAcc); ft.commit(); st = csvImporter->unattendedImport(filename, investmentProfile); QVERIFY(st.m_accountId == accID); } void CsvImporterTest::testCalculatedFeeColumn() { auto csvContent = csvDataset(0); QString filename("calculated-fee-column.csv"); writeStatementToCSV(csvContent, filename); investmentProfile->m_feeRate = QLatin1String("4"); investmentProfile->m_feeIsPercentage = true; // fee is calculated always as percentage auto st = csvImporter->unattendedImport(filename, investmentProfile); QVERIFY(st.m_listTransactions[0].m_amount == MyMoneyMoney(-130)); QVERIFY(st.m_listTransactions[0].m_fees == MyMoneyMoney(5)); investmentProfile->m_minFee = QLatin1String("6"); investmentProfile->m_colTypeNum.remove(Column::Fee); // hack st = csvImporter->unattendedImport(filename, investmentProfile); QVERIFY(st.m_listTransactions[0].m_amount == MyMoneyMoney(-131)); QVERIFY(st.m_listTransactions[0].m_fees == MyMoneyMoney(6)); // minimal fee is 6 now, so fee of 5 from above test must be increased to 6 } diff --git a/kmymoney/plugins/csvimport/tests/csvimporter-test.h b/kmymoney/plugins/csvimport/tests/csvimporter-test.h index 329140cb1..e2ba51092 100644 --- a/kmymoney/plugins/csvimport/tests/csvimporter-test.h +++ b/kmymoney/plugins/csvimport/tests/csvimporter-test.h @@ -1,55 +1,55 @@ /*************************************************************************** csvimporter-test.h ------------------- copyright : (C) 2017 by Łukasz Wojniłowicz email : lukasz.wojnilowicz@gmail.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. * * * ***************************************************************************/ #ifndef CSVIMPORTERTEST_H #define CSVIMPORTERTEST_H -#include +#include class CSVImporter; class BankingProfile; class PricesProfile; class InvestmentProfile; class MyMoneyFile; class MyMoneySeqAccessMgr; class CsvImporterTest : public QObject { Q_OBJECT CSVImporter *csvImporter; BankingProfile *debitCreditProfile; BankingProfile *amountProfile; PricesProfile *pricesProfile; InvestmentProfile *investmentProfile; MyMoneyFile *file; MyMoneySeqAccessMgr *storage; private slots: void initTestCase(); void init(); void cleanup(); void testBasicPriceTable(); void testPriceFractionSetting(); void testImportByDebitCredit(); void testImportByAmount(); void testImportByName(); void testImportBySymbol(); void testFeeColumn(); void testAutoDecimalSymbol(); void testInvAccountAutodetection(); void testCalculatedFeeColumn(); }; #endif diff --git a/kmymoney/plugins/csvimport/tests/parsedata-test.cpp b/kmymoney/plugins/csvimport/tests/parsedata-test.cpp index 17e7f7092..ab0e3be80 100644 --- a/kmymoney/plugins/csvimport/tests/parsedata-test.cpp +++ b/kmymoney/plugins/csvimport/tests/parsedata-test.cpp @@ -1,87 +1,87 @@ /*************************************************************************** parsedatatest.cpp ------------------- begin : Sat Jan 01 2010 copyright : (C) 2010 by Allan Anderson email : agander93@gmail.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 "parsedata-test.h" -#include -#include +#include +#include #include "../csvutil.h" QTEST_GUILESS_MAIN(ParseDataTest); ParseDataTest::ParseDataTest() { } void ParseDataTest::init() { m_parse = new Parse; } void ParseDataTest::cleanup() { delete m_parse; } void ParseDataTest::parseSplitString() { QVector delimiters {FieldDelimiter::Comma, FieldDelimiter::Semicolon, FieldDelimiter::Colon, FieldDelimiter::Tab}; foreach (const auto delimiter, delimiters) { // All four delimiters should produce same result m_parse->setFieldDelimiter(delimiter); QString input = "abc,defgh,";// When this string is QString::split(), two strings // ....will result if ',' is the field delimiter. // This is not good. input.prepend('"'); // make input string quoted input.append('"'); QStringList expected; expected << "abc,defgh,"; QVERIFY(m_parse->parseLine(input) == expected); // if parseLine() detects the condition, } // ...it rebuilds the string } void ParseDataTest::parse_data() { } void ParseDataTest::cleanupTestCase() { } void ParseDataTest::testConstructor() { } void ParseDataTest::testConstructor_data() { } void ParseDataTest::testDefaultConstructor() { } void ParseDataTest::testDefaultConstructor_data() { } void ParseDataTest::initTestCase() { } void ParseDataTest::initTestCase_data() { } diff --git a/kmymoney/plugins/csvimport/tests/parsedata-test.h b/kmymoney/plugins/csvimport/tests/parsedata-test.h index 565fc3963..75888bad8 100644 --- a/kmymoney/plugins/csvimport/tests/parsedata-test.h +++ b/kmymoney/plugins/csvimport/tests/parsedata-test.h @@ -1,56 +1,56 @@ /*************************************************************************** parsedatatest.h ------------------ begin : Sat Jan 01 2010 copyright : (C) 2010 by Allan Anderson email : agander93@gmail.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. * * * ***************************************************************************/ #ifndef PARSEDATATEST_H #define PARSEDATATEST_H #include "../csvutil.h" -#include +#include class Parse; class ParseDataTest : public QObject { Q_OBJECT public: ParseDataTest(); Parse* m_parse; private slots: void init(); void cleanup(); void cleanupTestCase(); void testDefaultConstructor(); void testDefaultConstructor_data(); void testConstructor(); void testConstructor_data(); void initTestCase(); void initTestCase_data(); /** * This method is used to test that a quoted string containing * a comma, which would get split by QString::split() when comma * is the field separator, is detected and rebuilt. If the field * separator is not a comma, the split does not occur. */ void parseSplitString(); void parse_data(); }; #endif diff --git a/kmymoney/plugins/csvimport/tests/symbol-test.cpp b/kmymoney/plugins/csvimport/tests/symbol-test.cpp index bec28a85f..52a16de4a 100644 --- a/kmymoney/plugins/csvimport/tests/symbol-test.cpp +++ b/kmymoney/plugins/csvimport/tests/symbol-test.cpp @@ -1,166 +1,166 @@ /*************************************************************************** symboltest.cpp ------------------- begin : Sat Jan 01 2010 copyright : (C) 2010 by Allan Anderson email : agander93@gmail.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 "symbol-test.h" #include "../csvutil.h" -#include -#include +#include +#include #include QTEST_GUILESS_MAIN(SymbolTest); Parse* m_parse; SymbolTest::SymbolTest() { } void SymbolTest::init() { m_parse = new Parse; m_parse->setDecimalSymbol(DecimalSymbol::Dot); m_localeDecimal = QLocale().decimalPoint(); m_localeThousands = QLocale().groupSeparator(); } void SymbolTest::cleanup() { delete m_parse; } void SymbolTest::testDecimalSymbolDot() { // Detect '.' as decimal and replace from locale m_parse->setDecimalSymbol(DecimalSymbol::Dot); // "." QFETCH(QString, input); QFETCH(QString, result); QVERIFY(m_parse->possiblyReplaceSymbol(input) == result); } void SymbolTest::testDecimalSymbolComma() { // Detect ',' as decimal and replace from locale m_parse->setDecimalSymbol(DecimalSymbol::Comma); // "," QFETCH(QString, input); QFETCH(QString, result); QCOMPARE(m_parse->possiblyReplaceSymbol(input), result); } void SymbolTest::testDecimalSymbolInvalid() { // Check for ',' as decimal, and none present m_parse->setDecimalSymbol(DecimalSymbol::Comma); // "," m_testDecimal = m_parse->decimalSymbol(DecimalSymbol::Comma); QFETCH(QString, input); QFETCH(QString, result); QString res = m_parse->possiblyReplaceSymbol(input); QVERIFY(m_parse->invalidConversion() == true); } void SymbolTest::testDecimalSymbolDot_data() { QTest::addColumn ("input"); QTest::addColumn ("result"); // Detect '.' as decimal and replace from locale QTest::newRow("test 1") << "1234.56" << QString("1234" + m_localeDecimal + "56"); // Check for '.' as decimal, and none present QTest::newRow("test 2") << "145" << QString("145" + m_localeDecimal + "00"); // Detect '.' as decimal and replace from locale, // with thousands separator present QTest::newRow("test 3") << "-123,456.78" << QString("-123456" + m_localeDecimal + "78"); // Detect '.' as decimal and replace from locale // and thousands separator present QTest::newRow("test 4") << "123,456.78" << QString("123456" + m_localeDecimal + "78"); // Detect '.' as decimal and replace from locale // and thousands separator present QTest::newRow("test 5") << "987,654.32" << QString("987654" + m_localeDecimal + "32"); } void SymbolTest::testDecimalSymbolComma_data() { QTest::addColumn ("input"); QTest::addColumn ("result"); // Detect ',' as decimal and replace from locale QTest::newRow("test 1") << "$987,654" << QString("$987" + m_localeDecimal + "654"); // Detect ',' as decimal and replace from locale // with thousands separator present QTest::newRow("test 2") << "-123.456,78" << QString("-123456" + m_localeDecimal + "78"); QTest::newRow("test 3") << "145" << QString("145" + m_localeDecimal + "00"); // Check for ',' as decimal QTest::newRow("test 4") << "123.456" << QString("123456" + m_localeDecimal + "00"); } void SymbolTest::testDecimalSymbolInvalid_data() { QTest::addColumn ("input"); QTest::addColumn ("result"); // Check for ',' as decimal, and none present QTest::newRow("test 1") << "1234.56" << "invalid"; // Detect ',' as decimal and replace from locale // with thousands separator present QTest::newRow("test 2") << "987,654.32" << "invalid"; } void SymbolTest::cleanupTestCase() { } void SymbolTest::testConstructor() { } void SymbolTest::testConstructor_data() { } void SymbolTest::testDefaultConstructor() { } void SymbolTest::testDefaultConstructor_data() { } void SymbolTest::initTestCase() { } void SymbolTest::initTestCase_data() { } diff --git a/kmymoney/plugins/csvimport/tests/symbol-test.h b/kmymoney/plugins/csvimport/tests/symbol-test.h index 8b2e40a5f..29434bad0 100644 --- a/kmymoney/plugins/csvimport/tests/symbol-test.h +++ b/kmymoney/plugins/csvimport/tests/symbol-test.h @@ -1,68 +1,68 @@ /*************************************************************************** symboltest.h ------------------ begin : Sat Jan 01 2010 copyright : (C) 2010 by Allan Anderson email : agander93@gmail.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. * * * ***************************************************************************/ #ifndef SYMBOLTEST_H #define SYMBOLTEST_H #include "../csvutil.h" -#include +#include class Parse; class SymbolTest : public QObject { Q_OBJECT public: SymbolTest(); Parse* m_parse; QStringList m_input; QStringList m_expected; private: QString m_localeDecimal; QString m_testDecimal; QString m_localeThousands; private slots: void init(); void cleanup(); void cleanupTestCase(); void testDefaultConstructor(); void testDefaultConstructor_data(); void testConstructor(); void testConstructor_data(); void initTestCase(); void initTestCase_data(); /** * There are three sub-tests in this class, for checking various * data strings, using both the dot '.' and the comma ',' as * decimal symbols, plus a format that should produce an invalid * conversion. */ void testDecimalSymbolDot(); void testDecimalSymbolDot_data(); void testDecimalSymbolComma(); void testDecimalSymbolComma_data(); void testDecimalSymbolInvalid(); void testDecimalSymbolInvalid_data(); }; #endif diff --git a/kmymoney/plugins/kbanking/aqbankingkmmoperators.h b/kmymoney/plugins/kbanking/aqbankingkmmoperators.h index e8943bfb5..070975b14 100644 --- a/kmymoney/plugins/kbanking/aqbankingkmmoperators.h +++ b/kmymoney/plugins/kbanking/aqbankingkmmoperators.h @@ -1,93 +1,93 @@ /* * This file is part of KMyMoney, A Personal Finance Manager by KDE * Copyright (C) 2013-2015 Christian Dávid * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /** * @file Helper functions for using aqbanking with KMyMoney * * These functions are similar to the ones in aqbanking. They are meant as glue between aqbanking and KMyMoney. * */ #ifndef AQBANKINGKMMOPERATORS_H #define AQBANKINGKMMOPERATORS_H -#include +#include #include "onlinetasks/interfaces/tasks/ionlinetasksettings.h" #include "onlinetasks/sepa/tasks/sepaonlinetransfer.h" struct AB_ACCOUNT; struct AB_TRANSACTION_LIMITS; struct AB_TRANSACTION; struct AB_VALUE; namespace payeeIdentifiers { class ibanBic; class nationalAccount; } /** * @brief AB_TransactionLimits_toSepaOnlineTaskSettings * @param aqlimits IN */ QSharedPointer AB_TransactionLimits_toSepaOnlineTaskSettings(const AB_TRANSACTION_LIMITS* aqlimits); /** * @brief AB_Transaction_SetRemoteAccount * @param transaction * @param ident */ void AB_Transaction_SetRemoteAccount(AB_TRANSACTION* transaction, const payeeIdentifiers::ibanBic& ident); void AB_Transaction_SetRemoteAccount(AB_TRANSACTION* transaction, const payeeIdentifiers::nationalAccount& ident); /** * @brief Set local account of transaction by aqBanking account ptr */ void AB_Transaction_SetLocalAccount(AB_TRANSACTION* transaction, const AB_ACCOUNT* account); /** * @brief AB_Transaction_SetLocalAccount * @param transaction * @param ident */ void AB_Transaction_SetLocalAccount(AB_TRANSACTION* transaction, const payeeIdentifiers::nationalAccount& ident); /** * @brief Set local account of transaction from list * * Will check if an element of accountNumbers is valid and if it is payeeIdentifiers::ibanBic or payeeIdentifiers::natinalAccount. * If such a payeeIdentifier is found, it is set as local account for @c transaction * * @return true if a valid payeeIdentifiers::natinalAccount was set */ bool AB_Transaction_SetLocalAccount(AB_TRANSACTION* transaction, const QList& accountNumbers); /** * @brief Create AB_VALUE from MyMoneyMoney * * @return caller gains ownership */ AB_VALUE* AB_Value_fromMyMoneyMoney(const MyMoneyMoney& input); /** * @brief Convert AB_VALUE to MyMoneyMoney */ MyMoneyMoney AB_Value_toMyMoneyMoney(const AB_VALUE *const value); #endif // AQBANKINGKMMOPERATORS_H diff --git a/kmymoney/plugins/kbanking/gwenhywfarqtoperators.cpp b/kmymoney/plugins/kbanking/gwenhywfarqtoperators.cpp index e26165eee..3e7057e64 100644 --- a/kmymoney/plugins/kbanking/gwenhywfarqtoperators.cpp +++ b/kmymoney/plugins/kbanking/gwenhywfarqtoperators.cpp @@ -1,39 +1,39 @@ /* * This file is part of KMyMoney, A Personal Finance Manager by KDE * Copyright (C) 2013-2015 Christian Dávid * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "gwenhywfarqtoperators.h" -#include -#include +#include +#include GWEN_STRINGLIST* GWEN_StringList_fromQStringList(const QStringList& input) { GWEN_STRINGLIST *ret = GWEN_StringList_new(); QString line; foreach (line, input) { GWEN_StringList_AppendString(ret, line.toUtf8().constData(), false, false); } return ret; } GWEN_STRINGLIST* GWEN_StringList_fromQString(const QString& input) { GWEN_STRINGLIST *ret = GWEN_StringList_new(); GWEN_StringList_AppendString(ret, input.toUtf8().constData(), false, false); return ret; } diff --git a/kmymoney/plugins/kbanking/gwenkdegui.cpp b/kmymoney/plugins/kbanking/gwenkdegui.cpp index 1121f3ddd..f1352ea34 100644 --- a/kmymoney/plugins/kbanking/gwenkdegui.cpp +++ b/kmymoney/plugins/kbanking/gwenkdegui.cpp @@ -1,83 +1,83 @@ /* * A gwenhywfar gui for aqbanking using KDE widgets * Copyright 2014 - 2016 Christian David * * 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) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include "gwenkdegui.h" -#include -#include -#include +#include +#include +#include #include #include #include "widgets/chiptandialog.h" gwenKdeGui::gwenKdeGui() : QT5_Gui() { } gwenKdeGui::~gwenKdeGui() { } int gwenKdeGui::getPassword(uint32_t flags, const char* token, const char* title, const char* text, char* buffer, int minLen, int maxLen, uint32_t guiid) { if ((flags & GWEN_GUI_INPUT_FLAGS_OPTICAL) && text && *text) { // Optical Tan (chipTan) // Extract text to display and hhd code QString infoText = QString::fromUtf8(text); QRegExp hhdRegExp = QRegExp("^(.*)\\$OBEGIN\\$(.*)\\$OEND\\$(.*)$", Qt::CaseInsensitive); hhdRegExp.setMinimal(true); hhdRegExp.indexIn(infoText); QStringList captured = hhdRegExp.capturedTexts(); QString hhdCode = captured.at(2); infoText = captured.at(1) + captured.at(3); //! @todo: Memory leak? QPointer dialog = new chipTanDialog(getParentWidget()); dialog->setInfoText(infoText); dialog->setHhdCode(hhdCode); dialog->setTanLimits(minLen, maxLen); const int rv = dialog->exec(); if (rv == chipTanDialog::Rejected) return GWEN_ERROR_USER_ABORTED; else if (rv == chipTanDialog::InternalError || dialog.isNull()) return GWEN_ERROR_INTERNAL; QString tan = dialog->tan(); if (tan.length() >= minLen && tan.length() <= maxLen) { strncpy(buffer, tan.toUtf8().constData() , tan.length()); buffer[tan.length()] = 0; return 0; } qDebug("Received Tan with incorrect length by ui."); return GWEN_ERROR_INTERNAL; } return QT5_Gui::getPassword(flags, token, title, text, buffer, minLen, maxLen, guiid); } diff --git a/kmymoney/plugins/kbanking/widgets/kbaccountlist.cpp b/kmymoney/plugins/kbanking/widgets/kbaccountlist.cpp index 88a63f255..ea09398b2 100644 --- a/kmymoney/plugins/kbanking/widgets/kbaccountlist.cpp +++ b/kmymoney/plugins/kbanking/widgets/kbaccountlist.cpp @@ -1,197 +1,197 @@ /*************************************************************************** begin : Mon Mar 01 2004 copyright : (C) 2004 by Martin Preuss email : martin@libchipcard.de *************************************************************************** * * * 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. * * * ***************************************************************************/ #ifdef HAVE_CONFIG_H # include #endif #include "kbaccountlist.h" #include -#include +#include #include KBAccountListViewItem::KBAccountListViewItem(KBAccountListView *parent, AB_ACCOUNT *acc) : QTreeWidgetItem(parent) , _account(acc) { assert(acc); _populate(); } KBAccountListViewItem::KBAccountListViewItem(const KBAccountListViewItem &item) : QTreeWidgetItem(item) , _account(0) { if (item._account) { _account = item._account; } } KBAccountListViewItem::KBAccountListViewItem(KBAccountListView *parent, QTreeWidgetItem *after, AB_ACCOUNT *acc) : QTreeWidgetItem(parent, after) , _account(acc) { assert(acc); _populate(); } KBAccountListViewItem::~KBAccountListViewItem() { } AB_ACCOUNT *KBAccountListViewItem::getAccount() { return _account; } void KBAccountListViewItem::_populate() { QString tmp; int i; assert(_account); i = 0; // unique id setText(i++, QString::number(AB_Account_GetUniqueId(_account))); // bank code setText(i++, QString::fromUtf8(AB_Account_GetBankCode(_account))); // bank name tmp = AB_Account_GetBankName(_account); if (tmp.isEmpty()) tmp = i18nc("replacement for institution or account w/o name", "(unnamed)"); setText(i++, tmp); // account id setText(i++, QString::fromUtf8(AB_Account_GetAccountNumber(_account))); // account name tmp = QString::fromUtf8(AB_Account_GetAccountName(_account)); if (tmp.isEmpty()) tmp = i18nc("replacement for institution or account w/o name", "(unnamed)"); setText(i++, tmp); tmp = QString::fromUtf8(AB_Account_GetOwnerName(_account)); if (tmp.isEmpty()) tmp = ""; setText(i++, tmp); tmp = QString::fromUtf8(AB_Provider_GetName(AB_Account_GetProvider(_account))); if (tmp.isEmpty()) tmp = i18nc("replacement for institution or account w/o name", "(unnamed)"); setText(i++, tmp); } bool KBAccountListViewItem::operator< (const QTreeWidgetItem & other) const { bool ok1, ok2; int column = treeWidget() ? treeWidget()->sortColumn() : 0; int a = text(column).toInt(&ok1); int b = other.text(column).toInt(&ok2); if (ok1 && ok2) return a < b; return QTreeWidgetItem::operator<(other); } KBAccountListView::KBAccountListView(QWidget *parent) : QTreeWidget(parent) { setAllColumnsShowFocus(true); setColumnCount(7); QStringList header; header << i18nc("Header for AqBanking account list", "Id"); header << i18nc("Header for AqBanking account list", "Institution Code"); header << i18nc("Header for AqBanking account list", "Institution Name"); header << i18nc("Header for AqBanking account list", "Account Number"); header << i18nc("Header for AqBanking account list", "Account Name"); header << i18nc("Header for AqBanking account list", "Owner"); header << i18nc("Header for AqBanking account list", "Backend"); setHeaderLabels(header); setSortingEnabled(true); sortItems(0, Qt::AscendingOrder); } KBAccountListView::~KBAccountListView() { } void KBAccountListView::addAccount(AB_ACCOUNT *acc) { new KBAccountListViewItem(this, acc); } void KBAccountListView::addAccounts(const std::list &accs) { std::list::const_iterator it; for (it = accs.begin(); it != accs.end(); ++it) { new KBAccountListViewItem(this, *it); } /* for */ } AB_ACCOUNT *KBAccountListView::getCurrentAccount() { KBAccountListViewItem *entry; entry = dynamic_cast(currentItem()); if (!entry) { return 0; } return entry->getAccount(); } std::list KBAccountListView::getSelectedAccounts() { std::list accs; KBAccountListViewItem *entry; // Create an iterator and give the listview as argument QTreeWidgetItemIterator it(this); // iterate through all items of the listview for (; *it; ++it) { if ((*it)->isSelected()) { entry = dynamic_cast(*it); if (entry) accs.push_back(entry->getAccount()); } } // for return accs; } std::list KBAccountListView::getSortedAccounts() { std::list accs; KBAccountListViewItem *entry; // Create an iterator and give the listview as argument QTreeWidgetItemIterator it(this); // iterate through all items of the listview for (; *it; ++it) { entry = dynamic_cast(*it); if (entry) accs.push_back(entry->getAccount()); } // for return accs; } diff --git a/kmymoney/plugins/onlinetasks/interfaces/tasks/ionlinetasksettings.h b/kmymoney/plugins/onlinetasks/interfaces/tasks/ionlinetasksettings.h index fbd278186..ddb9f22bb 100644 --- a/kmymoney/plugins/onlinetasks/interfaces/tasks/ionlinetasksettings.h +++ b/kmymoney/plugins/onlinetasks/interfaces/tasks/ionlinetasksettings.h @@ -1,57 +1,57 @@ /* * This file is part of KMyMoney, A Personal Finance Manager by KDE * Copyright (C) 2014 Christian Dávid * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef IONLINETASKSETTINGS_H #define IONLINETASKSETTINGS_H -#include +#include /** * @brief Account/plugin dependent settings for an onlineTask * * Many onlineTasks settings vary due to multiple reasons. E.g. * a credit transfer could have a maximum amount it can transfer at * once. But this amount could depend on the account and the user's * contract with the bank. * * Therefor onlineTasks can offer thier own set of configurations. There * is no predifined behavior, only subclass onlineTask::settings. * Of course onlinePlugins and widgets which support that task * need to know how to handle that specific settings. * * Using @ref onlineJobAdministration::taskSettings() KMyMoney will * request the correct onlinePlugin to create the settings and return * them as shared pointer. Please note that KMyMoney will try to reuse * that pointer if possible, so do not edit it. */ class IonlineTaskSettings { public: typedef QSharedPointer ptr; /** * Ensure this class to be polymorph * Make gcc happy and prevent a warning */ virtual ~IonlineTaskSettings() {} }; Q_DECLARE_INTERFACE(IonlineTaskSettings, "org.kmymoney.onlinetask.settings") #endif // IONLINETASKSETTINGS_H diff --git a/kmymoney/plugins/printcheck/kcm_printcheck.cpp b/kmymoney/plugins/printcheck/kcm_printcheck.cpp index 17e5631af..fe0b02c4c 100644 --- a/kmymoney/plugins/printcheck/kcm_printcheck.cpp +++ b/kmymoney/plugins/printcheck/kcm_printcheck.cpp @@ -1,97 +1,97 @@ /*************************************************************************** * Copyright 2009 Cristian Onet onet.cristian@gmail.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) version 3 or any later version * * accepted by the membership of KDE e.V. (or its successor approved * * by the membership of KDE e.V.), which shall act as a proxy * * defined in Section 14 of version 3 of the license. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see * ***************************************************************************/ #include "kcm_printcheck.h" #include // Qt includes #include #ifdef ENABLE_WEBENGINE #include #else -#include +#include #endif // KDE includes #include #include #include "pluginsettings.h" PluginSettingsWidget::PluginSettingsWidget(QWidget* parent) : QWidget(parent) { setupUi(this); #ifdef ENABLE_WEBENGINE m_checkTemplatePreviewHTMLPart = new QWebEngineView(m_previewFrame); #else m_checkTemplatePreviewHTMLPart = new KWebView(m_previewFrame); #endif QVBoxLayout *layout = new QVBoxLayout; m_previewFrame->setLayout(layout); layout->addWidget(m_checkTemplatePreviewHTMLPart); connect(kcfg_checkTemplateFile, SIGNAL(urlSelected(QUrl)), this, SLOT(urlSelected(QUrl))); connect(kcfg_checkTemplateFile, SIGNAL(returnPressed(QString)), this, SLOT(returnPressed(QString))); } void PluginSettingsWidget::urlSelected(const QUrl &url) { if (!url.isEmpty()) m_checkTemplatePreviewHTMLPart->load(url); } void PluginSettingsWidget::returnPressed(const QString& url) { if (!url.isEmpty()) m_checkTemplatePreviewHTMLPart->load(QUrl::fromUserInput(url)); } K_PLUGIN_FACTORY_WITH_JSON(KCMPrintCheckFactory, "kcm_kmm_printcheck.json", registerPlugin();) KCMPrintCheck::KCMPrintCheck(QWidget *parent, const QVariantList& args) : KCModule(parent, args) { KAboutData *about = new KAboutData(QStringLiteral("kmm_printcheck"), i18n("KMyMoney print check"), QStringLiteral(VERSION), QString(), KAboutLicense::GPL, i18n("Copyright 2009" ) ); about->addAuthor( QString::fromUtf8("Cristian Oneț") ); setAboutData( about ); PluginSettingsWidget* w = new PluginSettingsWidget(this); addConfig(PluginSettings::self(), w); QVBoxLayout *layout = new QVBoxLayout; setLayout(layout); layout->addWidget(w); load(); w->urlSelected(QUrl::fromUserInput(PluginSettings::checkTemplateFile())); } KCMPrintCheck::~KCMPrintCheck() { } #include "kcm_printcheck.moc" diff --git a/kmymoney/plugins/printcheck/printcheck.cpp b/kmymoney/plugins/printcheck/printcheck.cpp index 6b8587d2a..3def970a3 100644 --- a/kmymoney/plugins/printcheck/printcheck.cpp +++ b/kmymoney/plugins/printcheck/printcheck.cpp @@ -1,239 +1,239 @@ /*************************************************************************** * Copyright 2009 Cristian Onet onet.cristian@gmail.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) version 3 or any later version * * accepted by the membership of KDE e.V. (or its successor approved * * by the membership of KDE e.V.), which shall act as a proxy * * defined in Section 14 of version 3 of the license. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see * ***************************************************************************/ #include "printcheck.h" #include // QT includes #include #include #include #ifdef ENABLE_WEBENGINE #include #else -#include +#include #endif -#include -#include +#include +#include // KDE includes #include #include #include #include // KMyMoney includes #include "mymoneyfile.h" #include "mymoneyaccount.h" #include "mymoneyinstitution.h" #include "mymoneymoney.h" #include "mymoneypayee.h" #include "mymoneysecurity.h" #include "mymoneysplit.h" #include "mymoneytransaction.h" #include "mymoneyutils.h" #include "viewinterface.h" #include "selectedtransactions.h" #include "numbertowords.h" #include "pluginsettings.h" struct KMMPrintCheckPlugin::Private { QAction* m_action; QString m_checkTemplateHTML; QStringList m_printedTransactionIdList; KMyMoneyRegister::SelectedTransactions m_transactions; }; KMMPrintCheckPlugin::KMMPrintCheckPlugin() : KMyMoneyPlugin::Plugin(nullptr, "Print check"/*must be the same as X-KDE-PluginInfo-Name*/) { // Tell the host application to load my GUI component setComponentName("kmm_printcheck", i18n("Print check")); setXMLFile("kmm_printcheck.rc"); // For ease announce that we have been loaded. qDebug("KMyMoney printcheck plugin loaded"); d = std::unique_ptr(new Private); // Create the actions of this plugin QString actionName = i18n("Print check"); d->m_action = actionCollection()->addAction("transaction_printcheck", this, SLOT(slotPrintCheck())); d->m_action->setText(actionName); // wait until a transaction is selected before enableing the action d->m_action->setEnabled(false); d->m_printedTransactionIdList = PluginSettings::printedChecks(); readCheckTemplate(); //! @todo Christian: Replace #if 0 connect(KMyMoneyPlugin::PluginLoader::instance(), SIGNAL(plug(KPluginInfo*)), this, SLOT(slotPlug(KPluginInfo*))); connect(KMyMoneyPlugin::PluginLoader::instance(), SIGNAL(configChanged(Plugin*)), this, SLOT(slotUpdateConfig())); #endif } /** * @internal Destructor is needed because destructor call of unique_ptr must be in this compile unit */ KMMPrintCheckPlugin::~KMMPrintCheckPlugin() { } void KMMPrintCheckPlugin::readCheckTemplate() { QString checkTemplateHTMLPath = QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kmm_printcheck/check_template.html"); if (PluginSettings::checkTemplateFile().isEmpty()) { PluginSettings::setCheckTemplateFile(checkTemplateHTMLPath); PluginSettings::self()->save(); } QFile checkTemplateHTMLFile(PluginSettings::checkTemplateFile()); checkTemplateHTMLFile.open(QIODevice::ReadOnly); QTextStream stream(&checkTemplateHTMLFile); d->m_checkTemplateHTML = stream.readAll(); checkTemplateHTMLFile.close(); } bool KMMPrintCheckPlugin::canBePrinted(const KMyMoneyRegister::SelectedTransaction & selectedTransaction) const { MyMoneyFile* file = MyMoneyFile::instance(); bool isACheck = file->account(selectedTransaction.split().accountId()).accountType() == eMyMoney::Account::Checkings && selectedTransaction.split().shares().isNegative(); return isACheck && d->m_printedTransactionIdList.contains(selectedTransaction.transaction().id()) == 0; } void KMMPrintCheckPlugin::markAsPrinted(const KMyMoneyRegister::SelectedTransaction & selectedTransaction) { d->m_printedTransactionIdList.append(selectedTransaction.transaction().id()); } void KMMPrintCheckPlugin::slotPrintCheck() { MyMoneyFile* file = MyMoneyFile::instance(); MyMoneyMoneyToWordsConverter converter; #ifdef ENABLE_WEBENGINE auto htmlPart = new QWebEngineView(); #else auto htmlPart = new KWebView(); #endif KMyMoneyRegister::SelectedTransactions::const_iterator it; for (it = d->m_transactions.constBegin(); it != d->m_transactions.constEnd(); ++it) { if (!canBePrinted(*it)) continue; // skip this check since it was already printed QString checkHTML = d->m_checkTemplateHTML; const MyMoneyAccount account = file->account((*it).split().accountId()); const MyMoneySecurity currency = file->currency(account.currencyId()); const MyMoneyInstitution institution = file->institution(file->account((*it).split().accountId()).institutionId()); // replace the predefined tokens // data about the user checkHTML.replace("$OWNER_NAME", file->user().name()); checkHTML.replace("$OWNER_ADDRESS", file->user().address()); checkHTML.replace("$OWNER_CITY", file->user().city()); checkHTML.replace("$OWNER_STATE", file->user().state()); // data about the account institution checkHTML.replace("$INSTITUTION_NAME", institution.name()); checkHTML.replace("$INSTITUTION_STREET", institution.street()); checkHTML.replace("$INSTITUTION_TELEPHONE", institution.telephone()); checkHTML.replace("$INSTITUTION_TOWN", institution.town()); checkHTML.replace("$INSTITUTION_CITY", institution.city()); checkHTML.replace("$INSTITUTION_POSTCODE", institution.postcode()); checkHTML.replace("$INSTITUTION_MANAGER", institution.manager()); // data about the transaction checkHTML.replace("$DATE", QLocale().toString((*it).transaction().postDate(), QLocale::ShortFormat)); checkHTML.replace("$CHECK_NUMBER", (*it).split().number()); checkHTML.replace("$PAYEE_NAME", file->payee((*it).split().payeeId()).name()); checkHTML.replace("$PAYEE_ADDRESS", file->payee((*it).split().payeeId()).address()); checkHTML.replace("$PAYEE_CITY", file->payee((*it).split().payeeId()).city()); checkHTML.replace("$PAYEE_POSTCODE", file->payee((*it).split().payeeId()).postcode()); checkHTML.replace("$PAYEE_STATE", file->payee((*it).split().payeeId()).state()); checkHTML.replace("$AMOUNT_STRING", converter.convert((*it).split().shares().abs(), currency.smallestAccountFraction())); checkHTML.replace("$AMOUNT_DECIMAL", MyMoneyUtils::formatMoney((*it).split().shares().abs(), currency)); checkHTML.replace("$MEMO", (*it).split().memo()); // print the check htmlPart->setHtml(checkHTML, QUrl("file://")); m_currentPrinter = new QPrinter(); QPointer dialog = new QPrintDialog(m_currentPrinter); dialog->setWindowTitle(QString()); if (dialog->exec() != QDialog::Accepted) { delete m_currentPrinter; m_currentPrinter = nullptr; continue; } else { #ifdef ENABLE_WEBENGINE htmlPart->page()->print(m_currentPrinter, [=] (bool) {delete m_currentPrinter; m_currentPrinter = nullptr;}); #else htmlPart->print(m_currentPrinter); #endif } delete dialog; // mark the transaction as printed markAsPrinted(*it); } PluginSettings::setPrintedChecks(d->m_printedTransactionIdList); delete htmlPart; } void KMMPrintCheckPlugin::slotTransactionsSelected(const KMyMoneyRegister::SelectedTransactions& transactions) { d->m_transactions = transactions; bool actionEnabled = false; // enable/disable the action depending if there are transactions selected or not // and whether they can be printed or not KMyMoneyRegister::SelectedTransactions::const_iterator it; for (it = d->m_transactions.constBegin(); it != d->m_transactions.constEnd(); ++it) { if (canBePrinted(*it)) { actionEnabled = true; break; } } d->m_action->setEnabled(actionEnabled); } // the plugin loader plugs in a plugin void KMMPrintCheckPlugin::slotPlug(KPluginInfo *info) { if (info->name() == objectName()) { connect(viewInterface(), SIGNAL(transactionsSelected(KMyMoneyRegister::SelectedTransactions)), this, SLOT(slotTransactionsSelected(KMyMoneyRegister::SelectedTransactions))); } } // the plugin's configurations has changed void KMMPrintCheckPlugin::slotUpdateConfig() { PluginSettings::self()->load(); // re-read the data because the configuration has changed readCheckTemplate(); d->m_printedTransactionIdList = PluginSettings::printedChecks(); } diff --git a/kmymoney/plugins/reconciliationreport/kreconciliationreportdlg.cpp b/kmymoney/plugins/reconciliationreport/kreconciliationreportdlg.cpp index eda656953..4cce137d9 100644 --- a/kmymoney/plugins/reconciliationreport/kreconciliationreportdlg.cpp +++ b/kmymoney/plugins/reconciliationreport/kreconciliationreportdlg.cpp @@ -1,97 +1,97 @@ /*************************************************************************** * Copyright 2009 Cristian Onet onet.cristian@gmail.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) version 3 or any later version * * accepted by the membership of KDE e.V. (or its successor approved * * by the membership of KDE e.V.), which shall act as a proxy * * defined in Section 14 of version 3 of the license. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see * ***************************************************************************/ #include "kreconciliationreportdlg.h" // Qt includes #include #include #include -#include +#include // KDE includes #include #ifdef ENABLE_WEBENGINE -#include +#include #else -#include +#include #endif KReportDlg::KReportDlg(QWidget* parent, const QString& summaryReportHTML, const QString& detailsReportHTML) : QDialog(parent) { setupUi(this); #ifdef ENABLE_WEBENGINE m_summaryHTMLPart = new QWebEngineView(m_summaryTab); m_detailsHTMLPart = new QWebEngineView(m_detailsTab); #else m_summaryHTMLPart = new KWebView(m_summaryTab); m_detailsHTMLPart = new KWebView(m_detailsTab); #endif m_summaryLayout->addWidget(m_summaryHTMLPart); m_detailsLayout->addWidget(m_detailsHTMLPart); m_summaryHTMLPart->setHtml(summaryReportHTML, QUrl("file://")); m_detailsHTMLPart->setHtml(detailsReportHTML, QUrl("file://")); QPushButton* printButton = m_buttonBox->addButton(QString(), QDialogButtonBox::ActionRole); KGuiItem::assign(printButton, KStandardGuiItem::print()); // signals and slots connections connect(printButton, SIGNAL(clicked()), this, SLOT(print())); } KReportDlg::~KReportDlg() { } void KReportDlg::print() { m_currentPrinter = new QPrinter(); QPrintDialog *dialog = new QPrintDialog(m_currentPrinter, this); dialog->setWindowTitle(QString()); if (dialog->exec() != QDialog::Accepted) { delete m_currentPrinter; m_currentPrinter = nullptr; return; } // do the actual painting job switch (m_tabWidget->currentIndex()) { case 0: #ifdef ENABLE_WEBENGINE m_summaryHTMLPart->page()->print(m_currentPrinter, [=] (bool) {delete m_currentPrinter; m_currentPrinter = nullptr;}); #else m_summaryHTMLPart->print(m_currentPrinter); #endif break; case 1: #ifdef ENABLE_WEBENGINE m_detailsHTMLPart->page()->print(m_currentPrinter, [=] (bool) {delete m_currentPrinter; m_currentPrinter = nullptr;}); #else m_detailsHTMLPart->print(m_currentPrinter); #endif break; default: delete m_currentPrinter; m_currentPrinter = nullptr; qDebug("KReportDlg::print() current page index not handled correctly"); } } diff --git a/kmymoney/plugins/sqlcipher/qsqlcipherdriverplugin.h b/kmymoney/plugins/sqlcipher/qsqlcipherdriverplugin.h index 1006116d3..b2a6899cd 100644 --- a/kmymoney/plugins/sqlcipher/qsqlcipherdriverplugin.h +++ b/kmymoney/plugins/sqlcipher/qsqlcipherdriverplugin.h @@ -1,52 +1,52 @@ /* * QSqlDriver for SQLCipher * Copyright 2014 Christian David * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef QSQLCIPHERDRIVERPLUGIN_H #define QSQLCIPHERDRIVERPLUGIN_H -#include -#include +#include +#include #ifdef QT_PLUGIN #define Q_EXPORT_SQLDRIVER_SQLCIPHER #else #define Q_EXPORT_SQLDRIVER_SQLCIPHER Q_SQL_EXPORT #endif QT_BEGIN_NAMESPACE class Q_EXPORT_SQLDRIVER_SQLCIPHER QSqlcipherDriverPlugin : public QSqlDriverPlugin { Q_OBJECT public: virtual QSqlDriver* create(const QString&); virtual QStringList keys() const; }; QT_END_NAMESPACE #endif // QSQLCIPHERDRIVERPLUGIN_H diff --git a/kmymoney/plugins/sqlcipher/sqlcipherdriver.h b/kmymoney/plugins/sqlcipher/sqlcipherdriver.h index 1e25739de..eed244057 100644 --- a/kmymoney/plugins/sqlcipher/sqlcipherdriver.h +++ b/kmymoney/plugins/sqlcipher/sqlcipherdriver.h @@ -1,40 +1,40 @@ /* * QSqlDriver for SQLCipher * Copyright 2014 Christian David * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef SQLCIPHERDRIVER_H #define SQLCIPHERDRIVER_H -#include +#include // krazy:exclude=includes class SQLCipherDriver : public QSQLiteDriver { Q_OBJECT public: virtual bool open(const QString& db, const QString& user, const QString& password, const QString& host, int port, const QString& connOpts); }; #endif // SQLCIPHERDRIVER_H diff --git a/kmymoney/reports/tests/kreportsview-test.h b/kmymoney/reports/tests/kreportsview-test.h index 50fe2909b..cf62365a2 100644 --- a/kmymoney/reports/tests/kreportsview-test.h +++ b/kmymoney/reports/tests/kreportsview-test.h @@ -1,63 +1,63 @@ /*************************************************************************** mymoneyaccounttest.h ------------------- copyright : (C) 2002 by Thomas Baumgart email : ipwizard@users.sourceforge.net Ace Jones ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef KREPORTSVIEWTEST_H #define KREPORTSVIEWTEST_H -#include +#include #include "mymoneyfile.h" #include "mymoneyseqaccessmgr.h" class KReportsViewTest : public QObject { Q_OBJECT private: MyMoneyAccount *m; MyMoneySeqAccessMgr* storage; MyMoneyFile* file; private slots: void init(); void cleanup(); void testNetWorthSingle(); void testNetWorthOfsetting(); void testNetWorthOpeningPrior(); void testNetWorthDateFilter(); void testSpendingEmpty(); void testSingleTransaction(); void testSubAccount(); void testFilterIEvsIE(); void testFilterALvsAL(); void testFilterALvsIE(); void testFilterAllvsIE(); void testFilterBasics(); void testMultipleCurrencies(); void testAdvancedFilter(); void testColumnType(); void testXMLWrite(); void testQueryBasics(); void testCashFlowAnalysis(); void testAccountQuery(); void testInvestment(); void testWebQuotes(); void testDateFormat(); void testHasReferenceTo(); }; #endif diff --git a/kmymoney/reports/tests/pivotgrid-test.cpp b/kmymoney/reports/tests/pivotgrid-test.cpp index 7cec99e1c..25a2cabe5 100644 --- a/kmymoney/reports/tests/pivotgrid-test.cpp +++ b/kmymoney/reports/tests/pivotgrid-test.cpp @@ -1,173 +1,173 @@ /*************************************************************************** pivotgridtest.cpp ------------------- copyright : (C) 2002-2005 by Thomas Baumgart email : ipwizard@users.sourceforge.net Ace Jones ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "pivotgrid-test.h" -#include +#include #include "reportstestcommon.h" #include "pivotgrid.h" #include "mymoneyinstitution.h" #include "mymoneysecurity.h" using namespace reports; using namespace test; QTEST_GUILESS_MAIN(PivotGridTest) void PivotGridTest::init() { storage = new MyMoneySeqAccessMgr; file = MyMoneyFile::instance(); file->attachStorage(storage); MyMoneyFileTransaction ft; file->addCurrency(MyMoneySecurity("CAD", "Canadian Dollar", "C$")); file->addCurrency(MyMoneySecurity("USD", "US Dollar", "$")); file->addCurrency(MyMoneySecurity("JPY", "Japanese Yen", QChar(0x00A5), 1)); file->addCurrency(MyMoneySecurity("GBP", "British Pound", "#")); file->setBaseCurrency(file->currency("USD")); MyMoneyPayee payeeTest("Test Payee"); file->addPayee(payeeTest); MyMoneyPayee payeeTest2("Thomas Baumgart"); file->addPayee(payeeTest2); acAsset = (MyMoneyFile::instance()->asset().id()); acLiability = (MyMoneyFile::instance()->liability().id()); acExpense = (MyMoneyFile::instance()->expense().id()); acIncome = (MyMoneyFile::instance()->income().id()); acChecking = makeAccount(QString("Checking Account"), eMyMoney::Account::Checkings, moCheckingOpen, QDate(2004, 5, 15), acAsset); acCredit = makeAccount(QString("Credit Card"), eMyMoney::Account::CreditCard, moCreditOpen, QDate(2004, 7, 15), acLiability); acSolo = makeAccount(QString("Solo"), eMyMoney::Account::Expense, MyMoneyMoney(), QDate(2004, 1, 11), acExpense); acParent = makeAccount(QString("Parent"), eMyMoney::Account::Expense, MyMoneyMoney(), QDate(2004, 1, 11), acExpense); acChild = makeAccount(QString("Child"), eMyMoney::Account::Expense, MyMoneyMoney(), QDate(2004, 2, 11), acParent); acForeign = makeAccount(QString("Foreign"), eMyMoney::Account::Expense, MyMoneyMoney(), QDate(2004, 1, 11), acExpense); acSecondChild = makeAccount(QString("Second Child"), eMyMoney::Account::Expense, MyMoneyMoney(), QDate(2004, 2, 11), acParent); acGrandChild1 = makeAccount(QString("Grand Child 1"), eMyMoney::Account::Expense, MyMoneyMoney(), QDate(2004, 2, 11), acChild); acGrandChild2 = makeAccount(QString("Grand Child 2"), eMyMoney::Account::Expense, MyMoneyMoney(), QDate(2004, 2, 11), acChild); MyMoneyInstitution i("Bank of the World", "", "", "", "", "", ""); file->addInstitution(i); inBank = i.id(); ft.commit(); } void PivotGridTest::cleanup() { file->detachStorage(storage); delete storage; } void PivotGridTest::testCellAddValue() { PivotCell a; QVERIFY(a == MyMoneyMoney()); QVERIFY(a.m_stockSplit == MyMoneyMoney::ONE); QVERIFY(a.m_postSplit == MyMoneyMoney()); QVERIFY(a.formatMoney("", 2) == MyMoneyMoney().formatMoney("", 2)); PivotCell b(MyMoneyMoney(13, 10)); QVERIFY(b == MyMoneyMoney(13, 10)); QVERIFY(b.m_stockSplit == MyMoneyMoney::ONE); QVERIFY(b.m_postSplit == MyMoneyMoney()); QVERIFY(b.formatMoney("", 2) == MyMoneyMoney(13, 10).formatMoney("", 2)); PivotCell s(b); QVERIFY(s == MyMoneyMoney(13, 10)); QVERIFY(s.m_stockSplit == MyMoneyMoney::ONE); QVERIFY(s.m_postSplit == MyMoneyMoney()); QVERIFY(s.formatMoney("", 2) == MyMoneyMoney(13, 10).formatMoney("", 2)); s = PivotCell::stockSplit(MyMoneyMoney(1, 2)); QVERIFY(s == MyMoneyMoney()); QVERIFY(s.m_stockSplit == MyMoneyMoney(1, 2)); QVERIFY(s.m_postSplit == MyMoneyMoney()); QVERIFY(s.formatMoney("", 2) == MyMoneyMoney().formatMoney("", 2)); a += MyMoneyMoney::ONE; a += MyMoneyMoney(2, 1); QVERIFY(a == MyMoneyMoney(3, 1)); QVERIFY(a.m_stockSplit == MyMoneyMoney::ONE); QVERIFY(a.m_postSplit == MyMoneyMoney()); QVERIFY(a.formatMoney("", 2) == MyMoneyMoney(3, 1).formatMoney("", 2)); a += s; QVERIFY(a == MyMoneyMoney(3, 1)); QVERIFY(a.m_stockSplit == MyMoneyMoney(1, 2)); QVERIFY(a.m_postSplit == MyMoneyMoney()); QVERIFY(a.formatMoney("", 2) == MyMoneyMoney(15, 10).formatMoney("", 2)); a += MyMoneyMoney(3, 1); a += MyMoneyMoney(3, 1); QVERIFY(a == MyMoneyMoney(3, 1)); QVERIFY(a.m_stockSplit == MyMoneyMoney(1, 2)); QVERIFY(a.m_postSplit == MyMoneyMoney(6, 1)); QVERIFY(a.formatMoney("", 2) == MyMoneyMoney(75, 10).formatMoney("", 2)); } void PivotGridTest::testCellAddCell() { PivotCell a, b; a += MyMoneyMoney(3, 1); a += PivotCell::stockSplit(MyMoneyMoney(2, 1)); a += MyMoneyMoney(4, 1); QVERIFY(a == MyMoneyMoney(3, 1)); QVERIFY(a.m_stockSplit == MyMoneyMoney(2, 1)); QVERIFY(a.m_postSplit == MyMoneyMoney(4, 1)); QVERIFY(a.formatMoney("", 2) == MyMoneyMoney(10, 1).formatMoney("", 2)); b += MyMoneyMoney(4, 1); b += PivotCell::stockSplit(MyMoneyMoney(4, 1)); b += MyMoneyMoney(16, 1); QVERIFY(b == MyMoneyMoney(4, 1)); QVERIFY(b.m_stockSplit == MyMoneyMoney(4, 1)); QVERIFY(b.m_postSplit == MyMoneyMoney(16, 1)); QVERIFY(b.formatMoney("", 2) == MyMoneyMoney(32, 1).formatMoney("", 2)); a += b; QVERIFY(a == MyMoneyMoney(3, 1)); QVERIFY(a.m_stockSplit == MyMoneyMoney(8, 1)); QVERIFY(a.m_postSplit == MyMoneyMoney(48, 1)); QVERIFY(a.formatMoney("", 2) == MyMoneyMoney(72, 1).formatMoney("", 2)); } void PivotGridTest::testCellRunningSum() { PivotCell a; MyMoneyMoney runningSum(12, 10); a += MyMoneyMoney(3, 1); a += PivotCell::stockSplit(MyMoneyMoney(125, 100)); a += MyMoneyMoney(134, 10); QVERIFY(a.m_stockSplit != MyMoneyMoney::ONE); QVERIFY(a.m_postSplit != MyMoneyMoney()); runningSum = a.calculateRunningSum(runningSum); QVERIFY(runningSum == MyMoneyMoney(1865, 100)); QVERIFY(a.formatMoney("", 2) == MyMoneyMoney(1865, 100).formatMoney("", 2)); QVERIFY(a.m_stockSplit == MyMoneyMoney::ONE); QVERIFY(a.m_postSplit == MyMoneyMoney()); } diff --git a/kmymoney/reports/tests/pivotgrid-test.h b/kmymoney/reports/tests/pivotgrid-test.h index 7ba21bb97..00ad71169 100644 --- a/kmymoney/reports/tests/pivotgrid-test.h +++ b/kmymoney/reports/tests/pivotgrid-test.h @@ -1,53 +1,53 @@ /*************************************************************************** pivotgridtest.h ------------------- copyright : (C) 2002 by Thomas Baumgart email : ipwizard@users.sourceforge.net Ace Jones ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef PIVOTGRIDTEST_H #define PIVOTGRIDTEST_H -#include +#include namespace reports { class PivotGridTest; } #define KMM_MYMONEY_UNIT_TESTABLE friend class reports::PivotGridTest; #include "mymoneyfile.h" #include "mymoneyseqaccessmgr.h" namespace reports { class PivotGridTest : public QObject { Q_OBJECT private: MyMoneySeqAccessMgr* storage; MyMoneyFile* file; private slots: void init(); void cleanup(); void testCellAddValue(); void testCellAddCell(); void testCellRunningSum(); }; } #endif // PIVOTGRIDTEST_H diff --git a/kmymoney/reports/tests/pivottable-test.h b/kmymoney/reports/tests/pivottable-test.h index ff587769d..c027a8f91 100644 --- a/kmymoney/reports/tests/pivottable-test.h +++ b/kmymoney/reports/tests/pivottable-test.h @@ -1,69 +1,69 @@ /*************************************************************************** pivottabletest.h ------------------- copyright : (C) 2002 by Thomas Baumgart email : ipwizard@users.sourceforge.net Ace Jones ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef PIVOTTABLETEST_H #define PIVOTTABLETEST_H -#include +#include namespace reports { class PivotTableTest; } #define KMM_MYMONEY_UNIT_TESTABLE friend class reports::PivotTableTest; #include "mymoneyfile.h" #include "mymoneyseqaccessmgr.h" #include "reporttable.h" namespace reports { class PivotTableTest : public QObject { Q_OBJECT private: MyMoneySeqAccessMgr* storage; MyMoneyFile* file; private slots: void init(); void cleanup(); void testNetWorthSingle(); void testNetWorthOfsetting(); void testNetWorthOpeningPrior(); void testNetWorthDateFilter(); void testNetWorthOpening(); void testSpendingEmpty(); void testSingleTransaction(); void testSubAccount(); void testFilterIEvsIE(); void testFilterALvsAL(); void testFilterALvsIE(); void testFilterAllvsIE(); void testFilterBasics(); void testMultipleCurrencies(); void testAdvancedFilter(); void testColumnType(); void testInvestment(); void testBudget(); void testHtmlEncoding(); }; } #endif // PIVOTTABLETEST_H diff --git a/kmymoney/reports/tests/querytable-test.h b/kmymoney/reports/tests/querytable-test.h index 62034a7f5..91f640515 100644 --- a/kmymoney/reports/tests/querytable-test.h +++ b/kmymoney/reports/tests/querytable-test.h @@ -1,46 +1,46 @@ /*************************************************************************** querytabletest.h ------------------- copyright : (C) 2002 by Thomas Baumgart email : ipwizard@users.sourceforge.net Ace Jones ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef QUERYTABLETEST_H #define QUERYTABLETEST_H -#include +#include #include "mymoneyfile.h" #include "mymoneyseqaccessmgr.h" class QueryTableTest : public QObject { Q_OBJECT private: MyMoneySeqAccessMgr* storage; MyMoneyFile* file; private slots: void init(); void cleanup(); void testQueryBasics(); void testCashFlowAnalysis(); void testAccountQuery(); void testInvestment(); void testSplitShares(); void testConversionRate(); void testBalanceColumn(); void testBalanceColumnWithMultipleCurrencies(); void testTaxReport(); }; #endif diff --git a/kmymoney/tests/kmymoneyutils-test.cpp b/kmymoney/tests/kmymoneyutils-test.cpp index 006de9680..c7151bb4e 100644 --- a/kmymoney/tests/kmymoneyutils-test.cpp +++ b/kmymoney/tests/kmymoneyutils-test.cpp @@ -1,71 +1,71 @@ /* * This file is part of KMyMoney, A Personal Finance Manager by KDE * Copyright (C) 2012 Thomas Baumgart * Copyright (C) 2015 Christian Dávid * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "kmymoneyutils-test.h" #include "mymoneyaccount.h" -#include +#include QTEST_GUILESS_MAIN(KMyMoneyUtilsTest) void KMyMoneyUtilsTest::init() { } void KMyMoneyUtilsTest::cleanup() { } void KMyMoneyUtilsTest::initTestCase() { } void KMyMoneyUtilsTest::testNextCheckNumber() { MyMoneyAccount acc; // make sure first check number is 1 acc.setValue("lastNumberUsed", QString()); QVERIFY(KMyMoneyUtils::nextCheckNumber(acc) == QLatin1String("1")); // a simple increment of a plain value acc.setValue("lastNumberUsed", QLatin1String("123")); QVERIFY(KMyMoneyUtils::nextCheckNumber(acc) == QLatin1String("124")); // a number preceded by text acc.setValue("lastNumberUsed", QLatin1String("No 123")); QVERIFY(KMyMoneyUtils::nextCheckNumber(acc) == QLatin1String("No 124")); // a number followed by text acc.setValue("lastNumberUsed", QLatin1String("123 ABC")); QVERIFY(KMyMoneyUtils::nextCheckNumber(acc) == QLatin1String("124 ABC")); // a number enclosed by text acc.setValue("lastNumberUsed", QLatin1String("No 123 ABC")); QVERIFY(KMyMoneyUtils::nextCheckNumber(acc) == QLatin1String("No 124 ABC")); // a number containig a dash (e.g. invoice number) acc.setValue("lastNumberUsed", QLatin1String("No 123-001 ABC")); QVERIFY(KMyMoneyUtils::nextCheckNumber(acc) == QLatin1String("No 123-002 ABC")); // a number containing a dot (e.g. invoice number) acc.setValue("lastNumberUsed", QLatin1String("2012.001")); QVERIFY(KMyMoneyUtils::nextCheckNumber(acc) == QLatin1String("2012.002")); } diff --git a/kmymoney/tests/kmymoneyutils-test.h b/kmymoney/tests/kmymoneyutils-test.h index 860baffc1..82603e38e 100644 --- a/kmymoney/tests/kmymoneyutils-test.h +++ b/kmymoney/tests/kmymoneyutils-test.h @@ -1,42 +1,42 @@ /* * This file is part of KMyMoney, A Personal Finance Manager by KDE * Copyright (C) 2012 Thomas Baumgart * Copyright (C) 2015 Christian Dávid * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef KMYMONEYUTILSTEST_H #define KMYMONEYUTILSTEST_H -#include +#include #include #define KMM_MYMONEY_UNIT_TESTABLE friend class KMyMoneyUtilsTest; #include "kmymoneyutils.h" class KMyMoneyUtilsTest : public QObject { Q_OBJECT protected: private slots: void initTestCase(); void init(); void cleanup(); void testNextCheckNumber(); }; #endif diff --git a/kmymoney/views/CMakeLists.txt b/kmymoney/views/CMakeLists.txt index 5f98786c9..080b3f150 100644 --- a/kmymoney/views/CMakeLists.txt +++ b/kmymoney/views/CMakeLists.txt @@ -1,97 +1,97 @@ ############# next target (views) STATIC ################### set(libviews_a_SOURCES kaccountsview.cpp kbudgetview.cpp kcategoriesview.cpp kforecastview.cpp kgloballedgerview.cpp ledgerview.cpp kwelcomepage.cpp khomeview.cpp kinstitutionsview.cpp kinvestmentview.cpp kmymoneyfile.cpp kmymoneyview.cpp kmymoneyviewbase.cpp kmymoneyaccountsviewbase.cpp kpayeesview.cpp kreportsview.cpp kscheduledview.cpp tocitem.cpp tocitemgroup.cpp tocitemreport.cpp kscheduletreeitem.cpp ktagsview.cpp konlinejoboutbox.cpp kpayeeidentifierview.cpp payeeidentifierselectiondelegate.cpp simpleledgerview.cpp ledgerviewpage.cpp ledgerview.cpp ledgerdelegate.cpp newspliteditor.cpp newtransactioneditor.cpp newtransactionform.cpp splitdialog.cpp splitdelegate.cpp widgethintframe.cpp kmymoneywebpage.cpp ) set(libviews_a_HEADER kmymoneyview.h) set(libviews_a_UI kaccountsview.ui kbudgetview.ui kcategoriesview.ui kforecastviewdecl.ui kinstitutionsview.ui kinvestmentview.ui kpayeesviewdecl.ui kscheduledviewdecl.ui ktagsview.ui konlinejoboutbox.ui kpayeeidentifierview.ui simpleledgerview.ui ledgerview.ui ledgerviewpage.ui simpleledgerview.ui splitdialog.ui newspliteditor.ui newtransactioneditor.ui newtransactionform.ui ) # The handling of these ui files depends # on libkmymoney.so (the widgets library) ki18n_wrap_ui(libviews_a_SOURCES ${libviews_a_UI}) add_library(views STATIC ${libviews_a_SOURCES}) -target_link_libraries(views PUBLIC KChart KF5::KIOFileWidgets KF5::Notifications KF5::Archive KF5::TextWidgets Qt5::Sql Alkimia::alkimia) +target_link_libraries(views PUBLIC KChart KF5::KIOFileWidgets KF5::Notifications KF5::Archive KF5::TextWidgets Qt5::Sql Qt5::PrintSupport Alkimia::alkimia) if(ENABLE_WEBENGINE) target_link_libraries(views PUBLIC Qt5::WebEngineWidgets) else(ENABLE_WEBENGINE) target_link_libraries(views PUBLIC KF5::WebKit) endif(ENABLE_WEBENGINE) if(KF5Activities_FOUND) target_link_libraries(views PRIVATE KF5::Activities) endif() # TODO: Remove this dependency. But it is needed as long as the payee editor uses these objects directly # This should be replaced by virtual methods in a pure abstract object. target_link_libraries( views PUBLIC payeeidentifier_iban_bic payeeidentifier_nationalAccount kmm_mymoney # needed to load payeeIdentifier ) # we rely on some of the dialogs to be generated add_dependencies(views dialogs newinvestmentwizard newloanwizard endingbalancedlg) ########### install files ############### install(FILES ${libviews_a_HEADER} DESTINATION ${INCLUDE_INSTALL_DIR}/kmymoney COMPONENT Devel) diff --git a/kmymoney/views/khomeview.cpp b/kmymoney/views/khomeview.cpp index 4b48fa58e..8c27ec97d 100644 --- a/kmymoney/views/khomeview.cpp +++ b/kmymoney/views/khomeview.cpp @@ -1,2065 +1,2065 @@ /*************************************************************************** khomeview.cpp - description ------------------- begin : Tue Jan 22 2002 copyright : (C) 2000-2002 by Michael Edwardes Javier Campos Morales Felix Rodriguez John C Thomas Baumgart Kevin Tambascio ***************************************************************************/ /*************************************************************************** * * * 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 "khomeview.h" // ---------------------------------------------------------------------------- // QT Includes #include #include #include #include #include #include #include #include -#include -#include +#include +#include #ifdef ENABLE_WEBENGINE -#include +#include #else -#include +#include #endif // ---------------------------------------------------------------------------- // KDE Includes #include #include #include #include #include #include // ---------------------------------------------------------------------------- // Project Includes #include "mymoneyutils.h" #include "kmymoneyutils.h" #include "kwelcomepage.h" #include "kmymoneyglobalsettings.h" #include "mymoneyfile.h" #include "mymoneyaccount.h" #include "mymoneyprice.h" #include "mymoneyforecast.h" #include "kmymoney.h" #include "kreportchartview.h" #include "pivottable.h" #include "pivotgrid.h" #include "reportaccount.h" #include "mymoneysplit.h" #include "mymoneytransaction.h" #include "icons.h" #include "kmymoneywebpage.h" #include "mymoneyschedule.h" #include "mymoneyenums.h" #define VIEW_LEDGER "ledger" #define VIEW_SCHEDULE "schedule" #define VIEW_WELCOME "welcome" #define VIEW_HOME "home" #define VIEW_REPORTS "reports" using namespace Icons; using namespace eMyMoney; bool accountNameLess(const MyMoneyAccount &acc1, const MyMoneyAccount &acc2) { return acc1.name().localeAwareCompare(acc2.name()) < 0; } using namespace reports; class KHomeView::Private { public: Private() : m_showAllSchedules(false), m_needReload(false), m_needLoad(true), m_netWorthGraphLastValidSize(400, 300) { } /** * daily balances of an account */ typedef QMap dailyBalances; #ifdef ENABLE_WEBENGINE QWebEngineView *m_view; #else KWebView *m_view; #endif QString m_html; bool m_showAllSchedules; bool m_needReload; bool m_needLoad; MyMoneyForecast m_forecast; MyMoneyMoney m_total; /** * Hold the last valid size of the net worth graph * for the times when the needed size can't be computed. */ QSize m_netWorthGraphLastValidSize; /** * daily forecast balance of accounts */ QMap m_accountList; }; /** * @brief Converts a QPixmap to an data URI scheme * * According to RFC 2397 * * @param pixmap Source to convert * @return full data URI */ QString QPixmapToDataUri(const QPixmap& pixmap) { QImage image(pixmap.toImage()); QByteArray byteArray; QBuffer buffer(&byteArray); buffer.open(QIODevice::WriteOnly); image.save(&buffer, "PNG"); // writes the image in PNG format inside the buffer return QLatin1String("data:image/png;base64,") + QString(byteArray.toBase64()); } KHomeView::KHomeView(QWidget *parent) : KMyMoneyViewBase(parent), d(new Private) { } KHomeView::~KHomeView() { // if user wants to remember the font size, store it here if (KMyMoneyGlobalSettings::rememberZoomFactor()) { KMyMoneyGlobalSettings::setZoomFactor(d->m_view->zoomFactor()); KMyMoneyGlobalSettings::self()->save(); } delete d; } void KHomeView::init() { d->m_needLoad = false; auto vbox = new QVBoxLayout(this); setLayout(vbox); vbox->setSpacing(6); vbox->setMargin(0); #ifdef ENABLE_WEBENGINE d->m_view = new QWebEngineView(this); #else d->m_view = new KWebView(this); #endif d->m_view->setPage(new MyQWebEnginePage(d->m_view)); vbox->addWidget(d->m_view); d->m_view->setHtml(KWelcomePage::welcomePage(), QUrl("file://")); #ifdef ENABLE_WEBENGINE connect(d->m_view->page(), &QWebEnginePage::urlChanged, this, &KHomeView::slotOpenUrl); #else d->m_view->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks); connect(d->m_view->page(), &KWebPage::linkClicked, this, &KHomeView::slotOpenUrl); #endif } void KHomeView::wheelEvent(QWheelEvent* event) { // Zoom text on Ctrl + Scroll if (event->modifiers() & Qt::CTRL) { qreal factor = d->m_view->zoomFactor(); if (event->delta() > 0) factor += 0.1; else if (event->delta() < 0) factor -= 0.1; d->m_view->setZoomFactor(factor); event->accept(); return; } } void KHomeView::slotLoadView() { d->m_needReload = true; if (isVisible()) { loadView(); d->m_needReload = false; } } void KHomeView::showEvent(QShowEvent* event) { if (d->m_needLoad) init(); emit aboutToShow(View::Home); if (d->m_needReload) { loadView(); d->m_needReload = false; } QWidget::showEvent(event); } void KHomeView::slotPrintView() { if (d->m_view) { m_currentPrinter = new QPrinter(); QPrintDialog *dialog = new QPrintDialog(m_currentPrinter, this); dialog->setWindowTitle(QString()); if (dialog->exec() != QDialog::Accepted) { delete m_currentPrinter; m_currentPrinter = nullptr; return; } #ifdef ENABLE_WEBENGINE d->m_view->page()->print(m_currentPrinter, [=] (bool) {delete m_currentPrinter; m_currentPrinter = nullptr;}); #else d->m_view->print(m_currentPrinter); #endif } } void KHomeView::loadView() { d->m_view->setZoomFactor(KMyMoneyGlobalSettings::zoomFactor()); QList list; MyMoneyFile::instance()->accountList(list); if (list.count() == 0) { d->m_view->setHtml(KWelcomePage::welcomePage(), QUrl("file://")); } else { //clear the forecast flag so it will be reloaded d->m_forecast.setForecastDone(false); const QString filename = QStandardPaths::locate(QStandardPaths::AppConfigLocation, "html/kmymoney.css"); QString header = QString("\n\n").arg(QUrl::fromLocalFile(filename).url()); header += KMyMoneyUtils::variableCSS(); header += "\n"; QString footer = "\n"; d->m_html.clear(); d->m_html += header; d->m_html += QString("
%1
").arg(i18n("Your Financial Summary")); QStringList settings = KMyMoneyGlobalSettings::itemList(); QStringList::ConstIterator it; for (it = settings.constBegin(); it != settings.constEnd(); ++it) { int option = (*it).toInt(); if (option > 0) { switch (option) { case 1: // payments showPayments(); break; case 2: // preferred accounts showAccounts(Preferred, i18n("Preferred Accounts")); break; case 3: // payment accounts // Check if preferred accounts are shown separately if (settings.contains("2")) { showAccounts(static_cast(Payment | Preferred), i18n("Payment Accounts")); } else { showAccounts(Payment, i18n("Payment Accounts")); } break; case 4: // favorite reports showFavoriteReports(); break; case 5: // forecast showForecast(); break; case 6: // net worth graph over all accounts showNetWorthGraph(); break; case 8: // assets and liabilities showAssetsLiabilities(); break; case 9: // budget showBudget(); break; case 10: // cash flow summary showCashFlowSummary(); break; } d->m_html += "
 
\n"; } } d->m_html += "
"; d->m_html += link(VIEW_WELCOME, QString()) + i18n("Show KMyMoney welcome page") + linkend(); d->m_html += "
"; d->m_html += "
"; d->m_html += footer; d->m_view->setHtml(d->m_html, QUrl("file://")); } } void KHomeView::showNetWorthGraph() { d->m_html += QString("
%1
\n
 
\n").arg(i18n("Net Worth Forecast")); MyMoneyReport reportCfg = MyMoneyReport( MyMoneyReport::eAssetLiability, MyMoneyReport::eMonths, TransactionFilter::Date::UserDefined, // overridden by the setDateFilter() call below MyMoneyReport::eDetailTotal, i18n("Net Worth Forecast"), i18n("Generated Report")); reportCfg.setChartByDefault(true); reportCfg.setChartCHGridLines(false); reportCfg.setChartSVGridLines(false); reportCfg.setChartDataLabels(false); reportCfg.setChartType(MyMoneyReport::eChartLine); reportCfg.setIncludingSchedules(false); reportCfg.addAccountGroup(Account::Asset); reportCfg.addAccountGroup(Account::Liability); reportCfg.setColumnsAreDays(true); reportCfg.setConvertCurrency(true); reportCfg.setIncludingForecast(true); reportCfg.setDateFilter(QDate::currentDate(), QDate::currentDate().addDays(+ 90)); reports::PivotTable table(reportCfg); reports::KReportChartView* chartWidget = new reports::KReportChartView(0); table.drawChart(*chartWidget); // Adjust the size QSize netWorthGraphSize = KHomeView::size(); netWorthGraphSize -= QSize(80, 30); // consider the computed size valid only if it's smaller on both axes that the applications size if (netWorthGraphSize.width() < kmymoney->width() || netWorthGraphSize.height() < kmymoney->height()) { d->m_netWorthGraphLastValidSize = netWorthGraphSize; } chartWidget->resize(d->m_netWorthGraphLastValidSize); //save the chart to an image QString chart = QPixmapToDataUri(QPixmap::grabWidget(chartWidget->coordinatePlane()->parent())); d->m_html += QString(""); d->m_html += QString(""); d->m_html += QString("").arg(chart); d->m_html += QString(""); d->m_html += QString("
\"Networth\"
"); //delete the widget since we no longer need it delete chartWidget; } void KHomeView::showPayments() { MyMoneyFile* file = MyMoneyFile::instance(); QList overdues; QList schedule; int i = 0; //if forecast has not been executed yet, do it. if (!d->m_forecast.isForecastDone()) doForecast(); schedule = file->scheduleList(QString(), Schedule::Type::Any, Schedule::Occurrence::Any, Schedule::PaymentType::Any, QDate::currentDate(), QDate::currentDate().addMonths(1), false); overdues = file->scheduleList(QString(), Schedule::Type::Any, Schedule::Occurrence::Any, Schedule::PaymentType::Any, QDate(), QDate(), true); if (schedule.empty() && overdues.empty()) return; // HACK // Remove the finished schedules QList::Iterator d_it; //regular schedules d_it = schedule.begin(); while (d_it != schedule.end()) { if ((*d_it).isFinished()) { d_it = schedule.erase(d_it); continue; } ++d_it; } //overdue schedules d_it = overdues.begin(); while (d_it != overdues.end()) { if ((*d_it).isFinished()) { d_it = overdues.erase(d_it); continue; } ++d_it; } d->m_html += "
"; d->m_html += QString("
%1
\n").arg(i18n("Payments")); if (!overdues.isEmpty()) { d->m_html += "
 
\n"; qSort(overdues); QList::Iterator it; QList::Iterator it_f; d->m_html += ""; d->m_html += QString("\n").arg(showColoredAmount(i18n("Overdue payments"), true)); d->m_html += ""; d->m_html += ""; d->m_html += ""; d->m_html += ""; d->m_html += ""; d->m_html += ""; d->m_html += ""; for (it = overdues.begin(); it != overdues.end(); ++it) { // determine number of overdue payments int cnt = (*it).transactionsRemainingUntil(QDate::currentDate().addDays(-1)); d->m_html += QString("").arg(i++ & 0x01 ? "even" : "odd"); showPaymentEntry(*it, cnt); d->m_html += ""; } d->m_html += "
%1
"; d->m_html += i18n("Date"); d->m_html += ""; d->m_html += i18n("Schedule"); d->m_html += ""; d->m_html += i18n("Account"); d->m_html += ""; d->m_html += i18n("Amount"); d->m_html += ""; d->m_html += i18n("Balance after"); d->m_html += "
"; } if (!schedule.isEmpty()) { qSort(schedule); // Extract todays payments if any QList todays; QList::Iterator t_it; for (t_it = schedule.begin(); t_it != schedule.end();) { if ((*t_it).adjustedNextDueDate() == QDate::currentDate()) { todays.append(*t_it); (*t_it).setNextDueDate((*t_it).nextPayment(QDate::currentDate())); // if adjustedNextDueDate is still currentDate then remove it from // scheduled payments if ((*t_it).adjustedNextDueDate() == QDate::currentDate()) { t_it = schedule.erase(t_it); continue; } } ++t_it; } if (todays.count() > 0) { d->m_html += "
 
\n"; d->m_html += ""; d->m_html += QString("\n").arg(i18n("Today's due payments")); d->m_html += ""; d->m_html += ""; d->m_html += ""; d->m_html += ""; d->m_html += ""; d->m_html += ""; d->m_html += ""; for (t_it = todays.begin(); t_it != todays.end(); ++t_it) { d->m_html += QString("").arg(i++ & 0x01 ? "even" : "odd"); showPaymentEntry(*t_it); d->m_html += ""; } d->m_html += "
%1
"; d->m_html += i18n("Date"); d->m_html += ""; d->m_html += i18n("Schedule"); d->m_html += ""; d->m_html += i18n("Account"); d->m_html += ""; d->m_html += i18n("Amount"); d->m_html += ""; d->m_html += i18n("Balance after"); d->m_html += "
"; } if (!schedule.isEmpty()) { d->m_html += "
 
\n"; QList::Iterator it; d->m_html += ""; d->m_html += QString("\n").arg(i18n("Future payments")); d->m_html += ""; d->m_html += ""; d->m_html += ""; d->m_html += ""; d->m_html += ""; d->m_html += ""; d->m_html += ""; // show all or the first 6 entries int cnt; cnt = (d->m_showAllSchedules) ? -1 : 6; bool needMoreLess = d->m_showAllSchedules; QDate lastDate = QDate::currentDate().addMonths(1); qSort(schedule); do { it = schedule.begin(); if (it == schedule.end()) break; // if the next due date is invalid (schedule is finished) // we remove it from the list QDate nextDate = (*it).nextDueDate(); if (!nextDate.isValid()) { schedule.erase(it); continue; } if (nextDate > lastDate) break; if (cnt == 0) { needMoreLess = true; break; } // in case we've shown the current recurrence as overdue, // we don't show it here again, but keep the schedule // as it might show up later in the list again if (!(*it).isOverdue()) { if (cnt > 0) --cnt; d->m_html += QString("").arg(i++ & 0x01 ? "even" : "odd"); showPaymentEntry(*it); d->m_html += ""; // for single occurrence we have reported everything so we // better get out of here. if ((*it).occurrence() == Schedule::Occurrence::Once) { schedule.erase(it); continue; } } // if nextPayment returns an invalid date, setNextDueDate will // just skip it, resulting in a loop // we check the resulting date and erase the schedule if invalid if (!((*it).nextPayment((*it).nextDueDate())).isValid()) { schedule.erase(it); continue; } (*it).setNextDueDate((*it).nextPayment((*it).nextDueDate())); qSort(schedule); } while (1); if (needMoreLess) { d->m_html += QString("").arg(i++ & 0x01 ? "even" : "odd"); d->m_html += ""; d->m_html += ""; } d->m_html += "
%1
"; d->m_html += i18n("Date"); d->m_html += ""; d->m_html += i18n("Schedule"); d->m_html += ""; d->m_html += i18n("Account"); d->m_html += ""; d->m_html += i18n("Amount"); d->m_html += ""; d->m_html += i18n("Balance after"); d->m_html += "
"; if (d->m_showAllSchedules) { d->m_html += link(VIEW_SCHEDULE, QString("?mode=%1").arg("reduced")) + i18nc("Less...", "Show fewer schedules on the list") + linkend(); } else { d->m_html += link(VIEW_SCHEDULE, QString("?mode=%1").arg("full")) + i18nc("More...", "Show more schedules on the list") + linkend(); } d->m_html += "
"; } } d->m_html += "
"; } void KHomeView::showPaymentEntry(const MyMoneySchedule& sched, int cnt) { QString tmp; MyMoneyFile* file = MyMoneyFile::instance(); try { MyMoneyAccount acc = sched.account(); if (!acc.id().isEmpty()) { MyMoneyTransaction t = sched.transaction(); // only show the entry, if it is still active if (!sched.isFinished()) { MyMoneySplit sp = t.splitByAccount(acc.id(), true); QString pathEnter = QPixmapToDataUri(QIcon::fromTheme(g_Icons[Icon::KeyEnter]).pixmap(QSize(16,16))); QString pathSkip = QPixmapToDataUri(QIcon::fromTheme(g_Icons[Icon::MediaSkipForward]).pixmap(QSize(16,16))); //show payment date tmp = QString("") + QLocale().toString(sched.adjustedNextDueDate(), QLocale::ShortFormat) + ""; if (!pathEnter.isEmpty()) tmp += link(VIEW_SCHEDULE, QString("?id=%1&mode=enter").arg(sched.id()), i18n("Enter schedule")) + QString("").arg(pathEnter) + linkend(); if (!pathSkip.isEmpty()) tmp += " " + link(VIEW_SCHEDULE, QString("?id=%1&mode=skip").arg(sched.id()), i18n("Skip schedule")) + QString("").arg(pathSkip) + linkend(); tmp += QString(" "); tmp += link(VIEW_SCHEDULE, QString("?id=%1&mode=edit").arg(sched.id()), i18n("Edit schedule")) + sched.name() + linkend(); //show quantity of payments overdue if any if (cnt > 1) tmp += i18np(" (%1 payment)", " (%1 payments)", cnt); //show account of the main split tmp += ""; tmp += QString(file->account(acc.id()).name()); //show amount of the schedule tmp += ""; const MyMoneySecurity& currency = MyMoneyFile::instance()->currency(acc.currencyId()); MyMoneyMoney payment = MyMoneyMoney(sp.value(t.commodity(), acc.currencyId()) * cnt); QString amount = MyMoneyUtils::formatMoney(payment, acc, currency); amount.replace(QChar(' '), " "); tmp += showColoredAmount(amount, payment.isNegative()); tmp += ""; //show balance after payments tmp += ""; QDate paymentDate = QDate(sched.adjustedNextDueDate()); MyMoneyMoney balanceAfter = forecastPaymentBalance(acc, payment, paymentDate); QString balance = MyMoneyUtils::formatMoney(balanceAfter, acc, currency); balance.replace(QChar(' '), " "); tmp += showColoredAmount(balance, balanceAfter.isNegative()); tmp += ""; // qDebug("paymentEntry = '%s'", tmp.toLatin1()); d->m_html += tmp; } } } catch (const MyMoneyException &e) { qDebug("Unable to display schedule entry: %s", qPrintable(e.what())); } } void KHomeView::showAccounts(KHomeView::paymentTypeE type, const QString& header) { MyMoneyFile* file = MyMoneyFile::instance(); int prec = MyMoneyMoney::denomToPrec(file->baseCurrency().smallestAccountFraction()); QList accounts; bool showClosedAccounts = kmymoney->isActionToggled(Action::ViewShowAll); // get list of all accounts file->accountList(accounts); for (QList::Iterator it = accounts.begin(); it != accounts.end();) { bool removeAccount = false; if (!(*it).isClosed() || showClosedAccounts) { switch ((*it).accountType()) { case Account::Expense: case Account::Income: // never show a category account // Note: This might be different in a future version when // the homepage also shows category based information removeAccount = true; break; // Asset and Liability accounts are only shown if they // have the preferred flag set case Account::Asset: case Account::Liability: case Account::Investment: // if preferred accounts are requested, then keep in list if ((*it).value("PreferredAccount") != "Yes" || (type & Preferred) == 0) { removeAccount = true; } break; // Check payment accounts. If payment and preferred is selected, // then always show them. If only payment is selected, then // show only if preferred flag is not set. case Account::Checkings: case Account::Savings: case Account::Cash: case Account::CreditCard: switch (type & (Payment | Preferred)) { case Payment: if ((*it).value("PreferredAccount") == "Yes") removeAccount = true; break; case Preferred: if ((*it).value("PreferredAccount") != "Yes") removeAccount = true; break; case Payment | Preferred: break; default: removeAccount = true; break; } break; // filter all accounts that are not used on homepage views default: removeAccount = true; break; } } else if ((*it).isClosed() || (*it).isInvest()) { // don't show if closed or a stock account removeAccount = true; } if (removeAccount) it = accounts.erase(it); else ++it; } if (!accounts.isEmpty()) { // sort the accounts by name qStableSort(accounts.begin(), accounts.end(), accountNameLess); QString tmp; int i = 0; tmp = "
" + header + "
\n
 
\n"; d->m_html += tmp; d->m_html += ""; d->m_html += ""; if (KMyMoneyGlobalSettings::showBalanceStatusOfOnlineAccounts()) { QString pathStatusHeader = QPixmapToDataUri(QIcon::fromTheme(g_Icons[Icon::Download]).pixmap(QSize(16,16))); d->m_html += QString("").arg(pathStatusHeader); } d->m_html += ""; if (KMyMoneyGlobalSettings::showCountOfUnmarkedTransactions()) d->m_html += QString(""); if (KMyMoneyGlobalSettings::showCountOfClearedTransactions()) d->m_html += QString(""); if (KMyMoneyGlobalSettings::showCountOfNotReconciledTransactions()) d->m_html += QString(""); d->m_html += ""; //only show limit info if user chose to do so if (KMyMoneyGlobalSettings::showLimitInfo()) { d->m_html += ""; } d->m_html += ""; d->m_total = 0; QList::const_iterator it_m; for (it_m = accounts.constBegin(); it_m != accounts.constEnd(); ++it_m) { d->m_html += QString("").arg(i++ & 0x01 ? "even" : "odd"); showAccountEntry(*it_m); d->m_html += ""; } d->m_html += QString("").arg(i++ & 0x01 ? "even" : "odd"); QString amount = d->m_total.formatMoney(file->baseCurrency().tradingSymbol(), prec); if (KMyMoneyGlobalSettings::showBalanceStatusOfOnlineAccounts()) d->m_html += ""; d->m_html += QString("").arg(i18n("Total")); if (KMyMoneyGlobalSettings::showCountOfUnmarkedTransactions()) d->m_html += ""; if (KMyMoneyGlobalSettings::showCountOfClearedTransactions()) d->m_html += ""; if (KMyMoneyGlobalSettings::showCountOfNotReconciledTransactions()) d->m_html += ""; d->m_html += QString("").arg(showColoredAmount(amount, d->m_total.isNegative())); d->m_html += "
"; d->m_html += i18n("Account"); d->m_html += "!MC!R"; d->m_html += i18n("Current Balance"); d->m_html += ""; d->m_html += i18n("To Minimum Balance / Maximum Credit"); d->m_html += "
%1%1
"; } } void KHomeView::showAccountEntry(const MyMoneyAccount& acc) { MyMoneyFile* file = MyMoneyFile::instance(); MyMoneySecurity currency = file->currency(acc.currencyId()); MyMoneyMoney value; bool showLimit = KMyMoneyGlobalSettings::showLimitInfo(); if (acc.accountType() == Account::Investment) { //investment accounts show the balances of all its subaccounts value = investmentBalance(acc); //investment accounts have no minimum balance showAccountEntry(acc, value, MyMoneyMoney(), showLimit); } else { //get balance for normal accounts value = file->balance(acc.id(), QDate::currentDate()); if (acc.currencyId() != file->baseCurrency().id()) { ReportAccount repAcc = ReportAccount(acc.id()); MyMoneyMoney curPrice = repAcc.baseCurrencyPrice(QDate::currentDate()); MyMoneyMoney baseValue = value * curPrice; baseValue = baseValue.convert(file->baseCurrency().smallestAccountFraction()); d->m_total += baseValue; } else { d->m_total += value; } //if credit card or checkings account, show maximum credit if (acc.accountType() == Account::CreditCard || acc.accountType() == Account::Checkings) { QString maximumCredit = acc.value("maxCreditAbsolute"); if (maximumCredit.isEmpty()) { maximumCredit = acc.value("minBalanceAbsolute"); } MyMoneyMoney maxCredit = MyMoneyMoney(maximumCredit); showAccountEntry(acc, value, value - maxCredit, showLimit); } else { //otherwise use minimum balance QString minimumBalance = acc.value("minBalanceAbsolute"); MyMoneyMoney minBalance = MyMoneyMoney(minimumBalance); showAccountEntry(acc, value, value - minBalance, showLimit); } } } void KHomeView::showAccountEntry(const MyMoneyAccount& acc, const MyMoneyMoney& value, const MyMoneyMoney& valueToMinBal, const bool showMinBal) { MyMoneyFile* file = MyMoneyFile::instance(); QString tmp; MyMoneySecurity currency = file->currency(acc.currencyId()); QString amount; QString amountToMinBal; //format amounts amount = MyMoneyUtils::formatMoney(value, acc, currency); amount.replace(QChar(' '), " "); if (showMinBal) { amountToMinBal = MyMoneyUtils::formatMoney(valueToMinBal, acc, currency); amountToMinBal.replace(QChar(' '), " "); } QString cellStatus, cellCounts, pathOK, pathTODO, pathNotOK; if (KMyMoneyGlobalSettings::showBalanceStatusOfOnlineAccounts()) { //show account's online-status pathOK = QPixmapToDataUri(QIcon::fromTheme(g_Icons[Icon::DialogOKApply]).pixmap(QSize(16,16))); pathTODO = QPixmapToDataUri(QIcon::fromTheme(g_Icons[Icon::MailReceive]).pixmap(QSize(16,16))); pathNotOK = QPixmapToDataUri(QIcon::fromTheme(g_Icons[Icon::DialogCancel]).pixmap(QSize(16,16))); if (acc.value("lastImportedTransactionDate").isEmpty() || acc.value("lastStatementBalance").isEmpty()) cellStatus = '-'; else if (file->hasMatchingOnlineBalance(acc)) { if (file->hasNewerTransaction(acc.id(), QDate::fromString(acc.value("lastImportedTransactionDate"), Qt::ISODate))) cellStatus = QString("").arg(pathTODO); else cellStatus = QString("").arg(pathOK); } else cellStatus = QString("").arg(pathNotOK); tmp = QString("%1").arg(cellStatus); } tmp += QString("") + link(VIEW_LEDGER, QString("?id=%1").arg(acc.id())) + acc.name() + linkend() + ""; int countNotMarked = 0, countCleared = 0, countNotReconciled = 0; QString countStr; if (KMyMoneyGlobalSettings::showCountOfUnmarkedTransactions() || KMyMoneyGlobalSettings::showCountOfNotReconciledTransactions()) countNotMarked = file->countTransactionsWithSpecificReconciliationState(acc.id(), TransactionFilter::State::NotReconciled); if (KMyMoneyGlobalSettings::showCountOfClearedTransactions() || KMyMoneyGlobalSettings::showCountOfNotReconciledTransactions()) countCleared = file->countTransactionsWithSpecificReconciliationState(acc.id(), TransactionFilter::State::Cleared); if (KMyMoneyGlobalSettings::showCountOfNotReconciledTransactions()) countNotReconciled = countNotMarked + countCleared; if (KMyMoneyGlobalSettings::showCountOfUnmarkedTransactions()) { if (countNotMarked) countStr = QString("%1").arg(countNotMarked); else countStr = '-'; tmp += QString("%1").arg(countStr); } if (KMyMoneyGlobalSettings::showCountOfClearedTransactions()) { if (countCleared) countStr = QString("%1").arg(countCleared); else countStr = '-'; tmp += QString("%1").arg(countStr); } if (KMyMoneyGlobalSettings::showCountOfNotReconciledTransactions()) { if (countNotReconciled) countStr = QString("%1").arg(countNotReconciled); else countStr = '-'; tmp += QString("%1").arg(countStr); } //show account balance tmp += QString("%1").arg(showColoredAmount(amount, value.isNegative())); //show minimum balance column if requested if (showMinBal) { //if it is an investment, show minimum balance empty if (acc.accountType() == Account::Investment) { tmp += QString(" "); } else { //show minimum balance entry tmp += QString("%1").arg(showColoredAmount(amountToMinBal, valueToMinBal.isNegative())); } } // qDebug("accountEntry = '%s'", tmp.toLatin1()); d->m_html += tmp; } MyMoneyMoney KHomeView::investmentBalance(const MyMoneyAccount& acc) { auto file = MyMoneyFile::instance(); auto value = file->balance(acc.id(), QDate::currentDate()); foreach (const auto accountID, acc.accountList()) { auto stock = file->account(accountID); if (!stock.isClosed()) { try { MyMoneyMoney val; MyMoneyMoney balance = file->balance(stock.id(), QDate::currentDate()); MyMoneySecurity security = file->security(stock.currencyId()); const MyMoneyPrice &price = file->price(stock.currencyId(), security.tradingCurrency()); val = (balance * price.rate(security.tradingCurrency())).convertPrecision(security.pricePrecision()); // adjust value of security to the currency of the account MyMoneySecurity accountCurrency = file->currency(acc.currencyId()); val = val * file->price(security.tradingCurrency(), accountCurrency.id()).rate(accountCurrency.id()); val = val.convert(acc.fraction()); value += val; } catch (const MyMoneyException &e) { qWarning("%s", qPrintable(QString("cannot convert stock balance of %1 to base currency: %2").arg(stock.name(), e.what()))); } } } return value; } void KHomeView::showFavoriteReports() { QList reports = MyMoneyFile::instance()->reportList(); if (!reports.isEmpty()) { bool firstTime = 1; int row = 0; QList::const_iterator it_report = reports.constBegin(); while (it_report != reports.constEnd()) { if ((*it_report).isFavorite()) { if (firstTime) { d->m_html += QString("
%1
\n
 
\n").arg(i18n("Favorite Reports")); d->m_html += ""; d->m_html += ""; firstTime = false; } d->m_html += QString("") .arg(row++ & 0x01 ? "even" : "odd") .arg(link(VIEW_REPORTS, QString("?id=%1").arg((*it_report).id()))) .arg((*it_report).name()) .arg(linkend()) .arg((*it_report).comment()); } ++it_report; } if (!firstTime) d->m_html += "
"; d->m_html += i18n("Report"); d->m_html += ""; d->m_html += i18n("Comment"); d->m_html += "
%2%3%4%5
"; } } void KHomeView::showForecast() { MyMoneyFile* file = MyMoneyFile::instance(); QList accList; //if forecast has not been executed yet, do it. if (!d->m_forecast.isForecastDone()) doForecast(); accList = d->m_forecast.accountList(); if (accList.count() > 0) { // sort the accounts by name qStableSort(accList.begin(), accList.end(), accountNameLess); int i = 0; int colspan = 1; //get begin day int beginDay = QDate::currentDate().daysTo(d->m_forecast.beginForecastDate()); //if begin day is today skip to next cycle if (beginDay == 0) beginDay = d->m_forecast.accountsCycle(); // Now output header d->m_html += QString("
%1
\n
 
\n").arg(i18n("%1 Day Forecast", d->m_forecast.forecastDays())); d->m_html += ""; d->m_html += ""; int colWidth = 55 / (d->m_forecast.forecastDays() / d->m_forecast.accountsCycle()); for (i = 0; (i*d->m_forecast.accountsCycle() + beginDay) <= d->m_forecast.forecastDays(); ++i) { d->m_html += QString(""; colspan++; } d->m_html += ""; // Now output entries i = 0; QList::ConstIterator it_account; for (it_account = accList.constBegin(); it_account != accList.constEnd(); ++it_account) { //MyMoneyAccount acc = (*it_n); d->m_html += QString("").arg(i++ & 0x01 ? "even" : "odd"); d->m_html += QString(""; int dropZero = -1; //account dropped below zero int dropMinimum = -1; //account dropped below minimum balance QString minimumBalance = (*it_account).value("minimumBalance"); MyMoneyMoney minBalance = MyMoneyMoney(minimumBalance); MyMoneySecurity currency; MyMoneyMoney forecastBalance; //change account to deep currency if account is an investment if ((*it_account).isInvest()) { MyMoneySecurity underSecurity = file->security((*it_account).currencyId()); currency = file->security(underSecurity.tradingCurrency()); } else { currency = file->security((*it_account).currencyId()); } for (int f = beginDay; f <= d->m_forecast.forecastDays(); f += d->m_forecast.accountsCycle()) { forecastBalance = d->m_forecast.forecastBalance(*it_account, QDate::currentDate().addDays(f)); QString amount; amount = MyMoneyUtils::formatMoney(forecastBalance, *it_account, currency); amount.replace(QChar(' '), " "); d->m_html += QString("").arg(showColoredAmount(amount, forecastBalance.isNegative())); } d->m_html += ""; //Check if the account is going to be below zero or below the minimal balance in the forecast period //Check if the account is going to be below minimal balance dropMinimum = d->m_forecast.daysToMinimumBalance(*it_account); //Check if the account is going to be below zero in the future dropZero = d->m_forecast.daysToZeroBalance(*it_account); // spit out possible warnings QString msg; // if a minimum balance has been specified, an appropriate warning will // only be shown, if the drop below 0 is on a different day or not present if (dropMinimum != -1 && !minBalance.isZero() && (dropMinimum < dropZero || dropZero == -1)) { switch (dropMinimum) { case -1: break; case 0: msg = i18n("The balance of %1 is below the minimum balance %2 today.", (*it_account).name(), MyMoneyUtils::formatMoney(minBalance, *it_account, currency)); msg = showColoredAmount(msg, true); break; default: msg = i18np("The balance of %2 will drop below the minimum balance %3 in %1 day.", "The balance of %2 will drop below the minimum balance %3 in %1 days.", dropMinimum - 1, (*it_account).name(), MyMoneyUtils::formatMoney(minBalance, *it_account, currency)); msg = showColoredAmount(msg, true); break; } if (!msg.isEmpty()) { d->m_html += QString("").arg(msg).arg(colspan); } } // a drop below zero is always shown msg.clear(); switch (dropZero) { case -1: break; case 0: if ((*it_account).accountGroup() == Account::Asset) { msg = i18n("The balance of %1 is below %2 today.", (*it_account).name(), MyMoneyUtils::formatMoney(MyMoneyMoney(), *it_account, currency)); msg = showColoredAmount(msg, true); break; } if ((*it_account).accountGroup() == Account::Liability) { msg = i18n("The balance of %1 is above %2 today.", (*it_account).name(), MyMoneyUtils::formatMoney(MyMoneyMoney(), *it_account, currency)); break; } break; default: if ((*it_account).accountGroup() == Account::Asset) { msg = i18np("The balance of %2 will drop below %3 in %1 day.", "The balance of %2 will drop below %3 in %1 days.", dropZero, (*it_account).name(), MyMoneyUtils::formatMoney(MyMoneyMoney(), *it_account, currency)); msg = showColoredAmount(msg, true); break; } if ((*it_account).accountGroup() == Account::Liability) { msg = i18np("The balance of %2 will raise above %3 in %1 day.", "The balance of %2 will raise above %3 in %1 days.", dropZero, (*it_account).name(), MyMoneyUtils::formatMoney(MyMoneyMoney(), *it_account, currency)); break; } } if (!msg.isEmpty()) { d->m_html += QString("").arg(msg).arg(colspan); } } d->m_html += "
"; d->m_html += i18n("Account"); d->m_html += "").arg(colWidth); d->m_html += i18ncp("Forecast days", "%1 day", "%1 days", i * d->m_forecast.accountsCycle() + beginDay); d->m_html += "
") + link(VIEW_LEDGER, QString("?id=%1").arg((*it_account).id())) + (*it_account).name() + linkend() + "").arg(colWidth); d->m_html += QString("%1
%1
%1
"; } } QString KHomeView::link(const QString& view, const QString& query, const QString& _title) const { QString titlePart; QString title(_title); if (!title.isEmpty()) titlePart = QString(" title=\"%1\"").arg(title.replace(QLatin1Char(' '), " ")); return QString("").arg(view, query, titlePart); } QString KHomeView::linkend() const { return QStringLiteral(""); } void KHomeView::slotOpenUrl(const QUrl &url) { QString protocol = url.scheme(); QString view = url.fileName(); if (view.isEmpty()) return; QUrlQuery query(url); QString id = query.queryItemValue("id"); QString mode = query.queryItemValue("mode"); if (protocol == QLatin1String("http")) { QDesktopServices::openUrl(url); } else if (protocol == QLatin1String("mailto")) { QDesktopServices::openUrl(url); } else { KXmlGuiWindow* mw = KMyMoneyUtils::mainWindow(); Q_CHECK_PTR(mw); if (view == VIEW_LEDGER) { emit ledgerSelected(id, QString()); } else if (view == VIEW_SCHEDULE) { if (mode == QLatin1String("enter")) { emit scheduleSelected(id); QTimer::singleShot(0, mw->actionCollection()->action(kmymoney->s_Actions[Action::ScheduleEnter]), SLOT(trigger())); } else if (mode == QLatin1String("edit")) { emit scheduleSelected(id); QTimer::singleShot(0, mw->actionCollection()->action(kmymoney->s_Actions[Action::ScheduleEdit]), SLOT(trigger())); } else if (mode == QLatin1String("skip")) { emit scheduleSelected(id); QTimer::singleShot(0, mw->actionCollection()->action(kmymoney->s_Actions[Action::ScheduleSkip]), SLOT(trigger())); } else if (mode == QLatin1String("full")) { d->m_showAllSchedules = true; loadView(); } else if (mode == QLatin1String("reduced")) { d->m_showAllSchedules = false; loadView(); } } else if (view == VIEW_REPORTS) { emit reportSelected(id); } else if (view == VIEW_WELCOME) { if (mode == QLatin1String("whatsnew")) d->m_view->setHtml(KWelcomePage::whatsNewPage(), QUrl("file://")); else d->m_view->setHtml(KWelcomePage::welcomePage(), QUrl("file://")); } else if (view == QLatin1String("action")) { QTimer::singleShot(0, mw->actionCollection()->action(id), SLOT(trigger())); } else if (view == VIEW_HOME) { QList list; MyMoneyFile::instance()->accountList(list); if (list.count() == 0) { KMessageBox::information(this, i18n("Before KMyMoney can give you detailed information about your financial status, you need to create at least one account. Until then, KMyMoney shows the welcome page instead.")); } loadView(); } else { qDebug("Unknown view '%s' in KHomeView::slotOpenURL()", qPrintable(view)); } } } void KHomeView::showAssetsLiabilities() { QList accounts; QList::ConstIterator it; QList assets; QList liabilities; MyMoneyMoney netAssets; MyMoneyMoney netLiabilities; QString fontStart, fontEnd; MyMoneyFile* file = MyMoneyFile::instance(); int prec = MyMoneyMoney::denomToPrec(file->baseCurrency().smallestAccountFraction()); int i = 0; // get list of all accounts file->accountList(accounts); for (it = accounts.constBegin(); it != accounts.constEnd();) { if (!(*it).isClosed()) { switch ((*it).accountType()) { // group all assets into one list but make sure that investment accounts always show up case Account::Investment: assets << *it; break; case Account::Checkings: case Account::Savings: case Account::Cash: case Account::Asset: case Account::AssetLoan: // list account if it's the last in the hierarchy or has transactions in it if ((*it).accountList().isEmpty() || (file->transactionCount((*it).id()) > 0)) { assets << *it; } break; // group the liabilities into the other case Account::CreditCard: case Account::Liability: case Account::Loan: // list account if it's the last in the hierarchy or has transactions in it if ((*it).accountList().isEmpty() || (file->transactionCount((*it).id()) > 0)) { liabilities << *it; } break; default: break; } } ++it; } //only do it if we have assets or liabilities account if (assets.count() > 0 || liabilities.count() > 0) { // sort the accounts by name qStableSort(assets.begin(), assets.end(), accountNameLess); qStableSort(liabilities.begin(), liabilities.end(), accountNameLess); QString statusHeader; if (KMyMoneyGlobalSettings::showBalanceStatusOfOnlineAccounts()) { QString pathStatusHeader; pathStatusHeader = QPixmapToDataUri(QIcon::fromTheme(g_Icons[Icon::ViewOutbox]).pixmap(QSize(16,16))); statusHeader = QString("").arg(pathStatusHeader); } //print header d->m_html += "
" + i18n("Assets and Liabilities Summary") + "
\n
 
\n"; d->m_html += ""; //column titles d->m_html += ""; if (KMyMoneyGlobalSettings::showBalanceStatusOfOnlineAccounts()) { d->m_html += ""; } d->m_html += ""; if (KMyMoneyGlobalSettings::showCountOfUnmarkedTransactions()) d->m_html += ""; if (KMyMoneyGlobalSettings::showCountOfClearedTransactions()) d->m_html += ""; if (KMyMoneyGlobalSettings::showCountOfNotReconciledTransactions()) d->m_html += ""; d->m_html += ""; //intermediate row to separate both columns d->m_html += ""; if (KMyMoneyGlobalSettings::showBalanceStatusOfOnlineAccounts()) { d->m_html += ""; } d->m_html += ""; if (KMyMoneyGlobalSettings::showCountOfUnmarkedTransactions()) d->m_html += ""; if (KMyMoneyGlobalSettings::showCountOfClearedTransactions()) d->m_html += ""; if (KMyMoneyGlobalSettings::showCountOfNotReconciledTransactions()) d->m_html += ""; d->m_html += ""; QString placeHolder_Status, placeHolder_Counts; if (KMyMoneyGlobalSettings::showBalanceStatusOfOnlineAccounts()) placeHolder_Status = ""; if (KMyMoneyGlobalSettings::showCountOfUnmarkedTransactions()) placeHolder_Counts = ""; if (KMyMoneyGlobalSettings::showCountOfClearedTransactions()) placeHolder_Counts += ""; if (KMyMoneyGlobalSettings::showCountOfNotReconciledTransactions()) placeHolder_Counts += ""; //get asset and liability accounts QList::const_iterator asset_it = assets.constBegin(); QList::const_iterator liabilities_it = liabilities.constBegin(); for (; asset_it != assets.constEnd() || liabilities_it != liabilities.constEnd();) { d->m_html += QString("").arg(i++ & 0x01 ? "even" : "odd"); //write an asset account if we still have any if (asset_it != assets.constEnd()) { MyMoneyMoney value; //investment accounts consolidate the balance of its subaccounts if ((*asset_it).accountType() == Account::Investment) { value = investmentBalance(*asset_it); } else { value = MyMoneyFile::instance()->balance((*asset_it).id(), QDate::currentDate()); } //calculate balance for foreign currency accounts if ((*asset_it).currencyId() != file->baseCurrency().id()) { ReportAccount repAcc = ReportAccount((*asset_it).id()); MyMoneyMoney curPrice = repAcc.baseCurrencyPrice(QDate::currentDate()); MyMoneyMoney baseValue = value * curPrice; baseValue = baseValue.convert(10000); netAssets += baseValue; } else { netAssets += value; } //show the account without minimum balance showAccountEntry(*asset_it, value, MyMoneyMoney(), false); ++asset_it; } else { //write a white space if we don't d->m_html += QString("%1%2").arg(placeHolder_Status).arg(placeHolder_Counts); } //leave the intermediate column empty d->m_html += ""; //write a liability account if (liabilities_it != liabilities.constEnd()) { MyMoneyMoney value; value = MyMoneyFile::instance()->balance((*liabilities_it).id(), QDate::currentDate()); //calculate balance if foreign currency if ((*liabilities_it).currencyId() != file->baseCurrency().id()) { ReportAccount repAcc = ReportAccount((*liabilities_it).id()); MyMoneyMoney curPrice = repAcc.baseCurrencyPrice(QDate::currentDate()); MyMoneyMoney baseValue = value * curPrice; baseValue = baseValue.convert(10000); netLiabilities += baseValue; } else { netLiabilities += value; } //show the account without minimum balance showAccountEntry(*liabilities_it, value, MyMoneyMoney(), false); ++liabilities_it; } else { //leave the space empty if we run out of liabilities d->m_html += QString("%1%2").arg(placeHolder_Status).arg(placeHolder_Counts); } d->m_html += ""; } //calculate net worth MyMoneyMoney netWorth = netAssets + netLiabilities; //format assets, liabilities and net worth QString amountAssets = netAssets.formatMoney(file->baseCurrency().tradingSymbol(), prec); QString amountLiabilities = netLiabilities.formatMoney(file->baseCurrency().tradingSymbol(), prec); QString amountNetWorth = netWorth.formatMoney(file->baseCurrency().tradingSymbol(), prec); amountAssets.replace(QChar(' '), " "); amountLiabilities.replace(QChar(' '), " "); amountNetWorth.replace(QChar(' '), " "); d->m_html += QString("").arg(i++ & 0x01 ? "even" : "odd"); //print total for assets d->m_html += QString("%1%3").arg(placeHolder_Status).arg(i18n("Total Assets")).arg(placeHolder_Counts).arg(showColoredAmount(amountAssets, netAssets.isNegative())); //leave the intermediate column empty d->m_html += ""; //print total liabilities d->m_html += QString("%1%3").arg(placeHolder_Status).arg(i18n("Total Liabilities")).arg(placeHolder_Counts).arg(showColoredAmount(amountLiabilities, netLiabilities.isNegative())); d->m_html += ""; //print net worth d->m_html += QString("").arg(i++ & 0x01 ? "even" : "odd"); d->m_html += QString("%1%2").arg(placeHolder_Status).arg(placeHolder_Counts); d->m_html += QString("%1%3").arg(placeHolder_Status).arg(i18n("Net Worth")).arg(placeHolder_Counts).arg(showColoredAmount(amountNetWorth, netWorth.isNegative())); d->m_html += ""; d->m_html += "
"; d->m_html += statusHeader; d->m_html += ""; d->m_html += i18n("Asset Accounts"); d->m_html += "!MC!R"; d->m_html += i18n("Current Balance"); d->m_html += ""; d->m_html += statusHeader; d->m_html += ""; d->m_html += i18n("Liability Accounts"); d->m_html += "!MC!R"; d->m_html += i18n("Current Balance"); d->m_html += "
%2%4%2%4
%2%4
"; d->m_html += "
"; } } void KHomeView::showBudget() { MyMoneyFile* file = MyMoneyFile::instance(); if (file->countBudgets()) { int prec = MyMoneyMoney::denomToPrec(file->baseCurrency().smallestAccountFraction()); bool isOverrun = false; int i = 0; //config report just like "Monthly Budgeted vs Actual MyMoneyReport reportCfg = MyMoneyReport( MyMoneyReport::eBudgetActual, MyMoneyReport::eMonths, TransactionFilter::Date::CurrentMonth, MyMoneyReport::eDetailAll, i18n("Monthly Budgeted vs. Actual"), i18n("Generated Report")); reportCfg.setBudget("Any", true); reports::PivotTable table(reportCfg); PivotGrid grid = table.grid(); //div header d->m_html += "
" + i18n("Budget") + "
\n
 
\n"; //display budget summary d->m_html += ""; d->m_html += ""; d->m_html += ""; d->m_html += ""; d->m_html += ""; d->m_html += ""; d->m_html += ""; d->m_html += QString(""); MyMoneyMoney totalBudgetValue = grid.m_total[eBudget].m_total; MyMoneyMoney totalActualValue = grid.m_total[eActual].m_total; MyMoneyMoney totalBudgetDiffValue = grid.m_total[eBudgetDiff].m_total; QString totalBudgetAmount = totalBudgetValue.formatMoney(file->baseCurrency().tradingSymbol(), prec); QString totalActualAmount = totalActualValue.formatMoney(file->baseCurrency().tradingSymbol(), prec); QString totalBudgetDiffAmount = totalBudgetDiffValue.formatMoney(file->baseCurrency().tradingSymbol(), prec); d->m_html += QString("").arg(showColoredAmount(totalBudgetAmount, totalBudgetValue.isNegative())); d->m_html += QString("").arg(showColoredAmount(totalActualAmount, totalActualValue.isNegative())); d->m_html += QString("").arg(showColoredAmount(totalBudgetDiffAmount, totalBudgetDiffValue.isNegative())); d->m_html += ""; d->m_html += "
"; d->m_html += i18n("Current Month Summary"); d->m_html += "
"; d->m_html += i18n("Budgeted"); d->m_html += ""; d->m_html += i18n("Actual"); d->m_html += ""; d->m_html += i18n("Difference"); d->m_html += "
%1%1%1
"; //budget overrun d->m_html += "
 
\n"; d->m_html += ""; d->m_html += ""; d->m_html += ""; d->m_html += ""; d->m_html += ""; d->m_html += ""; d->m_html += ""; d->m_html += ""; PivotGrid::iterator it_outergroup = grid.begin(); while (it_outergroup != grid.end()) { i = 0; PivotOuterGroup::iterator it_innergroup = (*it_outergroup).begin(); while (it_innergroup != (*it_outergroup).end()) { PivotInnerGroup::iterator it_row = (*it_innergroup).begin(); while (it_row != (*it_innergroup).end()) { //column number is 1 because the report includes only current month if (it_row.value()[eBudgetDiff].value(1).isNegative()) { //get report account to get the name later ReportAccount rowname = it_row.key(); //write the outergroup if it is the first row of outergroup being shown if (i == 0) { d->m_html += ""; d->m_html += QString("").arg(MyMoneyAccount::accountTypeToString(rowname.accountType())); d->m_html += ""; } d->m_html += QString("").arg(i++ & 0x01 ? "even" : "odd"); //get values from grid MyMoneyMoney actualValue = it_row.value()[eActual][1]; MyMoneyMoney budgetValue = it_row.value()[eBudget][1]; MyMoneyMoney budgetDiffValue = it_row.value()[eBudgetDiff][1]; //format amounts QString actualAmount = actualValue.formatMoney(file->baseCurrency().tradingSymbol(), prec); QString budgetAmount = budgetValue.formatMoney(file->baseCurrency().tradingSymbol(), prec); QString budgetDiffAmount = budgetDiffValue.formatMoney(file->baseCurrency().tradingSymbol(), prec); //account name d->m_html += QString(""; //show amounts d->m_html += QString("").arg(showColoredAmount(budgetAmount, budgetValue.isNegative())); d->m_html += QString("").arg(showColoredAmount(actualAmount, actualValue.isNegative())); d->m_html += QString("").arg(showColoredAmount(budgetDiffAmount, budgetDiffValue.isNegative())); d->m_html += ""; //set the flag that there are overruns isOverrun = true; } ++it_row; } ++it_innergroup; } ++it_outergroup; } //if no negative differences are found, then inform that if (!isOverrun) { d->m_html += QString("").arg(i++ & 0x01 ? "even" : "odd"); d->m_html += QString("").arg(i18n("No Budget Categories have been overrun")); d->m_html += ""; } d->m_html += "
"; d->m_html += i18n("Budget Overruns"); d->m_html += "
"; d->m_html += i18n("Account"); d->m_html += ""; d->m_html += i18n("Budgeted"); d->m_html += ""; d->m_html += i18n("Actual"); d->m_html += ""; d->m_html += i18n("Difference"); d->m_html += "
%1
") + link(VIEW_LEDGER, QString("?id=%1").arg(rowname.id())) + rowname.name() + linkend() + "%1%1%1
%1
"; } } QString KHomeView::showColoredAmount(const QString& amount, bool isNegative) { if (isNegative) { //if negative, get the settings for negative numbers return QString("%2").arg(KMyMoneyGlobalSettings::schemeColor(SchemeColor::Negative).name(), amount); } //if positive, return the same string return amount; } void KHomeView::doForecast() { //clear m_accountList because forecast is about to changed d->m_accountList.clear(); //reinitialize the object d->m_forecast = KMyMoneyGlobalSettings::forecast(); //If forecastDays lower than accountsCycle, adjust to the first cycle if (d->m_forecast.accountsCycle() > d->m_forecast.forecastDays()) d->m_forecast.setForecastDays(d->m_forecast.accountsCycle()); //Get all accounts of the right type to calculate forecast d->m_forecast.doForecast(); } MyMoneyMoney KHomeView::forecastPaymentBalance(const MyMoneyAccount& acc, const MyMoneyMoney& payment, QDate& paymentDate) { //if paymentDate before or equal to currentDate set it to current date plus 1 //so we get to accumulate forecast balance correctly if (paymentDate <= QDate::currentDate()) paymentDate = QDate::currentDate().addDays(1); //check if the account is already there if (d->m_accountList.find(acc.id()) == d->m_accountList.end() || d->m_accountList[acc.id()].find(paymentDate) == d->m_accountList[acc.id()].end()) { if (paymentDate == QDate::currentDate()) { d->m_accountList[acc.id()][paymentDate] = d->m_forecast.forecastBalance(acc, paymentDate); } else { d->m_accountList[acc.id()][paymentDate] = d->m_forecast.forecastBalance(acc, paymentDate.addDays(-1)); } } d->m_accountList[acc.id()][paymentDate] = d->m_accountList[acc.id()][paymentDate] + payment; return d->m_accountList[acc.id()][paymentDate]; } void KHomeView::showCashFlowSummary() { MyMoneyTransactionFilter filter; MyMoneyMoney incomeValue; MyMoneyMoney expenseValue; MyMoneyFile* file = MyMoneyFile::instance(); int prec = MyMoneyMoney::denomToPrec(file->baseCurrency().smallestAccountFraction()); //set start and end of month dates QDate startOfMonth = QDate(QDate::currentDate().year(), QDate::currentDate().month(), 1); QDate endOfMonth = QDate(QDate::currentDate().year(), QDate::currentDate().month(), QDate::currentDate().daysInMonth()); //Add total income and expenses for this month //get transactions for current month filter.setDateFilter(startOfMonth, endOfMonth); filter.setReportAllSplits(false); QList transactions = file->transactionList(filter); //if no transaction then skip and print total in zero if (transactions.size() > 0) { QList::const_iterator it_transaction; //get all transactions for this month for (it_transaction = transactions.constBegin(); it_transaction != transactions.constEnd(); ++it_transaction) { //get the splits for each transaction const QList& splits = (*it_transaction).splits(); QList::const_iterator it_split; for (it_split = splits.begin(); it_split != splits.end(); ++it_split) { if (!(*it_split).shares().isZero()) { ReportAccount repSplitAcc = ReportAccount((*it_split).accountId()); //only add if it is an income or expense if (repSplitAcc.isIncomeExpense()) { MyMoneyMoney value; //convert to base currency if necessary if (repSplitAcc.currencyId() != file->baseCurrency().id()) { MyMoneyMoney curPrice = repSplitAcc.baseCurrencyPrice((*it_transaction).postDate()); value = ((*it_split).shares() * MyMoneyMoney::MINUS_ONE) * curPrice; value = value.convert(10000); } else { value = ((*it_split).shares() * MyMoneyMoney::MINUS_ONE); } //store depending on account type if (repSplitAcc.accountType() == Account::Income) { incomeValue += value; } else { expenseValue += value; } } } } } } //format income and expenses QString amountIncome = incomeValue.formatMoney(file->baseCurrency().tradingSymbol(), prec); QString amountExpense = expenseValue.formatMoney(file->baseCurrency().tradingSymbol(), prec); amountIncome.replace(QChar(' '), " "); amountExpense.replace(QChar(' '), " "); //calculate schedules //Add all schedules for this month MyMoneyMoney scheduledIncome; MyMoneyMoney scheduledExpense; MyMoneyMoney scheduledLiquidTransfer; MyMoneyMoney scheduledOtherTransfer; //get overdues and schedules until the end of this month QList schedule = file->scheduleList(QString(), Schedule::Type::Any, Schedule::Occurrence::Any, Schedule::PaymentType::Any, QDate(), endOfMonth, false); //Remove the finished schedules QList::Iterator finished_it; for (finished_it = schedule.begin(); finished_it != schedule.end();) { if ((*finished_it).isFinished()) { finished_it = schedule.erase(finished_it); continue; } ++finished_it; } //add income and expenses QList::Iterator sched_it; for (sched_it = schedule.begin(); sched_it != schedule.end();) { QDate nextDate = (*sched_it).nextDueDate(); int cnt = 0; while (nextDate.isValid() && nextDate <= endOfMonth) { ++cnt; nextDate = (*sched_it).nextPayment(nextDate); // for single occurrence nextDate will not change, so we // better get out of here. if ((*sched_it).occurrence() == Schedule::Occurrence::Once) break; } MyMoneyAccount acc = (*sched_it).account(); if (!acc.id().isEmpty()) { MyMoneyTransaction transaction = (*sched_it).transaction(); // only show the entry, if it is still active MyMoneySplit sp = transaction.splitByAccount(acc.id(), true); // take care of the autoCalc stuff if ((*sched_it).type() == Schedule::Type::LoanPayment) { QDate nextDate = (*sched_it).nextPayment((*sched_it).lastPayment()); //make sure we have all 'starting balances' so that the autocalc works QList::const_iterator it_s; QMap balanceMap; for (it_s = transaction.splits().constBegin(); it_s != transaction.splits().constEnd(); ++it_s) { MyMoneyAccount acc = file->account((*it_s).accountId()); // collect all overdues on the first day QDate schedDate = nextDate; if (QDate::currentDate() >= nextDate) schedDate = QDate::currentDate().addDays(1); balanceMap[acc.id()] += file->balance(acc.id(), QDate::currentDate()); } KMyMoneyUtils::calculateAutoLoan(*sched_it, transaction, balanceMap); } //go through the splits and assign to liquid or other transfers const QList splits = transaction.splits(); QList::const_iterator split_it; for (split_it = splits.constBegin(); split_it != splits.constEnd(); ++split_it) { if ((*split_it).accountId() != acc.id()) { ReportAccount repSplitAcc = ReportAccount((*split_it).accountId()); //get the shares and multiply by the quantity of occurrences in the period MyMoneyMoney value = (*split_it).shares() * cnt; //convert to foreign currency if needed if (repSplitAcc.currencyId() != file->baseCurrency().id()) { MyMoneyMoney curPrice = repSplitAcc.baseCurrencyPrice(QDate::currentDate()); value = value * curPrice; value = value.convert(10000); } if ((repSplitAcc.isLiquidLiability() || repSplitAcc.isLiquidAsset()) && acc.accountGroup() != repSplitAcc.accountGroup()) { scheduledLiquidTransfer += value; } else if (repSplitAcc.isAssetLiability() && !repSplitAcc.isLiquidLiability() && !repSplitAcc.isLiquidAsset()) { scheduledOtherTransfer += value; } else if (repSplitAcc.isIncomeExpense()) { //income and expenses are stored as negative values if (repSplitAcc.accountType() == Account::Income) scheduledIncome -= value; if (repSplitAcc.accountType() == Account::Expense) scheduledExpense -= value; } } } } ++sched_it; } //format the currency strings QString amountScheduledIncome = scheduledIncome.formatMoney(file->baseCurrency().tradingSymbol(), prec); QString amountScheduledExpense = scheduledExpense.formatMoney(file->baseCurrency().tradingSymbol(), prec); QString amountScheduledLiquidTransfer = scheduledLiquidTransfer.formatMoney(file->baseCurrency().tradingSymbol(), prec); QString amountScheduledOtherTransfer = scheduledOtherTransfer.formatMoney(file->baseCurrency().tradingSymbol(), prec); amountScheduledIncome.replace(QChar(' '), " "); amountScheduledExpense.replace(QChar(' '), " "); amountScheduledLiquidTransfer.replace(QChar(' '), " "); amountScheduledOtherTransfer.replace(QChar(' '), " "); //get liquid assets and liabilities QList accounts; QList::const_iterator account_it; MyMoneyMoney liquidAssets; MyMoneyMoney liquidLiabilities; // get list of all accounts file->accountList(accounts); for (account_it = accounts.constBegin(); account_it != accounts.constEnd();) { if (!(*account_it).isClosed()) { switch ((*account_it).accountType()) { //group all assets into one list case Account::Checkings: case Account::Savings: case Account::Cash: { MyMoneyMoney value = MyMoneyFile::instance()->balance((*account_it).id(), QDate::currentDate()); //calculate balance for foreign currency accounts if ((*account_it).currencyId() != file->baseCurrency().id()) { ReportAccount repAcc = ReportAccount((*account_it).id()); MyMoneyMoney curPrice = repAcc.baseCurrencyPrice(QDate::currentDate()); MyMoneyMoney baseValue = value * curPrice; liquidAssets += baseValue; liquidAssets = liquidAssets.convert(10000); } else { liquidAssets += value; } break; } //group the liabilities into the other case Account::CreditCard: { MyMoneyMoney value; value = MyMoneyFile::instance()->balance((*account_it).id(), QDate::currentDate()); //calculate balance if foreign currency if ((*account_it).currencyId() != file->baseCurrency().id()) { ReportAccount repAcc = ReportAccount((*account_it).id()); MyMoneyMoney curPrice = repAcc.baseCurrencyPrice(QDate::currentDate()); MyMoneyMoney baseValue = value * curPrice; liquidLiabilities += baseValue; liquidLiabilities = liquidLiabilities.convert(10000); } else { liquidLiabilities += value; } break; } default: break; } } ++account_it; } //calculate net worth MyMoneyMoney liquidWorth = liquidAssets + liquidLiabilities; //format assets, liabilities and net worth QString amountLiquidAssets = liquidAssets.formatMoney(file->baseCurrency().tradingSymbol(), prec); QString amountLiquidLiabilities = liquidLiabilities.formatMoney(file->baseCurrency().tradingSymbol(), prec); QString amountLiquidWorth = liquidWorth.formatMoney(file->baseCurrency().tradingSymbol(), prec); amountLiquidAssets.replace(QChar(' '), " "); amountLiquidLiabilities.replace(QChar(' '), " "); amountLiquidWorth.replace(QChar(' '), " "); //show the summary d->m_html += "
" + i18n("Cash Flow Summary") + "
\n
 
\n"; //print header d->m_html += ""; //income and expense title d->m_html += ""; d->m_html += ""; //column titles d->m_html += ""; d->m_html += ""; d->m_html += ""; d->m_html += ""; d->m_html += ""; d->m_html += ""; //add row with banding d->m_html += QString(""); //print current income d->m_html += QString("").arg(showColoredAmount(amountIncome, incomeValue.isNegative())); //print the scheduled income d->m_html += QString("").arg(showColoredAmount(amountScheduledIncome, scheduledIncome.isNegative())); //print current expenses d->m_html += QString("").arg(showColoredAmount(amountExpense, expenseValue.isNegative())); //print the scheduled expenses d->m_html += QString("").arg(showColoredAmount(amountScheduledExpense, scheduledExpense.isNegative())); d->m_html += ""; d->m_html += "
"; d->m_html += i18n("Income and Expenses of Current Month"); d->m_html += "
"; d->m_html += i18n("Income"); d->m_html += ""; d->m_html += i18n("Scheduled Income"); d->m_html += ""; d->m_html += i18n("Expenses"); d->m_html += ""; d->m_html += i18n("Scheduled Expenses"); d->m_html += "
%2%2%2%2
"; //print header of assets and liabilities d->m_html += "
 
\n"; d->m_html += ""; //assets and liabilities title d->m_html += ""; d->m_html += ""; //column titles d->m_html += ""; d->m_html += ""; d->m_html += ""; d->m_html += ""; d->m_html += ""; d->m_html += ""; //add row with banding d->m_html += QString(""); //print current liquid assets d->m_html += QString("").arg(showColoredAmount(amountLiquidAssets, liquidAssets.isNegative())); //print the scheduled transfers d->m_html += QString("").arg(showColoredAmount(amountScheduledLiquidTransfer, scheduledLiquidTransfer.isNegative())); //print current liabilities d->m_html += QString("").arg(showColoredAmount(amountLiquidLiabilities, liquidLiabilities.isNegative())); //print the scheduled transfers d->m_html += QString("").arg(showColoredAmount(amountScheduledOtherTransfer, scheduledOtherTransfer.isNegative())); d->m_html += ""; d->m_html += "
"; d->m_html += i18n("Liquid Assets and Liabilities"); d->m_html += "
"; d->m_html += i18n("Liquid Assets"); d->m_html += ""; d->m_html += i18n("Transfers to Liquid Liabilities"); d->m_html += ""; d->m_html += i18n("Liquid Liabilities"); d->m_html += ""; d->m_html += i18n("Other Transfers"); d->m_html += "
%2%2%2%2
"; //final conclusion MyMoneyMoney profitValue = incomeValue + expenseValue + scheduledIncome + scheduledExpense; MyMoneyMoney expectedAsset = liquidAssets + scheduledIncome + scheduledExpense + scheduledLiquidTransfer + scheduledOtherTransfer; MyMoneyMoney expectedLiabilities = liquidLiabilities + scheduledLiquidTransfer; QString amountExpectedAsset = expectedAsset.formatMoney(file->baseCurrency().tradingSymbol(), prec); QString amountExpectedLiabilities = expectedLiabilities.formatMoney(file->baseCurrency().tradingSymbol(), prec); QString amountProfit = profitValue.formatMoney(file->baseCurrency().tradingSymbol(), prec); amountProfit.replace(QChar(' '), " "); amountExpectedAsset.replace(QChar(' '), " "); amountExpectedLiabilities.replace(QChar(' '), " "); //print header of cash flow status d->m_html += "
 
\n"; d->m_html += ""; //income and expense title d->m_html += ""; d->m_html += ""; //column titles d->m_html += ""; d->m_html += ""; d->m_html += ""; d->m_html += ""; d->m_html += ""; d->m_html += ""; //add row with banding d->m_html += QString(""); d->m_html += ""; //print expected assets d->m_html += QString("").arg(showColoredAmount(amountExpectedAsset, expectedAsset.isNegative())); //print expected liabilities d->m_html += QString("").arg(showColoredAmount(amountExpectedLiabilities, expectedLiabilities.isNegative())); //print expected profit d->m_html += QString("").arg(showColoredAmount(amountProfit, profitValue.isNegative())); d->m_html += ""; d->m_html += "
"; d->m_html += i18n("Cash Flow Status"); d->m_html += "
 "; d->m_html += i18n("Expected Liquid Assets"); d->m_html += ""; d->m_html += i18n("Expected Liquid Liabilities"); d->m_html += ""; d->m_html += i18n("Expected Profit/Loss"); d->m_html += "
 %2%2%2
"; d->m_html += "
"; } // Make sure, that these definitions are only used within this file // this does not seem to be necessary, but when building RPMs the // build option 'final' is used and all CPP files are concatenated. // So it could well be, that in another CPP file these definitions // are also used. #undef VIEW_LEDGER #undef VIEW_SCHEDULE #undef VIEW_WELCOME #undef VIEW_HOME #undef VIEW_REPORTS diff --git a/kmymoney/views/khomeview.h b/kmymoney/views/khomeview.h index 5da0285be..3f6dacc7e 100644 --- a/kmymoney/views/khomeview.h +++ b/kmymoney/views/khomeview.h @@ -1,150 +1,152 @@ /*************************************************************************** khomeview.h - description ------------------- begin : Tue Jan 22 2002 copyright : (C) 2000-2002 by Michael Edwardes Javier Campos Morales Felix Rodriguez John C Thomas Baumgart Kevin Tambascio ***************************************************************************/ /*************************************************************************** * * * 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 KHOMEVIEW_H #define KHOMEVIEW_H +#include + // ---------------------------------------------------------------------------- // QT Includes // ---------------------------------------------------------------------------- // KDE Includes // ---------------------------------------------------------------------------- // Project Includes #include "kmymoneyviewbase.h" #ifdef ENABLE_WEBENGINE class QWebEngineView; #else class KWebView; #endif /** * Displays a 'home page' for the user. Similar to concepts used in * quicken and m$-money. * * @author Michael Edwardes * * @short A view containing the home page for kmymoney. **/ class QPrinter; class MyMoneyAccount; class MyMoneySchedule; class MyMoneyMoney; class KHomeView : public KMyMoneyViewBase { Q_OBJECT public: /** * Definition of bitmap used as argument for showAccounts(). */ enum paymentTypeE { Preferred = 1, ///< show preferred accounts Payment = 2 ///< show payment accounts }; explicit KHomeView(QWidget *parent = nullptr); ~KHomeView(); protected: virtual void wheelEvent(QWheelEvent *event); void showPayments(); void showPaymentEntry(const MyMoneySchedule&, int cnt = 1); void showAccounts(paymentTypeE type, const QString& hdr); void showAccountEntry(const MyMoneyAccount&); void showFavoriteReports(); void showForecast(); void showNetWorthGraph(); void showSummary(); void showAssetsLiabilities(); void showIncomeExpenseSummary(); void showSchedulesSummary(); void showBudget(); void showCashFlowSummary(); QString link(const QString& view, const QString& query, const QString& title = QString()) const; QString linkend() const; void loadView(); /** * Overridden so we can emit the activated signal. * * @return Nothing. */ void showEvent(QShowEvent* event); public slots: void slotOpenUrl(const QUrl &url); void slotLoadView(); /** * Print the current view */ void slotPrintView(); signals: void ledgerSelected(const QString& id, const QString& transaction); void scheduleSelected(const QString& id); void reportSelected(const QString& id); private: /// \internal d-pointer class. class Private; /// \internal d-pointer instance. Private* const d; /** Initializes page and sets its load status to initialized */ void init(); /** * Print an account and its balance and limit */ void showAccountEntry(const MyMoneyAccount& acc, const MyMoneyMoney& value, const MyMoneyMoney& valueToMinBal, const bool showMinBal); /** * @param acc the investment account * @return the balance in the currency of the investment account */ MyMoneyMoney investmentBalance(const MyMoneyAccount& acc); /** * Print text in the color set for negative numbers, if @p amount is negative * abd @p isNegative is true */ QString showColoredAmount(const QString& amount, bool isNegative); /** * Run the forecast */ void doForecast(); /** * Calculate the forecast balance after a payment has been made */ MyMoneyMoney forecastPaymentBalance(const MyMoneyAccount& acc, const MyMoneyMoney& payment, QDate& paymentDate); QPrinter *m_currentPrinter; }; #endif diff --git a/kmymoney/views/kreportsview.cpp b/kmymoney/views/kreportsview.cpp index 98e32827b..f22ed271f 100644 --- a/kmymoney/views/kreportsview.cpp +++ b/kmymoney/views/kreportsview.cpp @@ -1,1818 +1,1818 @@ /*************************************************************************** kreportsview.cpp - description ------------------- begin : Sat Mar 27 2004 copyright : (C) 2000-2004 by Michael Edwardes email : mte@users.sourceforge.net Javier Campos Morales Felix Rodriguez John C Thomas Baumgart Kevin Tambascio Ace Jones (C) 2017 Łukasz Wojniłowicz ***************************************************************************/ /*************************************************************************** * * * 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 "kreportsview.h" // ---------------------------------------------------------------------------- // QT Includes #include #include #include #include #include #include #include #include #include #include #include #include #include #include -#include +#include #include #ifdef ENABLE_WEBENGINE -#include +#include #else -#include +#include #endif // ---------------------------------------------------------------------------- // KDE Includes #include #include #include // ---------------------------------------------------------------------------- // Project Includes #include "ui_reportcontrol.h" #include "mymoneyfile.h" #include "mymoneyreport.h" #include "kmymoneyglobalsettings.h" #include "querytable.h" #include "objectinfotable.h" #include "kreportconfigurationfilterdlg.h" #include "icons/icons.h" #include #include "tocitem.h" #include "tocitemgroup.h" #include "tocitemreport.h" #include "kreportchartview.h" #include "pivottable.h" #include "reporttable.h" #include "../widgets/reportcontrolimpl.h" using namespace reports; using namespace eMyMoney; using namespace Icons; #define VIEW_LEDGER "ledger" #define VIEW_SCHEDULE "schedule" #define VIEW_WELCOME "welcome" #define VIEW_HOME "home" #define VIEW_REPORTS "reports" /** * KReportsView::KReportTab Implementation */ KReportsView::KReportTab::KReportTab(QTabWidget* parent, const MyMoneyReport& report, const KReportsView* eventHandler): QWidget(parent), #ifdef ENABLE_WEBENGINE m_tableView(new QWebEngineView(this)), #else m_tableView(new KWebView(this)), #endif m_chartView(new KReportChartView(this)), m_control(new ReportControl(this)), m_layout(new QVBoxLayout(this)), m_report(report), m_deleteMe(false), m_chartEnabled(false), m_showingChart(report.isChartByDefault()), m_needReload(true), m_table(0) { m_layout->setSpacing(6); m_tableView->setPage(new MyQWebEnginePage(m_tableView)); m_tableView->setZoomFactor(KMyMoneyGlobalSettings::zoomFactor()); //set button icons m_control->ui->buttonChart->setIcon(QIcon::fromTheme(g_Icons[Icon::OfficeChartLine])); m_control->ui->buttonClose->setIcon(QIcon::fromTheme(g_Icons[Icon::DocumentClose])); m_control->ui->buttonConfigure->setIcon(QIcon::fromTheme(g_Icons[Icon::Configure])); m_control->ui->buttonCopy->setIcon(QIcon::fromTheme(g_Icons[Icon::EditCopy])); m_control->ui->buttonDelete->setIcon(QIcon::fromTheme(g_Icons[Icon::EditDelete])); m_control->ui->buttonExport->setIcon(QIcon::fromTheme(g_Icons[Icon::DocumentExport])); m_control->ui->buttonNew->setIcon(QIcon::fromTheme(g_Icons[Icon::DocumentNew])); m_chartView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); m_chartView->hide(); m_tableView->hide(); m_layout->addWidget(m_control); m_layout->addWidget(m_tableView); m_layout->addWidget(m_chartView); connect(m_control->ui->buttonChart, SIGNAL(clicked()), eventHandler, SLOT(slotToggleChart())); connect(m_control->ui->buttonConfigure, SIGNAL(clicked()), eventHandler, SLOT(slotConfigure())); connect(m_control->ui->buttonNew, SIGNAL(clicked()), eventHandler, SLOT(slotDuplicate())); connect(m_control->ui->buttonCopy, SIGNAL(clicked()), eventHandler, SLOT(slotCopyView())); connect(m_control->ui->buttonExport, SIGNAL(clicked()), eventHandler, SLOT(slotSaveView())); connect(m_control->ui->buttonDelete, SIGNAL(clicked()), eventHandler, SLOT(slotDelete())); connect(m_control->ui->buttonClose, SIGNAL(clicked()), eventHandler, SLOT(slotCloseCurrent())); #ifdef ENABLE_WEBENGINE connect(m_tableView->page(), &QWebEnginePage::urlChanged, eventHandler, &KReportsView::slotOpenUrl); #else m_tableView->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks); connect(m_tableView->page(), &KWebPage::linkClicked, eventHandler, &KReportsView::slotOpenUrl); #endif // if this is a default report, then you can't delete it! if (report.id().isEmpty()) m_control->ui->buttonDelete->setEnabled(false); int tabNr = parent->addTab(this, QIcon::fromTheme(g_Icons[Icon::Spreadsheet]), report.name()); parent->setTabEnabled(tabNr, true); parent->setCurrentIndex(tabNr); // get users character set encoding m_encoding = QTextCodec::codecForLocale()->name(); } KReportsView::KReportTab::~KReportTab() { delete m_table; } void KReportsView::KReportTab::print() { if (m_tableView) { m_currentPrinter = new QPrinter(); QPrintDialog *dialog = new QPrintDialog(m_currentPrinter, this); dialog->setWindowTitle(QString()); if (dialog->exec() != QDialog::Accepted) { delete m_currentPrinter; m_currentPrinter = nullptr; return; } #ifdef ENABLE_WEBENGINE m_tableView->page()->print(m_currentPrinter, [=] (bool) {delete m_currentPrinter; m_currentPrinter = nullptr;}); #else m_tableView->print(m_currentPrinter); #endif } } void KReportsView::KReportTab::copyToClipboard() { QMimeData* pMimeData = new QMimeData(); pMimeData->setHtml(m_table->renderReport(QLatin1String("html"), m_encoding, m_report.name(), true)); QApplication::clipboard()->setMimeData(pMimeData); } void KReportsView::KReportTab::saveAs(const QString& filename, bool includeCSS) { QFile file(filename); if (file.open(QIODevice::WriteOnly)) { if (QFileInfo(filename).suffix().toLower() == QLatin1String("csv")) { QTextStream(&file) << m_table->renderReport(QLatin1String("csv"), m_encoding, QString()); } else { QString table = m_table->renderReport(QLatin1String("html"), m_encoding, m_report.name(), includeCSS); QTextStream stream(&file); stream << table; } file.close(); } } void KReportsView::KReportTab::loadTab() { m_needReload = true; if (isVisible()) { m_needReload = false; updateReport(); } } void KReportsView::KReportTab::showEvent(QShowEvent * event) { if (m_needReload) { m_needReload = false; updateReport(); } QWidget::showEvent(event); } void KReportsView::KReportTab::updateReport() { m_isChartViewValid = false; m_isTableViewValid = false; // reload the report from the engine. It might have // been changed by the user try { // Don't try to reload default reports from the engine if (!m_report.id().isEmpty()) m_report = MyMoneyFile::instance()->report(m_report.id()); } catch (const MyMoneyException &) { } delete m_table; m_table = 0; if (m_report.reportType() == MyMoneyReport::ePivotTable) { m_table = new PivotTable(m_report); m_chartEnabled = true; } else if (m_report.reportType() == MyMoneyReport::eQueryTable) { m_table = new QueryTable(m_report); m_chartEnabled = false; } else if (m_report.reportType() == MyMoneyReport::eInfoTable) { m_table = new ObjectInfoTable(m_report); m_chartEnabled = false; } m_control->ui->buttonChart->setEnabled(m_chartEnabled); m_showingChart = !m_showingChart; toggleChart(); } void KReportsView::KReportTab::toggleChart() { // for now it will just SHOW the chart. In the future it actually has to toggle it. if (m_showingChart) { if (!m_isTableViewValid) { m_tableView->setHtml(m_table->renderReport(QLatin1String("html"), m_encoding, m_report.name()), QUrl("file://")); // workaround for access permission to css file } m_isTableViewValid = true; m_tableView->show(); m_chartView->hide(); m_control->ui->buttonChart->setText(i18n("Chart")); m_control->ui->buttonChart->setToolTip(i18n("Show the chart version of this report")); m_control->ui->buttonChart->setIcon(QIcon::fromTheme(g_Icons[Icon::OfficeChartLine])); } else { if (!m_isChartViewValid) m_table->drawChart(*m_chartView); m_isChartViewValid = true; m_tableView->hide(); m_chartView->show(); m_control->ui->buttonChart->setText(i18n("Report")); m_control->ui->buttonChart->setToolTip(i18n("Show the report version of this chart")); m_control->ui->buttonChart->setIcon(QIcon::fromTheme(g_Icons[Icon::ViewFinancialList])); } m_showingChart = ! m_showingChart; } void KReportsView::KReportTab::updateDataRange() { QList grids = m_chartView->coordinatePlane()->gridDimensionsList(); // get dimmensions of ploted graph if (grids.isEmpty()) return; QChar separator = locale().groupSeparator(); QChar decimalPoint = locale().decimalPoint(); int precision = m_report.yLabelsPrecision(); QList> dims; // create list of dimension values in string and qreal // get qreal values dims.append(qMakePair(QString(), grids.at(1).start)); dims.append(qMakePair(QString(), grids.at(1).end)); dims.append(qMakePair(QString(), grids.at(1).stepWidth)); dims.append(qMakePair(QString(), grids.at(1).subStepWidth)); // convert qreal values to string variables for (int i = 0; i < 4; ++i) { if (i > 2) ++precision; if (precision == 0) dims[i].first = locale().toString(qRound(dims.at(i).second)); else dims[i].first = locale().toString(dims.at(i).second, 'f', precision).remove(separator).remove(QRegularExpression("0+$")).remove(QRegularExpression("\\" + decimalPoint + "$")); } // save string variables in report's data m_report.setDataRangeStart(dims.at(0).first); m_report.setDataRangeEnd(dims.at(1).first); m_report.setDataMajorTick(dims.at(2).first); m_report.setDataMinorTick(dims.at(3).first); } /** * KReportsView Implementation */ KReportsView::KReportsView(QWidget *parent) : KMyMoneyViewBase(parent), m_needReload(false), m_needLoad(true), m_reportListView(0) { } void KReportsView::setDefaultFocus() { QTimer::singleShot(0, m_tocTreeWidget, SLOT(setFocus())); } void KReportsView::init() { m_needLoad = false; auto vbox = new QVBoxLayout(this); setLayout(vbox); vbox->setSpacing(6); vbox->setMargin(0); // build reports toc setColumnsAlreadyAdjusted(false); m_reportTabWidget = new QTabWidget(this); vbox->addWidget(m_reportTabWidget); m_reportTabWidget->setTabsClosable(true); m_listTab = new QWidget(m_reportTabWidget); m_listTabLayout = new QVBoxLayout(m_listTab); m_listTabLayout->setSpacing(6); m_tocTreeWidget = new QTreeWidget(m_listTab); // report-group items have only 1 column (name of group), // report items have 2 columns (report name and comment) m_tocTreeWidget->setColumnCount(2); // headers QStringList headers; headers << i18n("Reports") << i18n("Comment"); m_tocTreeWidget->setHeaderLabels(headers); m_tocTreeWidget->setAlternatingRowColors(true); m_tocTreeWidget->setSortingEnabled(true); m_tocTreeWidget->sortByColumn(0, Qt::AscendingOrder); // for report group items: // doubleclick toggles the expand-state, // so avoid any further action in case of doubleclick // (see slotItemDoubleClicked) m_tocTreeWidget->setExpandsOnDoubleClick(false); m_tocTreeWidget->setContextMenuPolicy(Qt::CustomContextMenu); m_tocTreeWidget->setSelectionMode(QAbstractItemView::SingleSelection); m_listTabLayout->addWidget(m_tocTreeWidget); m_reportTabWidget->addTab(m_listTab, i18n("Reports")); connect(m_reportTabWidget, SIGNAL(tabCloseRequested(int)), this, SLOT(slotClose(int))); connect(m_tocTreeWidget, &QTreeWidget::itemActivated, this, &KReportsView::slotItemDoubleClicked); connect(m_tocTreeWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(slotListContextMenu(QPoint))); connect(MyMoneyFile::instance(), SIGNAL(dataChanged()), this, SLOT(slotLoadView())); } void KReportsView::showEvent(QShowEvent * event) { if (m_needLoad) init(); emit aboutToShow(View::Reports); if (m_needReload) { loadView(); m_needReload = false; } KReportTab* tab = dynamic_cast(m_reportTabWidget->currentWidget()); if (tab) emit reportSelected(tab->report()); else emit reportSelected(MyMoneyReport()); // don't forget base class implementation KMyMoneyViewBase::showEvent(event); } void KReportsView::slotLoadView() { m_needReload = true; if (isVisible()) { loadView(); m_needReload = false; } } void KReportsView::loadView() { // remember the id of the current selected item QTreeWidgetItem* item = m_tocTreeWidget->currentItem(); QString selectedItem = (item) ? item->text(0) : QString(); // save expand states of all top-level items QMap expandStates; for (int i = 0; i < m_tocTreeWidget->topLevelItemCount(); i++) { QTreeWidgetItem* item = m_tocTreeWidget->topLevelItem(i); if (item) { QString itemLabel = item->text(0); if (item->isExpanded()) { expandStates.insert(itemLabel, true); } else { expandStates.insert(itemLabel, false); } } } // find the item visible on top QTreeWidgetItem* visibleTopItem = m_tocTreeWidget->itemAt(0, 0); // text of column 0 identifies the item visible on top QString visibleTopItemText; bool visibleTopItemFound = true; if (visibleTopItem == NULL) { visibleTopItemFound = false; } else { // this assumes, that all item-texts in column 0 are unique, // no matter, whether the item is a report- or a group-item visibleTopItemText = visibleTopItem->text(0); } // turn off updates to avoid flickering during reload //m_reportListView->setUpdatesEnabled(false); // // Rebuild the list page // m_tocTreeWidget->clear(); // Default Reports QList defaultreports; defaultReports(defaultreports); QList::const_iterator it_group = defaultreports.constBegin(); // the item to be set as current item QTreeWidgetItem* currentItem = 0L; // group number, this will be used as sort key for reportgroup items // we have: // 1st some default groups // 2nd a chart group // 3rd maybe a favorite group // 4th maybe an orphan group (for old reports) int defaultGroupNo = 1; int chartGroupNo = defaultreports.size() + 1; // group for diagrams QString groupName = I18N_NOOP("Charts"); TocItemGroup* chartTocItemGroup = new TocItemGroup(m_tocTreeWidget, chartGroupNo, i18n(groupName.toLatin1().data())); m_allTocItemGroups.insert(groupName, chartTocItemGroup); while (it_group != defaultreports.constEnd()) { QString groupName = (*it_group).name(); TocItemGroup* defaultTocItemGroup = new TocItemGroup(m_tocTreeWidget, defaultGroupNo++, i18n(groupName.toLatin1().data())); m_allTocItemGroups.insert(groupName, defaultTocItemGroup); if (groupName == selectedItem) { currentItem = defaultTocItemGroup; } QList::const_iterator it_report = (*it_group).begin(); while (it_report != (*it_group).end()) { MyMoneyReport report = *it_report; report.setGroup(groupName); TocItemReport* reportTocItemReport = new TocItemReport(defaultTocItemGroup, report); if (report.name() == selectedItem) { currentItem = reportTocItemReport; } // ALSO place it into the Charts list if it's displayed as a chart by default if (report.isChartByDefault()) { new TocItemReport(chartTocItemGroup, report); } ++it_report; } ++it_group; } // group for custom (favorite) reports int favoriteGroupNo = chartGroupNo + 1; groupName = I18N_NOOP("Favorite Reports"); TocItemGroup* favoriteTocItemGroup = new TocItemGroup(m_tocTreeWidget, favoriteGroupNo, i18n(groupName.toLatin1().data())); m_allTocItemGroups.insert(groupName, favoriteTocItemGroup); TocItemGroup* orphanTocItemGroup = 0; QList customreports = MyMoneyFile::instance()->reportList(); QList::const_iterator it_report = customreports.constBegin(); while (it_report != customreports.constEnd()) { MyMoneyReport report = *it_report; QString groupName = (*it_report).group(); // If this report is in a known group, place it there // KReportGroupListItem* groupnode = groupitems[(*it_report).group()]; TocItemGroup* groupNode = m_allTocItemGroups[groupName]; if (groupNode) { new TocItemReport(groupNode, report); } else { // otherwise, place it in the orphanage if (!orphanTocItemGroup) { // group for orphaned reports int orphanGroupNo = favoriteGroupNo + 1; QString groupName = I18N_NOOP("Old Customized Reports"); orphanTocItemGroup = new TocItemGroup(m_tocTreeWidget, orphanGroupNo, i18n(groupName.toLatin1().data())); m_allTocItemGroups.insert(groupName, orphanTocItemGroup); } new TocItemReport(orphanTocItemGroup, report); } // ALSO place it into the Favorites list if it's a favorite if ((*it_report).isFavorite()) { new TocItemReport(favoriteTocItemGroup, report); } // ALSO place it into the Charts list if it's displayed as a chart by default if ((*it_report).isChartByDefault()) { new TocItemReport(chartTocItemGroup, report); } ++it_report; } // // Go through the tabs to set their update flag or delete them if needed // int index = 1; while (index < m_reportTabWidget->count()) { // TODO: Find some way of detecting the file is closed and kill these tabs!! KReportTab* tab = dynamic_cast(m_reportTabWidget->widget(index)); if (tab->isReadyToDelete() /* || ! reports.count() */) { delete tab; --index; } else { tab->loadTab(); } ++index; } if (visibleTopItemFound) { // try to find the visibleTopItem that we had at the start of this method // intentionally not using 'Qt::MatchCaseSensitive' here // to avoid 'item not found' if someone corrected a typo only QList visibleTopItemList = m_tocTreeWidget->findItems(visibleTopItemText, Qt::MatchFixedString | Qt::MatchRecursive); if (visibleTopItemList.isEmpty()) { // the item could not be found, it was deleted or renamed visibleTopItemFound = false; } else { visibleTopItem = visibleTopItemList.at(0); if (visibleTopItem == NULL) { visibleTopItemFound = false; } } } // adjust column widths, // but only the first time when the view is loaded, // maybe the user sets other column widths later, // so don't disturb him if (columnsAlreadyAdjusted()) { // restore expand states of all top-level items restoreTocExpandState(expandStates); // restore current item m_tocTreeWidget->setCurrentItem(currentItem); // try to scroll to the item visible on top // when this method started if (visibleTopItemFound) { m_tocTreeWidget->scrollToItem(visibleTopItem); } else { m_tocTreeWidget->scrollToTop(); } return; } // avoid flickering m_tocTreeWidget->setUpdatesEnabled(false); // expand all top-level items m_tocTreeWidget->expandAll(); // resize columns m_tocTreeWidget->resizeColumnToContents(0); m_tocTreeWidget->resizeColumnToContents(1); // restore expand states of all top-level items restoreTocExpandState(expandStates); // restore current item m_tocTreeWidget->setCurrentItem(currentItem); // try to scroll to the item visible on top // when this method started if (visibleTopItemFound) { m_tocTreeWidget->scrollToItem(visibleTopItem); } else { m_tocTreeWidget->scrollToTop(); } setColumnsAlreadyAdjusted(true); m_tocTreeWidget->setUpdatesEnabled(true); } void KReportsView::slotOpenUrl(const QUrl &url) { QString view = url.fileName(); if (view.isEmpty()) return; QString command = QUrlQuery(url).queryItemValue("command"); QString id = QUrlQuery(url).queryItemValue("id"); QString tid = QUrlQuery(url).queryItemValue("tid"); if (view == VIEW_REPORTS) { if (command.isEmpty()) { // slotRefreshView(); } else if (command == QLatin1String("print")) slotPrintView(); else if (command == QLatin1String("copy")) slotCopyView(); else if (command == QLatin1String("save")) slotSaveView(); else if (command == QLatin1String("configure")) slotConfigure(); else if (command == QLatin1String("duplicate")) slotDuplicate(); else if (command == QLatin1String("close")) slotCloseCurrent(); else if (command == QLatin1String("delete")) slotDelete(); else qWarning() << i18n("Unknown command '%1' in KReportsView::slotOpenUrl()", qPrintable(command)); } else if (view == VIEW_LEDGER) { emit ledgerSelected(id, tid); } else { qWarning() << i18n("Unknown view '%1' in KReportsView::slotOpenUrl()", qPrintable(view)); } } void KReportsView::slotPrintView() { KReportTab* tab = dynamic_cast(m_reportTabWidget->currentWidget()); if (tab) tab->print(); } void KReportsView::slotCopyView() { KReportTab* tab = dynamic_cast(m_reportTabWidget->currentWidget()); if (tab) tab->copyToClipboard(); } void KReportsView::slotSaveView() { KReportTab* tab = dynamic_cast(m_reportTabWidget->currentWidget()); if (tab) { QString filterList = i18nc("CSV (Filefilter)", "CSV files") + QLatin1String(" (*.csv);;") + i18nc("HTML (Filefilter)", "HTML files") + QLatin1String(" (*.html)"); QUrl newURL = QFileDialog::getSaveFileUrl(this, i18n("Export as"), QUrl::fromLocalFile(KRecentDirs::dir(":kmymoney-export")), filterList, &m_selectedExportFilter); if (!newURL.isEmpty()) { KRecentDirs::add(":kmymoney-export", newURL.adjusted(QUrl::RemoveFilename | QUrl::StripTrailingSlash).path()); QString newName = newURL.toDisplayString(QUrl::PreferLocalFile); try { tab->saveAs(newName, true); } catch (const MyMoneyException &e) { KMessageBox::error(this, i18n("Failed to save: %1", e.what())); } } } } void KReportsView::slotConfigure() { QString cm = "KReportsView::slotConfigure"; KReportTab* tab = dynamic_cast(m_reportTabWidget->currentWidget()); if (!tab) // nothing to do return; int tabNr = m_reportTabWidget->currentIndex(); tab->updateDataRange(); // range will be needed during configuration, but cannot be obtained earlier MyMoneyReport report = tab->report(); if (report.comment() == i18n("Default Report") || report.comment() == i18n("Generated Report")) { report.setComment(i18n("Custom Report")); report.setName(i18n("%1 (Customized)", report.name())); } QPointer dlg = new KReportConfigurationFilterDlg(report); if (dlg->exec()) { MyMoneyReport newreport = dlg->getConfig(); // If this report has an ID, then MODIFY it, otherwise ADD it MyMoneyFileTransaction ft; try { if (! newreport.id().isEmpty()) { MyMoneyFile::instance()->modifyReport(newreport); ft.commit(); tab->modifyReport(newreport); m_reportTabWidget->setTabText(tabNr, newreport.name()); m_reportTabWidget->setCurrentIndex(tabNr) ; } else { MyMoneyFile::instance()->addReport(newreport); ft.commit(); QString reportGroupName = newreport.group(); // find report group TocItemGroup* tocItemGroup = m_allTocItemGroups[reportGroupName]; if (!tocItemGroup) { QString error = i18n("Could not find reportgroup \"%1\" for report \"%2\".\nPlease report this error to the developer's list: kmymoney-devel@kde.org", reportGroupName, newreport.name()); // write to messagehandler qWarning() << cm << error; // also inform user KMessageBox::error(m_reportTabWidget, error, i18n("Critical Error")); // cleanup delete dlg; return; } // do not add TocItemReport to TocItemGroup here, // this is done in loadView addReportTab(newreport); } } catch (const MyMoneyException &e) { KMessageBox::error(this, i18n("Failed to configure report: %1", e.what())); } } delete dlg; } void KReportsView::slotDuplicate() { QString cm = "KReportsView::slotDuplicate"; KReportTab* tab = dynamic_cast(m_reportTabWidget->currentWidget()); if (!tab) { // nothing to do return; } MyMoneyReport dupe = tab->report(); dupe.setName(i18n("Copy of %1", dupe.name())); if (dupe.comment() == i18n("Default Report")) dupe.setComment(i18n("Custom Report")); dupe.clearId(); QPointer dlg = new KReportConfigurationFilterDlg(dupe); if (dlg->exec()) { MyMoneyReport newReport = dlg->getConfig(); MyMoneyFileTransaction ft; try { MyMoneyFile::instance()->addReport(newReport); ft.commit(); QString reportGroupName = newReport.group(); // find report group TocItemGroup* tocItemGroup = m_allTocItemGroups[reportGroupName]; if (!tocItemGroup) { QString error = i18n("Could not find reportgroup \"%1\" for report \"%2\".\nPlease report this error to the developer's list: kmymoney-devel@kde.org", reportGroupName, newReport.name()); // write to messagehandler qWarning() << cm << error; // also inform user KMessageBox::error(m_reportTabWidget, error, i18n("Critical Error")); // cleanup delete dlg; return; } // do not add TocItemReport to TocItemGroup here, // this is done in loadView addReportTab(newReport); } catch (const MyMoneyException &e) { QString error = i18n("Cannot add report, reason: \"%1\"", e.what()); // write to messagehandler qWarning() << cm << error; // also inform user KMessageBox::error(m_reportTabWidget, error, i18n("Critical Error")); } } delete dlg; } void KReportsView::slotDelete() { KReportTab* tab = dynamic_cast(m_reportTabWidget->currentWidget()); if (!tab) { // nothing to do return; } MyMoneyReport report = tab->report(); if (! report.id().isEmpty()) { if (KMessageBox::Continue == deleteReportDialog(report.name())) { // close the tab and then remove the report so that it is not // generated again during the following loadView() call slotClose(m_reportTabWidget->currentIndex()); MyMoneyFileTransaction ft; MyMoneyFile::instance()->removeReport(report); ft.commit(); } } else { KMessageBox::information(this, QString("") + i18n("%1 is a default report, so it cannot be deleted.", report.name()) + QString(""), i18n("Delete Report?")); } } int KReportsView::deleteReportDialog(const QString &reportName) { return KMessageBox::warningContinueCancel(this, QString("") + i18n("Are you sure you want to delete report %1? There is no way to recover it.", reportName) + QString(""), i18n("Delete Report?")); } void KReportsView::slotOpenReport(const QString& id) { if (id.isEmpty()) { // nothing to do return; } KReportTab* page = 0; // Find the tab which contains the report int index = 1; while (index < m_reportTabWidget->count()) { KReportTab* current = dynamic_cast(m_reportTabWidget->widget(index)); if (current->report().id() == id) { page = current; break; } ++index; } // Show the tab, or create a new one, as needed if (page) m_reportTabWidget->setCurrentIndex(index); else addReportTab(MyMoneyFile::instance()->report(id)); } void KReportsView::slotOpenReport(const MyMoneyReport& report) { qDebug() << Q_FUNC_INFO << " " << report.name(); KReportTab* page = 0; // Find the tab which contains the report indicated by this list item int index = 1; while (index < m_reportTabWidget->count()) { KReportTab* current = dynamic_cast(m_reportTabWidget->widget(index)); if (current->report().name() == report.name()) { page = current; break; } ++index; } // Show the tab, or create a new one, as needed if (page) m_reportTabWidget->setCurrentIndex(index); else addReportTab(report); } void KReportsView::slotItemDoubleClicked(QTreeWidgetItem* item, int) { TocItem* tocItem = dynamic_cast(item); if (!tocItem->isReport()) { // toggle the expanded-state for reportgroup-items item->setExpanded(item->isExpanded() ? false : true); // nothing else to do for reportgroup-items return; } TocItemReport* reportTocItem = dynamic_cast(tocItem); MyMoneyReport& report = reportTocItem->getReport(); KReportTab* page = 0; // Find the tab which contains the report indicated by this list item int index = 1; while (index < m_reportTabWidget->count()) { KReportTab* current = dynamic_cast(m_reportTabWidget->widget(index)); // If this report has an ID, we'll use the ID to match if (! report.id().isEmpty()) { if (current->report().id() == report.id()) { page = current; break; } } // Otherwise, use the name to match. THIS ASSUMES that no 2 default reports // have the same name...but that would be pretty a boneheaded thing to do. else { if (current->report().name() == report.name()) { page = current; break; } } ++index; } // Show the tab, or create a new one, as needed if (page) m_reportTabWidget->setCurrentIndex(index); else addReportTab(report); } void KReportsView::slotToggleChart() { KReportTab* tab = dynamic_cast(m_reportTabWidget->currentWidget()); if (tab) tab->toggleChart(); } void KReportsView::slotCloseCurrent() { slotClose(m_reportTabWidget->currentIndex()); } void KReportsView::slotClose(int index) { KReportTab* tab = dynamic_cast(m_reportTabWidget->widget(index)); if (tab) { m_reportTabWidget->removeTab(index); tab->setReadyToDelete(true); } } void KReportsView::slotCloseAll() { if(!m_needLoad) { while (true) { KReportTab* tab = dynamic_cast(m_reportTabWidget->widget(1)); if (tab) { m_reportTabWidget->removeTab(1); tab->setReadyToDelete(true); } else break; } } } void KReportsView::addReportTab(const MyMoneyReport& report) { new KReportTab(m_reportTabWidget, report, this); } void KReportsView::slotListContextMenu(const QPoint & p) { QTreeWidgetItem *item = m_tocTreeWidget->itemAt(p); if (!item) { return; } TocItem* tocItem = dynamic_cast(item); if (!tocItem->isReport()) { // currently there is no context menu for reportgroup items return; } QMenu* contextmenu = new QMenu(this); contextmenu->addAction(i18nc("To open a new report", "&Open"), this, SLOT(slotOpenFromList())); contextmenu->addAction(i18nc("Configure a report", "&Configure"), this, SLOT(slotConfigureFromList())); contextmenu->addAction(i18n("&New report"), this, SLOT(slotNewFromList())); // Only add this option if it's a custom report. Default reports cannot be deleted TocItemReport* reportTocItem = dynamic_cast(tocItem); MyMoneyReport& report = reportTocItem->getReport(); if (! report.id().isEmpty()) { contextmenu->addAction(i18n("&Delete"), this, SLOT(slotDeleteFromList())); } contextmenu->popup(m_tocTreeWidget->mapToGlobal(p)); } void KReportsView::slotOpenFromList() { TocItem* tocItem = dynamic_cast(m_tocTreeWidget->currentItem()); if (tocItem) slotItemDoubleClicked(tocItem, 0); } void KReportsView::slotConfigureFromList() { TocItem* tocItem = dynamic_cast(m_tocTreeWidget->currentItem()); if (tocItem) { slotItemDoubleClicked(tocItem, 0); slotConfigure(); } } void KReportsView::slotNewFromList() { TocItem* tocItem = dynamic_cast(m_tocTreeWidget->currentItem()); if (tocItem) { slotItemDoubleClicked(tocItem, 0); slotDuplicate(); } } void KReportsView::slotDeleteFromList() { TocItem* tocItem = dynamic_cast(m_tocTreeWidget->currentItem()); if (tocItem) { TocItemReport* reportTocItem = dynamic_cast(tocItem); MyMoneyReport& report = reportTocItem->getReport(); // If this report does not have an ID, it's a default report and cannot be deleted if (! report.id().isEmpty() && KMessageBox::Continue == deleteReportDialog(report.name())) { // check if report's tab is open; start from 1 because 0 is toc tab for (int i = 1; i < m_reportTabWidget->count(); ++i) { KReportTab* tab = dynamic_cast(m_reportTabWidget->widget(i)); if (tab->report().id() == report.id()) { slotClose(i); // if open, close it, so no crash when switching to it break; } } MyMoneyFileTransaction ft; MyMoneyFile::instance()->removeReport(report); ft.commit(); } } } void KReportsView::defaultReports(QList& groups) { { ReportGroup list("Income and Expenses", i18n("Income and Expenses")); list.push_back(MyMoneyReport( MyMoneyReport::eExpenseIncome, MyMoneyReport::eMonths, TransactionFilter::Date::CurrentMonth, MyMoneyReport::eDetailAll, i18n("Income and Expenses This Month"), i18n("Default Report") )); list.push_back(MyMoneyReport( MyMoneyReport::eExpenseIncome, MyMoneyReport::eMonths, TransactionFilter::Date::YearToDate, MyMoneyReport::eDetailAll, i18n("Income and Expenses This Year"), i18n("Default Report") )); list.push_back(MyMoneyReport( MyMoneyReport::eExpenseIncome, MyMoneyReport::eYears, TransactionFilter::Date::All, MyMoneyReport::eDetailAll, i18n("Income and Expenses By Year"), i18n("Default Report") )); list.push_back(MyMoneyReport( MyMoneyReport::eExpenseIncome, MyMoneyReport::eMonths, TransactionFilter::Date::Last12Months, MyMoneyReport::eDetailTop, i18n("Income and Expenses Graph"), i18n("Default Report") )); list.back().setChartByDefault(true); list.back().setChartType(MyMoneyReport::eChartLine); list.back().setChartDataLabels(false); list.push_back(MyMoneyReport( MyMoneyReport::eExpenseIncome, MyMoneyReport::eMonths, TransactionFilter::Date::YearToDate, MyMoneyReport::eDetailGroup, i18n("Income and Expenses Pie Chart"), i18n("Default Report") )); list.back().setChartByDefault(true); list.back().setChartType(MyMoneyReport::eChartPie); list.back().setShowingRowTotals(false); groups.push_back(list); } { ReportGroup list("Net Worth", i18n("Net Worth")); list.push_back(MyMoneyReport( MyMoneyReport::eAssetLiability, MyMoneyReport::eMonths, TransactionFilter::Date::YearToDate, MyMoneyReport::eDetailTop, i18n("Net Worth By Month"), i18n("Default Report") )); list.push_back(MyMoneyReport( MyMoneyReport::eAssetLiability, MyMoneyReport::eMonths, TransactionFilter::Date::Today, MyMoneyReport::eDetailTop, i18n("Net Worth Today"), i18n("Default Report") )); list.push_back(MyMoneyReport( MyMoneyReport::eAssetLiability, MyMoneyReport::eYears, TransactionFilter::Date::All, MyMoneyReport::eDetailTop, i18n("Net Worth By Year"), i18n("Default Report") )); list.push_back(MyMoneyReport( MyMoneyReport::eAssetLiability, MyMoneyReport::eMonths, TransactionFilter::Date::Next7Days, MyMoneyReport::eDetailTop, i18n("7-day Cash Flow Forecast"), i18n("Default Report") )); list.back().setIncludingSchedules(true); list.back().setColumnsAreDays(true); list.push_back(MyMoneyReport( MyMoneyReport::eAssetLiability, MyMoneyReport::eMonths, TransactionFilter::Date::Last12Months, MyMoneyReport::eDetailTotal, i18n("Net Worth Graph"), i18n("Default Report") )); list.back().setChartByDefault(true); list.back().setChartCHGridLines(false); list.back().setChartSVGridLines(false); list.back().setChartType(MyMoneyReport::eChartLine); list.push_back(MyMoneyReport( MyMoneyReport::eInstitution, MyMoneyReport::eQCnone, TransactionFilter::Date::YearToDate, MyMoneyReport::eDetailTop, i18n("Account Balances by Institution"), i18n("Default Report") )); list.push_back(MyMoneyReport( MyMoneyReport::eAccountType, MyMoneyReport::eQCnone, TransactionFilter::Date::YearToDate, MyMoneyReport::eDetailTop, i18n("Account Balances by Type"), i18n("Default Report") )); groups.push_back(list); } { ReportGroup list("Transactions", i18n("Transactions")); list.push_back(MyMoneyReport( MyMoneyReport::eAccount, MyMoneyReport::eQCnumber | MyMoneyReport::eQCpayee | MyMoneyReport::eQCcategory | MyMoneyReport::eQCtag | MyMoneyReport::eQCbalance, TransactionFilter::Date::YearToDate, MyMoneyReport::eDetailAll, i18n("Transactions by Account"), i18n("Default Report") )); //list.back().setConvertCurrency(false); list.push_back(MyMoneyReport( MyMoneyReport::eCategory, MyMoneyReport::eQCnumber | MyMoneyReport::eQCpayee | MyMoneyReport::eQCaccount | MyMoneyReport::eQCtag, TransactionFilter::Date::YearToDate, MyMoneyReport::eDetailAll, i18n("Transactions by Category"), i18n("Default Report") )); list.push_back(MyMoneyReport( MyMoneyReport::ePayee, MyMoneyReport::eQCnumber | MyMoneyReport::eQCcategory | MyMoneyReport::eQCtag, TransactionFilter::Date::YearToDate, MyMoneyReport::eDetailAll, i18n("Transactions by Payee"), i18n("Default Report") )); list.push_back(MyMoneyReport( MyMoneyReport::eTag, MyMoneyReport::eQCnumber | MyMoneyReport::eQCcategory, TransactionFilter::Date::YearToDate, MyMoneyReport::eDetailAll, i18n("Transactions by Tag"), i18n("Default Report") )); list.push_back(MyMoneyReport( MyMoneyReport::eMonth, MyMoneyReport::eQCnumber | MyMoneyReport::eQCpayee | MyMoneyReport::eQCcategory | MyMoneyReport::eQCtag, TransactionFilter::Date::YearToDate, MyMoneyReport::eDetailAll, i18n("Transactions by Month"), i18n("Default Report") )); list.push_back(MyMoneyReport( MyMoneyReport::eWeek, MyMoneyReport::eQCnumber | MyMoneyReport::eQCpayee | MyMoneyReport::eQCcategory | MyMoneyReport::eQCtag, TransactionFilter::Date::YearToDate, MyMoneyReport::eDetailAll, i18n("Transactions by Week"), i18n("Default Report") )); list.push_back(MyMoneyReport( MyMoneyReport::eAccount, MyMoneyReport::eQCloan, TransactionFilter::Date::All, MyMoneyReport::eDetailAll, i18n("Loan Transactions"), i18n("Default Report") )); list.back().setLoansOnly(true); list.push_back(MyMoneyReport( MyMoneyReport::eAccountReconcile, MyMoneyReport::eQCnumber | MyMoneyReport::eQCpayee | MyMoneyReport::eQCcategory | MyMoneyReport::eQCbalance, TransactionFilter::Date::Last3Months, MyMoneyReport::eDetailAll, i18n("Transactions by Reconciliation Status"), i18n("Default Report") )); groups.push_back(list); } { ReportGroup list("CashFlow", i18n("Cash Flow")); list.push_back(MyMoneyReport( MyMoneyReport::eCashFlow, MyMoneyReport::eQCnumber | MyMoneyReport::eQCpayee | MyMoneyReport::eQCaccount, TransactionFilter::Date::YearToDate, MyMoneyReport::eDetailAll, i18n("Cash Flow Transactions This Month"), i18n("Default Report") )); groups.push_back(list); } { ReportGroup list("Investments", i18n("Investments")); list.push_back(MyMoneyReport( MyMoneyReport::eTopAccount, MyMoneyReport::eQCaction | MyMoneyReport::eQCshares | MyMoneyReport::eQCprice, TransactionFilter::Date::YearToDate, MyMoneyReport::eDetailAll, i18n("Investment Transactions"), i18n("Default Report") )); list.back().setInvestmentsOnly(true); list.push_back(MyMoneyReport( MyMoneyReport::eAccountByTopAccount, MyMoneyReport::eQCshares | MyMoneyReport::eQCprice, TransactionFilter::Date::YearToDate, MyMoneyReport::eDetailAll, i18n("Investment Holdings by Account"), i18n("Default Report") )); list.back().setInvestmentsOnly(true); list.push_back(MyMoneyReport( MyMoneyReport::eEquityType, MyMoneyReport::eQCshares | MyMoneyReport::eQCprice, TransactionFilter::Date::YearToDate, MyMoneyReport::eDetailAll, i18n("Investment Holdings by Type"), i18n("Default Report") )); list.back().setInvestmentsOnly(true); list.push_back(MyMoneyReport( MyMoneyReport::eAccountByTopAccount, MyMoneyReport::eQCperformance, TransactionFilter::Date::YearToDate, MyMoneyReport::eDetailAll, i18n("Investment Performance by Account"), i18n("Default Report") )); list.back().setInvestmentsOnly(true); list.push_back(MyMoneyReport( MyMoneyReport::eEquityType, MyMoneyReport::eQCperformance, TransactionFilter::Date::YearToDate, MyMoneyReport::eDetailAll, i18n("Investment Performance by Type"), i18n("Default Report") )); list.back().setInvestmentsOnly(true); list.push_back(MyMoneyReport( MyMoneyReport::eAccountByTopAccount, MyMoneyReport::eQCcapitalgain, TransactionFilter::Date::YearToDate, MyMoneyReport::eDetailAll, i18n("Investment Capital Gains by Account"), i18n("Default Report") )); list.back().setInvestmentsOnly(true); list.push_back(MyMoneyReport( MyMoneyReport::eEquityType, MyMoneyReport::eQCcapitalgain, TransactionFilter::Date::YearToDate, MyMoneyReport::eDetailAll, i18n("Investment Capital Gains by Type"), i18n("Default Report") )); list.back().setInvestmentsOnly(true); list.push_back(MyMoneyReport( MyMoneyReport::eAssetLiability, MyMoneyReport::eMonths, TransactionFilter::Date::Today, MyMoneyReport::eDetailAll, i18n("Investment Holdings Pie"), i18n("Default Report") )); list.back().setChartByDefault(true); list.back().setChartCHGridLines(false); list.back().setChartSVGridLines(false); list.back().setChartType(MyMoneyReport::eChartPie); list.back().setInvestmentsOnly(true); list.push_back(MyMoneyReport( MyMoneyReport::eAssetLiability, MyMoneyReport::eMonths, TransactionFilter::Date::Last12Months, MyMoneyReport::eDetailAll, i18n("Investment Worth Graph"), i18n("Default Report") )); list.back().setChartByDefault(true); list.back().setChartCHGridLines(false); list.back().setChartSVGridLines(false); list.back().setChartType(MyMoneyReport::eChartLine); list.back().setColumnsAreDays(true); list.back().setInvestmentsOnly(true); list.push_back(MyMoneyReport( MyMoneyReport::eAssetLiability, MyMoneyReport::eMonths, TransactionFilter::Date::Last12Months, MyMoneyReport::eDetailAll, i18n("Investment Price Graph"), i18n("Default Report") )); list.back().setChartByDefault(true); list.back().setChartCHGridLines(false); list.back().setChartSVGridLines(false); list.back().setChartType(MyMoneyReport::eChartLine); list.back().setColumnsAreDays(true); list.back().setInvestmentsOnly(true); list.back().setIncludingBudgetActuals(false); list.back().setIncludingPrice(true); list.back().setConvertCurrency(true); list.back().setChartDataLabels(false); list.back().setSkipZero(true); list.back().setShowingColumnTotals(false); list.back().setShowingRowTotals(false); list.push_back(MyMoneyReport( MyMoneyReport::eAssetLiability, MyMoneyReport::eMonths, TransactionFilter::Date::Last12Months, MyMoneyReport::eDetailAll, i18n("Investment Moving Average Price Graph"), i18n("Default Report") )); list.back().setChartByDefault(true); list.back().setChartCHGridLines(false); list.back().setChartSVGridLines(false); list.back().setChartType(MyMoneyReport::eChartLine); list.back().setColumnsAreDays(true); list.back().setInvestmentsOnly(true); list.back().setIncludingBudgetActuals(false); list.back().setIncludingAveragePrice(true); list.back().setMovingAverageDays(10); list.back().setConvertCurrency(true); list.back().setChartDataLabels(false); list.back().setShowingColumnTotals(false); list.back().setShowingRowTotals(false); list.push_back(MyMoneyReport( MyMoneyReport::eAssetLiability, MyMoneyReport::eMonths, TransactionFilter::Date::Last30Days, MyMoneyReport::eDetailAll, i18n("Investment Moving Average"), i18n("Default Report") )); list.back().setChartCHGridLines(false); list.back().setChartSVGridLines(false); list.back().setChartType(MyMoneyReport::eChartLine); list.back().setColumnsAreDays(true); list.back().setInvestmentsOnly(true); list.back().setIncludingBudgetActuals(false); list.back().setIncludingMovingAverage(true); list.back().setMovingAverageDays(10); list.push_back(MyMoneyReport( MyMoneyReport::eAssetLiability, MyMoneyReport::eMonths, TransactionFilter::Date::Last30Days, MyMoneyReport::eDetailAll, i18n("Investment Moving Average vs Actual"), i18n("Default Report") )); list.back().setChartByDefault(true); list.back().setChartCHGridLines(false); list.back().setChartSVGridLines(false); list.back().setChartType(MyMoneyReport::eChartLine); list.back().setColumnsAreDays(true); list.back().setInvestmentsOnly(true); list.back().setIncludingBudgetActuals(true); list.back().setIncludingMovingAverage(true); list.back().setMovingAverageDays(10); groups.push_back(list); } { ReportGroup list("Taxes", i18n("Taxes")); list.push_back(MyMoneyReport( MyMoneyReport::eCategory, MyMoneyReport::eQCnumber | MyMoneyReport::eQCpayee | MyMoneyReport::eQCaccount, TransactionFilter::Date::YearToDate, MyMoneyReport::eDetailAll, i18n("Tax Transactions by Category"), i18n("Default Report") )); list.back().setTax(true); list.push_back(MyMoneyReport( MyMoneyReport::ePayee, MyMoneyReport::eQCnumber | MyMoneyReport::eQCcategory | MyMoneyReport::eQCaccount, TransactionFilter::Date::YearToDate, MyMoneyReport::eDetailAll, i18n("Tax Transactions by Payee"), i18n("Default Report") )); list.back().setTax(true); list.push_back(MyMoneyReport( MyMoneyReport::eCategory, MyMoneyReport::eQCnumber | MyMoneyReport::eQCpayee | MyMoneyReport::eQCaccount, TransactionFilter::Date::LastFiscalYear, MyMoneyReport::eDetailAll, i18n("Tax Transactions by Category Last Fiscal Year"), i18n("Default Report") )); list.back().setTax(true); list.push_back(MyMoneyReport( MyMoneyReport::ePayee, MyMoneyReport::eQCnumber | MyMoneyReport::eQCcategory | MyMoneyReport::eQCaccount, TransactionFilter::Date::LastFiscalYear, MyMoneyReport::eDetailAll, i18n("Tax Transactions by Payee Last Fiscal Year"), i18n("Default Report") )); list.back().setTax(true); groups.push_back(list); } { ReportGroup list("Budgeting", i18n("Budgeting")); list.push_back(MyMoneyReport( MyMoneyReport::eBudgetActual, MyMoneyReport::eMonths, TransactionFilter::Date::YearToDate, MyMoneyReport::eDetailAll, i18n("Budgeted vs. Actual This Year"), i18n("Default Report") )); list.back().setShowingRowTotals(true); list.back().setBudget("Any", true); list.push_back(MyMoneyReport( MyMoneyReport::eBudgetActual, MyMoneyReport::eMonths, TransactionFilter::Date::YearToMonth, MyMoneyReport::eDetailAll, i18n("Budgeted vs. Actual This Year (YTM)"), i18n("Default Report") )); list.back().setShowingRowTotals(true); list.back().setBudget("Any", true); // in case we're in January, we show the last year if (QDate::currentDate().month() == 1) { list.back().setDateFilter(TransactionFilter::Date::LastYear); } list.push_back(MyMoneyReport( MyMoneyReport::eBudgetActual, MyMoneyReport::eMonths, TransactionFilter::Date::CurrentMonth, MyMoneyReport::eDetailAll, i18n("Monthly Budgeted vs. Actual"), i18n("Default Report") )); list.back().setBudget("Any", true); list.push_back(MyMoneyReport( MyMoneyReport::eBudgetActual, MyMoneyReport::eMonths, TransactionFilter::Date::CurrentYear, MyMoneyReport::eDetailAll, i18n("Yearly Budgeted vs. Actual"), i18n("Default Report") )); list.back().setBudget("Any", true); list.back().setShowingRowTotals(true); list.push_back(MyMoneyReport( MyMoneyReport::eBudget, MyMoneyReport::eMonths, TransactionFilter::Date::CurrentMonth, MyMoneyReport::eDetailAll, i18n("Monthly Budget"), i18n("Default Report") )); list.back().setBudget("Any", false); list.push_back(MyMoneyReport( MyMoneyReport::eBudget, MyMoneyReport::eMonths, TransactionFilter::Date::CurrentYear, MyMoneyReport::eDetailAll, i18n("Yearly Budget"), i18n("Default Report") )); list.back().setBudget("Any", false); list.back().setShowingRowTotals(true); list.push_back(MyMoneyReport( MyMoneyReport::eBudgetActual, MyMoneyReport::eMonths, TransactionFilter::Date::CurrentYear, MyMoneyReport::eDetailGroup, i18n("Yearly Budgeted vs Actual Graph"), i18n("Default Report") )); list.back().setChartByDefault(true); list.back().setChartCHGridLines(false); list.back().setChartSVGridLines(false); list.back().setBudget("Any", true); list.back().setChartType(MyMoneyReport::eChartLine); groups.push_back(list); } { ReportGroup list("Forecast", i18n("Forecast")); list.push_back(MyMoneyReport( MyMoneyReport::eAssetLiability, MyMoneyReport::eMonths, TransactionFilter::Date::Next12Months, MyMoneyReport::eDetailTop, i18n("Forecast By Month"), i18n("Default Report") )); list.back().setIncludingForecast(true); list.push_back(MyMoneyReport( MyMoneyReport::eAssetLiability, MyMoneyReport::eMonths, TransactionFilter::Date::NextQuarter, MyMoneyReport::eDetailTop, i18n("Forecast Next Quarter"), i18n("Default Report") )); list.back().setColumnsAreDays(true); list.back().setIncludingForecast(true); list.push_back(MyMoneyReport( MyMoneyReport::eExpenseIncome, MyMoneyReport::eMonths, TransactionFilter::Date::CurrentYear, MyMoneyReport::eDetailTop, i18n("Income and Expenses Forecast This Year"), i18n("Default Report") )); list.back().setIncludingForecast(true); list.push_back(MyMoneyReport( MyMoneyReport::eAssetLiability, MyMoneyReport::eMonths, TransactionFilter::Date::Next3Months, MyMoneyReport::eDetailTotal, i18n("Net Worth Forecast Graph"), i18n("Default Report") )); list.back().setColumnsAreDays(true); list.back().setIncludingForecast(true); list.back().setChartByDefault(true); list.back().setChartCHGridLines(false); list.back().setChartSVGridLines(false); list.back().setChartType(MyMoneyReport::eChartLine); groups.push_back(list); } { ReportGroup list("Information", i18n("General Information")); list.push_back(MyMoneyReport( MyMoneyReport::eSchedule, MyMoneyReport::eMonths, TransactionFilter::Date::Next12Months, MyMoneyReport::eDetailAll, i18n("Schedule Information"), i18n("Default Report") )); list.back().setDetailLevel(MyMoneyReport::eDetailAll); list.push_back(MyMoneyReport( MyMoneyReport::eSchedule, MyMoneyReport::eMonths, TransactionFilter::Date::Next12Months, MyMoneyReport::eDetailAll, i18n("Schedule Summary Information"), i18n("Default Report") )); list.back().setDetailLevel(MyMoneyReport::eDetailTop); list.push_back(MyMoneyReport( MyMoneyReport::eAccountInfo, MyMoneyReport::eMonths, TransactionFilter::Date::Today, MyMoneyReport::eDetailAll, i18n("Account Information"), i18n("Default Report") )); list.back().setConvertCurrency(false); list.push_back(MyMoneyReport( MyMoneyReport::eAccountLoanInfo, MyMoneyReport::eMonths, TransactionFilter::Date::Today, MyMoneyReport::eDetailAll, i18n("Loan Information"), i18n("Default Report") )); list.back().setConvertCurrency(false); groups.push_back(list); } } bool KReportsView::columnsAlreadyAdjusted() { return m_columnsAlreadyAdjusted; } void KReportsView::setColumnsAlreadyAdjusted(bool adjusted) { m_columnsAlreadyAdjusted = adjusted; } void KReportsView::restoreTocExpandState(QMap& expandStates) { for (int i = 0; i < m_tocTreeWidget->topLevelItemCount(); i++) { QTreeWidgetItem* item = m_tocTreeWidget->topLevelItem(i); if (item) { QString itemLabel = item->text(0); if (expandStates.contains(itemLabel)) { item->setExpanded(expandStates[itemLabel]); } else { item->setExpanded(false); } } } } // Make sure, that these definitions are only used within this file // this does not seem to be necessary, but when building RPMs the // build option 'final' is used and all CPP files are concatenated. // So it could well be, that in another CPP file these definitions // are also used. #undef VIEW_LEDGER #undef VIEW_SCHEDULE #undef VIEW_WELCOME #undef VIEW_HOME #undef VIEW_REPORTS