Example #1
0
 def test_get_response(self):
     self.responses = ['']
     self.assertEqual(
         'preserve old value',
         Reconciler.get_response('prompt', 'preserve old value')
     )
     self.responses = ['new value']
     self.assertEqual(
         'new value',
         Reconciler.get_response('prompt', 'old value')
     )
Example #2
0
    def test_syntax_error(self):
        with FileTester.temp_input(testdata) as tempfilename:
            interpreter = Reconciler(LedgerFile(tempfilename, 'cash'))

        self.reset_redirect()
        bad_command = 'cthulu'
        interpreter.onecmd(bad_command)
        self.assertEqual(
            Reconciler.UNKNOWN_SYNTAX + bad_command,
            self.redirect.getvalue().rstrip()
        )
Example #3
0
    def test_get_key_and_cache_no_cache(self):

        assert not os.path.exists(FileTester.CACHE_FILE_TEST)

        with FileTester.temp_input(self.testcache) as tempfilename:
            recon = Reconciler(LedgerFile(tempfilename, 'cash'))

        assert not os.path.exists(FileTester.CACHE_FILE_TEST)

        key, cache = recon.get_key_and_cache()
        self.assertEqual('a: cash', key)
        self.assertEqual({}, cache)
Example #4
0
    def test_mark_and_unmark_all(self):

        with FileTester.temp_input(testdata) as tempfilename:
            recon = Reconciler(LedgerFile(tempfilename, 'cash'))

            self.verify_equal_floats(-15, recon.total_cleared)
            self.verify_equal_floats(-32.12, recon.total_pending)
            recon.do_unmark('all')
            self.verify_equal_floats(-15, recon.total_cleared)
            self.verify_equal_floats(0, recon.total_pending)
            recon.do_mark('all')
            self.verify_equal_floats(-15, recon.total_cleared)
            self.verify_equal_floats(-22.12, recon.total_pending)
Example #5
0
    def test_save_cache_error(self):

        with FileTester.temp_input(self.testcache) as tempfilename:
            recon = Reconciler(LedgerFile(tempfilename, 'cash'))

        self.reset_redirect()
        Reconciler.CACHE_FILE = '/not/a/real/path/dDFgMAEVRPcjMZ'
        recon.save_statement_info_to_cache()
        self.assertEqual(
            "Error writing reconciler cache: [Errno 2] No such file "
            "or directory: '/not/a/real/path/dDFgMAEVRPcjMZ'",
            self.redirect.getvalue().rstrip()
        )
Example #6
0
    def test_get_key_and_cache_error(self):

        with FileTester.temp_input(self.testcache) as tempfilename:
            recon = Reconciler(LedgerFile(tempfilename, 'cash'))

        self.reset_redirect()
        with open(Reconciler.CACHE_FILE, 'w') as cache_file:
            cache_file.write('bad json data')
        key, cache = recon.get_key_and_cache()
        self.assertEqual('a: cash', key)
        self.assertEqual({}, cache)
        self.assertEqual(
            'Error getting reconciler cache: '
            'No JSON object could be decoded.',
            self.redirect.getvalue().rstrip()
        )
Example #7
0
    def test_list(self):
        with FileTester.temp_input(testdata) as tempfilename:
            recon = Reconciler(LedgerFile(tempfilename, 'cash'))

        recon.do_list('')
        payees = {
            thing.payee for k, thing in
            recon.current_listing.iteritems()
        }
        # future items included only if pending ('three')
        self.assertEqual(
            ({'two', 'two pt five', 'three'}),
            payees
        )
        self.verify_equal_floats(-15, recon.total_cleared)
        self.verify_equal_floats(-32.12, recon.total_pending)
Example #8
0
    def process_file(self):

        if self.args.next_scheduled_date:
            if not self.args.schedule_file:
                print('error: -S/--schedule-file is required')
                return 8

            schedule_file = ScheduleFile(self.args.schedule_file)
            print(schedule_file.next_scheduled_date())
            return 0

        if not self.args.file:
            print('error: -f/--file is required')
            return 16

        try:
            ledgerfile = LedgerFile(self.args.file, self.args.reconcile)
        except LdgReconcilerMoreThanOneMatchingAccount as e:
            print('Reconcile error. More than one matching account:')
            for account in e.message:
                print('    ' + account)
            return 2
        except LdgReconcilerMultipleStatuses as e:
            print(str(e))
            return 4

        if self.args.schedule_file:
            schedule_file = ScheduleFile(self.args.schedule_file)
            scheduler = Scheduler(ledgerfile, schedule_file)
            scheduler.run()
            schedule_file.write_file()
            ledgerfile.write_file()

        if self.args.sort:
            ledgerfile.sort()
            ledgerfile.write_file()

        if self.args.reconcile:
            if ledgerfile.rec_account_matches:  # pragma: no cover
                reconciler = Reconciler(ledgerfile)
                reconciler.cmdloop()
            else:
                print('No matching account found for "{acct}"'.format(
                    acct=self.args.reconcile
                ))

        return 0
Example #9
0
    def test_simple_help_check(self):
        commands = [
            'help help',
            'help aliases',
            'help quit', 'help q', 'help EOF',
            'help list', 'help l', 'help ll',
            'help account',
            'help mark', 'help m',
            'help unmark', 'help u',
            'help start', 'help finish',
        ]
        with FileTester.temp_input(testdata) as tempfilename:
            interpreter = Reconciler(LedgerFile(tempfilename, 'cash'))

        for c in commands:
            self.reset_redirect()
            interpreter.onecmd(c)
            self.assertFalse(
                self.redirect.getvalue().startswith(Reconciler.NO_HELP)
            )
Example #10
0
    def test_cancel_statement(self):
        self.init_test('test_cancel_statement_stuff')

        with FileTester.temp_input(self.teststmt) as tempfilename:
            recon = Reconciler(LedgerFile(tempfilename, 'cash'))

        self.responses = ['2016/10/27', '50']
        recon.do_statement('')
        self.responses = ['cAnCeL']
        recon.do_statement('')
        self.assertIsNone(recon.ending_balance)
        print('<<< test: restart >>>')

        with FileTester.temp_input(self.teststmt) as tempfilename:
            recon = Reconciler(LedgerFile(tempfilename, 'cash'))

        self.assertIsNone(recon.ending_balance)
        self.responses = ['2016/10/28', '40']
        recon.do_statement('')
        self.responses = ['2016/10/28', 'cancel']
        recon.do_statement('')
        self.assertIsNone(recon.ending_balance)
Example #11
0
    def test_finish(self):
        self.init_test('test_reconcile_finish')

        with FileTester.temp_input(self.teststmt) as tempfilename:
            recon = Reconciler(LedgerFile(tempfilename, 'cash'))

            self.responses = ['2016/10/30', '-30']
            recon.do_statement('')
            recon.do_mark('1 2')
            recon.do_finish('')

        self.conclude_test(strip_ansi_color=True)
Example #12
0
    def test_list_all(self):
        with FileTester.temp_input(testdata) as tempfilename:
            recon = Reconciler(LedgerFile(tempfilename, 'cash'))

        recon.do_list('')
        payees = {
            thing.payee for k, thing in
            recon.current_listing.iteritems()
            }
        # future items included only if pending ('three')
        self.assertEqual(
            ({'two', 'two pt five', 'three'}),
            payees
        )
        recon.do_list('aLL')
        payees = {
            thing.payee for k, thing in
            recon.current_listing.iteritems()
            }
        self.assertEqual(
            ({'two', 'two pt five', 'three', 'four'}),
            payees
        )
Example #13
0
    def test_not_syntax_error(self):
        """ crudely verify basic commands """
        commands = [
            'help',
            'aliases',
            'quit', 'q', 'EOF',
            'account',
            'list', 'l', 'll',
            'mark', 'm',
            'unmark', 'u', 'un',
            # 'statement', 'start', # do not test here (need raw_input)
            'finish', 'end'
        ]
        with FileTester.temp_input(testdata) as tempfilename:
            interpreter = Reconciler(LedgerFile(tempfilename, 'cash'))

        for c in commands:
            self.reset_redirect()
            interpreter.onecmd(c)
            self.assertFalse(
                self.redirect.getvalue().startswith(
                    Reconciler.UNKNOWN_SYNTAX
                )
            )
Example #14
0
    def test_list_and_modify(self):

        with FileTester.temp_input(testdata) as tempfilename:
            recon = Reconciler(LedgerFile(tempfilename, 'cash'))
            self.verify_equal_floats(-15, recon.total_cleared)
            self.verify_equal_floats(-32.12, recon.total_pending)
            recon.do_list('')
            payees = {
                thing.payee for k, thing in
                recon.current_listing.iteritems()
                }
            self.assertEqual(
                ({'two', 'two pt five', 'three'}),
                payees
            )
            recon.do_unmark('3')

        # 3 was a pending future transaction, so:
        # pending total is adjusted and one less current listing
        # (also, the mark should have triggered a new listing...)
        payees = {
            thing.payee for k, thing in
            recon.current_listing.iteritems()
            }
        self.assertEqual(({'two', 'two pt five'}), payees)
        self.verify_equal_floats(-15, recon.total_cleared)
        self.verify_equal_floats(-2.12, recon.total_pending)

        # open transactions shouldn't change
        payees = {
            thing.payee for thing in recon.open_transactions
        }
        self.assertEqual(
            ({'two', 'two pt five', 'three', 'four'}),
            payees
        )
Example #15
0
    def test_setting_statement_date_and_balance(self):
        self.init_test('test_statement_stuff')

        with FileTester.temp_input(self.teststmt) as tempfilename:
            recon = Reconciler(LedgerFile(tempfilename, 'cash'))

        # errors and no change
        self.responses = ['blurg', '', 'abc', '']
        recon.do_statement('')
        # new settings
        self.responses = ['2016/10/30', '40']
        recon.do_statement('')
        # use $ symbol, no change
        self.responses = ['2016/10/30', '$40']
        recon.do_statement('')

        self.conclude_test(strip_ansi_color=True)
Example #16
0
    def test_finish_balancing_with_errors(self):
        """Verify things don't change when there are errors"""
        with FileTester.temp_input(testdata) as tempfilename:
            recon = Reconciler(LedgerFile(tempfilename, 'cash'))

            recon.finish_balancing()

            payees = {
                thing.payee for thing in recon.open_transactions
                }
            self.assertEqual(
                ({'two', 'two pt five', 'three', 'four'}),
                payees
            )
            payees = {
                thing.payee for k, thing in
                recon.current_listing.iteritems()
                }
            # future items included only if pending ('three')
            self.assertEqual(
                ({'two', 'two pt five', 'three'}),
                payees
            )

            recon.ending_balance = -1234.56
            recon.finish_balancing()

            self.assertEqual(-1234.56, recon.ending_balance)
            payees = {
                thing.payee for thing in recon.open_transactions
                }
            self.assertEqual(
                ({'two', 'two pt five', 'three', 'four'}),
                payees
            )
            payees = {
                thing.payee for k, thing in
                recon.current_listing.iteritems()
                }
            # future items included only if pending ('three')
            self.assertEqual(
                ({'two', 'two pt five', 'three'}),
                payees
            )
Example #17
0
    def test_mark_and_unmark_errors(self):

        with FileTester.temp_input(testdata) as tempfilename:
            recon = Reconciler(LedgerFile(tempfilename, 'cash'))

        self.reset_redirect()

        # none of these should result in a file write; we'll get out of
        # the context manager as an additional confirmation of this

        for command in [recon.do_mark, recon.do_unmark]:
            command('')
            self.assertEqual(
                '*** Transaction number(s) required',
                self.redirect.getvalue().rstrip()
            )
            self.reset_redirect()
            command('ahchew')
            self.assertEqual(
                'Transaction not found: ahchew',
                self.redirect.getvalue().rstrip()
            )
            self.reset_redirect()

        recon.do_list('')
        self.reset_redirect()

        recon.do_mark('2')
        self.assertEqual(
            'Already marked pending: 2',
            self.redirect.getvalue().rstrip()
        )
        self.reset_redirect()
        recon.do_unmark('1')
        self.assertEqual(
            "Not marked; can't unmark: 1",
            self.redirect.getvalue().rstrip()
        )
Example #18
0
    def test_finish_balancing_errors(self):

        with FileTester.temp_input(testdata) as tempfilename:
            recon = Reconciler(LedgerFile(tempfilename, 'cash'))

            self.reset_redirect()
            recon.finish_balancing()
            self.assertEqual(
                '*** Ending balance must be set in order to finish',
                self.redirect.getvalue().rstrip()
            )

            self.reset_redirect()
            recon.ending_balance = -1234.56
            recon.finish_balancing()
            self.assertEqual(
                '"To zero" must be zero in order to finish',
                self.redirect.getvalue().rstrip()
            )
            # confirms it didn't revert to None as on success
            self.assertEqual(-1234.56, recon.ending_balance)
Example #19
0
from reconciler import Reconciler

if __name__ == "__main__":
    r = Reconciler(
        gc={"token": ""},
        limit="finyear",
    )

    r.reconcile()
    r.export()
Example #20
0
    def test_cache(self):

        with FileTester.temp_input(self.testcache) as tempfilename:
            recon = Reconciler(LedgerFile(tempfilename, 'cash'))

        # saving cache with ending balance "None" causes cache entry to
        # be removed; first let's make sure it works w/o existing entry
        assert not os.path.exists(FileTester.CACHE_FILE_TEST)
        assert recon.ending_balance is None
        recon.save_statement_info_to_cache()
        key, cache = recon.get_key_and_cache()
        self.assertEqual({}, cache)

        # add entry
        recon.ending_balance = 100
        recon.ending_date = date(2020, 10, 20)
        recon.save_statement_info_to_cache()
        key, cache = recon.get_key_and_cache()
        self.assertEqual(
            {u'a: cash': {
                u'ending_balance': 100,
                u'ending_date': u'2020/10/20'
            }},
            cache
        )

        # remove entry
        recon.ending_balance = None
        recon.save_statement_info_to_cache()
        key, cache = recon.get_key_and_cache()
        self.assertEqual({}, cache)

        # multiple entries
        recon.ending_balance = 111
        recon.ending_date = date(2111, 11, 11)
        recon.save_statement_info_to_cache()

        with FileTester.temp_input(self.testcache) as tempfilename:
            recon = Reconciler(LedgerFile(tempfilename, 'credit'))

        recon.ending_balance = 222
        recon.ending_date = date(2222, 2, 22)
        recon.save_statement_info_to_cache()
        key, cache = recon.get_key_and_cache()
        self.assertEqual(
            {u'a: credit': {
                u'ending_balance': 222,
                u'ending_date': u'2222/02/22'
            }, u'a: cash': {
                u'ending_balance': 111,
                u'ending_date': u'2111/11/11'
            }},
            cache
        )

        # remove credit
        recon.ending_balance = None
        recon.save_statement_info_to_cache()
        key, cache = recon.get_key_and_cache()
        self.assertEqual(
            {u'a: cash': {
                u'ending_balance': 111,
                u'ending_date': u'2111/11/11'
            }},
            cache
        )

        # indirectly verify get_statement_info_from_cache
        with FileTester.temp_input(self.testcache) as tempfilename:
            recon = Reconciler(LedgerFile(tempfilename, 'cash'))

        # get_statement_info_from_cache will have been called in init
        self.assertEqual(111, recon.ending_balance)
        self.assertEqual(date(2111, 11, 11), recon.ending_date)
Example #21
0
    def test_mark_and_unmark(self):

        with FileTester.temp_input(testdata) as tempfilename:
            recon = Reconciler(LedgerFile(tempfilename, 'cash'))

            self.verify_equal_floats(-15, recon.total_cleared)
            self.verify_equal_floats(-32.12, recon.total_pending)
            recon.do_mark('1')
            self.verify_equal_floats(-15, recon.total_cleared)
            self.verify_equal_floats(-52.12, recon.total_pending)
            recon.do_unmark('1 2')
            self.verify_equal_floats(-15, recon.total_cleared)
            self.verify_equal_floats(-30, recon.total_pending)
            recon.do_mark('1 2')
            self.verify_equal_floats(-15, recon.total_cleared)
            self.verify_equal_floats(-52.12, recon.total_pending)
            recon.do_unmark('2')
            self.verify_equal_floats(-15, recon.total_cleared)
            self.verify_equal_floats(-50, recon.total_pending)
            recon.do_mark('1 2 blurg')
            self.verify_equal_floats(-15, recon.total_cleared)
            self.verify_equal_floats(-52.12, recon.total_pending)
            recon.do_unmark('blarg 2')
            self.verify_equal_floats(-15, recon.total_cleared)
            self.verify_equal_floats(-50, recon.total_pending)
            recon.do_unmark('1 sdjfkljsdfkljsdl 2')
            self.verify_equal_floats(-15, recon.total_cleared)
            self.verify_equal_floats(-30, recon.total_pending)
            recon.default('1')
            self.verify_equal_floats(-15, recon.total_cleared)
            self.verify_equal_floats(-50, recon.total_pending)

        # entry with account on multiple lines
        with FileTester.temp_input(testdata) as tempfilename:
            recon = Reconciler(LedgerFile(tempfilename, 'credit'))

            self.verify_equal_floats(0, recon.total_cleared)
            self.verify_equal_floats(0, recon.total_pending)
            recon.do_mark('1')
            self.verify_equal_floats(0, recon.total_cleared)
            self.verify_equal_floats(-33, recon.total_pending)
            recon.do_unmark('1')
            self.verify_equal_floats(0, recon.total_cleared)
            self.verify_equal_floats(0, recon.total_pending)
Example #22
0
 def test_get_response_with_none(self):
     """ None should be preserve for no response"""
     self.responses = ['']
     self.assertIsNone(Reconciler.get_response('prompt', None))
     self.responses = ['']
     self.assertEqual('', Reconciler.get_response('prompt', ''))
Example #23
0
    def cache_test(self, do_quit=True):
        self.init_test('test_reconciler_caching')

        with FileTester.temp_input(self.teststmt) as tempfilename:
            recon = Reconciler(LedgerFile(tempfilename, 'cash'))

        self.responses = ['2030/03/30', '-30']
        recon.do_statement('')
        if do_quit:
            recon.do_quit('')
        print('<<< test: restart >>>')

        with FileTester.temp_input(self.teststmt) as tempfilename:
            recon = Reconciler(LedgerFile(tempfilename, 'cash'))
            recon.do_mark('1 2')
            recon.do_finish('')

        if do_quit:
            recon.do_quit('')
        print('<<< test: restart >>>')

        with FileTester.temp_input(self.testfinish) as tempfilename:
            Reconciler(LedgerFile(tempfilename, 'cash'))

        self.conclude_test(strip_ansi_color=True)