class TestRetrieveFromMultipleDuplicateSingleTransactions(unittest.TestCase):
    def setUp(self):
        self.ts = TransactionStore()

        t1 = Transaction(
            start=date.today(),
            description="Once, today",
            amount=1.00,
            frequency=Transaction.ONCE)

        t2 = Transaction(
            start=date.today()+timedelta(days=4),
            description="Once, today",
            amount=1.02,
            frequency=Transaction.ONCE)

        self.ts.addTransactions(t1, t2)

    def test_retrieve_no_date_given(self):
        t_list = self.ts.getTransaction("Once, today")
        self.assertEqual(len(t_list), 2)
        self.assertEqual(t_list[0].description, "Once, today")
        self.assertEqual(t_list[0].description, "Once, today")

    def test_retrieve_good_date_given(self):
        retrieve_date = date.today()
        t_list = self.ts.getTransaction("Once, today",
                                        requested_date=retrieve_date)
        self.assertEqual(len(t_list), 1)
        self.assertEqual(t_list[0].description, "Once, today")
        self.assertEqual(t_list[0].amount, 1.00)

        retrieve_date = date.today()+timedelta(days=4)
        t_list = self.ts.getTransaction("Once, today",
                                        requested_date=retrieve_date)
        self.assertEqual(len(t_list), 1)
        self.assertEqual(t_list[0].description, "Once, today")
        self.assertEqual(t_list[0].amount, 1.02)

    def test_retrieve_bad_date_given(self):
        retrieve_date = date.today() + timedelta(days=3)
        t_list = self.ts.getTransaction("Once, today",
                                        requested_date=retrieve_date)
        self.assertEqual(len(t_list), 0)
class TestBasicUpdate(unittest.TestCase):
    def setUp(self):
        self.ts = TransactionStore()

        t1 = Transaction(
            start=date.today(),
            description="Once",
            amount=1.00,
            frequency=Transaction.ONCE)

        self.ts.addTransactions(t1)

    def test_replace(self):
        ts = self.ts.getTransaction("Once")
        self.assertEqual(len(ts), 1)
        t1 = ts[0]
        t2 = t1.duplicate()
        t2.description = "Once replaced"
        self.ts.replaceTransaction(t1, t2)
        t_old = self.ts.getTransaction("Once")
        self.assertEqual(len(t_old), 0)
        t_new = self.ts.getTransaction("Once replaced")
        self.assertEqual(len(t_new), 1)
class TestRetrieveFromMultipleRecurringTransactions(unittest.TestCase):
    def setUp(self):
        self.ts = TransactionStore()

        sd = date.today()
        skipd = date.today() + timedelta(days=14)
        t1 = Transaction(
            start=sd,
            description="Weekly",
            amount=1.00,
            frequency=Transaction.WEEKLY,
            skip=set([skipd]))
        t2 = Transaction(
            start=sd+timedelta(days=2),
            description="Monthly",
            amount=1.01,
            frequency=Transaction.MONTHLY)

        self.ts.addTransactions(t1, t2)

    def test_retrieve_non_existent_transaction(self):
        t_list = self.ts.getTransaction("Transaction does not exist")
        self.assertEqual(len(t_list), 0)

    def test_retrieve_no_date_given(self):
        t_list = self.ts.getTransaction("Weekly")
        self.assertEqual(len(t_list), 1)
        self.assertEqual(t_list[0].description, "Weekly")

    def test_retrieve_good_start_date_given(self):
        retrieve_date = date.today()
        t_list = self.ts.getTransaction("Weekly",
                                        requested_date=retrieve_date)
        self.assertEqual(len(t_list), 1)
        self.assertEqual(t_list[0].description, "Weekly")
        self.assertEqual(t_list[0].amount, 1.00)

    def test_retrieve_good_future_date_given(self):
        retrieve_date = date.today() + timedelta(days=21)
        t_list = self.ts.getTransaction("Weekly",
                                        requested_date=retrieve_date)
        self.assertEqual(len(t_list), 1)
        self.assertEqual(t_list[0].description, "Weekly")
        self.assertEqual(t_list[0].amount, 1.00)

    def test_retrieve_skip_date_given(self):
        retrieve_date = date.today() + timedelta(days=14)
        t_list = self.ts.getTransaction("Weekly",
                                        requested_date=retrieve_date)
        self.assertEqual(len(t_list), 0)

    def test_retrieve_bad_date_given(self):
        retrieve_date = date.today() + timedelta(days=3)
        t_list = self.ts.getTransaction("Weekly",
                                        requested_date=retrieve_date)
        self.assertEqual(len(t_list), 0)
class TestUtilityFunctions(unittest.TestCase):
    def setUp(self):
        self.ts = TransactionStore()

        origsd1 = date.today()
        origsd2 = date.today()+timedelta(days=2)
        self.t1 = Transaction(
            start=origsd1,
            description="Once, today",
            amount=1.00,
            frequency=Transaction.ONCE)
        self.t2 = Transaction(
            start=origsd2,
            description="Once, in two days",
            amount=1.01,
            frequency=Transaction.ONCE)
        self.t3 = Transaction(
            start=origsd1,
            description="Weekly",
            amount=1.02,
            frequency=Transaction.WEEKLY,
            skip=set([date.today()+timedelta(days=7)]),
            scheduled=True,
            cleared=True)
        self.t4 = Transaction(
            start=origsd2,
            description="Monthly",
            amount=1.03,
            frequency=Transaction.MONTHLY)

        self.ts.addTransactions(self.t1, self.t2, self.t3, self.t4)

    def test_update_all_recurring_start_dates(self):
        origsd1 = date.today()
        origsd2 = date.today()+timedelta(days=2)
        new_sd = date.today() + timedelta(days=10)
        new_weekly_sd = origsd1 + timedelta(days=14)
        new_monthly_sd = origsd2 + relativedelta(months=1)

        self.ts.updateRecurringStartDates(new_sd)

        self.assertEqual(self.t1.start, origsd1)
        self.assertEqual(self.t1.original_start, origsd1)
        self.assertEqual(self.t2.start, origsd2)
        self.assertEqual(self.t2.original_start, origsd2)
        self.assertEqual(self.t3.start, new_weekly_sd)
        self.assertEqual(self.t3.original_start, origsd1)
        self.assertEqual(self.t4.start, new_monthly_sd)
        self.assertEqual(self.t4.original_start, origsd2)

    def test_purge_outdated_single_transactions(self):
        purge_date = date.today() + timedelta(days=1)

        self.assertEqual(len(self.ts.store), 4)
        self.ts.purgeSingleBefore(purge_date)
        self.assertEqual(len(self.ts.store), 3)
        exp_set = set([self.t2, self.t3, self.t4])
        act_set = set(self.ts.store)
        self.assertEqual(exp_set.symmetric_difference(act_set), set())
        t_list = self.ts.getTransaction("Once, in two days")
        self.assertEqual(len(t_list), 1)
class TestBasicDelete(unittest.TestCase):
    def setUp(self):
        self.ts = TransactionStore()

        t1 = Transaction(
            start=date.today(),
            description="Once",
            amount=1.00,
            frequency=Transaction.ONCE)
        t2 = Transaction(
            start=date.today()+timedelta(days=2),
            description="Once, in two days",
            amount=1.01,
            frequency=Transaction.ONCE)
        t3 = Transaction(
            start=date.today(),
            end=date.today()+timedelta(days=56),
            description="Weekly",
            amount=1.02,
            frequency=Transaction.WEEKLY,
            skip=set([date.today()+timedelta(days=7)]),
            scheduled=True,
            cleared=True)

        self.ts.addTransactions(t1, t2, t3)

    def test_remove_existing_single_transaction(self):
        self.assertEqual(len(self.ts.store), 3)
        t_list = self.ts.getTransaction("Once")
        self.assertEqual(len(t_list), 1)
        t1 = t_list[0]
        self.ts.removeTransactions(t1)
        self.assertEqual(len(self.ts.store), 2)
        t_list = self.ts.getTransaction("Once")
        self.assertEqual(len(t_list), 0)

    def test_remove_existing_multiple_transactions(self):
        self.assertEqual(len(self.ts.store), 3)
        t_list = self.ts.getTransaction("Once")
        self.assertEqual(len(t_list), 1)
        t1 = t_list[0]
        t_list = self.ts.getTransaction("Weekly")
        self.assertEqual(len(t_list), 1)
        t2 = t_list[0]
        self.ts.removeTransactions(t1, t2)
        self.assertEqual(len(self.ts.store), 1)
        t_list = self.ts.getTransaction("Once")
        self.assertEqual(len(t_list), 0)
        t_list = self.ts.getTransaction("Weekly")
        self.assertEqual(len(t_list), 0)

    def test_remove_non_existent_single_transaction(self):
        t_missing = Transaction(
                start=date.today(),
                description="Missing",
                amount=1.00,
                frequency=Transaction.ONCE)
        self.assertEqual(len(self.ts.store), 3)
        self.ts.removeTransactions(t_missing)
        self.assertEqual(len(self.ts.store), 3)

    def test_remove_multiple_transactions_with_some_missing(self):
        t_missing = Transaction(
                start=date.today(),
                description="Missing",
                amount=1.00,
                frequency=Transaction.ONCE)

        self.assertEqual(len(self.ts.store), 3)
        t_list = self.ts.getTransaction("Once")
        self.assertEqual(len(t_list), 1)
        t1 = t_list[0]
        t_list = self.ts.getTransaction("Weekly")
        self.assertEqual(len(t_list), 1)
        t2 = t_list[0]
        self.ts.removeTransactions(t1, t2, t_missing)
        self.assertEqual(len(self.ts.store), 1)
        t_list = self.ts.getTransaction("Once")
        self.assertEqual(len(t_list), 0)
        t_list = self.ts.getTransaction("Weekly")
        self.assertEqual(len(t_list), 0)