/*
    SPDX-FileCopyrightText: 2003 Michael Edwardes <mte@users.sourceforge.net>
    SPDX-FileCopyrightText: 2006 Ace Jones <acejones@users.sourceforge.net>
    SPDX-FileCopyrightText: 2021 Thomas Baumgart <tbaumgart@kde.org>
    SPDX-License-Identifier: GPL-2.0-or-later
*/

#include "mymoneyschedule-test.h"

#include <QList>
#include <QTest>
#include <QDomDocument>
#include <QDomElement>

#define KMM_MYMONEY_UNIT_TESTABLE friend class MyMoneyScheduleTest;

#include "mymoneysplit.h"
#include "mymoneymoney.h"
#include "mymoneyschedule.h"
#include "mymoneyschedule_p.h"
#include "mymoneyfile.h"
#include "mymoneyexception.h"
#include "mymoneytransaction.h"
#include "mymoneytransaction_p.h"
#include "storage/mymoneystoragemgr.h"

QTEST_GUILESS_MAIN(MyMoneyScheduleTest)

using namespace eMyMoney;

void MyMoneyScheduleTest::testEmptyConstructor()
{
    MyMoneySchedule s;

    QCOMPARE(s.id().isEmpty(), true);
    QCOMPARE(s.baseOccurrence(), 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.baseOccurrence(), 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.d_func()->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.d_func()->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.d_func()->setId("SCHED001");
    s.setType(Schedule::Type::Bill);

    MyMoneySchedule s2 = s;

    QCOMPARE(s.id(), s2.id());
    QCOMPARE(s.type(), s2.type());
}

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::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<QDate> 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.occurrence(), Schedule::Occurrence::Once);
    s.setOccurrenceMultiplier(1);
    QCOMPARE(s.occurrenceMultiplier(), 1);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Once);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::Once);
    s.setOccurrenceMultiplier(2);
    QCOMPARE(s.occurrenceMultiplier(), 2);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Once);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::Once);

    s.setOccurrencePeriod(Schedule::Occurrence::Daily);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Daily);
    s.setOccurrenceMultiplier(1);
    QCOMPARE(s.occurrenceMultiplier(), 1);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Daily);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::Daily);
    s.setOccurrenceMultiplier(30);
    QCOMPARE(s.occurrenceMultiplier(), 30);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Daily);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::EveryThirtyDays);
    s.setOccurrenceMultiplier(2);
    QCOMPARE(s.occurrenceMultiplier(), 2);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Daily);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::Daily);

    s.setOccurrencePeriod(Schedule::Occurrence::Weekly);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Weekly);
    s.setOccurrenceMultiplier(1);
    QCOMPARE(s.occurrenceMultiplier(), 1);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Weekly);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::Weekly);
    s.setOccurrenceMultiplier(2);
    QCOMPARE(s.occurrenceMultiplier(), 2);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Weekly);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::EveryOtherWeek);
    s.setOccurrenceMultiplier(3);
    QCOMPARE(s.occurrenceMultiplier(), 3);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Weekly);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::EveryThreeWeeks);
    s.setOccurrenceMultiplier(4);
    QCOMPARE(s.occurrenceMultiplier(), 4);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Weekly);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::EveryFourWeeks);
    s.setOccurrenceMultiplier(5);
    QCOMPARE(s.occurrenceMultiplier(), 5);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Weekly);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::Weekly);
    s.setOccurrenceMultiplier(8);
    QCOMPARE(s.occurrenceMultiplier(), 8);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Weekly);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::EveryEightWeeks);

    s.setOccurrencePeriod(Schedule::Occurrence::EveryHalfMonth);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::EveryHalfMonth);
    s.setOccurrenceMultiplier(1);
    QCOMPARE(s.occurrenceMultiplier(), 1);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::EveryHalfMonth);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::EveryHalfMonth);
    s.setOccurrenceMultiplier(2);
    QCOMPARE(s.occurrenceMultiplier(), 2);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::EveryHalfMonth);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::EveryHalfMonth);

    s.setOccurrencePeriod(Schedule::Occurrence::Monthly);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Monthly);
    s.setOccurrenceMultiplier(1);
    QCOMPARE(s.occurrenceMultiplier(), 1);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Monthly);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::Monthly);
    s.setOccurrenceMultiplier(2);
    QCOMPARE(s.occurrenceMultiplier(), 2);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Monthly);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::EveryOtherMonth);
    s.setOccurrenceMultiplier(3);
    QCOMPARE(s.occurrenceMultiplier(), 3);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Monthly);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::EveryThreeMonths);
    s.setOccurrenceMultiplier(4);
    QCOMPARE(s.occurrenceMultiplier(), 4);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Monthly);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::EveryFourMonths);
    s.setOccurrenceMultiplier(5);
    QCOMPARE(s.occurrenceMultiplier(), 5);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Monthly);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::Monthly);
    s.setOccurrenceMultiplier(6);
    QCOMPARE(s.occurrenceMultiplier(), 6);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Monthly);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::TwiceYearly);

    s.setOccurrencePeriod(Schedule::Occurrence::Yearly);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Yearly);
    s.setOccurrenceMultiplier(1);
    QCOMPARE(s.occurrenceMultiplier(), 1);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Yearly);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::Yearly);
    s.setOccurrenceMultiplier(2);
    QCOMPARE(s.occurrenceMultiplier(), 2);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Yearly);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::EveryOtherYear);
    s.setOccurrenceMultiplier(3);
    QCOMPARE(s.occurrenceMultiplier(), 3);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Yearly);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::Yearly);

    // Set occurrence: check occurrence, Period and Multiplier
    s.setOccurrence(Schedule::Occurrence::Once);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::Once);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Once);
    QCOMPARE(s.occurrenceMultiplier(), 1);

    s.setOccurrence(Schedule::Occurrence::Daily);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::Daily);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Daily);
    QCOMPARE(s.occurrenceMultiplier(), 1);
    s.setOccurrence(Schedule::Occurrence::EveryThirtyDays);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::EveryThirtyDays);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Daily);
    QCOMPARE(s.occurrenceMultiplier(), 30);

    s.setOccurrence(Schedule::Occurrence::Weekly);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::Weekly);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Weekly);
    QCOMPARE(s.occurrenceMultiplier(), 1);
    s.setOccurrence(Schedule::Occurrence::EveryOtherWeek);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::EveryOtherWeek);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Weekly);
    QCOMPARE(s.occurrenceMultiplier(), 2);
    // Fortnightly no longer used: Every other week used instead
    s.setOccurrence(Schedule::Occurrence::Fortnightly);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::EveryOtherWeek);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Weekly);
    QCOMPARE(s.occurrenceMultiplier(), 2);
    s.setOccurrence(Schedule::Occurrence::EveryThreeWeeks);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::EveryThreeWeeks);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Weekly);
    QCOMPARE(s.occurrenceMultiplier(), 3);
    s.setOccurrence(Schedule::Occurrence::EveryFourWeeks);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::EveryFourWeeks);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Weekly);
    QCOMPARE(s.occurrenceMultiplier(), 4);
    s.setOccurrence(Schedule::Occurrence::EveryEightWeeks);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::EveryEightWeeks);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Weekly);
    QCOMPARE(s.occurrenceMultiplier(), 8);

    s.setOccurrence(Schedule::Occurrence::EveryHalfMonth);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::EveryHalfMonth);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::EveryHalfMonth);
    QCOMPARE(s.occurrenceMultiplier(), 1);

    s.setOccurrence(Schedule::Occurrence::Monthly);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::Monthly);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Monthly);
    QCOMPARE(s.occurrenceMultiplier(), 1);
    s.setOccurrence(Schedule::Occurrence::EveryOtherMonth);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::EveryOtherMonth);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Monthly);
    QCOMPARE(s.occurrenceMultiplier(), 2);
    s.setOccurrence(Schedule::Occurrence::EveryThreeMonths);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::EveryThreeMonths);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Monthly);
    QCOMPARE(s.occurrenceMultiplier(), 3);
    // Quarterly no longer used.  Every three months used instead
    s.setOccurrence(Schedule::Occurrence::Quarterly);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::EveryThreeMonths);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Monthly);
    QCOMPARE(s.occurrenceMultiplier(), 3);
    s.setOccurrence(Schedule::Occurrence::EveryFourMonths);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::EveryFourMonths);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Monthly);
    QCOMPARE(s.occurrenceMultiplier(), 4);
    s.setOccurrence(Schedule::Occurrence::TwiceYearly);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::TwiceYearly);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Monthly);
    QCOMPARE(s.occurrenceMultiplier(), 6);

    s.setOccurrence(Schedule::Occurrence::Yearly);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::Yearly);
    QCOMPARE(s.occurrence(), Schedule::Occurrence::Yearly);
    QCOMPARE(s.occurrenceMultiplier(), 1);
    s.setOccurrence(Schedule::Occurrence::EveryOtherYear);
    QCOMPARE(s.baseOccurrence(), Schedule::Occurrence::EveryOtherYear);
    QCOMPARE(s.occurrence(), 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()
{
    /// @todo extend test to cover application usage (with a processing calendar defined) ?

    // There should be no processing calendar defined so
    // make sure fall back works

    MyMoneySchedule s;
    // Check there is no processing calendar 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::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::testAdjustedNextPaymentOnLastDayInMonth()
{
    MyMoneySchedule s;

    QDate dueDate(2010, 5, 23);
    QDate adjustedDueDate(2010, 5, 21);
    s.setOccurrence(Schedule::Occurrence::Monthly);
    s.setWeekendOption(Schedule::WeekendOption::MoveBefore);
    auto t = s.transaction();
    t.setPostDate(QDate(2021, 12, 31));
    s.setTransaction(t);
    s.setLastPayment(QDate(2021, 12, 31));

    QCOMPARE(s.adjustedNextPayment(s.lastPayment()), QDate(2022, 1, 31));
}

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::testProcessLastDayInMonth()
{
    MyMoneySchedule s;
    // occurrence is unrelated
    s.setOccurrence(Schedule::Occurrence::Any);
    s.setLastDayInMonth(true);
    s.setNextDueDate(QDate(2010, 1, 1));
    QCOMPARE(s.nextDueDate(), QDate(2010, 1, 31));
    QCOMPARE(s.adjustedNextDueDate(), QDate(2010,1,31));
    s.setNextDueDate(QDate(2010, 2, 1));
    QCOMPARE(s.nextDueDate(), QDate(2010, 2, 28));
    QCOMPARE(s.adjustedNextDueDate(), QDate(2010,2,28));
    s.setNextDueDate(QDate(2016, 2, 1));
    QCOMPARE(s.nextDueDate(), QDate(2016, 2, 29));
    QCOMPARE(s.adjustedNextDueDate(), QDate(2016,2,29));
    s.setNextDueDate(QDate(2016, 4, 1));
    QCOMPARE(s.nextDueDate(), QDate(2016, 4, 30));
    QCOMPARE(s.adjustedNextDueDate(), QDate(2016,4,30));
    s.setLastDayInMonth(false);
    QCOMPARE(s.nextDueDate(), QDate(2016, 4, 1));
    QCOMPARE(s.adjustedNextDueDate(), QDate(2016,4,1));
}

void MyMoneyScheduleTest::testFixDate()
{
    MyMoneySchedule s;
    s.setStartDate(QDate(2021, 12, 17));

    s.setLastDayInMonth(false);
    QDate testDate(2022, 1, 31);
    s.fixDate(testDate);
    QCOMPARE(testDate, QDate(2022, 1, 17));

    s.setLastDayInMonth(true);
    testDate = QDate(2022, 1, 31);
    s.fixDate(testDate);
    QCOMPARE(testDate, QDate(2022, 1, 31));
}
