aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/journal_lib/dataclasses.py83
1 files changed, 81 insertions, 2 deletions
diff --git a/src/journal_lib/dataclasses.py b/src/journal_lib/dataclasses.py
index 73b81e9..9c9729f 100644
--- a/src/journal_lib/dataclasses.py
+++ b/src/journal_lib/dataclasses.py
@@ -1,7 +1,11 @@
import sys
-from dataclasses import dataclass
+from copy import deepcopy
+from dataclasses import dataclass, field
+from decimal import Decimal
+from datetime import datetime
FORCE_NOCOLOR = False
+DATE_FORMAT = "%Y-%m-%d"
def set_force_nocolor(value: bool):
@@ -29,6 +33,22 @@ class JournalEntryTransaction:
currency: str | None
amount: str | None
comment: str | None
+ sign: int = field(init=False)
+ amount_value: int = field(init=False)
+
+ def __post_init__(self):
+ if self.amount is not None:
+ if self.amount.startswith("-"):
+ self.sign = -1
+ else:
+ self.sign = 1
+
+ self.amount_value = Decimal(self.amount.lstrip("-+"))
+ else:
+ self.sign = 1
+
+ def key(self):
+ return (self.account, abs(Decimal(self.amount)), self.currency)
@dataclass
@@ -58,15 +78,74 @@ class JournalEntry:
amount_code = "32m"
if transaction.amount[0] == "-":
amount_code = "31m"
+ else:
+ t += " "
t += f" {anesc(amount_code)}{format_amount(transaction.amount, transaction.currency)}{anesc('0m')}"
if transaction.comment is not None:
t += f" {anesc('38m')}{transaction.comment}{anesc('0m')}"
s += t + f"{anesc('0m')}\n"
for comment in self.comments:
- s += f" {anesc('38m')}{comment}{anesc('0m')}\n"
+ s += f" ; {anesc('38m')}{comment}{anesc('0m')}\n"
return s + "\n"
+ def __lt__(self, other):
+ return self.date < other.date
+
+ def get_comment_by_label(self, label: str):
+ return next(
+ (
+ comment[len(label) + 2 :]
+ for comment in self.comments
+ if comment.startswith(label)
+ ),
+ None,
+ )
+
+ @property
+ def from_dump_account(self):
+ # Extract the first comment that starts with "FROM_DUMP_ACCOUNT", if any
+ return self.get_comment_by_label("FROM_DUMP_ACCOUNT")
+
+ @property
+ def class_info(self):
+ # Extract the first comment that starts with "FROM_DUMP_ACCOUNT", if any
+ return self.get_comment_by_label("CLASS_INFO")
+
+ def potential_transfer(self, other, date_skew=3):
+ date_diff = abs((self.date - other.date).days)
+ if date_diff > date_skew:
+ return False
+ return True
+
+ def likely_transfer(self, other, date_skew=3):
+ self_date = datetime.strptime(self.date, DATE_FORMAT)
+ other_date = datetime.strptime(other.date, DATE_FORMAT)
+ date_diff = abs((self_date - other_date).days)
+ if date_diff > date_skew:
+ return False
+
+ # Check for inverse matching transactions
+ for self_trans in self.transactions:
+ inverse_match_found = False
+ for other_trans in other.transactions:
+ if (
+ self_trans.account != other_trans.account
+ and self_trans.amount_value == other_trans.amount_value
+ and self_trans.currency == other_trans.currency
+ and self_trans.sign != other_trans.sign
+ ):
+ inverse_match_found = True
+ break
+
+ if not inverse_match_found:
+ return False
+
+ if self.from_dump_account == other.from_dump_account:
+ return False
+
+ return True
+
@dataclass
class JournalAccountDef: