diff options
author | Kristóf Marussy <kristof@marussy.com> | 2021-01-25 01:14:28 +0100 |
---|---|---|
committer | Kristóf Marussy <kristof@marussy.com> | 2021-01-25 01:14:28 +0100 |
commit | a1c2a999e449054d6641bbb633954e45fcd63f90 (patch) | |
tree | 47628c10ded721d66e47b5f87f501293cd8af003 /beancount_extras_kris7t/plugins/closing_balance.py | |
parent | Initialize package (diff) | |
download | beancount-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.py | 70 |
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 | ''' | ||
2 | Plugin 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 | |||
7 | from typing import Any, Dict, List, NamedTuple, Optional, Tuple | ||
8 | |||
9 | from beancount.core.data import Balance, Close, Directive, Entries, Meta, Posting, Transaction | ||
10 | from beancount.core.flags import FLAG_OKAY | ||
11 | from beancount.core.number import ZERO | ||
12 | |||
13 | __plugins__ = ('close_with_balance_assertions',) | ||
14 | |||
15 | CLOSE_TO_META = 'close-to' | ||
16 | CLOSING_META = 'closing' | ||
17 | |||
18 | |||
19 | class ClosingBalanceError(NamedTuple): | ||
20 | source: Optional[Meta] | ||
21 | message: str | ||
22 | entry: Directive | ||
23 | |||
24 | |||
25 | def 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 | ||