-
-
Notifications
You must be signed in to change notification settings - Fork 295
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ADD backport from 10.0 of l10n_it_sdi_channel
ADD backport from 10.0 of l10n_it_fatturapa_pec
- Loading branch information
Showing
35 changed files
with
1,994 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
========================================================= | ||
Italian Localization - FatturaPA - Emission - PEC Support | ||
========================================================= | ||
|
||
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
!! This file is generated by oca-gen-addon-readme !! | ||
!! changes will be overwritten. !! | ||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png | ||
:target: https://odoo-community.org/page/development-status | ||
:alt: Beta | ||
.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png | ||
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html | ||
:alt: License: LGPL-3 | ||
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fl10n--italy-lightgray.png?logo=github | ||
:target: https://github.com/OCA/l10n-italy/tree/10.0/l10n_it_fatturapa_pec | ||
:alt: OCA/l10n-italy | ||
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png | ||
:target: https://translation.odoo-community.org/projects/l10n-italy-10-0/l10n-italy-10-0-l10n_it_fatturapa_pec | ||
:alt: Translate me on Weblate | ||
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png | ||
:target: https://runbot.odoo-community.org/runbot/122/10.0 | ||
:alt: Try me on Runbot | ||
|
||
|badge1| |badge2| |badge3| |badge4| |badge5| | ||
|
||
This module allows you to send and receive electronic invoice XML file version 1.2 | ||
http://www.fatturapa.gov.it/export/fatturazione/en/sdi.htm | ||
via PEC | ||
|
||
Notifications from SDI are parsed and transmission state is tracked. | ||
|
||
**Table of contents** | ||
|
||
.. contents:: | ||
:local: | ||
|
||
Configuration | ||
============= | ||
|
||
See `l10n_it_sdi_channel` module | ||
|
||
Usage | ||
===== | ||
|
||
In electronic invoice out attachment you can click "Send Via PEC" button. | ||
|
||
Supplier electronic invoices are automatically created, fetched from PEC mailbox. | ||
|
||
Bug Tracker | ||
=========== | ||
|
||
Bugs are tracked on `GitHub Issues <https://github.com/OCA/l10n-italy/issues>`_. | ||
In case of trouble, please check there if your issue has already been reported. | ||
If you spotted it first, help us smashing it by providing a detailed and welcomed | ||
`feedback <https://github.com/OCA/l10n-italy/issues/new?body=module:%20l10n_it_fatturapa_pec%0Aversion:%2010.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_. | ||
|
||
Do not contact contributors directly about support or help with technical issues. | ||
|
||
Credits | ||
======= | ||
|
||
Authors | ||
~~~~~~~ | ||
|
||
* Openforce Srls Unipersonale | ||
|
||
Contributors | ||
~~~~~~~~~~~~ | ||
|
||
* Andrea Colangelo <andreacolangelo@openforce.it> | ||
* Sergio Corato <info@efatto.it> | ||
* Lorenzo Battistini <https://github.com/eLBati> | ||
|
||
Maintainers | ||
~~~~~~~~~~~ | ||
|
||
This module is maintained by the OCA. | ||
|
||
.. image:: https://odoo-community.org/logo.png | ||
:alt: Odoo Community Association | ||
:target: https://odoo-community.org | ||
|
||
OCA, or the Odoo Community Association, is a nonprofit organization whose | ||
mission is to support the collaborative development of Odoo features and | ||
promote its widespread use. | ||
|
||
This module is part of the `OCA/l10n-italy <https://github.com/OCA/l10n-italy/tree/10.0/l10n_it_fatturapa_pec>`_ project on GitHub. | ||
|
||
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# -*- coding: utf-8 -*- | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). | ||
|
||
from . import models |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
# -*- coding: utf-8 -*- | ||
# Author(s): Andrea Colangelo (andreacolangelo@openforce.it) | ||
# Copyright 2018 Openforce Srls Unipersonale (www.openforce.it) | ||
# Copyright 2018 Sergio Corato (https://efatto.it) | ||
# Copyright 2018 Lorenzo Battistini <https://github.com/eLBati> | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). | ||
{ | ||
'name': 'Italian Localization - FatturaPA - Emission - PEC Support', | ||
'version': '10.0.1.0.0', | ||
'category': 'Localization/Italy', | ||
'summary': 'Send electronic invoices via PEC', | ||
'author': 'Openforce Srls Unipersonale, Odoo Community Association (OCA)', | ||
'website': 'https://github.com/OCA/l10n-italy', | ||
'license': 'LGPL-3', | ||
'depends': [ | ||
'fetchmail', | ||
'l10n_it_fatturapa_out', | ||
# 'l10n_it_fatturapa_in', Enable this dep as soon as the module is ready | ||
'l10n_it_sdi_channel', | ||
], | ||
'data': [ | ||
'views/account.xml', | ||
'views/fatturapa_attachment_out.xml', | ||
], | ||
'installable': True | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# -*- coding: utf-8 -*- | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). | ||
|
||
from . import account | ||
from . import fatturapa_attachment_out | ||
from . import mail_thread |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# -*- coding: utf-8 -*- | ||
# Author(s): Andrea Colangelo (andreacolangelo@openforce.it) | ||
# Copyright © 2018 Openforce Srls Unipersonale (www.openforce.it) | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). | ||
|
||
|
||
from openerp import api, fields, models | ||
|
||
|
||
class AccountInvoice(models.Model): | ||
_inherit = 'account.invoice' | ||
|
||
fatturapa_state = fields.Selection( | ||
[('ready', 'Ready to Send'), | ||
('sent', 'Sent'), | ||
('delivered', 'Delivered'), | ||
('error', 'Error')], | ||
string='E-invoice State', | ||
compute='compute_fatturapa_state', | ||
store='true', | ||
) | ||
|
||
@api.multi | ||
@api.depends('fatturapa_attachment_out_id.state') | ||
def compute_fatturapa_state(self): | ||
mapping = { | ||
'ready': 'ready', | ||
'sent': 'sent', | ||
'validated': 'delivered', | ||
'sender_error': 'error', | ||
'recipient_error': 'error', | ||
'rejected': 'error' | ||
} | ||
for record in self: | ||
record.fatturapa_state = \ | ||
mapping.get(record.fatturapa_attachment_out_id.state) |
183 changes: 183 additions & 0 deletions
183
l10n_it_fatturapa_pec/models/fatturapa_attachment_out.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
# -*- coding: utf-8 -*- | ||
# Author(s): Andrea Colangelo (andreacolangelo@openforce.it) | ||
# Copyright © 2018 Openforce Srls Unipersonale (www.openforce.it) | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). | ||
|
||
import logging | ||
import re | ||
|
||
from lxml import etree | ||
|
||
from openerp import api, fields, models | ||
|
||
_logger = logging.getLogger(__name__) | ||
|
||
RESPONSE_MAIL_REGEX = '[A-Z]{2}[a-zA-Z0-9]{11,16}_[a-zA-Z0-9]{,5}_[A-Z]{2}_' \ | ||
'[a-zA-Z0-9]{,3}' | ||
|
||
|
||
class FatturaPAAttachmentOut(models.Model): | ||
_inherit = 'fatturapa.attachment.out' | ||
|
||
state = fields.Selection([('ready', 'Ready to Send'), | ||
('sent', 'Sent'), | ||
('validated', 'Delivered'), | ||
('sender_error', 'Sender Error'), | ||
('recipient_error', 'Recipient Error'), | ||
('rejected', 'Rejected (PA)')], | ||
string='State', | ||
default='ready',) | ||
|
||
last_sdi_response = fields.Text( | ||
string='Last Response from Exchange System', default='No response yet') | ||
|
||
@api.multi | ||
def send_via_pec(self): | ||
self.ensure_one() | ||
mail_message = self.env['mail.message'].create({ | ||
'model': self._name, | ||
'res_id': self.id, | ||
'subject': self.name, | ||
'body': 'XML file for FatturaPA {} sent to Exchange System to the' | ||
' email address {}.' | ||
.format( | ||
self.name, | ||
self.env.user.company_id.email_exchange_system), | ||
'attachment_ids': [(6, 0, self.ir_attachment_id.ids)], | ||
'email_from': self.env.user.company_id.email_from_for_fatturaPA, | ||
'mail_server_id': self.env.user.company_id.sdi_channel_id. | ||
pec_server_id.id, | ||
}) | ||
mail = self.env['mail.mail'].create({ | ||
'mail_message_id': mail_message.id, | ||
'body_html': mail_message.body, | ||
'email_to': self.env.user.company_id.email_exchange_system, | ||
}) | ||
|
||
if mail: | ||
res = mail.send(raise_exception=True) | ||
|
||
if res: | ||
self.state = 'sent' | ||
|
||
@api.multi | ||
def parse_pec_response(self, message_dict): | ||
message_dict['model'] = self._name | ||
message_dict['res_id'] = 0 | ||
|
||
regex = re.compile(RESPONSE_MAIL_REGEX) | ||
attachments = [x for x in message_dict['attachments'] | ||
if regex.match(x.fname)] | ||
|
||
for attachment in attachments: | ||
response_name = attachment.fname | ||
message_type = response_name.split('_')[2] | ||
if attachment.fname.lower().endswith('.zip'): | ||
# not implemented, case of AT, todo | ||
continue | ||
root = etree.fromstring(attachment.content) | ||
file_name = root.find('NomeFile') | ||
fatturapa_attachment_out = False | ||
|
||
if file_name is not None: | ||
file_name = file_name.text | ||
fatturapa_attachment_out = self.search( | ||
['|', | ||
('datas_fname', '=', file_name), | ||
('datas_fname', '=', file_name.replace('.p7m', ''))]) | ||
if len(fatturapa_attachment_out) > 1: | ||
_logger.info('More than 1 out invoice found for incoming' | ||
'message') | ||
fatturapa_attachment_out = fatturapa_attachment_out[0] | ||
if not fatturapa_attachment_out: | ||
if message_type == 'MT': # Metadati | ||
# out invoice not found, so it is an incoming invoice | ||
return message_dict | ||
else: | ||
_logger.info('Error: FatturaPA {} not found.'.format( | ||
file_name)) | ||
# TODO Send a mail warning | ||
return message_dict | ||
|
||
if fatturapa_attachment_out: | ||
id_sdi = root.find('IdentificativoSdI') | ||
receipt_dt = root.find('DataOraRicezione') | ||
message_id = root.find('MessageId') | ||
id_sdi = id_sdi.text if id_sdi is not None else False | ||
receipt_dt = receipt_dt.text if receipt_dt is not None \ | ||
else False | ||
message_id = message_id.text if message_id is not None \ | ||
else False | ||
if message_type == 'NS': # 2A. Notifica di Scarto | ||
error_list = root.find('ListaErrori').text | ||
fatturapa_attachment_out.write({ | ||
'state': 'sender_error', | ||
'last_sdi_response': 'SdI ID: {}; ' | ||
'Message ID: {}; Receipt date: {}; ' | ||
'Error: {}'.format( | ||
id_sdi, message_id, receipt_dt, error_list) | ||
}) | ||
elif message_type == 'MC': # 3A. Mancata consegna | ||
missed_delivery_note = root.find('Descrizione').text | ||
fatturapa_attachment_out.write({ | ||
'state': 'recipient_error', | ||
'last_sdi_response': 'SdI ID: {}; ' | ||
'Message ID: {}; Receipt date: {}; ' | ||
'Missed delivery note: {}'.format( | ||
id_sdi, message_id, receipt_dt, | ||
missed_delivery_note) | ||
}) | ||
elif message_type == 'RC': # 3B. Ricevuta di Consegna | ||
delivery_dt = root.find('DataOraConsegna').text | ||
fatturapa_attachment_out.write({ | ||
'state': 'validated', | ||
'last_sdi_response': 'SdI ID: {}; ' | ||
'Message ID: {}; Receipt date: {}; ' | ||
'Delivery date: {}'.format( | ||
id_sdi, message_id, receipt_dt, delivery_dt) | ||
}) | ||
elif message_type == 'NE': # 4A. Notifica Esito per PA | ||
esito_committente = root.find('EsitoCommittente') | ||
if esito_committente is not None: | ||
# more than one esito? | ||
id_sdi_esito = esito_committente.find( | ||
'IdentificativoSdI') | ||
esito = esito_committente.find( | ||
'Esito') | ||
if esito is not None: | ||
if esito.text == 'EC01': | ||
state = 'validated' | ||
elif esito.text == 'EC02': | ||
state = 'rejected' | ||
fatturapa_attachment_out.write({ | ||
'state': state, | ||
'last_sdi_response': 'SdI ID: {}; ' | ||
'Message ID: {}; Response: {}; '.format( | ||
id_sdi, message_id, esito.text) | ||
}) | ||
elif message_type == 'DT': # 5. Decorrenza Termini per PA | ||
description = root.find('Descrizione') | ||
if description is not None: | ||
fatturapa_attachment_out.write({ | ||
'state': 'validated', | ||
'last_sdi_response': 'SdI ID: {}; ' | ||
'Message ID: {}; Receipt date: {}; ' | ||
'Description: {}'.format( | ||
id_sdi, message_id, receipt_dt, | ||
description.text) | ||
}) | ||
# not implemented - todo | ||
elif message_type == 'AT': # 6. Avvenuta Trasmissione per PA | ||
description = root.find('Descrizione') | ||
if description is not None: | ||
fatturapa_attachment_out.write({ | ||
'state': 'validated', | ||
'last_sdi_response': 'SdI ID: {}; ' | ||
'Message ID: {}; Receipt date: {}; ' | ||
'Description: {}'.format( | ||
id_sdi, message_id, receipt_dt, | ||
description.text) | ||
}) | ||
|
||
message_dict['res_id'] = fatturapa_attachment_out.id | ||
return message_dict |
Oops, something went wrong.