diff --git a/tests/test_edocument.py b/tests/test_edocument.py index 4ff38b7..5ba67ac 100644 --- a/tests/test_edocument.py +++ b/tests/test_edocument.py @@ -5,20 +5,159 @@ from lxml import etree import os -from unittest.mock import Mock from decimal import Decimal from datetime import date from trytond.tests.test_tryton import ModuleTestCase, with_transaction from trytond.pool import Pool -from trytond.modules.edocument_uncefact.tests.test_module import get_invoice from trytond.modules.company.tests import create_company, set_company +from trytond.modules.account.tests import create_chart, get_fiscalyear from trytond.exceptions import UserError +def set_invoice_sequences(fiscalyear): + pool = Pool() + Sequence = pool.get('ir.sequence.strict') + SequenceType = pool.get('ir.sequence.type') + InvoiceSequence = pool.get('account.fiscalyear.invoice_sequence') + ModelData = pool.get('ir.model.data') + + sequence = Sequence( + name=fiscalyear.name, + sequence_type=SequenceType(ModelData.get_id( + 'account_invoice', 'sequence_type_account_invoice')), + company=fiscalyear.company) + sequence.save() + fiscalyear.invoice_sequences = [] + invoice_sequence = InvoiceSequence() + invoice_sequence.fiscalyear = fiscalyear + invoice_sequence.in_invoice_sequence = sequence + invoice_sequence.in_credit_note_sequence = sequence + invoice_sequence.out_invoice_sequence = sequence + invoice_sequence.out_credit_note_sequence = sequence + invoice_sequence.save() + return fiscalyear + + class EdocTestCase(ModuleTestCase): 'Test e-rechnung module' module = 'edocument_xrechnung' + def prep_fiscalyear(self, company1): + """ prepare fiscal year, sequences... + """ + pool = Pool() + FiscalYear = pool.get('account.fiscalyear') + + fisc_year = get_fiscalyear(company1, today=date(2024, 1, 15)) + set_invoice_sequences(fisc_year) + self.assertEqual(len(fisc_year.invoice_sequences), 1) + FiscalYear.create_period([fisc_year]) + + def prep_company(self): + """ create company, add country and bank-account + """ + pool = Pool() + Country = pool.get('country.country') + Party = pool.get('party.party') + Bank = pool.get('bank') + BankAccount = pool.get('bank.account') + + country_de, = Country.create([{ + 'name': 'Germany', + 'code': 'DE', + 'code3': 'DEU'}]) + + company = create_company('m-ds') + Party.write(*[[company.party], { + 'addresses': [('write', [company.party.addresses[0]], { + 'country': country_de.id})]}]) + + bank_party, = Party.create([{ + 'name': 'Bank 123', + 'addresses': [('create', [{}])]}]) + bank, = Bank.create([{'party': bank_party.id}]) + BankAccount.create([{ + 'bank': bank.id, + 'owners': [('add', [company.party.id])], + 'numbers': [('create', [{ + 'type': 'iban', + 'number': 'DE02300209000106531065'}])]}]) + return company + + def prep_invoice(self, credit_note=False): + """ add invoice + """ + pool = Pool() + Invoice = pool.get('account.invoice') + Taxes = pool.get('account.tax') + Account = pool.get('account.account') + Journal = pool.get('account.journal') + Currency = pool.get('currency.currency') + Uom = pool.get('product.uom') + Country = pool.get('country.country') + Party = pool.get('party.party') + + country_de, = Country.search([('code', '=', 'DE')]) + customer, = Party.create([{ + 'name': 'Customer', + 'identifiers': [('create', [{ + 'type': 'edoc_route_id', 'code': 'xrechn-route-id-123'}])], + 'addresses': [('create', [{ + 'invoice': True, + 'street': 'Customer Street 1', + 'postal_code': '12345', + 'city': 'Usertown', + 'country': country_de.id, + }])], + }]) + + currency1, = Currency.search([('code', '=', 'usd')]) + + tax, = Taxes.search([('name', '=', '20% VAT')]) + Taxes.write(*[ + [tax], + {'unece_code': 'GST', 'unece_category_code': 'S', + 'legal_notice': 'Legal Notice'}]) + + account_lst = Account.search([ + ('name', 'in', ['Main Revenue', 'Main Receivable']) + ], order=[('name', 'ASC')]) + self.assertEqual(len(account_lst), 2) + self.assertEqual(account_lst[0].name, 'Main Receivable') + + journ_lst = Journal.search([('name', '=', 'Revenue')]) + self.assertEqual(len(journ_lst), 1) + + to_create_invoice = [{ + 'type': 'out', + 'description': 'description of invoice', + 'comment': 'note line 1\nnote line 2', + 'invoice_date': date(2024, 7, 1), + 'party': customer.id, + 'invoice_address': customer.addresses[0].id, + 'account': account_lst[0].id, + 'journal': journ_lst[0].id, + 'currency': currency1.id, + 'lines': [('create', [{ + 'type': 'line', + 'quantity': 2.0 if not credit_note else -2.0, + 'description': 'Product 1', + 'unit': Uom.search([('symbol', '=', 'u')])[0].id, + 'unit_price': Decimal('50.0'), + 'taxes': [('add', [tax.id])], + 'account': account_lst[1].id, + 'currency': currency1.id, + }])], + }] + inv_lst, = Invoice.create(to_create_invoice) + inv_lst.on_change_lines() + inv_lst.save() + Invoice.validate_invoice([inv_lst]) + Invoice.post([inv_lst]) + self.assertEqual(inv_lst.currency.code, 'usd') + self.assertEqual(len(inv_lst.move.lines), 3) + return inv_lst + @with_transaction() def test_xrechn_bank_account_owned(self): """ check field 'company_owned' on bank.account.number @@ -100,45 +239,24 @@ class EdocTestCase(ModuleTestCase): """ pool = Pool() Template = pool.get('edocument.facturxext.invoice') - Identifier = pool.get('party.identifier') - Party = pool.get('party.party') - Bank = pool.get('bank') - BankAccount = pool.get('bank.account') - BankNumber = pool.get('bank.account.number') - invoice = get_invoice() - invoice.payment_term_date = date.today() - invoice.party.get_xrechnung_route_id = Mock( - return_value='xrechn-route-id-123') - invoice.company.party.bank_accounts = [ - Mock( - spec=BankAccount, - currency=invoice.currency, - bank=Mock(spec=Bank, party=Mock(spec=Party, name='Bank')), - owners=[invoice.company.party], - numbers=[Mock(spec=BankNumber, type='other', number='123456')], - )] - invoice.description = 'description of invoice' - invoice.comment = 'note line 1\nnote line 2' - invoice.taxes[0].tax.rate = Decimal('0.1') - invoice.identifiers = [ - Mock( - spec=Identifier, - type='edoc_route_id', - code='xrechn-route-id-123') - ] + company = self.prep_company() + with set_company(company): + create_chart(company=company, tax=True) + self.prep_fiscalyear(company) + invoice = self.prep_invoice() - template = Template(invoice) + template = Template(invoice) - schema_file = os.path.join( - os.path.dirname(__file__), - 'Factur-X_1.07.2_EXTENDED', - 'Factur-X_1.07.2_EXTENDED.xsd') + schema_file = os.path.join( + os.path.dirname(__file__), + 'Factur-X_1.07.2_EXTENDED', + 'Factur-X_1.07.2_EXTENDED.xsd') - invoice_string = template.render('Factur-X-1.07.2-extended') - invoice_xml = etree.fromstring(invoice_string) - schema = etree.XMLSchema(etree.parse(schema_file)) - schema.assertValid(invoice_xml) + invoice_string = template.render('Factur-X-1.07.2-extended') + invoice_xml = etree.fromstring(invoice_string) + schema = etree.XMLSchema(etree.parse(schema_file)) + schema.assertValid(invoice_xml) @with_transaction() def test_xrechn_export_xml_invoice(self): @@ -146,45 +264,24 @@ class EdocTestCase(ModuleTestCase): """ pool = Pool() Template = pool.get('edocument.xrechnung.invoice') - Identifier = pool.get('party.identifier') - Party = pool.get('party.party') - Bank = pool.get('bank') - BankAccount = pool.get('bank.account') - BankNumber = pool.get('bank.account.number') - invoice = get_invoice() - invoice.payment_term_date = date.today() - invoice.party.get_xrechnung_route_id = Mock( - return_value='xrechn-route-id-123') - invoice.company.party.bank_accounts = [ - Mock( - spec=BankAccount, - currency=invoice.currency, - bank=Mock(spec=Bank, party=Mock(spec=Party, name='Bank')), - owners=[invoice.company.party], - numbers=[Mock(spec=BankNumber, type='other', number='123456')], - )] - invoice.description = 'description of invoice' - invoice.comment = 'note line 1\nnote line 2' - invoice.taxes[0].tax.rate = Decimal('0.1') - invoice.identifiers = [ - Mock( - spec=Identifier, - type='edoc_route_id', - code='xrechn-route-id-123') - ] + company = self.prep_company() + with set_company(company): + create_chart(company=company, tax=True) + self.prep_fiscalyear(company) + invoice = self.prep_invoice() - template = Template(invoice) + template = Template(invoice) - schema_file = os.path.join( - os.path.dirname(__file__), 'os-UBL-2.1', - 'xsd', 'maindoc', 'UBL-Invoice-2.1.xsd') + schema_file = os.path.join( + os.path.dirname(__file__), 'os-UBL-2.1', + 'xsd', 'maindoc', 'UBL-Invoice-2.1.xsd') - for x in ['XRechnung-2.2', 'XRechnung-2.3', 'XRechnung-3.0']: - invoice_string = template.render(x) - invoice_xml = etree.fromstring(invoice_string) - schema = etree.XMLSchema(etree.parse(schema_file)) - schema.assertValid(invoice_xml) + for x in ['XRechnung-2.2', 'XRechnung-2.3', 'XRechnung-3.0']: + invoice_string = template.render(x) + invoice_xml = etree.fromstring(invoice_string) + schema = etree.XMLSchema(etree.parse(schema_file)) + schema.assertValid(invoice_xml) @with_transaction() def test_xrechn_export_xml_creditnote(self): @@ -192,59 +289,24 @@ class EdocTestCase(ModuleTestCase): """ pool = Pool() Template = pool.get('edocument.xrechnung.invoice') - Identifier = pool.get('party.identifier') - Party = pool.get('party.party') - Bank = pool.get('bank') - BankAccount = pool.get('bank.account') - BankNumber = pool.get('bank.account.number') - invoice = get_invoice() + company = self.prep_company() + with set_company(company): + create_chart(company=company, tax=True) + self.prep_fiscalyear(company) + invoice = self.prep_invoice(credit_note=True) - # credit note - invoice.lines[0].quantity = -1 - invoice.lines[0].amount = Decimal('-100.0') - invoice.taxes[0].base = Decimal('-100.0') - invoice.taxes[0].amount = Decimal('-10.0') - invoice.untaxed_amount = Decimal('-100.0') - invoice.tax_amount = Decimal('-10.0') - invoice.total_amount = Decimal('-110.0') - invoice.lines_to_pay[0].debit = Decimal('-110.0') + template = Template(invoice) - invoice.party.get_xrechnung_route_id = Mock( - return_value='xrechn-route-id-123') - invoice.company.party.bank_accounts = [ - Mock( - spec=BankAccount, - currency=invoice.currency, - bank=Mock(spec=Bank, party=Mock(spec=Party, name='Bank')), - owners=[invoice.company.party], - numbers=[Mock(spec=BankNumber, type='other', number='123456')], - )] - invoice.description = 'description of invoice' - invoice.comment = 'note line 1\nnote line 2' - invoice.taxes[0].tax.rate = Decimal('0.1') - invoice.identifiers = [ - Mock( - spec=Identifier, - type='edoc_route_id', - code='xrechn-route-id-123') - ] + schema_file = os.path.join( + os.path.dirname(__file__), 'os-UBL-2.1', + 'xsd', 'maindoc', 'UBL-CreditNote-2.1.xsd') - template = Template(invoice) - - schema_file = os.path.join( - os.path.dirname(__file__), 'os-UBL-2.1', - 'xsd', 'maindoc', 'UBL-CreditNote-2.1.xsd') - - for x in ['XRechnung-2.2', 'XRechnung-2.3', 'XRechnung-3.0']: - invoice_string = template.render(x) - invoice_xml = etree.fromstring(invoice_string) - schema = etree.XMLSchema(etree.parse(schema_file)) - schema.assertValid(invoice_xml) - - # invoice_string = template.render('XRechnung-2.2') - # with open('xrechnung-test-creditnote.xml', 'wt') as fhdl: - # fhdl.write(invoice_string.decode('utf8')) + for x in ['XRechnung-2.2', 'XRechnung-2.3', 'XRechnung-3.0']: + invoice_string = template.render(x) + invoice_xml = etree.fromstring(invoice_string) + schema = etree.XMLSchema(etree.parse(schema_file)) + schema.assertValid(invoice_xml) # end EdocTestCase