erster versuch

This commit is contained in:
jstaerk
2025-06-26 14:16:36 +02:00
parent ea14c700cb
commit 1b174e243f
5 changed files with 264 additions and 0 deletions

View File

@@ -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);
}
}

View File

@@ -4,6 +4,7 @@ import java.text.ParseException;
/*** /***
* will be thrown if an invoice cant be reproduced numerically * will be thrown if an invoice cant be reproduced numerically
* (deprecated, because of typo)
*/ */
public class ArithmetricException extends ParseException { public class ArithmetricException extends ParseException {
public ArithmetricException() { public ArithmetricException() {

View File

@@ -8,6 +8,7 @@ import java.io.UncheckedIOException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.text.ParseException;
import java.util.Calendar; import java.util.Calendar;
import javax.xml.XMLConstants; import javax.xml.XMLConstants;
@@ -20,7 +21,12 @@ import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory; import javax.xml.xpath.XPathFactory;
import org.mustangproject.CalculatedInvoice;
import org.mustangproject.Exceptions.ArithmetricException;
import org.mustangproject.XMLTools; 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.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.w3c.dom.Document; import org.w3c.dom.Document;
@@ -387,6 +393,7 @@ public class XMLValidator extends Validator {
} }
} }
} }
checkArithmetrics(context);
} catch (final IrrecoverableValidationError er) { } 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 { 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 //Guideline ID=urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_1.2 or

View File

@@ -8,6 +8,8 @@ import org.xmlunit.builder.Input;
import org.xmlunit.xpath.JAXPXPathEngine; import org.xmlunit.xpath.JAXPXPathEngine;
import org.xmlunit.xpath.XPathEngine; import org.xmlunit.xpath.XPathEngine;
import static org.xmlunit.assertj.XmlAssert.assertThat;
public class XMLValidatorTest extends ResourceCase { public class XMLValidatorTest extends ResourceCase {
public void testZF2XMLValidation() { 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="<validation>" + xv.getXMLResult() + "</validation>";
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() { public void testXRValidationUBL() {
ValidationContext ctx = new ValidationContext(null); ValidationContext ctx = new ValidationContext(null);
XMLValidator xv = new XMLValidator(ctx); XMLValidator xv = new XMLValidator(ctx);

View File

@@ -0,0 +1,186 @@
<?xml version='1.0' encoding="UTF-8" standalone="yes"?>
<rsm:CrossIndustryInvoice xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rsm="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100" xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100" xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100">
<rsm:ExchangedDocumentContext>
<ram:GuidelineSpecifiedDocumentContextParameter>
<ram:ID>urn:cen.eu:en16931:2017</ram:ID>
</ram:GuidelineSpecifiedDocumentContextParameter>
</rsm:ExchangedDocumentContext>
<rsm:ExchangedDocument>
<ram:ID>RE-20171118/506</ram:ID>
<ram:TypeCode>380</ram:TypeCode>
<ram:IssueDateTime><udt:DateTimeString format="102">20171118</udt:DateTimeString></ram:IssueDateTime>
</rsm:ExchangedDocument>
<rsm:SupplyChainTradeTransaction>
<ram:IncludedSupplyChainTradeLineItem>
<ram:AssociatedDocumentLineDocument>
<ram:LineID>1</ram:LineID>
</ram:AssociatedDocumentLineDocument>
<ram:SpecifiedTradeProduct>
<ram:Name>Künstlerische Gestaltung (Stunde): Einer Beispielrechnung</ram:Name>
<ram:Description></ram:Description>
</ram:SpecifiedTradeProduct>
<ram:SpecifiedLineTradeAgreement>
<ram:GrossPriceProductTradePrice>
<ram:ChargeAmount>160.0000</ram:ChargeAmount>
<ram:BasisQuantity unitCode="HUR">2.0000</ram:BasisQuantity>
</ram:GrossPriceProductTradePrice>
<ram:NetPriceProductTradePrice>
<ram:ChargeAmount>160.0000</ram:ChargeAmount>
<ram:BasisQuantity unitCode="HUR">2.0000</ram:BasisQuantity>
</ram:NetPriceProductTradePrice>
</ram:SpecifiedLineTradeAgreement>
<ram:SpecifiedLineTradeDelivery>
<ram:BilledQuantity unitCode="HUR">2.0000</ram:BilledQuantity>
</ram:SpecifiedLineTradeDelivery>
<ram:SpecifiedLineTradeSettlement>
<ram:ApplicableTradeTax>
<ram:TypeCode>VAT</ram:TypeCode>
<ram:CategoryCode>S</ram:CategoryCode>
<ram:RateApplicablePercent>7.00</ram:RateApplicablePercent>
</ram:ApplicableTradeTax>
<ram:SpecifiedTradeSettlementLineMonetarySummation>
<ram:LineTotalAmount>160.00</ram:LineTotalAmount>
</ram:SpecifiedTradeSettlementLineMonetarySummation>
</ram:SpecifiedLineTradeSettlement>
</ram:IncludedSupplyChainTradeLineItem>
<ram:IncludedSupplyChainTradeLineItem>
<ram:AssociatedDocumentLineDocument>
<ram:LineID>2</ram:LineID>
</ram:AssociatedDocumentLineDocument>
<ram:SpecifiedTradeProduct>
<ram:Name>Luftballon: Bunt, ca. 500ml</ram:Name>
<ram:Description></ram:Description>
</ram:SpecifiedTradeProduct>
<ram:SpecifiedLineTradeAgreement>
<ram:GrossPriceProductTradePrice>
<ram:ChargeAmount>0.7900</ram:ChargeAmount>
<ram:BasisQuantity unitCode="C62">1.0000</ram:BasisQuantity>
</ram:GrossPriceProductTradePrice>
<ram:NetPriceProductTradePrice>
<ram:ChargeAmount>0.7900</ram:ChargeAmount>
<ram:BasisQuantity unitCode="C62">1.0000</ram:BasisQuantity>
</ram:NetPriceProductTradePrice>
</ram:SpecifiedLineTradeAgreement>
<ram:SpecifiedLineTradeDelivery>
<ram:BilledQuantity unitCode="C62">400.0000</ram:BilledQuantity>
</ram:SpecifiedLineTradeDelivery>
<ram:SpecifiedLineTradeSettlement>
<ram:ApplicableTradeTax>
<ram:TypeCode>VAT</ram:TypeCode>
<ram:CategoryCode>S</ram:CategoryCode>
<ram:RateApplicablePercent>19.00</ram:RateApplicablePercent>
</ram:ApplicableTradeTax>
<ram:SpecifiedTradeSettlementLineMonetarySummation>
<ram:LineTotalAmount>316.00</ram:LineTotalAmount>
</ram:SpecifiedTradeSettlementLineMonetarySummation>
</ram:SpecifiedLineTradeSettlement>
</ram:IncludedSupplyChainTradeLineItem>
<ram:IncludedSupplyChainTradeLineItem>
<ram:AssociatedDocumentLineDocument>
<ram:LineID>3</ram:LineID>
</ram:AssociatedDocumentLineDocument>
<ram:SpecifiedTradeProduct>
<ram:Name>Heiße Luft pro Liter</ram:Name>
<ram:Description></ram:Description>
</ram:SpecifiedTradeProduct>
<ram:SpecifiedLineTradeAgreement>
<ram:GrossPriceProductTradePrice>
<ram:ChargeAmount>0.1000</ram:ChargeAmount>
<ram:BasisQuantity unitCode="LTR">1.0000</ram:BasisQuantity>
</ram:GrossPriceProductTradePrice>
<ram:NetPriceProductTradePrice>
<ram:ChargeAmount>0.1000</ram:ChargeAmount>
<ram:BasisQuantity unitCode="LTR">1.0000</ram:BasisQuantity>
</ram:NetPriceProductTradePrice>
</ram:SpecifiedLineTradeAgreement>
<ram:SpecifiedLineTradeDelivery>
<ram:BilledQuantity unitCode="LTR">200.0000</ram:BilledQuantity>
</ram:SpecifiedLineTradeDelivery>
<ram:SpecifiedLineTradeSettlement>
<ram:ApplicableTradeTax>
<ram:TypeCode>VAT</ram:TypeCode>
<ram:CategoryCode>S</ram:CategoryCode>
<ram:RateApplicablePercent>19.00</ram:RateApplicablePercent>
</ram:ApplicableTradeTax>
<ram:SpecifiedTradeSettlementLineMonetarySummation>
<ram:LineTotalAmount>20.00</ram:LineTotalAmount>
</ram:SpecifiedTradeSettlementLineMonetarySummation>
</ram:SpecifiedLineTradeSettlement>
</ram:IncludedSupplyChainTradeLineItem>
<ram:ApplicableHeaderTradeAgreement>
<ram:SellerTradeParty>
<ram:Name>Bei Spiel GmbH</ram:Name>
<ram:PostalTradeAddress>
<ram:PostcodeCode>12345</ram:PostcodeCode>
<ram:LineOne>Ecke 12</ram:LineOne>
<ram:CityName>Stadthausen</ram:CityName>
<ram:CountryID>DE</ram:CountryID>
</ram:PostalTradeAddress>
<ram:SpecifiedTaxRegistration>
<ram:ID schemeID="FC">22/815/0815/4</ram:ID>
</ram:SpecifiedTaxRegistration>
<ram:SpecifiedTaxRegistration>
<ram:ID schemeID="VA">DE136695976</ram:ID>
</ram:SpecifiedTaxRegistration>
</ram:SellerTradeParty>
<ram:BuyerTradeParty>
<ram:Name>Theodor Est</ram:Name>
<ram:PostalTradeAddress>
<ram:PostcodeCode>88802</ram:PostcodeCode>
<ram:LineOne>Bahnstr. 42</ram:LineOne>
<ram:CityName>Spielkreis</ram:CityName>
<ram:CountryID>DE</ram:CountryID>
</ram:PostalTradeAddress>
<ram:SpecifiedTaxRegistration>
<ram:ID schemeID="VA">DE999999999</ram:ID>
</ram:SpecifiedTaxRegistration>
</ram:BuyerTradeParty>
</ram:ApplicableHeaderTradeAgreement>
<ram:ApplicableHeaderTradeDelivery>
<ram:ActualDeliverySupplyChainEvent>
<ram:OccurrenceDateTime><udt:DateTimeString format="102">20171117</udt:DateTimeString></ram:OccurrenceDateTime>
</ram:ActualDeliverySupplyChainEvent>
</ram:ApplicableHeaderTradeDelivery>
<ram:ApplicableHeaderTradeSettlement>
<ram:PaymentReference>RE-20171118/506</ram:PaymentReference>
<ram:InvoiceCurrencyCode>EUR</ram:InvoiceCurrencyCode>
<ram:SpecifiedTradeSettlementPaymentMeans>
<ram:TypeCode>42</ram:TypeCode>
<ram:Information>Überweisung</ram:Information>
<ram:PayeePartyCreditorFinancialAccount>
<ram:IBANID>DE88 2008 0000 0970 3757 00</ram:IBANID>
</ram:PayeePartyCreditorFinancialAccount>
<ram:PayeeSpecifiedCreditorFinancialInstitution>
<ram:BICID>COBADEFFXXX</ram:BICID>
</ram:PayeeSpecifiedCreditorFinancialInstitution>
</ram:SpecifiedTradeSettlementPaymentMeans>
<ram:ApplicableTradeTax>
<ram:CalculatedAmount>11.20</ram:CalculatedAmount>
<ram:TypeCode>VAT</ram:TypeCode>
<ram:BasisAmount>160.00</ram:BasisAmount>
<ram:CategoryCode>S</ram:CategoryCode>
<ram:RateApplicablePercent>7.00</ram:RateApplicablePercent>
</ram:ApplicableTradeTax>
<ram:ApplicableTradeTax>
<ram:CalculatedAmount>63.84</ram:CalculatedAmount>
<ram:TypeCode>VAT</ram:TypeCode>
<ram:BasisAmount>336.00</ram:BasisAmount>
<ram:CategoryCode>S</ram:CategoryCode>
<ram:RateApplicablePercent>19.00</ram:RateApplicablePercent>
</ram:ApplicableTradeTax>
<ram:SpecifiedTradePaymentTerms>
<ram:Description>Zahlbar ohne Abzug bis 09.12.2017</ram:Description>
<ram:DueDateDateTime><udt:DateTimeString format="102">20171209</udt:DateTimeString></ram:DueDateDateTime>
</ram:SpecifiedTradePaymentTerms>
<ram:SpecifiedTradeSettlementHeaderMonetarySummation>
<ram:LineTotalAmount>496.00</ram:LineTotalAmount>
<ram:ChargeTotalAmount>0.00</ram:ChargeTotalAmount>
<ram:AllowanceTotalAmount>0.00</ram:AllowanceTotalAmount>
<ram:TaxBasisTotalAmount>496.00</ram:TaxBasisTotalAmount>
<ram:TaxTotalAmount currencyID="EUR">75.04</ram:TaxTotalAmount>
<ram:GrandTotalAmount>571.04</ram:GrandTotalAmount>
<ram:DuePayableAmount>571.05</ram:DuePayableAmount>
</ram:SpecifiedTradeSettlementHeaderMonetarySummation>
</ram:ApplicableHeaderTradeSettlement>
</rsm:SupplyChainTradeTransaction>
</rsm:CrossIndustryInvoice>