diff --git a/actual_imap_poll/parsers.py b/actual_imap_poll/parsers.py index b14c2f6..2df6db8 100644 --- a/actual_imap_poll/parsers.py +++ b/actual_imap_poll/parsers.py @@ -178,11 +178,16 @@ class CIBCParser(TransactionParser): flags=re.MULTILINE, ) + PURCHASE_EXTRACT_RE = re.compile( + r"made a purchase with your CIBC.*ending in (?P\d{4}) for \$(?P\d+\.\d{2}) at (?P.*?). bool: - return msg["From"] == "CIBC Banking " + return msg["From"] == "CIBC Banking " def extract_payment(self, msg: EmailMessage): content = self.get_content(msg) @@ -209,10 +214,37 @@ class CIBCParser(TransactionParser): imported_id=msg["Message-ID"], ) + def extract_purchase(self, msg: EmailMessage) -> Optional[Transaction]: + content = self.get_content(msg) + + matches = self.PURCHASE_EXTRACT_RE.search(content) + if matches is None: + raise TransactionParsingFailed("no matches for extraction RE") + + amount = Decimal(matches["amount"].replace(",", "")) * -1 + date = parse_email_time(msg["Date"]).date() + account_ref = int(matches["account"]) + + if account_ref not in self._account_map: + warning("Account %s not in account map, skipping transaction", account_ref) + return None + account_id = self._account_map[account_ref] + + return Transaction( + account=account_id, + date=date, + amount=amount, + payee=matches["payee"], + notes="via email", + imported_id=msg["Message-ID"], + ) + def extract(self, msg: EmailMessage) -> Optional[Transaction]: match msg["Subject"]: case "New payment to your credit card": return self.extract_payment(msg) + case "New purchase on your credit card": + return self.extract_purchase(msg) return None