__copyright__ = 'Copyright (c) 2020 Kristóf Marussy <kristof@marussy.com>'
__license__ = 'GNU GPLv2'
import unittest
from beancount.loader import load_doc
from beancount.parser import cmptest
class TestTransferAccounts(cmptest.TestCase):
@load_doc()
def test_same_currency(self, entries, _, __):
'''
plugin "beancount_extras_kris7t.plugins.transfer_accounts"
2020-01-01 open Assets:Checking
2020-01-01 open Liabilities:CreditCard
2020-01-01 open Expenses:Taxi
2020-03-15 * "Taxi home from concert in Brooklyn" ^taxi
Assets:Checking -20 USD
Expenses:Taxi
transfer-account: Liabilities:CreditCard
transfer-date: 2020-03-10
'''
self.assertEqualEntries('''
plugin "beancount_extras_kris7t.plugins.transfer_accounts"
2020-01-01 open Assets:Checking
2020-01-01 open Liabilities:CreditCard
2020-01-01 open Expenses:Taxi
2020-03-15 * "Taxi home from concert in Brooklyn" ^taxi
Assets:Checking -20 USD
Liabilities:CreditCard 20 USD
2020-03-10 * "Taxi home from concert in Brooklyn" ^taxi
Expenses:Taxi 20 USD
Liabilities:CreditCard -20 USD
''', entries)
@load_doc()
def test_missing_date(self, entries, _, __):
'''
plugin "beancount_extras_kris7t.plugins.transfer_accounts"
2020-01-01 open Assets:Checking
2020-01-01 open Liabilities:CreditCard
2020-01-01 open Expenses:Taxi
2020-03-15 * "Taxi home from concert in Brooklyn" ^taxi
Assets:Checking -20 USD
Expenses:Taxi
transfer-account: Liabilities:CreditCard
'''
self.assertEqualEntries('''
plugin "beancount_extras_kris7t.plugins.transfer_accounts"
2020-01-01 open Assets:Checking
2020-01-01 open Liabilities:CreditCard
2020-01-01 open Expenses:Taxi
2020-03-15 * "Taxi home from concert in Brooklyn" ^taxi
Assets:Checking -20 USD
Liabilities:CreditCard 20 USD
2020-03-15 * "Taxi home from concert in Brooklyn" ^taxi
Expenses:Taxi 20 USD
Liabilities:CreditCard -20 USD
''', entries)
@load_doc(expect_errors=True)
def test_missing_account_with_date(self, _, errors, __):
'''
plugin "beancount_extras_kris7t.plugins.transfer_accounts"
2020-01-01 open Assets:Checking
2020-01-01 open Liabilities:CreditCard
2020-01-01 open Expenses:Taxi
2020-03-15 * "Taxi home from concert in Brooklyn" ^taxi
Assets:Checking -20 USD
Expenses:Taxi
transfer-date: 2020-03-10
'''
self.assertRegex(errors[0].message, 'transfer-date was set but transfer-account was not')
@load_doc(expect_errors=True)
def test_missing_account_with_conversion(self, _, errors, __):
'''
plugin "beancount_extras_kris7t.plugins.transfer_accounts"
2020-01-01 open Assets:Checking
2020-01-01 open Liabilities:CreditCard
2020-01-01 open Expenses:Taxi
2020-03-15 * "Taxi home from concert in Brooklyn" ^taxi
Assets:Checking -25.60 CAD
Expenses:Taxi 20 USD @ 1.28 CAD
transfer-converted: FALSE
'''
self.assertRegex(
errors[0].message, 'transfer-converted was set but transfer-account was not')
@load_doc(expect_errors=True)
def test_invalid_account(self, _, errors, __):
'''
plugin "beancount_extras_kris7t.plugins.transfer_accounts"
2020-01-01 open Assets:Checking
2020-01-01 open Liabilities:CreditCard
2020-01-01 open Expenses:Taxi
2020-03-15 * "Taxi home from concert in Brooklyn" ^taxi
Assets:Checking -20 USD
Expenses:Taxi
transfer-account: 2020-03-10
'''
self.assertRegex(errors[0].message, 'transfer-account must be a string.*')
@load_doc(expect_errors=True)
def test_invalid_date(self, _, errors, __):
'''
plugin "beancount_extras_kris7t.plugins.transfer_accounts"
2020-01-01 open Assets:Checking
2020-01-01 open Liabilities:CreditCard
2020-01-01 open Expenses:Taxi
2020-03-15 * "Taxi home from concert in Brooklyn" ^taxi
Assets:Checking -20 USD
Expenses:Taxi
transfer-account: Liabilities:CreditCard
transfer-date: "Ides of March"
'''
self.assertRegex(errors[0].message, 'transfer-date must be a date.*')
@load_doc(expect_errors=True)
def test_invalid_conversion(self, _, errors, __):
'''
plugin "beancount_extras_kris7t.plugins.transfer_accounts"
2020-01-01 open Assets:Checking
2020-01-01 open Liabilities:CreditCard
2020-01-01 open Expenses:Taxi
2020-03-15 * "Taxi home from concert in Brooklyn" ^taxi
Assets:Checking -25.60 CAD
Expenses:Taxi 20 USD @ 1.28 CAD
transfer-account: Liabilities:CreditCard
transfer-converted: "indeed"
'''
self.assertRegex(errors[0].message, 'transfer-converted must be a Boolean.*')
@load_doc(expect_errors=True)
def test_invalid_account_conversion(self, _, errors, __):
'''
plugin "beancount_extras_kris7t.plugins.transfer_accounts"
2020-01-01 open Liabilities:CreditCard
transfer-converted: "Indeed"
'''
self.assertRegex(errors[0].message, 'transfer-converted must be a Boolean.*')
@load_doc(expect_errors=True)
def test_redundant_conversion(self, _, errors, __):
'''
plugin "beancount_extras_kris7t.plugins.transfer_accounts"
2020-01-01 open Assets:Checking
2020-01-01 open Liabilities:CreditCard
2020-01-01 open Expenses:Taxi
2020-03-15 * "Taxi home from concert in Brooklyn" ^taxi
Assets:Checking -20 USD
Expenses:Taxi
transfer-account: Liabilities:CreditCard
transfer-converted: TRUE
'''
self.assertRegex(
errors[0].message, 'transfer-converted was set, but there is no conversion.*')
@load_doc()
def test_converted_price_false(self, entries, _, __):
'''
plugin "beancount_extras_kris7t.plugins.transfer_accounts"
2020-01-01 open Assets:Checking
2020-01-01 open Liabilities:CreditCard
2020-01-01 open Expenses:Taxi
2020-03-15 * "Taxi home from concert in Brooklyn" ^taxi
Assets:Checking -25.60 CAD
Expenses:Taxi 20 USD @ 1.28 CAD
transfer-account: Liabilities:CreditCard
transfer-date: 2020-03-10
transfer-converted: FALSE
'''
self.assertEqualEntries('''
plugin "beancount_extras_kris7t.plugins.transfer_accounts"
2020-01-01 open Assets:Checking
2020-01-01 open Liabilities:CreditCard
2020-01-01 open Expenses:Taxi
2020-03-15 * "Taxi home from concert in Brooklyn" ^taxi
Assets:Checking -25.60 CAD
Liabilities:CreditCard 25.60 CAD
2020-03-10 * "Taxi home from concert in Brooklyn" ^taxi
Expenses:Taxi 20 USD @ 1.28 CAD
Liabilities:CreditCard -25.60 CAD
''', entries)
@load_doc()
def test_converted_price_true(self, entries, _, __):
'''
plugin "beancount_extras_kris7t.plugins.transfer_accounts"
2020-01-01 open Assets:Checking
2020-01-01 open Liabilities:CreditCard
2020-01-01 open Expenses:Taxi
2020-03-15 * "Taxi home from concert in Brooklyn" ^taxi
Assets:Checking -25.60 CAD
Expenses:Taxi 20 USD @ 1.28 CAD
transfer-account: Liabilities:CreditCard
transfer-date: 2020-03-10
transfer-converted: TRUE
'''
self.assertEqualEntries('''
plugin "beancount_extras_kris7t.plugins.transfer_accounts"
2020-01-01 open Assets:Checking
2020-01-01 open Liabilities:CreditCard
2020-01-01 open Expenses:Taxi
2020-03-15 * "Taxi home from concert in Brooklyn" ^taxi
Assets:Checking -25.60 CAD
Liabilities:CreditCard 20 USD @ 1.28 CAD
2020-03-10 * "Taxi home from concert in Brooklyn" ^taxi
Expenses:Taxi 20 USD
Liabilities:CreditCard -20 USD
''', entries)
@load_doc()
def test_converted_price_default(self, entries, _, __):
'''
plugin "beancount_extras_kris7t.plugins.transfer_accounts"
2020-01-01 open Assets:Checking
2020-01-01 open Liabilities:CreditCard
2020-01-01 open Expenses:Taxi
2020-03-15 * "Taxi home from concert in Brooklyn" ^taxi
Assets:Checking -25.60 CAD
Expenses:Taxi 20 USD @ 1.28 CAD
transfer-account: Liabilities:CreditCard
transfer-date: 2020-03-10
'''
self.assertEqualEntries('''
plugin "beancount_extras_kris7t.plugins.transfer_accounts"
2020-01-01 open Assets:Checking
2020-01-01 open Liabilities:CreditCard
2020-01-01 open Expenses:Taxi
2020-03-15 * "Taxi home from concert in Brooklyn" ^taxi
Assets:Checking -25.60 CAD
Liabilities:CreditCard 20 USD @ 1.28 CAD
2020-03-10 * "Taxi home from concert in Brooklyn" ^taxi
Expenses:Taxi 20 USD
Liabilities:CreditCard -20 USD
''', entries)
@load_doc()
def test_converted_price_account_false(self, entries, _, __):
'''
plugin "beancount_extras_kris7t.plugins.transfer_accounts"
2020-01-01 open Assets:Checking
2020-01-01 open Liabilities:CreditCard
transfer-converted: FALSE
2020-01-01 open Expenses:Taxi
2020-03-15 * "Taxi home from concert in Brooklyn" ^taxi
Assets:Checking -25.60 CAD
Expenses:Taxi 20 USD @ 1.28 CAD
transfer-account: Liabilities:CreditCard
transfer-date: 2020-03-10
'''
self.assertEqualEntries('''
plugin "beancount_extras_kris7t.plugins.transfer_accounts"
2020-01-01 open Assets:Checking
2020-01-01 open Liabilities:CreditCard
2020-01-01 open Expenses:Taxi
2020-03-15 * "Taxi home from concert in Brooklyn" ^taxi
Assets:Checking -25.60 CAD
Liabilities:CreditCard 25.60 CAD
2020-03-10 * "Taxi home from concert in Brooklyn" ^taxi
Expenses:Taxi 20 USD @ 1.28 CAD
Liabilities:CreditCard -25.60 CAD
''', entries)
@load_doc()
def test_converted_price_account_true(self, entries, _, __):
'''
plugin "beancount_extras_kris7t.plugins.transfer_accounts"
2020-01-01 open Assets:Checking
2020-01-01 open Liabilities:CreditCard
transfer-converted: TRUE
2020-01-01 open Expenses:Taxi
2020-03-15 * "Taxi home from concert in Brooklyn" ^taxi
Assets:Checking -25.60 CAD
Expenses:Taxi 20 USD @ 1.28 CAD
transfer-account: Liabilities:CreditCard
transfer-date: 2020-03-10
'''
self.assertEqualEntries('''
plugin "beancount_extras_kris7t.plugins.transfer_accounts"
2020-01-01 open Assets:Checking
2020-01-01 open Liabilities:CreditCard
2020-01-01 open Expenses:Taxi
2020-03-15 * "Taxi home from concert in Brooklyn" ^taxi
Assets:Checking -25.60 CAD
Liabilities:CreditCard 20 USD @ 1.28 CAD
2020-03-10 * "Taxi home from concert in Brooklyn" ^taxi
Expenses:Taxi 20 USD
Liabilities:CreditCard -20 USD
''', entries)
@load_doc()
def test_converted_cost_false(self, entries, _, __):
'''
plugin "beancount_extras_kris7t.plugins.transfer_accounts"
2020-01-01 open Assets:Checking
2020-01-01 open Liabilities:CreditCard
2020-01-01 open Expenses:Taxi
2020-03-15 * "Taxi home from concert in Brooklyn" ^taxi
Assets:Checking -25.60 CAD
Expenses:Taxi 20 USD {1.28 CAD}
transfer-account: Liabilities:CreditCard
transfer-date: 2020-03-10
transfer-converted: FALSE
'''
self.assertEqualEntries('''
plugin "beancount_extras_kris7t.plugins.transfer_accounts"
2020-01-01 open Assets:Checking
2020-01-01 open Liabilities:CreditCard
2020-01-01 open Expenses:Taxi
2020-03-15 * "Taxi home from concert in Brooklyn" ^taxi
Assets:Checking -25.60 CAD
Liabilities:CreditCard 25.60 CAD
2020-03-10 * "Taxi home from concert in Brooklyn" ^taxi
Expenses:Taxi 20 USD {1.28 CAD, 2020-03-15}
Liabilities:CreditCard -25.60 CAD
''', entries)
@load_doc()
def test_converted_cost_true(self, entries, _, __):
'''
plugin "beancount_extras_kris7t.plugins.transfer_accounts"
2020-01-01 open Assets:Checking
2020-01-01 open Liabilities:CreditCard
2020-01-01 open Expenses:Taxi
2020-03-15 * "Taxi home from concert in Brooklyn" ^taxi
Assets:Checking -25.60 CAD
Expenses:Taxi 20 USD {1.28 CAD}
transfer-account: Liabilities:CreditCard
transfer-date: 2020-03-10
transfer-converted: TRUE
'''
self.assertEqualEntries('''
plugin "beancount_extras_kris7t.plugins.transfer_accounts"
2020-01-01 open Assets:Checking
2020-01-01 open Liabilities:CreditCard
2020-01-01 open Expenses:Taxi
2020-03-15 * "Taxi home from concert in Brooklyn" ^taxi
Assets:Checking -25.60 CAD
Liabilities:CreditCard 20 USD {1.28 CAD, 2020-03-15}
2020-03-10 * "Taxi home from concert in Brooklyn" ^taxi
Expenses:Taxi 20 USD {1.28 CAD, 2020-03-15}
Liabilities:CreditCard -20 USD {1.28 CAD, 2020-03-15}
''', entries)
@load_doc()
def test_converted_cost_and_price_false(self, entries, _, __):
'''
plugin "beancount_extras_kris7t.plugins.transfer_accounts"
2020-01-01 open Assets:Checking
2020-01-01 open Liabilities:CreditCard
2020-01-01 open Expenses:Taxi
2020-03-15 * "Taxi home from concert in Brooklyn" ^taxi
Assets:Checking -25.60 CAD
Expenses:Taxi 20 USD {1.28 CAD} @ 1.30 CAD
transfer-account: Liabilities:CreditCard
transfer-date: 2020-03-10
transfer-converted: FALSE
'''
self.assertEqualEntries('''
plugin "beancount_extras_kris7t.plugins.transfer_accounts"
2020-01-01 open Assets:Checking
2020-01-01 open Liabilities:CreditCard
2020-01-01 open Expenses:Taxi
2020-03-15 * "Taxi home from concert in Brooklyn" ^taxi
Assets:Checking -25.60 CAD
Liabilities:CreditCard 25.60 CAD
2020-03-10 * "Taxi home from concert in Brooklyn" ^taxi
Expenses:Taxi 20 USD {1.28 CAD, 2020-03-15} @ 1.30 CAD
Liabilities:CreditCard -25.60 CAD
''', entries)
@load_doc()
def test_converted_cost_and_price_true(self, entries, _, __):
'''
plugin "beancount_extras_kris7t.plugins.transfer_accounts"
2020-01-01 open Assets:Checking
2020-01-01 open Liabilities:CreditCard
2020-01-01 open Expenses:Taxi
2020-03-15 * "Taxi home from concert in Brooklyn" ^taxi
Assets:Checking -25.60 CAD
Expenses:Taxi 20 USD {1.28 CAD} @ 1.30 CAD
transfer-account: Liabilities:CreditCard
transfer-date: 2020-03-10
transfer-converted: TRUE
'''
self.assertEqualEntries('''
plugin "beancount_extras_kris7t.plugins.transfer_accounts"
2020-01-01 open Assets:Checking
2020-01-01 open Liabilities:CreditCard
2020-01-01 open Expenses:Taxi
2020-03-15 * "Taxi home from concert in Brooklyn" ^taxi
Assets:Checking -25.60 CAD
Liabilities:CreditCard 20 USD {1.28 CAD, 2020-03-15} @ 1.30 CAD
2020-03-10 * "Taxi home from concert in Brooklyn" ^taxi
Expenses:Taxi 20 USD {1.28 CAD, 2020-03-15}
Liabilities:CreditCard -20 USD {1.28 CAD, 2020-03-15}
''', entries)
@load_doc()
def test_multiple_separate(self, entries, _, __):
'''
plugin "beancount_extras_kris7t.plugins.transfer_accounts"
2020-01-01 open Assets:Checking
2020-01-01 open Liabilities:CreditCard
2020-01-01 open Expenses:Taxi
2020-01-01 open Expenses:Food
2020-03-15 * "Night out in Brooklyn" ^taxi
Assets:Checking -45 USD
Expenses:Taxi 20 USD
transfer-account: Liabilities:CreditCard
transfer-date: 2020-03-10
Expenses:Food 25 USD
transfer-account: Liabilities:CreditCard
transfer-date: 2020-03-12
'''
self.assertEqualEntries('''
plugin "beancount_extras_kris7t.plugins.transfer_accounts"
2020-01-01 open Assets:Checking
2020-01-01 open Liabilities:CreditCard
2020-01-01 open Expenses:Taxi
2020-01-01 open Expenses:Food
2020-03-15 * "Night out in Brooklyn" ^taxi
Assets:Checking -45 USD
Liabilities:CreditCard 45 USD
2020-03-10 * "Night out in Brooklyn" ^taxi
Expenses:Taxi 20 USD
Liabilities:CreditCard -20 USD
2020-03-12 * "Night out in Brooklyn" ^taxi
Expenses:Food 25 USD
Liabilities:CreditCard -25 USD
''', entries)
@load_doc()
def test_multiple_merge(self, entries, _, __):
'''
plugin "beancount_extras_kris7t.plugins.transfer_accounts"
2020-01-01 open Assets:Checking
2020-01-01 open Liabilities:CreditCard
2020-01-01 open Expenses:Taxi
2020-01-01 open Expenses:Food
2020-03-15 * "Night out in Brooklyn" ^taxi
Assets:Checking -45 USD
Expenses:Taxi 20 USD
transfer-account: Liabilities:CreditCard
transfer-date: 2020-03-10
Expenses:Food 25 USD
transfer-account: Liabilities:CreditCard
transfer-date: 2020-03-10
'''
self.assertEqualEntries('''
plugin "beancount_extras_kris7t.plugins.transfer_accounts"
2020-01-01 open Assets:Checking
2020-01-01 open Liabilities:CreditCard
2020-01-01 open Expenses:Taxi
2020-01-01 open Expenses:Food
2020-03-15 * "Night out in Brooklyn" ^taxi
Assets:Checking -45 USD
Liabilities:CreditCard 45 USD
2020-03-10 * "Night out in Brooklyn" ^taxi
Expenses:Taxi 20 USD
Expenses:Food 25 USD
Liabilities:CreditCard -45 USD
''', entries)
@load_doc()
def test_multiple_currencies_merge_converted_false(self, entries, _, __):
'''
plugin "beancount_extras_kris7t.plugins.transfer_accounts"
2020-01-01 open Assets:Checking
2020-01-01 open Liabilities:CreditCard
2020-01-01 open Expenses:Taxi
2020-01-01 open Expenses:Food
2020-03-15 * "Night out in Brooklyn" ^taxi
Assets:Checking -50.60 CAD
Expenses:Taxi 20 USD @ 1.28 CAD
transfer-account: Liabilities:CreditCard
transfer-date: 2020-03-10
transfer-converted: FALSE
Expenses:Food 25 CAD
transfer-account: Liabilities:CreditCard
transfer-date: 2020-03-10
'''
self.assertEqualEntries('''
plugin "beancount_extras_kris7t.plugins.transfer_accounts"
2020-01-01 open Assets:Checking
2020-01-01 open Liabilities:CreditCard
2020-01-01 open Expenses:Taxi
2020-01-01 open Expenses:Food
2020-03-15 * "Night out in Brooklyn" ^taxi
Assets:Checking -50.60 CAD
Liabilities:CreditCard 50.60 CAD
2020-03-10 * "Night out in Brooklyn" ^taxi
Expenses:Taxi 20 USD @ 1.28 CAD
Expenses:Food 25 CAD
Liabilities:CreditCard -50.60 CAD
''', entries)
@load_doc()
def test_multiple_currencies_merge_converted_true(self, entries, _, __):
'''
plugin "beancount_extras_kris7t.plugins.transfer_accounts"
2020-01-01 open Assets:Checking
2020-01-01 open Liabilities:CreditCard
2020-01-01 open Expenses:Taxi
2020-01-01 open Expenses:Food
2020-03-15 * "Night out in Brooklyn" ^taxi
Assets:Checking -50.60 CAD
Expenses:Taxi 20 USD @ 1.28 CAD
transfer-account: Liabilities:CreditCard
transfer-date: 2020-03-10
transfer-converted: TRUE
Expenses:Food 25 CAD
transfer-account: Liabilities:CreditCard
transfer-date: 2020-03-10
'''
self.assertEqualEntries('''
plugin "beancount_extras_kris7t.plugins.transfer_accounts"
2020-01-01 open Assets:Checking
2020-01-01 open Liabilities:CreditCard
2020-01-01 open Expenses:Taxi
2020-01-01 open Expenses:Food
2020-03-15 * "Night out in Brooklyn" ^taxi
Assets:Checking -50.60 CAD
Liabilities:CreditCard 20 USD @ 1.28 CAD
Liabilities:CreditCard 25 CAD
2020-03-10 * "Night out in Brooklyn" ^taxi
Expenses:Taxi 20 USD
Expenses:Food 25 CAD
Liabilities:CreditCard -20 USD
Liabilities:CreditCard -25 CAD
''', entries)
if __name__ == '__main__':
unittest.main()