From 0b101f836e011d8b7ef175a1c33cedf4fa09962b Mon Sep 17 00:00:00 2001 From: HorstOeko Date: Sat, 16 Nov 2024 07:34:43 +0100 Subject: [PATCH] #169 Handle Decimals of the measure type --- examples/ExtendedSimple.php | 55 ++++++++++++++++++++++++++++++++ src/ZugferdSettings.php | 28 ++++++++++++++++ src/jms/ZugferdTypesHandler.php | 54 +++++++++++++++++++++++++++++-- tests/testcases/SettingsTest.php | 14 ++++++++ 4 files changed, 148 insertions(+), 3 deletions(-) create mode 100644 examples/ExtendedSimple.php diff --git a/examples/ExtendedSimple.php b/examples/ExtendedSimple.php new file mode 100644 index 0000000..67c7ff9 --- /dev/null +++ b/examples/ExtendedSimple.php @@ -0,0 +1,55 @@ +setDocumentInformation("471102", "380", \DateTime::createFromFormat("Ymd", "20180305"), "EUR") + ->addDocumentNote('Rechnung gemäß Bestellung vom 01.03.2018.') + ->addDocumentNote('Lieferant GmbH' . PHP_EOL . 'Lieferantenstraße 20' . PHP_EOL . '80333 München' . PHP_EOL . 'Deutschland' . PHP_EOL . 'Geschäftsführer: Hans Muster' . PHP_EOL . 'Handelsregisternummer: H A 123' . PHP_EOL . PHP_EOL, null, 'REG') + ->setDocumentSupplyChainEvent(\DateTime::createFromFormat('Ymd', '20180305')) + ->addDocumentPaymentMean(ZugferdPaymentMeans::UNTDID_4461_58, null, null, null, null, null, "DE12500105170648489890", null, null, null) + ->setDocumentSeller("Lieferant GmbH", "549910") + ->addDocumentSellerGlobalId("4000001123452", "0088") + ->addDocumentSellerTaxRegistration("FC", "201/113/40209") + ->addDocumentSellerTaxRegistration("VA", "DE123456789") + ->setDocumentSellerAddress("Lieferantenstraße 20", "", "", "80333", "München", "DE") + ->setDocumentSellerContact("Heinz Mükker", "Buchhaltung", "+49-111-2222222", "+49-111-3333333", "info@lieferant.de") + ->setDocumentBuyer("Kunden AG Mitte", "GE2020211") + ->setDocumentBuyerReference("34676-342323") + ->setDocumentBuyerAddress("Kundenstraße 15", "", "", "69876", "Frankfurt", "DE") + ->addDocumentTax("S", "VAT", 275.0, 19.25, 7.0) + ->addDocumentTax("S", "VAT", 198.0, 37.62, 19.0) + ->setDocumentSummation(529.87, 529.87, 473.00, 0.0, 0.0, 473.00, 56.87, null, 0.0) + ->addDocumentPaymentTerm("Zahlbar innerhalb 30 Tagen netto bis 04.04.2018, 3% Skonto innerhalb 10 Tagen bis 15.03.2018") + ->addNewPosition("1") + ->setDocumentPositionNote("Bemerkung zu Zeile 1") + ->setDocumentPositionProductDetails("Trennblätter A4", "", "TB100A4", null, "0160", "4012345001235") + ->addDocumentPositionProductCharacteristic("Farbe", "Gelb") + ->addDocumentPositionProductClassification("ClassCode", "ClassName", "ListId", "ListVersionId") + ->setDocumentPositionProductOriginTradeCountry("CN") + ->setDocumentPositionGrossPrice(9.9000) + ->setDocumentPositionNetPrice(9.9000) + ->setDocumentPositionQuantity(20, "H87") + ->addDocumentPositionTax('S', 'VAT', 19) + ->setDocumentPositionLineSummation(198.0) + ->addNewPosition("2") + ->setDocumentPositionNote("Bemerkung zu Zeile 2") + ->setDocumentPositionProductDetails("Joghurt Banane", "", "ARNR2", null, "0160", "4000050986428") + ->addDocumentPositionProductCharacteristic("Suesstoff", "Nein") + ->addDocumentPositionProductClassification("ClassCode", "ClassName", "ListId", "ListVersionId") + ->SetDocumentPositionGrossPrice(5.5000) + ->SetDocumentPositionNetPrice(5.5000) + ->SetDocumentPositionQuantity(50, "H87") + ->AddDocumentPositionTax('S', 'VAT', 7) + ->SetDocumentPositionLineSummation(275.0) + ->addDocumentPaymentTerm("Fälligkeitsdatum: 05.12.24 ; Skonto 3% bis zum 19.11.24", \DateTime::createFromFormat("d.m.y", "19.11.24")) + ->addDiscountTermsToPaymentTerms(3, \DateTime::createFromFormat("d.m.y", "05.11.24"), 14, "DAY", 2123.53, 63.71) + ->writeFile(dirname(__FILE__) . "/factur-x.xml"); diff --git a/src/ZugferdSettings.php b/src/ZugferdSettings.php index 63e4ca8..5ee7941 100644 --- a/src/ZugferdSettings.php +++ b/src/ZugferdSettings.php @@ -43,6 +43,13 @@ class ZugferdSettings */ protected static $percentDecimals = 2; + /** + * The number of decimals for measure values + * + * @var integer + */ + protected static $measureDecimals = 2; + /** * The decimal separator * @@ -141,6 +148,27 @@ public static function setPercentDecimals(int $percentDecimals): void static::$percentDecimals = $percentDecimals; } + /** + * Get the number of decimals to use for measure values + * + * @return integer + */ + public static function getMeasureDecimals(): int + { + return static::$measureDecimals; + } + + /** + * Set the number of decimals to use for measure values + * + * @param integer $measureDecimals + * @return void + */ + public static function setMeasureDecimals(int $measureDecimals): void + { + static::$measureDecimals = $measureDecimals; + } + /** * Get the decimal separator * diff --git a/src/jms/ZugferdTypesHandler.php b/src/jms/ZugferdTypesHandler.php index 0b36a5d..6f3a663 100644 --- a/src/jms/ZugferdTypesHandler.php +++ b/src/jms/ZugferdTypesHandler.php @@ -9,10 +9,7 @@ namespace horstoeko\zugferd\jms; -use DOMElement; -use DOMText; use horstoeko\zugferd\ZugferdSettings; -use JMS\Serializer\Context; use JMS\Serializer\GraphNavigator; use JMS\Serializer\Handler\SubscribingHandlerInterface; use JMS\Serializer\XmlSerializationVisitor; @@ -147,6 +144,30 @@ public static function getSubscribingMethods() 'type' => 'horstoeko\zugferd\entities\extended\udt\IndicatorType', 'method' => 'serializeIndicatorType' ], + [ + 'direction' => GraphNavigator::DIRECTION_SERIALIZATION, + 'format' => 'xml', + 'type' => 'horstoeko\zugferd\entities\basic\udt\MeasureType', + 'method' => 'serializeMeasureType' + ], + [ + 'direction' => GraphNavigator::DIRECTION_SERIALIZATION, + 'format' => 'xml', + 'type' => 'horstoeko\zugferd\entities\basicwl\udt\MeasureType', + 'method' => 'serializeMeasureType' + ], + [ + 'direction' => GraphNavigator::DIRECTION_SERIALIZATION, + 'format' => 'xml', + 'type' => 'horstoeko\zugferd\entities\en16931\udt\MeasureType', + 'method' => 'serializeMeasureType' + ], + [ + 'direction' => GraphNavigator::DIRECTION_SERIALIZATION, + 'format' => 'xml', + 'type' => 'horstoeko\zugferd\entities\extended\udt\MeasureType', + 'method' => 'serializeMeasureType' + ], ]; } @@ -225,6 +246,33 @@ public function serializePercentType(XmlSerializationVisitor $visitor, $data) return $node; } + /** + * Serialize a meassure value + * The valze will be serialized (by default) with a precission of 2 digits + * + * @param XmlSerializationVisitor $visitor + * @param mixed $data + */ + public function serializeMeasureType(XmlSerializationVisitor $visitor, $data) + { + $node = $visitor->getDocument()->createTextNode( + number_format( + $data->value(), + ZugferdSettings::getSpecialDecimalPlacesMap($visitor->getCurrentNode()->getNodePath(), ZugferdSettings::getMeasureDecimals()), + ZugferdSettings::getDecimalSeparator(), + ZugferdSettings::getThousandsSeparator() + ) + ); + + if ($data->getUnitCode() != null) { + $attr = $visitor->getDocument()->createAttribute("unitCode"); + $attr->value = $data->getUnitCode(); + $visitor->getCurrentNode()->appendChild($attr); + } + + return $node; + } + /** * Serialize a inditcator * False and true values will be serialized correctly (false won't be serialized diff --git a/tests/testcases/SettingsTest.php b/tests/testcases/SettingsTest.php index c068c67..1874be5 100644 --- a/tests/testcases/SettingsTest.php +++ b/tests/testcases/SettingsTest.php @@ -17,6 +17,7 @@ public static function tearDownAfterClass(): void ZugferdSettings::setAmountDecimals(2); ZugferdSettings::setQuantityDecimals(2); ZugferdSettings::setPercentDecimals(2); + ZugferdSettings::setMeasureDecimals(2); ZugferdSettings::setDecimalSeparator("."); ZugferdSettings::setThousandsSeparator(""); ZugferdSettings::setIccProfileFilename("sRGB_v4_ICC.icc"); @@ -61,6 +62,19 @@ public function testPercentDecimals(): void $this->assertEquals(3, $property->getValue()); } + public function testMeasureDecimals(): void + { + $this->assertEquals(2, ZugferdSettings::getMeasureDecimals()); + + ZugferdSettings::setMeasureDecimals(3); + + $this->assertEquals(3, ZugferdSettings::getMeasureDecimals()); + + $property = $this->getPrivatePropertyFromClassname(ZugferdSettings::class, "measureDecimals"); + + $this->assertEquals(3, $property->getValue()); + } + public function testDecimalSeparator(): void { $this->assertEquals(".", ZugferdSettings::getDecimalSeparator());