From 8b77fee4515f92a38b2a74989ea704d0ecf91a46 Mon Sep 17 00:00:00 2001 From: Lorenzo Battistini Date: Thu, 29 Nov 2018 13:57:42 +0100 Subject: [PATCH] l10n_it_fatturapa_pec: check possible fetch errors and track them (#682) While sending, check for valid fetchmail server FIX typo 'yo' --- l10n_it_fatturapa_pec/__manifest__.py | 3 +- .../i18n/l10n_it_fatturapa_pec.pot | 31 +++- l10n_it_fatturapa_pec/models/__init__.py | 1 + .../models/fatturapa_attachment_out.py | 13 +- l10n_it_fatturapa_pec/models/fetchmail.py | 134 ++++++++++++++++++ .../views/fetchmail_view.xml | 20 +++ 6 files changed, 195 insertions(+), 7 deletions(-) create mode 100644 l10n_it_fatturapa_pec/models/fetchmail.py create mode 100644 l10n_it_fatturapa_pec/views/fetchmail_view.xml diff --git a/l10n_it_fatturapa_pec/__manifest__.py b/l10n_it_fatturapa_pec/__manifest__.py index b8c56b377c8a..b39aec2598cc 100644 --- a/l10n_it_fatturapa_pec/__manifest__.py +++ b/l10n_it_fatturapa_pec/__manifest__.py @@ -6,7 +6,7 @@ # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl). { 'name': 'Italian Localization - FatturaPA - Emission - PEC Support', - 'version': '10.0.1.1.0', + 'version': '10.0.1.2.0', 'category': 'Localization/Italy', 'summary': 'Send electronic invoices via PEC', 'author': 'Openforce Srls Unipersonale, Odoo Community Association (OCA)', @@ -22,6 +22,7 @@ 'views/account.xml', 'views/fatturapa_attachment_out.xml', 'wizard/send_pec_view.xml', + 'views/fetchmail_view.xml', ], 'installable': True } diff --git a/l10n_it_fatturapa_pec/i18n/l10n_it_fatturapa_pec.pot b/l10n_it_fatturapa_pec/i18n/l10n_it_fatturapa_pec.pot index be20987e9562..2f6589fbd64e 100644 --- a/l10n_it_fatturapa_pec/i18n/l10n_it_fatturapa_pec.pot +++ b/l10n_it_fatturapa_pec/i18n/l10n_it_fatturapa_pec.pot @@ -95,6 +95,11 @@ msgstr "" msgid "Last Modified on" msgstr "" +#. module: l10n_it_fatturapa_pec +#: model:ir.model.fields,field_description:l10n_it_fatturapa_pec.field_fetchmail_server_last_pec_error_message +msgid "Last PEC error message" +msgstr "" + #. module: l10n_it_fatturapa_pec #: model:ir.model.fields,field_description:l10n_it_fatturapa_pec.field_fatturapa_attachment_out_last_sdi_response #: model:ir.ui.view,arch_db:l10n_it_fatturapa_pec.view_fatturapa_out_pec_attachment_form @@ -111,6 +116,22 @@ msgstr "" msgid "Last Updated on" msgstr "" +#. module: l10n_it_fatturapa_pec +#: model:ir.ui.view,arch_db:l10n_it_fatturapa_pec.view_email_server_form_e_invoice +msgid "Last error message" +msgstr "" + +#. module: l10n_it_fatturapa_pec +#: code:addons/l10n_it_fatturapa_pec/models/fatturapa_attachment_out.py:57 +#, python-format +msgid "No incoming PEC server found. Please configure it." +msgstr "" + +#. module: l10n_it_fatturapa_pec +#: model:ir.model,name:l10n_it_fatturapa_pec.model_fetchmail_server +msgid "POP/IMAP Server" +msgstr "" + #. module: l10n_it_fatturapa_pec #: model:ir.ui.view,arch_db:l10n_it_fatturapa_pec.view_fatturapa_out_attachment_search_state msgid "Ready" @@ -195,19 +216,19 @@ msgid "Wizard to send multiple e-invoice PEC" msgstr "" #. module: l10n_it_fatturapa_pec -#: code:addons/l10n_it_fatturapa_pec/models/fatturapa_attachment_out.py:47 +#: code:addons/l10n_it_fatturapa_pec/models/fatturapa_attachment_out.py:258 #, python-format -msgid "Yo can only reset 'sender error' files" +msgid "You can only delete 'ready to send' files" msgstr "" #. module: l10n_it_fatturapa_pec -#: code:addons/l10n_it_fatturapa_pec/models/fatturapa_attachment_out.py:247 +#: code:addons/l10n_it_fatturapa_pec/models/fatturapa_attachment_out.py:47 #, python-format -msgid "You can only delete 'ready to send' files" +msgid "You can only reset 'sender error' files" msgstr "" #. module: l10n_it_fatturapa_pec -#: code:addons/l10n_it_fatturapa_pec/models/fatturapa_attachment_out.py:54 +#: code:addons/l10n_it_fatturapa_pec/models/fatturapa_attachment_out.py:65 #, python-format msgid "You can only send 'ready to send' files" msgstr "" diff --git a/l10n_it_fatturapa_pec/models/__init__.py b/l10n_it_fatturapa_pec/models/__init__.py index 2299b9b3bda3..85b76325b359 100644 --- a/l10n_it_fatturapa_pec/models/__init__.py +++ b/l10n_it_fatturapa_pec/models/__init__.py @@ -4,3 +4,4 @@ from . import account from . import fatturapa_attachment_out from . import mail_thread +from . import fetchmail diff --git a/l10n_it_fatturapa_pec/models/fatturapa_attachment_out.py b/l10n_it_fatturapa_pec/models/fatturapa_attachment_out.py index f63d4c5f2bb7..84712cbda195 100644 --- a/l10n_it_fatturapa_pec/models/fatturapa_attachment_out.py +++ b/l10n_it_fatturapa_pec/models/fatturapa_attachment_out.py @@ -44,11 +44,22 @@ class FatturaPAAttachmentOut(models.Model): def reset_to_ready(self): for att in self: if att.state != 'sender_error': - raise UserError(_("Yo can only reset 'sender error' files")) + raise UserError(_("You can only reset 'sender error' files")) att.state = 'ready' + @api.model + def _check_fetchmail(self): + server = self.env['fetchmail.server'].search([ + ('is_fatturapa_pec', '=', True), + ('state', '=', 'done') + ]) + if not server: + raise UserError(_( + "No incoming PEC server found. Please configure it.")) + @api.multi def send_via_pec(self): + self._check_fetchmail() states = self.mapped('state') if set(states) != set(['ready']): raise UserError(_("You can only send 'ready to send' files")) diff --git a/l10n_it_fatturapa_pec/models/fetchmail.py b/l10n_it_fatturapa_pec/models/fetchmail.py new file mode 100644 index 000000000000..40c78d2f0ccb --- /dev/null +++ b/l10n_it_fatturapa_pec/models/fetchmail.py @@ -0,0 +1,134 @@ +# -*- coding: utf-8 -*- +# Copyright 2018 Lorenzo Battistini +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl). + +import logging +from odoo import models, api, fields + +_logger = logging.getLogger(__name__) +MAX_POP_MESSAGES = 50 + + +class Fetchmail(models.Model): + _inherit = 'fetchmail.server' + last_pec_error_message = fields.Text( + "Last PEC error message", readonly=True) + + @api.multi + def fetch_mail(self): + for server in self: + if not server.is_fatturapa_pec: + super(Fetchmail, server).fetch_mail() + else: + additional_context = { + 'fetchmail_cron_running': True + } + # Setting fetchmail_cron_running to avoid to disable cron while + # cron is running (otherwise it would be done by setting + # server.state = 'draft', + # see _update_cron method) + server = server.with_context(**additional_context) + MailThread = self.env['mail.thread'] + _logger.info( + 'start checking for new e-invoices on %s server %s', + server.type, server.name) + additional_context['fetchmail_server_id'] = server.id + additional_context['server_type'] = server.type + imap_server = None + pop_server = None + if server.type == 'imap': + try: + imap_server = server.connect() + imap_server.select() + result, data = imap_server.search(None, '(UNSEEN)') + for num in data[0].split(): + result, data = imap_server.fetch(num, '(RFC822)') + imap_server.store(num, '-FLAGS', '\\Seen') + try: + MailThread.with_context( + **additional_context + ).message_process( + server.object_id.model, data[0][1], + save_original=server.original, + strip_attachments=(not server.attach) + ) + # if message is processed without exceptions + server.last_pec_error_message = '' + except Exception as e: + _logger.info( + 'Failed to process mail from %s server ' + '%s. Resetting server status', + server.type, server.name, exc_info=True + ) + # Here is where we need to intervene. + # Setting to draft prevents new e-invoices to + # be sent via PEC + server.state = 'draft' + server.last_pec_error_message = str(e) + break + imap_server.store(num, '+FLAGS', '\\Seen') + # We need to commit because message is processed: + # Possible next exceptions, out of try, should not + # rollback processed messages + self._cr.commit() + except Exception as e: + _logger.info( + "General failure when trying to fetch mail from " + "%s server %s.", + server.type, server.name, exc_info=True) + server.state = 'draft' + server.last_pec_error_message = str(e) + finally: + if imap_server: + imap_server.close() + imap_server.logout() + elif server.type == 'pop': + try: + while True: + pop_server = server.connect() + (num_messages, total_size) = pop_server.stat() + pop_server.list() + for num in range( + 1, min(MAX_POP_MESSAGES, num_messages) + 1 + ): + (header, messages, octets) = pop_server.retr( + num) + message = '\n'.join(messages) + try: + MailThread.with_context( + **additional_context + ).message_process( + server.object_id.model, message, + save_original=server.original, + strip_attachments=(not server.attach) + ) + pop_server.dele(num) + # See the comments in the IMAP part + server.last_pec_error_message = '' + except Exception as e: + _logger.info( + 'Failed to process mail from %s server' + '%s. Resetting server status', + server.type, server.name, exc_info=True + ) + # See the comments in the IMAP part + server.state = 'draft' + server.last_pec_error_message = str(e) + break + self._cr.commit() + if num_messages < MAX_POP_MESSAGES: + break + pop_server.quit() + except Exception as e: + _logger.info( + "General failure when trying to fetch mail from %s" + " server %s.", + server.type, server.name, exc_info=True) + # See the comments in the IMAP part + server.state = 'draft' + server.last_pec_error_message = str(e) + finally: + if pop_server: + pop_server.quit() + server.write({'date': fields.Datetime.now()}) + return True diff --git a/l10n_it_fatturapa_pec/views/fetchmail_view.xml b/l10n_it_fatturapa_pec/views/fetchmail_view.xml new file mode 100644 index 000000000000..9e03f1ba33f5 --- /dev/null +++ b/l10n_it_fatturapa_pec/views/fetchmail_view.xml @@ -0,0 +1,20 @@ + + + + + view_email_server_form_e_invoice + fetchmail.server + + + + + + + + + + {'invisible': [('is_fatturapa_pec', '=', True)]} + + + +