diff --git a/document.py b/document.py index 54dbc61..470a4ee 100644 --- a/document.py +++ b/document.py @@ -30,7 +30,7 @@ xml_types = [ (['xsd', 'Factur-X_1.07.2_BASICWL', 'Factur-X_1.07.2_BASICWL.xsd'], 'Factur-X basicwl', 'facturx_basicwl'), (['xsd', 'Factur-X_1.07.2_EN16931', 'Factur-X_1.07.2_EN16931.xsd'], - 'Factur-X EN16931', ''), + 'Factur-X EN16931', 'facturx_en16931'), (['xsd', 'Factur-X_1.07.2_EXTENDED', 'Factur-X_1.07.2_EXTENDED.xsd'], 'Factur-X extended', 'facturx_extended'), (['xsd', 'CII D22B XSD', 'CrossIndustryInvoice_100pD22B.xsd'], @@ -63,25 +63,20 @@ class Incoming(metaclass=PoolMeta): with_children (bool, optional): convert sub-documents. Defaults to False. """ - print('\n## process:', documents) for document in documents: document._facturx_detect_content() - print('-- process-2:') super().process(documents, with_children) - print('-- process-3:') def _process_supplier_invoice(self): """ try to detect content of 'data', read values """ invoice = super()._process_supplier_invoice() - print('\n## _process_supplier_invoice:', self) if self.mime_type == 'application/xml': # detect xml-content xml_info = self._facturx_detect_content() if xml_info: (xsd_type, funcname, xmltree) = xml_info - print('-- _process_supplier_invoice-xml_info:', xml_info) xml_read_func = getattr(self, '_readxml_%s' % funcname, None) if not xml_read_func: raise UserError(gettext( @@ -95,7 +90,6 @@ class Incoming(metaclass=PoolMeta): invoice.save() self._readxml_check_invoice(invoice) # raise ValueError('stop') - print('-- _process_supplier_invoice-FIN:', invoice) return invoice def _readxml_check_invoice(self, invoice): @@ -436,6 +430,11 @@ class Incoming(metaclass=PoolMeta): 'document_incoming_invoice_xml.msg_convert_error', msg='factur-x basic-wl not supported')) + def _readxml_facturx_en16931(self, xmltree): + """ read facturx - EN16931 + """ + self._readxml_facturx_extended(xmltree) + def _readxml_facturx_extended(self, xmltree): """ read factur-x extended """ diff --git a/tests/document.py b/tests/document.py index 699e1f9..c7c3013 100644 --- a/tests/document.py +++ b/tests/document.py @@ -13,7 +13,8 @@ from trytond.exceptions import UserError from trytond.modules.company.tests import create_company, set_company from trytond.modules.account.tests import create_chart, get_fiscalyear from .parsed_data import ( - parsed_data_facturx_extended, parsed_data_facturx_basic) + parsed_data_facturx_extended, parsed_data_facturx_basic, + parsed_data_facturx_en16931) def set_invoice_sequences(fiscalyear): @@ -412,4 +413,121 @@ class DocumentTestCase(object): self.assertEqual(attachment.data, document.data) self.assertEqual(attachment.name, 'facturx-basic.xml') + @with_transaction() + def test_xmldoc_check_xml_read_facturx_en16931(self): + """ add incoming-dcument 'facturx-en16931' in memory, + read xml into 'parsed_data' + """ + pool = Pool() + IncDocument = pool.get('document.incoming') + + with open(os.path.join( + os.path.split(__file__)[0], + 'facturx-en16931.xml'), 'rb') as fhdl: + xml_txt = fhdl.read() + + incoming = IncDocument(data=xml_txt) + (xsdtype, funcname, xml_data) = incoming._facturx_detect_content() + self.assertEqual(xsdtype, 'Factur-X EN16931') + self.assertEqual(funcname, 'facturx_en16931') + + incoming._readxml_facturx_en16931(xml_data) + self.assertEqual( + self.prep_sorted_dict(incoming.parsed_data), + parsed_data_facturx_en16931) + + @with_transaction() + def test_xmldoc_import_facturx_en16931(self): + """ create incoming-document, load factur-x-en16931 xml, detect type + """ + pool = Pool() + IncDocument = pool.get('document.incoming') + Configuration = pool.get('document.incoming.configuration') + Party = pool.get('party.party') + IrAttachment = pool.get('ir.attachment') + Invoice = pool.get('account.invoice') + + company = create_company('m-ds') + with set_company(company): + + create_chart(company=company, tax=True) + self.prep_fiscalyear(company) + + product_categories = self.prep_prodcat_category(company) + config = Configuration( + product_category=product_categories) + config.save() + + self.assertEqual(config.create_supplier, True) + self.assertEqual(config.accept_other_company, False) + self.assertEqual(config.number_target, 'reference') + self.assertEqual(len(config.product_category), 3) + self.assertEqual(config.product_category[0].name, 'Accounting') + self.assertEqual(config.product_category[1].name, 'Accounting 19%') + self.assertEqual(config.product_category[2].name, 'Accounting 7%') + + to_create = [] + with open(os.path.join( + os.path.split(__file__)[0], + 'facturx-en16931.xml'), 'rb') as fhdl: + to_create.append({ + 'data': fhdl.read(), + 'name': 'facturx-en16931.xml', + 'type': 'supplier_invoice'}) + + document, = IncDocument.create(to_create) + self.assertEqual(document.mime_type, 'application/xml') + self.assertEqual(document.company.id, company.id) + self.assertTrue(document.data.startswith( + b'\n' + + b' + + + + urn:cen.eu:en16931:2017#conformant#urn:factur-x.eu:1p0:en16931 + + + + RE2024.01234 + 380 + + 20240617 + + + Description of invoice + + + Some notes to the customer. + + + Goes to field comment. + 42 + + + + + + 1 + + + Name of Product 1 + Description of Product 1 + + + + 1350.00 + + + + 1.0 + + + + VAT + S + 19.00 + + + 1350.00 + + + + + + 2 + + Description of Line 2 + + + + 3 + 4 + 5 + Name of Product 2 + Description of Product 2 + + Kilogram + kg + + + 3c + + + DE + + + + + 950.00 + 1.0 + + + 800.00 + 1.0 + + + + 1.5 + + + + VAT + S + 19.00 + + + 1200.00 + + + + + + 3 + + + Name of Product 3 + Description of Product 3 + + + + 150.00 + + + + 2.0 + + + + VAT + S + 7.00 + + + 300.00 + + + + + + Name of the Supplier + + + + 12345 + Street of Supplier No 1 + Berlin + DE + Berlin + + + + Our Company + + + + 23456 + Address Line 1 + Address Line 2 + Potsdam + DE + Brandenburg + + + + + + + + + + RE2024.01234 + EUR + + 30 + Wire transfer + + DE02300209000106531065 + Card Holder + + + DE02300209000106531065 + + + DE02300209000106531065 + mbs + + + WELADED1PMB + + + + 484.5 + VAT + 2550.0 + S + 19.00 + + + 21.0 + VAT + 300.0 + S + 7.00 + + + Payment description + + 20240701 + + mandat id + + + 1350.00 + 2850.00 + 505.5 + 3355.50 + 3355.50 + + + + diff --git a/tests/parsed_data.py b/tests/parsed_data.py index fcc1eb7..0722f61 100644 --- a/tests/parsed_data.py +++ b/tests/parsed_data.py @@ -7,6 +7,120 @@ from decimal import Decimal from datetime import date +parsed_data_facturx_en16931 = { + 'buyer_party': { + 'city': 'Potsdam', + 'name': 'Our Company', + 'postal_code': '23456', + 'street': 'Address Line 1\nAddress Line 2'}, + 'invoice_date': date(2024, 6, 17), + 'invoice_number': 'RE2024.01234', + 'lines_data': [{ + 'line_no': '1', + 'name': 'Name of Product 1', + 'description': 'Description of Product 1', + 'unit_net_price': {'amount': Decimal('1350.00')}, + 'quantity': { + 'billed': Decimal('1.0'), 'unit_code': 'KGM'}, + 'taxes': [{ + 'type': 'VAT', + 'category_code': 'S', + 'percent': Decimal('19.00')}], + 'total': {'amount': Decimal('1350.00')}, + }, { + 'line_no': '2', + 'line_note': 'Description of Line 2', + 'glob_id': '3', + 'seller_id': '4', + 'buyer_id': '5', + 'name': 'Name of Product 2', + 'description': 'Description of Product 2', + 'trade_country': 'DE', + 'attributes': [{ + 'description': 'Kilogram', + 'uom': 'kg'}], + 'classification': [{'code': '3c'}], + 'unit_net_price': { + 'amount': Decimal('800.00'), + 'basequantity': Decimal('1.0')}, + 'unit_gross_price': { + 'amount': Decimal('950.00'), + 'basequantity': Decimal('1.0')}, + 'quantity': { + 'billed': Decimal('1.5'), + 'unit_code': 'KGM'}, + 'taxes': [{ + 'type': 'VAT', + 'category_code': 'S', + 'percent': Decimal('19.00')}], + 'total': { + 'amount': Decimal('1200.00')}, + }, { + 'line_no': '3', + 'name': 'Name of Product 3', + 'description': 'Description of Product 3', + 'unit_net_price': {'amount': Decimal('150.00')}, + 'quantity': { + 'billed': Decimal('2.0'), + 'unit_code': 'MTR'}, + 'taxes': [{ + 'type': 'VAT', + 'category_code': 'S', + 'percent': Decimal('7.00')}], + 'total': {'amount': Decimal('300.00')}}], + 'note_list': [{ + 'Content': 'Description of invoice', + 'ContentCode': None, + 'SubjectCode': None, + }, { + 'Content': 'Some notes to the customer.', + 'ContentCode': None, + 'SubjectCode': None, + }, { + 'Content': 'Goes to field comment.', + 'ContentCode': None, + 'SubjectCode': '42'}], + 'payment': { + 'bank': [{ + 'info': 'Wire transfer', + 'type': '30', + 'debitor_iban': 'DE02300209000106531065', + 'creditor_iban': 'DE02300209000106531065', + 'creditor_name': 'mbs', + 'card_id': 'DE02300209000106531065', + 'card_holder_name': 'Card Holder', + 'institution': 'WELADED1PMB'}], + 'currency': 'EUR', + 'reference': 'RE2024.01234', + 'taxes': [{ + 'amount': Decimal('484.5'), + 'type': 'VAT', + 'base': Decimal('2550.0'), + 'category_code': 'S', + 'percent': Decimal('19.00'), + }, { + 'amount': Decimal('21.0'), + 'type': 'VAT', + 'base': Decimal('300.0'), + 'category_code': 'S', + 'percent': Decimal('7.00')}], + 'terms': [{ + 'description': 'Payment description', + 'duedate': date(2024, 7, 1), + 'mandat_id': 'mandat id'}]}, + 'seller_party': { + 'city': 'Berlin', + 'name': 'Name of the Supplier', + 'postal_code': '12345', + 'street': 'Street of Supplier No 1'}, + 'total': { + 'amount': Decimal('1350.00'), + 'duepayable': Decimal('3355.50'), + 'grand': Decimal('3355.50'), + 'taxbase': Decimal('2850.00'), + 'taxtotal': Decimal('505.5')}} + + parsed_data_facturx_basic = { 'buyer_party': { 'city': 'Potsdam',