Skip to content

Commit

Permalink
feat(backends): support fetching mutiple accounts info
Browse files Browse the repository at this point in the history
  • Loading branch information
nijel committed Oct 24, 2024
1 parent 7673857 commit b1dd850
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 46 deletions.
19 changes: 19 additions & 0 deletions weblate_web/invoices/migrations/0014_alter_invoice_currency.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Generated by Django 5.1.2 on 2024-10-24 18:30

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("invoices", "0013_invoice_extra"),
]

operations = [
migrations.AlterField(
model_name="invoice",
name="currency",
field=models.IntegerField(
choices=[(0, "EUR"), (1, "CZK"), (2, "USD"), (3, "GBP")], default=0
),
),
]
103 changes: 59 additions & 44 deletions weblate_web/payments/backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -512,53 +512,68 @@ def get_instructions(self) -> list[tuple[StrOrPromise, StrOrPromise]]:
]

@classmethod
def fetch_payments(cls, from_date=None) -> None:
# TODO: support token per currency
client = fiobank.FioBank(token=settings.FIO_TOKEN)
for entry in client.last(from_date=from_date):
matches = []
# Extract from message
if entry["recipient_message"]:
matches.extend(PROFORMA_RE.findall(entry["recipient_message"]))
# Extract from variable symbol
if entry["variable_symbol"]:
matches.extend(PROFORMA_RE.findall(entry["variable_symbol"]))
# Extract from sender reference
if entry.get("reference", None):
matches.extend(PROFORMA_RE.findall(entry["reference"]))
# Extract from comment for manual pairing
if entry["comment"]:
matches.extend(PROFORMA_RE.findall(entry["comment"]))
# Process all matches
for proforma_number in matches:
# TODO: Fetch invoice object
proforma_id = f"P{proforma_number}"
try:
related = Payment.objects.get(backend=cls.name, invoice=proforma_id)
if related.state != Payment.PENDING:
print(
f"{proforma_id} not pending: {related.get_state_display()}"
def fetch_payments(cls, from_date: str | None = None) -> None:
tokens: list[str]
if isinstance(settings.FIO_TOKEN, str):
tokens = [settings.FIO_TOKEN]
else:
tokens = settings.FIO_TOKEN
for token in tokens:
client = fiobank.FioBank(token=token)
info = client.info()
currency = info["currency"]
for entry in client.last(from_date=from_date):
matches = []
# Extract from message
if entry["recipient_message"]:
matches.extend(PROFORMA_RE.findall(entry["recipient_message"]))
# Extract from variable symbol
if entry["variable_symbol"]:
matches.extend(PROFORMA_RE.findall(entry["variable_symbol"]))
# Extract from sender reference
if entry.get("reference", None):
matches.extend(PROFORMA_RE.findall(entry["reference"]))
# Extract from comment for manual pairing
if entry["comment"]:
matches.extend(PROFORMA_RE.findall(entry["comment"]))
# Process all matches
for proforma_number in matches:
# TODO: Fetch invoice object
proforma_id = f"P{proforma_number}"
try:
related = Payment.objects.get(
backend=cls.name, invoice=proforma_id
)
continue

backend = cls(related)
proforma = backend.get_proforma()
proforma.mark_paid(
json.dumps(entry, indent=2, cls=DjangoJSONEncoder)
)
backend.git_commit([proforma.paid_path], proforma)
if floor(float(proforma.total_amount)) <= entry["amount"]:
print(f"Received payment for {proforma_id}")
backend.payment.details["transaction"] = entry
backend.success()
else:
print(
"Underpaid {}: received={}, expected={}".format(
proforma_id, entry["amount"], proforma.total_amount
expected_currency = related.get_currency_display()
if expected_currency != currency:
print(
f"{proforma_id} currency mismatch: expecting {expected_currency}, got {currency}"
)
continue
if related.state != Payment.PENDING:
print(
f"{proforma_id} not pending: {related.get_state_display()}"
)
continue

backend = cls(related)
proforma = backend.get_proforma()
proforma.mark_paid(
json.dumps(entry, indent=2, cls=DjangoJSONEncoder)
)
except Payment.DoesNotExist:
print(f"No matching payment for {proforma_id} found")
backend.git_commit([proforma.paid_path], proforma)
if floor(float(proforma.total_amount)) <= entry["amount"]:
print(f"Received payment for {proforma_id}")
backend.payment.details["transaction"] = entry
backend.success()
else:
print(
"Underpaid {}: received={}, expected={}".format(
proforma_id, entry["amount"], proforma.total_amount
)
)
except Payment.DoesNotExist:
print(f"No matching payment for {proforma_id} found")


@register_backend
Expand Down
20 changes: 20 additions & 0 deletions weblate_web/payments/migrations/0036_alter_payment_currency.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Generated by Django 5.1.2 on 2024-10-24 18:30

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("payments", "0035_payment_draft_invoice_payment_paid_invoice"),
]

operations = [
migrations.AlterField(
model_name="payment",
name="currency",
field=models.IntegerField(
choices=[(0, "EUR"), (1, "BTC"), (2, "USD"), (3, "CZK"), (4, "GBP")],
default=0,
),
),
]
2 changes: 2 additions & 0 deletions weblate_web/payments/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ class Payment(models.Model):
CURRENCY_BTC = 1
CURRENCY_USD = 2
CURRENCY_CZK = 3
CURRENCY_GBP = 4

uuid = Char32UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
amount = models.IntegerField()
Expand All @@ -224,6 +225,7 @@ class Payment(models.Model):
(CURRENCY_BTC, "BTC"),
(CURRENCY_USD, "USD"),
(CURRENCY_CZK, "CZK"),
(CURRENCY_GBP, "GBP"),
),
default=CURRENCY_EUR,
)
Expand Down
12 changes: 11 additions & 1 deletion weblate_web/payments/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@


FIO_API = "https://fioapi.fio.cz/v1/rest/last/test-token/transactions.json"
FIO_INFO_API = (
"https://fioapi.fio.cz/v1/rest/periods/test-token/{0}/{0}/transactions.json"
)
FIO_TRASACTIONS = {
"accountStatement": {
"info": {
Expand All @@ -61,7 +64,7 @@
"bic": "FIOBCZPPXXX",
"yearList": None,
"idTo": 10000000001,
"currency": "CZK",
"currency": "EUR",
"openingBalance": 2543.81,
"iban": "CZ1220100000001234567890",
"idFrom": 10000000002,
Expand Down Expand Up @@ -263,6 +266,13 @@ def test_proforma(self):
self.assertFalse(backend.complete(None))
self.check_payment(Payment.PENDING)
responses.add(responses.GET, FIO_API, body=json.dumps(FIO_TRASACTIONS))
responses.add(
responses.GET,
FIO_INFO_API.format(
date.today().isoformat() # noqa: DTZ011
),
body=json.dumps(FIO_TRASACTIONS),
)
FioBank.fetch_payments()
self.check_payment(Payment.PENDING)
self.assertEqual(len(mail.outbox), 1)
Expand Down
2 changes: 1 addition & 1 deletion weblate_web/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@

NOTIFY_SUBSCRIPTION: list[str] = []

FIO_TOKEN = None
FIO_TOKEN: str | list[str] = []

COMPRESS_OFFLINE = True
COMPRESS_OFFLINE_CONTEXT = [
Expand Down

0 comments on commit b1dd850

Please sign in to comment.