diff --git a/addons/l10n_it_edi/__manifest__.py b/addons/l10n_it_edi/__manifest__.py
index f0a88555d0a..c0ba05dd435 100644
--- a/addons/l10n_it_edi/__manifest__.py
+++ b/addons/l10n_it_edi/__manifest__.py
@@ -7,7 +7,10 @@
'version': '0.3',
'depends': [
'l10n_it',
- 'account_edi'
+ # Although account_edi is a dependency of account_edi_proxy_client,
+ # it is here because it's in the auto-install
+ 'account_edi',
+ 'account_edi_proxy_client',
],
'auto_install': ['l10n_it', 'account_edi'],
'author': 'Odoo',
@@ -21,6 +24,8 @@ E-invoice implementation
'data/account_edi_data.xml',
'data/invoice_it_template.xml',
'data/invoice_it_simplified_template.xml',
+ 'data/ir_cron.xml',
+ 'views/res_config_settings_views.xml',
'views/l10n_it_view.xml',
],
'demo': [
diff --git a/addons/l10n_it_edi_sdicoop/data/cron.xml b/addons/l10n_it_edi/data/ir_cron.xml
similarity index 100%
rename from addons/l10n_it_edi_sdicoop/data/cron.xml
rename to addons/l10n_it_edi/data/ir_cron.xml
diff --git a/addons/l10n_it_edi/i18n/it.po b/addons/l10n_it_edi/i18n/it.po
index b4f5df975df..dbeea228c60 100644
--- a/addons/l10n_it_edi/i18n/it.po
+++ b/addons/l10n_it_edi/i18n/it.po
@@ -10,6 +10,7 @@ msgstr ""
"PO-Revision-Date: 2022-03-29 14:31+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
+"Language: it\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
@@ -89,6 +90,24 @@ msgid ""
"'Scissione dei pagamenti' is not compatible with exoneration of kind 'N6'"
msgstr "'Scissione dei pagamenti' non è compatibile con l'esenzione di tipo 'N6'"
+#. module: l10n_it_edi
+#: model_terms:ir.ui.view,arch_db:l10n_it_edi.res_config_settings_view_form
+msgid ""
+"\n"
+" Fattura Elettronica mode\n"
+" "
+msgstr "Modalitá Fattura Elettronica"
+
+#. module: l10n_it_edi
+#: model_terms:ir.ui.view,arch_db:l10n_it_edi.res_config_settings_view_form
+msgid "Allow Odoo to process invoices"
+msgstr "Permetti ad Odoo di inviare le fatture"
+
+#. module: l10n_it_edi
+#: model_terms:ir.ui.view,arch_db:l10n_it_edi.res_config_settings_view_form
+msgid "A Demo service is in use."
+msgstr "Un servizio Demo è in uso"
+
#. module: l10n_it_edi
#: code:addons/l10n_it_edi/models/res_company.py:0
#, python-format
@@ -102,6 +121,17 @@ msgstr "Tutti i campi che riguardano l'Indice Economico e Amministrativo devono
msgid "Attachment from XML"
msgstr "Allegato dall'XML"
+#. module: l10n_it_edi
+#: model_terms:ir.ui.view,arch_db:l10n_it_edi.res_config_settings_view_form
+msgid "An Official or Test service has been registered."
+msgstr "É giá stato registrato un servizio Ufficiale o di Test."
+
+#. module: l10n_it_edi
+#: code:addons/l10n_it_edi/models/account_edi_format.py:0
+#, python-format
+msgid "Attached file is empty"
+msgstr "Il file allegato è vuoto"
+
#. module: l10n_it_edi
#: code:addons/l10n_it_edi/models/account_edi_format.py:0
#: code:addons/l10n_it_edi/models/account_edi_format.py:0
@@ -109,6 +139,11 @@ msgstr "Allegato dall'XML"
msgid "Bank account not found, useful informations from XML file:"
msgstr "Conto bancario non trovato, informazioni utili dal file XML:"
+#. module: l10n_it_edi
+#: model_terms:ir.ui.view,arch_db:l10n_it_edi.res_config_settings_view_form
+msgid "By checking this box, I accept that Odoo may process my invoices."
+msgstr "Selezionando questa casella, accetto che Odoo invii le mie fatture."
+
#. module: l10n_it_edi
#: model:ir.model.fields,field_description:l10n_it_edi.field_res_company__l10n_it_codice_fiscale
#: model:ir.model.fields,field_description:l10n_it_edi.field_res_partner__l10n_it_codice_fiscale
@@ -141,6 +176,11 @@ msgstr "L'azienda ha un rappresentante fiscale"
msgid "Company listed on the register of companies"
msgstr "L'azienda compare nel Registro delle Imprese"
+#. module: l10n_it_edi
+#: model:ir.model,name:l10n_it_edi.model_res_config_settings
+msgid "Config Settings"
+msgstr "Impostazione configurazioni"
+
#. module: l10n_it_edi
#: model:ir.model.fields,help:l10n_it_edi.field_res_company__l10n_it_mail_pec_server_id
msgid "Configure your PEC-mail server to send electronic invoices."
@@ -189,12 +229,15 @@ msgid ""
msgstr "Consegna non riuscita, il SdI certifica che ha ricevuto la fattura "
"e che non è stato possibile consegnare il file al destinatario"
+#. module: l10n_it_edi
+#: model:ir.model.fields.selection,name:l10n_it_edi.selection__res_config_settings__l10n_it_edi_sdicoop_demo_mode__demo
+msgid "Demo"
+msgstr "Demo"
+
#. module: l10n_it_edi
#: model:ir.model.fields,field_description:l10n_it_edi.field_account_edi_format__display_name
#: model:ir.model.fields,field_description:l10n_it_edi.field_account_move__display_name
#: model:ir.model.fields,field_description:l10n_it_edi.field_account_tax__display_name
-#: model:ir.model.fields,field_description:l10n_it_edi.field_fetchmail_server__display_name
-#: model:ir.model.fields,field_description:l10n_it_edi.field_ir_mail_server__display_name
#: model:ir.model.fields,field_description:l10n_it_edi.field_l10n_it_ddt__display_name
#: model:ir.model.fields,field_description:l10n_it_edi.field_res_company__display_name
#: model:ir.model.fields,field_description:l10n_it_edi.field_res_partner__display_name
@@ -237,6 +280,11 @@ msgstr "Il SdI certifica che ha ricevuto la Fattura e che non è stato possibile
msgid "Economic and Administrative Index"
msgstr "Indice Economico e Amministrativo"
+#. module: l10n_it_edi
+#: model_terms:ir.ui.view,arch_db:l10n_it_edi.res_config_settings_view_form
+msgid "Electronic Document Invoicing"
+msgstr "Interscambio di dati in formato elettronico"
+
#. module: l10n_it_edi
#: model_terms:ir.ui.view,arch_db:l10n_it_edi.account_invoice_form_l10n_it
#: model_terms:ir.ui.view,arch_db:l10n_it_edi.res_company_form_l10n_it
@@ -308,6 +356,20 @@ msgstr "Termine massimo di decorrenza per l'accettazione o il rifiuto della comu
msgid "FatturaPA Send State"
msgstr "Stato di invio della FatturaPA"
+#. module: l10n_it_edi
+#: model:ir.model.fields,field_description:l10n_it_edi.field_account_bank_statement_line__l10n_it_edi_transaction
+#: model:ir.model.fields,field_description:l10n_it_edi.field_account_move__l10n_it_edi_transaction
+#: model:ir.model.fields,field_description:l10n_it_edi.field_account_payment__l10n_it_edi_transaction
+msgid "FatturaPA Transaction"
+msgstr "Transazione FatturaPA"
+
+#. module: l10n_it_edi
+#: model:ir.actions.server,name:l10n_it_edi.ir_cron_receive_fattura_pa_invoice_ir_actions_server
+#: model:ir.cron,cron_name:l10n_it_edi.ir_cron_receive_fattura_pa_invoice
+#: model:ir.cron,name:l10n_it_edi.ir_cron_receive_fattura_pa_invoice
+msgid "FatturaPA: Receive invoices from the exchange system"
+msgstr "FatturaPA: Ricezione fatture dal Sistema d'Interscambio"
+
#. module: l10n_it_edi
#: model:ir.model.fields,help:l10n_it_edi.field_res_company__l10n_it_codice_fiscale
msgid "Fiscal code of your company"
@@ -327,10 +389,9 @@ msgstr "Esente dalle tasse (Italia)"
#: model:ir.model.fields,field_description:l10n_it_edi.field_account_edi_format__id
#: model:ir.model.fields,field_description:l10n_it_edi.field_account_move__id
#: model:ir.model.fields,field_description:l10n_it_edi.field_account_tax__id
-#: model:ir.model.fields,field_description:l10n_it_edi.field_fetchmail_server__id
-#: model:ir.model.fields,field_description:l10n_it_edi.field_ir_mail_server__id
#: model:ir.model.fields,field_description:l10n_it_edi.field_l10n_it_ddt__id
#: model:ir.model.fields,field_description:l10n_it_edi.field_res_company__id
+#: model:ir.model.fields,field_description:l10n_it_edi.field_res_config_settings__id
#: model:ir.model.fields,field_description:l10n_it_edi.field_res_partner__id
msgid "ID"
msgstr "ID"
@@ -355,6 +416,20 @@ msgid ""
msgstr "Se l'Imposta risulta essere un'Esenzione, bisogna compilare il Tipo "
"di Esenzione e il suo valore dev'essere 0.0."
+#. module: l10n_it_edi
+#: model_terms:ir.ui.view,arch_db:l10n_it_edi.res_config_settings_view_form
+msgid ""
+"In demo mode Odoo will just simulate the sending of invoices to the government.
\n"
+" In test mode (experimental) Odoo will send the invoices to a non-production service.\n"
+" Saving this change will direct all companies on this database to this use this configuration.\n"
+" Once registered for testing or official, the mode cannot be changed."
+msgstr "Nella modalitá Demo, Odoo simulerá l'invio delle fatture "
+"all'Agenzia.
Nella modalitá di Test (sperimentale) Odoo manderá le fatture "
+"a un servizio non di produzione. Salvando quest'impostazione fará sì che "
+"tutte le Aziende di questo Database usino questa configurazione. "
+"Una volta registrato per la modalitá Test o Ufficiale, la modalitá non può "
+"più essere cambiata."
+
#. module: l10n_it_edi
#: model:ir.model,name:l10n_it_edi.model_fetchmail_server
msgid "Incoming Mail Server"
@@ -386,11 +461,17 @@ msgstr "Riferimento Fattura"
msgid ""
"Invoices for PA are not managed by Odoo, you can download the document and "
"send it on your own."
-msgstr "Le Fatture verso la PA non sono gestite da Odoo, puoi scaricare il "
-"documento ed inviarlo manualmente."
+msgstr "Le Fatture per la Pubblica Amministrazione non sono gestite da Odoo. "
+"É possibile scaricare il documento e inviarlo tramite il sito dell'Agenzia delle Entrate."
+
+#. module: l10n_it_edi
+#: model:ir.model.fields,field_description:l10n_it_edi.field_res_config_settings__is_edi_proxy_active
+msgid "Is Edi Proxy Active"
+msgstr "É attivo il Proxy EDI"
#. module: l10n_it_edi
#: code:addons/l10n_it_edi/models/account_invoice.py:0
+#: code:addons/l10n_it_edi/models/account_edi_format.py:0
#, python-format
msgid "Italian invoice: %s"
msgstr "Fattura italiana: %s"
@@ -400,6 +481,21 @@ msgstr "Fattura italiana: %s"
msgid "Journal Entry"
msgstr "Movimento Contabile"
+#. module: l10n_it_edi
+#: model:ir.model.fields,field_description:l10n_it_edi.field_res_config_settings__l10n_it_edi_proxy_current_state
+msgid "L10N It Edi Proxy Current State"
+msgstr "Stato corrente del Proxy L10n It EDI"
+
+#. module: l10n_it_edi
+#: model:ir.model.fields,field_description:l10n_it_edi.field_res_config_settings__l10n_it_edi_sdicoop_demo_mode
+msgid "L10N It Edi Sdicoop Demo Mode"
+msgstr "Modalitá demo L10n It EDI Sdicoop"
+
+#. module: l10n_it_edi
+#: model:ir.model.fields,field_description:l10n_it_edi.field_res_config_settings__l10n_it_edi_sdicoop_register
+msgid "L10N It Edi Sdicoop Register"
+msgstr "Registra L10n It EDI Sdicoop"
+
#. module: l10n_it_edi
#: model:ir.model.fields,field_description:l10n_it_edi.field_account_bank_statement_line__l10n_it_einvoice_name
#: model:ir.model.fields,field_description:l10n_it_edi.field_account_move__l10n_it_einvoice_name
@@ -421,13 +517,12 @@ msgstr "Ha rappresentante fiscale"
#: model:ir.model.fields,field_description:l10n_it_edi.field_account_edi_format____last_update
#: model:ir.model.fields,field_description:l10n_it_edi.field_account_move____last_update
#: model:ir.model.fields,field_description:l10n_it_edi.field_account_tax____last_update
-#: model:ir.model.fields,field_description:l10n_it_edi.field_fetchmail_server____last_update
-#: model:ir.model.fields,field_description:l10n_it_edi.field_ir_mail_server____last_update
#: model:ir.model.fields,field_description:l10n_it_edi.field_l10n_it_ddt____last_update
#: model:ir.model.fields,field_description:l10n_it_edi.field_res_company____last_update
+#: model:ir.model.fields,field_description:l10n_it_edi.field_res_config_settings____last_update
#: model:ir.model.fields,field_description:l10n_it_edi.field_res_partner____last_update
msgid "Last Modified on"
-msgstr "Ultima modifica il"
+msgstr "Data Modifica"
#. module: l10n_it_edi
#: model:ir.model.fields,field_description:l10n_it_edi.field_l10n_it_ddt__write_uid
@@ -518,6 +613,11 @@ msgstr "Numero nel Registro delle Imprese"
msgid "Numero DDT"
msgstr "Numero DDT"
+#. module: l10n_it_edi
+#: model:ir.model.fields.selection,name:l10n_it_edi.selection__res_config_settings__l10n_it_edi_sdicoop_demo_mode__prod
+msgid "Official"
+msgstr "Ufficiale"
+
#. module: l10n_it_edi
#: code:addons/l10n_it_edi/models/ir_mail_server.py:0
#, python-format
@@ -586,6 +686,14 @@ msgstr "Per favore, configurare l'email PEC statale \n"
msgid "Please configure Username for this Server PEC"
msgstr "Per favore, configurare il Nome Utente per questo server email PEC"
+#. module: l10n_it_edi
+#: code:addons/l10n_it_edi/models/account_edi_format.py:0
+#, python-format
+msgid ""
+"Please fill your codice fiscale to be able to receive invoices from "
+"FatturaPA"
+msgstr "Per favore, inserire il Codice Fiscale per poter ricevere le fatture da FatturaPA"
+
#. module: l10n_it_edi
#: model:ir.model.fields,help:l10n_it_edi.field_res_company__l10n_it_tax_system
msgid "Please select the Tax system to which you are subjected."
@@ -823,6 +931,109 @@ msgstr "Questa fattura è consegnata e scaduta (è passato il termine "
msgid "This invoice is delivered and refused by destinatory"
msgstr "Questa fattura è consegnata e rifiutata dal destinatario"
+#. module: l10n_it_edi
+#: code:addons/l10n_it_edi/models/account_edi_format.py:0
+#, python-format
+msgid "Service momentarily unavailable"
+msgstr "Servizio momentaneamente non disponibile"
+
+#. module: l10n_it_edi
+#: model:ir.model.fields.selection,name:l10n_it_edi.selection__res_config_settings__l10n_it_edi_sdicoop_demo_mode__test
+msgid "Test (experimental)"
+msgstr "Test (sperimentale)"
+
+#. module: l10n_it_edi
+#: code:addons/l10n_it_edi/models/res_config_settings.py:0
+#, python-format
+msgid ""
+"The company has already registered with the service as 'Test' or 'Official',"
+" it cannot change."
+msgstr "L'Azienda è giá registrata al servizio con la modalitá Test o Officiale, non può essere cambiata."
+
+#. module: l10n_it_edi
+#: code:addons/l10n_it_edi/models/account_edi_format.py:0
+#, python-format
+msgid ""
+"The invoice has been issued, but the delivery to the Addressee has failed. "
+"You will be required to send a courtesy copy of the invoice to your customer"
+" through another channel, outside of the Exchange System, and promptly "
+"notify him that the original is deposited in his personal area on the portal"
+" \"Invoices and Fees\" of the Revenue Agency."
+msgstr "La fattura è stata inviata, ma la consegna al Destinatario è fallita. "
+"É necessario mandare una copia di cortesia della fattura al cliente "
+"tramite un altro canale al di fuori dell'SdI, e notificarlo che l'originale "
+"è depositato nella sua Area Personale all' interno del portale 'Fatture e Corrispettivi' "
+"sul sito dell'Agenzia delle Entrate"
+
+#. module: l10n_it_edi
+#: code:addons/l10n_it_edi/models/account_edi_format.py:0
+#, python-format
+msgid ""
+"The invoice has been issued, but the delivery to the Public Administration "
+"has failed. The Exchange System will contact them to report the problem and "
+"request that they provide a solution. During the following 10 days, the "
+"Exchange System will try to forward the FatturaPA file to the Public "
+"Administration in question again. Should this also fail, the System will "
+"notify Odoo of the failed delivery, and you will be required to send the "
+"invoice to the Administration through another channel, outside of the "
+"Exchange System."
+msgstr "La fattura è stata inviata, ma la consegna alla Pubblica Amministrazione "
+"è fallita. Il Sistema d'Interscambio contatterá il Destinatario per far rapporto "
+"sul problema, e richiederá che venga approntata una soluzione. Durante i "
+"10 giorni successivi, il Sistema d'Interscambio proverá a inoltrare il file "
+"FatturaPA in questione ancora. Dovesse fallire anche questo tentativo, il "
+"sistema notificherá Odoo della mancata consegna, e sará necessario inviare "
+"la fattura tramite un altro canale, al di fuori dell'SdI"
+
+#. module: l10n_it_edi
+#: code:addons/l10n_it_edi/models/account_edi_format.py:0
+#, python-format
+msgid "The invoice has been refused by the Exchange System"
+msgstr "La fattura è stata rifiutata dal Sistema d'Interscambio"
+
+#. module: l10n_it_edi
+#: code:addons/l10n_it_edi/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 "La fattura è stata trasmessa con successo. Il Destinatario ha 15 giorni per accettarla o rifiutarla."
+
+#. module: l10n_it_edi
+#: code:addons/l10n_it_edi/models/account_edi_format.py:0
+#, python-format
+msgid "The invoice was refused by the addressee."
+msgstr "La fattura è stata rifiutata dal Destinatario."
+
+#. module: l10n_it_edi
+#: code:addons/l10n_it_edi/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 "La fattura è stata trasmessa con successo alla Pubblica Amministrazione "
+"e siamo in attesa di conferma."
+
+#. module: l10n_it_edi
+#: code:addons/l10n_it_edi/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 "La fattura è stata inviata con successo alla Pubblica Amministrazione "
+"e siamo in attesa di conferma."
+
+#. module: l10n_it_edi
+#: code:addons/l10n_it_edi/models/account_edi_format.py:0
+#, python-format
+msgid ""
+"This invoice number had already been submitted to the SdI, so it is set as Sent. Please verify that the system is correctly configured, because the correct flow does not need to send the same invoice twice for any reason.\n"
+" Original message from the SDI: %s"
+msgstr "Una fattura con questo numero è giá stata inviata all'SdI, quindi viene impostata come inviata. "
+"Per favore, verificare che il sistema sia configurato correttamente, perchè in nessun caso il sistema "
+"ha motivo di inviare la stessa fattura più volte.\n"
+"Messaggio originale dall'SdI: %s"
+
#. module: l10n_it_edi
#: code:addons/l10n_it_edi/models/account_edi_format.py:0
#, python-format
@@ -851,6 +1062,12 @@ msgstr "Numero Documento Di Trasporto"
msgid "Transport informations from XML file:"
msgstr "Informazioni di Trasporto dal file XML:"
+#. module: l10n_it_edi
+#: code:addons/l10n_it_edi/models/account_edi_format.py:0
+#, python-format
+msgid "Unauthorized user"
+msgstr "Utente non autorizzato"
+
#. module: l10n_it_edi
#: model:ir.model.fields,field_description:l10n_it_edi.field_account_tax__l10n_it_vat_due_date
msgid "VAT due date"
@@ -862,6 +1079,12 @@ msgstr "Data scadenza IVA"
msgid "Vendor not found, useful informations from XML file:"
msgstr "Fornitore non trovato, informazioni dal file XML:"
+#. module: l10n_it_edi
+#: code:addons/l10n_it_edi/models/account_edi_format.py:0
+#, python-format
+msgid "You are not allowed to check the status of this invoice."
+msgstr "Non sei autorizzato a controllare lo stato di questa fattura."
+
#. module: l10n_it_edi
#: code:addons/l10n_it_edi/models/account_edi_format.py:0
#, python-format
@@ -870,6 +1093,16 @@ msgid ""
"no errors"
msgstr "Non puoi rigenerare una Fattura Elettronica se è giá stata inviata senza errori."
+#. module: l10n_it_edi
+#: code:addons/l10n_it_edi/models/account_edi_format.py:0
+#: code:addons/l10n_it_edi/models/account_edi_format.py:0
+#: code:addons/l10n_it_edi/models/account_edi_format.py:0
+#, python-format
+msgid ""
+"You must accept the terms and conditions in the settings to use FatturaPA."
+msgstr "Devi accettare i Termini e le Condizioni d'uso nelle impostazioni "
+"per poter utilizzare FatturaPA."
+
#. module: l10n_it_edi
#: code:addons/l10n_it_edi/models/res_company.py:0
#, python-format
diff --git a/addons/l10n_it_edi/i18n/l10n_it_edi.pot b/addons/l10n_it_edi/i18n/l10n_it_edi.pot
index 418a8d6df17..6f668e4515f 100644
--- a/addons/l10n_it_edi/i18n/l10n_it_edi.pot
+++ b/addons/l10n_it_edi/i18n/l10n_it_edi.pot
@@ -17,18 +17,11 @@ msgstr ""
#. module: l10n_it_edi
#: code:addons/l10n_it_edi/models/account_edi_format.py:0
+#: code:addons/l10n_it_edi/models/account_edi_format.py:0
#, python-format
msgid "%s has an amount of 0.0, you must indicate the kind of exoneration."
msgstr ""
-#. module: l10n_it_edi
-#: code:addons/l10n_it_edi/models/account_invoice.py:0
-#, python-format
-msgid ""
-"%s isn't in a right state. It must be in a 'Not yet send' or 'Invalid' "
-"state."
-msgstr ""
-
#. module: l10n_it_edi
#: code:addons/l10n_it_edi/models/account_edi_format.py:0
#, python-format
@@ -89,6 +82,34 @@ msgid ""
"'Scissione dei pagamenti' is not compatible with exoneration of kind 'N6'"
msgstr ""
+#. module: l10n_it_edi
+#: model_terms:ir.ui.view,arch_db:l10n_it_edi.res_config_settings_view_form
+msgid ""
+"\n"
+" Fattura Elettronica mode\n"
+" "
+msgstr ""
+
+#. module: l10n_it_edi
+#: model_terms:ir.ui.view,arch_db:l10n_it_edi.res_config_settings_view_form
+msgid "Allow Odoo to process invoices"
+msgstr ""
+
+#. module: l10n_it_edi
+#: model_terms:ir.ui.view,arch_db:l10n_it_edi.res_config_settings_view_form
+msgid "A Demo service is in use."
+msgstr ""
+
+#. module: l10n_it_edi
+#: code:addons/l10n_it_edi/models/account_invoice.py:0
+#, python-format
+msgid ""
+"A simplified invoice was created instead of an ordinary one. This is because"
+" the invoice is a domestic invoice with "
+"a total amount of less than or equal to 400€ and the customer's address is "
+"incomplete."
+msgstr ""
+
#. module: l10n_it_edi
#: code:addons/l10n_it_edi/models/res_company.py:0
#, python-format
@@ -96,6 +117,23 @@ msgid ""
"All fields about the Economic and Administrative Index must be completed."
msgstr ""
+#. module: l10n_it_edi
+#: code:addons/l10n_it_edi/models/account_edi_format.py:0
+#, python-format
+msgid "All quantities should be positive."
+msgstr ""
+
+#. module: l10n_it_edi
+#: model_terms:ir.ui.view,arch_db:l10n_it_edi.res_config_settings_view_form
+msgid "An Official or Test service has been registered."
+msgstr ""
+
+#. module: l10n_it_edi
+#: code:addons/l10n_it_edi/models/account_edi_format.py:0
+#, python-format
+msgid "Attached file is empty"
+msgstr ""
+
#. module: l10n_it_edi
#: code:addons/l10n_it_edi/models/account_edi_format.py:0
#, python-format
@@ -109,6 +147,19 @@ msgstr ""
msgid "Bank account not found, useful informations from XML file:"
msgstr ""
+#. module: l10n_it_edi
+#: model_terms:ir.ui.view,arch_db:l10n_it_edi.res_config_settings_view_form
+msgid "By checking this box, I accept that Odoo may process my invoices."
+msgstr ""
+
+#. module: l10n_it_edi
+#: code:addons/l10n_it_edi/models/account_edi_format.py:0
+#, python-format
+msgid ""
+"Cannot apply Reverse Charge to a bill which contains both services and "
+"goods."
+msgstr ""
+
#. module: l10n_it_edi
#: model:ir.model.fields,field_description:l10n_it_edi.field_res_company__l10n_it_codice_fiscale
#: model:ir.model.fields,field_description:l10n_it_edi.field_res_partner__l10n_it_codice_fiscale
@@ -126,11 +177,6 @@ msgstr ""
msgid "Companies"
msgstr ""
-#. module: l10n_it_edi
-#: model:ir.model.fields,field_description:l10n_it_edi.field_res_company__l10n_it_address_send_fatturapa
-msgid "Company PEC-mail"
-msgstr ""
-
#. module: l10n_it_edi
#: model_terms:ir.ui.view,arch_db:l10n_it_edi.res_company_form_l10n_it
msgid "Company have a tax representative"
@@ -142,8 +188,8 @@ msgid "Company listed on the register of companies"
msgstr ""
#. module: l10n_it_edi
-#: model:ir.model.fields,help:l10n_it_edi.field_res_company__l10n_it_mail_pec_server_id
-msgid "Configure your PEC-mail server to send electronic invoices."
+#: model:ir.model,name:l10n_it_edi.model_res_config_settings
+msgid "Config Settings"
msgstr ""
#. module: l10n_it_edi
@@ -182,30 +228,20 @@ msgid "Dati Bollo"
msgstr ""
#. module: l10n_it_edi
-#: model:ir.model.fields.selection,name:l10n_it_edi.selection__account_move__l10n_it_send_state__failed_delivery
-msgid ""
-"Delivery impossible, ES certify that it has received the invoice and that "
-"the file could not be delivered to the addressee"
+#: model:ir.model.fields.selection,name:l10n_it_edi.selection__res_config_settings__l10n_it_edi_sdicoop_demo_mode__demo
+msgid "Demo"
msgstr ""
#. module: l10n_it_edi
#: model:ir.model.fields,field_description:l10n_it_edi.field_account_edi_format__display_name
#: model:ir.model.fields,field_description:l10n_it_edi.field_account_move__display_name
#: model:ir.model.fields,field_description:l10n_it_edi.field_account_tax__display_name
-#: model:ir.model.fields,field_description:l10n_it_edi.field_fetchmail_server__display_name
-#: model:ir.model.fields,field_description:l10n_it_edi.field_ir_mail_server__display_name
#: model:ir.model.fields,field_description:l10n_it_edi.field_l10n_it_ddt__display_name
#: model:ir.model.fields,field_description:l10n_it_edi.field_res_company__display_name
#: model:ir.model.fields,field_description:l10n_it_edi.field_res_partner__display_name
msgid "Display Name"
msgstr ""
-#. module: l10n_it_edi
-#: code:addons/l10n_it_edi/models/ir_mail_server.py:0
-#, python-format
-msgid "E-Invoice is delivery to the destinatory:
%s"
-msgstr ""
-
#. module: l10n_it_edi
#: code:addons/l10n_it_edi/models/account_invoice.py:0
#, python-format
@@ -223,16 +259,13 @@ msgid "EDI format"
msgstr ""
#. module: l10n_it_edi
-#: code:addons/l10n_it_edi/models/ir_mail_server.py:0
-#, python-format
-msgid ""
-"ES certify that it has received the invoice and that the file"
-" could not be delivered to the addressee.
%s"
+#: model_terms:ir.ui.view,arch_db:l10n_it_edi.res_company_form_l10n_it
+msgid "Economic and Administrative Index"
msgstr ""
#. module: l10n_it_edi
-#: model_terms:ir.ui.view,arch_db:l10n_it_edi.res_company_form_l10n_it
-msgid "Economic and Administrative Index"
+#: model_terms:ir.ui.view,arch_db:l10n_it_edi.res_config_settings_view_form
+msgid "Electronic Document Invoicing"
msgstr ""
#. module: l10n_it_edi
@@ -248,36 +281,6 @@ msgstr ""
msgid "Electronic invoice"
msgstr ""
-#. module: l10n_it_edi
-#: model:ir.model.fields,help:l10n_it_edi.field_res_company__l10n_it_address_recipient_fatturapa
-msgid "Enter Government PEC-mail address. Ex: sdi01@pec.fatturapa.it"
-msgstr ""
-
-#. module: l10n_it_edi
-#: model:ir.model.fields,help:l10n_it_edi.field_res_company__l10n_it_address_send_fatturapa
-msgid "Enter your company PEC-mail address. Ex: yourcompany@pec.mail.it"
-msgstr ""
-
-#. module: l10n_it_edi
-#: code:addons/l10n_it_edi/models/account_invoice.py:0
-#, python-format
-msgid "Error when sending mail with E-Invoice: %s"
-msgstr ""
-
-#. module: l10n_it_edi
-#: code:addons/l10n_it_edi/models/account_invoice.py:0
-#, python-format
-msgid ""
-"Error when sending mail with E-Invoice: Your company must have a mail PEC "
-"server and must indicate the mail PEC that will send electronic invoice."
-msgstr ""
-
-#. module: l10n_it_edi
-#: code:addons/l10n_it_edi/models/ir_mail_server.py:0
-#, python-format
-msgid "Errors in the E-Invoice :
%s"
-msgstr ""
-
#. module: l10n_it_edi
#: model:ir.model.fields,field_description:l10n_it_edi.field_account_tax__l10n_it_kind_exoneration
msgid "Exoneration"
@@ -289,18 +292,24 @@ msgid "Exoneration type"
msgstr ""
#. module: l10n_it_edi
-#: code:addons/l10n_it_edi/models/ir_mail_server.py:0
-#, python-format
-msgid ""
-"Expiration of the maximum term for communication of acceptance/refusal:"
-" %s
%s"
+#: model:ir.model.fields,field_description:l10n_it_edi.field_account_bank_statement_line__l10n_it_edi_attachment_id
+#: model:ir.model.fields,field_description:l10n_it_edi.field_account_move__l10n_it_edi_attachment_id
+#: model:ir.model.fields,field_description:l10n_it_edi.field_account_payment__l10n_it_edi_attachment_id
+msgid "FatturaPA Attachment"
msgstr ""
#. module: l10n_it_edi
-#: model:ir.model.fields,field_description:l10n_it_edi.field_account_bank_statement_line__l10n_it_send_state
-#: model:ir.model.fields,field_description:l10n_it_edi.field_account_move__l10n_it_send_state
-#: model:ir.model.fields,field_description:l10n_it_edi.field_account_payment__l10n_it_send_state
-msgid "FatturaPA Send State"
+#: model:ir.model.fields,field_description:l10n_it_edi.field_account_bank_statement_line__l10n_it_edi_transaction
+#: model:ir.model.fields,field_description:l10n_it_edi.field_account_move__l10n_it_edi_transaction
+#: model:ir.model.fields,field_description:l10n_it_edi.field_account_payment__l10n_it_edi_transaction
+msgid "FatturaPA Transaction"
+msgstr ""
+
+#. module: l10n_it_edi
+#: model:ir.actions.server,name:l10n_it_edi.ir_cron_receive_fattura_pa_invoice_ir_actions_server
+#: model:ir.cron,cron_name:l10n_it_edi.ir_cron_receive_fattura_pa_invoice
+#: model:ir.cron,name:l10n_it_edi.ir_cron_receive_fattura_pa_invoice
+msgid "FatturaPA: Receive invoices from the exchange system"
msgstr ""
#. module: l10n_it_edi
@@ -308,11 +317,6 @@ msgstr ""
msgid "Fiscal code of your company"
msgstr ""
-#. module: l10n_it_edi
-#: model:ir.model.fields,field_description:l10n_it_edi.field_res_company__l10n_it_address_recipient_fatturapa
-msgid "Government PEC-mail"
-msgstr ""
-
#. module: l10n_it_edi
#: model:ir.model.fields,field_description:l10n_it_edi.field_account_tax__l10n_it_has_exoneration
msgid "Has exoneration of tax (Italy)"
@@ -335,12 +339,6 @@ msgstr ""
msgid "INTERNAL"
msgstr ""
-#. module: l10n_it_edi
-#: model:ir.model.fields,help:l10n_it_edi.field_fetchmail_server__l10n_it_is_pec
-msgid ""
-"If PEC Server, only mail from '...@pec.fatturapa.it' will be processed."
-msgstr ""
-
#. module: l10n_it_edi
#: code:addons/l10n_it_edi/models/account_invoice.py:0
#, python-format
@@ -350,8 +348,18 @@ msgid ""
msgstr ""
#. module: l10n_it_edi
-#: model:ir.model,name:l10n_it_edi.model_fetchmail_server
-msgid "Incoming Mail Server"
+#: model_terms:ir.ui.view,arch_db:l10n_it_edi.res_config_settings_view_form
+msgid ""
+"In demo mode Odoo will just simulate the sending of invoices to the government.
\n"
+" In test mode (experimental) Odoo will send the invoices to a non-production service.\n"
+" Saving this change will direct all companies on this database to this use this configuration.\n"
+" Once registered for testing or official, the mode cannot be changed."
+msgstr ""
+
+#. module: l10n_it_edi
+#: code:addons/l10n_it_edi/models/account_edi_format.py:0
+#, python-format
+msgid "In line %s, you must select one and only one tax by line."
msgstr ""
#. module: l10n_it_edi
@@ -362,12 +370,6 @@ msgid ""
"person and '12345678901' or 'IT12345678901' for businesses."
msgstr ""
-#. module: l10n_it_edi
-#: code:addons/l10n_it_edi/models/account_invoice.py:0
-#, python-format
-msgid "Invalid configuration:"
-msgstr ""
-
#. module: l10n_it_edi
#: model:ir.model.fields,field_description:l10n_it_edi.field_l10n_it_ddt__invoice_id
msgid "Invoice Reference"
@@ -382,6 +384,12 @@ msgid ""
msgstr ""
#. module: l10n_it_edi
+#: model:ir.model.fields,field_description:l10n_it_edi.field_res_config_settings__is_edi_proxy_active
+msgid "Is Edi Proxy Active"
+msgstr ""
+
+#. module: l10n_it_edi
+#: code:addons/l10n_it_edi/models/account_edi_format.py:0
#: code:addons/l10n_it_edi/models/account_invoice.py:0
#, python-format
msgid "Italian invoice: %s"
@@ -392,6 +400,21 @@ msgstr ""
msgid "Journal Entry"
msgstr ""
+#. module: l10n_it_edi
+#: model:ir.model.fields,field_description:l10n_it_edi.field_res_config_settings__l10n_it_edi_proxy_current_state
+msgid "L10N It Edi Proxy Current State"
+msgstr ""
+
+#. module: l10n_it_edi
+#: model:ir.model.fields,field_description:l10n_it_edi.field_res_config_settings__l10n_it_edi_sdicoop_demo_mode
+msgid "L10N It Edi Sdicoop Demo Mode"
+msgstr ""
+
+#. module: l10n_it_edi
+#: model:ir.model.fields,field_description:l10n_it_edi.field_res_config_settings__l10n_it_edi_sdicoop_register
+msgid "L10N It Edi Sdicoop Register"
+msgstr ""
+
#. module: l10n_it_edi
#: model:ir.model.fields,field_description:l10n_it_edi.field_account_bank_statement_line__l10n_it_einvoice_name
#: model:ir.model.fields,field_description:l10n_it_edi.field_account_move__l10n_it_einvoice_name
@@ -413,8 +436,6 @@ msgstr ""
#: model:ir.model.fields,field_description:l10n_it_edi.field_account_edi_format____last_update
#: model:ir.model.fields,field_description:l10n_it_edi.field_account_move____last_update
#: model:ir.model.fields,field_description:l10n_it_edi.field_account_tax____last_update
-#: model:ir.model.fields,field_description:l10n_it_edi.field_fetchmail_server____last_update
-#: model:ir.model.fields,field_description:l10n_it_edi.field_ir_mail_server____last_update
#: model:ir.model.fields,field_description:l10n_it_edi.field_l10n_it_ddt____last_update
#: model:ir.model.fields,field_description:l10n_it_edi.field_res_company____last_update
#: model:ir.model.fields,field_description:l10n_it_edi.field_res_partner____last_update
@@ -431,11 +452,6 @@ msgstr ""
msgid "Last Updated on"
msgstr ""
-#. module: l10n_it_edi
-#: model:ir.model.fields,field_description:l10n_it_edi.field_fetchmail_server__l10n_it_last_uid
-msgid "Last message UID"
-msgstr ""
-
#. module: l10n_it_edi
#: model:ir.model.fields,field_description:l10n_it_edi.field_account_tax__l10n_it_law_reference
msgid "Law Reference"
@@ -451,17 +467,6 @@ msgstr ""
msgid "MP05"
msgstr ""
-#. module: l10n_it_edi
-#: model:ir.model,name:l10n_it_edi.model_ir_mail_server
-msgid "Mail Server"
-msgstr ""
-
-#. module: l10n_it_edi
-#: code:addons/l10n_it_edi/models/account_invoice.py:0
-#, python-format
-msgid "Mail sent on %s by %s"
-msgstr ""
-
#. module: l10n_it_edi
#: model:ir.model.fields,help:l10n_it_edi.field_res_company__l10n_it_eco_index_share_capital
msgid ""
@@ -481,21 +486,11 @@ msgid ""
"invoice."
msgstr ""
-#. module: l10n_it_edi
-#: model:ir.model.fields.selection,name:l10n_it_edi.selection__account_move__l10n_it_send_state__new
-msgid "New"
-msgstr ""
-
#. module: l10n_it_edi
#: model:ir.model.fields.selection,name:l10n_it_edi.selection__res_company__l10n_it_eco_index_sole_shareholder__no
msgid "Not a limited liability company"
msgstr ""
-#. module: l10n_it_edi
-#: model:ir.model.fields.selection,name:l10n_it_edi.selection__account_move__l10n_it_send_state__to_send
-msgid "Not yet send"
-msgstr ""
-
#. module: l10n_it_edi
#: model:ir.model.fields,field_description:l10n_it_edi.field_res_company__l10n_it_eco_index_number
msgid "Number in register of companies"
@@ -507,20 +502,8 @@ msgid "Numero DDT"
msgstr ""
#. module: l10n_it_edi
-#: code:addons/l10n_it_edi/models/ir_mail_server.py:0
-#, python-format
-msgid "Original E-invoice XML file"
-msgstr ""
-
-#. module: l10n_it_edi
-#: model:ir.model.fields.selection,name:l10n_it_edi.selection__account_move__l10n_it_send_state__other
-msgid "Other"
-msgstr ""
-
-#. module: l10n_it_edi
-#: code:addons/l10n_it_edi/models/ir_mail_server.py:0
-#, python-format
-msgid "Outcome notice: %s
%s"
+#: model:ir.model.fields.selection,name:l10n_it_edi.selection__res_config_settings__l10n_it_edi_sdicoop_demo_mode__prod
+msgid "Official"
msgstr ""
#. module: l10n_it_edi
@@ -536,6 +519,7 @@ msgstr ""
#. module: l10n_it_edi
#: model_terms:ir.ui.view,arch_db:l10n_it_edi.account_invoice_it_FatturaPA_export
+#: model_terms:ir.ui.view,arch_db:l10n_it_edi.account_invoice_it_simplified_FatturaPA_export
msgid "PDF"
msgstr ""
@@ -545,32 +529,17 @@ msgstr ""
msgid "PEC e-mail"
msgstr ""
-#. module: l10n_it_edi
-#: code:addons/l10n_it_edi/models/ir_mail_server.py:0
-#, python-format
-msgid "PEC mail server must be of type IMAP."
-msgstr ""
-
-#. module: l10n_it_edi
-#: model:ir.model.fields,field_description:l10n_it_edi.field_fetchmail_server__l10n_it_is_pec
-msgid "PEC server"
-msgstr ""
-
#. module: l10n_it_edi
#: model:ir.model.fields.selection,name:l10n_it_edi.selection__res_company__l10n_it_eco_index_sole_shareholder__sm
msgid "Più soci"
msgstr ""
#. module: l10n_it_edi
-#: code:addons/l10n_it_edi/models/ir_mail_server.py:0
+#: code:addons/l10n_it_edi/models/account_edi_format.py:0
#, python-format
-msgid "Please configure Government PEC-mail\tin company settings"
-msgstr ""
-
-#. module: l10n_it_edi
-#: code:addons/l10n_it_edi/models/ir_mail_server.py:0
-#, python-format
-msgid "Please configure Username for this Server PEC"
+msgid ""
+"Please fill your codice fiscale to be able to receive invoices from "
+"FatturaPA"
msgstr ""
#. module: l10n_it_edi
@@ -589,30 +558,9 @@ msgid "SI"
msgstr ""
#. module: l10n_it_edi
-#: code:addons/l10n_it_edi/models/account_invoice.py:0
+#: code:addons/l10n_it_edi/models/account_edi_format.py:0
#, python-format
-msgid "Sending file: %s"
-msgstr ""
-
-#. module: l10n_it_edi
-#: code:addons/l10n_it_edi/models/account_invoice.py:0
-#, python-format
-msgid "Sending file: %s to ES: %s"
-msgstr ""
-
-#. module: l10n_it_edi
-#: model:ir.model.fields.selection,name:l10n_it_edi.selection__account_move__l10n_it_send_state__invalid
-msgid "Sent, but invalid"
-msgstr ""
-
-#. module: l10n_it_edi
-#: model:ir.model.fields.selection,name:l10n_it_edi.selection__account_move__l10n_it_send_state__sent
-msgid "Sent, waiting for response"
-msgstr ""
-
-#. module: l10n_it_edi
-#: model:ir.model.fields,field_description:l10n_it_edi.field_res_company__l10n_it_mail_pec_server_id
-msgid "Server PEC"
+msgid "Service momentarily unavailable"
msgstr ""
#. module: l10n_it_edi
@@ -685,24 +633,24 @@ msgid "Tax representative partner %s of %s must have a tax number."
msgstr ""
#. module: l10n_it_edi
-#: code:addons/l10n_it_edi/models/ir_mail_server.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. More "
-"information:
%s"
+#: model:ir.model.fields.selection,name:l10n_it_edi.selection__res_config_settings__l10n_it_edi_sdicoop_demo_mode__test
+msgid "Test (experimental)"
msgstr ""
#. module: l10n_it_edi
#: code:addons/l10n_it_edi/models/account_edi_format.py:0
#, python-format
msgid ""
-"The buyer, %s, or his company must have either a VAT number either a tax "
-"code (Codice Fiscale)."
+"The buyer, %s, or his company must have a VAT number and/or a tax code "
+"(Codice Fiscale)."
+msgstr ""
+
+#. module: l10n_it_edi
+#: code:addons/l10n_it_edi/models/res_config_settings.py:0
+#, python-format
+msgid ""
+"The company has already registered with the service as 'Test' or 'Official',"
+" it cannot change."
msgstr ""
#. module: l10n_it_edi
@@ -719,13 +667,69 @@ msgstr ""
#: code:addons/l10n_it_edi/models/account_edi_format.py:0
#, python-format
msgid ""
-"The maximum length for VAT number is 30. %s have a VAT number too long: %s."
+"The filename is duplicated. Try again (or adjust the FatturaPA Filename "
+"sequence). Original message from the SDI: %s"
msgstr ""
#. module: l10n_it_edi
#: code:addons/l10n_it_edi/models/account_edi_format.py:0
#, python-format
-msgid "The seller must have a bank account."
+msgid ""
+"The invoice has been issued, but the delivery to the Addressee has failed. "
+"You will be required to send a courtesy copy of the invoice to your customer"
+" through another channel, outside of the Exchange System, and promptly "
+"notify him that the original is deposited in his personal area on the portal"
+" \"Invoices and Fees\" of the Revenue Agency."
+msgstr ""
+
+#. module: l10n_it_edi
+#: code:addons/l10n_it_edi/models/account_edi_format.py:0
+#, python-format
+msgid ""
+"The invoice has been issued, but the delivery to the Public Administration "
+"has failed. The Exchange System will contact them to report the problem and "
+"request that they provide a solution. During the following 10 days, the "
+"Exchange System will try to forward the FatturaPA file to the Public "
+"Administration in question again. Should this also fail, the System will "
+"notify Odoo of the failed delivery, and you will be required to send the "
+"invoice to the Administration through another channel, outside of the "
+"Exchange System."
+msgstr ""
+
+#. module: l10n_it_edi
+#: code:addons/l10n_it_edi/models/account_edi_format.py:0
+#, python-format
+msgid "The invoice has been refused by the Exchange System"
+msgstr ""
+
+#. module: l10n_it_edi
+#: code:addons/l10n_it_edi/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
+#: code:addons/l10n_it_edi/models/account_edi_format.py:0
+#, python-format
+msgid "The invoice was refused by the addressee."
+msgstr ""
+
+#. module: l10n_it_edi
+#: code:addons/l10n_it_edi/models/account_edi_format.py:0
+#: code:addons/l10n_it_edi/models/account_edi_format.py:0
+#, python-format
+msgid ""
+"The invoice was sent to FatturaPA, but we are still awaiting a response. "
+"Click the link above to check for an update."
+msgstr ""
+
+#. module: l10n_it_edi
+#: code:addons/l10n_it_edi/models/account_edi_format.py:0
+#, python-format
+msgid ""
+"The maximum length for VAT number is 30. %s have a VAT number too long: %s."
msgstr ""
#. module: l10n_it_edi
@@ -773,25 +777,11 @@ msgid ""
msgstr ""
#. module: l10n_it_edi
-#: model:ir.model.fields.selection,name:l10n_it_edi.selection__account_move__l10n_it_send_state__delivered
-msgid "This invoice is delivered"
-msgstr ""
-
-#. module: l10n_it_edi
-#: model:ir.model.fields.selection,name:l10n_it_edi.selection__account_move__l10n_it_send_state__delivered_accepted
-msgid "This invoice is delivered and accepted by destinatory"
-msgstr ""
-
-#. module: l10n_it_edi
-#: model:ir.model.fields.selection,name:l10n_it_edi.selection__account_move__l10n_it_send_state__delivered_expired
+#: code:addons/l10n_it_edi/models/account_edi_format.py:0
+#, python-format
msgid ""
-"This invoice is delivered and expired (expiry of the maximum term for "
-"communication of acceptance/refusal)"
-msgstr ""
-
-#. module: l10n_it_edi
-#: model:ir.model.fields.selection,name:l10n_it_edi.selection__account_move__l10n_it_send_state__delivered_refused
-msgid "This invoice is delivered and refused by destinatory"
+"This invoice number had already been submitted to the SdI, so it is set as Sent. Please verify that the system is correctly configured, because the correct flow does not need to send the same invoice twice for any reason.\n"
+" Original message from the SDI: %s"
msgstr ""
#. module: l10n_it_edi
@@ -822,11 +812,25 @@ msgstr ""
msgid "Transport informations from XML file:"
msgstr ""
+#. module: l10n_it_edi
+#: code:addons/l10n_it_edi/models/account_edi_format.py:0
+#, python-format
+msgid "Unauthorized user"
+msgstr ""
+
#. module: l10n_it_edi
#: model:ir.model.fields,field_description:l10n_it_edi.field_account_tax__l10n_it_vat_due_date
msgid "VAT due date"
msgstr ""
+#. module: l10n_it_edi
+#: code:addons/l10n_it_edi/models/account_edi_format.py:0
+#, python-format
+msgid ""
+"Vendor bills sent as self-invoices to the SdI require a valid PA Index "
+"(Codice Destinatario) on the company's contact."
+msgstr ""
+
#. module: l10n_it_edi
#: code:addons/l10n_it_edi/models/account_edi_format.py:0
#, python-format
@@ -836,9 +840,16 @@ msgstr ""
#. module: l10n_it_edi
#: code:addons/l10n_it_edi/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
+#: code:addons/l10n_it_edi/models/account_edi_format.py:0
+#: code:addons/l10n_it_edi/models/account_edi_format.py:0
+#: code:addons/l10n_it_edi/models/account_edi_format.py:0
+#, python-format
msgid ""
-"You can't regenerate an E-Invoice when the first one is sent and there are "
-"no errors"
+"You must accept the terms and conditions in the settings to use FatturaPA."
msgstr ""
#. module: l10n_it_edi
@@ -847,12 +858,6 @@ msgstr ""
msgid "You must select a tax representative."
msgstr ""
-#. module: l10n_it_edi
-#: code:addons/l10n_it_edi/models/account_edi_format.py:0
-#, python-format
-msgid "You must select one and only one tax by line."
-msgstr ""
-
#. module: l10n_it_edi
#: code:addons/l10n_it_edi/models/res_company.py:0
#, python-format
diff --git a/addons/l10n_it_edi/models/__init__.py b/addons/l10n_it_edi/models/__init__.py
index 703ed068a9a..0465baacd14 100644
--- a/addons/l10n_it_edi/models/__init__.py
+++ b/addons/l10n_it_edi/models/__init__.py
@@ -3,8 +3,8 @@
from . import res_partner
from . import res_company
+from . import res_config_settings
from . import account_invoice
from . import account_edi_format
-from . import ir_mail_server
from . import ddt
from . import mail_template
diff --git a/addons/l10n_it_edi/models/account_edi_format.py b/addons/l10n_it_edi/models/account_edi_format.py
index 9838cffe7e7..bcfee240055 100644
--- a/addons/l10n_it_edi/models/account_edi_format.py
+++ b/addons/l10n_it_edi/models/account_edi_format.py
@@ -1,7 +1,9 @@
# -*- coding:utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
-from odoo import api, models, fields, _
+from odoo import api, models, fields, _, _lt
+from odoo.exceptions import UserError
+from odoo.addons.account_edi_proxy_client.models.account_edi_proxy_user import AccountEdiProxyError
from odoo.addons.l10n_it_edi.tools.remove_signature import remove_signature
from odoo.osv.expression import OR, AND
@@ -9,6 +11,7 @@ from lxml import etree
from datetime import datetime
import re
import logging
+import base64
_logger = logging.getLogger(__name__)
@@ -264,74 +267,71 @@ class AccountEdiFormat(models.Model):
def _l10n_it_is_simplified_document_type(self, document_type):
return self._l10n_it_document_type_mapping().get(document_type, {}).get('simplified', False)
- # -------------------------------------------------------------------------
- # Export
- # -------------------------------------------------------------------------
-
- def _prepare_invoice_report(self, pdf_writer, edi_document):
- self.ensure_one()
- if self.code != 'fattura_pa':
- return super()._prepare_invoice_report(pdf_writer, edi_document)
- if edi_document.attachment_id:
- pdf_writer.embed_odoo_attachment(edi_document.attachment_id)
-
- def _is_compatible_with_journal(self, journal):
- # OVERRIDE
- self.ensure_one()
- if self.code != 'fattura_pa':
- return super()._is_compatible_with_journal(journal)
- return journal.type in ('sale', 'purchase') and journal.country_code == 'IT'
-
- def _l10n_it_edi_is_required_for_invoice(self, invoice):
- """ Is the edi required for this invoice based on the method (here: PEC mail)
- Deprecated: in future release PEC mail will be removed.
- TO OVERRIDE
- """
- return ((invoice.is_sale_document() or self._l10n_it_get_document_type(invoice))
- and invoice.country_code == 'IT'
- and invoice.l10n_it_send_state not in ('sent', 'delivered', 'delivered_accepted'))
-
- def _is_required_for_invoice(self, invoice):
- # OVERRIDE
- self.ensure_one()
- if self.code != 'fattura_pa':
- return super()._is_required_for_invoice(invoice)
-
- return self._l10n_it_edi_is_required_for_invoice(invoice)
-
- def _post_fattura_pa(self, invoices):
- # TO OVERRIDE
- invoice = invoices # no batching ensure that we only have one invoice
- invoice.l10n_it_send_state = 'other'
- invoice._check_before_xml_exporting()
- if invoice.l10n_it_einvoice_id and invoice.l10n_it_send_state not in ['invalid', 'to_send']:
- return {'error': _("You can't regenerate an E-Invoice when the first one is sent and there are no errors")}
- if invoice.l10n_it_einvoice_id:
- invoice.l10n_it_einvoice_id.unlink()
- res = invoice.invoice_generate_xml()
- if invoice._is_commercial_partner_pa():
- invoice.message_post(
- body=(_("Invoices for PA are not managed by Odoo, you can download the document and send it on your own."))
- )
- else:
- invoice.l10n_it_send_state = 'to_send'
- if 'attachment' in res:
- res['success'] = True
- return {invoice: res}
-
- def _post_invoice_edi(self, invoices, test_mode=False):
- # OVERRIDE
- self.ensure_one()
- edi_result = super()._post_invoice_edi(invoices)
- if self.code != 'fattura_pa':
- return edi_result
-
- return self._post_fattura_pa(invoices)
-
# -------------------------------------------------------------------------
# Import
# -------------------------------------------------------------------------
+ def _cron_receive_fattura_pa(self):
+ ''' Check the proxy for incoming invoices.
+ '''
+ proxy_users = self.env['account_edi_proxy_client.user'].search([('edi_format_id', '=', self.env.ref('l10n_it_edi.edi_fatturaPA').id)])
+
+ if proxy_users._get_demo_state() == 'demo':
+ return
+
+ for proxy_user in proxy_users:
+ company = proxy_user.company_id
+ try:
+ res = proxy_user._make_request(proxy_user._get_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 exists: %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['account.move'].with_company(company).create({'move_type': 'in_invoice'})
+ attachment = self.env['ir.attachment'].create({
+ 'name': fattura['filename'],
+ 'raw': file,
+ 'type': 'binary',
+ 'res_model': 'account.move',
+ 'res_id': invoice.id
+ })
+ if not self.env.context.get('test_skip_commit'):
+ self.env.cr.commit() # In case something fails after, we still have the attachment
+ # So that we don't delete the attachment when deleting the invoice
+ attachment.res_id = False
+ attachment.res_model = False
+ invoice.unlink()
+ invoice = self.env.ref('l10n_it_edi.edi_fatturaPA')._create_invoice_from_xml_tree(fattura['filename'], tree)
+ attachment.write({'res_model': 'account.move',
+ 'res_id': invoice.id})
+ proxy_acks.append(id_transaction)
+ if not self.env.context.get('test_skip_commit'):
+ self.env.cr.commit()
+
+
+ if proxy_acks:
+ try:
+ proxy_user._make_request(proxy_user._get_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)
+
def _check_filename_is_fattura_pa(self, filename):
return re.search("([A-Z]{2}[A-Za-z0-9]{2,28}_[A-Za-z0-9]{0,5}.(xml.p7m|xml))", filename)
@@ -747,7 +747,6 @@ class AccountEdiFormat(models.Model):
invoice_line_global_discount.price_unit = general_discount
new_invoice = invoice_form
- new_invoice.l10n_it_send_state = "other"
elements = body_tree.xpath('.//Allegati')
if elements:
@@ -775,3 +774,315 @@ class AccountEdiFormat(models.Model):
invoices += new_invoice
return invoices
+
+ # -------------------------------------------------------------------------
+ # Export
+ # -------------------------------------------------------------------------
+
+ def _prepare_invoice_report(self, pdf_writer, edi_document):
+ self.ensure_one()
+ if self.code != 'fattura_pa':
+ return super()._prepare_invoice_report(pdf_writer, edi_document)
+ if edi_document.attachment_id:
+ pdf_writer.embed_odoo_attachment(edi_document.attachment_id)
+
+ def _is_compatible_with_journal(self, journal):
+ # OVERRIDE
+ self.ensure_one()
+ if self.code != 'fattura_pa':
+ return super()._is_compatible_with_journal(journal)
+ return journal.type in ('sale', 'purchase') and journal.country_code == 'IT'
+
+ def _is_required_for_invoice(self, invoice):
+ # OVERRIDE
+ self.ensure_one()
+ if self.code != 'fattura_pa':
+ return super()._is_required_for_invoice(invoice)
+
+ is_self_invoice = self._l10n_it_edi_is_self_invoice(invoice)
+ return (
+ (invoice.is_sale_document() or (is_self_invoice and invoice.is_purchase_document()))
+ and invoice.country_code == 'IT'
+ )
+
+ def _export_as_xml(self, invoice):
+ ''' Create the xml file content.
+ :return: The XML content as str.
+ '''
+ template_values = invoice._prepare_fatturapa_export_values()
+ if not self._l10n_it_is_simplified_document_type(template_values['document_type']):
+ content = self.env['ir.qweb']._render('l10n_it_edi.account_invoice_it_FatturaPA_export', template_values)
+ else:
+ content = self.env['ir.qweb']._render('l10n_it_edi.account_invoice_it_simplified_FatturaPA_export', template_values)
+ invoice.message_post(body=_(
+ "A simplified invoice was created instead of an ordinary one. This is because the invoice \
+ is a domestic invoice with a total amount of less than or equal to 400€ and the customer's address is incomplete."
+ ))
+ return content
+
+ def _get_invoice_edi_content(self, move):
+ #OVERRIDE
+ if self.code != 'fattura_pa':
+ return super()._get_invoice_edi_content(move)
+ return self._export_as_xml(move)
+
+ 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 _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 _get_batch_key(self, move, state):
+ # OVERRIDE
+ if self.code != 'fattura_pa':
+ return super()._get_batch_key(move, state)
+
+ return move.move_type, bool(move.l10n_it_edi_transaction)
+
+ def _l10n_it_post_invoices_step_1(self, invoices):
+ ''' Send the invoices to the proxy.
+ '''
+ to_return = {}
+
+ to_send = {}
+ for invoice in invoices:
+ xml = "" + str(self._export_as_xml(invoice))
+ 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,
+ 'raw': xml.encode(),
+ 'description': _('Italian invoice: %s', invoice.move_type),
+ 'type': 'binary',
+ })
+ invoice.l10n_it_edi_attachment_id = attachment
+
+ if invoice._is_commercial_partner_pa():
+ 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, 'success': True}
+ else:
+ to_send[filename] = {
+ 'invoice': invoice,
+ 'data': {'filename': filename, 'xml': base64.b64encode(xml.encode()).decode()}}
+
+ 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}
+
+ responses = {}
+ if proxy_user._get_demo_state() == 'demo':
+ responses = {i['data']['filename']: {'id_transaction': 'demo'} for i in to_send.values()}
+ 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 sent to FatturaPA, but we are still awaiting a response. Click the link above to check for an update.'),
+ '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 proxy_user._get_demo_state() == 'demo':
+ # 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(proxy_user._get_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 sent to FatturaPA, but we are still awaiting a response. Click the link above to check for an update.'),
+ 'blocking_level': 'info',
+ }
+ 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
+
+ if not response.get('file'): # It means there is no status update, so we can skip it
+ document = invoice.edi_document_ids.filtered(lambda d: d.edi_format_id.code == 'fattura_pa')
+ to_return[invoice] = {'error': document.error, 'blocking_level': document.blocking_level}
+ continue
+ xml = proxy_user._decrypt_data(response['file'], response['key'])
+ response_tree = etree.fromstring(xml)
+ if state == 'ricevutaConsegna':
+ if invoice._is_commercial_partner_pa():
+ to_return[invoice] = {'error': _('The invoice has been succesfully transmitted. The addressee has 15 days to accept or reject it.')}
+ else:
+ to_return[invoice] = {'attachment': invoice.l10n_it_edi_attachment_id, 'success': True}
+ elif state == 'notificaScarto':
+ elements = response_tree.xpath('//Errore')
+ error_codes = [element.find('Codice').text for element in elements]
+ errors = [element.find('Descrizione').text for element in elements]
+ # Duplicated invoice
+ if '00404' in error_codes:
+ idx = error_codes.index('00404')
+ invoice.message_post(body=_(
+ 'This invoice number had already been submitted to the SdI, so it is'
+ ' set as Sent. Please verify that the system is correctly configured,'
+ ' because the correct flow does not need to send the same invoice'
+ ' twice for any reason.\n'
+ ' Original message from the SDI: %s', errors[idx]))
+ to_return[invoice] = {'attachment': invoice.l10n_it_edi_attachment_id, 'success': True}
+ else:
+ # Add helpful text if duplicated filename error
+ if '00002' in error_codes:
+ idx = error_codes.index('00002')
+ errors[idx] = _(
+ 'The filename is duplicated. Try again (or adjust the FatturaPA Filename sequence).'
+ ' Original message from the SDI: %s', [errors[idx]]
+ )
+ to_return[invoice] = {'error': self._format_error_message(_('The invoice has been refused by the Exchange System'), errors), 'blocking_level': 'error'}
+ invoice.l10n_it_edi_transaction = False
+ elif state == 'notificaMancataConsegna':
+ if invoice._is_commercial_partner_pa():
+ to_return[invoice] = {'error': _(
+ 'The invoice has been issued, but the delivery to the Public Administration'
+ ' has failed. The Exchange System will contact them to report the problem'
+ ' and request that they provide a solution.'
+ ' During the following 10 days, the Exchange System will try to forward the'
+ ' FatturaPA file to the Public Administration in question again.'
+ ' Should this also fail, the System will notify Odoo of the failed delivery,'
+ ' and you will be required to send the invoice to the Administration'
+ ' through another channel, outside of the Exchange System.')}
+ else:
+ to_return[invoice] = {'success': True, 'attachment': invoice.l10n_it_edi_attachment_id}
+ invoice._message_log(body=_(
+ 'The invoice has been issued, but the delivery to the Addressee has'
+ ' failed. You will be required to send a courtesy copy of the invoice'
+ ' to your customer through another channel, outside of the Exchange'
+ ' System, and promptly notify him that the original is deposited'
+ ' in his personal area on the portal "Invoices and Fees" of the'
+ ' Revenue Agency.'))
+ elif state == 'notificaEsito':
+ outcome = response_tree.find('Esito').text
+ if outcome == 'EC01':
+ to_return[invoice] = {'attachment': invoice.l10n_it_edi_attachment_id, 'success': True}
+ else: # ECO2
+ to_return[invoice] = {'error': _('The invoice was refused by the addressee.'), 'blocking_level': 'error'}
+ elif state == 'NotificaDecorrenzaTermini':
+ to_return[invoice] = {'attachment': invoice.l10n_it_edi_attachment_id, 'success': True}
+ proxy_acks.append(id_transaction)
+
+ if proxy_acks:
+ try:
+ proxy_user._make_request(proxy_user._get_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[0].l10n_it_edi_transaction:
+ return self._l10n_it_post_invoices_step_1(invoices)
+ else:
+ return self._l10n_it_post_invoices_step_2(invoices)
+
+ def _post_invoice_edi(self, invoices, test_mode=False):
+ # OVERRIDE
+ self.ensure_one()
+ edi_result = super()._post_invoice_edi(invoices)
+ if self.code != 'fattura_pa':
+ return edi_result
+
+ return self._post_fattura_pa(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'},
+ }
+
+ if not files:
+ return {}
+
+ result = proxy_user._make_request(proxy_user._get_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/models/account_invoice.py b/addons/l10n_it_edi/models/account_invoice.py
index b8e37467fb8..90509276bcd 100644
--- a/addons/l10n_it_edi/models/account_invoice.py
+++ b/addons/l10n_it_edi/models/account_invoice.py
@@ -10,7 +10,9 @@ from datetime import datetime
from odoo import api, fields, models, _
from odoo.tools import float_repr, float_compare
from odoo.exceptions import UserError, ValidationError
-from odoo.addons.base.models.ir_mail_server import MailDeliveryException
+
+
+_logger = logging.getLogger(__name__)
DEFAULT_FACTUR_ITALIAN_DATE_FORMAT = '%Y-%m-%d'
@@ -18,19 +20,8 @@ DEFAULT_FACTUR_ITALIAN_DATE_FORMAT = '%Y-%m-%d'
class AccountMove(models.Model):
_inherit = 'account.move'
- l10n_it_send_state = fields.Selection([
- ('new', 'New'),
- ('other', 'Other'),
- ('to_send', 'Not yet send'),
- ('sent', 'Sent, waiting for response'),
- ('invalid', 'Sent, but invalid'),
- ('delivered', 'This invoice is delivered'),
- ('delivered_accepted', 'This invoice is delivered and accepted by destinatory'),
- ('delivered_refused', 'This invoice is delivered and refused by destinatory'),
- ('delivered_expired', 'This invoice is delivered and expired (expiry of the maximum term for communication of acceptance/refusal)'),
- ('failed_delivery', 'Delivery impossible, ES certify that it has received the invoice and that the file \
- could not be delivered to the addressee') # ok we must do nothing
- ], default='to_send', copy=False, string="FatturaPA Send State")
+ l10n_it_edi_transaction = fields.Char(copy=False, string="FatturaPA Transaction")
+ l10n_it_edi_attachment_id = fields.Many2one('ir.attachment', copy=False, string="FatturaPA Attachment")
l10n_it_stamp_duty = fields.Float(default=0, string="Dati Bollo", readonly=True, states={'draft': [('readonly', False)]})
@@ -48,12 +39,6 @@ class AccountMove(models.Model):
invoice.l10n_it_einvoice_id = einvoice.attachment_id
invoice.l10n_it_einvoice_name = einvoice.attachment_id.name
- def _check_before_xml_exporting(self):
- # DEPRECATED use AccountEdiFormat._l10n_it_edi_check_invoice_configuration instead
- errors = self.env['account.edi.format']._l10n_it_edi_check_invoice_configuration(self)
- if errors:
- raise UserError(self.env['account.edi.format']._format_error_message(_("Invalid configuration:"), errors))
-
def invoice_generate_xml(self):
self.ensure_one()
report_name = self.env['account.edi.format']._l10n_it_edi_generate_electronic_invoice_filename(self)
@@ -298,73 +283,11 @@ class AccountMove(models.Model):
}
return template_values
- def _export_as_xml(self):
- '''DEPRECATED : this will be moved to AccountEdiFormat in a future version.
- Create the xml file content.
- :return: The XML content as str.
- '''
- template_values = self._prepare_fatturapa_export_values()
- if not self.env['account.edi.format']._l10n_it_is_simplified_document_type(template_values['document_type']):
- content = self.env['ir.qweb']._render('l10n_it_edi.account_invoice_it_FatturaPA_export', template_values)
- else:
- content = self.env['ir.qweb']._render('l10n_it_edi.account_invoice_it_simplified_FatturaPA_export', template_values)
- self.message_post(body=_("A simplified invoice was created instead of an ordinary one. This is because the invoice \
- is a domestic invoice with a total amount of less than or equal to 400€ and the customer's address is incomplete."))
- return content
-
def _post(self, soft=True):
# OVERRIDE
posted = super()._post(soft=soft)
-
- for move in posted.filtered(lambda m: m.l10n_it_send_state == 'to_send' and m.move_type in ['out_invoice', 'out_refund'] and m.company_id.country_id.code == 'IT'):
- move.send_pec_mail()
-
return posted
- def send_pec_mail(self):
- self.ensure_one()
- allowed_state = ['to_send', 'invalid']
-
- if (
- not self.company_id.l10n_it_mail_pec_server_id
- or not self.company_id.l10n_it_mail_pec_server_id.active
- or not self.company_id.l10n_it_address_send_fatturapa
- ):
- self.message_post(
- body=(_("Error when sending mail with E-Invoice: Your company must have a mail PEC server and must indicate the mail PEC that will send electronic invoice."))
- )
- self.l10n_it_send_state = 'invalid'
- return
-
- if self.l10n_it_send_state not in allowed_state:
- raise UserError(_("%s isn't in a right state. It must be in a 'Not yet send' or 'Invalid' state.") % (self.display_name))
-
- message = self.env['mail.message'].create({
- 'subject': _('Sending file: %s') % (self.l10n_it_einvoice_name),
- 'body': _('Sending file: %s to ES: %s') % (self.l10n_it_einvoice_name, self.env.company.l10n_it_address_recipient_fatturapa),
- 'author_id': self.env.user.partner_id.id,
- 'email_from': self.env.company.l10n_it_address_send_fatturapa,
- 'reply_to': self.env.company.l10n_it_address_send_fatturapa,
- 'mail_server_id': self.env.company.l10n_it_mail_pec_server_id.id,
- 'attachment_ids': [(6, 0, self.l10n_it_einvoice_id.ids)],
- })
-
- mail_fattura = self.env['mail.mail'].sudo().with_context(wo_bounce_return_path=True).create({
- 'mail_message_id': message.id,
- 'email_to': self.env.company.l10n_it_address_recipient_fatturapa,
- })
- try:
- mail_fattura.send(raise_exception=True)
- self.message_post(
- body=(_("Mail sent on %s by %s") % (fields.Datetime.now(), self.env.user.display_name))
- )
- self.l10n_it_send_state = 'sent'
- except MailDeliveryException as error:
- self.message_post(
- body=(_("Error when sending mail with E-Invoice: %s") % (error.args[0]))
- )
- self.l10n_it_send_state = 'invalid'
-
def _compose_info_message(self, tree, element_tags):
output_str = ""
elements = tree.xpath(element_tags)
diff --git a/addons/l10n_it_edi/models/ir_mail_server.py b/addons/l10n_it_edi/models/ir_mail_server.py
deleted file mode 100644
index aa2841fdf7a..00000000000
--- a/addons/l10n_it_edi/models/ir_mail_server.py
+++ /dev/null
@@ -1,449 +0,0 @@
-# -*- coding:utf-8 -*-
-# Part of Odoo. See LICENSE file for full copyright and licensing details.
-
-import zipfile
-import io
-import re
-import logging
-import email
-import email.policy
-import dateutil
-import pytz
-
-from lxml import etree
-from datetime import datetime
-from xmlrpc import client as xmlrpclib
-
-from odoo import api, fields, models, tools, _
-from odoo.exceptions import ValidationError, UserError
-from odoo.addons.l10n_it_edi.tools.remove_signature import remove_signature
-
-
-_logger = logging.getLogger(__name__)
-
-class FetchmailServer(models.Model):
- _name = 'fetchmail.server'
- _inherit = 'fetchmail.server'
-
- l10n_it_is_pec = fields.Boolean('PEC server', help="If PEC Server, only mail from '...@pec.fatturapa.it' will be processed.")
- l10n_it_last_uid = fields.Integer(string='Last message UID IT', default=1)
-
- def _search_edi_invoice(self, att_name, send_state=False):
- """ Search sent l10n_it_edi fatturaPA invoices """
-
- conditions = [
- ('move_id', "!=", False),
- ('edi_format_id.code', '=', 'fattura_pa'),
- ('attachment_id.name', '=', att_name),
- ]
- if send_state:
- conditions.append(('move_id.l10n_it_send_state', '=', send_state))
-
- return self.env['account.edi.document'].search(conditions, limit=1).move_id
-
- @api.constrains('l10n_it_is_pec', 'server_type')
- def _check_pec(self):
- for record in self:
- if record.l10n_it_is_pec and record.server_type != 'imap':
- raise ValidationError(_("PEC mail server must be of type IMAP."))
-
- def fetch_mail(self):
- """ WARNING: meant for cron usage only - will commit() after each email! """
-
- MailThread = self.env['mail.thread']
- for server in self.filtered(lambda s: s.l10n_it_is_pec):
- _logger.info('start checking for new emails on %s PEC server %s', server.server_type, server.name)
-
- count, failed = 0, 0
- imap_server = None
- try:
- imap_server = server.connect()
- imap_server.select()
-
- # Only download new emails
- email_filter = ['(UID %s:*)' % (server.l10n_it_last_uid)]
-
- # The l10n_it_edi.fatturapa_bypass_incoming_address_filter prevents the sender address check on incoming email.
- bypass_incoming_address_filter = self.env['ir.config_parameter'].get_param('l10n_it_edi.bypass_incoming_address_filter', False)
- if not bypass_incoming_address_filter:
- email_filter.append('(FROM "@pec.fatturapa.it")')
-
- data = imap_server.uid('search', None, *email_filter)[1]
-
- new_max_uid = server.l10n_it_last_uid
- for uid in data[0].split():
- if int(uid) <= server.l10n_it_last_uid:
- # We get always minimum 1 message. If no new message, we receive the newest already managed.
- continue
-
- result, data = imap_server.uid('fetch', uid, '(RFC822)')
-
- if not data[0]:
- continue
- message = data[0][1]
-
- # To leave the mail in the state in which they were.
- if "Seen" not in data[1].decode("utf-8"):
- imap_server.uid('STORE', uid, '+FLAGS', '(\\Seen)')
- else:
- imap_server.uid('STORE', uid, '-FLAGS', '(\\Seen)')
-
- # See details in message_process() in mail_thread.py
- if isinstance(message, xmlrpclib.Binary):
- message = bytes(message.data)
- if isinstance(message, str):
- message = message.encode('utf-8')
- msg_txt = email.message_from_bytes(message, policy=email.policy.SMTP)
-
- try:
- self._attachment_invoice(msg_txt)
- new_max_uid = max(new_max_uid, int(uid))
- except Exception:
- _logger.info('Failed to process mail from %s server %s.', server.server_type, server.name, exc_info=True)
- failed += 1
- self._cr.commit()
- count += 1
- server.write({'l10n_it_last_uid': new_max_uid})
- _logger.info("Fetched %d email(s) on %s server %s; %d succeeded, %d failed.", count, server.server_type, server.name, (count - failed), failed)
- except Exception:
- _logger.info("General failure when trying to fetch mail from %s server %s.", server.server_type, server.name, exc_info=True)
- finally:
- if imap_server:
- imap_server.close()
- imap_server.logout()
- server.write({'date': fields.Datetime.now()})
- return super(FetchmailServer, self.filtered(lambda s: not s.l10n_it_is_pec)).fetch_mail()
-
- def _attachment_invoice(self, msg_txt):
- parsed_values = self.env['mail.thread']._message_parse_extract_payload(msg_txt)
- body, attachments = parsed_values['body'], parsed_values['attachments']
- from_address = msg_txt.get('from')
- for attachment in attachments:
- split_attachment = attachment.fname.rpartition('.')
- if len(split_attachment) < 3:
- _logger.info('E-invoice filename not compliant: %s', attachment.fname)
- continue
- attachment_name = split_attachment[0]
- attachment_ext = split_attachment[2]
- split_underscore = attachment_name.rsplit('_', 2)
- if len(split_underscore) < 2:
- _logger.info('E-invoice filename not compliant: %s', attachment.fname)
- continue
-
- if attachment_ext != 'zip':
- if split_underscore[1] in ['RC', 'NS', 'MC', 'MT', 'EC', 'SE', 'NE', 'DT']:
- # we have a receipt
- self._message_receipt_invoice(split_underscore[1], attachment)
- else:
- att_filename = attachment.fname
- match = re.search("([A-Z]{2}[A-Za-z0-9]{2,28}_[A-Za-z0-9]{0,5}.(xml.p7m|xml))", att_filename)
- # If match, we have an invoice.
- if match:
- # If it's signed, the content has a bytes type and we just remove the signature's envelope
- if match.groups()[1] == 'xml.p7m':
- att_content_data = remove_signature(attachment.content)
- # If the envelope cannot be removed, the remove_signature returns None, so we skip
- if not att_content_data:
- _logger.warning("E-invoice couldn't be read: %s", att_filename)
- continue
- att_filename = att_filename.replace('.xml.p7m', '.xml')
- else:
- # Otherwise, it should be an utf-8 encoded XML string
- att_content_data = attachment.content.encode()
- self._create_invoice_from_mail(att_content_data, att_filename, from_address)
- else:
- if split_underscore[1] == 'AT':
- # Attestazione di avvenuta trasmissione della fattura con impossibilità di recapito
- self._message_AT_invoice(attachment)
- else:
- _logger.info('New E-invoice in zip file: %s', attachment.fname)
- self._create_invoice_from_mail_with_zip(attachment, from_address)
-
- def _create_invoice_from_mail(self, att_content_data, att_name, from_address):
- """ Creates an invoice from the content of an email present in ir.attachments
-
- :param att_content_data: The 'utf-8' encoded bytes string representing the content of the attachment.
- :param att_name: The attachment's file name.
- :param from_address: The sender address of the email.
- """
-
- invoices = self.env['account.move']
-
- # Check if we already imported the email as an attachment
- existing = self.env['ir.attachment'].search([('name', '=', att_name), ('res_model', '=', 'account.move')])
- if existing:
- _logger.info('E-invoice already exist: %s', att_name)
- return invoices
-
- # Create the new attachment for the file
- attachment = self.env['ir.attachment'].create({
- 'name': att_name,
- 'raw': att_content_data,
- 'res_model': 'account.move',
- 'type': 'binary'})
-
- # Decode the file.
- try:
- tree = etree.fromstring(att_content_data)
- except Exception:
- _logger.info('The xml file is badly formatted: %s', att_name)
- return invoices
-
- invoices = self.env.ref('l10n_it_edi.edi_fatturaPA')._create_invoice_from_xml_tree(att_name, tree)
- if not invoices:
- _logger.info('E-invoice not found in file: %s', att_name)
- return invoices
- invoices.l10n_it_send_state = "new"
- invoices.invoice_source_email = from_address
- for invoice in invoices:
- invoice.with_context(no_new_invoice=True, default_res_id=invoice.id) \
- .message_post(body=(_("Original E-invoice XML file")), attachment_ids=[attachment.id])
-
- self._cr.commit()
-
- _logger.info('New E-invoices (%s), ids: %s', att_name, [x.id for x in invoices])
- return invoices
-
- def _create_invoice_from_mail_with_zip(self, attachment_zip, from_address):
- with zipfile.ZipFile(io.BytesIO(attachment_zip.content)) as z:
- for att_name in z.namelist():
- existing = self.env['ir.attachment'].search([('name', '=', att_name), ('res_model', '=', 'account.move')])
- if existing:
- # invoice already exist
- _logger.info('E-invoice in zip file (%s) already exist: %s', attachment_zip.fname, att_name)
- continue
- att_content = z.open(att_name).read()
-
- self._create_invoice_from_mail(att_content, att_name, from_address)
-
- def _message_AT_invoice(self, attachment_zip):
- with zipfile.ZipFile(io.BytesIO(attachment_zip.content)) as z:
- for attachment_name in z.namelist():
- split_name_attachment = attachment_name.rpartition('.')
- if len(split_name_attachment) < 3:
- continue
- split_underscore = split_name_attachment[0].rsplit('_', 2)
- if len(split_underscore) < 2:
- continue
- if split_underscore[1] == 'AT':
- attachment = z.open(attachment_name).read()
- _logger.info('New AT receipt for: %s', split_underscore[0])
- try:
- tree = etree.fromstring(attachment)
- except:
- _logger.info('Error in decoding new receipt file: %s', attachment_name)
- return
-
- elements = tree.xpath('//NomeFile')
- if elements and elements[0].text:
- filename = elements[0].text
- else:
- return
-
- related_invoice = self._search_edi_invoice(filename)
- if not related_invoice:
- _logger.info('Error: invoice not found for receipt file: %s', filename)
- return
-
- related_invoice.l10n_it_send_state = 'failed_delivery'
- info = self._return_multi_line_xml(tree, ['//IdentificativoSdI', '//DataOraRicezione', '//MessageId', '//PecMessageId', '//Note'])
- related_invoice.message_post(
- body=(_("ES certify that it has received the invoice and that the file \
- could not be delivered to the addressee.
%s") % (info))
- )
-
- def _message_receipt_invoice(self, receipt_type, attachment):
-
- try:
- tree = etree.fromstring(attachment.content.encode())
- except:
- _logger.info('Error in decoding new receipt file: %s', attachment.fname)
- return {}
-
- elements = tree.xpath('//NomeFile')
- if elements and elements[0].text:
- filename = elements[0].text
- else:
- return {}
-
- if receipt_type == 'RC':
- # Delivery receipt
- # This is the receipt sent by the ES to the transmitting subject to communicate
- # delivery of the file to the addressee
- related_invoice = self._search_edi_invoice(filename, 'sent')
- if not related_invoice:
- _logger.info('Error: invoice not found for receipt file: %s', attachment.fname)
- return
- related_invoice.l10n_it_send_state = 'delivered'
- info = self._return_multi_line_xml(tree, ['//IdentificativoSdI', '//DataOraRicezione', '//DataOraConsegna', '//Note'])
- related_invoice.message_post(
- body=(_("E-Invoice is delivery to the destinatory:
%s") % (info))
- )
-
- elif receipt_type == 'NS':
- # Rejection notice
- # This is the receipt sent by the ES to the transmitting subject if one or more of
- # the checks carried out by the ES on the file received do not have a successful result.
- related_invoice = self._search_edi_invoice(filename, 'sent')
- if not related_invoice:
- _logger.info('Error: invoice not found for receipt file: %s', attachment.fname)
- return
- related_invoice.l10n_it_send_state = 'invalid'
- error = self._return_error_xml(tree)
- related_invoice.message_post(
- body=(_("Errors in the E-Invoice :
%s") % (error))
- )
- related_invoice.activity_schedule(
- 'mail.mail_activity_data_todo',
- summary='Rejection notice',
- user_id=related_invoice.invoice_user_id.id if related_invoice.invoice_user_id else self.env.user.id)
-
- elif receipt_type == 'MC':
- # Failed delivery notice
- # This is the receipt sent by the ES to the transmitting subject if the file is not
- # delivered to the addressee.
- related_invoice = self._search_edi_invoice(filename, 'sent')
- if not related_invoice:
- _logger.info('Error: invoice not found for receipt file: %s', attachment.fname)
- return
- info = self._return_multi_line_xml(tree, [
- '//IdentificativoSdI',
- '//DataOraRicezione',
- '//Descrizione',
- '//MessageId',
- '//Note'])
- related_invoice.message_post(
- body=(_("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. More information:
%s") % (info))
- )
-
- elif receipt_type == 'NE':
- # Outcome notice
- # This is the receipt sent by the ES to the invoice sender to communicate the result
- # (acceptance or refusal of the invoice) of the checks carried out on the document by
- # the addressee.
- related_invoice = self._search_edi_invoice(filename, 'delivered')
- if not related_invoice:
- _logger.info('Error: invoice not found for receipt file: %s', attachment.fname)
- return
- elements = tree.xpath('//Esito')
- if elements and elements[0].text:
- if elements[0].text == 'EC01':
- related_invoice.l10n_it_send_state = 'delivered_accepted'
- elif elements[0].text == 'EC02':
- related_invoice.l10n_it_send_state = 'delivered_refused'
-
- info = self._return_multi_line_xml(tree,
- ['//Esito',
- '//Descrizione',
- '//IdentificativoSdI',
- '//DataOraRicezione',
- '//DataOraConsegna',
- '//Note'
- ])
- related_invoice.message_post(
- body=(_("Outcome notice: %s
%s") % (related_invoice.l10n_it_send_state, info))
- )
- if related_invoice.l10n_it_send_state == 'delivered_refused':
- related_invoice.activity_schedule(
- 'mail.mail_activity_todo',
- user_id=related_invoice.invoice_user_id.id if related_invoice.invoice_user_id else self.env.user.id,
- summary='Outcome notice: Refused')
-
- # elif receipt_type == 'MT':
- # Metadata file
- # This is the file sent by the ES to the addressee together with the invoice file,
- # containing the main reference data of the file useful for processing, including
- # the IdentificativoSDI.
- # Useless for Odoo
-
- elif receipt_type == 'DT':
- # Deadline passed notice
- # This is the receipt sent by the ES to both the invoice sender and the invoice
- # addressee to communicate the expiry of the maximum term for communication of
- # acceptance/refusal.
- related_invoice = self._search_edi_invoice(filename, 'delivered')
- if not related_invoice:
- _logger.info('Error: invoice not found for receipt file: %s', attachment.fname)
- return
- related_invoice.l10n_it_send_state = 'delivered_expired'
- info = self._return_multi_line_xml(tree, [
- '//Descrizione',
- '//IdentificativoSdI',
- '//Note'])
- related_invoice.message_post(
- body=(_("Expiration of the maximum term for communication of acceptance/refusal:\
- %s
%s") % (filename, info))
- )
-
- def _return_multi_line_xml(self, tree, element_tags):
- output_str = "