From 1b174e243f7e057fd273a44050de1636b45db321 Mon Sep 17 00:00:00 2001 From: jstaerk Date: Thu, 26 Jun 2025 14:16:36 +0200 Subject: [PATCH] erster versuch --- .../Exceptions/ArithmeticException.java | 16 ++ .../Exceptions/ArithmetricException.java | 1 + .../validator/XMLValidator.java | 35 ++++ .../validator/XMLValidatorTest.java | 26 +++ .../test/resources/invalidArithmetrics.xml | 186 ++++++++++++++++++ 5 files changed, 264 insertions(+) create mode 100644 library/src/main/java/org/mustangproject/Exceptions/ArithmeticException.java create mode 100644 validator/src/test/resources/invalidArithmetrics.xml diff --git a/library/src/main/java/org/mustangproject/Exceptions/ArithmeticException.java b/library/src/main/java/org/mustangproject/Exceptions/ArithmeticException.java new file mode 100644 index 00000000..f2341e1a --- /dev/null +++ b/library/src/main/java/org/mustangproject/Exceptions/ArithmeticException.java @@ -0,0 +1,16 @@ +package org.mustangproject.Exceptions; + +import java.text.ParseException; + +/*** + * will be thrown if an invoice cant be reproduced numerically + */ +public class ArithmeticException extends ArithmetricException { + public ArithmeticException() { + this(""); + } + + public ArithmeticException(String details) { +// super("Could not reproduce the invoice. " + details, 0); + } +} diff --git a/library/src/main/java/org/mustangproject/Exceptions/ArithmetricException.java b/library/src/main/java/org/mustangproject/Exceptions/ArithmetricException.java index e5b4071d..16af335b 100644 --- a/library/src/main/java/org/mustangproject/Exceptions/ArithmetricException.java +++ b/library/src/main/java/org/mustangproject/Exceptions/ArithmetricException.java @@ -4,6 +4,7 @@ import java.text.ParseException; /*** * will be thrown if an invoice cant be reproduced numerically + * (deprecated, because of typo) */ public class ArithmetricException extends ParseException { public ArithmetricException() { diff --git a/validator/src/main/java/org/mustangproject/validator/XMLValidator.java b/validator/src/main/java/org/mustangproject/validator/XMLValidator.java index 6f364751..c69d085b 100644 --- a/validator/src/main/java/org/mustangproject/validator/XMLValidator.java +++ b/validator/src/main/java/org/mustangproject/validator/XMLValidator.java @@ -8,6 +8,7 @@ import java.io.UncheckedIOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; +import java.text.ParseException; import java.util.Calendar; import javax.xml.XMLConstants; @@ -20,7 +21,12 @@ import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; +import org.mustangproject.CalculatedInvoice; +import org.mustangproject.Exceptions.ArithmetricException; import org.mustangproject.XMLTools; +import org.mustangproject.ZUGFeRD.TransactionCalculator; +import org.mustangproject.ZUGFeRD.ZUGFeRDImporter; +import org.mustangproject.ZUGFeRD.ZUGFeRDInvoiceImporter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; @@ -387,6 +393,7 @@ public class XMLValidator extends Validator { } } } + checkArithmetrics(context); } catch (final IrrecoverableValidationError er) { @@ -410,6 +417,34 @@ public class XMLValidator extends Validator { } + private void checkArithmetrics(ValidationContext context) { + ZUGFeRDInvoiceImporter zi=new ZUGFeRDInvoiceImporter(); + try { + zi.setRawXML(zfXML.getBytes()); + CalculatedInvoice ci=new CalculatedInvoice(); + zi.extractInto(ci); + TransactionCalculator tc=new TransactionCalculator(ci); + if (tc.getGrandTotal().compareTo(ci.getGrandTotal())!=0) { + + } + + } catch ( ArithmetricException e) { + try { + context.addResultItem(new ValidationResultItem(ESeverity.warning, "Can not arithmetrically reproduce the invoice.").setSection(10)); + + } catch (IrrecoverableValidationError ie) { + LOGGER.error(ie.getMessage(), ie); + } + } catch ( IOException e) { + LOGGER.error(e.getMessage(), e); + } catch (XPathExpressionException e) { + LOGGER.error(e.getMessage(), e); + } catch (ParseException e) { + LOGGER.error(e.getMessage(), e); + } + + } + public void validateXR(String xml, ESeverity errorImpact) throws IrrecoverableValidationError { //Guideline ID=urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_1.2 or diff --git a/validator/src/test/java/org/mustangproject/validator/XMLValidatorTest.java b/validator/src/test/java/org/mustangproject/validator/XMLValidatorTest.java index 2fda10ef..0a7032af 100644 --- a/validator/src/test/java/org/mustangproject/validator/XMLValidatorTest.java +++ b/validator/src/test/java/org/mustangproject/validator/XMLValidatorTest.java @@ -8,6 +8,8 @@ import org.xmlunit.builder.Input; import org.xmlunit.xpath.JAXPXPathEngine; import org.xmlunit.xpath.XPathEngine; +import static org.xmlunit.assertj.XmlAssert.assertThat; + public class XMLValidatorTest extends ResourceCase { public void testZF2XMLValidation() { @@ -282,6 +284,30 @@ public class XMLValidatorTest extends ResourceCase { } + public void testArithmetrics() { + final ValidationContext ctx = new ValidationContext(null); + final XMLValidator xv = new XMLValidator(ctx); + final XPathEngine xpath = new JAXPXPathEngine(); + + File tempFile = getResourceAsFile("invalidArithmetrics.xml"); + try { + xv.setFilename(tempFile.getAbsolutePath()); + xv.validate(); + + String s="" + xv.getXMLResult() + ""; + Source source = Input.fromString(s).build(); + String content = xpath.evaluate("/validation/summary/@status", source); + assertEquals("invalid", content); + assertThat(s).valueByXPath("count(//warning)") + .asInt() + .isEqualTo(1); + + } catch (final IrrecoverableValidationError e) { + // ignore, will be in XML output anyway + } + + } + public void testXRValidationUBL() { ValidationContext ctx = new ValidationContext(null); XMLValidator xv = new XMLValidator(ctx); diff --git a/validator/src/test/resources/invalidArithmetrics.xml b/validator/src/test/resources/invalidArithmetrics.xml new file mode 100644 index 00000000..e32358f0 --- /dev/null +++ b/validator/src/test/resources/invalidArithmetrics.xml @@ -0,0 +1,186 @@ + + + + + urn:cen.eu:en16931:2017 + + + + RE-20171118/506 + 380 + 20171118 + + + + + 1 + + + Künstlerische Gestaltung (Stunde): Einer Beispielrechnung + + + + + 160.0000 + 2.0000 + + + 160.0000 + 2.0000 + + + + 2.0000 + + + + VAT + S + 7.00 + + + 160.00 + + + + + + 2 + + + Luftballon: Bunt, ca. 500ml + + + + + 0.7900 + 1.0000 + + + 0.7900 + 1.0000 + + + + 400.0000 + + + + VAT + S + 19.00 + + + 316.00 + + + + + + 3 + + + Heiße Luft pro Liter + + + + + 0.1000 + 1.0000 + + + 0.1000 + 1.0000 + + + + 200.0000 + + + + VAT + S + 19.00 + + + 20.00 + + + + + + Bei Spiel GmbH + + 12345 + Ecke 12 + Stadthausen + DE + + + 22/815/0815/4 + + + DE136695976 + + + + Theodor Est + + 88802 + Bahnstr. 42 + Spielkreis + DE + + + DE999999999 + + + + + + 20171117 + + + + RE-20171118/506 + EUR + + 42 + Überweisung + + DE88 2008 0000 0970 3757 00 + + + COBADEFFXXX + + + + 11.20 + VAT + 160.00 + S + 7.00 + + + 63.84 + VAT + 336.00 + S + 19.00 + + + Zahlbar ohne Abzug bis 09.12.2017 + 20171209 + + + 496.00 + 0.00 + 0.00 + 496.00 + 75.04 + 571.04 + 571.05 + + + +