Example #1
0
 def option(self):
     flag = True
     while flag:
         print("Choose one of the following options to continue:")
         print("1 - show all data")
         print("2 - show data for specific date")
         print("3 - show expenses, ordered by categories")
         print("4 - add new income")
         print("5 - add new expense")
         print("6 - exit")
         choice = input()
         if choice == '1':
             obj = MoneyTracker(self.AggregatedObject)
             obj.list_user_data()
         if choice == '2':
             date = input()
             obj = MoneyTracker(self.AggregatedObject)
             obj.show_user_data_per_date(date)
         if choice == '3':
             obj = MoneyTracker(self.AggregatedObject)
             print(obj.list_user_expenses_ordered_by_categories())
         if choice == '4':
             print("New income amount:")
             money = input()
             if int(money) < 0:
                 raise CustomError('enter a valid amount')
             print("New income type:")
             income_category = input()
             print("New income date:")
             date = input()
             obj = MoneyTracker(self.AggregatedObject)
             i = Income(int(money), income_category, date)
             obj.add_income(i)
             # for el in obj.AggregatedObject.incomes:
             #   print(el)
         if choice == '5':
             print("New expense amount:")
             money = input()
             if int(money) < 0:
                 raise CustomError('enter a valid amount')
             print("New expense type:")
             expense_category = input()
             print("New expense date:")
             date = input()
             obj = MoneyTracker(self.AggregatedObject)
             i = Expense(int(money), expense_category, date)
             obj.add_expense(i)
             # for el in obj.AggregatedObject.expenses:
             #   print(el)
         if choice == '6':
             flag = False
         if choice not in ('1', '2', '3', '4', '5', '6'):
             raise Exception('Invalid input')
class MoneyTrackerMenu:
    def __init__(self, name):
        print(f'Hello, {name}!')
        self.option = 0
        self.parser = Parser("money_tracker.txt")
        self.parser.make_rows()
        self.agg = AggregatedMoneyTraker(self.parser)
        self.agg.generate_categories_from_parser()
        self.mt = MoneyTracker(self.agg)

    def start(self):

        while True:
            self.option = int(input("""Choose one of the following options to continue:
1 - show all data
2 - show data for specific date
3 - show expenses, ordered by categories
4 - add new income
5 - add new expense
6 - exit
"""))
            if type(self.option) is not int:
                raise TypeError
            if self.option < 1 or self.option > 6:
                raise ValueError

            if self.option == 1:
                print(self.mt.show_user_data())
            elif self.option == 2:
                date = input("Enter date: ")
                print(self.mt.show_user_data_for_specific_date(date))
            elif self.option == 3:
                print(self.mt.show_user_expenses_ordered_by_categories())
            elif self.option == 4:
                amount = float(input("New income amount: "))
                name = input("New income type: ")
                date = input("New income date: ")
                self.mt.add_income(amount, name, date)
            elif self.option == 5:
                amount = float(input("New expense amount: "))
                name = input("New expense type: ")
                date = input("New expense date: ")
                self.mt.add_expense(amount, name, date)
            if self.option == 6:
                self.mt.save()
                exit()
class MoneyTrackerMenu:
    def __init__(self):
        os.system('clear')
        self._user_name = input('Enter user name:')
        self.initialize_file_and_money_tracker()
        self.initialize_options()
        self.date_message = '(Format of the date is DD,MM,YYYY)\nEnter date:'

    def initialize_file_and_money_tracker(self):
        information_entered = False
        while information_entered is False:
            try:
                self._file_with_data = input('Enter file to load:')
                self._money_tracker = MoneyTracker(self._file_with_data)
                information_entered = True
                os.system('clear')
            except Exception:
                print('The file name is incorect or its content is invalid!')

    def initialize_options(self):
        self.options = ['1', '2', '3', '4', '5', '6', '7']
        self.options_functions = [
            self.option_one, self.option_two, self.option_three,
            self.option_four, self.option_five, self.option_six,
            self.option_seven
        ]

    def start(self):
        self.working = True
        option_chosen = ''
        while self.working is True:
            self.print_menu_options()
            option_chosen = input()
            if option_chosen not in self.options:
                print('Invalid option, try again!')
            else:
                self.options_functions[int(option_chosen) - 1]()
            if self.working is True:
                input('Press enter to continue:')
            os.system('clear')

    def print_menu_options(self):
        print(f'Hello, {self._user_name}!\n'
              'Choose one of the following options to continue:\n'
              '1 - show all data\n'
              '2 - show data for specific date\n'
              '3 - show expenses, ordered by categories\n'
              '4 - add new income\n'
              '5 - add new expense\n'
              '6 - exit without saving\n'
              '7 - exit and save\n')

    def option_one(self):
        print(self._money_tracker.list_user_data())

    def option_two(self):
        try:
            day, month, year = self.date_parser(input(self.date_message))
            print(self._money_tracker.show_user_data_per_date(
                day, month, year))
        except ValueError as ex:
            print(f'\nError!\n{ex}\n')

    def option_three(self):
        print(self._money_tracker.list_user_exepences_ordered_by_categories())

    def option_four(self):
        try:
            day, month, year = self.date_parser(input(self.date_message))
            category = input('Category of income:')
            amount = self.amount_parser(input('Amount of income:'))
            self._money_tracker.add_income(day, month, year, category, amount)
        except ValueError as ex:
            print(f'\nError!\n{ex}\n')

    def option_five(self):
        try:
            day, month, year = self.date_parser(input(self.date_message))
            category = input('Category of expence:')
            amount = self.amount_parser(input('Amount of expense:'))
            self._money_tracker.add_expence(day, month, year, category, amount)
        except ValueError as ex:
            print(f'\nError!\n{ex}\n')

    def option_six(self):
        self.working = False

    def option_seven(self):
        self.working = False
        self.save_data_in_a_file()

    def save_data_in_a_file(self):
        with open(self._file_with_data, 'w') as f:
            f.write(self._money_tracker.list_user_data())

    @staticmethod
    def date_parser(date):
        if re.match(r'\d{1,2},\d{1,2},\d{4}', date) is None:
            raise ValueError('The date is invalid!')
        parts = date.split(',')
        return int(parts[0]), int(parts[1]), int(parts[2])

    @staticmethod
    def amount_parser(amount):
        try:
            checked_amount = float(amount)
            return checked_amount
        except Exception:
            raise ValueError('The amount should be a number!')
class MoneyTrackerTests(unittest.TestCase):
    def setUp(self):
        self.categories = [
            Income('760', 'Salary'),
            Expense('5.5', 'Eating Out'),
            Expense('34', 'Clothes'),
            Income('50', 'Savings')
        ]
        self.strings = [
            '760, Salary, New Income', '5.5, Eating Out, New Expense',
            '34, Clothes, New Expense', '50, Savings, New Income'
        ]

        self.strings1 = [
            '50, Savings, New Income', '15, Food, New Expense',
            '200, Deposit, New Income', '5, Sports, New Expense'
        ]

        self.categories1 = [
            Income('50', 'Savings'),
            Expense('15', 'Food'),
            Income('200', 'Deposit'),
            Expense('5', 'Sports')
        ]
        self.aggregator1 = AggregateData({
            '=== 22-03-2018 ===': self.strings,
            '=== 23-03-2018 ===': self.strings1
        })
        self.tracker1 = MoneyTracker(self.aggregator1)

    def test_list_user_expenses_ordered_by_categories(self):
        result = [
            self.categories[2], self.categories[1], self.categories1[1],
            self.categories1[3]
        ]
        self.assertEqual(
            self.tracker1.list_user_expenses_ordered_by_categories(), result)

    def test_list_income_categories(self):
        result = [
            self.categories[0], self.categories[3], self.categories1[0],
            self.categories1[2]
        ]
        self.assertEqual(self.tracker1.list_income_categories(), result)

    def test_list_expense(self):
        result = [
            self.categories[1], self.categories[2], self.categories1[1],
            self.categories1[3]
        ]
        self.assertEqual(self.tracker1.list_expense_categories(), result)

    def test_add_income(self):
        with self.subTest("with new date"):
            data = self.tracker1.list_user_data()
            self.tracker1.add_income("Stipendiq", 100, '22-03-2018')
            self.assertTrue(
                Income(100, "Stipendiq") in data['=== 22-03-2018 ==='])

        with self.subTest("with old date"):
            data = self.tracker1.list_user_data()
            self.tracker1.add_expense("Tototo", 1.5, '22-03-2018')
            self.assertTrue(
                Income(1.5, "Tototo") in data['=== 22-03-2018 ==='])

    def test_add_expense(self):
        with self.subTest("with new date"):
            data = self.tracker1.list_user_data()
            self.tracker1.add_expense("Kniga", 17, '22-03-9999')
            self.assertTrue(Expense(17, "Kniga") in data['=== 22-03-9999 ==='])

        with self.subTest("with old date"):
            data = self.tracker1.list_user_data()
            self.tracker1.add_expense("Kola", 155.5, '22-03-2018')
            self.assertTrue(
                Expense(155.5, "Kola") in data['=== 22-03-2018 ==='])
class MoneyTrakerTests(unittest.TestCase):
    def setUp(self):
        self.par = Parser("money_tracker.txt")
        self.par.make_rows()
        self.agg = AggregatedMoneyTraker(self.par)
        self.agg.generate_categories_from_parser()
        self.mt = MoneyTracker(self.agg)

    def test_init_money_tracker(self):
        with self.assertRaises(TypeError):
            MoneyTracker(self.par)

    def test_show_user_data(self):
        expected = "\n".join(['=== 22-03-2018 ===', '760, Salary, New Income',
                              '5.5, Eating Out, New Expense',
                              '34, Clothes, New Expense',
                              '41.79, Food, New Expense',
                              '12, Eating Out, New Expense',
                              '7, House, New Expense', '14, Pets, New Expense',
                              '112.4, Bills, New Expense',
                              '21.5, Transport, New Expense',
                              '=== 23-03-2018 ===', '50, Savings, New Income',
                              '15, Food, New Expense',
                              '200, Deposit, New Income',
                              '5, Sports, New Expense'])
        actual = self.mt.show_user_data()
        self.assertEqual(actual, expected)

    def test_show_user_data_for_specific_date(self):
        date = '22-03-2018'
        expected = "\n".join(['760, Salary, New Income',
                              '5.5, Eating Out, New Expense',
                              '34, Clothes, New Expense',
                              '41.79, Food, New Expense',
                              '12, Eating Out, New Expense',
                              '7, House, New Expense', '14, Pets, New Expense',
                              '112.4, Bills, New Expense',
                              '21.5, Transport, New Expense'])
        actual = self.mt.show_user_data_for_specific_date(date)
        self.assertEqual(actual, expected)

    def test_show_user_expenses_ordered_by_categories(self):
        expected = "\n".join(['112.4, Bills, New Expense',
                              '34, Clothes, New Expense',
                              '5.5, Eating Out, New Expense',
                              '12, Eating Out, New Expense',
                              '41.79, Food, New Expense',
                              '15, Food, New Expense',
                              '7, House, New Expense',
                              '14, Pets, New Expense',
                              '5, Sports, New Expense',
                              '21.5, Transport, New Expense'])
        actual = self.mt.show_user_expenses_ordered_by_categories()
        self.assertEqual(actual, expected)

    def test_list_incomes(self):
        expected = "\n".join(['760, Salary, New Income',
                              '50, Savings, New Income',
                              '200, Deposit, New Income'])
        actual = self.mt.list_incomes()
        self.assertEqual(actual, expected)

    def test_list_expenses(self):
        expected = "\n".join(['5.5, Eating Out, New Expense',
                              '34, Clothes, New Expense',
                              '41.79, Food, New Expense',
                              '12, Eating Out, New Expense',
                              '7, House, New Expense',
                              '14, Pets, New Expense',
                              '112.4, Bills, New Expense',
                              '21.5, Transport, New Expense',
                              '15, Food, New Expense',
                              '5, Sports, New Expense'])
        actual = self.mt.list_expenses()
        self.assertEqual(actual, expected)

    def test_add_income(self):
        expected = ['=== 22-03-2018 ===',
                    '350, Savings, New Income',
                    '760, Salary, New Income',
                    '5.5, Eating Out, New Expense',
                    '34, Clothes, New Expense',
                    '41.79, Food, New Expense',
                    '12, Eating Out, New Expense',
                    '7, House, New Expense',
                    '14, Pets, New Expense',
                    '112.4, Bills, New Expense',
                    '21.5, Transport, New Expense',
                    '=== 23-03-2018 ===',
                    '50, Savings, New Income',
                    '15, Food, New Expense',
                    '200, Deposit, New Income',
                    '5, Sports, New Expense']
        amount = 350
        name = "Savings"
        date = '22-03-2018'
        self.mt.add_income(amount, name, date)
        actual = self.mt.aggregated.data
        self.assertEqual(actual, expected)

    def test_add_expense(self):
        expected = ['=== 22-03-2018 ===',
                    '760, Salary, New Income',
                    '5.5, Eating Out, New Expense',
                    '34, Clothes, New Expense',
                    '41.79, Food, New Expense',
                    '12, Eating Out, New Expense',
                    '7, House, New Expense',
                    '14, Pets, New Expense',
                    '112.4, Bills, New Expense',
                    '21.5, Transport, New Expense',
                    '=== 23-03-2018 ===',
                    '50, Food, New Expense',
                    '50, Savings, New Income',
                    '15, Food, New Expense',
                    '200, Deposit, New Income',
                    '5, Sports, New Expense']
        amount = 50
        name = "Food"
        date = '23-03-2018'
        self.mt.add_expense(amount, name, date)
        actual = self.mt.aggregated.data
        self.assertEqual(actual, expected)