diff --git a/django_afip/factories.py b/django_afip/factories.py index eb769be..e2b344f 100644 --- a/django_afip/factories.py +++ b/django_afip/factories.py @@ -124,6 +124,16 @@ class Meta: sales_terms = "Credit Card" +class ClientVatConditionFactory(DjangoModelFactory): + class Meta: + model = models.ClientVatCondition + django_get_or_create = ("code",) + + code = "5" + description = "Consumidor Final" + cmp_clase = "B,C" + + class ReceiptFactory(DjangoModelFactory): class Meta: model = models.Receipt @@ -146,6 +156,7 @@ class ReceiptWithVatAndTaxFactory(ReceiptFactory): """Receipt with a valid Vat and Tax, ready to validate.""" point_of_sales = LazyFunction(lambda: models.PointOfSales.objects.first()) + client_vat_condition = SubFactory(ClientVatConditionFactory) @post_generation def post(obj: models.Receipt, create: bool, extracted: None, **kwargs) -> None: @@ -153,19 +164,14 @@ def post(obj: models.Receipt, create: bool, extracted: None, **kwargs) -> None: TaxFactory(tax_type__code=3, receipt=obj) -class ReceiptFCEAWithVatAndTaxFactory(ReceiptFactory): +class ReceiptFCEAWithVatAndTaxFactory(ReceiptWithVatAndTaxFactory): """Receipt FCEA with a valid Vat and Tax, ready to validate.""" document_number = 20111111112 - point_of_sales = LazyFunction(lambda: models.PointOfSales.objects.first()) receipt_type = SubFactory(ReceiptTypeFactory, code=201) document_type = SubFactory(DocumentTypeFactory, code=80) expiration_date = LazyFunction(date.today) - - @post_generation - def post(obj: models.Receipt, create: bool, extracted: None, **kwargs) -> None: - VatFactory(vat_type__code=5, receipt=obj) - TaxFactory(tax_type__code=3, receipt=obj) + client_vat_condition = SubFactory(ClientVatConditionFactory, code="1") class ReceiptFCEAWithVatTaxAndOptionalsFactory(ReceiptFCEAWithVatAndTaxFactory): @@ -321,16 +327,6 @@ class Meta: vat = SubFactory(VatTypeFactory) -class ClientVatConditionFactory(DjangoModelFactory): - class Meta: - model = models.ClientVatCondition - django_get_or_create = ("code",) - - code = "5" - description = "Consumidor Final" - cmp_clase = "B,C" - - class ReceiptWithClientVatConditionFactory(ReceiptFactory): """Receipt with a valid Client VAT Condition, ready to validate.""" diff --git a/django_afip/models.py b/django_afip/models.py index 906ec9c..4b5e87e 100644 --- a/django_afip/models.py +++ b/django_afip/models.py @@ -1960,7 +1960,7 @@ def populate( check_response(response) for condition_data in response.ResultGet.CondicionIvaReceptor: - condition, created = cls.objects.update_or_create( + cls.objects.update_or_create( code=condition_data.Id, defaults={ "description": condition_data.Desc, diff --git a/docs/changelog.rst b/docs/changelog.rst index d7d0b23..f05c553 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -13,6 +13,14 @@ Check the `latest tags`_ or `PyPI`_ for the latest stable release. Any breaking changes which require intervention will be mentioned here. +13.3.0 +------ + +- ``setuptools>=77`` is required. Previous versions would often fail to + properly parse the ``licence`` field. +- Extend supported versions of ``django-renderpdf``, ``qrcode`` and + ``cryptography``. + 13.2.2 ------ diff --git a/pyproject.toml b/pyproject.toml index 6743925..af43376 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,16 +30,15 @@ classifiers = [ "Typing :: Typed", ] dependencies = [ - "cryptography>=3.2,<40", + "cryptography>=3.2,<47", "django>=4.2,<5.3", - "django_renderpdf>=3.0.0,<5.0.0", + "django_renderpdf>=3.0.0,<6.0.0", "lxml>=3.4.4", "pyopenssl>=16.2.0", - 'backports.zoneinfo;python_version<"3.9"', "setuptools-git>=1.1", "wheel>=0.24.0", "zeep>=1.1.0,<5.0.0", - "qrcode[pil]>=6.1,<8.0", + "qrcode[pil]>=6.1,<9.0", "pyyaml>=5.3.1,<7.0.0", # zeep depends on requests, but these specific version are incompatible. # See: https://github.com/WhyNotHugo/django-afip/issues/211 @@ -90,7 +89,7 @@ funding = "https://github.com/sponsors/WhyNotHugo" include = ["django_afip*"] [build-system] -requires = ["setuptools>=45", "wheel", "setuptools_scm>=6.2"] +requires = ["setuptools>=77", "wheel", "setuptools_scm>=6.2"] [tool.setuptools_scm] write_to = "django_afip/version.py" diff --git a/tests/test_clients.py b/tests/test_clients.py index df915ff..33d728c 100644 --- a/tests/test_clients.py +++ b/tests/test_clients.py @@ -25,5 +25,5 @@ def test_inexisting_service() -> None: @pytest.mark.live def test_insecure_dh_hack_required() -> None: - with pytest.raises(SSLError, match="SSL: DH_KEY_TOO_SMALL. dh key too small"): + with pytest.raises(SSLError, match="SSL: DH_KEY_TOO_SMALL\\] dh key too small"): requests.get("https://servicios1.afip.gov.ar/wsfev1/service.asmx?WSDL") diff --git a/tests/test_models.py b/tests/test_models.py index 9387c60..f16629a 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -601,7 +601,7 @@ def test_approximate_date_failure() -> None: with pytest.raises( exceptions.DjangoAfipException, - match="Expected to update one receipt, updated 0.", + match="Expected to update one receipt, updated 0\\.", ): receipt.approximate_date() diff --git a/tests/test_webservices.py b/tests/test_webservices.py index caae4b4..be7caf0 100644 --- a/tests/test_webservices.py +++ b/tests/test_webservices.py @@ -32,7 +32,7 @@ def test_authentication_with_bad_cuit() -> None: with pytest.raises( exceptions.AfipException, # Note: AFIP apparently edited this message and added a typo: - match="ValidacionDeToken: No apareci[oó] CUIT en lista de relaciones:", + match=r"ValidacionDeToken: No apareci[oó] CUIT en lista de relaciones:", ): taxpayer.fetch_points_of_sales() @@ -67,7 +67,7 @@ def test_authentication_with_no_active_taxpayer() -> None: """Test that no TaxPayers raises an understandable error.""" with pytest.raises( exceptions.AuthenticationError, - match="There are no taxpayers to generate a ticket.", + match="There are no taxpayers to generate a ticket\\.", ): models.AuthTicket.objects.get_any_active("wsfe") @@ -253,6 +253,7 @@ def test_receipt_queryset_validation_good_without_tax(populated_db: None) -> Non receipt = factories.ReceiptFactory( point_of_sales=models.PointOfSales.objects.first(), total_amount=121, + client_vat_condition=factories.ClientVatConditionFactory(), ) factories.VatFactory(vat_type__code=5, receipt=receipt) @@ -271,6 +272,7 @@ def test_receipt_queryset_validation_good_without_vat(populated_db: None) -> Non point_of_sales=models.PointOfSales.objects.first(), receipt_type__code=11, total_amount=109, + client_vat_condition=factories.ClientVatConditionFactory(), ) factories.TaxFactory(tax_type__code=3, receipt=receipt) diff --git a/tox.ini b/tox.ini index 8905fde..b41f83b 100644 --- a/tox.ini +++ b/tox.ini @@ -21,7 +21,7 @@ passenv = GENTESTCSR # Hint: quickly run a one-shot container with: -# docker run --rm -e POSTGRES_PASSWORD=postgres -p 5432:5432 -it postgres +# docker run --rm -e POSTGRES_PASSWORD=postgres -p 5432:5432 -it postgres:alpine [testenv:live] extras = dev, postgres commands = pytest -vv -m "live" {posargs}