Skip to content

[ADD] l10n_es_edi_verifactu{,_pos}: Veri*Factu support #197635

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed

Conversation

svfu-odoo
Copy link
Contributor

@svfu-odoo svfu-odoo commented Feb 13, 2025

[ADD] l10n_es_edi_verifactu{,_pos}: Veri*Factu support

Spain introduces a new EDI called "Veri*Factu" to send invoicing records
to the Spanish tax agency (AEAT).
It is mandatory for most tax payers (that cannot use any of the
other Spanish EDIs like SII or TicketBAI).

This commit adds 2 modules to enable Veri*Factu compliance

  • l10n_es_edi_verifactu for invoicing / accounting
  • l10n_es_edi_verifactu_pos for Point of Sale (PoS)

Their setup and usage is briefly described in the documentation
(see the related documentation PR).
The main features of the new modules are as follows.

  • l10n_es_edi_verifactu
    • The "Send & Print" wizard can be used to generate and send Veri*Factu documents.
    • A QR code is added to the PDF of invoices send with the Veri*Factu option.
      It can be used to check whether the invoice is known to the AEAT.
    • A "Veri*Factu" tab is added to the account move form view.
      It i.e. gives an overview about the send documents and their status.
  • l10n_es_edi_verifactu_pos
    • A Veri*Factu documents is generated and sent when validating each order.
    • A QR code is added to the PDF of PoS order receipts.
      It can be used to check whether the order is known to the AEAT.
    • A "Veri*Factu" tab is added to the pos order form view.
      It i.e. gives an overview about the send documents and their status.

I.e. note the following about Veri*Factu documents

  • Each document has a fingerprint (hash of some important values) called Huella.
  • All documents belonging to one company are linked together in a single chain in generation order.
    (Each document refers to the previous document including the Huella of the previous document)
  • There is a waiting time between submissions of documents (usually 60s).
    We sent the document immediately if possible.
    But due to the waiting time this is not always possible.
  • We still generate / store the needed values when the invoice is sent
    (mandated by Veri*Factu spec).
  • Documents can be sent in batches.
    • Due to the waiting time we sent all "waiting" documents at once.
    • In case of 1000 documents the waiting time can be / is ignored
    • A "Veri*Factu Document" in Odoo only represents a single invoice / PoS order.
  • The needed document values mandated by Veri*Factu are stored in JSON format
    on each invoice / order.
  • The actual "communication" with AEAT is done via SOAP. (So we sent / receive
    XML files)
  • We do not store the actual batch XML we sent to the AEAT or the received responses.
    • For the responses we extract the necessary information and store them
      on each of the document

It can happen that the document reached the AEAT but the response
timed out for some reason (Read-Timeout).

  • The AEAT has (potentially) registered the document but we have
    not received the response they sent.
  • The document will be marked with an error starting with [Read-Timeout] .
    and automatically be sent again as soon as possible
  • When the document is resend successfully we receive a response that the document
    was rejected with error [3000] Registro de facturación duplicado.
    (Assuming the AEAT registered / not rejected the document when it was sent originally.)
    But the response also contains some information about the state and potential errors
    of the record / duplicate.
  • Since the duplicate is the document we previously sent we just take the state from there.

There are 2 ways to create a correcting Veri*Factu document for invoices

  • Correction by difference: Done via "Reverse" in credit note wizard
    We just send a document representing the credit note as "correction by difference".
    The document references the corrected invoice.
  • Correction by substitution: Done via "Reverse and Create Invoice" in credit note wizard
    We first send a document representing the reversing credit note (it does not
    reference the original invoice and is send as an "invoice type").
    And then we send the new invoice created by the wizard. It is send as a
    "correction by substitution" and references the original invoice.
    To link the new invoice to the original invoice a new field was added
  • We do not support correcting multiple documents with a single new documents
    (neither correction by difference nor correction by substitution)

The "Veri*Factu" tab on the invoice form view also gives information
about which invoice was refunded or substituted.

Limitations

  • In Veri*Factu there is some dedicated way to handle the substitution of
    simplified invoices with "real" invoices.
    This is not implemented currently.
  • In Veri*Factu multiple tax types (Impuesto) and regimen keys (ClaveRegimen) can
    be indicated (one per DetalleDesglose element).
    We currently only allow a single tax type and regimen key for the whole
    document.
  • In Veri*Factu it is possible to send a "Subsanación" in case a change is made
    that does not require updating the invoice PDF.
    This is currently not supported.
    • I.e. we do not support sending new submission documents for already registered
      (possibly with errors) records.
    • It is not possible to reset registered (possibly with errors) records back to draft.
  • In VeriFactu it is possible to send a cancellation for records that are otherwise
    known to the AEAT (not Veri
    Factu).
    We do not support sending cancellations for records that are not Veri*Factu registered
    within Odoo.
  • For simplified invoices there are the special keys / fields FacturaSimplificadaArt7273
    and FacturaSinIdentifDestinatarioArt61d. Currently we never set them (so they are assumed
    to be N by the AEAT).

[IMP] l10n_es{,edi_sii,edi_tbai}: move some code to l10n_es

The moved code will also be needed for Veri*Factu

  • patched http adapter
  • a function to retrieve partner info

[FIX] l10n_es_pos: set simplifed partner only when we will invoice

Currently we also set the simplified partner directly on pos orders even
in case we do not invoice the pos order directly.
This is unnecessary; we only need to set a partner in case we invoice.
(Since we need a partner to put on the invoice.)

After this commit we only set the simplified partner on pos orders
that will be invoiced as simplified invoice.
(This happens automatically in case a simplified invoice journal is
set in the settings; see field pos_l10n_es_simplified_invoice_journal_id)

References

documentation PR: odoo/documentation#12068
task-3745982

@robodoo
Copy link
Contributor

robodoo commented Feb 13, 2025

Pull request status dashboard

@svfu-odoo svfu-odoo changed the title [ADD] l10n_es_edi_verifactu{,pos}: Veri*Factu support [WIP][ADD] l10n_es_edi_verifactu{,pos}: Veri*Factu support Feb 13, 2025
@C3POdoo C3POdoo added the RD research & development, internal work label Feb 13, 2025
@svfu-odoo svfu-odoo force-pushed the 17.0-add_l10n_es_edi_verifactu-svfu branch 6 times, most recently from 3c4efa2 to 7ea2c91 Compare February 20, 2025 08:35
@svfu-odoo svfu-odoo force-pushed the 17.0-add_l10n_es_edi_verifactu-svfu branch 7 times, most recently from fc880c7 to dc48ce3 Compare February 27, 2025 13:49
Copy link
Contributor

@jco-odoo jco-odoo left a comment

Choose a reason for hiding this comment

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

Still many uncertainties I am afraid, as well because of how strict the regulations should be interpreted...


for order in self:
# Cancel the order
# TODO: in case we have waiting records we need to delete them
Copy link
Contributor

Choose a reason for hiding this comment

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

Not clear what you mean by that

Copy link
Contributor Author

Choose a reason for hiding this comment

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

On second thought. We should not delete anything because of the chaining.

The issue I am thinking about:
We are waiting to send a record document to register / update the order.
But then we invoice it (from the order form view).
We still need to send everything for the chaining.

I am not sure this flow is possible though. At least I could not find how to do it. I will have to check again
I just throw an error for now.

I still have to check the case that the same record is multiple times in the same batch (e.g. registration + immediate cancellation)

@svfu-odoo svfu-odoo force-pushed the 17.0-add_l10n_es_edi_verifactu-svfu branch 9 times, most recently from cae2e42 to 35ac635 Compare March 11, 2025 09:46
Copy link
Contributor

@jco-odoo jco-odoo left a comment

Choose a reason for hiding this comment

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

I am probably wrong about some things...

recargo_amount = recargo_equivalencia.get("tax_amount")

detalle = {
'Impuesto': verifactu_tax_type,
Copy link
Contributor

Choose a reason for hiding this comment

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

Everything is just double. It is simple in l10n_es_edi_tbai.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

TODO: I will double check and try to simplify

svfu-odoo added a commit to odoo-dev/odoo that referenced this pull request Jul 23, 2025
Spain introduces a new EDI called "Veri*Factu" to send invoicing records
to the Spanish tax agency (AEAT).
It is mandatory for most tax payers (that cannot use any of the
other Spanish EDIs like SII or TicketBAI).

This commit adds 2 modules to enable Veri*Factu compliance
- `l10n_es_edi_verifactu` for invoicing / accounting
- `l10n_es_edi_verifactu_pos` for Point of Sale (PoS)

Their setup and usage is briefly described in the documentation
(see the related documentation PR).
The main features of the new modules are as follows.
- `l10n_es_edi_verifactu`
  - The "Send & Print" wizard can be used to generate and send Veri*Factu documents.
  - A QR code is added to the PDF of invoices send with the Veri*Factu option.
    It can be used to check whether the invoice is known to the AEAT.
  - A "Veri*Factu" tab is added to the account move form view.
    It i.e. gives an overview about the send documents and their status.
- `l10n_es_edi_verifactu_pos`
  - A Veri*Factu documents is generated and sent when validating each order.
  - A QR code is added to the PDF of PoS order receipts.
    It can be used to check whether the order is known to the AEAT.
  - A "Veri*Factu" tab is added to the pos order form view.
    It i.e. gives an overview about the send documents and their status.

I.e. note the following about Veri*Factu documents
- Each document has a fingerprint (hash of some important values) called `Huella`.
- All documents belonging to one company are linked together in a single chain in generation order.
  (Each document refers to the previous document including the `Huella` of the previous document)
- There is a waiting time between submissions of documents (usually 60s).
  We sent the document immediately if possible.
  But due to the waiting time this is not always possible.
- We still generate / store the needed values when the invoice is sent
  (mandated by Veri*Factu spec).
- Documents can be sent in batches.
  - Due to the waiting time we sent all "waiting" documents at once.
  - In case of 1000 documents the waiting time can be / is ignored
  - A "Veri*Factu Document" in Odoo only represents a single invoice / PoS order.
- The needed document values mandated by Veri*Factu are stored in JSON format
  on each invoice / order.
- The actual "communication" with AEAT is done via SOAP. (So we sent / receive
  XML files)
- We do not store the actual batch XML we sent to the AEAT or the received responses.
  - For the responses we extract the necessary information and store them
    on each of the document

It can happen that the document reached the AEAT but the response
timed out for some reason (Read-Timeout).
  - The AEAT has (potentially) registered the document but we have
    not received the response they sent.
  - The document will be marked with an error starting with `[Read-Timeout] `.
    and automatically be sent again as soon as possible
  - When the document is resend successfully we receive a response that the document
    was rejected with error `[3000] Registro de facturación duplicado.`
    (Assuming the AEAT registered / not rejected the document when it was sent originally.)
    But the response also contains some information about the state and potential errors
    of the record / duplicate.
  - Since the duplicate is the document we previously sent we just take the state from there.

There are 2 ways to create a correcting Veri*Factu document for invoices
- Correction by difference: Done via "Reverse" in credit note wizard
  We just send a document representing the credit note as "correction by difference".
  The document references the corrected invoice.
- Correction by substitution: Done via "Reverse and Create Invoice" in credit note wizard
  We first send a document representing the reversing credit note (it does not
  reference the original invoice and is send as an "invoice type").
  And then we send the new invoice created by the wizard. It is send as a
  "correction by substitution" and references the original invoice.
  To link the new invoice to the original invoice a new field was added
- We do not support correcting multiple documents with a single new documents
  (neither correction by difference nor correction by substitution)

The "Veri*Factu" tab on the invoice form view also gives information
about which invoice was refunded or substituted.

Limitations
- In Veri*Factu there is some dedicated way to handle the substitution of
  simplified invoices with "real" invoices.
  This is not implemented currently.
- In Veri*Factu multiple tax types (`Impuesto`) and regimen keys (`ClaveRegimen`) can
  be indicated (one per `DetalleDesglose` element).
  We currently only allow a single tax type and regimen key for the whole
  document.
- In Veri*Factu it is possible to send a "Subsanación" in case a change is made
  that does not require updating the invoice PDF.
  This is currently not supported.
  - I.e. we do not support sending new submission documents for already registered
    (possibly with errors) records.
  - It is not possible to reset registered (possibly with errors) records back to draft.
- In Veri*Factu it is possible to send a cancellation for records that are otherwise
  known to the AEAT (not Veri*Factu).
  We do not support sending cancellations for records that are not Veri*Factu registered
  within Odoo.
- For simplified invoices there are the special keys / fields `FacturaSimplificadaArt7273`
  and `FacturaSinIdentifDestinatarioArt61d`. Currently we never set them (so they are assumed
  to be `N` by the AEAT).

task-3745982

closes odoo#197635

Signed-off-by: Sven Führ (svfu) <[email protected]>
svfu-odoo added a commit to odoo-dev/odoo that referenced this pull request Jul 25, 2025
Spain introduces a new EDI called "Veri*Factu" to send invoicing records
to the Spanish tax agency (AEAT).
It is mandatory for most tax payers (that cannot use any of the
other Spanish EDIs like SII or TicketBAI).

This commit adds 2 modules to enable Veri*Factu compliance
- `l10n_es_edi_verifactu` for invoicing / accounting
- `l10n_es_edi_verifactu_pos` for Point of Sale (PoS)

Their setup and usage is briefly described in the documentation
(see the related documentation PR).
The main features of the new modules are as follows.
- `l10n_es_edi_verifactu`
  - The "Send & Print" wizard can be used to generate and send Veri*Factu documents.
  - A QR code is added to the PDF of invoices send with the Veri*Factu option.
    It can be used to check whether the invoice is known to the AEAT.
  - A "Veri*Factu" tab is added to the account move form view.
    It i.e. gives an overview about the send documents and their status.
- `l10n_es_edi_verifactu_pos`
  - A Veri*Factu documents is generated and sent when validating each order.
  - A QR code is added to the PDF of PoS order receipts.
    It can be used to check whether the order is known to the AEAT.
  - A "Veri*Factu" tab is added to the pos order form view.
    It i.e. gives an overview about the send documents and their status.

I.e. note the following about Veri*Factu documents
- Each document has a fingerprint (hash of some important values) called `Huella`.
- All documents belonging to one company are linked together in a single chain in generation order.
  (Each document refers to the previous document including the `Huella` of the previous document)
- There is a waiting time between submissions of documents (usually 60s).
  We sent the document immediately if possible.
  But due to the waiting time this is not always possible.
- We still generate / store the needed values when the invoice is sent
  (mandated by Veri*Factu spec).
- Documents can be sent in batches.
  - Due to the waiting time we sent all "waiting" documents at once.
  - In case of 1000 documents the waiting time can be / is ignored
  - A "Veri*Factu Document" in Odoo only represents a single invoice / PoS order.
- The needed document values mandated by Veri*Factu are stored in JSON format
  on each invoice / order.
- The actual "communication" with AEAT is done via SOAP. (So we sent / receive
  XML files)
- We do not store the actual batch XML we sent to the AEAT or the received responses.
  - For the responses we extract the necessary information and store them
    on each of the document

It can happen that the document reached the AEAT but the response
timed out for some reason (Read-Timeout).
  - The AEAT has (potentially) registered the document but we have
    not received the response they sent.
  - The document will be marked with an error starting with `[Read-Timeout] `.
    and automatically be sent again as soon as possible
  - When the document is resend successfully we receive a response that the document
    was rejected with error `[3000] Registro de facturación duplicado.`
    (Assuming the AEAT registered / not rejected the document when it was sent originally.)
    But the response also contains some information about the state and potential errors
    of the record / duplicate.
  - Since the duplicate is the document we previously sent we just take the state from there.

There are 2 ways to create a correcting Veri*Factu document for invoices
- Correction by difference: Done via "Reverse" in credit note wizard
  We just send a document representing the credit note as "correction by difference".
  The document references the corrected invoice.
- Correction by substitution: Done via "Reverse and Create Invoice" in credit note wizard
  We first send a document representing the reversing credit note (it does not
  reference the original invoice and is send as an "invoice type").
  And then we send the new invoice created by the wizard. It is send as a
  "correction by substitution" and references the original invoice.
  To link the new invoice to the original invoice a new field was added
- We do not support correcting multiple documents with a single new documents
  (neither correction by difference nor correction by substitution)

The "Veri*Factu" tab on the invoice form view also gives information
about which invoice was refunded or substituted.

Limitations
- In Veri*Factu there is some dedicated way to handle the substitution of
  simplified invoices with "real" invoices.
  This is not implemented currently.
- In Veri*Factu multiple tax types (`Impuesto`) and regimen keys (`ClaveRegimen`) can
  be indicated (one per `DetalleDesglose` element).
  We currently only allow a single tax type and regimen key for the whole
  document.
- In Veri*Factu it is possible to send a "Subsanación" in case a change is made
  that does not require updating the invoice PDF.
  This is currently not supported.
  - I.e. we do not support sending new submission documents for already registered
    (possibly with errors) records.
  - It is not possible to reset registered (possibly with errors) records back to draft.
- In Veri*Factu it is possible to send a cancellation for records that are otherwise
  known to the AEAT (not Veri*Factu).
  We do not support sending cancellations for records that are not Veri*Factu registered
  within Odoo.
- For simplified invoices there are the special keys / fields `FacturaSimplificadaArt7273`
  and `FacturaSinIdentifDestinatarioArt61d`. Currently we never set them (so they are assumed
  to be `N` by the AEAT).

task-3745982

closes odoo#197635

Signed-off-by: Sven Führ (svfu) <[email protected]>
svfu-odoo added a commit to odoo-dev/odoo that referenced this pull request Jul 28, 2025
Spain introduces a new EDI called "Veri*Factu" to send invoicing records
to the Spanish tax agency (AEAT).
It is mandatory for most tax payers (that cannot use any of the
other Spanish EDIs like SII or TicketBAI).

This commit adds 2 modules to enable Veri*Factu compliance
- `l10n_es_edi_verifactu` for invoicing / accounting
- `l10n_es_edi_verifactu_pos` for Point of Sale (PoS)

Their setup and usage is briefly described in the documentation
(see the related documentation PR).
The main features of the new modules are as follows.
- `l10n_es_edi_verifactu`
  - The "Send & Print" wizard can be used to generate and send Veri*Factu documents.
  - A QR code is added to the PDF of invoices send with the Veri*Factu option.
    It can be used to check whether the invoice is known to the AEAT.
  - A "Veri*Factu" tab is added to the account move form view.
    It i.e. gives an overview about the send documents and their status.
- `l10n_es_edi_verifactu_pos`
  - A Veri*Factu documents is generated and sent when validating each order.
  - A QR code is added to the PDF of PoS order receipts.
    It can be used to check whether the order is known to the AEAT.
  - A "Veri*Factu" tab is added to the pos order form view.
    It i.e. gives an overview about the send documents and their status.

I.e. note the following about Veri*Factu documents
- Each document has a fingerprint (hash of some important values) called `Huella`.
- All documents belonging to one company are linked together in a single chain in generation order.
  (Each document refers to the previous document including the `Huella` of the previous document)
- There is a waiting time between submissions of documents (usually 60s).
  We sent the document immediately if possible.
  But due to the waiting time this is not always possible.
- We still generate / store the needed values when the invoice is sent
  (mandated by Veri*Factu spec).
- Documents can be sent in batches.
  - Due to the waiting time we sent all "waiting" documents at once.
  - In case of 1000 documents the waiting time can be / is ignored
  - A "Veri*Factu Document" in Odoo only represents a single invoice / PoS order.
- The needed document values mandated by Veri*Factu are stored in JSON format
  on each invoice / order.
- The actual "communication" with AEAT is done via SOAP. (So we sent / receive
  XML files)
- We do not store the actual batch XML we sent to the AEAT or the received responses.
  - For the responses we extract the necessary information and store them
    on each of the document

It can happen that the document reached the AEAT but the response
timed out for some reason (Read-Timeout).
  - The AEAT has (potentially) registered the document but we have
    not received the response they sent.
  - The document will be marked with an error starting with `[Read-Timeout] `.
    and automatically be sent again as soon as possible
  - When the document is resend successfully we receive a response that the document
    was rejected with error `[3000] Registro de facturación duplicado.`
    (Assuming the AEAT registered / not rejected the document when it was sent originally.)
    But the response also contains some information about the state and potential errors
    of the record / duplicate.
  - Since the duplicate is the document we previously sent we just take the state from there.

There are 2 ways to create a correcting Veri*Factu document for invoices
- Correction by difference: Done via "Reverse" in credit note wizard
  We just send a document representing the credit note as "correction by difference".
  The document references the corrected invoice.
- Correction by substitution: Done via "Reverse and Create Invoice" in credit note wizard
  We first send a document representing the reversing credit note (it does not
  reference the original invoice and is send as an "invoice type").
  And then we send the new invoice created by the wizard. It is send as a
  "correction by substitution" and references the original invoice.
  To link the new invoice to the original invoice a new field was added
- We do not support correcting multiple documents with a single new documents
  (neither correction by difference nor correction by substitution)

The "Veri*Factu" tab on the invoice form view also gives information
about which invoice was refunded or substituted.

Limitations
- In Veri*Factu there is some dedicated way to handle the substitution of
  simplified invoices with "real" invoices.
  This is not implemented currently.
- In Veri*Factu multiple tax types (`Impuesto`) and regimen keys (`ClaveRegimen`) can
  be indicated (one per `DetalleDesglose` element).
  We currently only allow a single tax type and regimen key for the whole
  document.
- In Veri*Factu it is possible to send a "Subsanación" in case a change is made
  that does not require updating the invoice PDF.
  This is currently not supported.
  - I.e. we do not support sending new submission documents for already registered
    (possibly with errors) records.
  - It is not possible to reset registered (possibly with errors) records back to draft.
- In Veri*Factu it is possible to send a cancellation for records that are otherwise
  known to the AEAT (not Veri*Factu).
  We do not support sending cancellations for records that are not Veri*Factu registered
  within Odoo.
- For simplified invoices there are the special keys / fields `FacturaSimplificadaArt7273`
  and `FacturaSinIdentifDestinatarioArt61d`. Currently we never set them (so they are assumed
  to be `N` by the AEAT).

task-3745982

closes odoo#197635

Signed-off-by: Sven Führ (svfu) <[email protected]>
svfu-odoo added a commit to odoo/documentation that referenced this pull request Jul 29, 2025
Spain introduces a new EDI called "Veri*Factu" to send all invoices
to the Spanish tax agency (AEAT).
It is mandatory for most tax payers (that cannot use any of the
other Spanish EDIs like SII or TicketBAI)

In the related community PR new modules were added to enable
sending invoices and PoS orders via "Veri*Factu".

This commit adds some documentation about how to enable and use
"Veri*Factu".

Community PR: odoo/odoo#197635

task-3745982
svfu-odoo added a commit to odoo-dev/odoo that referenced this pull request Jul 29, 2025
Spain introduces a new EDI called "Veri*Factu" to send invoicing records
to the Spanish tax agency (AEAT).
It is mandatory for most tax payers (that cannot use any of the
other Spanish EDIs like SII or TicketBAI).

This commit adds 2 modules to enable Veri*Factu compliance
- `l10n_es_edi_verifactu` for invoicing / accounting
- `l10n_es_edi_verifactu_pos` for Point of Sale (PoS)

Their setup and usage is briefly described in the documentation
(see the related documentation PR).
The main features of the new modules are as follows.
- `l10n_es_edi_verifactu`
  - The "Send & Print" wizard can be used to generate and send Veri*Factu documents.
  - A QR code is added to the PDF of invoices send with the Veri*Factu option.
    It can be used to check whether the invoice is known to the AEAT.
  - A "Veri*Factu" tab is added to the account move form view.
    It i.e. gives an overview about the send documents and their status.
- `l10n_es_edi_verifactu_pos`
  - A Veri*Factu documents is generated and sent when validating each order.
  - A QR code is added to the PDF of PoS order receipts.
    It can be used to check whether the order is known to the AEAT.
  - A "Veri*Factu" tab is added to the pos order form view.
    It i.e. gives an overview about the send documents and their status.

I.e. note the following about Veri*Factu documents
- Each document has a fingerprint (hash of some important values) called `Huella`.
- All documents belonging to one company are linked together in a single chain in generation order.
  (Each document refers to the previous document including the `Huella` of the previous document)
- There is a waiting time between submissions of documents (usually 60s).
  We sent the document immediately if possible.
  But due to the waiting time this is not always possible.
- We still generate / store the needed values when the invoice is sent
  (mandated by Veri*Factu spec).
- Documents can be sent in batches.
  - Due to the waiting time we sent all "waiting" documents at once.
  - In case of 1000 documents the waiting time can be / is ignored
  - A "Veri*Factu Document" in Odoo only represents a single invoice / PoS order.
- The needed document values mandated by Veri*Factu are stored in JSON format
  on each invoice / order.
- The actual "communication" with AEAT is done via SOAP. (So we sent / receive
  XML files)
- We do not store the actual batch XML we sent to the AEAT or the received responses.
  - For the responses we extract the necessary information and store them
    on each of the document

It can happen that the document reached the AEAT but the response
timed out for some reason (Read-Timeout).
  - The AEAT has (potentially) registered the document but we have
    not received the response they sent.
  - The document will be marked with an error starting with `[Read-Timeout] `.
    and automatically be sent again as soon as possible
  - When the document is resend successfully we receive a response that the document
    was rejected with error `[3000] Registro de facturación duplicado.`
    (Assuming the AEAT registered / not rejected the document when it was sent originally.)
    But the response also contains some information about the state and potential errors
    of the record / duplicate.
  - Since the duplicate is the document we previously sent we just take the state from there.

There are 2 ways to create a correcting Veri*Factu document for invoices
- Correction by difference: Done via "Reverse" in credit note wizard
  We just send a document representing the credit note as "correction by difference".
  The document references the corrected invoice.
- Correction by substitution: Done via "Reverse and Create Invoice" in credit note wizard
  We first send a document representing the reversing credit note (it does not
  reference the original invoice and is send as an "invoice type").
  And then we send the new invoice created by the wizard. It is send as a
  "correction by substitution" and references the original invoice.
  To link the new invoice to the original invoice a new field was added
- We do not support correcting multiple documents with a single new documents
  (neither correction by difference nor correction by substitution)

The "Veri*Factu" tab on the invoice form view also gives information
about which invoice was refunded or substituted.

Limitations
- In Veri*Factu there is some dedicated way to handle the substitution of
  simplified invoices with "real" invoices.
  This is not implemented currently.
- In Veri*Factu multiple tax types (`Impuesto`) and regimen keys (`ClaveRegimen`) can
  be indicated (one per `DetalleDesglose` element).
  We currently only allow a single tax type and regimen key for the whole
  document.
- In Veri*Factu it is possible to send a "Subsanación" in case a change is made
  that does not require updating the invoice PDF.
  This is currently not supported.
  - I.e. we do not support sending new submission documents for already registered
    (possibly with errors) records.
  - It is not possible to reset registered (possibly with errors) records back to draft.
- In Veri*Factu it is possible to send a cancellation for records that are otherwise
  known to the AEAT (not Veri*Factu).
  We do not support sending cancellations for records that are not Veri*Factu registered
  within Odoo.
- For simplified invoices there are the special keys / fields `FacturaSimplificadaArt7273`
  and `FacturaSinIdentifDestinatarioArt61d`. Currently we never set them (so they are assumed
  to be `N` by the AEAT).

task-3745982

closes odoo#197635

Signed-off-by: Sven Führ (svfu) <[email protected]>
@fw-bot fw-bot deleted the 17.0-add_l10n_es_edi_verifactu-svfu branch July 29, 2025 15:55
svfu-odoo added a commit to odoo-dev/odoo that referenced this pull request Jul 29, 2025
Spain introduces a new EDI called "Veri*Factu" to send invoicing records
to the Spanish tax agency (AEAT).
It is mandatory for most tax payers (that cannot use any of the
other Spanish EDIs like SII or TicketBAI).

This commit adds 2 modules to enable Veri*Factu compliance
- `l10n_es_edi_verifactu` for invoicing / accounting
- `l10n_es_edi_verifactu_pos` for Point of Sale (PoS)

Their setup and usage is briefly described in the documentation
(see the related documentation PR).
The main features of the new modules are as follows.
- `l10n_es_edi_verifactu`
  - The "Send & Print" wizard can be used to generate and send Veri*Factu documents.
  - A QR code is added to the PDF of invoices send with the Veri*Factu option.
    It can be used to check whether the invoice is known to the AEAT.
  - A "Veri*Factu" tab is added to the account move form view.
    It i.e. gives an overview about the send documents and their status.
- `l10n_es_edi_verifactu_pos`
  - A Veri*Factu documents is generated and sent when validating each order.
  - A QR code is added to the PDF of PoS order receipts.
    It can be used to check whether the order is known to the AEAT.
  - A "Veri*Factu" tab is added to the pos order form view.
    It i.e. gives an overview about the send documents and their status.

I.e. note the following about Veri*Factu documents
- Each document has a fingerprint (hash of some important values) called `Huella`.
- All documents belonging to one company are linked together in a single chain in generation order.
  (Each document refers to the previous document including the `Huella` of the previous document)
- There is a waiting time between submissions of documents (usually 60s).
  We sent the document immediately if possible.
  But due to the waiting time this is not always possible.
- We still generate / store the needed values when the invoice is sent
  (mandated by Veri*Factu spec).
- Documents can be sent in batches.
  - Due to the waiting time we sent all "waiting" documents at once.
  - In case of 1000 documents the waiting time can be / is ignored
  - A "Veri*Factu Document" in Odoo only represents a single invoice / PoS order.
- The needed document values mandated by Veri*Factu are stored in JSON format
  on each invoice / order.
- The actual "communication" with AEAT is done via SOAP. (So we sent / receive
  XML files)
- We do not store the actual batch XML we sent to the AEAT or the received responses.
  - For the responses we extract the necessary information and store them
    on each of the document

It can happen that the document reached the AEAT but the response
timed out for some reason (Read-Timeout).
  - The AEAT has (potentially) registered the document but we have
    not received the response they sent.
  - The document will be marked with an error starting with `[Read-Timeout] `.
    and automatically be sent again as soon as possible
  - When the document is resend successfully we receive a response that the document
    was rejected with error `[3000] Registro de facturación duplicado.`
    (Assuming the AEAT registered / not rejected the document when it was sent originally.)
    But the response also contains some information about the state and potential errors
    of the record / duplicate.
  - Since the duplicate is the document we previously sent we just take the state from there.

There are 2 ways to create a correcting Veri*Factu document for invoices
- Correction by difference: Done via "Reverse" in credit note wizard
  We just send a document representing the credit note as "correction by difference".
  The document references the corrected invoice.
- Correction by substitution: Done via "Reverse and Create Invoice" in credit note wizard
  We first send a document representing the reversing credit note (it does not
  reference the original invoice and is send as an "invoice type").
  And then we send the new invoice created by the wizard. It is send as a
  "correction by substitution" and references the original invoice.
  To link the new invoice to the original invoice a new field was added
- We do not support correcting multiple documents with a single new documents
  (neither correction by difference nor correction by substitution)

The "Veri*Factu" tab on the invoice form view also gives information
about which invoice was refunded or substituted.

Limitations
- In Veri*Factu there is some dedicated way to handle the substitution of
  simplified invoices with "real" invoices.
  This is not implemented currently.
- In Veri*Factu multiple tax types (`Impuesto`) and regimen keys (`ClaveRegimen`) can
  be indicated (one per `DetalleDesglose` element).
  We currently only allow a single tax type and regimen key for the whole
  document.
- In Veri*Factu it is possible to send a "Subsanación" in case a change is made
  that does not require updating the invoice PDF.
  This is currently not supported.
  - I.e. we do not support sending new submission documents for already registered
    (possibly with errors) records.
  - It is not possible to reset registered (possibly with errors) records back to draft.
- In Veri*Factu it is possible to send a cancellation for records that are otherwise
  known to the AEAT (not Veri*Factu).
  We do not support sending cancellations for records that are not Veri*Factu registered
  within Odoo.
- For simplified invoices there are the special keys / fields `FacturaSimplificadaArt7273`
  and `FacturaSinIdentifDestinatarioArt61d`. Currently we never set them (so they are assumed
  to be `N` by the AEAT).

task-3745982

closes odoo#197635

Signed-off-by: Sven Führ (svfu) <[email protected]>
svfu-odoo added a commit to odoo-dev/odoo that referenced this pull request Jul 30, 2025
Spain introduces a new EDI called "Veri*Factu" to send invoicing records
to the Spanish tax agency (AEAT).
It is mandatory for most tax payers (that cannot use any of the
other Spanish EDIs like SII or TicketBAI).

This commit adds 2 modules to enable Veri*Factu compliance
- `l10n_es_edi_verifactu` for invoicing / accounting
- `l10n_es_edi_verifactu_pos` for Point of Sale (PoS)

Their setup and usage is briefly described in the documentation
(see the related documentation PR).
The main features of the new modules are as follows.
- `l10n_es_edi_verifactu`
  - The "Send & Print" wizard can be used to generate and send Veri*Factu documents.
  - A QR code is added to the PDF of invoices send with the Veri*Factu option.
    It can be used to check whether the invoice is known to the AEAT.
  - A "Veri*Factu" tab is added to the account move form view.
    It i.e. gives an overview about the send documents and their status.
- `l10n_es_edi_verifactu_pos`
  - A Veri*Factu documents is generated and sent when validating each order.
  - A QR code is added to the PDF of PoS order receipts.
    It can be used to check whether the order is known to the AEAT.
  - A "Veri*Factu" tab is added to the pos order form view.
    It i.e. gives an overview about the send documents and their status.

I.e. note the following about Veri*Factu documents
- Each document has a fingerprint (hash of some important values) called `Huella`.
- All documents belonging to one company are linked together in a single chain in generation order.
  (Each document refers to the previous document including the `Huella` of the previous document)
- There is a waiting time between submissions of documents (usually 60s).
  We sent the document immediately if possible.
  But due to the waiting time this is not always possible.
- We still generate / store the needed values when the invoice is sent
  (mandated by Veri*Factu spec).
- Documents can be sent in batches.
  - Due to the waiting time we sent all "waiting" documents at once.
  - In case of 1000 documents the waiting time can be / is ignored
  - A "Veri*Factu Document" in Odoo only represents a single invoice / PoS order.
- The needed document values mandated by Veri*Factu are stored in JSON format
  on each invoice / order.
- The actual "communication" with AEAT is done via SOAP. (So we sent / receive
  XML files)
- We do not store the actual batch XML we sent to the AEAT or the received responses.
  - For the responses we extract the necessary information and store them
    on each of the document

It can happen that the document reached the AEAT but the response
timed out for some reason (Read-Timeout).
  - The AEAT has (potentially) registered the document but we have
    not received the response they sent.
  - The document will be marked with an error starting with `[Read-Timeout] `.
    and automatically be sent again as soon as possible
  - When the document is resend successfully we receive a response that the document
    was rejected with error `[3000] Registro de facturación duplicado.`
    (Assuming the AEAT registered / not rejected the document when it was sent originally.)
    But the response also contains some information about the state and potential errors
    of the record / duplicate.
  - Since the duplicate is the document we previously sent we just take the state from there.

There are 2 ways to create a correcting Veri*Factu document for invoices
- Correction by difference: Done via "Reverse" in credit note wizard
  We just send a document representing the credit note as "correction by difference".
  The document references the corrected invoice.
- Correction by substitution: Done via "Reverse and Create Invoice" in credit note wizard
  We first send a document representing the reversing credit note (it does not
  reference the original invoice and is send as an "invoice type").
  And then we send the new invoice created by the wizard. It is send as a
  "correction by substitution" and references the original invoice.
  To link the new invoice to the original invoice a new field was added
- We do not support correcting multiple documents with a single new documents
  (neither correction by difference nor correction by substitution)

The "Veri*Factu" tab on the invoice form view also gives information
about which invoice was refunded or substituted.

Limitations
- In Veri*Factu there is some dedicated way to handle the substitution of
  simplified invoices with "real" invoices.
  This is not implemented currently.
- In Veri*Factu multiple tax types (`Impuesto`) and regimen keys (`ClaveRegimen`) can
  be indicated (one per `DetalleDesglose` element).
  We currently only allow a single tax type and regimen key for the whole
  document.
- In Veri*Factu it is possible to send a "Subsanación" in case a change is made
  that does not require updating the invoice PDF.
  This is currently not supported.
  - I.e. we do not support sending new submission documents for already registered
    (possibly with errors) records.
  - It is not possible to reset registered (possibly with errors) records back to draft.
- In Veri*Factu it is possible to send a cancellation for records that are otherwise
  known to the AEAT (not Veri*Factu).
  We do not support sending cancellations for records that are not Veri*Factu registered
  within Odoo.
- For simplified invoices there are the special keys / fields `FacturaSimplificadaArt7273`
  and `FacturaSinIdentifDestinatarioArt61d`. Currently we never set them (so they are assumed
  to be `N` by the AEAT).

task-3745982

closes odoo#197635

Signed-off-by: Sven Führ (svfu) <[email protected]>
svfu-odoo added a commit to odoo-dev/odoo that referenced this pull request Jul 30, 2025
Spain introduces a new EDI called "Veri*Factu" to send invoicing records
to the Spanish tax agency (AEAT).
It is mandatory for most tax payers (that cannot use any of the
other Spanish EDIs like SII or TicketBAI).

This commit adds 2 modules to enable Veri*Factu compliance
- `l10n_es_edi_verifactu` for invoicing / accounting
- `l10n_es_edi_verifactu_pos` for Point of Sale (PoS)

Their setup and usage is briefly described in the documentation
(see the related documentation PR).
The main features of the new modules are as follows.
- `l10n_es_edi_verifactu`
  - The "Send & Print" wizard can be used to generate and send Veri*Factu documents.
  - A QR code is added to the PDF of invoices send with the Veri*Factu option.
    It can be used to check whether the invoice is known to the AEAT.
  - A "Veri*Factu" tab is added to the account move form view.
    It i.e. gives an overview about the send documents and their status.
- `l10n_es_edi_verifactu_pos`
  - A Veri*Factu documents is generated and sent when validating each order.
  - A QR code is added to the PDF of PoS order receipts.
    It can be used to check whether the order is known to the AEAT.
  - A "Veri*Factu" tab is added to the pos order form view.
    It i.e. gives an overview about the send documents and their status.

I.e. note the following about Veri*Factu documents
- Each document has a fingerprint (hash of some important values) called `Huella`.
- All documents belonging to one company are linked together in a single chain in generation order.
  (Each document refers to the previous document including the `Huella` of the previous document)
- There is a waiting time between submissions of documents (usually 60s).
  We sent the document immediately if possible.
  But due to the waiting time this is not always possible.
- We still generate / store the needed values when the invoice is sent
  (mandated by Veri*Factu spec).
- Documents can be sent in batches.
  - Due to the waiting time we sent all "waiting" documents at once.
  - In case of 1000 documents the waiting time can be / is ignored
  - A "Veri*Factu Document" in Odoo only represents a single invoice / PoS order.
- The needed document values mandated by Veri*Factu are stored in JSON format
  on each invoice / order.
- The actual "communication" with AEAT is done via SOAP. (So we sent / receive
  XML files)
- We do not store the actual batch XML we sent to the AEAT or the received responses.
  - For the responses we extract the necessary information and store them
    on each of the document

It can happen that the document reached the AEAT but the response
timed out for some reason (Read-Timeout).
  - The AEAT has (potentially) registered the document but we have
    not received the response they sent.
  - The document will be marked with an error starting with `[Read-Timeout] `.
    and automatically be sent again as soon as possible
  - When the document is resend successfully we receive a response that the document
    was rejected with error `[3000] Registro de facturación duplicado.`
    (Assuming the AEAT registered / not rejected the document when it was sent originally.)
    But the response also contains some information about the state and potential errors
    of the record / duplicate.
  - Since the duplicate is the document we previously sent we just take the state from there.

There are 2 ways to create a correcting Veri*Factu document for invoices
- Correction by difference: Done via "Reverse" in credit note wizard
  We just send a document representing the credit note as "correction by difference".
  The document references the corrected invoice.
- Correction by substitution: Done via "Reverse and Create Invoice" in credit note wizard
  We first send a document representing the reversing credit note (it does not
  reference the original invoice and is send as an "invoice type").
  And then we send the new invoice created by the wizard. It is send as a
  "correction by substitution" and references the original invoice.
  To link the new invoice to the original invoice a new field was added
- We do not support correcting multiple documents with a single new documents
  (neither correction by difference nor correction by substitution)

The "Veri*Factu" tab on the invoice form view also gives information
about which invoice was refunded or substituted.

Limitations
- In Veri*Factu there is some dedicated way to handle the substitution of
  simplified invoices with "real" invoices.
  This is not implemented currently.
- In Veri*Factu multiple tax types (`Impuesto`) and regimen keys (`ClaveRegimen`) can
  be indicated (one per `DetalleDesglose` element).
  We currently only allow a single tax type and regimen key for the whole
  document.
- In Veri*Factu it is possible to send a "Subsanación" in case a change is made
  that does not require updating the invoice PDF.
  This is currently not supported.
  - I.e. we do not support sending new submission documents for already registered
    (possibly with errors) records.
  - It is not possible to reset registered (possibly with errors) records back to draft.
- In Veri*Factu it is possible to send a cancellation for records that are otherwise
  known to the AEAT (not Veri*Factu).
  We do not support sending cancellations for records that are not Veri*Factu registered
  within Odoo.
- For simplified invoices there are the special keys / fields `FacturaSimplificadaArt7273`
  and `FacturaSinIdentifDestinatarioArt61d`. Currently we never set them (so they are assumed
  to be `N` by the AEAT).

task-3745982

closes odoo#197635

Signed-off-by: Sven Führ (svfu) <[email protected]>
svfu-odoo added a commit to odoo-dev/odoo that referenced this pull request Jul 30, 2025
Spain introduces a new EDI called "Veri*Factu" to send invoicing records
to the Spanish tax agency (AEAT).
It is mandatory for most tax payers (that cannot use any of the
other Spanish EDIs like SII or TicketBAI).

This commit adds 2 modules to enable Veri*Factu compliance
- `l10n_es_edi_verifactu` for invoicing / accounting
- `l10n_es_edi_verifactu_pos` for Point of Sale (PoS)

Their setup and usage is briefly described in the documentation
(see the related documentation PR).
The main features of the new modules are as follows.
- `l10n_es_edi_verifactu`
  - The "Send & Print" wizard can be used to generate and send Veri*Factu documents.
  - A QR code is added to the PDF of invoices send with the Veri*Factu option.
    It can be used to check whether the invoice is known to the AEAT.
  - A "Veri*Factu" tab is added to the account move form view.
    It i.e. gives an overview about the send documents and their status.
- `l10n_es_edi_verifactu_pos`
  - A Veri*Factu documents is generated and sent when validating each order.
  - A QR code is added to the PDF of PoS order receipts.
    It can be used to check whether the order is known to the AEAT.
  - A "Veri*Factu" tab is added to the pos order form view.
    It i.e. gives an overview about the send documents and their status.

I.e. note the following about Veri*Factu documents
- Each document has a fingerprint (hash of some important values) called `Huella`.
- All documents belonging to one company are linked together in a single chain in generation order.
  (Each document refers to the previous document including the `Huella` of the previous document)
- There is a waiting time between submissions of documents (usually 60s).
  We sent the document immediately if possible.
  But due to the waiting time this is not always possible.
- We still generate / store the needed values when the invoice is sent
  (mandated by Veri*Factu spec).
- Documents can be sent in batches.
  - Due to the waiting time we sent all "waiting" documents at once.
  - In case of 1000 documents the waiting time can be / is ignored
  - A "Veri*Factu Document" in Odoo only represents a single invoice / PoS order.
- The needed document values mandated by Veri*Factu are stored in JSON format
  on each invoice / order.
- The actual "communication" with AEAT is done via SOAP. (So we sent / receive
  XML files)
- We do not store the actual batch XML we sent to the AEAT or the received responses.
  - For the responses we extract the necessary information and store them
    on each of the document

It can happen that the document reached the AEAT but the response
timed out for some reason (Read-Timeout).
  - The AEAT has (potentially) registered the document but we have
    not received the response they sent.
  - The document will be marked with an error starting with `[Read-Timeout] `.
    and automatically be sent again as soon as possible
  - When the document is resend successfully we receive a response that the document
    was rejected with error `[3000] Registro de facturación duplicado.`
    (Assuming the AEAT registered / not rejected the document when it was sent originally.)
    But the response also contains some information about the state and potential errors
    of the record / duplicate.
  - Since the duplicate is the document we previously sent we just take the state from there.

There are 2 ways to create a correcting Veri*Factu document for invoices
- Correction by difference: Done via "Reverse" in credit note wizard
  We just send a document representing the credit note as "correction by difference".
  The document references the corrected invoice.
- Correction by substitution: Done via "Reverse and Create Invoice" in credit note wizard
  We first send a document representing the reversing credit note (it does not
  reference the original invoice and is send as an "invoice type").
  And then we send the new invoice created by the wizard. It is send as a
  "correction by substitution" and references the original invoice.
  To link the new invoice to the original invoice a new field was added
- We do not support correcting multiple documents with a single new documents
  (neither correction by difference nor correction by substitution)

The "Veri*Factu" tab on the invoice form view also gives information
about which invoice was refunded or substituted.

Limitations
- In Veri*Factu there is some dedicated way to handle the substitution of
  simplified invoices with "real" invoices.
  This is not implemented currently.
- In Veri*Factu multiple tax types (`Impuesto`) and regimen keys (`ClaveRegimen`) can
  be indicated (one per `DetalleDesglose` element).
  We currently only allow a single tax type and regimen key for the whole
  document.
- In Veri*Factu it is possible to send a "Subsanación" in case a change is made
  that does not require updating the invoice PDF.
  This is currently not supported.
  - I.e. we do not support sending new submission documents for already registered
    (possibly with errors) records.
  - It is not possible to reset registered (possibly with errors) records back to draft.
- In Veri*Factu it is possible to send a cancellation for records that are otherwise
  known to the AEAT (not Veri*Factu).
  We do not support sending cancellations for records that are not Veri*Factu registered
  within Odoo.
- For simplified invoices there are the special keys / fields `FacturaSimplificadaArt7273`
  and `FacturaSinIdentifDestinatarioArt61d`. Currently we never set them (so they are assumed
  to be `N` by the AEAT).

task-3745982

closes odoo#197635

Signed-off-by: Sven Führ (svfu) <[email protected]>
robodoo pushed a commit that referenced this pull request Jul 30, 2025
Spain introduces a new EDI called "Veri*Factu" to send invoicing records
to the Spanish tax agency (AEAT).
It is mandatory for most tax payers (that cannot use any of the
other Spanish EDIs like SII or TicketBAI).

This commit adds 2 modules to enable Veri*Factu compliance
- `l10n_es_edi_verifactu` for invoicing / accounting
- `l10n_es_edi_verifactu_pos` for Point of Sale (PoS)

Their setup and usage is briefly described in the documentation
(see the related documentation PR).
The main features of the new modules are as follows.
- `l10n_es_edi_verifactu`
  - The "Send & Print" wizard can be used to generate and send Veri*Factu documents.
  - A QR code is added to the PDF of invoices send with the Veri*Factu option.
    It can be used to check whether the invoice is known to the AEAT.
  - A "Veri*Factu" tab is added to the account move form view.
    It i.e. gives an overview about the send documents and their status.
- `l10n_es_edi_verifactu_pos`
  - A Veri*Factu documents is generated and sent when validating each order.
  - A QR code is added to the PDF of PoS order receipts.
    It can be used to check whether the order is known to the AEAT.
  - A "Veri*Factu" tab is added to the pos order form view.
    It i.e. gives an overview about the send documents and their status.

I.e. note the following about Veri*Factu documents
- Each document has a fingerprint (hash of some important values) called `Huella`.
- All documents belonging to one company are linked together in a single chain in generation order.
  (Each document refers to the previous document including the `Huella` of the previous document)
- There is a waiting time between submissions of documents (usually 60s).
  We sent the document immediately if possible.
  But due to the waiting time this is not always possible.
- We still generate / store the needed values when the invoice is sent
  (mandated by Veri*Factu spec).
- Documents can be sent in batches.
  - Due to the waiting time we sent all "waiting" documents at once.
  - In case of 1000 documents the waiting time can be / is ignored
  - A "Veri*Factu Document" in Odoo only represents a single invoice / PoS order.
- The needed document values mandated by Veri*Factu are stored in JSON format
  on each invoice / order.
- The actual "communication" with AEAT is done via SOAP. (So we sent / receive
  XML files)
- We do not store the actual batch XML we sent to the AEAT or the received responses.
  - For the responses we extract the necessary information and store them
    on each of the document

It can happen that the document reached the AEAT but the response
timed out for some reason (Read-Timeout).
  - The AEAT has (potentially) registered the document but we have
    not received the response they sent.
  - The document will be marked with an error starting with `[Read-Timeout] `.
    and automatically be sent again as soon as possible
  - When the document is resend successfully we receive a response that the document
    was rejected with error `[3000] Registro de facturación duplicado.`
    (Assuming the AEAT registered / not rejected the document when it was sent originally.)
    But the response also contains some information about the state and potential errors
    of the record / duplicate.
  - Since the duplicate is the document we previously sent we just take the state from there.

There are 2 ways to create a correcting Veri*Factu document for invoices
- Correction by difference: Done via "Reverse" in credit note wizard
  We just send a document representing the credit note as "correction by difference".
  The document references the corrected invoice.
- Correction by substitution: Done via "Reverse and Create Invoice" in credit note wizard
  We first send a document representing the reversing credit note (it does not
  reference the original invoice and is send as an "invoice type").
  And then we send the new invoice created by the wizard. It is send as a
  "correction by substitution" and references the original invoice.
  To link the new invoice to the original invoice a new field was added
- We do not support correcting multiple documents with a single new documents
  (neither correction by difference nor correction by substitution)

The "Veri*Factu" tab on the invoice form view also gives information
about which invoice was refunded or substituted.

Limitations
- In Veri*Factu there is some dedicated way to handle the substitution of
  simplified invoices with "real" invoices.
  This is not implemented currently.
- In Veri*Factu multiple tax types (`Impuesto`) and regimen keys (`ClaveRegimen`) can
  be indicated (one per `DetalleDesglose` element).
  We currently only allow a single tax type and regimen key for the whole
  document.
- In Veri*Factu it is possible to send a "Subsanación" in case a change is made
  that does not require updating the invoice PDF.
  This is currently not supported.
  - I.e. we do not support sending new submission documents for already registered
    (possibly with errors) records.
  - It is not possible to reset registered (possibly with errors) records back to draft.
- In Veri*Factu it is possible to send a cancellation for records that are otherwise
  known to the AEAT (not Veri*Factu).
  We do not support sending cancellations for records that are not Veri*Factu registered
  within Odoo.
- For simplified invoices there are the special keys / fields `FacturaSimplificadaArt7273`
  and `FacturaSinIdentifDestinatarioArt61d`. Currently we never set them (so they are assumed
  to be `N` by the AEAT).

task-3745982

closes #197635

closes #219953

Signed-off-by: Sven Führ (svfu) <[email protected]>
fw-bot pushed a commit to odoo-dev/odoo that referenced this pull request Jul 30, 2025
Spain introduces a new EDI called "Veri*Factu" to send invoicing records
to the Spanish tax agency (AEAT).
It is mandatory for most tax payers (that cannot use any of the
other Spanish EDIs like SII or TicketBAI).

This commit adds 2 modules to enable Veri*Factu compliance
- `l10n_es_edi_verifactu` for invoicing / accounting
- `l10n_es_edi_verifactu_pos` for Point of Sale (PoS)

Their setup and usage is briefly described in the documentation
(see the related documentation PR).
The main features of the new modules are as follows.
- `l10n_es_edi_verifactu`
  - The "Send & Print" wizard can be used to generate and send Veri*Factu documents.
  - A QR code is added to the PDF of invoices send with the Veri*Factu option.
    It can be used to check whether the invoice is known to the AEAT.
  - A "Veri*Factu" tab is added to the account move form view.
    It i.e. gives an overview about the send documents and their status.
- `l10n_es_edi_verifactu_pos`
  - A Veri*Factu documents is generated and sent when validating each order.
  - A QR code is added to the PDF of PoS order receipts.
    It can be used to check whether the order is known to the AEAT.
  - A "Veri*Factu" tab is added to the pos order form view.
    It i.e. gives an overview about the send documents and their status.

I.e. note the following about Veri*Factu documents
- Each document has a fingerprint (hash of some important values) called `Huella`.
- All documents belonging to one company are linked together in a single chain in generation order.
  (Each document refers to the previous document including the `Huella` of the previous document)
- There is a waiting time between submissions of documents (usually 60s).
  We sent the document immediately if possible.
  But due to the waiting time this is not always possible.
- We still generate / store the needed values when the invoice is sent
  (mandated by Veri*Factu spec).
- Documents can be sent in batches.
  - Due to the waiting time we sent all "waiting" documents at once.
  - In case of 1000 documents the waiting time can be / is ignored
  - A "Veri*Factu Document" in Odoo only represents a single invoice / PoS order.
- The needed document values mandated by Veri*Factu are stored in JSON format
  on each invoice / order.
- The actual "communication" with AEAT is done via SOAP. (So we sent / receive
  XML files)
- We do not store the actual batch XML we sent to the AEAT or the received responses.
  - For the responses we extract the necessary information and store them
    on each of the document

It can happen that the document reached the AEAT but the response
timed out for some reason (Read-Timeout).
  - The AEAT has (potentially) registered the document but we have
    not received the response they sent.
  - The document will be marked with an error starting with `[Read-Timeout] `.
    and automatically be sent again as soon as possible
  - When the document is resend successfully we receive a response that the document
    was rejected with error `[3000] Registro de facturación duplicado.`
    (Assuming the AEAT registered / not rejected the document when it was sent originally.)
    But the response also contains some information about the state and potential errors
    of the record / duplicate.
  - Since the duplicate is the document we previously sent we just take the state from there.

There are 2 ways to create a correcting Veri*Factu document for invoices
- Correction by difference: Done via "Reverse" in credit note wizard
  We just send a document representing the credit note as "correction by difference".
  The document references the corrected invoice.
- Correction by substitution: Done via "Reverse and Create Invoice" in credit note wizard
  We first send a document representing the reversing credit note (it does not
  reference the original invoice and is send as an "invoice type").
  And then we send the new invoice created by the wizard. It is send as a
  "correction by substitution" and references the original invoice.
  To link the new invoice to the original invoice a new field was added
- We do not support correcting multiple documents with a single new documents
  (neither correction by difference nor correction by substitution)

The "Veri*Factu" tab on the invoice form view also gives information
about which invoice was refunded or substituted.

Limitations
- In Veri*Factu there is some dedicated way to handle the substitution of
  simplified invoices with "real" invoices.
  This is not implemented currently.
- In Veri*Factu multiple tax types (`Impuesto`) and regimen keys (`ClaveRegimen`) can
  be indicated (one per `DetalleDesglose` element).
  We currently only allow a single tax type and regimen key for the whole
  document.
- In Veri*Factu it is possible to send a "Subsanación" in case a change is made
  that does not require updating the invoice PDF.
  This is currently not supported.
  - I.e. we do not support sending new submission documents for already registered
    (possibly with errors) records.
  - It is not possible to reset registered (possibly with errors) records back to draft.
- In Veri*Factu it is possible to send a cancellation for records that are otherwise
  known to the AEAT (not Veri*Factu).
  We do not support sending cancellations for records that are not Veri*Factu registered
  within Odoo.
- For simplified invoices there are the special keys / fields `FacturaSimplificadaArt7273`
  and `FacturaSinIdentifDestinatarioArt61d`. Currently we never set them (so they are assumed
  to be `N` by the AEAT).

task-3745982

closes odoo#197635

Signed-off-by: Sven Führ (svfu) <[email protected]>
X-original-commit: 02f8d55
svfu-odoo added a commit to odoo-dev/odoo that referenced this pull request Jul 30, 2025
Spain introduces a new EDI called "Veri*Factu" to send invoicing records
to the Spanish tax agency (AEAT).
It is mandatory for most tax payers (that cannot use any of the
other Spanish EDIs like SII or TicketBAI).

This commit adds 2 modules to enable Veri*Factu compliance
- `l10n_es_edi_verifactu` for invoicing / accounting
- `l10n_es_edi_verifactu_pos` for Point of Sale (PoS)

Their setup and usage is briefly described in the documentation
(see the related documentation PR).
The main features of the new modules are as follows.
- `l10n_es_edi_verifactu`
  - The "Send & Print" wizard can be used to generate and send Veri*Factu documents.
  - A QR code is added to the PDF of invoices send with the Veri*Factu option.
    It can be used to check whether the invoice is known to the AEAT.
  - A "Veri*Factu" tab is added to the account move form view.
    It i.e. gives an overview about the send documents and their status.
- `l10n_es_edi_verifactu_pos`
  - A Veri*Factu documents is generated and sent when validating each order.
  - A QR code is added to the PDF of PoS order receipts.
    It can be used to check whether the order is known to the AEAT.
  - A "Veri*Factu" tab is added to the pos order form view.
    It i.e. gives an overview about the send documents and their status.

I.e. note the following about Veri*Factu documents
- Each document has a fingerprint (hash of some important values) called `Huella`.
- All documents belonging to one company are linked together in a single chain in generation order.
  (Each document refers to the previous document including the `Huella` of the previous document)
- There is a waiting time between submissions of documents (usually 60s).
  We sent the document immediately if possible.
  But due to the waiting time this is not always possible.
- We still generate / store the needed values when the invoice is sent
  (mandated by Veri*Factu spec).
- Documents can be sent in batches.
  - Due to the waiting time we sent all "waiting" documents at once.
  - In case of 1000 documents the waiting time can be / is ignored
  - A "Veri*Factu Document" in Odoo only represents a single invoice / PoS order.
- The needed document values mandated by Veri*Factu are stored in JSON format
  on each invoice / order.
- The actual "communication" with AEAT is done via SOAP. (So we sent / receive
  XML files)
- We do not store the actual batch XML we sent to the AEAT or the received responses.
  - For the responses we extract the necessary information and store them
    on each of the document

It can happen that the document reached the AEAT but the response
timed out for some reason (Read-Timeout).
  - The AEAT has (potentially) registered the document but we have
    not received the response they sent.
  - The document will be marked with an error starting with `[Read-Timeout] `.
    and automatically be sent again as soon as possible
  - When the document is resend successfully we receive a response that the document
    was rejected with error `[3000] Registro de facturación duplicado.`
    (Assuming the AEAT registered / not rejected the document when it was sent originally.)
    But the response also contains some information about the state and potential errors
    of the record / duplicate.
  - Since the duplicate is the document we previously sent we just take the state from there.

There are 2 ways to create a correcting Veri*Factu document for invoices
- Correction by difference: Done via "Reverse" in credit note wizard
  We just send a document representing the credit note as "correction by difference".
  The document references the corrected invoice.
- Correction by substitution: Done via "Reverse and Create Invoice" in credit note wizard
  We first send a document representing the reversing credit note (it does not
  reference the original invoice and is send as an "invoice type").
  And then we send the new invoice created by the wizard. It is send as a
  "correction by substitution" and references the original invoice.
  To link the new invoice to the original invoice a new field was added
- We do not support correcting multiple documents with a single new documents
  (neither correction by difference nor correction by substitution)

The "Veri*Factu" tab on the invoice form view also gives information
about which invoice was refunded or substituted.

Limitations
- In Veri*Factu there is some dedicated way to handle the substitution of
  simplified invoices with "real" invoices.
  This is not implemented currently.
- In Veri*Factu multiple tax types (`Impuesto`) and regimen keys (`ClaveRegimen`) can
  be indicated (one per `DetalleDesglose` element).
  We currently only allow a single tax type and regimen key for the whole
  document.
- In Veri*Factu it is possible to send a "Subsanación" in case a change is made
  that does not require updating the invoice PDF.
  This is currently not supported.
  - I.e. we do not support sending new submission documents for already registered
    (possibly with errors) records.
  - It is not possible to reset registered (possibly with errors) records back to draft.
- In Veri*Factu it is possible to send a cancellation for records that are otherwise
  known to the AEAT (not Veri*Factu).
  We do not support sending cancellations for records that are not Veri*Factu registered
  within Odoo.
- For simplified invoices there are the special keys / fields `FacturaSimplificadaArt7273`
  and `FacturaSinIdentifDestinatarioArt61d`. Currently we never set them (so they are assumed
  to be `N` by the AEAT).

task-3745982

closes odoo#197635

Signed-off-by: Sven Führ (svfu) <[email protected]>
X-original-commit: 02f8d55
svfu-odoo added a commit to odoo-dev/odoo that referenced this pull request Jul 30, 2025
Spain introduces a new EDI called "Veri*Factu" to send invoicing records
to the Spanish tax agency (AEAT).
It is mandatory for most tax payers (that cannot use any of the
other Spanish EDIs like SII or TicketBAI).

This commit adds 2 modules to enable Veri*Factu compliance
- `l10n_es_edi_verifactu` for invoicing / accounting
- `l10n_es_edi_verifactu_pos` for Point of Sale (PoS)

Their setup and usage is briefly described in the documentation
(see the related documentation PR).
The main features of the new modules are as follows.
- `l10n_es_edi_verifactu`
  - The "Send & Print" wizard can be used to generate and send Veri*Factu documents.
  - A QR code is added to the PDF of invoices send with the Veri*Factu option.
    It can be used to check whether the invoice is known to the AEAT.
  - A "Veri*Factu" tab is added to the account move form view.
    It i.e. gives an overview about the send documents and their status.
- `l10n_es_edi_verifactu_pos`
  - A Veri*Factu documents is generated and sent when validating each order.
  - A QR code is added to the PDF of PoS order receipts.
    It can be used to check whether the order is known to the AEAT.
  - A "Veri*Factu" tab is added to the pos order form view.
    It i.e. gives an overview about the send documents and their status.

I.e. note the following about Veri*Factu documents
- Each document has a fingerprint (hash of some important values) called `Huella`.
- All documents belonging to one company are linked together in a single chain in generation order.
  (Each document refers to the previous document including the `Huella` of the previous document)
- There is a waiting time between submissions of documents (usually 60s).
  We sent the document immediately if possible.
  But due to the waiting time this is not always possible.
- We still generate / store the needed values when the invoice is sent
  (mandated by Veri*Factu spec).
- Documents can be sent in batches.
  - Due to the waiting time we sent all "waiting" documents at once.
  - In case of 1000 documents the waiting time can be / is ignored
  - A "Veri*Factu Document" in Odoo only represents a single invoice / PoS order.
- The needed document values mandated by Veri*Factu are stored in JSON format
  on each invoice / order.
- The actual "communication" with AEAT is done via SOAP. (So we sent / receive
  XML files)
- We do not store the actual batch XML we sent to the AEAT or the received responses.
  - For the responses we extract the necessary information and store them
    on each of the document

It can happen that the document reached the AEAT but the response
timed out for some reason (Read-Timeout).
  - The AEAT has (potentially) registered the document but we have
    not received the response they sent.
  - The document will be marked with an error starting with `[Read-Timeout] `.
    and automatically be sent again as soon as possible
  - When the document is resend successfully we receive a response that the document
    was rejected with error `[3000] Registro de facturación duplicado.`
    (Assuming the AEAT registered / not rejected the document when it was sent originally.)
    But the response also contains some information about the state and potential errors
    of the record / duplicate.
  - Since the duplicate is the document we previously sent we just take the state from there.

There are 2 ways to create a correcting Veri*Factu document for invoices
- Correction by difference: Done via "Reverse" in credit note wizard
  We just send a document representing the credit note as "correction by difference".
  The document references the corrected invoice.
- Correction by substitution: Done via "Reverse and Create Invoice" in credit note wizard
  We first send a document representing the reversing credit note (it does not
  reference the original invoice and is send as an "invoice type").
  And then we send the new invoice created by the wizard. It is send as a
  "correction by substitution" and references the original invoice.
  To link the new invoice to the original invoice a new field was added
- We do not support correcting multiple documents with a single new documents
  (neither correction by difference nor correction by substitution)

The "Veri*Factu" tab on the invoice form view also gives information
about which invoice was refunded or substituted.

Limitations
- In Veri*Factu there is some dedicated way to handle the substitution of
  simplified invoices with "real" invoices.
  This is not implemented currently.
- In Veri*Factu multiple tax types (`Impuesto`) and regimen keys (`ClaveRegimen`) can
  be indicated (one per `DetalleDesglose` element).
  We currently only allow a single tax type and regimen key for the whole
  document.
- In Veri*Factu it is possible to send a "Subsanación" in case a change is made
  that does not require updating the invoice PDF.
  This is currently not supported.
  - I.e. we do not support sending new submission documents for already registered
    (possibly with errors) records.
  - It is not possible to reset registered (possibly with errors) records back to draft.
- In Veri*Factu it is possible to send a cancellation for records that are otherwise
  known to the AEAT (not Veri*Factu).
  We do not support sending cancellations for records that are not Veri*Factu registered
  within Odoo.
- For simplified invoices there are the special keys / fields `FacturaSimplificadaArt7273`
  and `FacturaSinIdentifDestinatarioArt61d`. Currently we never set them (so they are assumed
  to be `N` by the AEAT).

task-3745982

closes odoo#197635

Signed-off-by: Sven Führ (svfu) <[email protected]>
X-original-commit: 02f8d55
robodoo pushed a commit that referenced this pull request Jul 31, 2025
Spain introduces a new EDI called "Veri*Factu" to send invoicing records
to the Spanish tax agency (AEAT).
It is mandatory for most tax payers (that cannot use any of the
other Spanish EDIs like SII or TicketBAI).

This commit adds 2 modules to enable Veri*Factu compliance
- `l10n_es_edi_verifactu` for invoicing / accounting
- `l10n_es_edi_verifactu_pos` for Point of Sale (PoS)

Their setup and usage is briefly described in the documentation
(see the related documentation PR).
The main features of the new modules are as follows.
- `l10n_es_edi_verifactu`
  - The "Send & Print" wizard can be used to generate and send Veri*Factu documents.
  - A QR code is added to the PDF of invoices send with the Veri*Factu option.
    It can be used to check whether the invoice is known to the AEAT.
  - A "Veri*Factu" tab is added to the account move form view.
    It i.e. gives an overview about the send documents and their status.
- `l10n_es_edi_verifactu_pos`
  - A Veri*Factu documents is generated and sent when validating each order.
  - A QR code is added to the PDF of PoS order receipts.
    It can be used to check whether the order is known to the AEAT.
  - A "Veri*Factu" tab is added to the pos order form view.
    It i.e. gives an overview about the send documents and their status.

I.e. note the following about Veri*Factu documents
- Each document has a fingerprint (hash of some important values) called `Huella`.
- All documents belonging to one company are linked together in a single chain in generation order.
  (Each document refers to the previous document including the `Huella` of the previous document)
- There is a waiting time between submissions of documents (usually 60s).
  We sent the document immediately if possible.
  But due to the waiting time this is not always possible.
- We still generate / store the needed values when the invoice is sent
  (mandated by Veri*Factu spec).
- Documents can be sent in batches.
  - Due to the waiting time we sent all "waiting" documents at once.
  - In case of 1000 documents the waiting time can be / is ignored
  - A "Veri*Factu Document" in Odoo only represents a single invoice / PoS order.
- The needed document values mandated by Veri*Factu are stored in JSON format
  on each invoice / order.
- The actual "communication" with AEAT is done via SOAP. (So we sent / receive
  XML files)
- We do not store the actual batch XML we sent to the AEAT or the received responses.
  - For the responses we extract the necessary information and store them
    on each of the document

It can happen that the document reached the AEAT but the response
timed out for some reason (Read-Timeout).
  - The AEAT has (potentially) registered the document but we have
    not received the response they sent.
  - The document will be marked with an error starting with `[Read-Timeout] `.
    and automatically be sent again as soon as possible
  - When the document is resend successfully we receive a response that the document
    was rejected with error `[3000] Registro de facturación duplicado.`
    (Assuming the AEAT registered / not rejected the document when it was sent originally.)
    But the response also contains some information about the state and potential errors
    of the record / duplicate.
  - Since the duplicate is the document we previously sent we just take the state from there.

There are 2 ways to create a correcting Veri*Factu document for invoices
- Correction by difference: Done via "Reverse" in credit note wizard
  We just send a document representing the credit note as "correction by difference".
  The document references the corrected invoice.
- Correction by substitution: Done via "Reverse and Create Invoice" in credit note wizard
  We first send a document representing the reversing credit note (it does not
  reference the original invoice and is send as an "invoice type").
  And then we send the new invoice created by the wizard. It is send as a
  "correction by substitution" and references the original invoice.
  To link the new invoice to the original invoice a new field was added
- We do not support correcting multiple documents with a single new documents
  (neither correction by difference nor correction by substitution)

The "Veri*Factu" tab on the invoice form view also gives information
about which invoice was refunded or substituted.

Limitations
- In Veri*Factu there is some dedicated way to handle the substitution of
  simplified invoices with "real" invoices.
  This is not implemented currently.
- In Veri*Factu multiple tax types (`Impuesto`) and regimen keys (`ClaveRegimen`) can
  be indicated (one per `DetalleDesglose` element).
  We currently only allow a single tax type and regimen key for the whole
  document.
- In Veri*Factu it is possible to send a "Subsanación" in case a change is made
  that does not require updating the invoice PDF.
  This is currently not supported.
  - I.e. we do not support sending new submission documents for already registered
    (possibly with errors) records.
  - It is not possible to reset registered (possibly with errors) records back to draft.
- In Veri*Factu it is possible to send a cancellation for records that are otherwise
  known to the AEAT (not Veri*Factu).
  We do not support sending cancellations for records that are not Veri*Factu registered
  within Odoo.
- For simplified invoices there are the special keys / fields `FacturaSimplificadaArt7273`
  and `FacturaSinIdentifDestinatarioArt61d`. Currently we never set them (so they are assumed
  to be `N` by the AEAT).

task-3745982

closes #197635

closes #221214

X-original-commit: 02f8d55
Signed-off-by: Sven Führ (svfu) <[email protected]>
fw-bot pushed a commit to odoo-dev/odoo that referenced this pull request Jul 31, 2025
Spain introduces a new EDI called "Veri*Factu" to send invoicing records
to the Spanish tax agency (AEAT).
It is mandatory for most tax payers (that cannot use any of the
other Spanish EDIs like SII or TicketBAI).

This commit adds 2 modules to enable Veri*Factu compliance
- `l10n_es_edi_verifactu` for invoicing / accounting
- `l10n_es_edi_verifactu_pos` for Point of Sale (PoS)

Their setup and usage is briefly described in the documentation
(see the related documentation PR).
The main features of the new modules are as follows.
- `l10n_es_edi_verifactu`
  - The "Send & Print" wizard can be used to generate and send Veri*Factu documents.
  - A QR code is added to the PDF of invoices send with the Veri*Factu option.
    It can be used to check whether the invoice is known to the AEAT.
  - A "Veri*Factu" tab is added to the account move form view.
    It i.e. gives an overview about the send documents and their status.
- `l10n_es_edi_verifactu_pos`
  - A Veri*Factu documents is generated and sent when validating each order.
  - A QR code is added to the PDF of PoS order receipts.
    It can be used to check whether the order is known to the AEAT.
  - A "Veri*Factu" tab is added to the pos order form view.
    It i.e. gives an overview about the send documents and their status.

I.e. note the following about Veri*Factu documents
- Each document has a fingerprint (hash of some important values) called `Huella`.
- All documents belonging to one company are linked together in a single chain in generation order.
  (Each document refers to the previous document including the `Huella` of the previous document)
- There is a waiting time between submissions of documents (usually 60s).
  We sent the document immediately if possible.
  But due to the waiting time this is not always possible.
- We still generate / store the needed values when the invoice is sent
  (mandated by Veri*Factu spec).
- Documents can be sent in batches.
  - Due to the waiting time we sent all "waiting" documents at once.
  - In case of 1000 documents the waiting time can be / is ignored
  - A "Veri*Factu Document" in Odoo only represents a single invoice / PoS order.
- The needed document values mandated by Veri*Factu are stored in JSON format
  on each invoice / order.
- The actual "communication" with AEAT is done via SOAP. (So we sent / receive
  XML files)
- We do not store the actual batch XML we sent to the AEAT or the received responses.
  - For the responses we extract the necessary information and store them
    on each of the document

It can happen that the document reached the AEAT but the response
timed out for some reason (Read-Timeout).
  - The AEAT has (potentially) registered the document but we have
    not received the response they sent.
  - The document will be marked with an error starting with `[Read-Timeout] `.
    and automatically be sent again as soon as possible
  - When the document is resend successfully we receive a response that the document
    was rejected with error `[3000] Registro de facturación duplicado.`
    (Assuming the AEAT registered / not rejected the document when it was sent originally.)
    But the response also contains some information about the state and potential errors
    of the record / duplicate.
  - Since the duplicate is the document we previously sent we just take the state from there.

There are 2 ways to create a correcting Veri*Factu document for invoices
- Correction by difference: Done via "Reverse" in credit note wizard
  We just send a document representing the credit note as "correction by difference".
  The document references the corrected invoice.
- Correction by substitution: Done via "Reverse and Create Invoice" in credit note wizard
  We first send a document representing the reversing credit note (it does not
  reference the original invoice and is send as an "invoice type").
  And then we send the new invoice created by the wizard. It is send as a
  "correction by substitution" and references the original invoice.
  To link the new invoice to the original invoice a new field was added
- We do not support correcting multiple documents with a single new documents
  (neither correction by difference nor correction by substitution)

The "Veri*Factu" tab on the invoice form view also gives information
about which invoice was refunded or substituted.

Limitations
- In Veri*Factu there is some dedicated way to handle the substitution of
  simplified invoices with "real" invoices.
  This is not implemented currently.
- In Veri*Factu multiple tax types (`Impuesto`) and regimen keys (`ClaveRegimen`) can
  be indicated (one per `DetalleDesglose` element).
  We currently only allow a single tax type and regimen key for the whole
  document.
- In Veri*Factu it is possible to send a "Subsanación" in case a change is made
  that does not require updating the invoice PDF.
  This is currently not supported.
  - I.e. we do not support sending new submission documents for already registered
    (possibly with errors) records.
  - It is not possible to reset registered (possibly with errors) records back to draft.
- In Veri*Factu it is possible to send a cancellation for records that are otherwise
  known to the AEAT (not Veri*Factu).
  We do not support sending cancellations for records that are not Veri*Factu registered
  within Odoo.
- For simplified invoices there are the special keys / fields `FacturaSimplificadaArt7273`
  and `FacturaSinIdentifDestinatarioArt61d`. Currently we never set them (so they are assumed
  to be `N` by the AEAT).

task-3745982

closes odoo#197635

Signed-off-by: Sven Führ (svfu) <[email protected]>
X-original-commit: ba362e7
svfu-odoo added a commit to odoo-dev/odoo that referenced this pull request Jul 31, 2025
Spain introduces a new EDI called "Veri*Factu" to send invoicing records
to the Spanish tax agency (AEAT).
It is mandatory for most tax payers (that cannot use any of the
other Spanish EDIs like SII or TicketBAI).

This commit adds 2 modules to enable Veri*Factu compliance
- `l10n_es_edi_verifactu` for invoicing / accounting
- `l10n_es_edi_verifactu_pos` for Point of Sale (PoS)

Their setup and usage is briefly described in the documentation
(see the related documentation PR).
The main features of the new modules are as follows.
- `l10n_es_edi_verifactu`
  - The "Send & Print" wizard can be used to generate and send Veri*Factu documents.
  - A QR code is added to the PDF of invoices send with the Veri*Factu option.
    It can be used to check whether the invoice is known to the AEAT.
  - A "Veri*Factu" tab is added to the account move form view.
    It i.e. gives an overview about the send documents and their status.
- `l10n_es_edi_verifactu_pos`
  - A Veri*Factu documents is generated and sent when validating each order.
  - A QR code is added to the PDF of PoS order receipts.
    It can be used to check whether the order is known to the AEAT.
  - A "Veri*Factu" tab is added to the pos order form view.
    It i.e. gives an overview about the send documents and their status.

I.e. note the following about Veri*Factu documents
- Each document has a fingerprint (hash of some important values) called `Huella`.
- All documents belonging to one company are linked together in a single chain in generation order.
  (Each document refers to the previous document including the `Huella` of the previous document)
- There is a waiting time between submissions of documents (usually 60s).
  We sent the document immediately if possible.
  But due to the waiting time this is not always possible.
- We still generate / store the needed values when the invoice is sent
  (mandated by Veri*Factu spec).
- Documents can be sent in batches.
  - Due to the waiting time we sent all "waiting" documents at once.
  - In case of 1000 documents the waiting time can be / is ignored
  - A "Veri*Factu Document" in Odoo only represents a single invoice / PoS order.
- The needed document values mandated by Veri*Factu are stored in JSON format
  on each invoice / order.
- The actual "communication" with AEAT is done via SOAP. (So we sent / receive
  XML files)
- We do not store the actual batch XML we sent to the AEAT or the received responses.
  - For the responses we extract the necessary information and store them
    on each of the document

It can happen that the document reached the AEAT but the response
timed out for some reason (Read-Timeout).
  - The AEAT has (potentially) registered the document but we have
    not received the response they sent.
  - The document will be marked with an error starting with `[Read-Timeout] `.
    and automatically be sent again as soon as possible
  - When the document is resend successfully we receive a response that the document
    was rejected with error `[3000] Registro de facturación duplicado.`
    (Assuming the AEAT registered / not rejected the document when it was sent originally.)
    But the response also contains some information about the state and potential errors
    of the record / duplicate.
  - Since the duplicate is the document we previously sent we just take the state from there.

There are 2 ways to create a correcting Veri*Factu document for invoices
- Correction by difference: Done via "Reverse" in credit note wizard
  We just send a document representing the credit note as "correction by difference".
  The document references the corrected invoice.
- Correction by substitution: Done via "Reverse and Create Invoice" in credit note wizard
  We first send a document representing the reversing credit note (it does not
  reference the original invoice and is send as an "invoice type").
  And then we send the new invoice created by the wizard. It is send as a
  "correction by substitution" and references the original invoice.
  To link the new invoice to the original invoice a new field was added
- We do not support correcting multiple documents with a single new documents
  (neither correction by difference nor correction by substitution)

The "Veri*Factu" tab on the invoice form view also gives information
about which invoice was refunded or substituted.

Limitations
- In Veri*Factu there is some dedicated way to handle the substitution of
  simplified invoices with "real" invoices.
  This is not implemented currently.
- In Veri*Factu multiple tax types (`Impuesto`) and regimen keys (`ClaveRegimen`) can
  be indicated (one per `DetalleDesglose` element).
  We currently only allow a single tax type and regimen key for the whole
  document.
- In Veri*Factu it is possible to send a "Subsanación" in case a change is made
  that does not require updating the invoice PDF.
  This is currently not supported.
  - I.e. we do not support sending new submission documents for already registered
    (possibly with errors) records.
  - It is not possible to reset registered (possibly with errors) records back to draft.
- In Veri*Factu it is possible to send a cancellation for records that are otherwise
  known to the AEAT (not Veri*Factu).
  We do not support sending cancellations for records that are not Veri*Factu registered
  within Odoo.
- For simplified invoices there are the special keys / fields `FacturaSimplificadaArt7273`
  and `FacturaSinIdentifDestinatarioArt61d`. Currently we never set them (so they are assumed
  to be `N` by the AEAT).

task-3745982

closes odoo#197635

Signed-off-by: Sven Führ (svfu) <[email protected]>
X-original-commit: ba362e7
robodoo pushed a commit that referenced this pull request Aug 1, 2025
Spain introduces a new EDI called "Veri*Factu" to send invoicing records
to the Spanish tax agency (AEAT).
It is mandatory for most tax payers (that cannot use any of the
other Spanish EDIs like SII or TicketBAI).

This commit adds 2 modules to enable Veri*Factu compliance
- `l10n_es_edi_verifactu` for invoicing / accounting
- `l10n_es_edi_verifactu_pos` for Point of Sale (PoS)

Their setup and usage is briefly described in the documentation
(see the related documentation PR).
The main features of the new modules are as follows.
- `l10n_es_edi_verifactu`
  - The "Send & Print" wizard can be used to generate and send Veri*Factu documents.
  - A QR code is added to the PDF of invoices send with the Veri*Factu option.
    It can be used to check whether the invoice is known to the AEAT.
  - A "Veri*Factu" tab is added to the account move form view.
    It i.e. gives an overview about the send documents and their status.
- `l10n_es_edi_verifactu_pos`
  - A Veri*Factu documents is generated and sent when validating each order.
  - A QR code is added to the PDF of PoS order receipts.
    It can be used to check whether the order is known to the AEAT.
  - A "Veri*Factu" tab is added to the pos order form view.
    It i.e. gives an overview about the send documents and their status.

I.e. note the following about Veri*Factu documents
- Each document has a fingerprint (hash of some important values) called `Huella`.
- All documents belonging to one company are linked together in a single chain in generation order.
  (Each document refers to the previous document including the `Huella` of the previous document)
- There is a waiting time between submissions of documents (usually 60s).
  We sent the document immediately if possible.
  But due to the waiting time this is not always possible.
- We still generate / store the needed values when the invoice is sent
  (mandated by Veri*Factu spec).
- Documents can be sent in batches.
  - Due to the waiting time we sent all "waiting" documents at once.
  - In case of 1000 documents the waiting time can be / is ignored
  - A "Veri*Factu Document" in Odoo only represents a single invoice / PoS order.
- The needed document values mandated by Veri*Factu are stored in JSON format
  on each invoice / order.
- The actual "communication" with AEAT is done via SOAP. (So we sent / receive
  XML files)
- We do not store the actual batch XML we sent to the AEAT or the received responses.
  - For the responses we extract the necessary information and store them
    on each of the document

It can happen that the document reached the AEAT but the response
timed out for some reason (Read-Timeout).
  - The AEAT has (potentially) registered the document but we have
    not received the response they sent.
  - The document will be marked with an error starting with `[Read-Timeout] `.
    and automatically be sent again as soon as possible
  - When the document is resend successfully we receive a response that the document
    was rejected with error `[3000] Registro de facturación duplicado.`
    (Assuming the AEAT registered / not rejected the document when it was sent originally.)
    But the response also contains some information about the state and potential errors
    of the record / duplicate.
  - Since the duplicate is the document we previously sent we just take the state from there.

There are 2 ways to create a correcting Veri*Factu document for invoices
- Correction by difference: Done via "Reverse" in credit note wizard
  We just send a document representing the credit note as "correction by difference".
  The document references the corrected invoice.
- Correction by substitution: Done via "Reverse and Create Invoice" in credit note wizard
  We first send a document representing the reversing credit note (it does not
  reference the original invoice and is send as an "invoice type").
  And then we send the new invoice created by the wizard. It is send as a
  "correction by substitution" and references the original invoice.
  To link the new invoice to the original invoice a new field was added
- We do not support correcting multiple documents with a single new documents
  (neither correction by difference nor correction by substitution)

The "Veri*Factu" tab on the invoice form view also gives information
about which invoice was refunded or substituted.

Limitations
- In Veri*Factu there is some dedicated way to handle the substitution of
  simplified invoices with "real" invoices.
  This is not implemented currently.
- In Veri*Factu multiple tax types (`Impuesto`) and regimen keys (`ClaveRegimen`) can
  be indicated (one per `DetalleDesglose` element).
  We currently only allow a single tax type and regimen key for the whole
  document.
- In Veri*Factu it is possible to send a "Subsanación" in case a change is made
  that does not require updating the invoice PDF.
  This is currently not supported.
  - I.e. we do not support sending new submission documents for already registered
    (possibly with errors) records.
  - It is not possible to reset registered (possibly with errors) records back to draft.
- In Veri*Factu it is possible to send a cancellation for records that are otherwise
  known to the AEAT (not Veri*Factu).
  We do not support sending cancellations for records that are not Veri*Factu registered
  within Odoo.
- For simplified invoices there are the special keys / fields `FacturaSimplificadaArt7273`
  and `FacturaSinIdentifDestinatarioArt61d`. Currently we never set them (so they are assumed
  to be `N` by the AEAT).

task-3745982

closes #197635

closes #221431

X-original-commit: ba362e7
Signed-off-by: Sven Führ (svfu) <[email protected]>
fw-bot pushed a commit to odoo-dev/odoo that referenced this pull request Aug 1, 2025
Spain introduces a new EDI called "Veri*Factu" to send invoicing records
to the Spanish tax agency (AEAT).
It is mandatory for most tax payers (that cannot use any of the
other Spanish EDIs like SII or TicketBAI).

This commit adds 2 modules to enable Veri*Factu compliance
- `l10n_es_edi_verifactu` for invoicing / accounting
- `l10n_es_edi_verifactu_pos` for Point of Sale (PoS)

Their setup and usage is briefly described in the documentation
(see the related documentation PR).
The main features of the new modules are as follows.
- `l10n_es_edi_verifactu`
  - The "Send & Print" wizard can be used to generate and send Veri*Factu documents.
  - A QR code is added to the PDF of invoices send with the Veri*Factu option.
    It can be used to check whether the invoice is known to the AEAT.
  - A "Veri*Factu" tab is added to the account move form view.
    It i.e. gives an overview about the send documents and their status.
- `l10n_es_edi_verifactu_pos`
  - A Veri*Factu documents is generated and sent when validating each order.
  - A QR code is added to the PDF of PoS order receipts.
    It can be used to check whether the order is known to the AEAT.
  - A "Veri*Factu" tab is added to the pos order form view.
    It i.e. gives an overview about the send documents and their status.

I.e. note the following about Veri*Factu documents
- Each document has a fingerprint (hash of some important values) called `Huella`.
- All documents belonging to one company are linked together in a single chain in generation order.
  (Each document refers to the previous document including the `Huella` of the previous document)
- There is a waiting time between submissions of documents (usually 60s).
  We sent the document immediately if possible.
  But due to the waiting time this is not always possible.
- We still generate / store the needed values when the invoice is sent
  (mandated by Veri*Factu spec).
- Documents can be sent in batches.
  - Due to the waiting time we sent all "waiting" documents at once.
  - In case of 1000 documents the waiting time can be / is ignored
  - A "Veri*Factu Document" in Odoo only represents a single invoice / PoS order.
- The needed document values mandated by Veri*Factu are stored in JSON format
  on each invoice / order.
- The actual "communication" with AEAT is done via SOAP. (So we sent / receive
  XML files)
- We do not store the actual batch XML we sent to the AEAT or the received responses.
  - For the responses we extract the necessary information and store them
    on each of the document

It can happen that the document reached the AEAT but the response
timed out for some reason (Read-Timeout).
  - The AEAT has (potentially) registered the document but we have
    not received the response they sent.
  - The document will be marked with an error starting with `[Read-Timeout] `.
    and automatically be sent again as soon as possible
  - When the document is resend successfully we receive a response that the document
    was rejected with error `[3000] Registro de facturación duplicado.`
    (Assuming the AEAT registered / not rejected the document when it was sent originally.)
    But the response also contains some information about the state and potential errors
    of the record / duplicate.
  - Since the duplicate is the document we previously sent we just take the state from there.

There are 2 ways to create a correcting Veri*Factu document for invoices
- Correction by difference: Done via "Reverse" in credit note wizard
  We just send a document representing the credit note as "correction by difference".
  The document references the corrected invoice.
- Correction by substitution: Done via "Reverse and Create Invoice" in credit note wizard
  We first send a document representing the reversing credit note (it does not
  reference the original invoice and is send as an "invoice type").
  And then we send the new invoice created by the wizard. It is send as a
  "correction by substitution" and references the original invoice.
  To link the new invoice to the original invoice a new field was added
- We do not support correcting multiple documents with a single new documents
  (neither correction by difference nor correction by substitution)

The "Veri*Factu" tab on the invoice form view also gives information
about which invoice was refunded or substituted.

Limitations
- In Veri*Factu there is some dedicated way to handle the substitution of
  simplified invoices with "real" invoices.
  This is not implemented currently.
- In Veri*Factu multiple tax types (`Impuesto`) and regimen keys (`ClaveRegimen`) can
  be indicated (one per `DetalleDesglose` element).
  We currently only allow a single tax type and regimen key for the whole
  document.
- In Veri*Factu it is possible to send a "Subsanación" in case a change is made
  that does not require updating the invoice PDF.
  This is currently not supported.
  - I.e. we do not support sending new submission documents for already registered
    (possibly with errors) records.
  - It is not possible to reset registered (possibly with errors) records back to draft.
- In Veri*Factu it is possible to send a cancellation for records that are otherwise
  known to the AEAT (not Veri*Factu).
  We do not support sending cancellations for records that are not Veri*Factu registered
  within Odoo.
- For simplified invoices there are the special keys / fields `FacturaSimplificadaArt7273`
  and `FacturaSinIdentifDestinatarioArt61d`. Currently we never set them (so they are assumed
  to be `N` by the AEAT).

task-3745982

closes odoo#197635

Signed-off-by: Sven Führ (svfu) <[email protected]>
X-original-commit: 0834a4e
fw-bot pushed a commit to odoo-dev/odoo that referenced this pull request Aug 1, 2025
Spain introduces a new EDI called "Veri*Factu" to send invoicing records
to the Spanish tax agency (AEAT).
It is mandatory for most tax payers (that cannot use any of the
other Spanish EDIs like SII or TicketBAI).

This commit adds 2 modules to enable Veri*Factu compliance
- `l10n_es_edi_verifactu` for invoicing / accounting
- `l10n_es_edi_verifactu_pos` for Point of Sale (PoS)

Their setup and usage is briefly described in the documentation
(see the related documentation PR).
The main features of the new modules are as follows.
- `l10n_es_edi_verifactu`
  - The "Send & Print" wizard can be used to generate and send Veri*Factu documents.
  - A QR code is added to the PDF of invoices send with the Veri*Factu option.
    It can be used to check whether the invoice is known to the AEAT.
  - A "Veri*Factu" tab is added to the account move form view.
    It i.e. gives an overview about the send documents and their status.
- `l10n_es_edi_verifactu_pos`
  - A Veri*Factu documents is generated and sent when validating each order.
  - A QR code is added to the PDF of PoS order receipts.
    It can be used to check whether the order is known to the AEAT.
  - A "Veri*Factu" tab is added to the pos order form view.
    It i.e. gives an overview about the send documents and their status.

I.e. note the following about Veri*Factu documents
- Each document has a fingerprint (hash of some important values) called `Huella`.
- All documents belonging to one company are linked together in a single chain in generation order.
  (Each document refers to the previous document including the `Huella` of the previous document)
- There is a waiting time between submissions of documents (usually 60s).
  We sent the document immediately if possible.
  But due to the waiting time this is not always possible.
- We still generate / store the needed values when the invoice is sent
  (mandated by Veri*Factu spec).
- Documents can be sent in batches.
  - Due to the waiting time we sent all "waiting" documents at once.
  - In case of 1000 documents the waiting time can be / is ignored
  - A "Veri*Factu Document" in Odoo only represents a single invoice / PoS order.
- The needed document values mandated by Veri*Factu are stored in JSON format
  on each invoice / order.
- The actual "communication" with AEAT is done via SOAP. (So we sent / receive
  XML files)
- We do not store the actual batch XML we sent to the AEAT or the received responses.
  - For the responses we extract the necessary information and store them
    on each of the document

It can happen that the document reached the AEAT but the response
timed out for some reason (Read-Timeout).
  - The AEAT has (potentially) registered the document but we have
    not received the response they sent.
  - The document will be marked with an error starting with `[Read-Timeout] `.
    and automatically be sent again as soon as possible
  - When the document is resend successfully we receive a response that the document
    was rejected with error `[3000] Registro de facturación duplicado.`
    (Assuming the AEAT registered / not rejected the document when it was sent originally.)
    But the response also contains some information about the state and potential errors
    of the record / duplicate.
  - Since the duplicate is the document we previously sent we just take the state from there.

There are 2 ways to create a correcting Veri*Factu document for invoices
- Correction by difference: Done via "Reverse" in credit note wizard
  We just send a document representing the credit note as "correction by difference".
  The document references the corrected invoice.
- Correction by substitution: Done via "Reverse and Create Invoice" in credit note wizard
  We first send a document representing the reversing credit note (it does not
  reference the original invoice and is send as an "invoice type").
  And then we send the new invoice created by the wizard. It is send as a
  "correction by substitution" and references the original invoice.
  To link the new invoice to the original invoice a new field was added
- We do not support correcting multiple documents with a single new documents
  (neither correction by difference nor correction by substitution)

The "Veri*Factu" tab on the invoice form view also gives information
about which invoice was refunded or substituted.

Limitations
- In Veri*Factu there is some dedicated way to handle the substitution of
  simplified invoices with "real" invoices.
  This is not implemented currently.
- In Veri*Factu multiple tax types (`Impuesto`) and regimen keys (`ClaveRegimen`) can
  be indicated (one per `DetalleDesglose` element).
  We currently only allow a single tax type and regimen key for the whole
  document.
- In Veri*Factu it is possible to send a "Subsanación" in case a change is made
  that does not require updating the invoice PDF.
  This is currently not supported.
  - I.e. we do not support sending new submission documents for already registered
    (possibly with errors) records.
  - It is not possible to reset registered (possibly with errors) records back to draft.
- In Veri*Factu it is possible to send a cancellation for records that are otherwise
  known to the AEAT (not Veri*Factu).
  We do not support sending cancellations for records that are not Veri*Factu registered
  within Odoo.
- For simplified invoices there are the special keys / fields `FacturaSimplificadaArt7273`
  and `FacturaSinIdentifDestinatarioArt61d`. Currently we never set them (so they are assumed
  to be `N` by the AEAT).

task-3745982

closes odoo#197635

Signed-off-by: Sven Führ (svfu) <[email protected]>
X-original-commit: 0834a4e
robodoo pushed a commit that referenced this pull request Aug 1, 2025
Spain introduces a new EDI called "Veri*Factu" to send invoicing records
to the Spanish tax agency (AEAT).
It is mandatory for most tax payers (that cannot use any of the
other Spanish EDIs like SII or TicketBAI).

This commit adds 2 modules to enable Veri*Factu compliance
- `l10n_es_edi_verifactu` for invoicing / accounting
- `l10n_es_edi_verifactu_pos` for Point of Sale (PoS)

Their setup and usage is briefly described in the documentation
(see the related documentation PR).
The main features of the new modules are as follows.
- `l10n_es_edi_verifactu`
  - The "Send & Print" wizard can be used to generate and send Veri*Factu documents.
  - A QR code is added to the PDF of invoices send with the Veri*Factu option.
    It can be used to check whether the invoice is known to the AEAT.
  - A "Veri*Factu" tab is added to the account move form view.
    It i.e. gives an overview about the send documents and their status.
- `l10n_es_edi_verifactu_pos`
  - A Veri*Factu documents is generated and sent when validating each order.
  - A QR code is added to the PDF of PoS order receipts.
    It can be used to check whether the order is known to the AEAT.
  - A "Veri*Factu" tab is added to the pos order form view.
    It i.e. gives an overview about the send documents and their status.

I.e. note the following about Veri*Factu documents
- Each document has a fingerprint (hash of some important values) called `Huella`.
- All documents belonging to one company are linked together in a single chain in generation order.
  (Each document refers to the previous document including the `Huella` of the previous document)
- There is a waiting time between submissions of documents (usually 60s).
  We sent the document immediately if possible.
  But due to the waiting time this is not always possible.
- We still generate / store the needed values when the invoice is sent
  (mandated by Veri*Factu spec).
- Documents can be sent in batches.
  - Due to the waiting time we sent all "waiting" documents at once.
  - In case of 1000 documents the waiting time can be / is ignored
  - A "Veri*Factu Document" in Odoo only represents a single invoice / PoS order.
- The needed document values mandated by Veri*Factu are stored in JSON format
  on each invoice / order.
- The actual "communication" with AEAT is done via SOAP. (So we sent / receive
  XML files)
- We do not store the actual batch XML we sent to the AEAT or the received responses.
  - For the responses we extract the necessary information and store them
    on each of the document

It can happen that the document reached the AEAT but the response
timed out for some reason (Read-Timeout).
  - The AEAT has (potentially) registered the document but we have
    not received the response they sent.
  - The document will be marked with an error starting with `[Read-Timeout] `.
    and automatically be sent again as soon as possible
  - When the document is resend successfully we receive a response that the document
    was rejected with error `[3000] Registro de facturación duplicado.`
    (Assuming the AEAT registered / not rejected the document when it was sent originally.)
    But the response also contains some information about the state and potential errors
    of the record / duplicate.
  - Since the duplicate is the document we previously sent we just take the state from there.

There are 2 ways to create a correcting Veri*Factu document for invoices
- Correction by difference: Done via "Reverse" in credit note wizard
  We just send a document representing the credit note as "correction by difference".
  The document references the corrected invoice.
- Correction by substitution: Done via "Reverse and Create Invoice" in credit note wizard
  We first send a document representing the reversing credit note (it does not
  reference the original invoice and is send as an "invoice type").
  And then we send the new invoice created by the wizard. It is send as a
  "correction by substitution" and references the original invoice.
  To link the new invoice to the original invoice a new field was added
- We do not support correcting multiple documents with a single new documents
  (neither correction by difference nor correction by substitution)

The "Veri*Factu" tab on the invoice form view also gives information
about which invoice was refunded or substituted.

Limitations
- In Veri*Factu there is some dedicated way to handle the substitution of
  simplified invoices with "real" invoices.
  This is not implemented currently.
- In Veri*Factu multiple tax types (`Impuesto`) and regimen keys (`ClaveRegimen`) can
  be indicated (one per `DetalleDesglose` element).
  We currently only allow a single tax type and regimen key for the whole
  document.
- In Veri*Factu it is possible to send a "Subsanación" in case a change is made
  that does not require updating the invoice PDF.
  This is currently not supported.
  - I.e. we do not support sending new submission documents for already registered
    (possibly with errors) records.
  - It is not possible to reset registered (possibly with errors) records back to draft.
- In Veri*Factu it is possible to send a cancellation for records that are otherwise
  known to the AEAT (not Veri*Factu).
  We do not support sending cancellations for records that are not Veri*Factu registered
  within Odoo.
- For simplified invoices there are the special keys / fields `FacturaSimplificadaArt7273`
  and `FacturaSinIdentifDestinatarioArt61d`. Currently we never set them (so they are assumed
  to be `N` by the AEAT).

task-3745982

closes #197635

closes #221556

X-original-commit: 0834a4e
Signed-off-by: Sven Führ (svfu) <[email protected]>
robodoo pushed a commit that referenced this pull request Aug 1, 2025
Spain introduces a new EDI called "Veri*Factu" to send invoicing records
to the Spanish tax agency (AEAT).
It is mandatory for most tax payers (that cannot use any of the
other Spanish EDIs like SII or TicketBAI).

This commit adds 2 modules to enable Veri*Factu compliance
- `l10n_es_edi_verifactu` for invoicing / accounting
- `l10n_es_edi_verifactu_pos` for Point of Sale (PoS)

Their setup and usage is briefly described in the documentation
(see the related documentation PR).
The main features of the new modules are as follows.
- `l10n_es_edi_verifactu`
  - The "Send & Print" wizard can be used to generate and send Veri*Factu documents.
  - A QR code is added to the PDF of invoices send with the Veri*Factu option.
    It can be used to check whether the invoice is known to the AEAT.
  - A "Veri*Factu" tab is added to the account move form view.
    It i.e. gives an overview about the send documents and their status.
- `l10n_es_edi_verifactu_pos`
  - A Veri*Factu documents is generated and sent when validating each order.
  - A QR code is added to the PDF of PoS order receipts.
    It can be used to check whether the order is known to the AEAT.
  - A "Veri*Factu" tab is added to the pos order form view.
    It i.e. gives an overview about the send documents and their status.

I.e. note the following about Veri*Factu documents
- Each document has a fingerprint (hash of some important values) called `Huella`.
- All documents belonging to one company are linked together in a single chain in generation order.
  (Each document refers to the previous document including the `Huella` of the previous document)
- There is a waiting time between submissions of documents (usually 60s).
  We sent the document immediately if possible.
  But due to the waiting time this is not always possible.
- We still generate / store the needed values when the invoice is sent
  (mandated by Veri*Factu spec).
- Documents can be sent in batches.
  - Due to the waiting time we sent all "waiting" documents at once.
  - In case of 1000 documents the waiting time can be / is ignored
  - A "Veri*Factu Document" in Odoo only represents a single invoice / PoS order.
- The needed document values mandated by Veri*Factu are stored in JSON format
  on each invoice / order.
- The actual "communication" with AEAT is done via SOAP. (So we sent / receive
  XML files)
- We do not store the actual batch XML we sent to the AEAT or the received responses.
  - For the responses we extract the necessary information and store them
    on each of the document

It can happen that the document reached the AEAT but the response
timed out for some reason (Read-Timeout).
  - The AEAT has (potentially) registered the document but we have
    not received the response they sent.
  - The document will be marked with an error starting with `[Read-Timeout] `.
    and automatically be sent again as soon as possible
  - When the document is resend successfully we receive a response that the document
    was rejected with error `[3000] Registro de facturación duplicado.`
    (Assuming the AEAT registered / not rejected the document when it was sent originally.)
    But the response also contains some information about the state and potential errors
    of the record / duplicate.
  - Since the duplicate is the document we previously sent we just take the state from there.

There are 2 ways to create a correcting Veri*Factu document for invoices
- Correction by difference: Done via "Reverse" in credit note wizard
  We just send a document representing the credit note as "correction by difference".
  The document references the corrected invoice.
- Correction by substitution: Done via "Reverse and Create Invoice" in credit note wizard
  We first send a document representing the reversing credit note (it does not
  reference the original invoice and is send as an "invoice type").
  And then we send the new invoice created by the wizard. It is send as a
  "correction by substitution" and references the original invoice.
  To link the new invoice to the original invoice a new field was added
- We do not support correcting multiple documents with a single new documents
  (neither correction by difference nor correction by substitution)

The "Veri*Factu" tab on the invoice form view also gives information
about which invoice was refunded or substituted.

Limitations
- In Veri*Factu there is some dedicated way to handle the substitution of
  simplified invoices with "real" invoices.
  This is not implemented currently.
- In Veri*Factu multiple tax types (`Impuesto`) and regimen keys (`ClaveRegimen`) can
  be indicated (one per `DetalleDesglose` element).
  We currently only allow a single tax type and regimen key for the whole
  document.
- In Veri*Factu it is possible to send a "Subsanación" in case a change is made
  that does not require updating the invoice PDF.
  This is currently not supported.
  - I.e. we do not support sending new submission documents for already registered
    (possibly with errors) records.
  - It is not possible to reset registered (possibly with errors) records back to draft.
- In Veri*Factu it is possible to send a cancellation for records that are otherwise
  known to the AEAT (not Veri*Factu).
  We do not support sending cancellations for records that are not Veri*Factu registered
  within Odoo.
- For simplified invoices there are the special keys / fields `FacturaSimplificadaArt7273`
  and `FacturaSinIdentifDestinatarioArt61d`. Currently we never set them (so they are assumed
  to be `N` by the AEAT).

task-3745982

closes #197635

closes #221588

X-original-commit: 0834a4e
Signed-off-by: Sven Führ (svfu) <[email protected]>
robodoo pushed a commit that referenced this pull request Aug 1, 2025
Spain introduces a new EDI called "Veri*Factu" to send invoicing records
to the Spanish tax agency (AEAT).
It is mandatory for most tax payers (that cannot use any of the
other Spanish EDIs like SII or TicketBAI).

This commit adds 2 modules to enable Veri*Factu compliance
- `l10n_es_edi_verifactu` for invoicing / accounting
- `l10n_es_edi_verifactu_pos` for Point of Sale (PoS)

Their setup and usage is briefly described in the documentation
(see the related documentation PR).
The main features of the new modules are as follows.
- `l10n_es_edi_verifactu`
  - The "Send & Print" wizard can be used to generate and send Veri*Factu documents.
  - A QR code is added to the PDF of invoices send with the Veri*Factu option.
    It can be used to check whether the invoice is known to the AEAT.
  - A "Veri*Factu" tab is added to the account move form view.
    It i.e. gives an overview about the send documents and their status.
- `l10n_es_edi_verifactu_pos`
  - A Veri*Factu documents is generated and sent when validating each order.
  - A QR code is added to the PDF of PoS order receipts.
    It can be used to check whether the order is known to the AEAT.
  - A "Veri*Factu" tab is added to the pos order form view.
    It i.e. gives an overview about the send documents and their status.

I.e. note the following about Veri*Factu documents
- Each document has a fingerprint (hash of some important values) called `Huella`.
- All documents belonging to one company are linked together in a single chain in generation order.
  (Each document refers to the previous document including the `Huella` of the previous document)
- There is a waiting time between submissions of documents (usually 60s).
  We sent the document immediately if possible.
  But due to the waiting time this is not always possible.
- We still generate / store the needed values when the invoice is sent
  (mandated by Veri*Factu spec).
- Documents can be sent in batches.
  - Due to the waiting time we sent all "waiting" documents at once.
  - In case of 1000 documents the waiting time can be / is ignored
  - A "Veri*Factu Document" in Odoo only represents a single invoice / PoS order.
- The needed document values mandated by Veri*Factu are stored in JSON format
  on each invoice / order.
- The actual "communication" with AEAT is done via SOAP. (So we sent / receive
  XML files)
- We do not store the actual batch XML we sent to the AEAT or the received responses.
  - For the responses we extract the necessary information and store them
    on each of the document

It can happen that the document reached the AEAT but the response
timed out for some reason (Read-Timeout).
  - The AEAT has (potentially) registered the document but we have
    not received the response they sent.
  - The document will be marked with an error starting with `[Read-Timeout] `.
    and automatically be sent again as soon as possible
  - When the document is resend successfully we receive a response that the document
    was rejected with error `[3000] Registro de facturación duplicado.`
    (Assuming the AEAT registered / not rejected the document when it was sent originally.)
    But the response also contains some information about the state and potential errors
    of the record / duplicate.
  - Since the duplicate is the document we previously sent we just take the state from there.

There are 2 ways to create a correcting Veri*Factu document for invoices
- Correction by difference: Done via "Reverse" in credit note wizard
  We just send a document representing the credit note as "correction by difference".
  The document references the corrected invoice.
- Correction by substitution: Done via "Reverse and Create Invoice" in credit note wizard
  We first send a document representing the reversing credit note (it does not
  reference the original invoice and is send as an "invoice type").
  And then we send the new invoice created by the wizard. It is send as a
  "correction by substitution" and references the original invoice.
  To link the new invoice to the original invoice a new field was added
- We do not support correcting multiple documents with a single new documents
  (neither correction by difference nor correction by substitution)

The "Veri*Factu" tab on the invoice form view also gives information
about which invoice was refunded or substituted.

Limitations
- In Veri*Factu there is some dedicated way to handle the substitution of
  simplified invoices with "real" invoices.
  This is not implemented currently.
- In Veri*Factu multiple tax types (`Impuesto`) and regimen keys (`ClaveRegimen`) can
  be indicated (one per `DetalleDesglose` element).
  We currently only allow a single tax type and regimen key for the whole
  document.
- In Veri*Factu it is possible to send a "Subsanación" in case a change is made
  that does not require updating the invoice PDF.
  This is currently not supported.
  - I.e. we do not support sending new submission documents for already registered
    (possibly with errors) records.
  - It is not possible to reset registered (possibly with errors) records back to draft.
- In Veri*Factu it is possible to send a cancellation for records that are otherwise
  known to the AEAT (not Veri*Factu).
  We do not support sending cancellations for records that are not Veri*Factu registered
  within Odoo.
- For simplified invoices there are the special keys / fields `FacturaSimplificadaArt7273`
  and `FacturaSinIdentifDestinatarioArt61d`. Currently we never set them (so they are assumed
  to be `N` by the AEAT).

task-3745982

closes #197635

closes #221588

X-original-commit: 0834a4e
Signed-off-by: Sven Führ (svfu) <[email protected]>
robodoo pushed a commit that referenced this pull request Aug 1, 2025
Spain introduces a new EDI called "Veri*Factu" to send invoicing records
to the Spanish tax agency (AEAT).
It is mandatory for most tax payers (that cannot use any of the
other Spanish EDIs like SII or TicketBAI).

This commit adds 2 modules to enable Veri*Factu compliance
- `l10n_es_edi_verifactu` for invoicing / accounting
- `l10n_es_edi_verifactu_pos` for Point of Sale (PoS)

Their setup and usage is briefly described in the documentation
(see the related documentation PR).
The main features of the new modules are as follows.
- `l10n_es_edi_verifactu`
  - The "Send & Print" wizard can be used to generate and send Veri*Factu documents.
  - A QR code is added to the PDF of invoices send with the Veri*Factu option.
    It can be used to check whether the invoice is known to the AEAT.
  - A "Veri*Factu" tab is added to the account move form view.
    It i.e. gives an overview about the send documents and their status.
- `l10n_es_edi_verifactu_pos`
  - A Veri*Factu documents is generated and sent when validating each order.
  - A QR code is added to the PDF of PoS order receipts.
    It can be used to check whether the order is known to the AEAT.
  - A "Veri*Factu" tab is added to the pos order form view.
    It i.e. gives an overview about the send documents and their status.

I.e. note the following about Veri*Factu documents
- Each document has a fingerprint (hash of some important values) called `Huella`.
- All documents belonging to one company are linked together in a single chain in generation order.
  (Each document refers to the previous document including the `Huella` of the previous document)
- There is a waiting time between submissions of documents (usually 60s).
  We sent the document immediately if possible.
  But due to the waiting time this is not always possible.
- We still generate / store the needed values when the invoice is sent
  (mandated by Veri*Factu spec).
- Documents can be sent in batches.
  - Due to the waiting time we sent all "waiting" documents at once.
  - In case of 1000 documents the waiting time can be / is ignored
  - A "Veri*Factu Document" in Odoo only represents a single invoice / PoS order.
- The needed document values mandated by Veri*Factu are stored in JSON format
  on each invoice / order.
- The actual "communication" with AEAT is done via SOAP. (So we sent / receive
  XML files)
- We do not store the actual batch XML we sent to the AEAT or the received responses.
  - For the responses we extract the necessary information and store them
    on each of the document

It can happen that the document reached the AEAT but the response
timed out for some reason (Read-Timeout).
  - The AEAT has (potentially) registered the document but we have
    not received the response they sent.
  - The document will be marked with an error starting with `[Read-Timeout] `.
    and automatically be sent again as soon as possible
  - When the document is resend successfully we receive a response that the document
    was rejected with error `[3000] Registro de facturación duplicado.`
    (Assuming the AEAT registered / not rejected the document when it was sent originally.)
    But the response also contains some information about the state and potential errors
    of the record / duplicate.
  - Since the duplicate is the document we previously sent we just take the state from there.

There are 2 ways to create a correcting Veri*Factu document for invoices
- Correction by difference: Done via "Reverse" in credit note wizard
  We just send a document representing the credit note as "correction by difference".
  The document references the corrected invoice.
- Correction by substitution: Done via "Reverse and Create Invoice" in credit note wizard
  We first send a document representing the reversing credit note (it does not
  reference the original invoice and is send as an "invoice type").
  And then we send the new invoice created by the wizard. It is send as a
  "correction by substitution" and references the original invoice.
  To link the new invoice to the original invoice a new field was added
- We do not support correcting multiple documents with a single new documents
  (neither correction by difference nor correction by substitution)

The "Veri*Factu" tab on the invoice form view also gives information
about which invoice was refunded or substituted.

Limitations
- In Veri*Factu there is some dedicated way to handle the substitution of
  simplified invoices with "real" invoices.
  This is not implemented currently.
- In Veri*Factu multiple tax types (`Impuesto`) and regimen keys (`ClaveRegimen`) can
  be indicated (one per `DetalleDesglose` element).
  We currently only allow a single tax type and regimen key for the whole
  document.
- In Veri*Factu it is possible to send a "Subsanación" in case a change is made
  that does not require updating the invoice PDF.
  This is currently not supported.
  - I.e. we do not support sending new submission documents for already registered
    (possibly with errors) records.
  - It is not possible to reset registered (possibly with errors) records back to draft.
- In Veri*Factu it is possible to send a cancellation for records that are otherwise
  known to the AEAT (not Veri*Factu).
  We do not support sending cancellations for records that are not Veri*Factu registered
  within Odoo.
- For simplified invoices there are the special keys / fields `FacturaSimplificadaArt7273`
  and `FacturaSinIdentifDestinatarioArt61d`. Currently we never set them (so they are assumed
  to be `N` by the AEAT).

task-3745982

closes #197635

closes #221588

X-original-commit: 0834a4e
Signed-off-by: Sven Führ (svfu) <[email protected]>
robodoo pushed a commit that referenced this pull request Aug 2, 2025
Spain introduces a new EDI called "Veri*Factu" to send invoicing records
to the Spanish tax agency (AEAT).
It is mandatory for most tax payers (that cannot use any of the
other Spanish EDIs like SII or TicketBAI).

This commit adds 2 modules to enable Veri*Factu compliance
- `l10n_es_edi_verifactu` for invoicing / accounting
- `l10n_es_edi_verifactu_pos` for Point of Sale (PoS)

Their setup and usage is briefly described in the documentation
(see the related documentation PR).
The main features of the new modules are as follows.
- `l10n_es_edi_verifactu`
  - The "Send & Print" wizard can be used to generate and send Veri*Factu documents.
  - A QR code is added to the PDF of invoices send with the Veri*Factu option.
    It can be used to check whether the invoice is known to the AEAT.
  - A "Veri*Factu" tab is added to the account move form view.
    It i.e. gives an overview about the send documents and their status.
- `l10n_es_edi_verifactu_pos`
  - A Veri*Factu documents is generated and sent when validating each order.
  - A QR code is added to the PDF of PoS order receipts.
    It can be used to check whether the order is known to the AEAT.
  - A "Veri*Factu" tab is added to the pos order form view.
    It i.e. gives an overview about the send documents and their status.

I.e. note the following about Veri*Factu documents
- Each document has a fingerprint (hash of some important values) called `Huella`.
- All documents belonging to one company are linked together in a single chain in generation order.
  (Each document refers to the previous document including the `Huella` of the previous document)
- There is a waiting time between submissions of documents (usually 60s).
  We sent the document immediately if possible.
  But due to the waiting time this is not always possible.
- We still generate / store the needed values when the invoice is sent
  (mandated by Veri*Factu spec).
- Documents can be sent in batches.
  - Due to the waiting time we sent all "waiting" documents at once.
  - In case of 1000 documents the waiting time can be / is ignored
  - A "Veri*Factu Document" in Odoo only represents a single invoice / PoS order.
- The needed document values mandated by Veri*Factu are stored in JSON format
  on each invoice / order.
- The actual "communication" with AEAT is done via SOAP. (So we sent / receive
  XML files)
- We do not store the actual batch XML we sent to the AEAT or the received responses.
  - For the responses we extract the necessary information and store them
    on each of the document

It can happen that the document reached the AEAT but the response
timed out for some reason (Read-Timeout).
  - The AEAT has (potentially) registered the document but we have
    not received the response they sent.
  - The document will be marked with an error starting with `[Read-Timeout] `.
    and automatically be sent again as soon as possible
  - When the document is resend successfully we receive a response that the document
    was rejected with error `[3000] Registro de facturación duplicado.`
    (Assuming the AEAT registered / not rejected the document when it was sent originally.)
    But the response also contains some information about the state and potential errors
    of the record / duplicate.
  - Since the duplicate is the document we previously sent we just take the state from there.

There are 2 ways to create a correcting Veri*Factu document for invoices
- Correction by difference: Done via "Reverse" in credit note wizard
  We just send a document representing the credit note as "correction by difference".
  The document references the corrected invoice.
- Correction by substitution: Done via "Reverse and Create Invoice" in credit note wizard
  We first send a document representing the reversing credit note (it does not
  reference the original invoice and is send as an "invoice type").
  And then we send the new invoice created by the wizard. It is send as a
  "correction by substitution" and references the original invoice.
  To link the new invoice to the original invoice a new field was added
- We do not support correcting multiple documents with a single new documents
  (neither correction by difference nor correction by substitution)

The "Veri*Factu" tab on the invoice form view also gives information
about which invoice was refunded or substituted.

Limitations
- In Veri*Factu there is some dedicated way to handle the substitution of
  simplified invoices with "real" invoices.
  This is not implemented currently.
- In Veri*Factu multiple tax types (`Impuesto`) and regimen keys (`ClaveRegimen`) can
  be indicated (one per `DetalleDesglose` element).
  We currently only allow a single tax type and regimen key for the whole
  document.
- In Veri*Factu it is possible to send a "Subsanación" in case a change is made
  that does not require updating the invoice PDF.
  This is currently not supported.
  - I.e. we do not support sending new submission documents for already registered
    (possibly with errors) records.
  - It is not possible to reset registered (possibly with errors) records back to draft.
- In Veri*Factu it is possible to send a cancellation for records that are otherwise
  known to the AEAT (not Veri*Factu).
  We do not support sending cancellations for records that are not Veri*Factu registered
  within Odoo.
- For simplified invoices there are the special keys / fields `FacturaSimplificadaArt7273`
  and `FacturaSinIdentifDestinatarioArt61d`. Currently we never set them (so they are assumed
  to be `N` by the AEAT).

task-3745982

closes #197635

closes #221588

X-original-commit: 0834a4e
Signed-off-by: Sven Führ (svfu) <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
RD research & development, internal work
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants