WhyNotHugo / django-afip

⚖️ AFIP invoice integration for django.
https://django-afip.readthedocs.io/
ISC License
48 stars 24 forks source link

Tests PointOfSales.issuance_type wrong value #161

Closed erebodino closed 1 year ago

erebodino commented 2 years ago

I was running tests and found something weird in the way that factories are creating the PointOfSales, to be more precise when it come to test the live tests, in the method _validate from ReceiptQuerySet the point_of_sales.issuance_type created for the tests must be "CAE" since it's hardcoded in that way in the PointOfSalesFactory:

class PointOfSalesFactory(DjangoModelFactory):
    class Meta:
        model = models.PointOfSales
        django_get_or_create = ["owner", "number"]

    number = 1
    issuance_type = "CAE"
    blocked = False
    owner = SubFactory(TaxPayerFactory)
    # TODO: Renamethis to something more regional:
    issuing_name = "Red Company Inc."
    issuing_address = "100 Red Av\nRedsville\nUK"
    issuing_email = "billing@example.com"
    vat_condition = "Exempt"
    gross_income_condition = "Exempt"
    sales_terms = "Credit Card"

but, found that the PointOfSales created return CAE - Monotributo as value for issuance_type and not 'CAE' as is supposed.

I figured out this when I was running my live test to check de CAEA support and my tests were failing (I modified the _validate to check the issuance_type). So I tried with the package without any modification and there the problem is there too.

To see the output I modified the ReceiptQuerySet._validate and added 1 line: print('\n\n---',first.point_of_sales.issuance_type,'---')

and the modified the tox.ini in the line commands as: commands = pytest -vv -s

Some idea about why this is happening? and how I can fixed? Since it's supposed that issuance_type it should be created as 'CAE'

Update: It seems like the problem is in coftest.py when de pytest fixture populate_db is executed, inside an instance of TaxPayer is created and execute the method fetch_points_of_sales() and in that moment is when the db gets populated with a PointOfSales with CAE - Monotributo as issuance_type. I don't know why AFIP is returning that data, but if I monkey patch that model with:

pos = models.PointOfSales.objects.get(pk=1)
pos.issuance_type = 'CAE'
pos.save()

every test run ok.

Now the new question is: Any idea of why AFIP is returning a a PointOfSales with that data?

Alvezgr commented 2 years ago

Hi @erebodino, That is how AFIP handle the EmisionTipo field. We ask them for a list of possible values but they don't have it, or at leas are not willing to share. The only know thing about, is that the longest value is 200 BYTE, we recently modified the issuance_type length due to AFIP reply for a pos was CAEA - Ri Iva CONTINGENCIA, It is just how they manage things and I would not be surprised if anything else comes up, perhaps if you test for CAE - Monotributo works but for CAE - Ri Monotributo it will not. What if we do not assume anything from AFIP and review the test case?

erebodino commented 2 years ago

Hi @Alvezgr, thanks you for your reply.

So, the problem shows up because I did a modification on _validate in this moment it checks if issuance_type == 'CAE or 'CAEA', but for what you are telling me this could lead to another problem in the future if AFIP make some weird change. Do yo know if they include always in the EmisionTipo the words CAE or CAEA because in that way no greater changes must be done and everything should work fine. If that is the case my solution will be modificate the check 'EmisionTipo' to look for the words CAE or CAEA inside that string instead of an exact match for that words.

This idea will work if AFIP send the value as: 'CAE/CAEA - Another stuff' can we be sure that AFIP send the data in that way?

Alvezgr commented 2 years ago

At least in my experience, for CAE and CAEA I will think yes, but not pretty sure for any other type of issuance_type.

WhyNotHugo commented 1 year ago

Note that the factory has:

django_get_or_create = ["owner", "number"]

This means that instead of creating new models. In other words, it uses get_or_create:

PointOfSales.objects.get_or_create(owner=X, number=Y, defaults={...})

Live tests use fetch_points_of_sales() to fetch the POS from AFIP's test servers, so the issuance type comes from there (since this is executed before any factory runs).

The test account returns CAE - Monotributo because that's what my real account used at the time it was set up (and it seems it stays that way forever).

Checking some very old points of sales in production, I see that in the past they were "CAE" but new ones are "CAE - Ri Iva". I guess this changed at some point. I recommend checking pos.issuance_type.starts_with("CAEA") (keep in mind that CAEA also starts with CAE).