Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/protoocls #17

Merged
merged 3 commits into from
Apr 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/ficamp/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def cli() -> argparse.Namespace:
subparsers = parser.add_subparsers(dest="command", required=True)

# Subparser for the import command
import_parser = subparsers.add_parser("import", help="Import a Transactions")
import_parser = subparsers.add_parser("import", help="Import transactions")
import_parser.add_argument(
"--bank",
choices=[e.value for e in BankParser],
Expand Down
2 changes: 1 addition & 1 deletion src/ficamp/classifier/google_apis.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ def query_gmaps_category(concept):
cached_category = cached.get(concept)
if not cached_category:
try:
#ams = "52.3676,4.9041"
# ams = "52.3676,4.9041"
gmaps_category = find_business_category_in_google(concept)
except GoogleException as error:
print(f"error: {error}")
Expand Down
8 changes: 5 additions & 3 deletions src/ficamp/classifier/keywords.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
"""
Logic to sort transactions based on keywords.
"""
import json
import pathlib

from typing import Any

def sort_by_keyword_matches(categories: dict, description: str) -> list[str]:

def sort_by_keyword_matches(
categories: dict, description: str
) -> list[tuple[int, Any]]:
description = description.lower()
matches = []
for category, keywords in categories.items():
Expand Down
4 changes: 3 additions & 1 deletion src/ficamp/datastructures.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,14 @@ class Concept:
class Tx(SQLModel, table=True):
"""Represents a transaction extracted from a bank"""

id: Optional[int] = Field(default=None, primary_key=True)
date: datetime
amount: Decimal
currency: Currency
concept: str
concept_clean: Optional[str]
category: None | str

# fields with defaults
id: Optional[int] = Field(default=None, primary_key=True)
tx_metadata: dict[str, str] = Field(sa_column=Column(JSON))
tags: list[str] = Field(sa_column=Column(JSON))
6 changes: 4 additions & 2 deletions src/ficamp/parsers/abn.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import xlrd # type: ignore

from ficamp.datastructures import Currency, Tx
from ficamp.parsers.protocols import Parser
from ficamp.parsers.protocols import ParserProtocol

TRANSACTIONDATE_REGEX = r"(\d{4})(\d{2})(\d{2})"
transactiondate_re = re.compile(TRANSACTIONDATE_REGEX)
Expand Down Expand Up @@ -105,7 +105,7 @@ def parse_abn(self, concept: str) -> str:
return "ABN AMRO|" + concept


class AbnParser(Parser):
class AbnParser(ParserProtocol):
"""Parser for ABN AMRO bank statements.

ABN uses the old `.xls` excel version, and we require xlrd
Expand Down Expand Up @@ -162,10 +162,12 @@ def build_transaction(
_concept = self.concept_parser.parse(concept)

return Tx(
id=None,
date=_date,
amount=_amount,
currency=_currency,
concept=_concept,
concept_clean=None,
category=None,
tx_metadata={},
tags=[],
Expand Down
6 changes: 3 additions & 3 deletions src/ficamp/parsers/bbva.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
from openpyxl import load_workbook

from ficamp.datastructures import Currency, Tx
from ficamp.parsers.protocols import Parser
from ficamp.parsers.protocols import ParserProtocol


class AccountBBVAParser(Parser):
class AccountBBVAParser(ParserProtocol):
"""Parser for BBVA bank account extract"""

def load(self, filename: Path):
Expand Down Expand Up @@ -49,7 +49,7 @@ def row_processor(self, row):
)


class CreditCardBBVAParser(Parser):
class CreditCardBBVAParser(ParserProtocol):
"""Parser for BBVA Credit Card Extract"""

def load(self, filename: Path):
Expand Down
6 changes: 3 additions & 3 deletions src/ficamp/parsers/bsabadell.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
from openpyxl import load_workbook

from ficamp.datastructures import Currency, Tx
from ficamp.parsers.protocols import Parser
from ficamp.parsers.protocols import ParserProtocol


class AccountBSabadellParser(Parser):
class AccountBSabadellParser(ParserProtocol):
"""Parser for BSabadell bank account extract"""

def load(self, filename: Path):
Expand Down Expand Up @@ -62,7 +62,7 @@ def concept_builder(self, row):
return concept


class CreditCardBSabadellParser(Parser):
class CreditCardBSabadellParser(ParserProtocol):
"""Parser for BSabadell Credit Card Extract"""

def load(self, filename: Path):
Expand Down
4 changes: 2 additions & 2 deletions src/ficamp/parsers/caixabank.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
from openpyxl import load_workbook

from ficamp.datastructures import Currency, Tx
from ficamp.parsers.protocols import Parser
from ficamp.parsers.protocols import ParserProtocol


class CaixaBankParser(Parser):
class CaixaBankParser(ParserProtocol):
"""Parser for CaixaBank bank account extract"""

def load(self, filename: Path):
Expand Down
3 changes: 2 additions & 1 deletion src/ficamp/parsers/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from ficamp.parsers.bbva import AccountBBVAParser, CreditCardBBVAParser
from ficamp.parsers.bsabadell import AccountBSabadellParser, CreditCardBSabadellParser
from ficamp.parsers.caixabank import CaixaBankParser
from ficamp.parsers.protocols import ParserProtocol


class BankParser(StrEnum):
Expand All @@ -14,7 +15,7 @@ class BankParser(StrEnum):
BSABADELL_CREDIT = "bsabadell-credit"
CAIXABANK = "caixabank"

def get_parser(self):
def get_parser(self) -> ParserProtocol:
if self == BankParser.ABN:
return AbnParser()
if self == BankParser.BBVA_ACCOUNT:
Expand Down
2 changes: 1 addition & 1 deletion src/ficamp/parsers/protocols.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from ficamp.datastructures import Tx


class Parser(Protocol):
class ParserProtocol(Protocol):
"""Main protocol to define parsers for different banks."""

def load(self, filename: Path): ...
Expand Down
17 changes: 17 additions & 0 deletions src/ficamp/sinks/protocols.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from enum import Enum
from typing import Protocol

from ficamp.datastructures import Tx


class BaseSinkException(Exception):
"""Base exception for all sink exceptions.

If your sink function is going to raise an exception, it should inherit from this class.
"""

pass


class SinkProtocol(Protocol):
def write(self, transations: list[Tx]): ...
woile marked this conversation as resolved.
Show resolved Hide resolved
2 changes: 1 addition & 1 deletion tests/test_preprocessing.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
remove_colon,
remove_comma,
remove_digits,
remove_isolated_digits,
remove_pipes,
remove_punctuation,
remove_isolated_digits,
remove_short_words,
)

Expand Down
Loading