Skip to content
Draft
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
9 changes: 9 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ jobs:
run: |
sudo apt update
sudo apt install gettext
- name: Start validation service
env:
# renovate: datasource=github-releases depName=gflohr/e-invoice-eu-validator versioning=loose
VALIDATOR_VERSION: 2.16.4
run: |
curl -L "https://github.com/gflohr/e-invoice-eu-validator/releases/download/v$VALIDATOR_VERSION/validator-$VALIDATOR_VERSION-jar-with-dependencies.jar" > /tmp/validator.jar
PORT=7070 java -jar /tmp/validator.jar &
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
with:
Expand All @@ -63,6 +70,8 @@ jobs:
run: ./manage.py collectstatic
- name: Django checks
run: ./manage.py check
env:
EINVOICE_VALIDATOR_URL: http://localhost:7070/
- name: Test with Django
run: |
pytest --junitxml=junit.xml weblate_web
Expand Down
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ django-redis==6.0.0
django-stubs-ext==5.2.8
django-vies==6.2.2
djangosaml2==1.11.1
drafthorse==2025.2.0
fiobank==4.0.0
hiredis==3.3.0
html2text==2025.4.15
Expand All @@ -20,6 +21,7 @@ mysqlclient==2.2.7
paramiko==4.0.0
Pillow==12.0.0
psycopg[binary]==3.3.2
PyCheval==0.3.0
pyopenssl==25.3.0
python-dateutil==2.9.0.post0
pytz==2025.2
Expand Down
163 changes: 162 additions & 1 deletion weblate_web/invoices/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,23 @@
from django.utils.timezone import now
from django.utils.translation import gettext, override
from lxml import etree
from pycheval import (
BankAccount,
EN16931Invoice,
EN16931LineItem,
Money,
PaymentMeans,
PaymentTerms,
PostalAddress,
Tax,
TradeParty,
generate_xml,
)

# TODO: consider https://pypi.org/project/pyfactx/ instead of pycheval
from pycheval.quantities import QuantityCode
from pycheval.type_codes import DocumentTypeCode, PaymentMeansCode, TaxCategoryCode
from weasyprint import Attachment

from weblate_web.exchange_rates import ExchangeRates
from weblate_web.pdf import render_pdf
Expand Down Expand Up @@ -540,8 +557,14 @@
"""XML path object."""
return settings.INVOICES_PATH / self.get_filename("xml")

@property
def en_16931_xml_path(self) -> Path:
"""XML path object."""
return settings.INVOICES_PATH / self.get_filename("einvoice.xml")

def generate_files(self) -> None:
self.generate_money_s3_xml()
self.generate_en_16931_xml()
self.generate_pdf()
self.sync_files()

Expand Down Expand Up @@ -657,7 +680,7 @@
add_element(adresa, "Ulice", self.customer.address)
add_element(adresa, "Misto", self.customer.city)
add_element(adresa, "PSC", self.customer.postcode)
add_element(adresa, "Stat", self.customer.country)
add_element(adresa, "Stat", self.customer.country.code)
if self.customer.vat:
add_element(prijemce, "PlatceDPH", "1")
add_element(prijemce, "FyzOsoba", "0")
Expand Down Expand Up @@ -690,13 +713,151 @@
settings.INVOICES_PATH.mkdir(exist_ok=True)
self.save_invoice_xml(document, self.xml_path)

def get_en_16931_xml(self) -> EN16931Invoice:
type_code = DocumentTypeCode.INVOICING_DATA_SHEET
if self.kind == InvoiceKind.INVOICE:
type_code = DocumentTypeCode.INVOICE
elif self.kind == InvoiceKind.QUOTE:
type_code = DocumentTypeCode.VALIDATED_PRICED_TENDER
elif self.kind == InvoiceKind.PROFORMA:
type_code = DocumentTypeCode.PRO_FORMA_INVOICE
total_amount = Money(self.total_amount, self.get_currency_display())

tax_amount = Money(self.total_vat, self.get_currency_display())
tax_basis_amount = Money(self.total_amount_no_vat, self.get_currency_display())

tax_category = (
TaxCategoryCode.STANDARD_RATE
if self.vat_rate
else TaxCategoryCode.REVERSE_CHARGE
)
tax = Tax(
category_code=tax_category,
calculated_amount=tax_amount,
basis_amount=tax_basis_amount,
rate_percent=self.vat_rate or None,

Check failure on line 738 in weblate_web/invoices/models.py

View workflow job for this annotation

GitHub Actions / mypy

Argument "rate_percent" to "Tax" has incompatible type "int | None"; expected "Decimal | None"

Check failure on line 738 in weblate_web/invoices/models.py

View workflow job for this annotation

GitHub Actions / mypy

Argument "rate_percent" to "Tax" has incompatible type "int | None"; expected "Decimal | None"
exemption_reason="Reverse charge" if not self.vat_rate else None,
)

line_items = [
EN16931LineItem(
id=item.package.name if item.package else "ITEM",
name=item.description,
net_price=Money(item.unit_price, self.get_currency_display()),
billed_quantity=(

Check failure on line 747 in weblate_web/invoices/models.py

View workflow job for this annotation

GitHub Actions / mypy

Argument "billed_quantity" to "EN16931LineItem" has incompatible type "tuple[int, QuantityCode]"; expected "tuple[Decimal, QuantityCode]"

Check failure on line 747 in weblate_web/invoices/models.py

View workflow job for this annotation

GitHub Actions / mypy

Argument "billed_quantity" to "EN16931LineItem" has incompatible type "tuple[int, QuantityCode]"; expected "tuple[Decimal, QuantityCode]"
item.quantity,
QuantityCode.ONE,
), # TODO: convert quantity_unit to QuantityCode
billed_total=Money(item.total_price, self.get_currency_display()),
tax_rate=self.vat_rate or None,

Check failure on line 752 in weblate_web/invoices/models.py

View workflow job for this annotation

GitHub Actions / mypy

Argument "tax_rate" to "EN16931LineItem" has incompatible type "int | None"; expected "Decimal | None"

Check failure on line 752 in weblate_web/invoices/models.py

View workflow job for this annotation

GitHub Actions / mypy

Argument "tax_rate" to "EN16931LineItem" has incompatible type "int | None"; expected "Decimal | None"
tax_category=tax_category,
billing_period=(item.start_date, item.end_date)

Check failure on line 754 in weblate_web/invoices/models.py

View workflow job for this annotation

GitHub Actions / mypy

Argument "billing_period" to "EN16931LineItem" has incompatible type "tuple[date | None, date | None] | None"; expected "tuple[date, date] | None"

Check failure on line 754 in weblate_web/invoices/models.py

View workflow job for this annotation

GitHub Actions / mypy

Argument "billing_period" to "EN16931LineItem" has incompatible type "tuple[date | None, date | None] | None"; expected "tuple[date, date] | None"
if item.has_date_range
else None,
)
for item in self.all_items
]
# TODO: There might be model for discount
if self.discount:
line_items.append(
EN16931LineItem(
id="DISCOUNT",
name=self.discount.description,
description=self.discount.display_percents,
net_price=Money(self.total_discount, self.get_currency_display()),
billed_quantity=(1, QuantityCode.ONE),

Check failure on line 768 in weblate_web/invoices/models.py

View workflow job for this annotation

GitHub Actions / mypy

Argument "billed_quantity" to "EN16931LineItem" has incompatible type "tuple[int, QuantityCode]"; expected "tuple[Decimal, QuantityCode]"

Check failure on line 768 in weblate_web/invoices/models.py

View workflow job for this annotation

GitHub Actions / mypy

Argument "billed_quantity" to "EN16931LineItem" has incompatible type "tuple[int, QuantityCode]"; expected "tuple[Decimal, QuantityCode]"
billed_total=Money(
self.total_discount, self.get_currency_display()
),
tax_rate=self.vat_rate,

Check failure on line 772 in weblate_web/invoices/models.py

View workflow job for this annotation

GitHub Actions / mypy

Argument "tax_rate" to "EN16931LineItem" has incompatible type "int"; expected "Decimal | None"

Check failure on line 772 in weblate_web/invoices/models.py

View workflow job for this annotation

GitHub Actions / mypy

Argument "tax_rate" to "EN16931LineItem" has incompatible type "int"; expected "Decimal | None"
Copy link

Copilot AI Nov 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The discount line item should use self.vat_rate or None for consistency with other line items (line 740). When vat_rate is 0 (falsy), the tax_rate should be None, not 0.

Suggested change
tax_rate=self.vat_rate,
tax_rate=self.vat_rate or None,

Copilot uses AI. Check for mistakes.
tax_category=tax_category,
)
)

payment_means = []
if self.prepaid:
prepaid_amount = total_amount
due_payable_amount = Money(Decimal(0), self.get_currency_display())
payment_reference = None
payment_terms = None
else:
prepaid_amount = None
due_payable_amount = total_amount
payment_reference = self.number
if self.currency == Currency.EUR:
# TODO: support other currencies here
payment_means = [
PaymentMeans(
type_code=PaymentMeansCode.BANK_PAYMENT,
payee_account=BankAccount(
name=self.bank_account.holder,
bank_id=self.bank_account.bic,
iban=self.bank_account.raw_iban,
),
payee_bic=self.bank_account.bic,
)
]
payment_terms = PaymentTerms(due_date=self.due_date)

return EN16931Invoice(
invoice_number=self.number,
invoice_date=self.issue_date,
currency_code=self.get_currency_display(),
grand_total_amount=total_amount,
tax_basis_total_amount=total_amount,
tax_total_amounts=[tax_amount] if self.vat_rate else [],
due_payable_amount=due_payable_amount,
prepaid_amount=prepaid_amount,
payment_reference=payment_reference,
payment_means=payment_means,
payment_terms=payment_terms,
line_total_amount=total_amount,
line_items=line_items,
type_code=type_code,
seller=TradeParty(
name="Weblate s.r.o.",
address=PostalAddress(
country_code="CZ",
post_code="471 54",
city="Cvikov",
line_one="Nábřežní 694",
),
vat_id="CZ21668027",
),
buyer=TradeParty(
name=self.customer.name,
address=PostalAddress(
country_code=self.customer.country.code,
post_code=self.customer.postcode,
city=self.customer.city,
line_one=self.customer.address,
line_two=self.customer.address_2 or None,
),
vat_id=self.customer.vat or None,
),
tax=[tax],
)

Check failure on line 839 in weblate_web/invoices/models.py

View workflow job for this annotation

GitHub Actions / pylint

E1123

Unexpected keyword argument 'type_code' in constructor call

Check failure on line 839 in weblate_web/invoices/models.py

View workflow job for this annotation

GitHub Actions / pylint

E1123

Unexpected keyword argument 'line_items' in constructor call

Check failure on line 839 in weblate_web/invoices/models.py

View workflow job for this annotation

GitHub Actions / pylint

E1123

Unexpected keyword argument 'line_total_amount' in constructor call

Check failure on line 839 in weblate_web/invoices/models.py

View workflow job for this annotation

GitHub Actions / pylint

E1123

Unexpected keyword argument 'due_payable_amount' in constructor call

Check failure on line 839 in weblate_web/invoices/models.py

View workflow job for this annotation

GitHub Actions / pylint

E1123

Unexpected keyword argument 'tax_total_amounts' in constructor call

Check failure on line 839 in weblate_web/invoices/models.py

View workflow job for this annotation

GitHub Actions / pylint

E1123

Unexpected keyword argument 'tax_basis_total_amount' in constructor call

Check failure on line 839 in weblate_web/invoices/models.py

View workflow job for this annotation

GitHub Actions / pylint

E1123

Unexpected keyword argument 'grand_total_amount' in constructor call

Check failure on line 839 in weblate_web/invoices/models.py

View workflow job for this annotation

GitHub Actions / pylint

E1123

Unexpected keyword argument 'currency_code' in constructor call

Check failure on line 839 in weblate_web/invoices/models.py

View workflow job for this annotation

GitHub Actions / pylint

E1123

Unexpected keyword argument 'invoice_date' in constructor call

Check failure on line 839 in weblate_web/invoices/models.py

View workflow job for this annotation

GitHub Actions / pylint

E1123

Unexpected keyword argument 'invoice_number' in constructor call

Check failure on line 839 in weblate_web/invoices/models.py

View workflow job for this annotation

GitHub Actions / pylint

E1123

Unexpected keyword argument 'type_code' in constructor call

Check failure on line 839 in weblate_web/invoices/models.py

View workflow job for this annotation

GitHub Actions / pylint

E1123

Unexpected keyword argument 'line_items' in constructor call

Check failure on line 839 in weblate_web/invoices/models.py

View workflow job for this annotation

GitHub Actions / pylint

E1123

Unexpected keyword argument 'line_total_amount' in constructor call

Check failure on line 839 in weblate_web/invoices/models.py

View workflow job for this annotation

GitHub Actions / pylint

E1123

Unexpected keyword argument 'due_payable_amount' in constructor call

Check failure on line 839 in weblate_web/invoices/models.py

View workflow job for this annotation

GitHub Actions / pylint

E1123

Unexpected keyword argument 'tax_total_amounts' in constructor call

Check failure on line 839 in weblate_web/invoices/models.py

View workflow job for this annotation

GitHub Actions / pylint

E1123

Unexpected keyword argument 'tax_basis_total_amount' in constructor call

Check failure on line 839 in weblate_web/invoices/models.py

View workflow job for this annotation

GitHub Actions / pylint

E1123

Unexpected keyword argument 'grand_total_amount' in constructor call

Check failure on line 839 in weblate_web/invoices/models.py

View workflow job for this annotation

GitHub Actions / pylint

E1123

Unexpected keyword argument 'currency_code' in constructor call

Check failure on line 839 in weblate_web/invoices/models.py

View workflow job for this annotation

GitHub Actions / pylint

E1123

Unexpected keyword argument 'invoice_date' in constructor call

Check failure on line 839 in weblate_web/invoices/models.py

View workflow job for this annotation

GitHub Actions / pylint

E1123

Unexpected keyword argument 'invoice_number' in constructor call

def generate_en_16931_xml(self) -> None:
invoice = self.get_en_16931_xml()
xml_string = generate_xml(invoice)
self.en_16931_xml_path.write_text(xml_string)

def generate_pdf(self) -> None:
"""Render invoice as PDF."""
# Create directory to store invoices
settings.INVOICES_PATH.mkdir(exist_ok=True)
render_pdf(
html=self.render_html(),
output=settings.INVOICES_PATH / self.filename,
pdf_variant="pdf/a-3b",
attachments=[
Attachment(
string=generate_xml(self.get_en_16931_xml()),
base_url="factur-x.xml",
description="Factur-x invoice",
)
],
)

def duplicate( # noqa: PLR0913
Expand Down
22 changes: 22 additions & 0 deletions weblate_web/invoices/tests.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
from __future__ import annotations

import os
from datetime import date, timedelta
from decimal import Decimal
from pathlib import Path
from typing import cast

import requests
from django.test.utils import override_settings
from drafthorse.utils import validate_xml

Check failure on line 11 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / mypy

Skipping analyzing "drafthorse.utils": module is installed, but missing library stubs or py.typed marker

Check failure on line 11 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / mypy

Skipping analyzing "drafthorse.utils": module is installed, but missing library stubs or py.typed marker
from lxml import etree

from weblate_web.models import Package, PackageCategory
Expand Down Expand Up @@ -121,6 +124,25 @@
xml_doc = etree.parse(invoice.xml_path)
S3_SCHEMA.assertValid(xml_doc)

einvoice = invoice.en_16931_xml_path.read_bytes()
validate_xml(einvoice, "FACTUR-X_EN16931")

if validator_url := os.environ.get("VALIDATOR_URL"):
# Validate standalone eInvoice
response = requests.post(
f"{validator_url}validate",
files={"invoice": einvoice},
timeout=20,
)
self.assertEqual(response.status_code, 200, response.text)
# Validate eInvoice included in the PDF
response = requests.post(
f"{validator_url}validate",
files={"invoice": invoice.path.read_bytes()},
timeout=20,
)
self.assertEqual(response.status_code, 200, response.text)

def test_dates(self) -> None:
invoice = self.create_invoice(vat="CZ8003280318")
self.assertEqual(invoice.tax_date, invoice.issue_date)
Expand All @@ -136,7 +158,7 @@
def test_total(self) -> None:
invoice = self.create_invoice(vat="CZ8003280318")
self.assertEqual(invoice.total_amount, 100)
self.validate_invoice(invoice)

Check failure on line 161 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, mariadb

InvoiceTestCase.test_total AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 161 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, sqlite

InvoiceTestCase.test_total AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 161 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, sqlite

InvoiceTestCase.test_total AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 161 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, mariadb

InvoiceTestCase.test_total AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 161 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, mariadb

InvoiceTestCase.test_total AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 161 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, postgresql

InvoiceTestCase.test_total AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 161 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, sqlite

InvoiceTestCase.test_total AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 161 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, sqlite

InvoiceTestCase.test_total AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 161 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, postgresql

InvoiceTestCase.test_total AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 161 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, mariadb

InvoiceTestCase.test_total AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 161 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, mariadb

InvoiceTestCase.test_total AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 161 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, postgresql

InvoiceTestCase.test_total AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 161 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, postgresql

InvoiceTestCase.test_total AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 161 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, sqlite

InvoiceTestCase.test_total AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 161 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, mariadb

InvoiceTestCase.test_total AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 161 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, postgresql

InvoiceTestCase.test_total AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 161 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, postgresql

InvoiceTestCase.test_total AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 161 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, sqlite

InvoiceTestCase.test_total AttributeError: 'HTML' object has no attribute 'metadata'

def test_total_vat(self) -> None:
invoice = self.create_invoice(vat_rate=21, customer_reference="PO123456")
Expand Down Expand Up @@ -185,7 +207,7 @@
discount=Discount.objects.create(description="Test discount", percents=50)
)
self.assertEqual(invoice.total_amount, 50)
self.validate_invoice(invoice)

Check failure on line 210 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, mariadb

InvoiceTestCase.test_discount AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 210 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, sqlite

InvoiceTestCase.test_discount AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 210 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, sqlite

InvoiceTestCase.test_discount AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 210 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, mariadb

InvoiceTestCase.test_discount AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 210 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, mariadb

InvoiceTestCase.test_discount AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 210 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, postgresql

InvoiceTestCase.test_discount AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 210 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, sqlite

InvoiceTestCase.test_discount AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 210 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, sqlite

InvoiceTestCase.test_discount AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 210 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, postgresql

InvoiceTestCase.test_discount AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 210 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, mariadb

InvoiceTestCase.test_discount AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 210 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, mariadb

InvoiceTestCase.test_discount AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 210 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, postgresql

InvoiceTestCase.test_discount AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 210 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, postgresql

InvoiceTestCase.test_discount AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 210 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, sqlite

InvoiceTestCase.test_discount AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 210 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, mariadb

InvoiceTestCase.test_discount AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 210 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, postgresql

InvoiceTestCase.test_discount AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 210 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, postgresql

InvoiceTestCase.test_discount AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 210 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, sqlite

InvoiceTestCase.test_discount AttributeError: 'HTML' object has no attribute 'metadata'

def test_discount_negative(self) -> None:
invoice = self.create_invoice(
Expand All @@ -193,7 +215,7 @@
)
invoice.invoiceitem_set.create(description="Prepaid amount", unit_price=-10)
self.assertEqual(invoice.total_amount, 40)
self.validate_invoice(invoice)

Check failure on line 218 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, mariadb

InvoiceTestCase.test_discount_negative AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 218 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, sqlite

InvoiceTestCase.test_discount_negative AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 218 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, sqlite

InvoiceTestCase.test_discount_negative AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 218 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, mariadb

InvoiceTestCase.test_discount_negative AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 218 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, mariadb

InvoiceTestCase.test_discount_negative AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 218 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, postgresql

InvoiceTestCase.test_discount_negative AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 218 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, sqlite

InvoiceTestCase.test_discount_negative AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 218 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, sqlite

InvoiceTestCase.test_discount_negative AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 218 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, postgresql

InvoiceTestCase.test_discount_negative AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 218 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, mariadb

InvoiceTestCase.test_discount_negative AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 218 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, mariadb

InvoiceTestCase.test_discount_negative AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 218 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, postgresql

InvoiceTestCase.test_discount_negative AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 218 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, postgresql

InvoiceTestCase.test_discount_negative AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 218 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, sqlite

InvoiceTestCase.test_discount_negative AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 218 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, mariadb

InvoiceTestCase.test_discount_negative AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 218 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, postgresql

InvoiceTestCase.test_discount_negative AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 218 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, postgresql

InvoiceTestCase.test_discount_negative AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 218 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, sqlite

InvoiceTestCase.test_discount_negative AttributeError: 'HTML' object has no attribute 'metadata'

def test_discount_vat(self) -> None:
invoice = self.create_invoice(
Expand All @@ -201,12 +223,12 @@
vat_rate=21,
)
self.assertEqual(invoice.total_amount, Decimal("60.50"))
self.validate_invoice(invoice)

Check failure on line 226 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, mariadb

InvoiceTestCase.test_discount_vat pycheval.exc.ModelError: Calculated amount EUR 10.5 does not match basis amount EUR 50 and tax rate 21 %.

Check failure on line 226 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, sqlite

InvoiceTestCase.test_discount_vat pycheval.exc.ModelError: Calculated amount EUR 10.5 does not match basis amount EUR 50 and tax rate 21 %.

Check failure on line 226 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, sqlite

InvoiceTestCase.test_discount_vat pycheval.exc.ModelError: Calculated amount EUR 10.5 does not match basis amount EUR 50 and tax rate 21 %.

Check failure on line 226 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, mariadb

InvoiceTestCase.test_discount_vat pycheval.exc.ModelError: Calculated amount EUR 10.5 does not match basis amount EUR 50 and tax rate 21 %.

Check failure on line 226 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, mariadb

InvoiceTestCase.test_discount_vat pycheval.exc.ModelError: Calculated amount EUR 10.5 does not match basis amount EUR 50 and tax rate 21 %.

Check failure on line 226 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, postgresql

InvoiceTestCase.test_discount_vat pycheval.exc.ModelError: Calculated amount EUR 10.5 does not match basis amount EUR 50 and tax rate 21 %.

Check failure on line 226 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, sqlite

InvoiceTestCase.test_discount_vat pycheval.exc.ModelError: Calculated amount EUR 10.5 does not match basis amount EUR 50 and tax rate 21 %.

Check failure on line 226 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, sqlite

InvoiceTestCase.test_discount_vat pycheval.exc.ModelError: Calculated amount EUR 10.5 does not match basis amount EUR 50 and tax rate 21 %.

Check failure on line 226 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, postgresql

InvoiceTestCase.test_discount_vat pycheval.exc.ModelError: Calculated amount EUR 10.5 does not match basis amount EUR 50 and tax rate 21 %.

Check failure on line 226 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, mariadb

InvoiceTestCase.test_discount_vat pycheval.exc.ModelError: Calculated amount EUR 10.5 does not match basis amount EUR 50 and tax rate 21 %.

Check failure on line 226 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, mariadb

InvoiceTestCase.test_discount_vat pycheval.exc.ModelError: Calculated amount EUR 10.5 does not match basis amount EUR 50 and tax rate 21 %.

Check failure on line 226 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, postgresql

InvoiceTestCase.test_discount_vat pycheval.exc.ModelError: Calculated amount EUR 10.5 does not match basis amount EUR 50 and tax rate 21 %.

Check failure on line 226 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, postgresql

InvoiceTestCase.test_discount_vat pycheval.exc.ModelError: Calculated amount EUR 10.5 does not match basis amount EUR 50 and tax rate 21 %.

Check failure on line 226 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, sqlite

InvoiceTestCase.test_discount_vat pycheval.exc.ModelError: Calculated amount EUR 10.5 does not match basis amount EUR 50 and tax rate 21 %.

Check failure on line 226 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, mariadb

InvoiceTestCase.test_discount_vat pycheval.exc.ModelError: Calculated amount EUR 10.5 does not match basis amount EUR 50 and tax rate 21 %.

Check failure on line 226 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, postgresql

InvoiceTestCase.test_discount_vat pycheval.exc.ModelError: Calculated amount EUR 10.5 does not match basis amount EUR 50 and tax rate 21 %.

Check failure on line 226 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, postgresql

InvoiceTestCase.test_discount_vat pycheval.exc.ModelError: Calculated amount EUR 10.5 does not match basis amount EUR 50 and tax rate 21 %.

Check failure on line 226 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, sqlite

InvoiceTestCase.test_discount_vat pycheval.exc.ModelError: Calculated amount EUR 10.5 does not match basis amount EUR 50 and tax rate 21 %.

def test_package(self) -> None:
invoice = self.create_invoice_package()
self.assertEqual(invoice.total_amount, Decimal(100))
self.validate_invoice(invoice)

Check failure on line 231 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, mariadb

InvoiceTestCase.test_package AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 231 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, sqlite

InvoiceTestCase.test_package AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 231 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, sqlite

InvoiceTestCase.test_package AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 231 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, mariadb

InvoiceTestCase.test_package AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 231 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, mariadb

InvoiceTestCase.test_package AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 231 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, postgresql

InvoiceTestCase.test_package AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 231 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, sqlite

InvoiceTestCase.test_package AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 231 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, sqlite

InvoiceTestCase.test_package AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 231 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, postgresql

InvoiceTestCase.test_package AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 231 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, mariadb

InvoiceTestCase.test_package AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 231 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, mariadb

InvoiceTestCase.test_package AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 231 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, postgresql

InvoiceTestCase.test_package AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 231 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, postgresql

InvoiceTestCase.test_package AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 231 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, sqlite

InvoiceTestCase.test_package AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 231 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, mariadb

InvoiceTestCase.test_package AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 231 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, postgresql

InvoiceTestCase.test_package AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 231 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, postgresql

InvoiceTestCase.test_package AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 231 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, sqlite

InvoiceTestCase.test_package AttributeError: 'HTML' object has no attribute 'metadata'

def test_package_usd(self) -> None:
invoice = self.create_invoice_package(currency=Currency.USD)
Expand All @@ -214,17 +236,17 @@
invoice.total_amount,
round(Decimal(100) * invoice.exchange_rate_eur * Decimal("1.1"), 0),
)
self.validate_invoice(invoice)

Check failure on line 239 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, mariadb

InvoiceTestCase.test_package_usd AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 239 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, sqlite

InvoiceTestCase.test_package_usd AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 239 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, sqlite

InvoiceTestCase.test_package_usd AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 239 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, mariadb

InvoiceTestCase.test_package_usd AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 239 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, mariadb

InvoiceTestCase.test_package_usd AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 239 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, postgresql

InvoiceTestCase.test_package_usd AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 239 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, sqlite

InvoiceTestCase.test_package_usd AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 239 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, sqlite

InvoiceTestCase.test_package_usd AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 239 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, postgresql

InvoiceTestCase.test_package_usd AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 239 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, mariadb

InvoiceTestCase.test_package_usd AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 239 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, mariadb

InvoiceTestCase.test_package_usd AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 239 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, postgresql

InvoiceTestCase.test_package_usd AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 239 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, postgresql

InvoiceTestCase.test_package_usd AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 239 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, sqlite

InvoiceTestCase.test_package_usd AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 239 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, mariadb

InvoiceTestCase.test_package_usd AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 239 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, postgresql

InvoiceTestCase.test_package_usd AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 239 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, postgresql

InvoiceTestCase.test_package_usd AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 239 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, sqlite

InvoiceTestCase.test_package_usd AttributeError: 'HTML' object has no attribute 'metadata'

def test_invoice_kinds(self) -> None:
for kind in InvoiceKind.values:
invoice = self.create_invoice(kind=InvoiceKind(kind))
self.validate_invoice(invoice)

Check failure on line 244 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, mariadb

InvoiceTestCase.test_invoice_kinds pycheval.exc.ModelError: Invalid invoice type code: 130.

Check failure on line 244 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, sqlite

InvoiceTestCase.test_invoice_kinds pycheval.exc.ModelError: Invalid invoice type code: 130.

Check failure on line 244 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, sqlite

InvoiceTestCase.test_invoice_kinds pycheval.exc.ModelError: Invalid invoice type code: 130.

Check failure on line 244 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, mariadb

InvoiceTestCase.test_invoice_kinds pycheval.exc.ModelError: Invalid invoice type code: 130.

Check failure on line 244 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, mariadb

InvoiceTestCase.test_invoice_kinds pycheval.exc.ModelError: Invalid invoice type code: 130.

Check failure on line 244 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, postgresql

InvoiceTestCase.test_invoice_kinds pycheval.exc.ModelError: Invalid invoice type code: 130.

Check failure on line 244 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, sqlite

InvoiceTestCase.test_invoice_kinds pycheval.exc.ModelError: Invalid invoice type code: 130.

Check failure on line 244 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, sqlite

InvoiceTestCase.test_invoice_kinds pycheval.exc.ModelError: Invalid invoice type code: 130.

Check failure on line 244 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, postgresql

InvoiceTestCase.test_invoice_kinds pycheval.exc.ModelError: Invalid invoice type code: 130.

Check failure on line 244 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, mariadb

InvoiceTestCase.test_invoice_kinds pycheval.exc.ModelError: Invalid invoice type code: 130.

Check failure on line 244 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, mariadb

InvoiceTestCase.test_invoice_kinds pycheval.exc.ModelError: Invalid invoice type code: 130.

Check failure on line 244 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, postgresql

InvoiceTestCase.test_invoice_kinds pycheval.exc.ModelError: Invalid invoice type code: 130.

Check failure on line 244 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, postgresql

InvoiceTestCase.test_invoice_kinds pycheval.exc.ModelError: Invalid invoice type code: 130.

Check failure on line 244 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, sqlite

InvoiceTestCase.test_invoice_kinds pycheval.exc.ModelError: Invalid invoice type code: 130.

Check failure on line 244 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, mariadb

InvoiceTestCase.test_invoice_kinds pycheval.exc.ModelError: Invalid invoice type code: 130.

Check failure on line 244 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, postgresql

InvoiceTestCase.test_invoice_kinds pycheval.exc.ModelError: Invalid invoice type code: 130.

Check failure on line 244 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, postgresql

InvoiceTestCase.test_invoice_kinds pycheval.exc.ModelError: Invalid invoice type code: 130.

Check failure on line 244 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, sqlite

InvoiceTestCase.test_invoice_kinds pycheval.exc.ModelError: Invalid invoice type code: 130.

@override_settings(PAYMENT_DEBUG=True)
def test_pay_link(self) -> None:
invoice = self.create_invoice_package()
self.validate_invoice(invoice)

Check failure on line 249 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, mariadb

InvoiceTestCase.test_pay_link AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 249 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, sqlite

InvoiceTestCase.test_pay_link AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 249 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, sqlite

InvoiceTestCase.test_pay_link AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 249 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, mariadb

InvoiceTestCase.test_pay_link AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 249 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, mariadb

InvoiceTestCase.test_pay_link AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 249 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, postgresql

InvoiceTestCase.test_pay_link AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 249 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, sqlite

InvoiceTestCase.test_pay_link AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 249 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, sqlite

InvoiceTestCase.test_pay_link AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 249 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, postgresql

InvoiceTestCase.test_pay_link AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 249 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, mariadb

InvoiceTestCase.test_pay_link AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 249 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, mariadb

InvoiceTestCase.test_pay_link AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 249 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.13, postgresql

InvoiceTestCase.test_pay_link AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 249 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, postgresql

InvoiceTestCase.test_pay_link AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 249 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, sqlite

InvoiceTestCase.test_pay_link AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 249 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, mariadb

InvoiceTestCase.test_pay_link AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 249 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.11, postgresql

InvoiceTestCase.test_pay_link AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 249 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, postgresql

InvoiceTestCase.test_pay_link AttributeError: 'HTML' object has no attribute 'metadata'

Check failure on line 249 in weblate_web/invoices/tests.py

View workflow job for this annotation

GitHub Actions / Python 3.12, sqlite

InvoiceTestCase.test_pay_link AttributeError: 'HTML' object has no attribute 'metadata'
url = cast("str", invoice.get_payment_url())
self.assertIsNotNone(url)

Expand Down
15 changes: 14 additions & 1 deletion weblate_web/pdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,16 @@
from __future__ import annotations

from pathlib import Path
from typing import TYPE_CHECKING

from django.conf import settings
from django.contrib.staticfiles import finders
from weasyprint import CSS, HTML
from weasyprint.text.fonts import FontConfiguration

if TYPE_CHECKING:
from weasyprint import Attachment

SIGNATURE_URL = "signature:"
INVOICES_URL = "invoices:"
LEGAL_URL = "legal:"
Expand Down Expand Up @@ -63,7 +67,13 @@ def url_fetcher(url: str) -> dict[str, str | bytes]:
return result


def render_pdf(*, html: str, output: Path) -> None:
def render_pdf(
*,
html: str,
output: Path,
attachments: list[Attachment] | None = None,
pdf_variant: str | None = None,
) -> None:
font_config = FontConfiguration()

renderer = HTML(
Expand All @@ -78,8 +88,11 @@ def render_pdf(*, html: str, output: Path) -> None:
font_config=font_config,
url_fetcher=url_fetcher,
)
if attachments:
renderer.metadata.attachments = attachments
renderer.write_pdf(
output,
stylesheets=[font_style],
font_config=font_config,
pdf_variant=pdf_variant,
)
Loading