]> git.ipfire.org Git - thirdparty/python-drafthorse.git/commitdiff
Make samples in README work
authorRaphael Michel <michel@rami.io>
Wed, 3 Aug 2022 10:55:27 +0000 (12:55 +0200)
committerRaphael Michel <michel@rami.io>
Wed, 3 Aug 2022 10:55:48 +0000 (12:55 +0200)
README.rst
tests/samples/Empty.pdf [new file with mode: 0644]
tests/test_mininal.py [new file with mode: 0644]
tests/test_roundtrip.py

index dbd5c06974cf9a462a61ac6329244e29cb21c4bf..50e00d1a99ac6178283817ab352a9fd0c9a92f21 100644 (file)
@@ -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'<?xml version="1.0" encoding="UTF-8"?><rsm:CrossIndustryDocument …'
+    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
+
+    # Build data structure
+    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")
+
+    # Generate XML file
+    xml = doc.serialize(schema="FACTUR-X_EXTENDED")
 
     # Attach XML to an existing PDF.
     # Note that the existing PDF should be compliant to PDF/A-3!
     # You can validate this here: https://www.pdf-online.com/osa/validate.aspx
-    >>> 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 (file)
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 (file)
index 0000000..7b4bdfc
--- /dev/null
@@ -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')
index fd53e501589d9eeb48e9139b87e38c935b12c947..47c0cc0b9122d833f1d966d228179554a9b4fcb2 100644 (file)
@@ -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):