Moved plugins to their own repo
This commit is contained in:
86
old_split_account.py
Normal file
86
old_split_account.py
Normal file
@@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import re
|
||||
|
||||
from beancount.core import data
|
||||
from beancount.core import getters
|
||||
from beancount.core import amount
|
||||
from beancount.core import account_types
|
||||
from beancount.core import realization
|
||||
from beancount.core.number import D
|
||||
from beancount.parser import options
|
||||
|
||||
__plugins__ = ('split_account_plugin',)
|
||||
|
||||
def get_group(tag, _pattern=re.compile(r"split-(.*)")):
|
||||
m = _pattern.match(tag)
|
||||
if m:
|
||||
return m.group(1)
|
||||
return ""
|
||||
|
||||
def is_splitable(posting: data.Posting, accs: account_types.AccountTypes) -> bool:
|
||||
if posting.meta.get("split", "") == "no":
|
||||
return False
|
||||
return account_types.is_income_statement_account(posting.account, accs)
|
||||
|
||||
def add_tag(txn: data.Transaction, tag: str) -> data.Transaction:
|
||||
return txn._replace(tags=txn.tags | set([tag]))
|
||||
|
||||
def divide_and_flip(posting: data.Posting, n: int = 2) -> data.Posting:
|
||||
"""Return a new posting with n-th the amount and opposite sign."""
|
||||
assert(n>0)
|
||||
old_amount = posting.units
|
||||
new_amount = amount.div(old_amount, D(-n))
|
||||
return posting._replace(units=new_amount)
|
||||
|
||||
def split_txn(txn: data.Transaction, split_accounts: dict, accs: account_types.AccountTypes) -> None | data.Transaction:
|
||||
# involves_account = any((acc in split_accounts.items() for acc in getters.get_accounts([entry])))
|
||||
|
||||
groups = [g for g in ( get_group(tag) for tag in txn.tags ) if g in split_accounts]
|
||||
if len(groups) != 1:
|
||||
return None
|
||||
group = groups[0]
|
||||
|
||||
has_ignore_meta = txn.meta.get("split", "") == "no"
|
||||
if has_ignore_meta:
|
||||
return None
|
||||
|
||||
# gather all splitable expenses/income, and get their total balance
|
||||
new_postings = [posting for posting in txn.postings if is_splitable(posting, accs)]
|
||||
if len(new_postings) == 0:
|
||||
return None
|
||||
|
||||
new_balance = realization.compute_postings_balance(new_postings)
|
||||
for position in new_balance:
|
||||
new_postings.append(data.Posting(
|
||||
account=split_accounts[group],
|
||||
units=-position.units,
|
||||
cost=position.cost,
|
||||
price=None,
|
||||
flag=None,
|
||||
meta=None
|
||||
))
|
||||
|
||||
new_postings = [ divide_and_flip(p) for p in new_postings ]
|
||||
|
||||
return add_tag(txn._replace(postings=new_postings), "retorn")
|
||||
|
||||
def split_account_plugin(entries, options_map):
|
||||
errors = []
|
||||
new_entries = []
|
||||
accs = options.get_account_types(options_map)
|
||||
|
||||
split_accounts = {}
|
||||
for entry in entries:
|
||||
if isinstance(entry, data.Open):
|
||||
if "split" in entry.meta:
|
||||
split_accounts[entry.meta["split"]] = entry.account
|
||||
|
||||
for entry in entries:
|
||||
if isinstance(entry, data.Transaction):
|
||||
new_txn = split_txn(entry, split_accounts, accs)
|
||||
if new_txn is not None:
|
||||
new_entries.append(new_txn)
|
||||
new_entries.append(entry)
|
||||
|
||||
return new_entries, errors
|
||||
Reference in New Issue
Block a user