diff --git a/import2ledger/template.py b/import2ledger/template.py index 6e8ac63..97271dd 100644 --- a/import2ledger/template.py +++ b/import2ledger/template.py @@ -91,12 +91,16 @@ class AccountSplitter: def __init__(self, signed_currencies, signed_currency_fmt, unsigned_currency_fmt, template_name): self.splits = collections.OrderedDict() + self.metadata = [] self.signed_currency_fmt = signed_currency_fmt self.unsigned_currency_fmt = unsigned_currency_fmt self.signed_currencies = set(signed_currencies) self.template_name = template_name self._last_template_vars = object() + def is_empty(self): + return not self.splits + def add(self, account, amount_expr): try: clean_expr = AmountTokenTransformer.from_str(amount_expr).transform() @@ -105,6 +109,10 @@ class AccountSplitter: raise errors.UserInputConfigurationError(error.args[0], amount_expr) else: self.splits[account] = compiled_expr + self.metadata.append('') + + def set_metadata(self, metadata_s): + self.metadata[-1] = metadata_s def _currency_decimal(self, amount, currency): return decimal.Decimal(babel.numbers.format_currency(amount, currency, '###0.###')) @@ -146,11 +154,16 @@ class AccountSplitter: amt_fmt = self.signed_currency_fmt else: amt_fmt = self.unsigned_currency_fmt - for account, amount in amounts.items(): - yield ' {:45} {:>19}\n'.format( - account.format_map(template_vars), - babel.numbers.format_currency(amount, template_vars['currency'], amt_fmt), - ) + for (account, amount), metadata in zip(amounts.items(), self.metadata): + if amount == 0: + yield '' + else: + account_s = ' {:45} {:>19}\n'.format( + account.format_map(template_vars), + babel.numbers.format_currency(amount, template_vars['currency'], amt_fmt), + ) + metadata_s = metadata.format_map(template_vars) + yield account_s + metadata_s def render_next(self, template_vars): if template_vars is not self._last_template_vars: @@ -180,8 +193,7 @@ class Template: break del lines[:index] self.format_funcs = [ - '\n'.format_map, - '{date} {payee}\n'.format_map, + '\n{date} {payee}\n'.format_map, ] start_index = 0 for index, line in enumerate(lines): @@ -204,7 +216,10 @@ class Template: def _add_str_func(self, str_seq): str_flat = ''.join(' ' + s for s in str_seq) - self.format_funcs.append(str_flat.format_map) + if self.splitter.is_empty(): + self.format_funcs.append(str_flat.format_map) + else: + self.splitter.set_metadata(str_flat) def render(self, payee, amount, currency, date=None, **template_vars): if date is None: diff --git a/tests/data/templates.ini b/tests/data/templates.ini index a59d7b3..474e96b 100644 --- a/tests/data/templates.ini +++ b/tests/data/templates.ini @@ -24,6 +24,7 @@ template = [Multivalue] template = Expenses:Taxes {tax} + ;TaxAuthority: IRS Accrued:Accounts Receivable {amount} - {tax} Income:RBI -.1*{amount} Income:Donations -.9*{amount} diff --git a/tests/test_templates.py b/tests/test_templates.py index e7dd551..fcdc8bf 100644 --- a/tests/test_templates.py +++ b/tests/test_templates.py @@ -83,11 +83,25 @@ def test_multivalue(): "", "2015/03/14 DD", " Expenses:Taxes 12.50 USD", + " ;TaxAuthority: IRS", " Accrued:Accounts Receivable 137.50 USD", " Income:RBI -15.00 USD", " Income:Donations -135.00 USD", ] +def test_zeroed_account_skipped(): + tmpl = template_from('Multivalue') + rendered = tmpl.render('GG', decimal.Decimal('110.00'), 'USD', DATE, + tax=decimal.Decimal(0)) + lines = [normalize_whitespace(s) for s in rendered.splitlines()] + assert lines == [ + "", + "2015/03/14 GG", + " Accrued:Accounts Receivable 110.00 USD", + " Income:RBI -11.00 USD", + " Income:Donations -99.00 USD", + ] + @pytest.mark.parametrize('amount_expr', [ '', 'name',