Usage¶
Getting started¶
First of all, you’ll need to create a TaxPayer
instance, and upload the related SSL key and certificate (for authorization).
Official documentation for obtaining the certificate is available here, and for delegation here.
django-afip includes admin views for every model included, and it’s the
recommended way to create TaxPayer
objects (at least during
development/testing).
Once you have created a TaxPayer
, you’ll need its points of sales. This,
again, can be done via the admin by selecting “fetch points of sales’. You may
also do this programmatically via fetch_points_of_sales()
.
Metadata populuation¶
You’ll also need to pre-populate certain models with AFIP-defined metadata
(ReceiptType
, DocumentType
and a few others).
Rather than include fixtures which require updating over time, we fetch this information from AFIP’s web services via an included django management command. This command is idempotent, and running it more than once will not create any duplicate data. To fetch all metadata, simply run:
python manage.py afipmetadata
This metadata can also be downloaded programmatically, via
populate_all()
.
You are now ready to start creating and validating receipts. While you may do this via the admin as well, you probably want to do this programmatically or via some custom view. Note that the admin views provided do very little validations - it’s generally intended as a developer tool, though it’s known to be used for invoicing by a few people who understand it’s limitations.
Example¶
This brief example shows how to achieve the above:
from django.core.files import File
from django_afip import models
# Create a TaxPayer object:
taxpayer = models.TaxPayer(
pk=1,
name='test taxpayer',
cuit=20329642330,
is_sandboxed=True,
)
# Add the key and certificate files to the TaxPayer:
with open('/path/to/your.key') as key:
taxpayer.key.save('test.key', File(key))
with open('/path/to/your.crt') as crt:
taxpayer.certificate.save('test.crt', File(crt))
taxpayer.save()
# Load all metadata:
models.populate_all()
# Get the TaxPayer's Point of Sales:
taxpayer.fetch_points_of_sales()
Validating receipts¶
After getting started, you should be ready to emit/validate receipts.
The first step is, naturally, to create a Receipt
instance. Receipts
are then sent to AFIP’s web services in batches, so you van actually validate
multiple ones, by operating over a QuerySet
; eg:
Receipt.objects.filter(...).validate()
.
To validate the receipts, you’ll need to use validate()
or
validate()
. Authorization is handled transparently
(consult the API documentation if you’d prefer to do this manually).
Validation is also possible via the Receipt
admin.
PDF Receipts¶
Version 1.2.0 introduced PDF-generation for validated receipts. These PDFs are
backed by the ReceiptPDF
model.
There are two ways of creating these objects; you can do this manually, or via these steps:
- Creating a
TaxPayerProfile
object for yourTaxPayer
, with the right default values. - Create the PDFs via
ReceiptPDF.objects.create_for_receipt()
. - Add the proper
ReceiptEntry
objects to theReceipt
. EachReceiptEntry
represents a line in the resulting PDF file.
The PDF file itself can then be generated via:
# Save the file as a model field into your MEDIA_ROOT directory:
receipt_pdf.save_pdf()
# Save to some custom file-like-object:
receipt_pdf.save_pdf_to(file_object)
The former is usually recommended since it allows simpler interaction via standard django patterns.
Barcodes¶
Since version 3.2.0, PDFs include the barcode defined in AFIP 1702/04.
Version 3.2.0 used the receipt’s expiration date for the barcode. After some debate with fellow developers and accountants, we’ve resolved that the CAE’s expiration date should be used. Even though resolution 1702/04 does not explicitly state this (it just says “Expiration Date”, their own receipt PDFs use this date. Also, not all receipts have expiration dates.
Exposing receipts¶
Generated receipt files may be exposed both as PDF or html with an existing view, for example, using:
url(
r'^invoices/pdf/(?P<pk>\d+)?$',
views.ReceiptPDFView.as_view(),
name='receipt_view',
),
url(
r'^invoices/html/(?P<pk>\d+)?$',
views.ReceiptHTMLView.as_view(),
name='receipt_view',
),
You’ll generally want to subclass this view, and add some authorization checks to it. If you want some other, more complex generation (like sending via email), these views should serve as a reference to the PDF API.
The template used for the HTML and PDF receipts is found in
templates/receipts/code_X.html
, where X is the ReceiptType
‘s
code. If you want to override the default (you probably do), simply place a
template with the same path/name inside your own app, and make sure it’s listed
before django_afip
in INSTALLED_APPS
.
About the admin¶
As mentioned above, admin views are included for most models. If you need to customize admin views, it is recommended that you subclass these and aviod repeating anything.
Admin views are generally present for developers to check data (especially during development and tests), or for low-volume power-users to generate their invoices (but they really do need to know what they’re doing). They are not really intended for end-users, and definitely not on multi-user systems.