From 677467d4c35c130e4f56f0934a6b22bb05e05c24 Mon Sep 17 00:00:00 2001 From: Daniel Egger Date: Wed, 29 May 2024 14:22:35 +0200 Subject: [PATCH] Refactor Abacus invoice xml code --- server/vbv_lernwelt/shop/invoice/abacus.py | 74 +++++----- .../vbv_lernwelt/shop/tests/test_invoice.py | 126 +++++++++++++++--- 2 files changed, 153 insertions(+), 47 deletions(-) diff --git a/server/vbv_lernwelt/shop/invoice/abacus.py b/server/vbv_lernwelt/shop/invoice/abacus.py index a92b1056..946d5750 100644 --- a/server/vbv_lernwelt/shop/invoice/abacus.py +++ b/server/vbv_lernwelt/shop/invoice/abacus.py @@ -31,7 +31,7 @@ class AbacusInvoiceCreator(InvoiceCreator): ) ] - invoice = self.invoice_xml( + invoice = self.render_invoice_xml( customer_number, order_date, reference_purchase_order, @@ -45,12 +45,12 @@ class AbacusInvoiceCreator(InvoiceCreator): self.repository.upload_invoice(invoice, filename) @staticmethod - def invoice_xml( - customer_number: str, + def render_invoice_xml( + abacus_debitor_number: int, + abacus_order_id: int, + datatrans_transaction_id: str, order_date: datetime.date, - reference_purchase_order: str, - unic_id: str, - items: List[Item], + item_description: str, ) -> str: container = Element("AbaConnectContainer") task = SubElement(container, "Task") @@ -66,37 +66,51 @@ class AbacusInvoiceCreator(InvoiceCreator): sales_order_header, "SalesOrderHeaderFields", mode="SAVE" ) - SubElement(sales_order_header_fields, "CustomerNumber").text = customer_number + # Skender: Kundennummer, erste Ziffer abhängig von der Plattform (4 = LMS, 6 = myVBV, 7 = EduManager), Plattform führt ein eigenständiges hochzählendes Mapping. + SubElement(sales_order_header_fields, "CustomerNumber").text = str( + abacus_debitor_number + ) + + # Skender: ePayment: Ablaufnr. für ePayment Rechnung in Abacus + SubElement(sales_order_header_fields, "ProcessFlowNumber").text = "30" + + # Skender: ePayment: Zahlungskondition für ePaymente in Abacus 9999 Tage Mahnungsfrist, da schon bezahlt + SubElement(sales_order_header_fields, "PaymentCode").text = "9999" + + # Skender: Bestellzeitpunkt SubElement( sales_order_header_fields, "PurchaseOrderDate" ).text = order_date.isoformat() - SubElement( - sales_order_header_fields, "DeliveryDate" - ).text = order_date.isoformat() + + # Skender: ePayment: TRANSACTION-ID von Datatrans in Bestellreferenz SubElement( sales_order_header_fields, "ReferencePurchaseOrder" - ).text = reference_purchase_order - SubElement(sales_order_header_fields, "UnicId").text = unic_id + ).text = datatrans_transaction_id - for index, item in enumerate(items, start=1): - item_element = SubElement(sales_order_header, "Item", mode="SAVE") - item_fields = SubElement(item_element, "ItemFields", mode="SAVE") - SubElement(item_fields, "ItemNumber").text = str(index) - SubElement(item_fields, "ProductNumber").text = item.product_number - SubElement(item_fields, "QuantityOrdered").text = str(item.quantity) + # Skender: ePayment: OrderID. max 10 Ziffern, erste Ziffer abhängig von der Plattform (4 = LMS, 6 = myVBV, 7 = EduManager) + SubElement(sales_order_header_fields, "GroupingNumberAscii1").text = str( + abacus_order_id + ) - item_text = SubElement(item_element, "ItemText", mode="SAVE") - item_text_fields = SubElement(item_text, "ItemTextFields", mode="SAVE") - SubElement(item_text_fields, "Text").text = item.description + item_element = SubElement(sales_order_header, "Item", mode="SAVE") + item_fields = SubElement(item_element, "ItemFields", mode="SAVE") + SubElement(item_fields, "DeliveryDate").text = order_date.isoformat() + SubElement(item_fields, "ItemNumber").text = "1" + SubElement(item_fields, "ProductNumber").text = "30202" + SubElement(item_fields, "QuantityOrdered").text = "1" + + item_text = SubElement(item_element, "ItemText", mode="SAVE") + item_text_fields = SubElement(item_text, "ItemTextFields", mode="SAVE") + SubElement(item_text_fields, "Text").text = item_description return AbacusInvoiceCreator.create_xml_string(container) @staticmethod - def customer_xml( - customer_number: str, - name: str, + def render_customer_xml( + abacus_debitor_number: int, + last_name: str, first_name: str, - address_text: str, + company_name: str, street: str, house_number: str, zip_code: str, @@ -117,16 +131,16 @@ class AbacusInvoiceCreator(InvoiceCreator): transaction = SubElement(task, "Transaction") customer_element = SubElement(transaction, "Customer", mode="SAVE") - SubElement(customer_element, "CustomerNumber").text = customer_number + SubElement(customer_element, "CustomerNumber").text = str(abacus_debitor_number) SubElement(customer_element, "DefaultCurrency").text = "CHF" SubElement(customer_element, "PaymentTermNumber").text = "1" SubElement(customer_element, "ReminderProcedure").text = "NORM" address_data = SubElement(customer_element, "AddressData", mode="SAVE") - SubElement(address_data, "AddressNumber").text = customer_number - SubElement(address_data, "Name").text = name + SubElement(address_data, "AddressNumber").text = str(abacus_debitor_number) + SubElement(address_data, "Name").text = last_name SubElement(address_data, "FirstName").text = first_name - SubElement(address_data, "Text").text = address_text + SubElement(address_data, "Text").text = company_name SubElement(address_data, "Street").text = street SubElement(address_data, "HouseNumber").text = house_number SubElement(address_data, "ZIP").text = zip_code @@ -138,7 +152,7 @@ class AbacusInvoiceCreator(InvoiceCreator): return AbacusInvoiceCreator.create_xml_string(container) @staticmethod - def create_xml_string(container: Element, encoding: str = "UTF-8") -> str: + def create_xml_string(container: Element, encoding: str = "utf-8") -> str: xml_bytes = tostring(container, encoding) xml_pretty_str = minidom.parseString(xml_bytes).toprettyxml( indent=" ", encoding=encoding diff --git a/server/vbv_lernwelt/shop/tests/test_invoice.py b/server/vbv_lernwelt/shop/tests/test_invoice.py index 538aeaf3..15c9c661 100644 --- a/server/vbv_lernwelt/shop/tests/test_invoice.py +++ b/server/vbv_lernwelt/shop/tests/test_invoice.py @@ -23,30 +23,122 @@ class InvoiceTestCase(TestCase): is_active=True, ) - def test_render_invoice(self): + def test_render_invoice_xml(self): # GIVEN creator = AbacusInvoiceCreator(repository=create_autospec(InvoiceRepository)) - items = [Item(product_number="001", quantity=1, description="Test Item")] - customer_number = "12345" - order_date = date(2023, 1, 1) - reference_purchase_order = "PO12345678" - unic_id = "UNIC001" # WHEN - invoice_xml = creator.invoice_xml( - customer_number, - order_date, - reference_purchase_order, - unic_id, - items, + invoice_xml = creator.render_invoice_xml( + abacus_debitor_number=60000012, + abacus_order_id=6000000001, + order_date=date(2024, 2, 15), + datatrans_transaction_id="24021508331287484", + item_description="myVBV Versicherungsvermittler - Lernpfad, 2024-02-15, Skender, Gebhart-Krasniqi", ) + # example from Skender + expected_xml = """ + + + + ORDE + Verkaufsauftrag + AbaDefault + 2022.00 + + + + + 60000012 + 30 + 9999 + 2024-02-15 + 24021508331287484 + 6000000001 + + + + 2024-02-15 + 1 + 30202 + 1 + + + + myVBV Versicherungsvermittler - Lernpfad, 2024-02-15, Skender, Gebhart-Krasniqi + + + + + + + + """ + # THEN - assert "12345" in invoice_xml - assert "1" in invoice_xml - assert "001" in invoice_xml - assert "1" in invoice_xml - assert "Test Item" in invoice_xml + self.maxDiff = None + self.assertXMLEqual(expected_xml, invoice_xml) + + def test_render_customer_xml(self): + # GIVEN + creator = AbacusInvoiceCreator( + repository=create_autospec(InvoiceRepository)) + + # WHEN + customer_xml = creator.render_customer_xml( + abacus_debitor_number=60000012, + last_name="Gebhart-Krasniqi", + first_name="Skender", + company_name="VBV", + street="Laupenstrasse", + house_number="10", + zip_code="3000", + city="Bern", + country="CH", + language="de", + email="skender.krasniqi@vbv-afa.ch" + ) + + print(customer_xml) + + # example from Skender + expected_xml = """ + + + + DEBI + Kunden + AbaDefault + 2022.00 + + + + 60000012 + CHF + 1 + NORM + + 60000012 + Gebhart-Krasniqi + Skender + VBV + Laupenstrasse + 10 + 3000 + Bern + CH + de + skender.krasniqi@vbv-afa.ch + + + + + + """ + + # THEN + self.maxDiff = None + self.assertXMLEqual(expected_xml, customer_xml) def test_create_invoice_calls_upload(self): # GIVEN