Skip to content

Commit

Permalink
chore: consolidate bank account information
Browse files Browse the repository at this point in the history
  • Loading branch information
nijel committed Nov 14, 2024
1 parent feb29ea commit 8d24421
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 44 deletions.
129 changes: 123 additions & 6 deletions weblate_web/invoices/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from decimal import Decimal
from pathlib import Path
from shutil import copyfile
from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, Literal, cast

import qrcode
import qrcode.image.svg
Expand All @@ -37,14 +37,18 @@
from django.template.loader import render_to_string
from django.utils.functional import cached_property
from django.utils.safestring import mark_safe
from django.utils.translation import override
from django.utils.translation import gettext, override
from fakturace.rates import DecimalRates
from lxml import etree

from weblate_web.pdf import render_pdf
from weblate_web.utils import get_site_url

if TYPE_CHECKING:
from collections.abc import Generator

Check warning on line 48 in weblate_web/invoices/models.py

View check run for this annotation

Codecov / codecov/patch

weblate_web/invoices/models.py#L48

Added line #L48 was not covered by tests

from django_stubs_ext import StrOrPromise

Check warning on line 50 in weblate_web/invoices/models.py

View check run for this annotation

Codecov / codecov/patch

weblate_web/invoices/models.py#L50

Added line #L50 was not covered by tests

from weblate_web.payments.models import Payment

INVOICES_URL = "invoices:"
Expand Down Expand Up @@ -101,6 +105,115 @@ class Currency(models.IntegerChoices):
GBP = 3, "GBP"


InfoType = Literal["number", "short_number", "iban", "bic", "bank", "holder"]


class BankAccountInfo:
def __init__( # noqa: PLR0913
self,
*,
number: str,
bank: str,
iban: str,
bic: str,
holder: str = "Weblate s.r.o.",
short_list: tuple[InfoType, ...],
):
self._number = number
self._bank = bank
self._iban = iban
self._bic = bic
self._holder = holder
self._short_list = short_list

@property
def number(self) -> str:
return self._number

@property
def short_number(self) -> str:
return self._number.split("/")[0].strip()

@property
def bank(self) -> str:
return self._bank

@property
def iban(self) -> str:
return self._iban

Check warning on line 143 in weblate_web/invoices/models.py

View check run for this annotation

Codecov / codecov/patch

weblate_web/invoices/models.py#L143

Added line #L143 was not covered by tests

@property
def raw_iban(self) -> str:
return self._iban.replace(" ", "")

@property
def bic(self) -> str:
return self._bic

@property
def holder(self) -> str:
return self._holder

def get_info(self, *items: InfoType) -> Generator[tuple[StrOrPromise, str]]:
for item in items:
if item == "iban":
yield (gettext("IBAN"), self._iban)
elif item == "number":
yield (gettext("Account number"), self._number)
elif item == "short_number":
yield (gettext("Account number"), self.short_number)
elif item == "bic":
yield (gettext("BIC/SWIFT"), self._bic)
elif item == "bank":
yield (gettext("Issuing bank"), self._bank)
elif item == "holder":
yield (gettext("Account holder"), self._holder)
else:
raise ValueError(f"Unknown info type: {item}")

Check warning on line 172 in weblate_web/invoices/models.py

View check run for this annotation

Codecov / codecov/patch

weblate_web/invoices/models.py#L172

Added line #L172 was not covered by tests

def get_full_info(self) -> list[tuple[StrOrPromise, str]]:
return list(self.get_info("iban", "number", "bic", "bank", "holder"))

def get_short_info(self) -> list[tuple[StrOrPromise, str]]:
return list(self.get_info(*self._short_list))


FIO_BANK: str = "Fio banka, a.s., Na Florenci 2139/2, 11000 Praha, Czechia"
FIO_BIC: str = "FIOBCZPPXXX"


BANK_ACCOUNTS: dict[Currency, BankAccountInfo] = {
Currency.EUR: BankAccountInfo(
number="2302907395 / 2010",
bank=FIO_BANK,
iban="CZ30 2010 0000 0023 0290 7395",
bic=FIO_BIC,
short_list=("iban",),
),
Currency.CZK: BankAccountInfo(
number="2002907393 / 2010",
bank=FIO_BANK,
iban="CZ49 2010 0000 0020 0290 7393",
bic=FIO_BIC,
short_list=("number",),
),
Currency.USD: BankAccountInfo(
number="2603015278 / 2010",
bank=FIO_BANK,
iban="CZ37 2010 0000 0026 0301 5278",
bic=FIO_BIC,
short_list=("short_number", "bic"),
),
Currency.GBP: BankAccountInfo(
number="2803015280 / 2010",
bank=FIO_BANK,
iban="CZ71 2010 0000 0028 0301 5280",
bic=FIO_BIC,
short_list=("short_number", "bic"),
),
}


class InvoiceKind(models.IntegerChoices):
DRAFT = 0, "Draft"
INVOICE = 10, "Invoice"
Expand Down Expand Up @@ -231,6 +344,10 @@ def exchange_rate_czk(self) -> Decimal:
self.issue_date.isoformat(), self.get_currency_display()
)

@cached_property
def bank_account(self) -> BankAccountInfo:
return BANK_ACCOUNTS[cast(Currency, self.currency)]

@cached_property
def exchange_rate_eur(self) -> Decimal:
"""Exchange rate from currency to EUR."""
Expand Down Expand Up @@ -531,17 +648,17 @@ def get_payment_qrcode(self) -> str:
001
1
SCT
FIOBCZPPXXX
Weblate s.r.o.
CZ3020100000002302907395
{self.bank_account.bic}
{self.bank_account.holder}
{self.bank_account.raw_iban}
EUR{self.total_amount}
{self.number}
"""
elif self.currency == Currency.CZK:
data = f"SPD*1.0*ACC:CZ3020100000002302907395*AM:{self.total_amount}*CC:CZK*RF:{self.number}*RN:Weblate s.r.o"
data = f"SPD*1.0*ACC:{self.bank_account.raw_iban}*AM:{self.total_amount}*CC:CZK*RF:{self.number}*RN:{self.bank_account.holder}"

Check warning on line 661 in weblate_web/invoices/models.py

View check run for this annotation

Codecov / codecov/patch

weblate_web/invoices/models.py#L661

Added line #L661 was not covered by tests
else:
return ""

Expand Down
32 changes: 7 additions & 25 deletions weblate_web/invoices/templates/invoice-template.html
Original file line number Diff line number Diff line change
Expand Up @@ -167,18 +167,10 @@ <h2>Issued by</h2>
{% else %}
Bank transfer
<br />
{% if invoice.get_currency_display == "CZK" %}
Bank account: 2002907393 / 2010
{% elif invoice.get_currency_display == "EUR" %}
IBAN: CZ30 2010 0000 0023 0290 7395
{% elif invoice.get_currency_display == "USD" %}
Bank account: 2603015278
BIC/SWIFT: FIOBCZPPXXX
{% elif invoice.get_currency_display == "GBP" %}
Bank account: 2803015280
BIC/SWIFT: FIOBCZPPXXX
{% endif %}
<br />
{% for item, value in invoice.bank_account.get_short_info %}
{{ item }}: {{ value }}
<br />
{% endfor %}
Reference: {{ invoice.number }}
<br />
{% endif %}
Expand Down Expand Up @@ -235,19 +227,9 @@ <h2>Issued by</h2>
</tr>
<tr>
<td>Weblate s.r.o.</td>
<td>
{% if invoice.get_currency_display == "CZK" %}
2002907393 / 2010
{% elif invoice.get_currency_display == "EUR" %}
2302907395 / 2010
{% elif invoice.get_currency_display == "USD" %}
2603015278 / 2010
{% elif invoice.get_currency_display == "GBP" %}
2803015280 / 2010
{% endif %}
</td>
<td>FIOBCZPPXXX</td>
<td>Fio banka, a.s., Na Florenci 2139/2, 11000 Praha, Czechia</td>
<td>{{ invoice.bank_account.number }}</td>
<td>{{ invoice.bank_account.bic }}</td>
<td>{{ invoice.bank_account.bank }}</td>
<td class="thanks">♥ Thank you!</td>
</tr>
</tbody>
Expand Down
19 changes: 6 additions & 13 deletions weblate_web/payments/backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ def collect(self, request: HttpRequest | None) -> bool | None:
"""Collect payment information."""
raise NotImplementedError

def get_instructions(self) -> list[tuple[StrOrPromise, StrOrPromise]]:
def get_instructions(self) -> list[tuple[StrOrPromise, str]]:
"""Payment instructions for manual methods."""
return []

Expand Down Expand Up @@ -544,20 +544,13 @@ def perform(
self.send_notification("payment_pending")
return redirect(complete_url)

def get_instructions(self) -> list[tuple[StrOrPromise, StrOrPromise]]:
def get_instructions(self) -> list[tuple[StrOrPromise, str]]:
from weblate_web.invoices.models import Invoice # noqa: PLC0415

return [
(
gettext("Issuing bank"),
"Fio banka, a.s., Na Florenci 2139/2, 11000 Praha, Czechia",
),
(gettext("Account holder"), "Weblate s.r.o."),
(gettext("Account number"), "2302907395 / 2010"),
(gettext("SWIFT code"), "FIOBCZPPXXX"),
(gettext("IBAN"), "CZ30 2010 0000 0023 0290 7395"),
(gettext("Reference"), cast(Invoice, self.payment.draft_invoice).number),
]
invoice = cast(Invoice, self.payment.draft_invoice)
instructions = invoice.bank_account.get_full_info()
instructions.append((gettext("Reference"), invoice.number))
return instructions

@classmethod
def fetch_payments(cls, from_date: str | None = None) -> None:
Expand Down

0 comments on commit 8d24421

Please sign in to comment.