# coding: utf-8 import base64 from pytz import timezone from datetime import datetime from odoo.tests import tagged from odoo.tools import misc from odoo.modules import module as modules from odoo.addons.account_edi.tests.common import AccountEdiTestCommon MAX_WAIT_ITER = 6 CODE_98_ERROR_MSG = "

The cancellation request has not yet finished processing by SUNAT. Please retry in a few minutes.

SOAP status code: 98

" def mocked_l10n_pe_edi_post_invoice_web_service(edi_format, invoice, edi_filename, edi_str): # simulate the EDI always success. zip_edi_str = edi_format._l10n_pe_edi_zip_edi_document([('%s.xml' % edi_filename, edi_str)]) return { 'attachment': edi_format.env['ir.attachment'].create({ 'res_model': invoice._name, 'res_id': invoice.id, 'type': 'binary', 'name': '%s.zip' % edi_filename, 'datas': base64.encodebytes(zip_edi_str), 'mimetype': 'application/zip', }) } class TestPeEdiCommon(AccountEdiTestCommon): @classmethod def setUpClass(cls, chart_template_ref='pe', edi_format_ref='l10n_pe_edi.edi_pe_ubl_2_1'): super().setUpClass(chart_template_ref=chart_template_ref, edi_format_ref=edi_format_ref) cls.frozen_today = datetime(year=2017, month=1, day=1, hour=0, minute=0, second=0, tzinfo=timezone('utc')) # Allow to see the full result of AssertionError. cls.maxDiff = None # Replace USD by the fake currency created in setup (GOL). cls.env.ref('base.USD').name = "OLD_USD" cls.currency_data['currency'].name = 'USD' cls.currency_data['currency'].rounding = 0.01 # ==== Config ==== cls.certificate = cls.env['l10n_pe_edi.certificate'].create({ 'content': base64.encodebytes( misc.file_open('l10n_pe_edi/demo/certificates/certificate.pfx', 'rb').read()), 'password': '12345678a', }) cls.certificate.write({ 'date_start': '2016-01-01 01:00:00', 'date_end': '2018-01-01 01:00:00', }) cls.company_data['company'].write({ 'country_id': cls.env.ref('base.pe').id, 'l10n_pe_edi_provider': 'digiflow', 'l10n_pe_edi_certificate_id': cls.certificate.id, 'l10n_pe_edi_test_env': True, }) cls.national_bank = cls.env.ref("l10n_pe.peruvian_national_bank") cls.national_bank_account = cls.env['res.partner.bank'].create({ 'acc_number': 'CUENTAPRUEBA', 'bank_id': cls.national_bank.id, 'partner_id': cls.company_data['company'].partner_id.id }) cls.company_data['company'].partner_id.write({ 'vat': "20557912879", 'l10n_latam_identification_type_id': cls.env.ref('l10n_pe.it_RUC').id, }) cls.company_data['default_journal_sale'].l10n_latam_use_documents = True cls.iap_account = cls.env['iap.account'].create({ 'service_name': 'l10n_pe_edi', 'company_ids': [(6, 0, cls.company_data['company'].ids)], }) # Prevent the xsd validation because it could lead to a not-deterministic behavior since the xsd is downloaded # by a CRON. xsd_attachments = cls.env['ir.attachment'] for doc_type in ('CreditNote', 'DebitNote', 'Invoice'): xsd_attachment = cls.env.ref('l10n_pe_edi.UBL-%s-2.1.xsd' % doc_type, raise_if_not_found=False) if xsd_attachment: xsd_attachments |= xsd_attachment if xsd_attachments: xsd_attachments.unlink() # ==== Business ==== cls.tax_group = cls.env['account.tax.group'].create({ 'name': "IGV", 'l10n_pe_edi_code': "IGV", }) cls.tax_18 = cls.env['account.tax'].create({ 'name': 'tax_18', 'amount_type': 'percent', 'amount': 18, 'l10n_pe_edi_tax_code': '1000', 'l10n_pe_edi_unece_category': 'S', 'type_tax_use': 'sale', 'tax_group_id': cls.tax_group.id, }) cls.product = cls.env['product.product'].create({ 'name': 'product_pe', 'weight': 2, 'uom_po_id': cls.env.ref('uom.product_uom_kgm').id, 'uom_id': cls.env.ref('uom.product_uom_kgm').id, 'lst_price': 1000.0, 'property_account_income_id': cls.company_data['default_account_revenue'].id, 'property_account_expense_id': cls.company_data['default_account_expense'].id, 'unspsc_code_id': cls.env.ref('product_unspsc.unspsc_code_01010101').id, }) cls.partner_a.write({ 'vat': '20462509236', 'l10n_latam_identification_type_id': cls.env.ref('l10n_pe.it_RUC').id, 'country_id': cls.env.ref('base.pe').id, }) # Invoice name are tracked by the web-services so this constant tries to get a new unique invoice name at each # execution. cls.time_name = datetime.now().strftime('%H%M%S') # Initialize the cancellation request filename sequence, to avoid collisions between different people running # the UTs on the same day seq = cls.env.ref('l10n_pe_edi.l10n_pe_edi_summary_sequence') if seq.number_next_actual < 50: seq.write({'number_next': int(cls.time_name[-3:]) + 60}) # ==== INVOICE ==== cls.expected_invoice_xml_values = ''' 2.1 2.0 ___ignore___ 2017-01-01 2017-01-01 01 NUEVE MIL CUATROCIENTOS CUARENTA Y 00/100 GOLD USD ___ignore___ IDSignKG 20557912879 COMPANY_1_DATA #SignVX 20557912879 20557912879 company_1_data PE Peru company_1_data 20557912879 PE Peru VAT company_1_data 20557912879 0000 PE Peru ___ignore___ company_1_data 6 20462509236 partner_a PE Peru partner_a 20462509236 PE Peru VAT partner_a 20462509236 PE Peru ___ignore___ partner_a
PE Peru
FormaPago Contado 1440.00 8000.00 1440.00 1000 IGV VAT 8000.00 8000.00 9440.00 0.00 9440.00 ___ignore___ 5.0 8000.00 1888.00 01 1440.00 8000.00 1440.00 18.0 10 1000 IGV VAT product_pe product_pe 01010101 1600.0
''' # ==== REFUND ==== cls.expected_refund_xml_values = ''' 2.1 2.0 ___ignore___ 2017-01-01 381 USD 01 abc abc ___ignore___ 01 IDSignKG 20557912879 COMPANY_1_DATA #SignVX 20557912879 20557912879 company_1_data PE Peru company_1_data 20557912879 PE Peru VAT company_1_data 20557912879 0000 PE Peru ___ignore___ company_1_data 6 20462509236 partner_a PE Peru partner_a 20462509236 PE Peru VAT partner_a 20462509236 PE Peru ___ignore___ partner_a
PE Peru
1440.00 8000.00 1440.00 1000 IGV VAT 8000.00 8000.00 9440.00 0.00 9440.00 ___ignore___ 5.0 8000.00 1888.00 01 1440.00 8000.00 1440.00 18.0 10 1000 IGV VAT product_pe product_pe 01010101 1600.0
''' # ==== DEBIT NOTE ==== cls.expected_debit_note_xml_values = ''' 2.1 2.0 ___ignore___ 2017-01-01 USD 01 abc abc ___ignore___ 01 IDSignKG 20557912879 COMPANY_1_DATA #SignVX 20557912879 20557912879 company_1_data PE Peru company_1_data 20557912879 PE Peru VAT company_1_data 20557912879 0000 PE Peru ___ignore___ company_1_data 6 20462509236 partner_a PE Peru partner_a 20462509236 PE Peru VAT partner_a 20462509236 PE Peru ___ignore___ partner_a
PE Peru
FormaPago Contado 1440.00 8000.00 1440.00 1000 IGV VAT 8000.00 8000.00 9440.00 0.00 9440.00 ___ignore___ 5.0 8000.00 1888.00 01 1440.00 8000.00 1440.00 18.0 10 1000 IGV VAT product_pe product_pe 01010101 1600.0
''' def _create_invoice(self, **kwargs): vals = { 'name': 'F FFI-%s1' % self.time_name, 'move_type': 'out_invoice', 'partner_id': self.partner_a.id, 'invoice_date': '2017-01-01', 'date': '2017-01-01', 'currency_id': self.currency_data['currency'].id, 'l10n_latam_document_type_id': self.env.ref('l10n_pe.document_type01').id, 'invoice_line_ids': [(0, 0, { 'product_id': self.product.id, 'product_uom_id': self.env.ref('uom.product_uom_kgm').id, 'price_unit': 2000.0, 'quantity': 5, 'discount': 20.0, 'tax_ids': [(6, 0, self.tax_18.ids)], })], } vals.update(kwargs) # Increment the name to make sure it is unique at each call self.time_name = str(int(self.time_name) + 1) return self.env['account.move'].create(vals) def _create_refund(self, **kwargs): invoice = self._create_invoice(name='F FFI-%s2' % self.time_name, **kwargs) vals = { 'name': 'F CNE-%s1' % self.time_name, 'move_type': 'out_refund', 'ref': 'abc', 'partner_id': self.partner_a.id, 'invoice_date': '2017-01-01', 'date': '2017-01-01', 'currency_id': self.currency_data['currency'].id, 'reversed_entry_id': invoice.id, 'l10n_latam_document_type_id': self.env.ref('l10n_pe.document_type07').id, 'l10n_pe_edi_refund_reason': '01', 'invoice_line_ids': [(0, 0, { 'product_id': self.product.id, 'product_uom_id': self.env.ref('uom.product_uom_kgm').id, 'price_unit': 2000.0, 'quantity': 5, 'discount': 20.0, 'tax_ids': [(6, 0, self.tax_18.ids)], })], } vals.update(kwargs) return self.env['account.move'].create(vals) def _create_debit_note(self, **kwargs): invoice = self._create_invoice(name='F FFI-%s3' % self.time_name, **kwargs) vals = { 'name': 'F NDI-%s1' % self.time_name, 'move_type': 'out_invoice', 'ref': 'abc', 'partner_id': self.partner_a.id, 'invoice_date': '2017-01-01', 'date': '2017-01-01', 'currency_id': self.currency_data['currency'].id, 'debit_origin_id': invoice.id, 'l10n_latam_document_type_id': self.env.ref('l10n_pe.document_type08').id, 'l10n_pe_edi_charge_reason': '01', 'invoice_line_ids': [(0, 0, { 'product_id': self.product.id, 'product_uom_id': self.env.ref('uom.product_uom_kgm').id, 'price_unit': 2000.0, 'quantity': 5, 'discount': 20.0, 'tax_ids': [(6, 0, self.tax_18.ids)], })], } vals.update(kwargs) return self.env['account.move'].create(vals)