From: Raphael Michel Date: Wed, 3 Aug 2022 10:55:27 +0000 (+0200) Subject: Make samples in README work X-Git-Tag: 2.2.0~1^2~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=845a58212bf384ad1a07205cce3f89e0dff5340b;p=thirdparty%2Fpython-drafthorse.git Make samples in README work --- diff --git a/README.rst b/README.rst index dbd5c06..50e00d1 100644 --- a/README.rst +++ b/README.rst @@ -15,48 +15,98 @@ format for sending digital invoices. ZUGFeRD XML files are to be attached to a P file. This library can be used to generate or parse the contents of this XML file as well as attach it to a PDF. We do not support parsing PDF files (for now). -By low-level, we mean that this library models the ZUGFeRD data model 1:1 without any further -abstractions or simplifications. You can set and parse all parameters defined in ZUGFeRD 2.1. +By low-level, we mean that this library tries to model the ZUGFeRD data model 1:1 without any +further abstractions or simplifications. You can set and parse all parameters defined in ZUGFeRD +2.2. -All output is validated against the official XSDs, but no validation of profile levels (basic, comfort, extended) is performed. +All output is validated against the official XSDs, but no validation of profile levels +(basic, comfort, extended) is performed. Usage ----- Parsing:: - >>> from drafthorse.models.document import Document - >>> samplexml = open("sample.xml", "rb").read() - >>> doc = Document.parse(samplexml) - >>> str(doc.trade.agreement.seller.name) - 'Lieferant GmbH' + from drafthorse.models.document import Document + samplexml = open("sample.xml", "rb").read() + doc = Document.parse(samplexml) + print(doc.trade.agreement.seller.name) Generating:: - >>> from datetime import date - >>> from drafthorse.models.document import Document - >>> from drafthorse.models.note import IncludedNote - - >>> doc = Document() - >>> doc.context.guideline_parameter.id = "urn:ferd:CrossIndustryDocument:invoice:1p0:comfort" - >>> doc.header.id = "RE1337" - >>> doc.header.name = "RECHNUNG" - >>> doc.header.type_code = "380" - >>> doc.header.issue_date_time.value = date.today() - >>> doc.header.languages.add("de") - >>> note = IncludedNote() - >>> note.content.add("Test Node 1") - >>> doc.header.notes.add(n) - >>> doc.trade.agreement.seller.name = "Lieferant GmbH" - - >>> xml = doc.serialize() - >>> xml - b'>> new_pdf_bytes = attach_xml(original_pdf_bytes, xml, 'BASIC') + with open("input.pdf", "rb") as original_file: + new_pdf_bytes = attach_xml(original_file.read(), xml, 'EXTENDED') + + with open("output.pdf", "wb") as f: + f.write(new_pdf_bytes) Development diff --git a/tests/samples/Empty.pdf b/tests/samples/Empty.pdf new file mode 100644 index 0000000..eae1b7a Binary files /dev/null and b/tests/samples/Empty.pdf differ diff --git a/tests/test_mininal.py b/tests/test_mininal.py new file mode 100644 index 0000000..7b4bdfc --- /dev/null +++ b/tests/test_mininal.py @@ -0,0 +1,66 @@ +import os +from datetime import date +from decimal import Decimal + +from drafthorse.models.accounting import ApplicableTradeTax +from drafthorse.models.document import Document +from drafthorse.models.note import IncludedNote +from drafthorse.models.tradelines import LineItem +from drafthorse.pdf import attach_xml + + +def test_readme_construction_example(): + doc = Document() + doc.context.guideline_parameter.id = "urn:cen.eu:en16931:2017#conformant#urn:factur-x.eu:1p0:extended" + doc.header.id = "RE1337" + doc.header.type_code = "380" + doc.header.name = "RECHNUNG" + doc.header.issue_date_time = date.today() + doc.header.languages.add("de") + + note = IncludedNote() + note.content.add("Test Node 1") + doc.header.notes.add(note) + + doc.trade.agreement.seller.name = "Lieferant GmbH" + doc.trade.settlement.payee.name = "Kunde GmbH" + + doc.trade.agreement.buyer.name = "Kunde GmbH" + doc.trade.settlement.invoicee.name = "Kunde GmbH" + + doc.trade.settlement.currency_code = "EUR" + doc.trade.settlement.payment_means.type_code = "ZZZ" + + li = LineItem() + li.document.line_id = "1" + li.product.name = "Rainbow" + li.agreement.gross.amount = Decimal("999.00") + li.agreement.gross.basis_quantity = (Decimal("1.0000"), "C62") # C62 == pieces + li.agreement.net.amount = Decimal("999.00") + li.agreement.net.basis_quantity = (Decimal("999.00"), "EUR") + li.delivery.billed_quantity = (Decimal("1.0000"), "C62") # C62 == pieces + li.settlement.trade_tax.type_code = "VAT" + li.settlement.trade_tax.category_code = "E" + li.settlement.trade_tax.rate_applicable_percent = Decimal("0.00") + li.settlement.monetary_summation.total_amount = Decimal("999.00") + doc.trade.items.add(li) + + trade_tax = ApplicableTradeTax() + trade_tax.calculated_amount = Decimal("0.00") + trade_tax.basis_amount = Decimal("999.00") + trade_tax.type_code = "VAT" + trade_tax.category_code = "E" + trade_tax.rate_applicable_percent = Decimal("0.00") + doc.trade.settlement.trade_tax.add(trade_tax) + + doc.trade.settlement.monetary_summation.line_total = Decimal("999.00") + doc.trade.settlement.monetary_summation.charge_total = Decimal("0.00") + doc.trade.settlement.monetary_summation.allowance_total = Decimal("0.00") + doc.trade.settlement.monetary_summation.tax_basis_total = Decimal("999.00") + doc.trade.settlement.monetary_summation.tax_total = Decimal("0.00") + doc.trade.settlement.monetary_summation.grand_total = Decimal("999.00") + doc.trade.settlement.monetary_summation.due_amount = Decimal("999.00") + + xml = doc.serialize(schema="FACTUR-X_EXTENDED") + with open(os.path.join(os.path.dirname(__file__), "samples", "Empty.pdf"), "rb") as original_file: + assert attach_xml(original_file.read(), xml, 'EXTENDED') diff --git a/tests/test_roundtrip.py b/tests/test_roundtrip.py index fd53e50..47c0cc0 100644 --- a/tests/test_roundtrip.py +++ b/tests/test_roundtrip.py @@ -1,5 +1,4 @@ import os -import sys from difflib import unified_diff import pytest @@ -8,7 +7,7 @@ import lxml.etree from drafthorse.models.document import Document from drafthorse.utils import prettify, validate_xml -samples = os.listdir(os.path.join(os.path.dirname(__file__), "samples")) +samples = [f for f in os.listdir(os.path.join(os.path.dirname(__file__), "samples")) if f.endswith(".xml")] def _diff_xml(a, b):