diff options
| author | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
|---|---|---|
| committer | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
| commit | 3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch) | |
| tree | a44932296ef4a9b71d5f010906253d8c53727726 /addons/l10n_it_edi_sdicoop | |
| parent | 0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff) | |
initial commit 2
Diffstat (limited to 'addons/l10n_it_edi_sdicoop')
| -rw-r--r-- | addons/l10n_it_edi_sdicoop/__init__.py | 14 | ||||
| -rw-r--r-- | addons/l10n_it_edi_sdicoop/__manifest__.py | 26 | ||||
| -rw-r--r-- | addons/l10n_it_edi_sdicoop/data/cron.xml | 13 | ||||
| -rw-r--r-- | addons/l10n_it_edi_sdicoop/i18n_extra/l10n_it_edi_sdicoop.pot | 213 | ||||
| -rw-r--r-- | addons/l10n_it_edi_sdicoop/models/__init__.py | 6 | ||||
| -rw-r--r-- | addons/l10n_it_edi_sdicoop/models/account_edi_format.py | 281 | ||||
| -rw-r--r-- | addons/l10n_it_edi_sdicoop/models/account_invoice.py | 24 | ||||
| -rw-r--r-- | addons/l10n_it_edi_sdicoop/models/res_config_settings.py | 25 | ||||
| -rw-r--r-- | addons/l10n_it_edi_sdicoop/views/l10n_it_view.xml | 75 | ||||
| -rw-r--r-- | addons/l10n_it_edi_sdicoop/views/res_config_settings_views.xml | 45 |
10 files changed, 722 insertions, 0 deletions
diff --git a/addons/l10n_it_edi_sdicoop/__init__.py b/addons/l10n_it_edi_sdicoop/__init__.py new file mode 100644 index 00000000..c1eff7ed --- /dev/null +++ b/addons/l10n_it_edi_sdicoop/__init__.py @@ -0,0 +1,14 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. +from . import models + +from odoo import api, SUPERUSER_ID + + +def _disable_pec_mail_post_init(cr, registry): + ''' Pec mail cannot be used in conjunction with SdiCoop, so disable the Pec fetchmail servers. + ''' + env = api.Environment(cr, SUPERUSER_ID, {}) + + env['fetchmail.server'].search([('l10n_it_is_pec', '=', True)]).l10n_it_is_pec = False + env['res.company'].search([('l10n_it_mail_pec_server_id', '!=', None)]).l10n_it_mail_pec_server_id = None diff --git a/addons/l10n_it_edi_sdicoop/__manifest__.py b/addons/l10n_it_edi_sdicoop/__manifest__.py new file mode 100644 index 00000000..7d2dc79a --- /dev/null +++ b/addons/l10n_it_edi_sdicoop/__manifest__.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +{ + 'name': 'Italy - E-invoicing (SdiCoop)', + 'version': '0.3', + 'depends': [ + 'l10n_it_edi', + 'account_edi_extended', + 'account_edi_proxy_client', + ], + 'author': 'Odoo', + 'description': """ +E-invoice implementation for Italy with the web-service. Ability to send and receive document from SdiCoop. Files sent by SdiCoop are first stored on the proxy +and then fetched by this module. + """, + 'category': 'Accounting/Localizations/EDI', + 'website': 'http://www.odoo.com/', + 'data': [ + 'data/cron.xml', + 'views/l10n_it_view.xml', + 'views/res_config_settings_views.xml', + ], + 'post_init_hook': '_disable_pec_mail_post_init', + 'license': 'LGPL-3', +} diff --git a/addons/l10n_it_edi_sdicoop/data/cron.xml b/addons/l10n_it_edi_sdicoop/data/cron.xml new file mode 100644 index 00000000..0515ecef --- /dev/null +++ b/addons/l10n_it_edi_sdicoop/data/cron.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<odoo> + <record id="ir_cron_receive_fattura_pa_invoice" model="ir.cron"> + <field name="name">FatturaPA: Receive invoices from the exchange system</field> + <field name="interval_number">1</field> + <field name="interval_type">days</field> + <field name="numbercall">-1</field> + <field name="model_id" ref="account_edi.model_account_edi_format"/> + <field name="code">model._cron_receive_fattura_pa()</field> + <field name="doall" eval="False"/> + <field name="state">code</field> + </record> +</odoo> diff --git a/addons/l10n_it_edi_sdicoop/i18n_extra/l10n_it_edi_sdicoop.pot b/addons/l10n_it_edi_sdicoop/i18n_extra/l10n_it_edi_sdicoop.pot new file mode 100644 index 00000000..c06e62ee --- /dev/null +++ b/addons/l10n_it_edi_sdicoop/i18n_extra/l10n_it_edi_sdicoop.pot @@ -0,0 +1,213 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * l10n_it_edi_sdicoop +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0+e\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-06-03 13:44+0000\n" +"PO-Revision-Date: 2021-06-03 13:44+0000\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: l10n_it_edi_sdicoop +#: model_terms:ir.ui.view,arch_db:l10n_it_edi_sdicoop.res_config_settings_view_form +msgid "<span class=\"o_form_label\">Allow Odoo to process invoices</span>" +msgstr "" + +#. module: l10n_it_edi_sdicoop +#: model_terms:ir.ui.view,arch_db:l10n_it_edi_sdicoop.res_config_settings_view_form +msgid "Already registered" +msgstr "" + +#. module: l10n_it_edi_sdicoop +#: code:addons/l10n_it_edi_sdicoop/models/account_edi_format.py:0 +#, python-format +msgid "Attached file is empty" +msgstr "" + +#. module: l10n_it_edi_sdicoop +#: model_terms:ir.ui.view,arch_db:l10n_it_edi_sdicoop.res_config_settings_view_form +msgid "" +"By clicking this button, I hereby accept that Odoo may process my invoices" +msgstr "" + +#. module: l10n_it_edi_sdicoop +#: model:ir.model,name:l10n_it_edi_sdicoop.model_res_config_settings +msgid "Config Settings" +msgstr "" + +#. module: l10n_it_edi_sdicoop +#: model:ir.model.fields,field_description:l10n_it_edi_sdicoop.field_account_edi_format__display_name +#: model:ir.model.fields,field_description:l10n_it_edi_sdicoop.field_account_move__display_name +#: model:ir.model.fields,field_description:l10n_it_edi_sdicoop.field_res_config_settings__display_name +msgid "Display Name" +msgstr "" + +#. module: l10n_it_edi_sdicoop +#: model:ir.model,name:l10n_it_edi_sdicoop.model_account_edi_format +msgid "EDI format" +msgstr "" + +#. module: l10n_it_edi_sdicoop +#: model_terms:ir.ui.view,arch_db:l10n_it_edi_sdicoop.res_config_settings_view_form +msgid "Electronic Document Invoicing" +msgstr "" + +#. module: l10n_it_edi_sdicoop +#: code:addons/l10n_it_edi_sdicoop/models/account_edi_format.py:0 +#, python-format +msgid "Expiration of the maximum term for communication of acceptance/refusal" +msgstr "" + +#. module: l10n_it_edi_sdicoop +#: model:ir.actions.server,name:l10n_it_edi_sdicoop.ir_cron_receive_fattura_pa_invoice_ir_actions_server +#: model:ir.cron,cron_name:l10n_it_edi_sdicoop.ir_cron_receive_fattura_pa_invoice +#: model:ir.cron,name:l10n_it_edi_sdicoop.ir_cron_receive_fattura_pa_invoice +msgid "FatturaPA: Receive invoices from the exchange system" +msgstr "" + +#. module: l10n_it_edi_sdicoop +#: model:ir.model.fields,field_description:l10n_it_edi_sdicoop.field_account_edi_format__id +#: model:ir.model.fields,field_description:l10n_it_edi_sdicoop.field_account_move__id +#: model:ir.model.fields,field_description:l10n_it_edi_sdicoop.field_res_config_settings__id +msgid "ID" +msgstr "" + +#. module: l10n_it_edi_sdicoop +#: code:addons/l10n_it_edi_sdicoop/models/account_edi_format.py:0 +#, python-format +msgid "" +"Invoices for PA are not managed by Odoo, you can download the document and " +"send it on your own." +msgstr "" + +#. module: l10n_it_edi_sdicoop +#: model:ir.model.fields,field_description:l10n_it_edi_sdicoop.field_res_config_settings__is_edi_proxy_active +msgid "Is Edi Proxy Active" +msgstr "" + +#. module: l10n_it_edi_sdicoop +#: code:addons/l10n_it_edi_sdicoop/models/account_edi_format.py:0 +#, python-format +msgid "Italian invoice: %s" +msgstr "" + +#. module: l10n_it_edi_sdicoop +#: model:ir.model,name:l10n_it_edi_sdicoop.model_account_move +msgid "Journal Entry" +msgstr "" + +#. module: l10n_it_edi_sdicoop +#: model:ir.model.fields,field_description:l10n_it_edi_sdicoop.field_account_bank_statement_line__l10n_it_edi_attachment_id +#: model:ir.model.fields,field_description:l10n_it_edi_sdicoop.field_account_move__l10n_it_edi_attachment_id +#: model:ir.model.fields,field_description:l10n_it_edi_sdicoop.field_account_payment__l10n_it_edi_attachment_id +msgid "L10N It Edi Attachment" +msgstr "" + +#. module: l10n_it_edi_sdicoop +#: model:ir.model.fields,field_description:l10n_it_edi_sdicoop.field_account_bank_statement_line__l10n_it_edi_transaction +#: model:ir.model.fields,field_description:l10n_it_edi_sdicoop.field_account_move__l10n_it_edi_transaction +#: model:ir.model.fields,field_description:l10n_it_edi_sdicoop.field_account_payment__l10n_it_edi_transaction +msgid "L10N It Edi Transaction" +msgstr "" + +#. module: l10n_it_edi_sdicoop +#: model:ir.model.fields,field_description:l10n_it_edi_sdicoop.field_account_edi_format____last_update +#: model:ir.model.fields,field_description:l10n_it_edi_sdicoop.field_account_move____last_update +#: model:ir.model.fields,field_description:l10n_it_edi_sdicoop.field_res_config_settings____last_update +msgid "Last Modified on" +msgstr "" + +#. module: l10n_it_edi_sdicoop +#: code:addons/l10n_it_edi_sdicoop/models/account_edi_format.py:0 +#, python-format +msgid "" +"Please fill your codice fiscale to be able to receive invoices from " +"FatturaPA" +msgstr "" + +#. module: l10n_it_edi_sdicoop +#: model_terms:ir.ui.view,arch_db:l10n_it_edi_sdicoop.res_config_settings_view_form +msgid "Register" +msgstr "" + +#. module: l10n_it_edi_sdicoop +#: code:addons/l10n_it_edi_sdicoop/models/account_edi_format.py:0 +#, python-format +msgid "Service momentarily unavailable" +msgstr "" + +#. module: l10n_it_edi_sdicoop +#: code:addons/l10n_it_edi_sdicoop/models/account_edi_format.py:0 +#, python-format +msgid "" +"The E-invoice is not delivered to the addressee. The Exchange System is" +" unable to deliver the file to the Public Administration." +" The Exchange System will contact the PA to report the " +"problem and request that they provide a solution. During" +" the following 15 days, the Exchange System will try to forward the " +"FatturaPA file to the Administration in question again." +msgstr "" + +#. module: l10n_it_edi_sdicoop +#: code:addons/l10n_it_edi_sdicoop/models/account_edi_format.py:0 +#, python-format +msgid "The invoice has been refused by the Exchange System" +msgstr "" + +#. module: l10n_it_edi_sdicoop +#: code:addons/l10n_it_edi_sdicoop/models/account_edi_format.py:0 +#, python-format +msgid "" +"The invoice has been succesfully transmitted. The addressee has 15 days to " +"accept or reject it." +msgstr "" + +#. module: l10n_it_edi_sdicoop +#: code:addons/l10n_it_edi_sdicoop/models/account_edi_format.py:0 +#, python-format +msgid "The invoice was refused by the addressee." +msgstr "" + +#. module: l10n_it_edi_sdicoop +#: code:addons/l10n_it_edi_sdicoop/models/account_edi_format.py:0 +#, python-format +msgid "" +"The invoice was successfully transmitted to the Public Administration and we" +" are waiting for confirmation" +msgstr "" + +#. module: l10n_it_edi_sdicoop +#: code:addons/l10n_it_edi_sdicoop/models/account_edi_format.py:0 +#, python-format +msgid "" +"The invoice was successfully transmitted to the Public Administration and we" +" are waiting for confirmation." +msgstr "" + +#. module: l10n_it_edi_sdicoop +#: code:addons/l10n_it_edi_sdicoop/models/account_edi_format.py:0 +#, python-format +msgid "Unauthorized user" +msgstr "" + +#. module: l10n_it_edi_sdicoop +#: code:addons/l10n_it_edi_sdicoop/models/account_edi_format.py:0 +#, python-format +msgid "You are not allowed to check the status of this invoice." +msgstr "" + +#. module: l10n_it_edi_sdicoop +#: code:addons/l10n_it_edi_sdicoop/models/account_edi_format.py:0 +#: code:addons/l10n_it_edi_sdicoop/models/account_edi_format.py:0 +#: code:addons/l10n_it_edi_sdicoop/models/account_edi_format.py:0 +#, python-format +msgid "" +"You must accept the terms and conditions in the settings to use FatturaPA." +msgstr "" diff --git a/addons/l10n_it_edi_sdicoop/models/__init__.py b/addons/l10n_it_edi_sdicoop/models/__init__.py new file mode 100644 index 00000000..b297cf8a --- /dev/null +++ b/addons/l10n_it_edi_sdicoop/models/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import account_invoice +from . import account_edi_format +from . import res_config_settings diff --git a/addons/l10n_it_edi_sdicoop/models/account_edi_format.py b/addons/l10n_it_edi_sdicoop/models/account_edi_format.py new file mode 100644 index 00000000..95db0ada --- /dev/null +++ b/addons/l10n_it_edi_sdicoop/models/account_edi_format.py @@ -0,0 +1,281 @@ +# -*- coding:utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import models, _, _lt +from odoo.exceptions import UserError +from odoo.addons.account_edi_proxy_client.models.account_edi_proxy_user import AccountEdiProxyError, SERVER_URL + +from lxml import etree +import base64 +import logging + +_logger = logging.getLogger(__name__) + + +class AccountEdiFormat(models.Model): + _inherit = 'account.edi.format' + + # ------------------------------------------------------------------------- + # Import + # ------------------------------------------------------------------------- + + def _cron_receive_fattura_pa(self): + ''' Check the proxy for incoming invoices. + ''' + if self.env['ir.config_parameter'].get_param('account_edi_proxy_client.demo', False): + return + + proxy_users = self.env['account_edi_proxy_client.user'].search([('edi_format_id', '=', self.env.ref('l10n_it_edi.edi_fatturaPA').id)]) + for proxy_user in proxy_users: + company = proxy_user.company_id + try: + res = proxy_user._make_request(SERVER_URL + '/api/l10n_it_edi/1/in/RicezioneInvoice', + params={'recipient_codice_fiscale': company.l10n_it_codice_fiscale}) + except AccountEdiProxyError as e: + _logger.error('Error while receiving file from SdiCoop: %s', e) + + proxy_acks = [] + for id_transaction, fattura in res.items(): + if self.env['ir.attachment'].search([('name', '=', fattura['filename']), ('res_model', '=', 'account.move')], limit=1): + # name should be unique, the invoice already exists + _logger.info('E-invoice already exist: %s', fattura['filename']) + proxy_acks.append(id_transaction) + continue + + file = proxy_user._decrypt_data(fattura['file'], fattura['key']) + + try: + tree = etree.fromstring(file) + except Exception: + # should not happen as the file has been checked by SdiCoop + _logger.info('Received file badly formatted, skipping: \n %s', file) + continue + + invoice = self.env.ref('l10n_it_edi.edi_fatturaPA')._create_invoice_from_xml_tree(fattura['filename'], tree) + self.env['ir.attachment'].create({ + 'name': fattura['filename'], + 'raw': file, + 'type': 'binary', + 'res_model': 'account.move', + 'res_id': invoice.id + }) + + proxy_acks.append(id_transaction) + + if proxy_acks: + try: + proxy_user._make_request(SERVER_URL + '/api/l10n_it_edi/1/ack', + params={'transaction_ids': proxy_acks}) + except AccountEdiProxyError as e: + _logger.error('Error while receiving file from SdiCoop: %s', e) + + # ------------------------------------------------------------------------- + # Export + # ------------------------------------------------------------------------- + + def _check_move_configuration(self, move): + # OVERRIDE + res = super()._check_move_configuration(move) + if self.code != 'fattura_pa': + return res + + res.extend(self._l10n_it_edi_check_invoice_configuration(move)) + + if not self._get_proxy_user(move.company_id): + res.append(_("You must accept the terms and conditions in the settings to use FatturaPA.")) + + return res + + def _needs_web_services(self): + self.ensure_one() + return self.code == 'fattura_pa' or super()._needs_web_services() + + def _l10n_it_edi_is_required_for_invoice(self, invoice): + """ _is_required_for_invoice for SdiCoop. + OVERRIDE + """ + return invoice.is_sale_document() and invoice.country_code == 'IT' + + def _support_batching(self, move=None, state=None, company=None): + # OVERRIDE + if self.code == 'fattura_pa': + return state == 'to_send' and move.is_invoice() + + return super()._support_batching(move=move, state=state, company=company) + + def _l10n_it_post_invoices_step_1(self, invoices): + ''' Send the invoices to the proxy. + ''' + to_return = {} + + to_send = {} + for invoice in invoices: + xml = b"<?xml version='1.0' encoding='UTF-8'?>" + invoice._export_as_xml() + filename = self._l10n_it_edi_generate_electronic_invoice_filename(invoice) + attachment = self.env['ir.attachment'].create({ + 'name': filename, + 'res_id': invoice.id, + 'res_model': invoice._name, + 'datas': base64.encodebytes(xml), + 'description': _('Italian invoice: %s', invoice.move_type), + 'type': 'binary', + }) + invoice.l10n_it_edi_attachment_id = attachment + + if len(invoice.commercial_partner_id.l10n_it_pa_index or '') == 6: + invoice.message_post( + body=(_("Invoices for PA are not managed by Odoo, you can download the document and send it on your own.")) + ) + to_return[invoice] = {'attachment': attachment} + else: + to_send[filename] = { + 'invoice': invoice, + 'data': {'filename': filename, 'xml': base64.b64encode(xml)}} + + company = invoices.company_id + proxy_user = self._get_proxy_user(company) + if not proxy_user: # proxy user should exist, because there is a check in _check_move_configuration + return {invoice: { + 'error': _("You must accept the terms and conditions in the settings to use FatturaPA."), + 'blocking_level': 'error'} for invoice in invoices} + + if self.env['ir.config_parameter'].get_param('account_edi_proxy_client.demo', False): + responses = {filename: {'id_transaction': 'demo'} for invoice in invoices} + else: + try: + responses = self._l10n_it_edi_upload([i['data'] for i in to_send.values()], proxy_user) + except AccountEdiProxyError as e: + return {invoice: {'error': e.message, 'blocking_level': 'error'} for invoice in invoices} + + for filename, response in responses.items(): + invoice = to_send[filename]['invoice'] + to_return[invoice] = response + if 'id_transaction' in response: + invoice.l10n_it_edi_transaction = response['id_transaction'] + to_return[invoice].update({ + 'error': _('The invoice was successfully transmitted to the Public Administration and we are waiting for confirmation.'), + 'blocking_level': 'info', + }) + return to_return + + def _l10n_it_post_invoices_step_2(self, invoices): + ''' Check if the sent invoices have been processed by FatturaPA. + ''' + to_check = {i.l10n_it_edi_transaction: i for i in invoices} + to_return = {} + company = invoices.company_id + proxy_user = self._get_proxy_user(company) + if not proxy_user: # proxy user should exist, because there is a check in _check_move_configuration + return {invoice: { + 'error': _("You must accept the terms and conditions in the settings to use FatturaPA."), + 'blocking_level': 'error'} for invoice in invoices} + + if self.env['ir.config_parameter'].get_param('account_edi_proxy_client.demo', False): + # simulate success and bypass ack + return {invoice: {'attachment': invoice.l10n_it_edi_attachment_id} for invoice in invoices} + else: + try: + responses = proxy_user._make_request(SERVER_URL + '/api/l10n_it_edi/1/in/TrasmissioneFatture', + params={'ids_transaction': list(to_check.keys())}) + except AccountEdiProxyError as e: + return {invoice: {'error': e.message, 'blocking_level': 'error'} for invoice in invoices} + + proxy_acks = [] + for id_transaction, response in responses.items(): + invoice = to_check[id_transaction] + if 'error' in response: + to_return[invoice] = response + continue + + state = response['state'] + if state == 'awaiting_outcome': + to_return[invoice] = { + 'error': _('The invoice was successfully transmitted to the Public Administration and we are waiting for confirmation'), + 'blocking_level': 'info', + } + proxy_acks.append(id_transaction) + continue + elif state == 'not_found': + # Invoice does not exist on proxy. Either it does not belong to this proxy_user or it was not created correctly when + # it was sent to the proxy. + to_return[invoice] = {'error': _('You are not allowed to check the status of this invoice.'), 'blocking_level': 'error'} + continue + + xml = proxy_user._decrypt_data(response['file'], response['key']) + response_tree = etree.fromstring(xml) + if state == 'ricevutaConsegna': + to_return[invoice] = {'error': _('The invoice has been succesfully transmitted. The addressee has 15 days to accept or reject it.')} + elif state == 'notificaScarto': + errors = [element.find('Descrizione').text for element in response_tree.xpath('//Errore')] + to_return[invoice] = {'error': self._format_error_message(_('The invoice has been refused by the Exchange System'), errors), 'blocking_level': 'error'} + elif state == 'notificaMancataConsegna': + to_return[invoice] = { + 'error': _('The E-invoice is not delivered to the addressee. The Exchange System is\ + unable to deliver the file to the Public Administration. The Exchange System will\ + contact the PA to report the problem and request that they provide a solution. \ + During the following 15 days, the Exchange System will try to forward the FatturaPA\ + file to the Administration in question again.'), + } + elif state == 'notificaEsito': + outcome = response_tree.find('Esito').text + if outcome == 'EC01': + to_return[invoice] = {'attachment': invoice.l10n_it_edi_attachment_id} + else: # ECO2 + to_return[invoice] = {'error': _('The invoice was refused by the addressee.'), 'blocking_level': 'error'} + elif state == 'NotificaDecorrenzaTermini': + to_return[invoice] = {'error': _('Expiration of the maximum term for communication of acceptance/refusal'), 'blocking_level': 'error'} + proxy_acks.append(id_transaction) + + try: + proxy_user._make_request(SERVER_URL + '/api/l10n_it_edi/1/ack', + params={'transaction_ids': proxy_acks}) + except AccountEdiProxyError as e: + # Will be ignored and acked again next time. + _logger.error('Error while acking file to SdiCoop: %s', e) + + return to_return + + def _post_fattura_pa(self, invoices): + # OVERRIDE + if not invoices.l10n_it_edi_transaction: + return self._l10n_it_post_invoices_step_1(invoices) + else: + return self._l10n_it_post_invoices_step_2(invoices) + + # ------------------------------------------------------------------------- + # Proxy methods + # ------------------------------------------------------------------------- + + def _get_proxy_identification(self, company): + if self.code != 'fattura_pa': + return super()._get_proxy_identification() + + if not company.l10n_it_codice_fiscale: + raise UserError(_('Please fill your codice fiscale to be able to receive invoices from FatturaPA')) + + return self.env['res.partner']._l10n_it_normalize_codice_fiscale(company.l10n_it_codice_fiscale) + + def _l10n_it_edi_upload(self, files, proxy_user): + '''Upload files to fatturapa. + + :param files: A list of dictionary {filename, base64_xml}. + :returns: A dictionary. + * message: Message from fatturapa. + * transactionId: The fatturapa ID of this request. + * error: An eventual error. + * error_level: Info, warning, error. + ''' + ERRORS = { + 'EI01': {'error': _lt('Attached file is empty'), 'blocking_level': 'error'}, + 'EI02': {'error': _lt('Service momentarily unavailable'), 'blocking_level': 'warning'}, + 'EI03': {'error': _lt('Unauthorized user'), 'blocking_level': 'error'}, + } + + result = proxy_user._make_request(SERVER_URL + '/api/l10n_it_edi/1/out/SdiRiceviFile', params={'files': files}) + + # Translate the errors. + for filename in result.keys(): + if 'error' in result[filename]: + result[filename] = ERRORS.get(result[filename]['error'], {'error': result[filename]['error'], 'blocking_level': 'error'}) + + return result diff --git a/addons/l10n_it_edi_sdicoop/models/account_invoice.py b/addons/l10n_it_edi_sdicoop/models/account_invoice.py new file mode 100644 index 00000000..4221dbc0 --- /dev/null +++ b/addons/l10n_it_edi_sdicoop/models/account_invoice.py @@ -0,0 +1,24 @@ +# -*- coding:utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. +import logging + +from odoo import fields, models + + +_logger = logging.getLogger(__name__) + +DEFAULT_FACTUR_ITALIAN_DATE_FORMAT = '%Y-%m-%d' + + +class AccountMove(models.Model): + _inherit = 'account.move' + + l10n_it_edi_transaction = fields.Char(copy=False) + l10n_it_edi_attachment_id = fields.Many2one('ir.attachment', copy=False) + + def send_pec_mail(self): + self.ensure_one() + # OVERRIDE + # With SdiCoop web-service, no need to send PEC mail. + # Set the state to 'other' because the invoice should not be managed par l10n_it_edi. + self.l10n_it_send_state = 'other' diff --git a/addons/l10n_it_edi_sdicoop/models/res_config_settings.py b/addons/l10n_it_edi_sdicoop/models/res_config_settings.py new file mode 100644 index 00000000..04d78743 --- /dev/null +++ b/addons/l10n_it_edi_sdicoop/models/res_config_settings.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- + +from odoo import api, models, fields + + +class ResConfigSettings(models.TransientModel): + _inherit = 'res.config.settings' + + is_edi_proxy_active = fields.Boolean(compute='_compute_is_edi_proxy_active') + + @api.depends('company_id.account_edi_proxy_client_ids', 'company_id.account_edi_proxy_client_ids.active') + def _compute_is_edi_proxy_active(self): + for config in self: + config.is_edi_proxy_active = config.company_id.account_edi_proxy_client_ids + + def button_create_proxy_user(self): + # For now, only fattura_pa uses the proxy. + # To use it for more, we have to either make the activation of the proxy on a format basis + # or create a user per format here (but also when installing new formats) + fattura_pa = self.env.ref('l10n_it_edi.edi_fatturaPA') + edi_identification = fattura_pa._get_proxy_identification(self.company_id) + if not edi_identification: + return + + self.env['account_edi_proxy_client.user']._register_proxy_user(self.company_id, fattura_pa, edi_identification) diff --git a/addons/l10n_it_edi_sdicoop/views/l10n_it_view.xml b/addons/l10n_it_edi_sdicoop/views/l10n_it_view.xml new file mode 100644 index 00000000..40ea1041 --- /dev/null +++ b/addons/l10n_it_edi_sdicoop/views/l10n_it_view.xml @@ -0,0 +1,75 @@ +<?xml version="1.0" encoding="utf-8"?> +<odoo> + <record id="fetchmail_server_form_l10n_it_inherit" model="ir.ui.view"> + <field name="name">fetchmail.server.form.l10n.it.inherit</field> + <field name="model">fetchmail.server</field> + <field name="priority">30</field> + <field name="inherit_id" ref="l10n_it_edi.fetchmail_server_form_l10n_it"/> + <field name="arch" type="xml"> + <data> + <xpath expr="//field[@name='l10n_it_is_pec']" position="replace" /> + </data> + </field> + </record> + + <record id="res_company_form_l10n_it_inherit" model="ir.ui.view"> + <field name="name">res.company.form.l10n.it.inherit</field> + <field name="model">res.company</field> + <field name="priority">30</field> + <field name="inherit_id" ref="l10n_it_edi.res_company_form_l10n_it"/> + <field name="arch" type="xml"> + <data> + <xpath expr="//field[@name='l10n_it_mail_pec_server_id']" position="replace"/> + <xpath expr="//field[@name='l10n_it_address_send_fatturapa']" position="replace"/> + <xpath expr="//field[@name='l10n_it_address_recipient_fatturapa']" position="replace"/> + </data> + </field> + </record> + + <record id="l10n_it_edi.invoice_supplier_tree_l10n_it" model="ir.ui.view"> + <field name="arch" type="xml"> + <!-- Remove the l10n_state_it field. Doing so + with xpath might replace other view elements that we shouldn't remove.--> + <data/> + </field> + </record> + + <record id="l10n_it_edi.invoice_kanban_l10n_it" model="ir.ui.view"> + <field name="arch" type="xml"> + <!-- Remove the l10n_state_it field. Doing so + with xpath might replace other view elements that we shouldn't remove.--> + <data/> + </field> + </record> + + <record id="l10n_it_edi.account_invoice_form_l10n_it" model="ir.ui.view"> + <field name="arch" type="xml"> + <!-- Remove the l10n_state_it field but keep other info tab. + Doing so with xpath might repace other view elements that we shouldn't remove. --> + <data> + <xpath expr="//page[@name='other_info']" position="after"> + <page string="Electronic Invoicing" + name="electronic_invoicing" + attrs="{'invisible': [('move_type', 'not in', ('out_invoice', 'out_refund', 'in_invoice', 'in_refund'))]}"> + <group> + <group> + <field name="l10n_it_stamp_duty"/> + <field name="l10n_it_ddt_id" + attrs="{'invisible': [('move_type', 'not in', ('out_invoice', 'out_refund'))]}"/> + </group> + </group> + </page> + </xpath> + </data> + </field> + </record> + + + <record id="l10n_it_edi.view_account_invoice_filter_l10n_it" model="ir.ui.view"> + <field name="arch" type="xml"> + <!-- Remove the filters.--> + <data /> + </field> + </record> + +</odoo> diff --git a/addons/l10n_it_edi_sdicoop/views/res_config_settings_views.xml b/addons/l10n_it_edi_sdicoop/views/res_config_settings_views.xml new file mode 100644 index 00000000..3929c555 --- /dev/null +++ b/addons/l10n_it_edi_sdicoop/views/res_config_settings_views.xml @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="utf-8"?> +<odoo> + + <record id="res_config_settings_view_form" model="ir.ui.view"> + <field name="name">res.config.settings.view.form.inherit.proxy.user</field> + <field name="model">res.config.settings</field> + <field name="inherit_id" ref="account.res_config_settings_view_form"/> + <field name="arch" type="xml"> + <xpath expr="//div[@id='account_vendor_bills']" position="after"> + <div attrs="{'invisible':[('country_code', '!=', 'IT')]}"> + <h2>Electronic Document Invoicing</h2> + <div class="row mt16 o_settings_container" id='account_edi'> + <div class="col-12 col-lg-6 o_setting_box"> + <div class="o_setting_right_pane"> + <span class="o_form_label">Allow Odoo to process invoices</span> + <div class="text-muted"> + By clicking this button, I accept that Odoo may process my invoices. + </div> + <div class="content-group"> + <field name="is_edi_proxy_active" invisible="True" /> + <div class="row mt8"> + <div class="col-lg-6" title="Register"> + <button name="button_create_proxy_user" + type="object" + string="Register" + class="btn-primary" icon="fa-lg fa-check" + attrs="{'invisible':[('is_edi_proxy_active', '=', True)]}"/> + <button name="button_create_proxy_user" + type="object" + string="Already registered" + disabled="1" + class="btn-lnk" icon="fa-lg fa-check" + attrs="{'invisible':[('is_edi_proxy_active', '=', False)]}"/> + </div> + </div> + </div> + </div> + </div> + </div> + </div> + </xpath> + </field> + </record> + +</odoo> |
