Skip to content

Commit

Permalink
strip invalid characters when parsing decimals
Browse files Browse the repository at this point in the history
  • Loading branch information
isaacharrisholt committed Jul 19, 2023
1 parent 4e44170 commit 15e015e
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 9 deletions.
20 changes: 11 additions & 9 deletions quiffen/core/transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -388,18 +388,18 @@ def from_list(
current_split.memo = field_info
elif line_code in {"$", "£"}:
if current_split:
current_split.amount = Decimal(field_info.replace(",", ""))
current_split.amount = utils.parse_decimal(field_info)
elif line_code == "%":
if current_split:
current_split.percent = Decimal(
field_info.split(" ")[0].replace("%", "")
current_split.percent = utils.parse_decimal(
field_info.split(" ")[0]
)
elif line_code in {"T", "U"}:
amount = field_info.replace(",", "")
amount = utils.parse_decimal(field_info)
if not splits:
kwargs["amount"] = amount
elif current_split:
current_split.amount = Decimal(amount)
current_split.amount = amount
elif line_code == "M":
if not splits:
kwargs["memo"] = field_info
Expand Down Expand Up @@ -480,18 +480,20 @@ def from_list(
kwargs["line_number"] = line_number

# Set splits percentage if they don't already have one
total = Decimal(kwargs.get("amount", 0))
total = utils.parse_decimal(kwargs.get("amount", 0))
if splits and total:
for split in splits:
if split.percent is None and split.amount is not None:
split.percent = Decimal(round(split.amount / total * 100, 2))
split.percent = utils.parse_decimal(
round(split.amount / total * 100, 2)
)
# Check if the split percentage is correct
elif (
split.percent is not None
and split.amount is not None
and not (
Decimal(round(split.percent, 2))
== Decimal(
utils.parse_decimal(round(split.percent, 2))
== utils.parse_decimal(
round(
split.amount / total * 100,
2,
Expand Down
10 changes: 10 additions & 0 deletions quiffen/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
ZERO_SEPARATED_DATE = re.compile(
r"^(\d{2}|\d{4}|[a-zA-Z]+)0(\d{2}|[a-zA-Z]+)0(\d{2}|\d{4})$",
)
INVALID_AMOUNT_CHARACTERS = re.compile(
r"[^\d\.-]",
)


def parse_date(date_string: str, day_first: bool = False) -> datetime:
Expand Down Expand Up @@ -150,3 +153,10 @@ def apply_csv_formatting_to_container(
}
else:
return apply_csv_formatting_to_scalar(obj, date_format)


def parse_decimal(value: Union[str, Decimal]) -> Decimal:
"""Parse a decimal from a string, removing non-numeric characters."""
if isinstance(value, Decimal):
return value
return Decimal(INVALID_AMOUNT_CHARACTERS.sub("", value))
18 changes: 18 additions & 0 deletions tests/test_transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -866,3 +866,21 @@ def test_check_number_allows_strings():
check_number="Transfer",
)
assert transaction.check_number == "Transfer"


def test_from_list_invalid_characters_in_amount_field():
"""Test that the amount field correctly parses out invalid
characters (non-numeric).
Relates to issue #56.
https://github.com/isaacharrisholt/quiffen/issues/56
"""
qif_list = [
"D2022-02-01",
"T$1,0ab£c00",
"L[Test To Account]", # Brackets denote to account
"LTest Category 1",
"LTest Category 2",
]
transaction, _ = Transaction.from_list(qif_list)
assert transaction.amount == 1000

0 comments on commit 15e015e

Please sign in to comment.