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:
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()
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)
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
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),