aboutsummaryrefslogblamecommitdiffstats
path: root/beancount_extras_kris7t/plugins/default_tolerance.py
blob: 52fa956dc93b845aeb887d636c4847464d582db9 (plain) (tree)














































                                                                                                   
'''
Plugin that sets the tolerance values of balance assertions to an amount determined by the account.
'''
__copyright__ = 'Copyright (c) 2020  Kristóf Marussy <kristof@marussy.com>'
__license__ = 'GNU GPLv2'

from decimal import Decimal
from typing import Any, Dict, List, NamedTuple, Optional, Tuple

from beancount.core.data import Open, Balance, Directive, Entries, Meta

__plugins__ = ('set_tolerances_to_default',)

DEFAULT_TOLERANCE_META = 'default-balance-tolerance'


class DefaultToleranceError(NamedTuple):
    source: Optional[Meta]
    message: str
    entry: Directive


def set_tolerances_to_default(entries: Entries,
                              options_map: Dict[str, Any],
                              config_str: Optional[str] = None) -> \
                              Tuple[Entries, List[DefaultToleranceError]]:
    errors: List[DefaultToleranceError] = []
    accounts: Dict[str, Optional[Decimal]] = {}
    for entry in entries:
        if not isinstance(entry, Open):
            continue
        if tolerance := entry.meta.get(DEFAULT_TOLERANCE_META, None):
            if isinstance(tolerance, Decimal):
                accounts[entry.account] = tolerance
            else:
                errors.append(DefaultToleranceError(
                    entry.meta,
                    f'{DEFAULT_TOLERANCE_META} must be decimal, got {tolerance} instead',
                    entry))
    new_entries: Entries = []
    for entry in entries:
        if isinstance(entry, Balance) and entry.tolerance is None and entry.account in accounts:
            account_tolerance = accounts[entry.account]
            new_entries.append(entry._replace(tolerance=account_tolerance))
        else:
            new_entries.append(entry)
    return new_entries, errors