diff --git a/README.rst b/README.rst index b2ba766..63f6f94 100644 --- a/README.rst +++ b/README.rst @@ -49,38 +49,36 @@ Parsing:: Generating:: - from datetime import date, datetime, timezone + from datetime import date, datetime, timedelta, timezone 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.party import TaxRegistration + from drafthorse.models.payment import PaymentTerms + from drafthorse.models.payment import PaymentMeans + from drafthorse.models.trade import AdvancePayment, IncludedTradeTax 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.context.guideline_parameter.id = "urn:cen.eu:en16931:2017" 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 = "Lieferant GmbH" + doc.header.notes.add(IncludedNote(content="Test Note 1")) doc.trade.agreement.buyer.name = "Kunde GmbH" - doc.trade.settlement.invoicee.name = "Kunde GmbH" + doc.trade.agreement.buyer.address.country_id = "DE" doc.trade.settlement.currency_code = "EUR" - doc.trade.settlement.payment_means.type_code = "ZZZ" + doc.trade.settlement.payment_means.add(PaymentMeans(type_code="ZZZ")) + doc.trade.agreement.seller.name = "Lieferant GmbH" doc.trade.agreement.seller.address.country_id = "DE" doc.trade.agreement.seller.address.country_subdivision = "Bayern" doc.trade.agreement.seller.tax_registrations.add( @@ -89,41 +87,52 @@ Generating:: ) ) - doc.trade.agreement.seller_order.issue_date_time = datetime.now(timezone.utc) - doc.trade.agreement.buyer_order.issue_date_time = datetime.now(timezone.utc) - doc.trade.settlement.advance_payment.received_date = datetime.now(timezone.utc) - doc.trade.agreement.customer_order.issue_date_time = datetime.now(timezone.utc) + advance = AdvancePayment( + received_date=datetime.now(timezone.utc), paid_amount=Decimal(42) + ) + advance.included_trade_tax.add( + IncludedTradeTax( + calculated_amount=Decimal(0), + type_code="VAT", + category_code="E", + rate_applicable_percent=Decimal(0), + ) + ) + doc.trade.settlement.advance_payment.add(advance) 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"), "H87") # H87 == pieces - li.agreement.net.amount = Decimal("999.00") - li.agreement.net.basis_quantity = (Decimal("999.00"), "EUR") - li.delivery.billed_quantity = (Decimal("1.0000"), "H87") # H87 == pieces + li.agreement.gross.amount = Decimal("1198.8") + li.agreement.gross.basis_quantity = (Decimal("1.0000"), "C62") # C62 == unit + li.agreement.net.amount = Decimal("999") + li.agreement.net.basis_quantity = (Decimal("1.0000"), "C62") # C62 == unit + li.delivery.billed_quantity = (Decimal("1.0000"), "C62") # C62 == unit 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.trade_tax.category_code = "S" + li.settlement.trade_tax.rate_applicable_percent = Decimal("20.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.calculated_amount = Decimal("199.80") trade_tax.basis_amount = Decimal("999.00") trade_tax.type_code = "VAT" - trade_tax.category_code = "AE" - trade_tax.exemption_reason_code = 'VATEX-EU-AE' - trade_tax.rate_applicable_percent = Decimal("0.00") + trade_tax.category_code = "S" + trade_tax.rate_applicable_percent = Decimal("20.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") + doc.trade.settlement.monetary_summation.tax_total = (Decimal("199.80"), "EUR") + doc.trade.settlement.monetary_summation.grand_total = Decimal("1198.8") + doc.trade.settlement.monetary_summation.due_amount = Decimal("1198.8") + + terms = PaymentTerms() + terms.due = datetime.now(timezone.utc) + timedelta(days=30) + doc.trade.settlement.terms.add(terms) # Generate XML file xml = doc.serialize(schema="FACTUR-X_EXTENDED") diff --git a/tests/conftest.py b/tests/conftest.py index 5238a6f..7c1ad10 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,80 +1,24 @@ import os import pytest -from datetime import date, datetime, timezone -from decimal import Decimal +import re +from pathlib import Path +from textwrap import dedent -from drafthorse.models.accounting import ApplicableTradeTax -from drafthorse.models.document import Document -from drafthorse.models.note import IncludedNote -from drafthorse.models.party import TaxRegistration -from drafthorse.models.tradelines import LineItem +README_PATH = Path(__file__).parent.parent / "README.rst" @pytest.fixture def invoice_document(request): - doc = Document() - doc.context.guideline_parameter.id = ( - "urn:cen.eu:en16931:2017#conformant#urn:factur-x.eu:1p0:extended" + readme = README_PATH.read_text(encoding="UTF-8") + readme_example = re.search( + "Generating::$" "(?P.*)" "# Attach XML to an existing PDF.$", + readme, + flags=re.MULTILINE | re.DOTALL, ) - doc.header.id = "RE1337" - doc.header.type_code = request.param - doc.header.name = "RECHNUNG" - doc.header.issue_date_time = date.today() - doc.header.languages.add("de") - - doc.header.notes.add(IncludedNote(content="Test Node 1")) - - doc.trade.agreement.seller.name = "Lieferant GmbH" - doc.trade.settlement.payee.name = "Lieferant 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" - - doc.trade.agreement.seller.address.country_id = "DE" - doc.trade.agreement.seller.address.country_subdivision = "Bayern" - doc.trade.agreement.seller.tax_registrations.add( - TaxRegistration(id=("VA", "DE000000000")) - ) - - doc.trade.agreement.seller_order.issue_date_time = datetime.now(timezone.utc) - doc.trade.agreement.buyer_order.issue_date_time = datetime.now(timezone.utc) - doc.trade.settlement.advance_payment.received_date = datetime.now(timezone.utc) - doc.trade.agreement.customer_order.issue_date_time = datetime.now(timezone.utc) - - 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"), "C62") - 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"), "EUR") - doc.trade.settlement.monetary_summation.grand_total = Decimal("999.00") - doc.trade.settlement.monetary_summation.due_amount = Decimal("999.00") - - return doc + assert readme_example + local_ns = {} + exec(dedent(readme_example["example"]), locals=local_ns) + return local_ns['doc'] @pytest.fixture