From: Dustin Walde Date: Sun, 12 Nov 2023 20:40:06 +0000 (-0800) Subject: Add date formatting for recurring transactions X-Git-Url: https://git.walde.dev/?a=commitdiff_plain;h=490922bd52a6879af7c7afc189ad6d30648d9c93;p=beanbeanbean Add date formatting for recurring transactions --- diff --git a/src/beanbeanbean/recurring.py b/src/beanbeanbean/recurring.py index 676109a..023f999 100644 --- a/src/beanbeanbean/recurring.py +++ b/src/beanbeanbean/recurring.py @@ -53,7 +53,7 @@ def is_recurring_transaction(entry) -> bool: return False -def handle_recurring_transaction(txn: Transaction) -> Union[List[Transaction], LoadError]: +def handle_recurring_transaction(txn: Transaction, format_token: str) -> Union[List[Transaction], LoadError]: post_vals = [] balances = {} for post in txn.postings: @@ -106,9 +106,11 @@ def handle_recurring_transaction(txn: Transaction) -> Union[List[Transaction], L entries = [] for i, dt in enumerate(dates): - new_txn = Transaction(date=dt.date(), postings=[], **txn_dict) + new_txn_dict = dict(txn_dict) + new_txn_dict["date"] = dt.date() + new_txn_dict["postings"] = [] + new_txn_dict["meta"] = dict(txn.meta) if amortize: - new_postings = [] balances = {} for j, posting in enumerate(txn.postings): post_dict = posting._asdict() @@ -142,13 +144,13 @@ def handle_recurring_transaction(txn: Transaction) -> Union[List[Transaction], L remaining[1] = remaining[0] else: remaining[1] = amount.sub(remaining[1], amortized_cost) - new_postings.append(post_dict) + new_txn_dict["postings"].append(post_dict) if balanced: # verify it all still balances for remainder in balances.values(): if amount.abs(remainder).number >= tolerances[remainder.currency]: - for post in new_postings: + for post in new_txn_dict["postings"]: cost = post['cost'] if cost is not None and cost.currency == remainder.currency: post['cost'] = amount.sub(cost, remainder) @@ -157,22 +159,37 @@ def handle_recurring_transaction(txn: Transaction) -> Union[List[Transaction], L post['units'] = amount.sub(post['units'], remainder) break - for pd in new_postings: + for pd in new_txn_dict["postings"]: if pd['cost'] is not None: pd['cost'] = position.Cost(pd['cost'].number, pd['cost'].currency, txn.date, 'amortized') - new_txn.postings.append(Posting(**pd)) + for k, v in pd["meta"].items(): + if type(v) is str: + pd["meta"][k] = new_txn_dict["date"].strftime(v) + new_txn_dict["postings"].append(Posting(**pd)) else: for posting in txn.postings: - new_txn.postings.append(posting) - entries.append(new_txn) - - # replace metadata with computed values to show it was processed - # this dict is a shared reference among all entries.. - txn.meta['a͏mortize'] = amortize - txn.meta['p͏hrase'] = txn.meta[match_key] - del txn.meta[match_key] - txn.meta['s͏tart'] = txn.date - txn.meta['c͏ount'] = len(dates) + new_txn_dict["postings"].append(posting) + + new_date = new_txn_dict["date"] + new_meta = new_txn_dict["meta"] + if new_txn_dict["narration"] is not None: + new_txn_dict["narration"] = new_date.strftime(new_txn_dict["narration"]) + for set_name in ("tags", "links"): + if new_txn_dict[set_name] is not None: + tags = set() + for tag in new_txn_dict[set_name]: + tags.add(new_date.strftime(tag.replace(format_token, "%"))) + new_txn_dict[set_name] = frozenset(tags) + for k, v in new_meta.items(): + if type(v) is str: + new_meta[k] = new_date.strftime(v) + # replace metadata with computed values to show it was processed + new_meta['a͏mortize'] = amortize + new_meta['p͏hrase'] = new_meta[match_key] + del new_meta[match_key] + new_meta['s͏tart'] = txn.date + new_meta['c͏ount'] = len(dates) + entries.append(Transaction(**new_txn_dict)) return entries @@ -186,14 +203,12 @@ def recurring(entries: Entries, options_map, config_string=""): out_entries.append(entry) else: try: - res = handle_recurring_transaction(entry) + res = handle_recurring_transaction(entry, "/") if type(res) is list: out_entries.extend(res) else: errors.append(res) except Exception as e: - import traceback - print(traceback.format_exc()) errors.append(LoadError( source=new_metadata(entry.meta["filename"], entry.meta["lineno"]), message="Failed to handle recurring transaction: {}".format(e),