Files @ dc2e2d200d70
Branch filter:

Location: NPO-Accounting/conservancy_beancount/conservancy_beancount/plugin/meta_approval.py

Brett Smith
balance_sheet: Fix logger name.
"""meta_approval - Validate approval metadata"""
# Copyright © 2020  Brett Smith
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.

import decimal

from . import core
from .. import config as configmod
from .. import data
from .. import errors as errormod
from ..beancount_types import (
    Transaction,
)

class MetaApproval(core._RequireLinksPostingMetadataHook):
    CHECKED_METADATA = ['approval']
    SKIP_FLAGS = '!'
    SKIP_TAX_IMPLICATIONS = frozenset([
        'Bank-Transfer',
        'Chargeback',
    ])

    def __init__(self, config: configmod.Config) -> None:
        self.payment_threshold = -config.payment_threshold()

    def _run_on_txn(self, txn: Transaction) -> bool:
        return (
            super()._run_on_txn(txn)
            # approval is required when funds leave a cash equivalent asset,
            # UNLESS that transaction is a transfer to another asset,
            # or paying off a credit card.
            and self.payment_threshold > data.balance_of(
                txn,
                data.Account.is_cash_equivalent,
                data.Account.is_credit_card,
            ).number
        )

    def _run_on_post(self, txn: Transaction, post: data.Posting) -> bool:
        return (
            post.account.is_cash_equivalent()
            and post.units.number < 0
            and str(post.meta.get('tax-implication')).title() not in self.SKIP_TAX_IMPLICATIONS
        )