aboutsummaryrefslogtreecommitdiffstats
path: root/beancount_extras_kris7t/plugins/closing_balance.py
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2021-01-25 01:14:28 +0100
committerLibravatar Kristóf Marussy <kristof@marussy.com>2021-01-25 01:14:28 +0100
commita1c2a999e449054d6641bbb633954e45fcd63f90 (patch)
tree47628c10ded721d66e47b5f87f501293cd8af003 /beancount_extras_kris7t/plugins/closing_balance.py
parentInitialize package (diff)
downloadbeancount-extras-kris7t-a1c2a999e449054d6641bbb633954e45fcd63f90.tar.gz
beancount-extras-kris7t-a1c2a999e449054d6641bbb633954e45fcd63f90.tar.zst
beancount-extras-kris7t-a1c2a999e449054d6641bbb633954e45fcd63f90.zip
Add plugins and importers from private config
The importers are missing tests, because not having any specifications for the import formats means we must use real, private data as test inputs
Diffstat (limited to 'beancount_extras_kris7t/plugins/closing_balance.py')
-rw-r--r--beancount_extras_kris7t/plugins/closing_balance.py70
1 files changed, 70 insertions, 0 deletions
diff --git a/beancount_extras_kris7t/plugins/closing_balance.py b/beancount_extras_kris7t/plugins/closing_balance.py
new file mode 100644
index 0000000..a22e712
--- /dev/null
+++ b/beancount_extras_kris7t/plugins/closing_balance.py
@@ -0,0 +1,70 @@
1'''
2Plugin that closes an account by transferring its whole balance to another account.
3'''
4__copyright__ = 'Copyright (c) 2020 Kristóf Marussy <kristof@marussy.com>'
5__license__ = 'GNU GPLv2'
6
7from typing import Any, Dict, List, NamedTuple, Optional, Tuple
8
9from beancount.core.data import Balance, Close, Directive, Entries, Meta, Posting, Transaction
10from beancount.core.flags import FLAG_OKAY
11from beancount.core.number import ZERO
12
13__plugins__ = ('close_with_balance_assertions',)
14
15CLOSE_TO_META = 'close-to'
16CLOSING_META = 'closing'
17
18
19class ClosingBalanceError(NamedTuple):
20 source: Optional[Meta]
21 message: str
22 entry: Directive
23
24
25def close_with_balance_assertions(entries: Entries,
26 options_map: Dict[str, Any],
27 config_str: Optional[str] = None) -> \
28 Tuple[Entries, List[ClosingBalanceError]]:
29 new_entries: Entries = []
30 errors: List[ClosingBalanceError] = []
31 for entry in entries:
32 new_entries.append(entry)
33 if isinstance(entry, Balance) and CLOSE_TO_META in entry.meta:
34 close_to_account = entry.meta[CLOSE_TO_META]
35 if not isinstance(close_to_account, str):
36 errors.append(ClosingBalanceError(
37 entry.meta,
38 f'{CLOSE_TO_META} must be a string, got {close_to_account} instead',
39 entry))
40 continue
41 if entry.tolerance is not None and entry.tolerance != ZERO:
42 errors.append(ClosingBalanceError(
43 entry.meta,
44 f'Closing an account requires {ZERO} tolerance, got {entry.tolerance} instead',
45 entry))
46 continue
47 if entry.diff_amount is not None:
48 errors.append(ClosingBalanceError(
49 entry.meta,
50 f'Not closing {entry.account} with {entry.diff_amount} failed balance check',
51 entry))
52 continue
53 new_meta = dict(entry.meta)
54 del new_meta[CLOSE_TO_META]
55 if entry.amount.number != ZERO:
56 new_entries.append(Transaction(
57 new_meta,
58 entry.date,
59 FLAG_OKAY,
60 None,
61 f'Closing {entry.account}',
62 set(),
63 set(),
64 [
65 Posting(entry.account, -entry.amount, None, None, None,
66 {CLOSING_META: True}),
67 Posting(close_to_account, entry.amount, None, None, None, None)
68 ]))
69 new_entries.append(Close(new_meta, entry.date, entry.account))
70 return new_entries, errors