1# -*- coding: utf-8 -*- 2# Part of Odoo. See LICENSE file for full copyright and licensing details. 3 4import datetime 5import logging 6from collections import namedtuple 7from unittest.mock import patch 8import freezegun 9 10from odoo import tools 11from odoo.addons.account_edi.tests.common import AccountEdiTestCommon 12from odoo.addons.l10n_it_edi.tools.remove_signature import remove_signature 13 14_logger = logging.getLogger(__name__) 15 16 17class PecMailServerTests(AccountEdiTestCommon): 18 """ Main test class for the l10n_it_edi vendor bills XML import from a PEC mail account""" 19 20 fake_test_content = """<?xml version="1.0" encoding="UTF-8"?> 21 <p:FatturaElettronica versione="FPR12" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" 22 xmlns:p="http://ivaservizi.agenziaentrate.gov.it/docs/xsd/fatture/v1.2" 23 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 24 xsi:schemaLocation="http://ivaservizi.agenziaentrate.gov.it/docs/xsd/fatture/v1.2 http://www.fatturapa.gov.it/export/fatturazione/sdi/fatturapa/v1.2/Schema_del_file_xml_FatturaPA_versione_1.2.xsd"> 25 <FatturaElettronicaHeader> 26 <CessionarioCommittente> 27 <DatiAnagrafici> 28 <CodiceFiscale>01234560157</CodiceFiscale> 29 </DatiAnagrafici> 30 </CessionarioCommittente> 31 </FatturaElettronicaHeader> 32 <FatturaElettronicaBody> 33 <DatiGenerali> 34 <DatiGeneraliDocumento> 35 <TipoDocumento>TD02</TipoDocumento> 36 </DatiGeneraliDocumento> 37 </DatiGenerali> 38 </FatturaElettronicaBody> 39 </p:FatturaElettronica>""" 40 41 @classmethod 42 def setUpClass(cls): 43 """ Setup the test class with a PEC mail server and a fake fatturaPA content """ 44 45 super().setUpClass(chart_template_ref='l10n_it.l10n_it_chart_template_generic', 46 edi_format_ref='l10n_it_edi.edi_fatturaPA') 47 48 # Use the company_data_2 to test that the e-invoice is imported for the right company 49 cls.company = cls.company_data_2['company'] 50 51 # Initialize the company's codice fiscale 52 cls.company.l10n_it_codice_fiscale = 'IT01234560157' 53 54 # Build test data. 55 # invoice_filename1 is used for vendor bill receipts tests 56 # invoice_filename2 is used for vendor bill tests 57 cls.invoice_filename1 = 'IT01234567890_FPR01.xml' 58 cls.invoice_filename2 = 'IT01234567890_FPR02.xml' 59 cls.signed_invoice_filename = 'IT01234567890_FPR01.xml.p7m' 60 cls.invoice_content = cls._get_test_file_content(cls.invoice_filename1) 61 cls.signed_invoice_content = cls._get_test_file_content(cls.signed_invoice_filename) 62 cls.invoice = cls.env['account.move'].create({ 63 'move_type': 'in_invoice', 64 'ref': '01234567890' 65 }) 66 cls.attachment = cls.env['ir.attachment'].create({ 67 'name': cls.invoice_filename1, 68 'raw': cls.invoice_content, 69 'res_id': cls.invoice.id, 70 'res_model': 'account.move', 71 }) 72 cls.edi_document = cls.env['account.edi.document'].create({ 73 'edi_format_id': cls.edi_format.id, 74 'move_id': cls.invoice.id, 75 'attachment_id': cls.attachment.id, 76 'state': 'sent' 77 }) 78 79 # Initialize the fetchmail server that has to be tested 80 cls.server = cls.env['fetchmail.server'].sudo().create({ 81 'name': 'test_server', 82 'server_type': 'imap', 83 'l10n_it_is_pec': True}) 84 85 @classmethod 86 def _get_test_file_content(cls, filename): 87 """ Get the content of a test file inside this module """ 88 path = 'l10n_it_edi/tests/expected_xmls/' + filename 89 with tools.file_open(path, mode='rb') as test_file: 90 return test_file.read() 91 92 def _create_invoice(self, content, filename): 93 """ Create an invoice from given attachment content """ 94 with patch.object(self.server._cr, 'commit', return_value=None): 95 if filename.endswith(".p7m"): 96 content = remove_signature(content) 97 return self.server._create_invoice_from_mail(content, filename, 'fake@address.be') 98 99 # ----------------------------- 100 # 101 # Vendor bills 102 # 103 # ----------------------------- 104 105 def test_receive_vendor_bill(self): 106 """ Test a sample e-invoice file from https://www.fatturapa.gov.it/export/documenti/fatturapa/v1.2/IT01234567890_FPR01.xml """ 107 invoices = self._create_invoice(self.invoice_content, self.invoice_filename2) 108 self.assertTrue(bool(invoices)) 109 110 def test_receive_signed_vendor_bill(self): 111 """ Test a signed (P7M) sample e-invoice file from https://www.fatturapa.gov.it/export/documenti/fatturapa/v1.2/IT01234567890_FPR01.xml """ 112 with freezegun.freeze_time('2020-04-06'): 113 invoices = self._create_invoice(self.signed_invoice_content, self.signed_invoice_filename) 114 self.assertRecordValues(invoices, [{ 115 'company_id': self.company.id, 116 'name': 'BILL/2014/12/0001', 117 'invoice_date': datetime.date(2014, 12, 18), 118 'ref': '01234567890', 119 }]) 120 121 def test_receive_same_vendor_bill_twice(self): 122 """ Test that the second time we are receiving a PEC mail with the same attachment, the second is discarded """ 123 content = self.fake_test_content.encode() 124 for result in [True, False]: 125 invoice = self._create_invoice(content, self.invoice_filename2) 126 self.assertEqual(result, bool(invoice)) 127 128 # ----------------------------- 129 # 130 # Receipts 131 # 132 # ----------------------------- 133 134 def _test_receipt(self, receipt_type, source_state, destination_state): 135 """ Test a receipt from the ones in the module's test files """ 136 137 # Simulate the 'sent' state of the move, even if we didn't actually send an email in this test 138 self.invoice.l10n_it_send_state = source_state 139 140 # Create a fake receipt from the test file 141 receipt_filename = 'IT01234567890_FPR01_%s_001.xml' % receipt_type 142 receipt_content = self._get_test_file_content(receipt_filename).decode() 143 144 create_mail_attachment = namedtuple('Attachment', ('fname', 'content', 'info')) 145 receipt_mail_attachment = create_mail_attachment(receipt_filename, receipt_content, {}) 146 147 # Simulate the arrival of the receipt 148 with patch.object(self.server._cr, 'commit', return_value=None): 149 self.server._message_receipt_invoice(receipt_type, receipt_mail_attachment) 150 151 # Check the Destination state of the edi_document 152 self.assertTrue(destination_state, self.edi_document.state) 153 154 def test_ricevuta_consegna(self): 155 """ Test a receipt adapted from https://www.fatturapa.gov.it/export/documenti/messaggi/v1.0/IT01234567890_11111_RC_001.xml """ 156 self._test_receipt('RC', 'sent', 'delivered') 157 158 def test_decorrenza_termini(self): 159 """ Test a receipt adapted from https://www.fatturapa.gov.it/export/documenti/messaggi/v1.0/IT01234567890_11111_DT_001.xml """ 160 self._test_receipt('DT', 'delivered', 'delivered_expired') 161