From 0802ba7d0e6b1a00c71e7d4670444b6aedfb5b97 Mon Sep 17 00:00:00 2001 From: Raphael Michel Date: Mon, 30 Nov 2020 18:54:10 +0100 Subject: [PATCH] Close to first tests passing --- drafthorse/models/__init__.py | 1 + drafthorse/models/accounting.py | 31 ++++++++++++++++--------------- drafthorse/models/container.py | 5 +++-- drafthorse/models/document.py | 6 ++++-- drafthorse/models/elements.py | 7 +++++-- drafthorse/models/fields.py | 8 ++++++-- drafthorse/models/payment.py | 14 +++++++------- drafthorse/models/trade.py | 4 ++-- drafthorse/models/tradelines.py | 10 +++++----- 9 files changed, 49 insertions(+), 37 deletions(-) diff --git a/drafthorse/models/__init__.py b/drafthorse/models/__init__.py index 858ded3..b4ba96e 100644 --- a/drafthorse/models/__init__.py +++ b/drafthorse/models/__init__.py @@ -1,5 +1,6 @@ NS_RSM = "urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100" NS_UDT = "urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100" +NS_A = "urn:un:unece:uncefact:data:standard:UnqualifiedDataType:10" NS_RAM = "urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100" NS_QDT = "urn:un:unece:uncefact:data:standard:QualifiedDataType:10" BASIC = "BASIC" diff --git a/drafthorse/models/accounting.py b/drafthorse/models/accounting.py index 8cadcbe..893dbcf 100644 --- a/drafthorse/models/accounting.py +++ b/drafthorse/models/accounting.py @@ -1,3 +1,4 @@ + from . import BASIC, COMFORT, EXTENDED, NS_RAM from .elements import Element from .fields import ( @@ -7,8 +8,8 @@ from .fields import ( class LineApplicableTradeTax(Element): - calculated_amount = CurrencyField(NS_RAM, "CalculatedAmount", required=True, - profile=BASIC, _d="Steuerbetrag") + calculated_amount = DecimalField(NS_RAM, "CalculatedAmount", required=True, + profile=BASIC, _d="Steuerbetrag") type_code = StringField(NS_RAM, "TypeCode", required=True, profile=BASIC, _d="Steuerart (Code)") exemption_reason = StringField(NS_RAM, "ExemptionReason", required=False, @@ -24,7 +25,7 @@ class LineApplicableTradeTax(Element): class ApplicableTradeTax(Element): - calculated_amount = CurrencyField(NS_RAM, "CalculatedAmount", required=True, + calculated_amount = DecimalField(NS_RAM, "CalculatedAmount", required=True, profile=BASIC, _d="Steuerbetrag") type_code = StringField(NS_RAM, "TypeCode", required=True, profile=BASIC, _d="Steuerart (Code)") @@ -32,12 +33,12 @@ class ApplicableTradeTax(Element): profile=COMFORT, _d="Grund der Steuerbefreiung (Freitext)") exemption_reason_code = StringField(NS_RAM, "ExemptionReasonCode", required=False, profile=EXTENDED, _d="Grund der Steuerbefreiung (Code)") - basis_amount = CurrencyField(NS_RAM, "BasisAmount", required=True, + basis_amount = DecimalField(NS_RAM, "BasisAmount", required=True, profile=BASIC, _d="Basisbetrag der Steuerberechnung") - line_total_basis_amount = CurrencyField(NS_RAM, "LineTotalBasisAmount", + line_total_basis_amount = DecimalField(NS_RAM, "LineTotalBasisAmount", required=False, profile=EXTENDED, _d="Warenbetrag des Steuersatzes") - allowance_charge_basis_amount = CurrencyField(NS_RAM, "AllowanceChargeBasisAmount", + allowance_charge_basis_amount = DecimalField(NS_RAM, "AllowanceChargeBasisAmount", required=False, profile=EXTENDED, _d="Gesamtbetrag Zu- und Abschläge des Steuersatzes") category_code = StringField(NS_RAM, "CategoryCode", required=False, @@ -67,21 +68,21 @@ class ReceivableAccountingAccount(Element): class MonetarySummation(Element): - line_total = CurrencyField(NS_RAM, "LineTotalAmount", required=True, + line_total = DecimalField(NS_RAM, "LineTotalAmount", required=True, profile=BASIC, _d="Gesamtbetrag der Positionen") - charge_total = CurrencyField(NS_RAM, "ChargeTotalAmount", required=True, + charge_total = DecimalField(NS_RAM, "ChargeTotalAmount", required=True, profile=BASIC, _d="Gesamtbetrag der Zuschläge") - allowance_total = CurrencyField(NS_RAM, "AllowanceTotalAmount", required=True, + allowance_total = DecimalField(NS_RAM, "AllowanceTotalAmount", required=True, profile=BASIC, _d="Gesamtbetrag der Abschläge") - tax_basis_total = CurrencyField(NS_RAM, "TaxBasisTotalAmount", required=True, + tax_basis_total = DecimalField(NS_RAM, "TaxBasisTotalAmount", required=True, profile=BASIC, _d="Steuerbasisbetrag") tax_total = CurrencyField(NS_RAM, "TaxTotalAmount", required=True, profile=BASIC, _d="Steuergesamtbetrag") - grand_total = CurrencyField(NS_RAM, "GrandTotalAmount", required=True, + grand_total = DecimalField(NS_RAM, "GrandTotalAmount", required=True, profile=BASIC, _d="Bruttosumme") - prepaid_total = CurrencyField(NS_RAM, "TotalPrepaidAmount", required=False, + prepaid_total = DecimalField(NS_RAM, "TotalPrepaidAmount", required=False, profile=COMFORT, _d="Anzahlungsbetrag") - due_amount = CurrencyField(NS_RAM, "DuePayableAmount", required=False, + due_amount = DecimalField(NS_RAM, "DuePayableAmount", required=False, profile=COMFORT, _d="Zahlbetrag") class Meta: @@ -122,11 +123,11 @@ class TradeAllowanceCharge(Element): calculation_percent = DecimalField(NS_RAM, "CalculationPercent", required=False, profile=EXTENDED, _d="Rabatt in Prozent") - basis_amount = CurrencyField(NS_RAM, "BasisAmount", required=False, + basis_amount = DecimalField(NS_RAM, "BasisAmount", required=False, profile=EXTENDED, _d="Basisbetrag des Rabatts") basis_quantity = QuantityField(NS_RAM, "BasisQuantity", required=False, profile=EXTENDED, _d="Basismenge des Rabatts") - actual_amount = CurrencyField(NS_RAM, "ActualAmount", required=True, + actual_amount = DecimalField(NS_RAM, "ActualAmount", required=True, profile=COMFORT, _d="Betrag des Zu-/Abschlags") reason_code = StringField(NS_RAM, "ReasonCode", required=False, profile=EXTENDED) reason = StringField(NS_RAM, "Reason", required=False, profile=COMFORT) diff --git a/drafthorse/models/container.py b/drafthorse/models/container.py index 3629300..981fb44 100644 --- a/drafthorse/models/container.py +++ b/drafthorse/models/container.py @@ -57,10 +57,11 @@ class CurrencyContainer(SimpleContainer): return CurrencyElement(namespace=self.namespace, tag=self.tag) def set_element(self, el, child): - el.amount = child + el.amount = child[0] + el.currency = child[1] def add_from_etree(self, root): - self.add(root.text) + self.add((root.text, root.attrib['currencyID'])) class IDContainer(SimpleContainer): diff --git a/drafthorse/models/document.py b/drafthorse/models/document.py index 29669f3..fd4a097 100644 --- a/drafthorse/models/document.py +++ b/drafthorse/models/document.py @@ -2,7 +2,7 @@ import xml.etree.cElementTree as ET from drafthorse.models.note import IncludedNote -from . import BASIC, EXTENDED, NS_RAM, NS_UDT, NS_RSM +from . import BASIC, EXTENDED, NS_RAM, NS_UDT, NS_RSM, NS_QDT, NS_A from .elements import Element from .fields import ( DateTimeField, Field, IndicatorField, MultiField, MultiStringField, @@ -76,9 +76,11 @@ class Invoice(Element): def __init__(self): super().__init__() - ET.register_namespace("xsi", "http://www.w3.org/2001/XMLSchema-instance") + ET.register_namespace("a", NS_A) ET.register_namespace("rsm", NS_RSM) + ET.register_namespace("qdt", NS_QDT) ET.register_namespace("ram", NS_RAM) + ET.register_namespace("xsi", "http://www.w3.org/2001/XMLSchema") ET.register_namespace("udt", NS_UDT) class Meta: diff --git a/drafthorse/models/elements.py b/drafthorse/models/elements.py index 249d738..2c95b18 100644 --- a/drafthorse/models/elements.py +++ b/drafthorse/models/elements.py @@ -159,21 +159,24 @@ class QuantityElement(StringElement): class CurrencyElement(StringElement): - def __init__(self, namespace, tag, amount=""): + def __init__(self, namespace, tag, amount="", currency="EUR"): super().__init__(namespace, tag) self.amount = amount + self.currency = currency def to_etree(self): node = self._etree_node() node.text = str(self.amount) + node.attrib["currencyID"] = self.currency return node def from_etree(self, root): self.amount = Decimal(root.text) + self.currency = root.attrib.get('currencyID', 'EUR') return self def __str__(self): - return self.amount + return "{} {}".format(self.amount, self.currency) class ClassificationElement(StringElement): diff --git a/drafthorse/models/fields.py b/drafthorse/models/fields.py index 2a8558b..ca733f2 100644 --- a/drafthorse/models/fields.py +++ b/drafthorse/models/fields.py @@ -155,7 +155,11 @@ class CurrencyField(Field): if instance._data.get(self.name, None) is None: instance._data[self.name] = self.initialize() - instance._data[self.name].amount = value + if not isinstance(value, (tuple, list)): + raise TypeError("Please pass a 2-tuple of including amount and currency.") + + instance._data[self.name].amount = value[0] + instance._data[self.name].currency = value[1] def initialize(self): return self.cls(self.namespace, self.tag) @@ -228,7 +232,7 @@ class MultiStringField(Field): return self.cls(child_type=str, namespace=self.namespace, tag=self.tag) -class MultiCurrencyField(Field): +class MultiDecimalField(Field): def __init__(self, namespace, tag, default=False, required=False, profile=BASIC, _d=None): super().__init__(CurrencyContainer, default, required, profile, _d) self.namespace = namespace diff --git a/drafthorse/models/payment.py b/drafthorse/models/payment.py index ec900b1..5037733 100644 --- a/drafthorse/models/payment.py +++ b/drafthorse/models/payment.py @@ -1,8 +1,8 @@ from . import BASIC, COMFORT, EXTENDED, NS_RAM from .elements import Element from .fields import ( - AgencyIDField, CurrencyField, DateTimeField, DecimalField, Field, - MultiCurrencyField, MultiStringField, QuantityField, StringField, + AgencyIDField, DecimalField, DateTimeField, DecimalField, Field, + MultiDecimalField, MultiStringField, QuantityField, StringField, ) @@ -40,11 +40,11 @@ class PaymentPenaltyTerms(Element): profile=EXTENDED, _d="Bezugsdatum der Fälligkeit") basis_period_measure = QuantityField(NS_RAM, "BasisPeriodMeasure", required=False, profile=EXTENDED, _d="Fälligkeitszeitraum") - basis_amount = CurrencyField(NS_RAM, "BasisAmount", required=False, + basis_amount = DecimalField(NS_RAM, "BasisAmount", required=False, profile=EXTENDED, _d="Basisbetrag des Zahlungszuschlags") calculation_percent = DecimalField(NS_RAM, "CalculationPercent", required=False, profile=EXTENDED, _d="Prozentwert des Zahlungszuschlags") - actual_amount = CurrencyField(NS_RAM, "ActualPenaltyAmount", required=False, + actual_amount = DecimalField(NS_RAM, "ActualPenaltyAmount", required=False, profile=EXTENDED, _d="Betrag des Zahlungszuschlags") class Meta: @@ -57,11 +57,11 @@ class PaymentDiscountTerms(Element): profile=EXTENDED, _d="Bezugsdatum der Fälligkeit") basis_period_measure = QuantityField(NS_RAM, "BasisPeriodMeasure", required=False, profile=EXTENDED, _d="Fälligkeitszeitraum") - basis_amount = CurrencyField(NS_RAM, "BasisAmount", required=False, + basis_amount = DecimalField(NS_RAM, "BasisAmount", required=False, profile=EXTENDED, _d="Basisbetrag des Zahlungsabschlags") calculation_percent = DecimalField(NS_RAM, "CalculationPercent", required=False, profile=EXTENDED, _d="Prozentwert des Zahlungsabschlags") - actual_amount = CurrencyField(NS_RAM, "ActualDiscountAmount", required=False, + actual_amount = DecimalField(NS_RAM, "ActualDiscountAmount", required=False, profile=EXTENDED, _d="Betrag des Zahlungsabschlags") class Meta: @@ -74,7 +74,7 @@ class PaymentTerms(Element): _d="Freitext der Zahlungsbedingungen") due = DateTimeField(NS_RAM, "DueDateDateTime", required=False, profile=COMFORT, _d="Fälligkeitsdatum") - partial_amount = MultiCurrencyField(NS_RAM, "PartialPaymentAmount", profile=EXTENDED, + partial_amount = MultiDecimalField(NS_RAM, "PartialPaymentAmount", profile=EXTENDED, required=False, _d="Betrag der Teilzahlung") penalty_terms = Field(PaymentPenaltyTerms, required=False, profile=EXTENDED, _d="Detailinformationen zu Zahlungszuschlägen") diff --git a/drafthorse/models/trade.py b/drafthorse/models/trade.py index 6e48aae..c299606 100644 --- a/drafthorse/models/trade.py +++ b/drafthorse/models/trade.py @@ -5,7 +5,7 @@ from .accounting import ( ) from .delivery import TradeDelivery from .elements import Element -from .fields import CurrencyField, Field, MultiField, StringField +from .fields import DecimalField, Field, MultiField, StringField from .party import ( BuyerTradeParty, EndUserTradeParty, InvoiceeTradeParty, PayeeTradeParty, SellerTradeParty, @@ -48,7 +48,7 @@ class TradeAgreement(Element): class LogisticsServiceCharge(Element): description = StringField(NS_RAM, "Description", required=True, profile=COMFORT, _d="Identifikation der Servicegebühr") - applied_amount = CurrencyField(NS_RAM, "AppliedAmount", required=True, + applied_amount = DecimalField(NS_RAM, "AppliedAmount", required=True, profile=COMFORT, _d="Betrag der Servicegebühr") trade_tax = MultiField(AppliedTradeTax, required=False, profile=COMFORT) diff --git a/drafthorse/models/tradelines.py b/drafthorse/models/tradelines.py index 82b0d7a..9ba88fb 100644 --- a/drafthorse/models/tradelines.py +++ b/drafthorse/models/tradelines.py @@ -6,7 +6,7 @@ from .accounting import ( from .delivery import SupplyChainEvent from .elements import Element from .fields import ( - CurrencyField, Field, MultiField, QuantityField, StringField, + DecimalField, Field, MultiField, QuantityField, StringField, ) from .note import IncludedNote from .party import ShipToTradeParty, UltimateShipToTradeParty @@ -26,7 +26,7 @@ class AllowanceCharge(TradeAllowanceCharge): class GrossPrice(Element): - amount = CurrencyField(NS_RAM, "ChargeAmount", required=True, profile=COMFORT, + amount = DecimalField(NS_RAM, "ChargeAmount", required=True, profile=COMFORT, _d="Bruttopreis") basis_quantity = QuantityField(NS_RAM, "BasisQuantity", required=False, profile=COMFORT, _d="Preisbasismenge") @@ -38,7 +38,7 @@ class GrossPrice(Element): class NetPrice(Element): - amount = CurrencyField(NS_RAM, "ChargeAmount", required=True, profile=COMFORT) + amount = DecimalField(NS_RAM, "ChargeAmount", required=True, profile=COMFORT) basis_quantity = QuantityField(NS_RAM, "BasisQuantity", required=False, profile=COMFORT, _d="Preisbasismenge") @@ -94,9 +94,9 @@ class LineDelivery(Element): class LineSummation(Element): - total_amount = CurrencyField(NS_RAM, "LineTotalAmount", required=True, + total_amount = DecimalField(NS_RAM, "LineTotalAmount", required=True, profile=COMFORT) - total_allowance_charge = CurrencyField(NS_RAM, "TotalAllowanceChargeAmount", + total_allowance_charge = DecimalField(NS_RAM, "TotalAllowanceChargeAmount", required=False, profile=EXTENDED, _d="Gesamtbetrag der Zu- und Abschläge") class Meta: -- 2.47.3