Merge branch 'master' into issue-830
This commit is contained in:
22
History.md
22
History.md
@@ -1,8 +1,20 @@
|
|||||||
#820/801/815
|
- support parsing of BT-90 CreditorReferenceID
|
||||||
#822
|
- #870
|
||||||
#843
|
- #871 sec
|
||||||
add getCalculation on calculatedInvoice
|
- #868
|
||||||
Transactioncalculator getTaxDetails to include correct percentage, calculated amounts
|
|
||||||
|
2.17.0
|
||||||
|
=======
|
||||||
|
2025-06-11
|
||||||
|
- Breaking change: #764 Item allowances not to be multiplied by quantity
|
||||||
|
(there are now product level quantities for that)
|
||||||
|
- #820/801/815 Fix invoiceImporter: empty NodeList, empty Strings
|
||||||
|
- #822 Wrapping Message Text in Validation Result PDF
|
||||||
|
- #843 Re-Initialize the HTML-template on language change
|
||||||
|
- #854 allow multiple item charges/allowances when visualizing to html
|
||||||
|
- #786 Fix Invoices with Category Code "O" #786
|
||||||
|
- add getCalculation on calculatedInvoice
|
||||||
|
- Transactioncalculator getTaxDetails to include correct percentage, calculated amounts
|
||||||
|
|
||||||
2.16.5
|
2.16.5
|
||||||
=======
|
=======
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mustangproject</groupId>
|
<groupId>org.mustangproject</groupId>
|
||||||
<artifactId>core</artifactId>
|
<artifactId>core</artifactId>
|
||||||
<version>2.17.0-SNAPSHOT</version>
|
<version>2.17.1-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>org.mustangproject</groupId>
|
<groupId>org.mustangproject</groupId>
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
should also work for XRechnung/CII.
|
should also work for XRechnung/CII.
|
||||||
</name>
|
</name>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<version>2.17.0-SNAPSHOT</version>
|
<version>2.17.1-SNAPSHOT</version>
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<maven.compiler.compilerVersion>11</maven.compiler.compilerVersion>
|
<maven.compiler.compilerVersion>11</maven.compiler.compilerVersion>
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.mustangproject</groupId>
|
<groupId>org.mustangproject</groupId>
|
||||||
<artifactId>validator</artifactId>
|
<artifactId>validator</artifactId>
|
||||||
<version>2.17.0-SNAPSHOT</version>
|
<version>2.17.1-SNAPSHOT</version>
|
||||||
<!-- prototypes of new mustangproject versions can be installed by referring to them and installed to the local repo from a jar file with
|
<!-- prototypes of new mustangproject versions can be installed by referring to them and installed to the local repo from a jar file with
|
||||||
mvn install:install-file -Dfile=mustang-1.5.4-SNAPSHOT.jar -DgroupId=org.mustangproject.ZUGFeRD -DartifactId=mustang -Dversion=1.5.4 -Dpackaging=jar -DgeneratePom=true
|
mvn install:install-file -Dfile=mustang-1.5.4-SNAPSHOT.jar -DgroupId=org.mustangproject.ZUGFeRD -DartifactId=mustang -Dversion=1.5.4 -Dpackaging=jar -DgeneratePom=true
|
||||||
-->
|
-->
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ If you set up a Maven project, you can reference the mustang artifact like this:
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.mustangproject</groupId>
|
<groupId>org.mustangproject</groupId>
|
||||||
<artifactId>validator</artifactId>
|
<artifactId>validator</artifactId>
|
||||||
<version>2.15.0</version>
|
<version>2.17.0</version>
|
||||||
<classifier>shaded</classifier>
|
<classifier>shaded</classifier>
|
||||||
</dependency>
|
</dependency>
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,277 +0,0 @@
|
|||||||
package mustangtest;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.GregorianCalendar;
|
|
||||||
|
|
||||||
import org.mustangproject.ZUGFeRD.IExportableTransaction;
|
|
||||||
import org.mustangproject.ZUGFeRD.IZUGFeRDAllowanceCharge;
|
|
||||||
import org.mustangproject.ZUGFeRD.IZUGFeRDExportableItem;
|
|
||||||
import org.mustangproject.ZUGFeRD.IZUGFeRDExportableProduct;
|
|
||||||
import org.mustangproject.ZUGFeRD.IZUGFeRDExportableTradeParty;
|
|
||||||
import org.mustangproject.ZUGFeRD.IZUGFeRDExporter;
|
|
||||||
import org.mustangproject.ZUGFeRD.ZUGFeRDExporterFromA1;
|
|
||||||
|
|
||||||
class Contact implements IZUGFeRDExportableTradeParty {
|
|
||||||
|
|
||||||
public String getCountry() {
|
|
||||||
return "DE";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getLocation() {
|
|
||||||
return "Spielkreis";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return "Theodor Est";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getStreet() {
|
|
||||||
return "Bahnstr. 42";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getVATID() {
|
|
||||||
return "DE999999999";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getZIP() {
|
|
||||||
return "88802";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Item implements IZUGFeRDExportableItem {
|
|
||||||
public Item(BigDecimal price, BigDecimal quantity, Product product) {
|
|
||||||
super();
|
|
||||||
this.price = price;
|
|
||||||
this.quantity = quantity;
|
|
||||||
this.product = product;
|
|
||||||
}
|
|
||||||
|
|
||||||
private BigDecimal price, quantity;
|
|
||||||
private Product product;
|
|
||||||
|
|
||||||
public BigDecimal getPrice() {
|
|
||||||
return price;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPrice(BigDecimal price) {
|
|
||||||
this.price = price;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BigDecimal getQuantity() {
|
|
||||||
return quantity;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setQuantity(BigDecimal quantity) {
|
|
||||||
this.quantity = quantity;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Product getProduct() {
|
|
||||||
return product;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setProduct(Product product) {
|
|
||||||
this.product = product;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IZUGFeRDAllowanceCharge[] getItemAllowances() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IZUGFeRDAllowanceCharge[] getItemCharges() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Product implements IZUGFeRDExportableProduct {
|
|
||||||
public Product(String description, String name, String unit, BigDecimal vATPercent) {
|
|
||||||
super();
|
|
||||||
this.description = description;
|
|
||||||
this.name = name;
|
|
||||||
this.unit = unit;
|
|
||||||
VATPercent = vATPercent;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String description, name, unit;
|
|
||||||
private BigDecimal VATPercent;
|
|
||||||
|
|
||||||
public String getDescription() {
|
|
||||||
return description;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDescription(String description) {
|
|
||||||
this.description = description;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setName(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUnit() {
|
|
||||||
return unit;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setUnit(String unit) {
|
|
||||||
this.unit = unit;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BigDecimal getVATPercent() {
|
|
||||||
return VATPercent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setVATPercent(BigDecimal vATPercent) {
|
|
||||||
VATPercent = vATPercent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class MustangWriter implements IExportableTransaction {
|
|
||||||
|
|
||||||
private void apply() {
|
|
||||||
try {
|
|
||||||
System.out.println("Reading Blanko-PDF");
|
|
||||||
IZUGFeRDExporter ze = new ZUGFeRDExporterFromA1().setProducer("My Application")
|
|
||||||
.setCreator(System.getProperty("user.name"))
|
|
||||||
.load("./MustangGnuaccountingBeispielRE-20170509_505blanko.pdf");
|
|
||||||
System.out.println("Generating and attaching ZUGFeRD-Data");
|
|
||||||
ze.setTransaction(this);
|
|
||||||
System.out.println("Writing ZUGFeRD-PDF");
|
|
||||||
ze.export("./MustangGnuaccountingBeispielRE-20170509_505new.pdf");
|
|
||||||
System.out.println("Done.");
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
MustangWriter mw=new MustangWriter();
|
|
||||||
mw.apply();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCurrency() {
|
|
||||||
return "EUR";
|
|
||||||
}
|
|
||||||
|
|
||||||
public Date getDeliveryDate() {
|
|
||||||
return new GregorianCalendar(2017, Calendar.NOVEMBER, 17).getTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Date getDueDate() {
|
|
||||||
return new GregorianCalendar(2017, Calendar.DECEMBER, 9).getTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Date getIssueDate() {
|
|
||||||
return new GregorianCalendar(2017, Calendar.NOVEMBER, 18).getTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getNumber() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return "RE-20171118/506";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getOwnBIC() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return "COBADEFFXXX";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getOwnBankName() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return "Commerzbank";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getOwnCountry() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return "DE";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getOwnIBAN() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return "DE88 2008 0000 0970 3757 00";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getOwnLocation() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return "Stadthausen";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getOwnOrganisationFullPlaintextInfo() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return "Bei Spiel GmbH\n" + "Ecke 12\n" + "12345 Stadthausen\n" + "Geschäftsführer: Max Mustermann";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getOwnOrganisationName() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return "Bei Spiel GmbH";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getOwnPaymentInfoText() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getOwnStreet() {
|
|
||||||
return "Ecke 12";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getOwnTaxID() {
|
|
||||||
return "22/815/0815/4";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getOwnVATID() {
|
|
||||||
return "DE136695976";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getOwnZIP() {
|
|
||||||
return "12345";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPaymentTermDescription() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IZUGFeRDExportableTradeParty getRecipient() {
|
|
||||||
return new Contact();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getReferenceNumber() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IZUGFeRDAllowanceCharge[] getZFAllowances() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IZUGFeRDAllowanceCharge[] getZFCharges() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IZUGFeRDExportableItem[] getZFItems() {
|
|
||||||
Item[] allItems = new Item[3];
|
|
||||||
Product designProduct = new Product("", "Künstlerische Gestaltung (Stunde): Einer Beispielrechnung", "HUR",
|
|
||||||
new BigDecimal("7.000000"));
|
|
||||||
Product balloonProduct = new Product("", "Luftballon: Bunt, ca. 500ml", "C62", new BigDecimal("19.000000"));
|
|
||||||
Product airProduct = new Product("", "Heiße Luft pro Liter", "LTR", new BigDecimal("19.000000"));
|
|
||||||
allItems[0] = new Item(new BigDecimal("160"), new BigDecimal("1"), designProduct);
|
|
||||||
allItems[1] = new Item(new BigDecimal("0.79"), new BigDecimal("400"), balloonProduct);
|
|
||||||
allItems[2] = new Item(new BigDecimal("0.10"), new BigDecimal("200"), airProduct);
|
|
||||||
return allItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IZUGFeRDAllowanceCharge[] getZFLogisticsServiceCharges() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
446
doc/ZugferdDev.de.adoc
Normal file
446
doc/ZugferdDev.de.adoc
Normal file
@@ -0,0 +1,446 @@
|
|||||||
|
== [#anchor]####Mustang Project Nutzerdokumentation
|
||||||
|
|
||||||
|
Jochen Stärk
|
||||||
|
|
||||||
|
zu Mustangproject 1.5.1, 13.01.2018
|
||||||
|
|
||||||
|
http://www.mustangproject.org/[http://www.mustangproject.org]
|
||||||
|
|
||||||
|
== [#anchor-1]####Über Mustangproject
|
||||||
|
|
||||||
|
Mustangproject ist eine Java-Bibliothek zur Unterstützung von
|
||||||
|
erweiterten („ZUGFeRD“-)Metadaten in PDF-Rechnungsdateien. Sie verwendet
|
||||||
|
als Eingabe PDF/A-Dateien, benötigt die Apache PDFBox-Bibliothek und
|
||||||
|
unterliegt wie diese der APL-Lizenz. Sie ist daher, entsprechend den
|
||||||
|
Richtlinien der Apache Public License, unter Einbettung einer
|
||||||
|
entsprechenden „Notice“-Datei kostenlos einsetzbar in kommerziellen und
|
||||||
|
nichtkommerziellen Projekten.
|
||||||
|
|
||||||
|
== [#anchor-2]####Übersicht von ZUGFeRD-Lösungen
|
||||||
|
|
||||||
|
[cols=",,,,,,,,,,,",]
|
||||||
|
|===
|
||||||
|
| |Plattform |Lizenz |ZF Versionen |Funktionsumfang |Geeignet für |Preis
|
||||||
|
| | | | |
|
||||||
|
|
||||||
|
|Lesen |XML erzeugen |PDF Schreiben |PDF/A-Umwandlung |Kommerz. Software
|
||||||
|
|Freeware |Open Source | | | | |
|
||||||
|
|
||||||
|
|intarsys |Java |proprietär |1 |Ja |Ja |Ja |Ja |Ja |Ja |Nein |a.A.
|
||||||
|
|
||||||
|
|Konik |Java |AGPL |1 |Ja |Ja |Ja |Nein |Nein |Nein |Ja |0 €
|
||||||
|
|
||||||
|
|Mustang |Java |APL |1 |Ja |Ja |Ja |Nein |Ja |Ja |Ja |0 €
|
||||||
|
|
||||||
|
|https://github.com/akretion/factur-x |Python |BSD |1,2 |Nein |Nein |Ja
|
||||||
|
|Nein |Ja |Ja |Ja |0€
|
||||||
|
|
||||||
|
|https://github.com/stephanstapel/ZUGFeRD-csharp |C# |APL |1 |Ja |Ja
|
||||||
|
|Nein |Nein |Ja |Ja |Ja |0 €
|
||||||
|
|===
|
||||||
|
|
||||||
|
== [#anchor-3]####Download/Projekteinrichtung
|
||||||
|
|
||||||
|
=== [#anchor-4]####Source code
|
||||||
|
|
||||||
|
Heimat der Mustangprojekt-Quelltexte ist
|
||||||
|
https://github.com/ZUGFeRD/mustangproject/
|
||||||
|
|
||||||
|
=== [#anchor-5]####Projekteinrichtung ohne Maven
|
||||||
|
|
||||||
|
Mit installiertem OpenOffice.org oder LibreOffice und Eclipse for Java.
|
||||||
|
|
||||||
|
[arabic]
|
||||||
|
. Starten Sie Eclipse, Neues Java-Eclipse-Projekt erstellen,
|
||||||
|
beispielsweise „MustangSample“.
|
||||||
|
. Wechseln Sie in der Shell in den erstellten Ordner.
|
||||||
|
. Download von
|
||||||
|
[arabic]
|
||||||
|
.. Mustang
|
||||||
|
[arabic]
|
||||||
|
... Downloaden Sie
|
||||||
|
http://mustangproject.org/deploy/mustang-1.5.1.jarfootnote:[Falls Sie
|
||||||
|
ohnehin PDFBox verwenden (pdfbox, fontbox, preflight, xmpbox sowie deren
|
||||||
|
Abhängigkeiten apache-commons-io und apache-commons-logging) können Sie
|
||||||
|
auch die wesentlich kleinere
|
||||||
|
http://mustangproject.org/deploy/original-mustang-1.5.1.jar verwenden]
|
||||||
|
... Downloaden Sie http://mustangproject.org/deploy/NOTICE
|
||||||
|
.. Laden Sie
|
||||||
|
[arabic]
|
||||||
|
... Direkt eine PDF-A/1-Musterrechnung noch ohne
|
||||||
|
ZUGFeRD-Mhttp://www.mustangproject.org/files/MustangGnuaccountingBeispielRE-20171118_506blanko.pdf[http://www.mustangproject.org/files/MustangGnuaccountingBeispielRE-2017]etadaten
|
||||||
|
von
|
||||||
|
http://www.mustangproject.org/MustangGnuaccountingBeispielRE-20171118_506blanko.pdf[1118]http://www.mustangproject.org/MustangGnuaccountingBeispielRE-20171118_506blanko.pdf[_50]http://www.mustangproject.org/MustangGnuaccountingBeispielRE-20171118_506blanko.pdf[6]http://www.mustangproject.org/MustangGnuaccountingBeispielRE-20171118_506blanko.pdf[blanko.pdf]
|
||||||
|
herunter.
|
||||||
|
... oder erzeugen sich alternativ
|
||||||
|
[arabic]
|
||||||
|
.... ein eigenes Beispiel-PDF durch Download der Quelldatei im
|
||||||
|
OpenOffice.org-Format
|
||||||
|
http://www.mustangproject.org/files/MustangGnuaccountingBeispielRE-20171118_506.odt[http://www.mustangproject.org/files/MustangGnuaccountingBeispielRE-]http://www.mustangproject.org/files/MustangGnuaccountingBeispielRE-20171118_506.odt[20171118_506.odt]
|
||||||
|
und
|
||||||
|
[arabic]
|
||||||
|
..... Öffnen Sie die Datei in OpenOffice.org
|
||||||
|
..... Datei|Exportieren als PDF: Wichtig ist hier, dass Sie die Checkbox
|
||||||
|
PDF/A-1a setzen
|
||||||
|
..... Speichern Sie die PDF-Datei beispielsweise als
|
||||||
|
„http://www.mustangproject.org/files/MustangGnuaccountingBeispielRE-20171118_506blanko.pdf[MustangGnuaccountingBeispiel]http://www.mustangproject.org/files/MustangGnuaccountingBeispielRE-20171118_506blanko.pdf[RE-20171118_506blanko.pdf]“
|
||||||
|
im MustangSample-Ordner
|
||||||
|
. Wechseln Sie zurück zu Eclipse. Fügen Sie durch Rechtsklick auf das
|
||||||
|
Projekt („Eigenschaften“) die heruntergeladene JAR-Dateien
|
||||||
|
Projekteigenschaften als „externe Jars“ zum „Java Build Path“ Reiter
|
||||||
|
„Bibliotheken“ hinzu.
|
||||||
|
|
||||||
|
=== [#anchor-6]####Mit Maven
|
||||||
|
|
||||||
|
Mit folgendem Repository
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
|
||||||
|
<repository>
|
||||||
|
|
||||||
|
<id>mustang-mvn-repo</id>
|
||||||
|
|
||||||
|
<url>https://raw.github.com/ZUGFeRD/mustangproject/mvn-repo/</url>
|
||||||
|
|
||||||
|
</repository>
|
||||||
|
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
und folgender Dependency
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
|
||||||
|
<groupId>org.mustangproject.ZUGFeRD</groupId>
|
||||||
|
|
||||||
|
<artifactId>mustang</artifactId>
|
||||||
|
|
||||||
|
<version>1.5.1</version>
|
||||||
|
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
Bei der Gelegenheit kann man auch gleich Apache Commons Logging und JAXB
|
||||||
|
importieren:
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
|
||||||
|
<groupId>commons-logging</groupId>
|
||||||
|
|
||||||
|
<artifactId>commons-logging</artifactId>
|
||||||
|
|
||||||
|
<version>1.1.1</version>
|
||||||
|
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
|
||||||
|
<groupId>com.sun.xml.bind</groupId>
|
||||||
|
|
||||||
|
<artifactId>jaxb-impl</artifactId>
|
||||||
|
|
||||||
|
<version>2.2.5</version>
|
||||||
|
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
== [#anchor-7]####Lesen von ZUGFeRD-Daten
|
||||||
|
|
||||||
|
[arabic]
|
||||||
|
. Laden Sie sich eine PDF-Datei mit ZUGFeRD-Daten herunter,
|
||||||
|
beispielsweise
|
||||||
|
http://www.mustangproject.org/files/MustangGnuaccountingBeispielRE-20171118_506.pdf
|
||||||
|
. Erstellen Sie eine neue Java-Klasse unterhalb von src, beispielsweise
|
||||||
|
MustangReader. inklusive „Public static void main()“
|
||||||
|
. Geben Sie innerhalb von Main „ZUGFeRDImporter zi=**new**
|
||||||
|
ZUGFeRDImporter();“ ein und lassen Sie den Import durch STRG+SHIFT+O
|
||||||
|
ergänzen
|
||||||
|
. verwenden Sie zi.extract(PDF-Dateiname) und ggf. canParse() um
|
||||||
|
festzustellen ob es sich um ZUGFeRD-Daten handelt.
|
||||||
|
. Nach zi.parse() haben Sie Zugriff auf die getter wie getAmount()
|
||||||
|
. Welche Daten enthalten sind, können Sie der XML-Datei entnehmen die im
|
||||||
|
ZUGFeRD-Beispiel-PDF eingebettet ist
|
||||||
|
|
||||||
|
=== [#anchor-8]####Komplettes Lesebeispiel
|
||||||
|
|
||||||
|
[arabic, start=7]
|
||||||
|
.
|
||||||
|
|
||||||
|
*package* sample;
|
||||||
|
|
||||||
|
*import* org.mustangproject.ZUGFeRD.ZUGFeRDImporter;
|
||||||
|
|
||||||
|
*public* *class* Read \{
|
||||||
|
|
||||||
|
*public* *static* *void* main(String[] args) \{
|
||||||
|
|
||||||
|
ZUGFeRDImporter zi=**new** ZUGFeRDImporter();
|
||||||
|
|
||||||
|
zi.extract("./MustangGnuaccountingBeispielRE-20171118_506.pdf");
|
||||||
|
|
||||||
|
System._out_.println("Lese ZUGFeRD");
|
||||||
|
|
||||||
|
*if* (zi.canParse()) \{
|
||||||
|
|
||||||
|
zi.parse();
|
||||||
|
|
||||||
|
System._out_.println("Fälliger Betrag:"+zi.getAmount());
|
||||||
|
|
||||||
|
System._out_.println("BIC:"+zi.getBIC());
|
||||||
|
|
||||||
|
System._out_.println("IBAN:"+zi.getIBAN());
|
||||||
|
|
||||||
|
System._out_.println("Kontoinhaber:"+zi.getHolder());
|
||||||
|
|
||||||
|
System._out_.println("Rechnungsnr:"+zi.getForeignReference());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
== [#anchor-9]####Schreiben einer ZUGFeRD-PDF-Datei
|
||||||
|
|
||||||
|
Ein Beispielprogramm zum Schreiben ist deshalb umfangreicher, weil
|
||||||
|
erstens mehr Daten in einer differenzierteren Struktur geschrieben
|
||||||
|
werden als derzeit beim Lesen benötigt und zweitens dem Exporter die
|
||||||
|
Daten per Interface zur Verfügung gestellt werden müssen.
|
||||||
|
|
||||||
|
[arabic]
|
||||||
|
. Erstellen Sie eine neue Klasse unterhalb von src, beispielsweise
|
||||||
|
MustangWriter inklusive des obligatorischen „Public static void main()“
|
||||||
|
.
|
||||||
|
. Ändern Sie __*public* *class* MustangWriter __in__ *public* *class*
|
||||||
|
MustangWriter *implements* IZUGFeRDExportableTransaction__
|
||||||
|
. Fügen Sie innerhalb der Klasse MustangWriter folgende Klassen hinzu
|
||||||
|
[arabic]
|
||||||
|
.. *class* _Contact_ *implements* IZUGFeRDExportableContact \{}
|
||||||
|
.. *class* _Item_ *implements* IZUGFeRDExportableItem \{
|
||||||
|
[arabic]
|
||||||
|
... _*private* BigDecimal price, quantity;_
|
||||||
|
|
||||||
|
*private* Product product;
|
||||||
|
|
||||||
|
[arabic, start=4]
|
||||||
|
. {blank}
|
||||||
|
[arabic]
|
||||||
|
.. }
|
||||||
|
.. *class* Product *implements* IZUGFeRDExportableProduct \{
|
||||||
|
[arabic]
|
||||||
|
... *private* String description, name, unit;
|
||||||
|
|
||||||
|
*private* BigDecimal VATPercent;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[arabic, start=5]
|
||||||
|
. Generieren Sie die Imports durch Drücken von STRG+SHIFT+O
|
||||||
|
. Markieren Sie den Klassennamen MustangWriter und drücken Sie
|
||||||
|
ALT+SHIFT+S, wählen Sie Override/Implement Methods und drücken Return.
|
||||||
|
. Klicken Sie auf Contact und Wiederholen Sie den letzten Schritt.
|
||||||
|
. Klicken Sie auf Item, markieren Sie die Variablen und wählen Sie
|
||||||
|
zuerst „_Generate Getters and Setters_“ nach drücken von ALT+SHIFT+S.
|
||||||
|
Wählen Sie alle Member aus und drücken Sie Return.
|
||||||
|
. Klicken Sie erneut auf Item, drücken von ALT+SHIFT+S und wählen
|
||||||
|
„Generate Constructor using Fields“. Wählen Sie erneut alle Member aus
|
||||||
|
und drücken Sie Return.
|
||||||
|
. Auf Item muss der Quick Fix „add unimplemented methods“ ausgeführt
|
||||||
|
werden, die zwei generierten Funktionen (getItemAllowances und
|
||||||
|
getItemCharges) dürfen null zurück geben.
|
||||||
|
. Wenden Sie die beiden letzten Schritte auch auf Product an: Klicken
|
||||||
|
Sie auf Product, markieren Sie die Variablen und wählen Sie „Generate
|
||||||
|
Getters and Setters“ nach drücken von ALT+SHIFT+S. Wählen Sie alle
|
||||||
|
Member aus und drücken Sie Return.
|
||||||
|
. Item benötigt neben den getter/setter auch noch andere Methode, wählen
|
||||||
|
Sie Item aus, drücken Sie ALT+SHIFT+S, wählen Sie Override/Implement
|
||||||
|
Methods
|
||||||
|
. Klicken Sie erneut auf Product, drücken von ALT+SHIFT+S und wählen
|
||||||
|
„Generate Constructor using Fields“. Wählen Sie erneut alle Member aus
|
||||||
|
und drücken Sie Return.
|
||||||
|
. Folgende Methoden von Contact sollten Folgendes zurückgeben:
|
||||||
|
[arabic]
|
||||||
|
.. getCountry(): "DE"
|
||||||
|
.. getLocation(): "Spielkreis"
|
||||||
|
.. getName(): "Theodor Est"
|
||||||
|
.. getStreet(): "Bahnstr. 42"
|
||||||
|
.. getVATID(): "DE999999999"
|
||||||
|
.. getZIP(): "88802";
|
||||||
|
. Folgende Methoden der Hauptklasse -MustangWriter- sollten folgendes
|
||||||
|
zurückgeben:
|
||||||
|
[arabic]
|
||||||
|
.. getDeliveryDate(): *new*
|
||||||
|
GregorianCalendar(2017,Calendar._NOVEMBER_,17).getTime()
|
||||||
|
.. Zweimaliges CTRL+SHIFT+O importiert die dazu nötige GregorianCalendar
|
||||||
|
und Calendar Klasse
|
||||||
|
.. getDueDate(): *new*
|
||||||
|
GregorianCalendar(2017,Calendar._DECEMBER_,9).getTime()
|
||||||
|
.. getIssueDate(): *new*
|
||||||
|
GregorianCalendar(2017,Calendar._NOVEMBER_,18).getTime()
|
||||||
|
.. __getNumber(): "RE-2017__1118__/50__6__"__
|
||||||
|
.. _getOwnBIC(): "COBADEFFXXX"_
|
||||||
|
.. getOwnBankName(): "Commerzbank"
|
||||||
|
.. getOwnCountry() "DE"
|
||||||
|
.. getOwnIBAN(): "DE88 2008 0000 0970 3757 00"
|
||||||
|
.. getOwnLocation() "Stadthausen"
|
||||||
|
.. _getOwnOrganisationName(): "Bei Spiel GmbH"_
|
||||||
|
.. getOwnStreet() "Ecke 12"
|
||||||
|
.. getOwnTaxID(): "22/815/0815/4"
|
||||||
|
.. getOwnVATID(): "DE136695976"
|
||||||
|
.. getOwnZIP(): "12345"
|
||||||
|
.. getOwnOrganisationFullPlaintextInfo(): "Bei Spiel GmbH\n"+
|
||||||
|
+
|
||||||
|
"Ecke 12\n"+
|
||||||
|
+
|
||||||
|
"12345 Stadthausen\n"+
|
||||||
|
+
|
||||||
|
"Geschäftsführer: Max Mustermann"
|
||||||
|
.. _getRecipient(): *new* Contact()_
|
||||||
|
+
|
||||||
|
.. getZFItems() der Hauptklasse kann jetzt Produkte anlegen und diese
|
||||||
|
als Array von Posten (Items) zurückliefern:
|
||||||
|
+
|
||||||
|
Item[] allItems=**new** Item[3];
|
||||||
|
|
||||||
|
Product designProduct=**new** Product("", "Künstlerische Gestaltung
|
||||||
|
(Stunde): Einer Beispielrechnung", "HUR", *new* BigDecimal("7.000000"));
|
||||||
|
|
||||||
|
Product balloonProduct=**new** Product("", "Luftballon: Bunt, ca.
|
||||||
|
500ml", "C62", *new* BigDecimal("19.000000"));
|
||||||
|
|
||||||
|
Product airProduct=**new** Product("", "Heiße Luft pro Liter", "LTR",
|
||||||
|
*new* BigDecimal("19.000000"));
|
||||||
|
|
||||||
|
allItems[0]=**new** Item(*new* BigDecimal("160"), *new* BigDecimal("1"),
|
||||||
|
designProduct);
|
||||||
|
|
||||||
|
allItems[1]=**new** Item(*new* BigDecimal("0.79"), *new*
|
||||||
|
BigDecimal("400"), balloonProduct);
|
||||||
|
|
||||||
|
allItems[2]=**new** Item(*new* BigDecimal("0.10"), *new*
|
||||||
|
BigDecimal("200"), airProduct);
|
||||||
|
|
||||||
|
*return* allItems;
|
||||||
|
|
||||||
|
[arabic]
|
||||||
|
.
|
||||||
|
|
||||||
|
[arabic]
|
||||||
|
. {blank}
|
||||||
|
[arabic]
|
||||||
|
.. Legen Sie eine neue Funktion, beispielsweise „apply“ an (private
|
||||||
|
reicht).
|
||||||
|
.. In der Main-Methode der Hauptklasse instantiiert man jetzt die Klasse
|
||||||
|
und rufen Sie dort apply() auf.
|
||||||
|
.. In der apply-Methode kann man jetzt
|
||||||
|
[arabic]
|
||||||
|
... eine ZUGFeRDExporterFactory instantiieren,
|
||||||
|
... darauf Producer und Creator setzen (bspw. ZUGFeRDExporter ze=new
|
||||||
|
ZUGFeRDExporterFromA1Factory().setProducer(_"string"_).setCreator(_"string"_))
|
||||||
|
und über load die PDF-A/1-Datei angeben und über den Rückgabewert den
|
||||||
|
ZUGFeRDExporter holen. Die ZUGFeRD-Version kann man in der
|
||||||
|
setProducer.setCreator-Kette mit setZUGFeRDVersion(2) angeben.
|
||||||
|
... Auf dem Exporter ruft man diePDFattachZugferdFile-Methode (mit this
|
||||||
|
als IZUGFeRDExportableTransaction) auf und
|
||||||
|
... benutzt schlussendlich die export-Funktion. Die apply-Methode sieht
|
||||||
|
dann – mit entsprechenden try/catch-Blöcken- beispielsweise so aus:
|
||||||
|
|
||||||
|
* try* \{
|
||||||
|
|
||||||
|
System._out_.println("Lese Blanko-PDF");
|
||||||
|
|
||||||
|
ZUGFeRDExporter ze = *new*
|
||||||
|
ZUGFeRDExporterFromA1Factory().setProducer("My
|
||||||
|
Application").setCreator(System._getProperty_("user.name")).load("./MustangGnuaccountingBeispielRE-20171118_506blanko.pdf");
|
||||||
|
|
||||||
|
System._out_.println("Generiere ZUGFeRD-Daten");
|
||||||
|
|
||||||
|
ze.PDFattachZugferdFile(*this*);
|
||||||
|
|
||||||
|
System._out_.println("Schreibe ZUGFeRD-PDF");
|
||||||
|
|
||||||
|
ze.export("./MustangGnuaccountingBeispielRE-20171118_506new.pdf");
|
||||||
|
|
||||||
|
System._out_.println("Fertig.");
|
||||||
|
|
||||||
|
} *catch* (IOException e) \{
|
||||||
|
|
||||||
|
e.printStackTrace();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[arabic, start=2]
|
||||||
|
. {blank}
|
||||||
|
[arabic]
|
||||||
|
.. Ein CTRL+SHIFT+O hilft wieder beim Hinzufügen der nötigen Imports
|
||||||
|
.. „My Application“ und __System.getProperty("user.name") __werden in
|
||||||
|
den Metadaten als „Producer“ (in etwa: erstellende Anwendung)
|
||||||
|
beziehungsweise „Creator“ (in etwa: Autor) gespeichert. Bitte passen Sie
|
||||||
|
die Werte entsprechend Ihrer Anwendung an.
|
||||||
|
.. Starten Sie, es sollte eine valide ZUFeRD-Rechnung in
|
||||||
|
_./MustangGnuaccountingBeispielRE-20171118_506new.pdf_
|
||||||
|
+
|
||||||
|
erstellt werden.
|
||||||
|
.. Passen Sie ggf. die NOTICE-Datei an und fügen Sie Ihrer Anwendung
|
||||||
|
hinzu.
|
||||||
|
.. Stellen Sie sicher, dass die XML-Daten in der dem PDF eingebetteten
|
||||||
|
ZUGFeRD-invoice.xml immer den menschenlesbaren Daten im PDF entsprechen.
|
||||||
|
|
||||||
|
Die erzeugte Datei beinhaltet ZUGFeRD-invoice.xml statt factur-x.xml im
|
||||||
|
offiziellen Beispiel so lange die ZUGFeRD-Version in der Factory nicht
|
||||||
|
auf 2 gesetzt wurde.
|
||||||
|
|
||||||
|
[arabic]
|
||||||
|
.
|
||||||
|
|
||||||
|
=== [#anchor-10]####Komplettes Schreibbeispiel
|
||||||
|
|
||||||
|
Siehe MustangWriter.java in diesem Verzeichnis.
|
||||||
|
|
||||||
|
=== [#anchor-11]####Schreiben eigener XML-Daten
|
||||||
|
|
||||||
|
Sollten Sie eine eigene Implementierung verwenden um ZUGFeRD-XML-Daten
|
||||||
|
zu erzeugen können Sie diese mit setZUGFeRDXMLData schreiben:
|
||||||
|
|
||||||
|
ZUGFeRDExporter ze;
|
||||||
|
|
||||||
|
*try* \{
|
||||||
|
|
||||||
|
System.*_out_*.println("Konvertiere zu PDF/A-3u");
|
||||||
|
|
||||||
|
ze = new
|
||||||
|
|
||||||
|
ZUGFeRDExporterFromA1Factory().setProducer("My
|
||||||
|
|
||||||
|
Application").setCreator(System._getProperty_("user.name")).load("./MustangGnuaccountingBeispielRE-20171118_506blanko.pdf");
|
||||||
|
|
||||||
|
System.*_out_*.println("Hänge ZUGFeRD-Datei an");
|
||||||
|
|
||||||
|
String ownZUGFeRDXML =
|
||||||
|
"<rsm:CrossIndustryDocument></rsm:CrossIndustryDocument>";
|
||||||
|
|
||||||
|
ze.setZUGFeRDXMLData(ownZUGFeRDXML.getBytes());
|
||||||
|
|
||||||
|
System.*_out_*.println("Schreibe ZUGFeRD-PDF");
|
||||||
|
|
||||||
|
ze.export("./Target.pdf");
|
||||||
|
|
||||||
|
System.*_out_*.println("Fertig.");
|
||||||
|
|
||||||
|
} *catch* (IOException e) \{
|
||||||
|
|
||||||
|
e.printStackTrace();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Mustangproject prüft, die Eingabedatei auf einigermaßen korrektes PDF/A
|
||||||
|
ist und dass die XML-Daten mindestens <rsm:CrossIndustry enthalten was
|
||||||
|
auf ZF1- (CrossIndustryDocument) und ZF2-Daten (CrossIndustryInvoice)
|
||||||
|
zutrifft.
|
||||||
|
|
||||||
|
=== [#anchor-12]####Zusatzfunktionen
|
||||||
|
|
||||||
|
* ZUGFeRDExporter.setTest() setzt ein Attribut im ZUGFeRD-XML, das
|
||||||
|
benutzt wird um eine Testrechnung auszuzeichnen.
|
||||||
|
* ZUGFeRDExporter.ignoreA1Errors() überspringt die Überprüfung der
|
||||||
|
Eingangsdatei auf PDF/A-1-Fehler
|
||||||
|
* Ein erster Versuch bestehendes ZUGFeRD1-XML in 2 zu konvertieren kann
|
||||||
|
mit String facturx=new
|
||||||
|
ZUGFeRDMigrator().migrateFromV1ToV2(zugferdInvoice); begonnen werden.
|
||||||
182
doc/ZugferdDev.en.adoc
Normal file
182
doc/ZugferdDev.en.adoc
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
== Mustang project user documentation
|
||||||
|
|
||||||
|
Jochen Stärk
|
||||||
|
|
||||||
|
For Mustangproject 2.17.0, 2025-05-28
|
||||||
|
|
||||||
|
http://www.mustangproject.org/[http://www.mustangproject.org]
|
||||||
|
|
||||||
|
== About Mustangproject
|
||||||
|
|
||||||
|
Mustangproject is a Java-Library for invoice („Factur-X/ZUGFeRD“-)metadata in
|
||||||
|
PDF-invoices as well as XRechnung (CII, or on the reading side also UBL).
|
||||||
|
|
||||||
|
It can read, write and validate those files uses PDF/A files as
|
||||||
|
input, underlies the Apache Public License and can
|
||||||
|
be used for free in commercial and noncommercial projects as long as
|
||||||
|
the license conditions are met.
|
||||||
|
|
||||||
|
On link:https://zugferd.org/[zugferd.org] we list other libraries also for other
|
||||||
|
languages
|
||||||
|
|
||||||
|
== Download/Project setup
|
||||||
|
|
||||||
|
=== Source code
|
||||||
|
|
||||||
|
Home of the Mustangproject source code is
|
||||||
|
https://github.com/ZUGFeRD/mustangproject/
|
||||||
|
|
||||||
|
=== With Maven
|
||||||
|
|
||||||
|
E.g. using link:https://www.jetbrains.com/idea/download/?section=windows[IntelliJ].
|
||||||
|
|
||||||
|
Add the following dependency to your project
|
||||||
|
|
||||||
|
|
||||||
|
----
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mustangproject</groupId>
|
||||||
|
<artifactId>validator</artifactId>
|
||||||
|
<classifier>shaded</classifier>
|
||||||
|
<version>2.17.0</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
----
|
||||||
|
|
||||||
|
Open the Maven Window and click Sync all Maven projects.
|
||||||
|
|
||||||
|
== Reading Factur-X/ZUGFeRD data
|
||||||
|
|
||||||
|
[arabic]
|
||||||
|
. Download a factur-x sample with metadata like
|
||||||
|
https://www.mustangproject.org/files/MustangGnuaccountingBeispielRE-20201121_508.pdf[https://www.mustangproject.org/files/MustangGnuaccountingBeispielRE-20201121_508.pdf]
|
||||||
|
. Create a new Maven project. Add the jar in the pom.xml as described above. In
|
||||||
|
----
|
||||||
|
public class Main {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
System.out.println("Hello, World!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
----
|
||||||
|
|
||||||
|
use
|
||||||
|
|
||||||
|
----
|
||||||
|
ZUGFeRDInvoiceImporter zii=new ZUGFeRDInvoiceImporter("MustangGnuaccountingBeispielRE-20201121_508.pdf");
|
||||||
|
CalculatedInvoice ci=new CalculatedInvoice();
|
||||||
|
try {
|
||||||
|
zii.extractInto(ci);
|
||||||
|
System.out.println("Pay: "+ci.getDuePayable());
|
||||||
|
} catch (XPathExpressionException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} catch (ParseException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
----
|
||||||
|
|
||||||
|
To find out how much you have to pay.
|
||||||
|
|
||||||
|
=== Complete sample source code for reading ZUGFeRD data
|
||||||
|
|
||||||
|
|
||||||
|
----
|
||||||
|
package de.usegroup;
|
||||||
|
|
||||||
|
import org.mustangproject.CalculatedInvoice;
|
||||||
|
import org.mustangproject.ZUGFeRD.ZUGFeRDInvoiceImporter;
|
||||||
|
|
||||||
|
import javax.xml.xpath.XPathExpressionException;
|
||||||
|
import java.text.ParseException;
|
||||||
|
|
||||||
|
public class Main {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
ZUGFeRDInvoiceImporter zii=new ZUGFeRDInvoiceImporter("MustangGnuaccountingBeispielRE-20201121_508.pdf");
|
||||||
|
CalculatedInvoice ci=new CalculatedInvoice();
|
||||||
|
try {
|
||||||
|
zii.extractInto(ci);
|
||||||
|
System.out.println("Pay: "+ci.getDuePayable());
|
||||||
|
} catch (XPathExpressionException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} catch (ParseException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
----
|
||||||
|
|
||||||
|
NOTE: You can additionally validate the file with two additional lines
|
||||||
|
----
|
||||||
|
ZUGFeRDValidator zv=new ZUGFeRDValidator();
|
||||||
|
System.out.println(zv.validate("MustangGnuaccountingBeispielRE-20201121_508.pdf"));
|
||||||
|
----
|
||||||
|
|
||||||
|
|
||||||
|
== Writing a ZUGFeRD-PDF file
|
||||||
|
|
||||||
|
A sample for writing Factur-X/ZUGFeRD PDFs requires a PDF/A file to attach the XML to,
|
||||||
|
saved
|
||||||
|
e.g. as link:https://www.mustangproject.org/files/MustangGnuaccountingBeispielRE-20190610_507blanko.pdf[blanko.pdf]
|
||||||
|
|
||||||
|
The core is creating an exporter, an invoice and send the invoice through the exporter:
|
||||||
|
----
|
||||||
|
IZUGFeRDExporter ze = new ZUGFeRDExporterFromPDFA().load(sourcePDF).setProducer("My Application").
|
||||||
|
setCreator(System.getProperty("user.name"));
|
||||||
|
|
||||||
|
Invoice i=new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date())
|
||||||
|
.setSender(new TradeParty("ACME co", "teststr", "55232", "teststadt", "DE")
|
||||||
|
.addBankDetails(new BankDetails("777666555", "DE4321"))).setOwnTaxID("4711").setOwnVATID("DE19990815")
|
||||||
|
.setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE")
|
||||||
|
.setContact(new Contact("nameRep", "phoneRep", "emailRep@test.com"))).setNumber("X12")
|
||||||
|
.addItem(new Item(new Product("Testproduct", "", "H87", new BigDecimal(19)),
|
||||||
|
new BigDecimal(2.5), new BigDecimal(1.0)));
|
||||||
|
ze.setTransaction(i);
|
||||||
|
ze.export("factur-x.pdf");
|
||||||
|
----
|
||||||
|
Additionally, you should confirm that Mustangs calculated total matches that of your PDF/A file, for which you can use
|
||||||
|
the TransactionCalculator (which is also used internally in the exporter):
|
||||||
|
|
||||||
|
----
|
||||||
|
TransactionCalculator tc=new TransactionCalculator(i);
|
||||||
|
System.out.println("Confirm "+tc.getDuePayable()+ " is also the final amount in your PDF");
|
||||||
|
----
|
||||||
|
|
||||||
|
NOTE: We're using BigDecimals to avoid rounding errors.
|
||||||
|
|
||||||
|
So the complete write example looks like this:
|
||||||
|
----
|
||||||
|
package de.usegroup;
|
||||||
|
|
||||||
|
import org.mustangproject.*;
|
||||||
|
import org.mustangproject.ZUGFeRD.IZUGFeRDExporter;
|
||||||
|
import org.mustangproject.ZUGFeRD.TransactionCalculator;
|
||||||
|
import org.mustangproject.ZUGFeRD.ZUGFeRDExporterFromPDFA;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
public class Main {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
String sourcePDF="MustangGnuaccountingBeispielRE-20201121_508.pdf";
|
||||||
|
try {
|
||||||
|
IZUGFeRDExporter ze = new ZUGFeRDExporterFromPDFA().load(sourcePDF).setProducer("My Application").
|
||||||
|
setCreator(System.getProperty("user.name"));
|
||||||
|
|
||||||
|
Invoice i=new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date())
|
||||||
|
.setSender(new TradeParty("ACME co", "teststr", "55232", "teststadt", "DE")
|
||||||
|
.addBankDetails(new BankDetails("777666555", "DE4321"))).setOwnTaxID("4711").setOwnVATID("DE19990815")
|
||||||
|
.setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE")
|
||||||
|
.setContact(new Contact("nameRep", "phoneRep", "emailRep@test.com"))).setNumber("X12")
|
||||||
|
.addItem(new Item(new Product("Testproduct", "", "H87", new BigDecimal(19)),
|
||||||
|
new BigDecimal(2.5), new BigDecimal(1.0)));
|
||||||
|
ze.setTransaction(i);
|
||||||
|
ze.export("factur-x.pdf");
|
||||||
|
TransactionCalculator tc=new TransactionCalculator(i);
|
||||||
|
System.out.println("Confirm "+tc.getDuePayable()+ " is also the final amount in your PDF");
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
----
|
||||||
Binary file not shown.
@@ -3,13 +3,13 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mustangproject</groupId>
|
<groupId>org.mustangproject</groupId>
|
||||||
<artifactId>core</artifactId>
|
<artifactId>core</artifactId>
|
||||||
<version>2.17.0-SNAPSHOT</version>
|
<version>2.17.1-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>org.mustangproject</groupId>
|
<groupId>org.mustangproject</groupId>
|
||||||
<artifactId>library</artifactId>
|
<artifactId>library</artifactId>
|
||||||
<version>2.17.0-SNAPSHOT</version>
|
<version>2.17.1-SNAPSHOT</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<name>Library to write, read and validate e-invoices (Factur-X, ZUGFeRD, Order-X, XRechnung/CII)</name>
|
<name>Library to write, read and validate e-invoices (Factur-X, ZUGFeRD, Order-X, XRechnung/CII)</name>
|
||||||
<description>FOSS Java library to read, write and validate european electronic invoices and orders in the UN/CEFACT
|
<description>FOSS Java library to read, write and validate european electronic invoices and orders in the UN/CEFACT
|
||||||
@@ -133,7 +133,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.helger</groupId>
|
<groupId>com.helger</groupId>
|
||||||
<artifactId>en16931-cii2ubl</artifactId>
|
<artifactId>en16931-cii2ubl</artifactId>
|
||||||
<version>2.2.4</version>
|
<version>2.3.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- test dependencies -->
|
<!-- test dependencies -->
|
||||||
|
|||||||
@@ -3,8 +3,10 @@ package org.mustangproject;
|
|||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import org.mustangproject.ZUGFeRD.IAbsoluteValueProvider;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* (absolute) allowances on item and document level
|
* (absolute) allowances on item and document level
|
||||||
@@ -29,6 +31,22 @@ public class Allowance extends Charge {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigDecimal getTotalAmount(IAbsoluteValueProvider currentItem) {
|
||||||
|
if(totalAmount != null) {
|
||||||
|
return totalAmount;
|
||||||
|
} else if (percent!=null) {
|
||||||
|
BigDecimal singlePrice=currentItem.getValue().divide(BigDecimal.ONE.add(getPercent().divide(new BigDecimal(100))), 18, RoundingMode.HALF_UP);
|
||||||
|
// BigDecimal singlePrice=currentItem.getValue().multiply(BigDecimal.ONE.subtract(getPercent().divide(new BigDecimal(100))));
|
||||||
|
BigDecimal singlePriceDiff=currentItem.getValue().subtract(singlePrice);
|
||||||
|
return singlePriceDiff;
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("percent must be set");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Always to return false for IZUGFeRDAllowanceCharge
|
* Always to return false for IZUGFeRDAllowanceCharge
|
||||||
* @return false since its not supposed to be calculated negatively
|
* @return false since its not supposed to be calculated negatively
|
||||||
|
|||||||
@@ -23,6 +23,14 @@ public class BankDetails implements IZUGFeRDTradeSettlementPayment {
|
|||||||
* the "name" of the bank account (holder)
|
* the "name" of the bank account (holder)
|
||||||
*/
|
*/
|
||||||
protected String accountName = null;
|
protected String accountName = null;
|
||||||
|
/**
|
||||||
|
* payment means code
|
||||||
|
*/
|
||||||
|
protected String paymentMeansCode = "58";
|
||||||
|
/**
|
||||||
|
* payment means information
|
||||||
|
*/
|
||||||
|
protected String paymentMeansInformation = "SEPA credit transfer";
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* bean constructor
|
* bean constructor
|
||||||
@@ -123,5 +131,31 @@ public class BankDetails implements IZUGFeRDTradeSettlementPayment {
|
|||||||
return accountName;
|
return accountName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set payment means code
|
||||||
|
*
|
||||||
|
* @param paymentMeansCode the payment means code
|
||||||
|
* @return fluent setter
|
||||||
|
*/
|
||||||
|
public BankDetails setPaymentMeansCode(String paymentMeansCode) {
|
||||||
|
this.paymentMeansCode = paymentMeansCode;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPaymentMeansCode() { return paymentMeansCode; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set payment means information
|
||||||
|
*
|
||||||
|
* @param paymentMeansInformation the payment mean information
|
||||||
|
* @return fluent setter
|
||||||
|
*/
|
||||||
|
public BankDetails setPaymentMeansInformation(String paymentMeansInformation) {
|
||||||
|
this.paymentMeansInformation = paymentMeansInformation;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPaymentMeansInformation() { return paymentMeansInformation; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,7 +103,6 @@ public class CalculatedInvoice extends Invoice implements Serializable {
|
|||||||
* @return a updated transactioncalulator
|
* @return a updated transactioncalulator
|
||||||
*/
|
*/
|
||||||
public TransactionCalculator getCalculation() {
|
public TransactionCalculator getCalculation() {
|
||||||
calculate();
|
|
||||||
return tc;
|
return tc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import org.mustangproject.ZUGFeRD.IAbsoluteValueProvider;
|
|||||||
import org.mustangproject.ZUGFeRD.IZUGFeRDAllowanceCharge;
|
import org.mustangproject.ZUGFeRD.IZUGFeRDAllowanceCharge;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Absolute and relative charges for document and item level
|
* Absolute and relative charges for document and item level
|
||||||
@@ -23,6 +24,10 @@ public class Charge implements IZUGFeRDAllowanceCharge {
|
|||||||
* the absolute value if not percentage
|
* the absolute value if not percentage
|
||||||
*/
|
*/
|
||||||
protected BigDecimal totalAmount;
|
protected BigDecimal totalAmount;
|
||||||
|
/**
|
||||||
|
* the value the percentage is applied upon
|
||||||
|
*/
|
||||||
|
protected BigDecimal basisAmount;
|
||||||
/**
|
/**
|
||||||
* the tax rate the charge belongs to
|
* the tax rate the charge belongs to
|
||||||
*/
|
*/
|
||||||
@@ -103,6 +108,22 @@ public class Charge implements IZUGFeRDAllowanceCharge {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BigDecimal getBasisAmount() {
|
||||||
|
return basisAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* sets a potential basis for the potential percentage
|
||||||
|
* @param basis the basis amount
|
||||||
|
* @return fluid setter
|
||||||
|
*/
|
||||||
|
public Charge setBasisAmount(BigDecimal basis) {
|
||||||
|
this.basisAmount = basis;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getReasonCode() {
|
public String getReasonCode() {
|
||||||
return reasonCode;
|
return reasonCode;
|
||||||
@@ -121,10 +142,13 @@ public class Charge implements IZUGFeRDAllowanceCharge {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BigDecimal getTotalAmount(IAbsoluteValueProvider currentItem) {
|
public BigDecimal getTotalAmount(IAbsoluteValueProvider currentItem) {
|
||||||
if (percent!=null) {
|
if(totalAmount != null) {
|
||||||
return currentItem.getValue().multiply(getPercent().divide(new BigDecimal(100)));
|
|
||||||
} else if(totalAmount != null) {
|
|
||||||
return totalAmount;
|
return totalAmount;
|
||||||
|
} else if (percent!=null) {
|
||||||
|
BigDecimal singlePrice=currentItem.getValue().divide(BigDecimal.ONE.add(getPercent().divide(new BigDecimal(100))), 18, RoundingMode.HALF_UP);
|
||||||
|
// BigDecimal singlePrice=currentItem.getValue().multiply(BigDecimal.ONE.subtract(getPercent().divide(new BigDecimal(100))));
|
||||||
|
BigDecimal singlePriceDiff=currentItem.getValue().add(singlePrice);
|
||||||
|
return singlePriceDiff;
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("percent must be set");
|
throw new RuntimeException("percent must be set");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,8 +72,6 @@ public class Item implements IZUGFeRDExportableItem {
|
|||||||
//we need: name description unitcode
|
//we need: name description unitcode
|
||||||
//and we additionally have vat%
|
//and we additionally have vat%
|
||||||
|
|
||||||
// Bharti's homework 20241126:Streams https://www.youtube.com/watch?v=Lf01cBzmuXw
|
|
||||||
// and Lambdas https://www.youtube.com/watch?v=HCyx31NW8xg
|
|
||||||
setProduct(new Product(itemMap.getNode("Item").get()));
|
setProduct(new Product(itemMap.getNode("Item").get()));
|
||||||
icnm.getAsString("Name").ifPresent(product::setName);
|
icnm.getAsString("Name").ifPresent(product::setName);
|
||||||
icnm.getAsString("Description").ifPresent(product::setDescription);
|
icnm.getAsString("Description").ifPresent(product::setDescription);
|
||||||
@@ -86,17 +84,6 @@ public class Item implements IZUGFeRDExportableItem {
|
|||||||
BuyersItemIdentification.getAsString("ID").ifPresent(product::setBuyerAssignedID);
|
BuyersItemIdentification.getAsString("ID").ifPresent(product::setBuyerAssignedID);
|
||||||
});
|
});
|
||||||
|
|
||||||
// String name = icnm.getAsStringOrNull("Name");
|
|
||||||
// String val = icnm.getAsStringOrNull("Value");
|
|
||||||
// if (name != null && val != null) {
|
|
||||||
// if (attributes == null) {
|
|
||||||
// attributes = new HashMap<>();
|
|
||||||
// }
|
|
||||||
// product.attributes.put(name, val);
|
|
||||||
// }
|
|
||||||
//icnm.getNode("AdditionalItemProperty").flatMap(n ->n.getAttributes()).ifPresent(product::setAttributes);
|
|
||||||
|
|
||||||
|
|
||||||
icnm.getAsNodeMap("ClassifiedTaxCategory").flatMap(m -> m.getAsBigDecimal("Percent"))
|
icnm.getAsNodeMap("ClassifiedTaxCategory").flatMap(m -> m.getAsBigDecimal("Percent"))
|
||||||
.ifPresent(product::setVATPercent);
|
.ifPresent(product::setVATPercent);
|
||||||
});
|
});
|
||||||
@@ -175,11 +162,12 @@ public class Item implements IZUGFeRDExportableItem {
|
|||||||
.ifPresent(product::setTaxExemptionReason);
|
.ifPresent(product::setTaxExemptionReason);
|
||||||
|
|
||||||
icnm.getAllNodes("SpecifiedTradeAllowanceCharge").map(NodeMap::new).forEach(stac -> {
|
icnm.getAllNodes("SpecifiedTradeAllowanceCharge").map(NodeMap::new).forEach(stac -> {
|
||||||
stac.getAsNodeMap("ChargeIndicator").ifPresent(ci -> { //CII
|
stac.getAsNodeMap("ChargeIndicator").ifPresent(ci -> {
|
||||||
String isChargeString = ci.getAsString("Indicator").get();
|
String isChargeString = ci.getAsString("Indicator").get();
|
||||||
String percentString = stac.getAsStringOrNull("CalculationPercent");//MultiplierFactorNumeric
|
String percentString = stac.getAsStringOrNull("CalculationPercent");
|
||||||
String amountString = stac.getAsStringOrNull("ActualAmount");//Amount
|
String amountString = stac.getAsStringOrNull("ActualAmount");
|
||||||
String reason = stac.getAsStringOrNull("Reason");//AllowanceChargeReason
|
String basisAmountString = stac.getAsStringOrNull("BasisAmount");
|
||||||
|
String reason = stac.getAsStringOrNull("Reason");
|
||||||
Charge izac = new Charge();
|
Charge izac = new Charge();
|
||||||
if (isChargeString.equalsIgnoreCase("false")) {
|
if (isChargeString.equalsIgnoreCase("false")) {
|
||||||
izac = new Allowance();
|
izac = new Allowance();
|
||||||
@@ -188,6 +176,12 @@ public class Item implements IZUGFeRDExportableItem {
|
|||||||
}
|
}
|
||||||
if (amountString != null) {
|
if (amountString != null) {
|
||||||
izac.setTotalAmount(new BigDecimal(amountString));
|
izac.setTotalAmount(new BigDecimal(amountString));
|
||||||
|
if (percentString!=null&&(percentString!="0")) {
|
||||||
|
izac.setTotalAmount(new BigDecimal(amountString).divide(getQuantity()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (basisAmountString != null) {
|
||||||
|
izac.setBasisAmount(new BigDecimal(basisAmountString));
|
||||||
}
|
}
|
||||||
if (percentString != null) {
|
if (percentString != null) {
|
||||||
izac.setPercent(new BigDecimal(percentString));
|
izac.setPercent(new BigDecimal(percentString));
|
||||||
@@ -288,6 +282,16 @@ public class Item implements IZUGFeRDExportableItem {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override public IZUGFeRDAllowanceCharge[] getAllowances() {
|
||||||
|
IZUGFeRDAllowanceCharge[] izac=new IZUGFeRDAllowanceCharge[Allowances.size()];
|
||||||
|
return Allowances.toArray(izac);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public IZUGFeRDAllowanceCharge[] getCharges() {
|
||||||
|
IZUGFeRDAllowanceCharge[] izac=new IZUGFeRDAllowanceCharge[Charges.size()];
|
||||||
|
return Charges.toArray(izac);
|
||||||
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* BT 132 (issue https://github.com/ZUGFeRD/mustangproject/issues/247)
|
* BT 132 (issue https://github.com/ZUGFeRD/mustangproject/issues/247)
|
||||||
* @return the line ID of the order (BT132)
|
* @return the line ID of the order (BT132)
|
||||||
@@ -461,6 +465,7 @@ public class Item implements IZUGFeRDExportableItem {
|
|||||||
* @return fluent setter
|
* @return fluent setter
|
||||||
*/
|
*/
|
||||||
public Item addAllowance(IZUGFeRDAllowanceCharge izac) {
|
public Item addAllowance(IZUGFeRDAllowanceCharge izac) {
|
||||||
|
|
||||||
Allowances.add(izac);
|
Allowances.add(izac);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ public class Product implements IZUGFeRDExportableProduct {
|
|||||||
protected boolean isIntraCommunitySupply = false;
|
protected boolean isIntraCommunitySupply = false;
|
||||||
protected SchemedID globalId = null;
|
protected SchemedID globalId = null;
|
||||||
protected String countryOfOrigin = null;
|
protected String countryOfOrigin = null;
|
||||||
|
protected ArrayList<Charge> charges=new ArrayList<>();
|
||||||
|
protected ArrayList<Allowance> allowances=new ArrayList<>();
|
||||||
protected HashMap<String, String> attributes = new HashMap<>();
|
protected HashMap<String, String> attributes = new HashMap<>();
|
||||||
|
|
||||||
protected List<IDesignatedProductClassification> classifications = new ArrayList<>();
|
protected List<IDesignatedProductClassification> classifications = new ArrayList<>();
|
||||||
@@ -393,4 +395,42 @@ public class Product implements IZUGFeRDExportableProduct {
|
|||||||
this.classifications.add(classification);
|
this.classifications.add(classification);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Product addCharge(Charge e) {
|
||||||
|
charges.add(e);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Product addAllowance(Allowance a) {
|
||||||
|
allowances.add(a);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* returns the AppliedTradeAllowanceCharges of this product which are actually Charges
|
||||||
|
* @return array of or null, if none
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Charge[] getCharges() {
|
||||||
|
if (charges.size()==0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Charge[] chargeArr = new Charge[charges.size()];
|
||||||
|
return charges.toArray(chargeArr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
/***
|
||||||
|
* returns the AppliedTradeAllowanceCharges of this product which are actually Allowances
|
||||||
|
* @return array of or null, if none
|
||||||
|
*/
|
||||||
|
public Allowance[] getAllowances() {
|
||||||
|
if (allowances.size()==0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Allowance[] allowanceArr = new Allowance[allowances.size()];
|
||||||
|
return allowances.toArray(allowanceArr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,12 @@ public interface IZUGFeRDAllowanceCharge {
|
|||||||
*/
|
*/
|
||||||
default BigDecimal getPercent() {return null;}
|
default BigDecimal getPercent() {return null;}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* returns a basis the precentage is calculated from
|
||||||
|
* @return null or the basis
|
||||||
|
*/
|
||||||
|
default BigDecimal getBasisAmount() {return null;}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* get a description for the allowance/charge
|
* get a description for the allowance/charge
|
||||||
* @return the description
|
* @return the description
|
||||||
|
|||||||
@@ -43,7 +43,11 @@ public interface IZUGFeRDExportableItem extends IAbsoluteValueProvider{
|
|||||||
* item level discounts
|
* item level discounts
|
||||||
* @return array of the discounts on a single item
|
* @return array of the discounts on a single item
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
default IZUGFeRDAllowanceCharge[] getItemAllowances() {
|
default IZUGFeRDAllowanceCharge[] getItemAllowances() {
|
||||||
|
if (getProduct()!=null) {
|
||||||
|
return getProduct().getAllowances();
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,10 +55,27 @@ public interface IZUGFeRDExportableItem extends IAbsoluteValueProvider{
|
|||||||
* item level price additions
|
* item level price additions
|
||||||
* @return array of the additional charges on the item
|
* @return array of the additional charges on the item
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
default IZUGFeRDAllowanceCharge[] getItemCharges() {
|
default IZUGFeRDAllowanceCharge[] getItemCharges() {
|
||||||
|
if (getProduct()!=null) {
|
||||||
|
return getProduct().getCharges();
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
default IZUGFeRDAllowanceCharge[] getAllowances() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* item level price additions
|
||||||
|
* @return array of the additional charges on the item
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
default IZUGFeRDAllowanceCharge[] getCharges() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* BT 132 (issue https://github.com/ZUGFeRD/mustangproject/issues/247)
|
* BT 132 (issue https://github.com/ZUGFeRD/mustangproject/issues/247)
|
||||||
@@ -147,9 +168,9 @@ public interface IZUGFeRDExportableItem extends IAbsoluteValueProvider{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* specify allowances amount for the line item total
|
* get all (allowances and charges) SpecifiedTradeAllowanceCharges
|
||||||
*
|
*
|
||||||
* @return the sum of allowances for this item
|
* @return the real item lecel SpecifiedTradeAllowanceCharges
|
||||||
*/
|
*/
|
||||||
default IZUGFeRDAllowanceCharge[] getItemTotalAllowances() {
|
default IZUGFeRDAllowanceCharge[] getItemTotalAllowances() {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -166,6 +166,25 @@ public interface IZUGFeRDExportableProduct {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* product level discounts (AppliedTradeAllowanceCharge, will change net price)
|
||||||
|
* @return array of the discounts on a single product
|
||||||
|
*/
|
||||||
|
default IZUGFeRDAllowanceCharge[] getAllowances() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* product level charges (AppliedTradeAllowanceCharge, will change net price)
|
||||||
|
* @return array of the additional charges on the product
|
||||||
|
*/
|
||||||
|
default IZUGFeRDAllowanceCharge[] getCharges() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detailed information about the product
|
* Detailed information about the product
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -59,6 +59,16 @@ public interface IZUGFeRDTradeSettlementPayment extends IZUGFeRDTradeSettlement
|
|||||||
*/
|
*/
|
||||||
default String getAccountName() { return null; }
|
default String getAccountName() { return null; }
|
||||||
|
|
||||||
|
/***
|
||||||
|
* @return payment means code (BT-81 / UNTDID 4461)
|
||||||
|
*/
|
||||||
|
default String getPaymentMeansCode() { return null; };
|
||||||
|
|
||||||
|
/***
|
||||||
|
* @return payment means description (BT-82) (optional)
|
||||||
|
*/
|
||||||
|
default String getPaymentMeansInformation() { return null; };
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
@@ -70,12 +80,14 @@ public interface IZUGFeRDTradeSettlementPayment extends IZUGFeRDTradeSettlement
|
|||||||
}
|
}
|
||||||
|
|
||||||
String xml = "<ram:SpecifiedTradeSettlementPaymentMeans>"
|
String xml = "<ram:SpecifiedTradeSettlementPaymentMeans>"
|
||||||
+ "<ram:TypeCode>58</ram:TypeCode>"
|
+ "<ram:TypeCode>" + XMLTools.encodeXML(getPaymentMeansCode()) + "</ram:TypeCode>"
|
||||||
+ "<ram:Information>SEPA credit transfer</ram:Information>"
|
+ "<ram:Information>" + XMLTools.encodeXML(getPaymentMeansInformation()) + "</ram:Information>";
|
||||||
+ "<ram:PayeePartyCreditorFinancialAccount>"
|
if (getOwnIBAN() != null) {
|
||||||
+ "<ram:IBANID>" + XMLTools.encodeXML(getOwnIBAN()) + "</ram:IBANID>";
|
xml += "<ram:PayeePartyCreditorFinancialAccount>"
|
||||||
xml+= accountNameStr;
|
+ "<ram:IBANID>" + XMLTools.encodeXML(getOwnIBAN()) + "</ram:IBANID>"
|
||||||
xml+= "</ram:PayeePartyCreditorFinancialAccount>";
|
+ accountNameStr
|
||||||
|
+ "</ram:PayeePartyCreditorFinancialAccount>";
|
||||||
|
}
|
||||||
if (getOwnBIC()!=null) {
|
if (getOwnBIC()!=null) {
|
||||||
xml+= "<ram:PayeeSpecifiedCreditorFinancialInstitution>"
|
xml+= "<ram:PayeeSpecifiedCreditorFinancialInstitution>"
|
||||||
+ "<ram:BICID>" + XMLTools.encodeXML(getOwnBIC()) + "</ram:BICID>"
|
+ "<ram:BICID>" + XMLTools.encodeXML(getOwnBIC()) + "</ram:BICID>"
|
||||||
|
|||||||
@@ -2,30 +2,49 @@ package org.mustangproject.ZUGFeRD;
|
|||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.RoundingMode;
|
import java.math.RoundingMode;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* the linecalculator does the math within an item line, and e.g. calculates quantity*price.
|
* the linecalculator does the math within an item line, and e.g. calculates quantity*price.
|
||||||
* @see TransactionCalculator
|
* @see TransactionCalculator
|
||||||
*/
|
*/
|
||||||
public class LineCalculator {
|
public class LineCalculator {
|
||||||
private final BigDecimal price;
|
protected BigDecimal price;
|
||||||
private final BigDecimal priceGross;
|
protected BigDecimal priceGross;
|
||||||
private final BigDecimal itemTotalNetAmount;
|
protected BigDecimal itemTotalNetAmount;
|
||||||
private final BigDecimal itemTotalVATAmount;
|
protected BigDecimal itemTotalVATAmount;
|
||||||
private BigDecimal allowance = BigDecimal.ZERO;
|
protected BigDecimal lineAllowance = BigDecimal.ZERO;
|
||||||
private BigDecimal charge = BigDecimal.ZERO;
|
protected BigDecimal lineCharge = BigDecimal.ZERO;
|
||||||
private BigDecimal allowanceItemTotal = BigDecimal.ZERO;
|
protected BigDecimal itemAllowance = BigDecimal.ZERO;
|
||||||
|
protected BigDecimal itemCharge = BigDecimal.ZERO;
|
||||||
|
protected BigDecimal allowanceItemTotal = BigDecimal.ZERO;
|
||||||
|
|
||||||
public LineCalculator(IZUGFeRDExportableItem currentItem) {
|
public LineCalculator(IZUGFeRDExportableItem currentItem) {
|
||||||
|
|
||||||
if (currentItem.getItemAllowances() != null && currentItem.getItemAllowances().length > 0) {
|
if (currentItem.getItemAllowances() != null && currentItem.getItemAllowances().length > 0) {
|
||||||
for (IZUGFeRDAllowanceCharge allowance : currentItem.getItemAllowances()) {
|
for (IZUGFeRDAllowanceCharge allowance : currentItem.getItemAllowances()) {
|
||||||
addAllowance(allowance.getTotalAmount(currentItem));
|
BigDecimal factor=BigDecimal.ONE;
|
||||||
|
BigDecimal singleAllowance=allowance.getTotalAmount(currentItem);
|
||||||
|
addItemAllowance(singleAllowance);
|
||||||
|
|
||||||
|
if ((allowance.getPercent()!=null)&&(allowance.getPercent().compareTo(BigDecimal.ZERO)!=0)) {
|
||||||
|
factor=currentItem.getQuantity();
|
||||||
|
}
|
||||||
|
addAllowanceItemTotal(singleAllowance.multiply(factor));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (currentItem.getItemCharges() != null && currentItem.getItemCharges().length > 0) {
|
if (currentItem.getItemCharges() != null && currentItem.getItemCharges().length > 0) {
|
||||||
for (IZUGFeRDAllowanceCharge charge : currentItem.getItemCharges()) {
|
for (IZUGFeRDAllowanceCharge charge : currentItem.getItemCharges()) {
|
||||||
addCharge(charge.getTotalAmount(currentItem));
|
BigDecimal factor=BigDecimal.ONE;
|
||||||
|
BigDecimal singleCharge=charge.getTotalAmount(currentItem);
|
||||||
|
addItemCharge(singleCharge);
|
||||||
|
if ((charge.getPercent()!=null)&&(charge.getPercent().compareTo(BigDecimal.ZERO)!=0)) {
|
||||||
|
factor=currentItem.getQuantity();
|
||||||
|
}
|
||||||
|
subtractAllowanceItemTotal(singleCharge.multiply(factor));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (currentItem.getItemTotalAllowances() != null && currentItem.getItemTotalAllowances().length > 0) {
|
if (currentItem.getItemTotalAllowances() != null && currentItem.getItemTotalAllowances().length > 0) {
|
||||||
@@ -42,22 +61,41 @@ public class LineCalculator {
|
|||||||
vatPercent = BigDecimal.ZERO;
|
vatPercent = BigDecimal.ZERO;
|
||||||
}
|
}
|
||||||
BigDecimal multiplicator = vatPercent.divide(BigDecimal.valueOf(100));
|
BigDecimal multiplicator = vatPercent.divide(BigDecimal.valueOf(100));
|
||||||
priceGross = currentItem.getPrice(); // see https://github.com/ZUGFeRD/mustangproject/issues/159
|
|
||||||
price = priceGross.subtract(allowance).add(charge);
|
|
||||||
|
|
||||||
BigDecimal quantity=BigDecimal.ZERO;
|
BigDecimal quantity=BigDecimal.ZERO;
|
||||||
if ((currentItem!=null)&&(currentItem.getQuantity()!=null)) {
|
if ((currentItem!=null)&&(currentItem.getQuantity()!=null)) {
|
||||||
quantity=currentItem.getQuantity();
|
quantity=currentItem.getQuantity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
price=currentItem.getPrice();
|
||||||
|
priceGross=price;
|
||||||
|
// price=price.subtract(itemAllowance).add(itemCharge);
|
||||||
|
// BigDecimal delta=charge.subtract(allowanceItemTotal).subtract(allowance);
|
||||||
|
// delta=delta.divide(currentItem.getQuantity(), 18, RoundingMode.HALF_UP);
|
||||||
|
|
||||||
|
BigDecimal delta=BigDecimal.ZERO;
|
||||||
|
if(currentItem.getProduct()!=null){
|
||||||
|
if (currentItem.getProduct().getAllowances()!=null) {
|
||||||
|
for (IZUGFeRDAllowanceCharge ccaf:currentItem.getProduct().getAllowances()) {
|
||||||
|
delta=delta.subtract(ccaf.getTotalAmount(currentItem));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (currentItem.getProduct().getCharges()!=null) {
|
||||||
|
for (IZUGFeRDAllowanceCharge ccaf : currentItem.getProduct().getCharges()) {
|
||||||
|
delta = delta.subtract(ccaf.getTotalAmount(currentItem));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
price=price.add(delta);
|
||||||
// Division/Zero occurred here.
|
// Division/Zero occurred here.
|
||||||
// Used the setScale only because that's also done in getBasisQuantity
|
// Used the setScale only because that's also done in getBasisQuantity
|
||||||
BigDecimal basisQuantity = currentItem.getBasisQuantity().compareTo(BigDecimal.ZERO) == 0
|
BigDecimal basisQuantity = currentItem.getBasisQuantity().compareTo(BigDecimal.ZERO) == 0
|
||||||
? BigDecimal.ONE.setScale(4)
|
? BigDecimal.ONE.setScale(4)
|
||||||
: currentItem.getBasisQuantity();
|
: currentItem.getBasisQuantity();
|
||||||
itemTotalNetAmount = quantity.multiply(price).divide(basisQuantity, 18, RoundingMode.HALF_UP)
|
itemTotalNetAmount = quantity.multiply(price).divide(basisQuantity, 18, RoundingMode.HALF_UP)
|
||||||
.subtract(allowanceItemTotal).setScale(2, RoundingMode.HALF_UP);
|
.add(lineCharge).subtract(lineAllowance).subtract(allowanceItemTotal).setScale(2, RoundingMode.HALF_UP);
|
||||||
itemTotalVATAmount = itemTotalNetAmount.multiply(multiplicator);
|
itemTotalVATAmount = itemTotalNetAmount.multiply(multiplicator);//.setScale(2, RoundingMode.HALF_UP);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BigDecimal getPrice() {
|
public BigDecimal getPrice() {
|
||||||
@@ -80,16 +118,27 @@ public class LineCalculator {
|
|||||||
return priceGross;
|
return priceGross;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAllowance(BigDecimal b) {
|
public void addLineAllowance(BigDecimal b) {
|
||||||
allowance = allowance.add(b);
|
lineAllowance = lineAllowance.add(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addCharge(BigDecimal b) {
|
public void addLineCharge(BigDecimal b) {
|
||||||
charge = charge.add(b);
|
lineCharge = lineCharge.add(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addItemAllowance(BigDecimal b) {
|
||||||
|
itemAllowance = itemAllowance.add(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addItemCharge(BigDecimal b) {
|
||||||
|
itemCharge = itemCharge.add(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAllowanceItemTotal(BigDecimal b) {
|
public void addAllowanceItemTotal(BigDecimal b) {
|
||||||
allowanceItemTotal = allowanceItemTotal.add(b);
|
allowanceItemTotal = allowanceItemTotal.add(b);
|
||||||
}
|
}
|
||||||
|
public void subtractAllowanceItemTotal(BigDecimal b) {
|
||||||
|
allowanceItemTotal = allowanceItemTotal.subtract(b);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ public class VATAmount {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public VATAmount add(VATAmount v) {
|
public VATAmount add(VATAmount v) {
|
||||||
return new VATAmount(basis.add(v.getBasis()), calculated.add(v.getCalculated()), this.categoryCode, this.dueDateTypeCode).setVatExemptionReasonText(v.getVatExemptionReasonText());
|
return new VATAmount(basis.add(v.getBasis()), calculated.add(v.getCalculated()), this.categoryCode, this.dueDateTypeCode).setVatExemptionReasonText(v.getVatExemptionReasonText() != null ? v.getVatExemptionReasonText(): this.vatExemptionReasonText);
|
||||||
}
|
}
|
||||||
|
|
||||||
public VATAmount subtract(VATAmount v) {
|
public VATAmount subtract(VATAmount v) {
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ import org.mustangproject.IncludedNote;
|
|||||||
import org.mustangproject.ReferencedDocument;
|
import org.mustangproject.ReferencedDocument;
|
||||||
import org.mustangproject.XMLTools;
|
import org.mustangproject.XMLTools;
|
||||||
import org.mustangproject.ZUGFeRD.model.DocumentCodeTypeConstants;
|
import org.mustangproject.ZUGFeRD.model.DocumentCodeTypeConstants;
|
||||||
|
import org.mustangproject.ZUGFeRD.model.TaxCategoryCodeTypeConstants;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@@ -320,11 +321,12 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String reason = "";
|
String reason = "";
|
||||||
if ((allowance.getReason() != null) && (profile == Profiles.getByName("Extended") || profile == Profiles.getByName("XRechnung"))) {
|
boolean isEN16931=(profile == Profiles.getByName("XRechnung")) || (profile == Profiles.getByName("EN16931"));
|
||||||
|
if ((allowance.getReason() != null) && (profile == Profiles.getByName("Extended") || isEN16931)) {
|
||||||
reason = "<ram:Reason>" + XMLTools.encodeXML(allowance.getReason()) + "</ram:Reason>";
|
reason = "<ram:Reason>" + XMLTools.encodeXML(allowance.getReason()) + "</ram:Reason>";
|
||||||
}
|
}
|
||||||
String reasonCode = "";
|
String reasonCode = "";
|
||||||
if ((allowance.getReasonCode() != null) && (profile == Profiles.getByName("XRechnung"))) {
|
if ((allowance.getReasonCode() != null) && (profile == Profiles.getByName("Extended") || isEN16931)) {
|
||||||
// only in XRechnung profile
|
// only in XRechnung profile
|
||||||
reasonCode = "<ram:ReasonCode>" + allowance.getReasonCode() + "</ram:ReasonCode>";
|
reasonCode = "<ram:ReasonCode>" + allowance.getReasonCode() + "</ram:ReasonCode>";
|
||||||
}
|
}
|
||||||
@@ -432,24 +434,29 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
|||||||
+ XMLTools.encodeXML(currentItem.getProduct().getBuyerAssignedID()) + "</ram:BuyerAssignedID>";
|
+ XMLTools.encodeXML(currentItem.getProduct().getBuyerAssignedID()) + "</ram:BuyerAssignedID>";
|
||||||
}
|
}
|
||||||
String allowanceChargeStr = "";
|
String allowanceChargeStr = "";
|
||||||
if (currentItem.getItemAllowances() != null && currentItem.getItemAllowances().length > 0) {
|
if (currentItem.getProduct().getAllowances() != null && currentItem.getProduct().getAllowances().length > 0) {
|
||||||
for (final IZUGFeRDAllowanceCharge allowance : currentItem.getItemAllowances()) {
|
for (final IZUGFeRDAllowanceCharge allowance : currentItem.getProduct().getAllowances()) {
|
||||||
allowanceChargeStr += getAllowanceChargeStr(allowance, currentItem);
|
allowanceChargeStr += getAllowanceChargeStr(allowance, currentItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (currentItem.getItemCharges() != null && currentItem.getItemCharges().length > 0) {
|
if (currentItem.getProduct().getCharges() != null && currentItem.getProduct().getCharges().length > 0) {
|
||||||
for (final IZUGFeRDAllowanceCharge charge : currentItem.getItemCharges()) {
|
for (final IZUGFeRDAllowanceCharge charge : currentItem.getProduct().getCharges()) {
|
||||||
allowanceChargeStr += getAllowanceChargeStr(charge, currentItem);
|
allowanceChargeStr += getAllowanceChargeStr(charge, currentItem);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String itemTotalAllowanceChargeStr = "";
|
String itemTotalAllowanceChargeStr = "";
|
||||||
if (currentItem.getItemTotalAllowances() != null && currentItem.getItemTotalAllowances().length > 0) {
|
if (currentItem.getAllowances() != null && currentItem.getAllowances().length > 0) {
|
||||||
for (final IZUGFeRDAllowanceCharge itemTotalAllowance : currentItem.getItemTotalAllowances()) {
|
for (final IZUGFeRDAllowanceCharge itemTotalAllowance : currentItem.getAllowances()) {
|
||||||
itemTotalAllowanceChargeStr += getItemTotalAllowanceChargeStr(itemTotalAllowance, currentItem);
|
itemTotalAllowanceChargeStr += getItemTotalAllowanceChargeStr(itemTotalAllowance, currentItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (currentItem.getCharges() != null && currentItem.getCharges().length > 0) {
|
||||||
|
for (final IZUGFeRDAllowanceCharge itemTotalCharges : currentItem.getCharges()) {
|
||||||
|
itemTotalAllowanceChargeStr += getItemTotalAllowanceChargeStr(itemTotalCharges, currentItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
xml += "<ram:Name>" + XMLTools.encodeXML(currentItem.getProduct().getName()) + "</ram:Name>";
|
xml += "<ram:Name>" + XMLTools.encodeXML(currentItem.getProduct().getName()) + "</ram:Name>";
|
||||||
if (currentItem.getProduct().getDescription() != null && currentItem.getProduct().getDescription().length() > 0) {
|
if (currentItem.getProduct().getDescription() != null && currentItem.getProduct().getDescription().length() > 0) {
|
||||||
@@ -531,15 +538,16 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
|||||||
+ "<ram:SpecifiedLineTradeSettlement>"
|
+ "<ram:SpecifiedLineTradeSettlement>"
|
||||||
+ "<ram:ApplicableTradeTax>"
|
+ "<ram:ApplicableTradeTax>"
|
||||||
+ "<ram:TypeCode>VAT</ram:TypeCode>";
|
+ "<ram:TypeCode>VAT</ram:TypeCode>";
|
||||||
|
|
||||||
if (currentItem.getProduct().getTaxExemptionReason() != null) {
|
if (currentItem.getProduct().getTaxExemptionReason() != null) {
|
||||||
xml += "<ram:ExemptionReason>" + XMLTools.encodeXML(currentItem.getProduct().getTaxExemptionReason()) + "</ram:ExemptionReason>";
|
xml += "<ram:ExemptionReason>" + XMLTools.encodeXML(currentItem.getProduct().getTaxExemptionReason()) + "</ram:ExemptionReason>";
|
||||||
}
|
}
|
||||||
|
xml += "<ram:CategoryCode>" + currentItem.getProduct().getTaxCategoryCode() + "</ram:CategoryCode>";
|
||||||
|
if (!currentItem.getProduct().getTaxCategoryCode().equals(TaxCategoryCodeTypeConstants.UNTAXEDSERVICE)) {
|
||||||
|
xml += "<ram:RateApplicablePercent>"
|
||||||
|
+ vatFormat(currentItem.getProduct().getVATPercent()) + "</ram:RateApplicablePercent>";
|
||||||
|
}
|
||||||
|
xml += "</ram:ApplicableTradeTax>";
|
||||||
|
|
||||||
xml += "<ram:CategoryCode>" + currentItem.getProduct().getTaxCategoryCode() + "</ram:CategoryCode>"
|
|
||||||
+ "<ram:RateApplicablePercent>"
|
|
||||||
+ vatFormat(currentItem.getProduct().getVATPercent()) + "</ram:RateApplicablePercent>"
|
|
||||||
+ "</ram:ApplicableTradeTax>";
|
|
||||||
if ((currentItem.getDetailedDeliveryPeriodFrom() != null) || (currentItem.getDetailedDeliveryPeriodTo() != null)) {
|
if ((currentItem.getDetailedDeliveryPeriodFrom() != null) || (currentItem.getDetailedDeliveryPeriodTo() != null)) {
|
||||||
xml += "<ram:BillingSpecifiedPeriod>";
|
xml += "<ram:BillingSpecifiedPeriod>";
|
||||||
if (currentItem.getDetailedDeliveryPeriodFrom() != null) {
|
if (currentItem.getDetailedDeliveryPeriodFrom() != null) {
|
||||||
@@ -551,7 +559,10 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
|||||||
xml += "</ram:BillingSpecifiedPeriod>";
|
xml += "</ram:BillingSpecifiedPeriod>";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// item charges/allowances
|
||||||
|
if (!itemTotalAllowanceChargeStr.isEmpty()) {
|
||||||
xml += itemTotalAllowanceChargeStr ;
|
xml += itemTotalAllowanceChargeStr ;
|
||||||
|
}
|
||||||
|
|
||||||
xml += "<ram:SpecifiedTradeSettlementLineMonetarySummation>"
|
xml += "<ram:SpecifiedTradeSettlementLineMonetarySummation>"
|
||||||
+ "<ram:LineTotalAmount>" + currencyFormat(lc.getItemTotalNetAmount())
|
+ "<ram:LineTotalAmount>" + currencyFormat(lc.getItemTotalNetAmount())
|
||||||
@@ -725,9 +736,12 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
|||||||
+ exemptionReasonTextXML
|
+ exemptionReasonTextXML
|
||||||
+ "<ram:BasisAmount>" + currencyFormat(amount.getBasis()) + "</ram:BasisAmount>" // currencyID=\"EUR\"
|
+ "<ram:BasisAmount>" + currencyFormat(amount.getBasis()) + "</ram:BasisAmount>" // currencyID=\"EUR\"
|
||||||
+ "<ram:CategoryCode>" + amountCategoryCode + "</ram:CategoryCode>"
|
+ "<ram:CategoryCode>" + amountCategoryCode + "</ram:CategoryCode>"
|
||||||
+ (amountDueDateTypeCode != null ? "<ram:DueDateTypeCode>" + amountDueDateTypeCode + "</ram:DueDateTypeCode>" : "")
|
+ (amountDueDateTypeCode != null ? "<ram:DueDateTypeCode>" + amountDueDateTypeCode + "</ram:DueDateTypeCode>" : "");
|
||||||
+ "<ram:RateApplicablePercent>"
|
if (!amountCategoryCode.equals(TaxCategoryCodeTypeConstants.UNTAXEDSERVICE)) {
|
||||||
+ vatFormat(amount.getApplicablePercent()) + "</ram:RateApplicablePercent></ram:ApplicableTradeTax>";
|
xml += "<ram:RateApplicablePercent>"
|
||||||
|
+ vatFormat(amount.getApplicablePercent()) + "</ram:RateApplicablePercent>";
|
||||||
|
}
|
||||||
|
xml += "</ram:ApplicableTradeTax>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -759,7 +773,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
|||||||
xml += "<ram:CategoryTradeTax>" +
|
xml += "<ram:CategoryTradeTax>" +
|
||||||
"<ram:TypeCode>VAT</ram:TypeCode>" +
|
"<ram:TypeCode>VAT</ram:TypeCode>" +
|
||||||
"<ram:CategoryCode>" + charge.getCategoryCode() + "</ram:CategoryCode>";
|
"<ram:CategoryCode>" + charge.getCategoryCode() + "</ram:CategoryCode>";
|
||||||
if (charge.getTaxPercent() != null) {
|
if (charge.getTaxPercent() != null && !charge.getCategoryCode().equals(TaxCategoryCodeTypeConstants.UNTAXEDSERVICE)) {
|
||||||
xml += "<ram:RateApplicablePercent>" + vatFormat(charge.getTaxPercent()) + "</ram:RateApplicablePercent>";
|
xml += "<ram:RateApplicablePercent>" + vatFormat(charge.getTaxPercent()) + "</ram:RateApplicablePercent>";
|
||||||
}
|
}
|
||||||
xml += "</ram:CategoryTradeTax>" +
|
xml += "</ram:CategoryTradeTax>" +
|
||||||
@@ -874,7 +888,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
|
|||||||
final String chargesTotalLine = "<ram:ChargeTotalAmount>" + currencyFormat(calc.getChargesForPercent(null)) + "</ram:ChargeTotalAmount>";
|
final String chargesTotalLine = "<ram:ChargeTotalAmount>" + currencyFormat(calc.getChargesForPercent(null)) + "</ram:ChargeTotalAmount>";
|
||||||
|
|
||||||
xml += "<ram:SpecifiedTradeSettlementHeaderMonetarySummation>";
|
xml += "<ram:SpecifiedTradeSettlementHeaderMonetarySummation>";
|
||||||
if ((getProfile() != Profiles.getByName("Minimum")) && (getProfile() != Profiles.getByName("BASICWL"))) {
|
if ((getProfile() != Profiles.getByName("Minimum"))) {
|
||||||
xml += "<ram:LineTotalAmount>" + currencyFormat(calc.getTotal()) + "</ram:LineTotalAmount>";
|
xml += "<ram:LineTotalAmount>" + currencyFormat(calc.getTotal()) + "</ram:LineTotalAmount>";
|
||||||
xml += chargesTotalLine
|
xml += chargesTotalLine
|
||||||
+ allowanceTotalLine;
|
+ allowanceTotalLine;
|
||||||
|
|||||||
@@ -383,29 +383,7 @@ public class ZUGFeRDInvoiceImporter {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
String street, name, additionalStreet, city, postal, countrySubentity, line, country = null;
|
String street, name, additionalStreet, city, postal, countrySubentity, line, country = null;
|
||||||
/*
|
|
||||||
String idx = extractString("//*[local-name()=\"DeliveryLocation\"]/*[local-name() = \"ID\"]");
|
|
||||||
street = extractString("//*[local-name()=\"DeliveryLocation\"]/*[local-name()=\"Address\"]/*[local-name()=\"StreetName\"]");
|
|
||||||
additionalStreet = extractString("//*[local-name()=\"DeliveryLocation\"]/*[local-name() = \"Address\"]/*[local-name() = \"AdditionalStreetName\"]");
|
|
||||||
city = extractString("//*[local-name()=\"DeliveryLocation\"]/*[local-name() = \"Address\"]/*[local-name() = \"CityName\"]");
|
|
||||||
postal = extractString("//*[local-name()=\"DeliveryLocation\"]/*[local-name() = \"Address\"]/*[local-name() = \"PostalZone\"]");
|
|
||||||
countrySubentity = extractString("//*[local-name()=\"DeliveryLocation\"]/*[local-name() = \"Address\"]/*[local-name() = \"CountrySubentity\"]");
|
|
||||||
line = extractString("//*[local-name()=\"DeliveryLocation\"]/*[local-name() = \"Address\"]//*[local-name() = \"AddressLine\"]/*[local-name() = \"Line\"]");
|
|
||||||
country = extractString("//*[local-name()=\"DeliveryLocation\"]/*[local-name() = \"Address\"]//*[local-name() = \"Country\"]/*[local-name() = \"IdentificationCode\"]");
|
|
||||||
name = extractString("//*[local-name()=\"DeliveryLocation\"]/*[local-name() = \"DeliveryParty\"]//*[local-name() = \"PartyName\"]/*[local-name() = \"Name\"]");
|
|
||||||
*/
|
|
||||||
zpp.setDeliveryAddress(delivery);
|
zpp.setDeliveryAddress(delivery);
|
||||||
/*
|
|
||||||
zpp.setDeliveryAddress(new TradeParty()
|
|
||||||
.setStreet(street)
|
|
||||||
.setAdditionalAddress(additionalStreet)
|
|
||||||
.setLocation(city)
|
|
||||||
.setZIP(postal)
|
|
||||||
.setAdditionalAddressExtension(line)
|
|
||||||
.setCountry(country)
|
|
||||||
.setName(name)
|
|
||||||
);
|
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -420,14 +398,6 @@ public class ZUGFeRDInvoiceImporter {
|
|||||||
XPathExpression shipPayee = xpath.compile("//*[local-name()=\"PayeeParty\"]/*");
|
XPathExpression shipPayee = xpath.compile("//*[local-name()=\"PayeeParty\"]/*");
|
||||||
NodeList ublPayeeNodes = (NodeList) shipPayee.evaluate(getDocument(), XPathConstants.NODESET);
|
NodeList ublPayeeNodes = (NodeList) shipPayee.evaluate(getDocument(), XPathConstants.NODESET);
|
||||||
|
|
||||||
// if(ublPayeeNodes != null) {
|
|
||||||
// TradeParty payee = new TradeParty();
|
|
||||||
// NodeMap nodeMap = new NodeMap(ublPayeeNodes).getAsNodeMap("PayeeParty").get();
|
|
||||||
// nodeMap.getNode("ID").ifPresent(s -> {
|
|
||||||
// SchemedID sID = new SchemedID().setScheme(s.getAttributes().getNamedItem("schemeID").getTextContent()).setId(s.getTextContent());
|
|
||||||
// payee.addGlobalID(sID);
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
//NodeList UBLpayeeNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
|
//NodeList UBLpayeeNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
|
||||||
if (ublPayeeNodes.getLength() > 0) {
|
if (ublPayeeNodes.getLength() > 0) {
|
||||||
zpp.setPayee(new TradeParty(ublPayeeNodes));
|
zpp.setPayee(new TradeParty(ublPayeeNodes));
|
||||||
@@ -598,6 +568,15 @@ public class ZUGFeRDInvoiceImporter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String creditorReferenceID = extractString("//*[local-name()=\"ApplicableHeaderTradeSettlement\"]/*[local-name()=\"CreditorReferenceID\"]").trim();//BT-90
|
||||||
|
if ((creditorReferenceID == null)||(creditorReferenceID.length()==0)) {
|
||||||
|
//maybe it's there in UBL?
|
||||||
|
creditorReferenceID = extractString("//*[local-name()=\"AccountingSupplierParty\"]/*[local-name()=\"Party\"]/*[local-name()=\"PartyIdentification\"]/*[local-name()=\"ID\"]").trim();
|
||||||
|
}
|
||||||
|
if ((creditorReferenceID != null)&&(creditorReferenceID.length()>0)) {
|
||||||
|
zpp.setCreditorReferenceID(creditorReferenceID);
|
||||||
|
}
|
||||||
|
|
||||||
xpr = xpath.compile("//*[local-name()=\"ApplicableHeaderTradeDelivery\"]|//*[local-name()=\"Delivery\"]");
|
xpr = xpath.compile("//*[local-name()=\"ApplicableHeaderTradeDelivery\"]|//*[local-name()=\"Delivery\"]");
|
||||||
NodeList headerTradeDeliveryNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
|
NodeList headerTradeDeliveryNodes = (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET);
|
||||||
|
|
||||||
@@ -836,9 +815,6 @@ public class ZUGFeRDInvoiceImporter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if ((paymentMeansChilds.item(paymentTermChildIndex).getLocalName() != null) && (paymentTermChilds.item(paymentTermChildIndex).getLocalName().equals("DirectDebitMandateID"))) {
|
|
||||||
// directDebitMandateID = paymentTermChilds.item(paymentTermChildIndex).getTextContent();
|
|
||||||
// }
|
|
||||||
if ((paymentMeansChilds.item(meansChildIndex).getLocalName() != null)
|
if ((paymentMeansChilds.item(meansChildIndex).getLocalName() != null)
|
||||||
&& (paymentMeansChilds.item(meansChildIndex).getLocalName().equals("PaymentMandate"))) {
|
&& (paymentMeansChilds.item(meansChildIndex).getLocalName().equals("PaymentMandate"))) {
|
||||||
NodeList paymentMandateChilds = paymentMeansChilds.item(meansChildIndex).getChildNodes();
|
NodeList paymentMandateChilds = paymentMeansChilds.item(meansChildIndex).getChildNodes();
|
||||||
@@ -974,6 +950,7 @@ public class ZUGFeRDInvoiceImporter {
|
|||||||
NodeList chargeNodeChilds = chargeNodes.item(i).getChildNodes();
|
NodeList chargeNodeChilds = chargeNodes.item(i).getChildNodes();
|
||||||
boolean isCharge = true;
|
boolean isCharge = true;
|
||||||
String chargeAmount = null;
|
String chargeAmount = null;
|
||||||
|
String basisAmount = null;
|
||||||
String reason = null;
|
String reason = null;
|
||||||
String reasonCode = null;
|
String reasonCode = null;
|
||||||
String taxPercent = null;
|
String taxPercent = null;
|
||||||
@@ -1001,6 +978,8 @@ public class ZUGFeRDInvoiceImporter {
|
|||||||
|
|
||||||
} else if (chargeChildName.equals("ActualAmount") || chargeChildName.equals("Amount")) {
|
} else if (chargeChildName.equals("ActualAmount") || chargeChildName.equals("Amount")) {
|
||||||
chargeAmount = XMLTools.trimOrNull(chargeNodeChilds.item(chargeChildIndex));
|
chargeAmount = XMLTools.trimOrNull(chargeNodeChilds.item(chargeChildIndex));
|
||||||
|
} else if (chargeChildName.equals("BasisAmount")) {
|
||||||
|
basisAmount = XMLTools.trimOrNull(chargeNodeChilds.item(chargeChildIndex));
|
||||||
} else if (chargeChildName.equals("Reason") || chargeChildName.equals("AllowanceChargeReason")) {
|
} else if (chargeChildName.equals("Reason") || chargeChildName.equals("AllowanceChargeReason")) {
|
||||||
reason = XMLTools.trimOrNull(chargeNodeChilds.item(chargeChildIndex));
|
reason = XMLTools.trimOrNull(chargeNodeChilds.item(chargeChildIndex));
|
||||||
} else if (chargeChildName.equals("ReasonCode") || chargeChildName.equals("AllowanceChargeReasonCode")) {
|
} else if (chargeChildName.equals("ReasonCode") || chargeChildName.equals("AllowanceChargeReasonCode")) {
|
||||||
@@ -1028,6 +1007,9 @@ public class ZUGFeRDInvoiceImporter {
|
|||||||
if (taxPercent != null) {
|
if (taxPercent != null) {
|
||||||
c.setTaxPercent(new BigDecimal(taxPercent));
|
c.setTaxPercent(new BigDecimal(taxPercent));
|
||||||
}
|
}
|
||||||
|
if (basisAmount != null) {
|
||||||
|
c.setBasisAmount(new BigDecimal(basisAmount));
|
||||||
|
}
|
||||||
zpp.addCharge(c);
|
zpp.addCharge(c);
|
||||||
} else {
|
} else {
|
||||||
Allowance a = new Allowance(new BigDecimal(chargeAmount));
|
Allowance a = new Allowance(new BigDecimal(chargeAmount));
|
||||||
@@ -1040,6 +1022,9 @@ public class ZUGFeRDInvoiceImporter {
|
|||||||
if (taxPercent != null) {
|
if (taxPercent != null) {
|
||||||
a.setTaxPercent(new BigDecimal(taxPercent));
|
a.setTaxPercent(new BigDecimal(taxPercent));
|
||||||
}
|
}
|
||||||
|
if (basisAmount != null) {
|
||||||
|
a.setBasisAmount(new BigDecimal(basisAmount));
|
||||||
|
}
|
||||||
zpp.addAllowance(a);
|
zpp.addAllowance(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +1,23 @@
|
|||||||
/** **********************************************************************
|
/**
|
||||||
*
|
* *********************************************************************
|
||||||
|
* <p>
|
||||||
* Copyright 2018 Jochen Staerk
|
* Copyright 2018 Jochen Staerk
|
||||||
*
|
* <p>
|
||||||
* Use is subject to license terms.
|
* Use is subject to license terms.
|
||||||
*
|
* <p>
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
* use this file except in compliance with the License. You may obtain a copy
|
* use this file except in compliance with the License. You may obtain a copy
|
||||||
* of the License at http://www.apache.org/licenses/LICENSE-2.0.
|
* of the License at http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
*
|
* <p>
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
*
|
* <p>
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*
|
* <p>
|
||||||
*********************************************************************** */
|
* **********************************************************************
|
||||||
|
*/
|
||||||
package org.mustangproject.ZUGFeRD.model;
|
package org.mustangproject.ZUGFeRD.model;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -31,5 +33,5 @@ public class TaxCategoryCodeTypeConstants {
|
|||||||
public static final String INTRACOMMUNITY = "K";
|
public static final String INTRACOMMUNITY = "K";
|
||||||
public static final String FREEEXPORT = "G";
|
public static final String FREEEXPORT = "G";
|
||||||
|
|
||||||
public static Set<String> CATEGORY_CODES_WITH_EXEMPTION_REASON = Stream.of(INTRACOMMUNITY, REVERSECHARGE, TAXEXEMPT, FREEEXPORT).collect(Collectors.toSet());
|
public static Set<String> CATEGORY_CODES_WITH_EXEMPTION_REASON = Stream.of(INTRACOMMUNITY, REVERSECHARGE, TAXEXEMPT, FREEEXPORT, UNTAXEDSERVICE).collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -136,7 +136,7 @@
|
|||||||
<entry key="xr:Tender_or_lot_reference" id="BT-17">Vergabenummer</entry>
|
<entry key="xr:Tender_or_lot_reference" id="BT-17">Vergabenummer</entry>
|
||||||
<entry key="xr:Receiving_advice_reference" id="BT-15">Kennung der Empfangsbestätigung</entry>
|
<entry key="xr:Receiving_advice_reference" id="BT-15">Kennung der Empfangsbestätigung</entry>
|
||||||
<entry key="xr:Despatch_advice_reference" id="BT-16">Kennung der Versandanzeige</entry>
|
<entry key="xr:Despatch_advice_reference" id="BT-16">Kennung der Versandanzeige</entry>
|
||||||
<entry key="xr:Business_process_type_identifier" id="BT-23">Prozesskennung</entry>
|
<entry key="xr:Business_process_type" id="BT-23">Prozesskennung</entry>
|
||||||
<entry key="xr:Specification_identifier" id="BT-24">Spezifikationskennung</entry>
|
<entry key="xr:Specification_identifier" id="BT-24">Spezifikationskennung</entry>
|
||||||
<entry key="xr:Invoiced_object_identifier" id="BT-18">Objektkennung</entry>
|
<entry key="xr:Invoiced_object_identifier" id="BT-18">Objektkennung</entry>
|
||||||
<entry key="xr:Invoiced_object_identifier/@scheme_identifier" id="BT-18_scheme">Schema der Objektkennung</entry>
|
<entry key="xr:Invoiced_object_identifier/@scheme_identifier" id="BT-18_scheme">Schema der Objektkennung</entry>
|
||||||
|
|||||||
@@ -99,11 +99,11 @@
|
|||||||
<xsl:attribute name="xr:id" select="'BG-2'"/>
|
<xsl:attribute name="xr:id" select="'BG-2'"/>
|
||||||
<xsl:attribute name="xr:src" select="xr:src-path(.)"/>
|
<xsl:attribute name="xr:src" select="xr:src-path(.)"/>
|
||||||
<xsl:if test="./cbc:ProfileID">
|
<xsl:if test="./cbc:ProfileID">
|
||||||
<xr:Business_process_type_identifier>
|
<xr:Business_process_type>
|
||||||
<xsl:attribute name="xr:id" select="'BT-23'"/>
|
<xsl:attribute name="xr:id" select="'BT-23'"/>
|
||||||
<xsl:attribute name="xr:src" select="xr:src-path(.)"/>
|
<xsl:attribute name="xr:src" select="xr:src-path(.)"/>
|
||||||
<xsl:value-of select="./cbc:ProfileID"/>
|
<xsl:value-of select="./cbc:ProfileID"/>
|
||||||
</xr:Business_process_type_identifier>
|
</xr:Business_process_type>
|
||||||
</xsl:if>
|
</xsl:if>
|
||||||
<xr:Specification_identifier>
|
<xr:Specification_identifier>
|
||||||
<xsl:attribute name="xr:id" select="'BT-24'"/>
|
<xsl:attribute name="xr:id" select="'BT-24'"/>
|
||||||
|
|||||||
@@ -98,11 +98,11 @@
|
|||||||
<xsl:attribute name="xr:id" select="'BG-2'"/>
|
<xsl:attribute name="xr:id" select="'BG-2'"/>
|
||||||
<xsl:attribute name="xr:src" select="xr:src-path(.)"/>
|
<xsl:attribute name="xr:src" select="xr:src-path(.)"/>
|
||||||
<xsl:if test="./cbc:ProfileID">
|
<xsl:if test="./cbc:ProfileID">
|
||||||
<xr:Business_process_type_identifier>
|
<xr:Business_process_type>
|
||||||
<xsl:attribute name="xr:id" select="'BT-23'"/>
|
<xsl:attribute name="xr:id" select="'BT-23'"/>
|
||||||
<xsl:attribute name="xr:src" select="xr:src-path(.)"/>
|
<xsl:attribute name="xr:src" select="xr:src-path(.)"/>
|
||||||
<xsl:value-of select="./cbc:ProfileID"/>
|
<xsl:value-of select="./cbc:ProfileID"/>
|
||||||
</xr:Business_process_type_identifier>
|
</xr:Business_process_type>
|
||||||
</xsl:if>
|
</xsl:if>
|
||||||
<xr:Specification_identifier>
|
<xr:Specification_identifier>
|
||||||
<xsl:attribute name="xr:id" select="'BT-24'"/>
|
<xsl:attribute name="xr:id" select="'BT-24'"/>
|
||||||
|
|||||||
@@ -818,7 +818,6 @@
|
|||||||
<xsl:apply-templates mode="list-entry" select="xr:Despatch_advice_reference"/>
|
<xsl:apply-templates mode="list-entry" select="xr:Despatch_advice_reference"/>
|
||||||
<xsl:apply-templates mode="list-entry" select="xr:PROCESS_CONTROL/xr:Business_process_type"/>
|
<xsl:apply-templates mode="list-entry" select="xr:PROCESS_CONTROL/xr:Business_process_type"/>
|
||||||
<xsl:apply-templates mode="list-entry" select="xr:PROCESS_CONTROL/xr:Specification_identifier"/>
|
<xsl:apply-templates mode="list-entry" select="xr:PROCESS_CONTROL/xr:Specification_identifier"/>
|
||||||
<xsl:apply-templates mode="list-entry" select="xr:PROCESS_CONTROL/xr:Business_process_type_identifier"/>
|
|
||||||
<xsl:apply-templates mode="list-entry" select="xr:Invoiced_object_identifier"/>
|
<xsl:apply-templates mode="list-entry" select="xr:Invoiced_object_identifier"/>
|
||||||
<xsl:apply-templates mode="list-entry" select="xr:Invoiced_object_identifier/@scheme_identifier">
|
<xsl:apply-templates mode="list-entry" select="xr:Invoiced_object_identifier/@scheme_identifier">
|
||||||
<xsl:with-param name="field-mapping-identifier" select="'xr:Invoiced_object_identifier/@scheme_identifier'"/>
|
<xsl:with-param name="field-mapping-identifier" select="'xr:Invoiced_object_identifier/@scheme_identifier'"/>
|
||||||
|
|||||||
@@ -1797,7 +1797,7 @@ function downloadData (element_id) {
|
|||||||
<div class="boxtabelle boxinhalt noPaddingTop borderSpacing">
|
<div class="boxtabelle boxinhalt noPaddingTop borderSpacing">
|
||||||
<div class="boxzeile">
|
<div class="boxzeile">
|
||||||
<div class="boxdaten legende "><xsl:value-of select="$i18n.bt147"/>:</div>
|
<div class="boxdaten legende "><xsl:value-of select="$i18n.bt147"/>:</div>
|
||||||
<div id="BT-147" title="BT-147" class="boxdaten wert"><xsl:value-of select="format-number(xr:PRICE_DETAILS/xr:Item_price_discount,'###.##0,00','decimal')"/></div>
|
<div id="BT-147" title="BT-147" class="boxdaten wert"><xsl:value-of select="format-number(sum(xr:PRICE_DETAILS/xr:Item_price_discount),'###.##0,00','decimal')"/></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="boxzeile">
|
<div class="boxzeile">
|
||||||
<div class="boxdaten legende "><xsl:value-of select="$i18n.bt148"/>:</div>
|
<div class="boxdaten legende "><xsl:value-of select="$i18n.bt148"/>:</div>
|
||||||
|
|||||||
@@ -54,9 +54,9 @@ public class CalculationTest extends ResourceCase {
|
|||||||
|
|
||||||
final LineCalculator calculator = new LineCalculator(currentItem);
|
final LineCalculator calculator = new LineCalculator(currentItem);
|
||||||
|
|
||||||
assertEquals(valueOf(133.857).stripTrailingZeros(), calculator.getPrice().stripTrailingZeros());
|
assertEquals(valueOf(148.73).stripTrailingZeros(), calculator.getPrice().stripTrailingZeros());
|
||||||
assertEquals(valueOf(1606.28).stripTrailingZeros(), calculator.getItemTotalNetAmount().stripTrailingZeros());
|
assertEquals(valueOf(1769.89).stripTrailingZeros(), calculator.getItemTotalNetAmount().stripTrailingZeros());
|
||||||
assertEquals(valueOf(257.0048).stripTrailingZeros(), calculator.getItemTotalVATAmount().stripTrailingZeros());
|
assertEquals(valueOf(283.1824).stripTrailingZeros(), calculator.getItemTotalVATAmount().stripTrailingZeros());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -74,17 +74,20 @@ public class CalculationTest extends ResourceCase {
|
|||||||
|
|
||||||
final LineCalculator calculator = new LineCalculator(currentItem);
|
final LineCalculator calculator = new LineCalculator(currentItem);
|
||||||
|
|
||||||
assertEquals(valueOf(163.603).stripTrailingZeros(), calculator.getPrice().stripTrailingZeros());
|
assertEquals(valueOf(148.73).stripTrailingZeros(), calculator.getPrice().stripTrailingZeros());
|
||||||
assertEquals(valueOf(1963.24).stripTrailingZeros(), calculator.getItemTotalNetAmount().stripTrailingZeros());
|
assertEquals(valueOf(1799.63).stripTrailingZeros(), calculator.getItemTotalNetAmount().stripTrailingZeros());
|
||||||
assertEquals(valueOf(314.1184).stripTrailingZeros(), calculator.getItemTotalVATAmount().stripTrailingZeros());
|
assertEquals(valueOf(287.9408).stripTrailingZeros(), calculator.getItemTotalVATAmount().stripTrailingZeros());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLineCalculatorForeignCurrencyExample() {
|
public void testLineCalculatorForeignCurrencyExample() {
|
||||||
|
/*** xml of official fx sample with allowances and charges
|
||||||
/*
|
* 10x100 with 10% and 50€ item discount =850€
|
||||||
|
* +8,75 charges on document level=858,75, +19%VAT=1021,91
|
||||||
|
* prepaid 500->due payable=521,91
|
||||||
|
*/
|
||||||
File inputCII = getResourceAsFile("Extended_fremdwaehrung.xml");
|
File inputCII = getResourceAsFile("Extended_fremdwaehrung.xml");
|
||||||
inputCII=new File("C:\\Users\\jstaerk\\workspace\\XMLExamples\\zfdiverses\\20250407\\fremdwaehrung.xml");
|
|
||||||
ZUGFeRDInvoiceImporter zii=new ZUGFeRDInvoiceImporter();
|
ZUGFeRDInvoiceImporter zii=new ZUGFeRDInvoiceImporter();
|
||||||
Invoice invoice=null;
|
Invoice invoice=null;
|
||||||
zii.doIgnoreCalculationErrors();
|
zii.doIgnoreCalculationErrors();
|
||||||
@@ -104,9 +107,9 @@ inputCII=new File("C:\\Users\\jstaerk\\workspace\\XMLExamples\\zfdiverses\\20250
|
|||||||
|
|
||||||
final TransactionCalculator calculator = new TransactionCalculator(invoice);
|
final TransactionCalculator calculator = new TransactionCalculator(invoice);
|
||||||
|
|
||||||
assertEquals(valueOf(521.91).stripTrailingZeros(), calculator.getGrandTotal().stripTrailingZeros());
|
assertEquals(valueOf(521.91).stripTrailingZeros(), calculator.getDuePayable().stripTrailingZeros());
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -221,9 +224,94 @@ inputCII=new File("C:\\Users\\jstaerk\\workspace\\XMLExamples\\zfdiverses\\20250
|
|||||||
invoice.addAllowance(new Allowance().setPercent(total_discount_percent).setTaxPercent(sales_tax_percent1).setReasonCode("95").setReason("Rabatte"));
|
invoice.addAllowance(new Allowance().setPercent(total_discount_percent).setTaxPercent(sales_tax_percent1).setReasonCode("95").setReason("Rabatte"));
|
||||||
}
|
}
|
||||||
TransactionCalculator calculator = new TransactionCalculator(invoice);
|
TransactionCalculator calculator = new TransactionCalculator(invoice);
|
||||||
assertEquals(valueOf(101.86).stripTrailingZeros(), calculator.getGrandTotal().stripTrailingZeros());
|
assertEquals(valueOf(307.18).stripTrailingZeros(), calculator.getGrandTotal().stripTrailingZeros());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testSimpleItemPercentAllowance() {
|
||||||
|
/***
|
||||||
|
* a product with net 1.10 and qty 5 and relative item allowance of 10% should return 5 as line and grand total
|
||||||
|
*/
|
||||||
|
SimpleDateFormat sqlDate = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
|
|
||||||
|
Invoice invoice = new Invoice();
|
||||||
|
invoice.setDocumentName("Rechnung");
|
||||||
|
invoice.setNumber("777777");
|
||||||
|
try {
|
||||||
|
invoice.setIssueDate(sqlDate.parse("2020-12-31"));
|
||||||
|
invoice.setDetailedDeliveryPeriod(sqlDate.parse("2020-12-01 - 2020-12-31".split(" - ")[0]), sqlDate.parse("2020-12-01 - 2020-12-31".split(" - ")[1]));
|
||||||
|
invoice.setDeliveryDate(sqlDate.parse("2020-12-31"));
|
||||||
|
invoice.setDueDate(sqlDate.parse("2021-01-15"));
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.error("Failed to set dates", e);
|
||||||
|
|
||||||
|
}
|
||||||
|
TradeParty sender = new TradeParty("Maier GmbH", "Musterweg 5", "11111", "Testung", "DE");
|
||||||
|
sender.addVATID("DE2222222222");
|
||||||
|
invoice.setSender(sender);
|
||||||
|
|
||||||
|
/* trade party (recipient) */
|
||||||
|
TradeParty recipient = new TradeParty("Teston GmbH" + " " + "Zentrale" + " " + "", "Testweg 5", "11111", "Testung", "DE");
|
||||||
|
recipient.setID("111111");
|
||||||
|
recipient.addVATID("DE111111111");
|
||||||
|
invoice.setRecipient(recipient);
|
||||||
|
|
||||||
|
/* item */
|
||||||
|
Product product;
|
||||||
|
Item item;
|
||||||
|
|
||||||
|
product = new Product("AAA", "", "H84", BigDecimal.ZERO);
|
||||||
|
item = new Item(product, new BigDecimal("1.10"), new BigDecimal(5.00));
|
||||||
|
|
||||||
|
item.addAllowance(new Allowance().setPercent(new BigDecimal(10)).setTaxPercent(BigDecimal.ZERO));
|
||||||
|
invoice.addItem(item);
|
||||||
|
|
||||||
|
TransactionCalculator calculator = new TransactionCalculator(invoice);
|
||||||
|
assertEquals(new BigDecimal(5), calculator.getGrandTotal().stripTrailingZeros());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testSimpleItemTotalAllowance() {
|
||||||
|
/***
|
||||||
|
* a product with net 1 and qty 5 and absolute _item_ allowance of 1 should return 4 as line total, and grand total
|
||||||
|
*/
|
||||||
|
SimpleDateFormat sqlDate = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
|
|
||||||
|
Invoice invoice = new Invoice();
|
||||||
|
invoice.setDocumentName("Rechnung");
|
||||||
|
invoice.setNumber("777777");
|
||||||
|
try {
|
||||||
|
invoice.setIssueDate(sqlDate.parse("2020-12-31"));
|
||||||
|
invoice.setDetailedDeliveryPeriod(sqlDate.parse("2020-12-01 - 2020-12-31".split(" - ")[0]), sqlDate.parse("2020-12-01 - 2020-12-31".split(" - ")[1]));
|
||||||
|
invoice.setDeliveryDate(sqlDate.parse("2020-12-31"));
|
||||||
|
invoice.setDueDate(sqlDate.parse("2021-01-15"));
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.error("Failed to set dates", e);
|
||||||
|
|
||||||
|
}
|
||||||
|
TradeParty sender = new TradeParty("Maier GmbH", "Musterweg 5", "11111", "Testung", "DE");
|
||||||
|
sender.addVATID("DE2222222222");
|
||||||
|
invoice.setSender(sender);
|
||||||
|
|
||||||
|
/* trade party (recipient) */
|
||||||
|
TradeParty recipient = new TradeParty("Teston GmbH" + " " + "Zentrale" + " " + "", "Testweg 5", "11111", "Testung", "DE");
|
||||||
|
recipient.setID("111111");
|
||||||
|
recipient.addVATID("DE111111111");
|
||||||
|
invoice.setRecipient(recipient);
|
||||||
|
|
||||||
|
/* item */
|
||||||
|
Product product;
|
||||||
|
Item item;
|
||||||
|
|
||||||
|
product = new Product("AAA", "", "H84", BigDecimal.ZERO);
|
||||||
|
item = new Item(product, new BigDecimal("1.00"), new BigDecimal(5.00));
|
||||||
|
|
||||||
|
item.addAllowance(new Allowance(new BigDecimal(1)).setTaxPercent(BigDecimal.ZERO));
|
||||||
|
invoice.addItem(item);
|
||||||
|
|
||||||
|
TransactionCalculator calculator = new TransactionCalculator(invoice);
|
||||||
|
assertEquals(new BigDecimal(4), calculator.getGrandTotal().stripTrailingZeros());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LineCalculator should not throw an exception when calculating a non-terminating decimal expansion
|
* LineCalculator should not throw an exception when calculating a non-terminating decimal expansion
|
||||||
* */
|
* */
|
||||||
|
|||||||
@@ -395,7 +395,7 @@ public class DeSerializationTest extends ResourceCase {
|
|||||||
try {
|
try {
|
||||||
Invoice newInvoiceFromJSON = mapper.readValue(json, Invoice.class);
|
Invoice newInvoiceFromJSON = mapper.readValue(json, Invoice.class);
|
||||||
TransactionCalculator tc=new TransactionCalculator(newInvoiceFromJSON);
|
TransactionCalculator tc=new TransactionCalculator(newInvoiceFromJSON);
|
||||||
assertEquals(new BigDecimal("19.52"),tc.getGrandTotal());
|
assertEquals(new BigDecimal("18.92"),tc.getGrandTotal());
|
||||||
|
|
||||||
} catch (JsonProcessingException e) {
|
} catch (JsonProcessingException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ import java.io.IOException;
|
|||||||
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.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||||
public class VisualizationTest extends ResourceCase {
|
public class VisualizationTest extends ResourceCase {
|
||||||
@@ -94,6 +96,7 @@ public class VisualizationTest extends ResourceCase {
|
|||||||
.replace(" ", ""));
|
.replace(" ", ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void testPDFVisualizationCII() {
|
public void testPDFVisualizationCII() {
|
||||||
|
|
||||||
File CIIinputFile = getResourceAsFile("cii/01.01a-INVOICE.cii.xml");
|
File CIIinputFile = getResourceAsFile("cii/01.01a-INVOICE.cii.xml");
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import javax.xml.parsers.DocumentBuilderFactory;
|
|||||||
import javax.xml.parsers.ParserConfigurationException;
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
import javax.xml.xpath.XPath;
|
import javax.xml.xpath.XPath;
|
||||||
import javax.xml.xpath.XPathConstants;
|
import javax.xml.xpath.XPathConstants;
|
||||||
|
import org.mustangproject.ZUGFeRD.model.TaxCategoryCodeTypeConstants;
|
||||||
import javax.xml.xpath.XPathExpressionException;
|
import javax.xml.xpath.XPathExpressionException;
|
||||||
import javax.xml.xpath.XPathFactory;
|
import javax.xml.xpath.XPathFactory;
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
@@ -90,6 +91,7 @@ public class XRTest extends TestCase {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void testXREdgeExport() {
|
public void testXREdgeExport() {
|
||||||
|
|
||||||
// the writing part
|
// the writing part
|
||||||
@@ -289,6 +291,36 @@ public class XRTest extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void testApplicablePercentInUntaxedService() {
|
||||||
|
|
||||||
|
// the writing part
|
||||||
|
TradeParty recipient = new TradeParty("Franz Müller", null, "55232", "Entenhausen", "DE");
|
||||||
|
String orgname = "Test company";
|
||||||
|
String number = "123";
|
||||||
|
String amountStr = "1.00";
|
||||||
|
BigDecimal amount = new BigDecimal(amountStr);
|
||||||
|
var i = new Invoice().setDueDate(new java.util.Date()).setIssueDate(new java.util.Date()).setDeliveryDate(new java.util.Date())
|
||||||
|
.setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addTaxID("DE4711").addVATID("DE0815").setEmail("info@example.org").setContact(new org.mustangproject.Contact("Hans Test", "+49123456789", "test@example.org")).addBankDetails(new org.mustangproject.BankDetails("DE12500105170648489890", "COBADEFXXX")))
|
||||||
|
.setRecipient(recipient)
|
||||||
|
.setReferenceNumber("991-01484-64")//leitweg-id
|
||||||
|
// not using any VAT, this is also a test of zero-rated goods:
|
||||||
|
.setNumber(number).addItem(new org.mustangproject.Item(new org.mustangproject.Product("Testprodukt", "", "C62", java.math.BigDecimal.ZERO).setTaxCategoryCode(TaxCategoryCodeTypeConstants.UNTAXEDSERVICE).setTaxExemptionReason("Expemtion reason"), amount, new java.math.BigDecimal(1.0)));
|
||||||
|
|
||||||
|
ZUGFeRD2PullProvider zf2p = new ZUGFeRD2PullProvider();
|
||||||
|
zf2p.setProfile(Profiles.getByName("XRechnung"));
|
||||||
|
zf2p.generateXML(i);
|
||||||
|
String theXML = new String(zf2p.getXML(), StandardCharsets.UTF_8);
|
||||||
|
// Untaxed services don't have the field RateApplicablePercent, since it would be always 0. An error is thrown on validation, if 0 is set.
|
||||||
|
assertThat(theXML).valueByXPath("count(//*[local-name()='RateApplicablePercent'])")
|
||||||
|
.asInt()
|
||||||
|
.isEqualTo(0);
|
||||||
|
|
||||||
|
//Exemption reason needs to be set if TaxCategoryCode == "O", reason should be at the product and in the ApplicableTradeTax
|
||||||
|
assertThat(theXML).valueByXPath("count(//*[local-name()='ExemptionReason'])")
|
||||||
|
.asInt()
|
||||||
|
.isEqualTo(2);
|
||||||
|
}
|
||||||
|
|
||||||
private org.mustangproject.Invoice createInvoice(TradeParty recipient) {
|
private org.mustangproject.Invoice createInvoice(TradeParty recipient) {
|
||||||
String orgname = "Test company";
|
String orgname = "Test company";
|
||||||
String number = "123";
|
String number = "123";
|
||||||
|
|||||||
@@ -261,10 +261,10 @@ public class ZF2PushTest extends TestCase {
|
|||||||
.setContact(new Contact("contact testname", "123456", "contact.testemail@example.org").setFax("0911623562")))
|
.setContact(new Contact("contact testname", "123456", "contact.testemail@example.org").setFax("0911623562")))
|
||||||
.setNumber(number)
|
.setNumber(number)
|
||||||
.addCharge(new Charge(new BigDecimal(1)).setReasonCode("ABK").setReason("AReason").setTaxPercent(new BigDecimal(19)))
|
.addCharge(new Charge(new BigDecimal(1)).setReasonCode("ABK").setReason("AReason").setTaxPercent(new BigDecimal(19)))
|
||||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addAllowance(new Allowance(new BigDecimal("0.1"))))
|
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addAllowance(new Allowance(new BigDecimal("0.1")).setReasonCode("95")))
|
||||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addAllowance(new Allowance().setPercent(new BigDecimal(50))))
|
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addAllowance(new Allowance().setPercent(new BigDecimal(50)).setReason("In love with salesperson")))
|
||||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(2.0)).addCharge(new Charge(new BigDecimal(1)).setReasonCode("ABK").setReason("AnotherReason")))
|
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(2.0)).addCharge(new Charge(new BigDecimal(1)).setReasonCode("ABK").setReason("AnotherReason")))
|
||||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addCharge(new Charge(new BigDecimal(1))).addAllowance(new Allowance(new BigDecimal("1"))));
|
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), amount, new BigDecimal(1.0)).addCharge(new Charge(new BigDecimal(1)).setReasonCode("ABK").setReason("Yet another reason")).addAllowance(new Allowance(new BigDecimal("1")).setReason("Something completely strange")));
|
||||||
ze.setTransaction(i);
|
ze.setTransaction(i);
|
||||||
|
|
||||||
|
|
||||||
@@ -275,21 +275,20 @@ public class ZF2PushTest extends TestCase {
|
|||||||
fail("IOException should not be raised");
|
fail("IOException should not be raised");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
// now check the contents (like MustangReaderTest)
|
// now check the contents (like MustangReaderTest)
|
||||||
ZUGFeRDImporter zi = new ZUGFeRDImporter(TARGET_ITEMCHARGESALLOWANCESPDF);
|
ZUGFeRDImporter zi = new ZUGFeRDImporter(TARGET_ITEMCHARGESALLOWANCESPDF);
|
||||||
|
|
||||||
assertEquals("EUR", zi.getInvoiceCurrencyCode());
|
assertEquals("EUR", zi.getInvoiceCurrencyCode());
|
||||||
assertTrue(zi.getUTF8().contains("0911623562")); // fax number
|
assertTrue(zi.getUTF8().contains("0911623562")); // fax number
|
||||||
assertTrue(zi.getUTF8().contains("ABK"));
|
assertTrue(zi.getUTF8().contains("ABK"));
|
||||||
|
|
||||||
// Reading ZUGFeRD
|
// Reading ZUGFeRD
|
||||||
assertEquals("19.52", zi.getAmount());
|
assertEquals("18.92", zi.getAmount());
|
||||||
assertEquals(orgname, zi.getHolder());
|
assertEquals(orgname, zi.getHolder());
|
||||||
assertEquals(number, zi.getForeignReference());
|
assertEquals(number, zi.getForeignReference());
|
||||||
try {
|
|
||||||
assertEquals(zi.getVersion(), 2);
|
assertEquals(zi.getVersion(), 2);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
fail("Exception should not be raised");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -629,7 +628,7 @@ public class ZF2PushTest extends TestCase {
|
|||||||
.setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addTaxID("4711").addVATID("DE0815"))
|
.setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addTaxID("4711").addVATID("DE0815"))
|
||||||
.setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE"))
|
.setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE"))
|
||||||
.setNumber(number)
|
.setNumber(number)
|
||||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), new BigDecimal(500.0), qty).addAllowance(new Allowance(new BigDecimal(300)).setTaxPercent(new BigDecimal(19))))
|
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)).addAllowance(new Allowance(BigDecimal.ONE)), new BigDecimal(500.0), qty).addAllowance(new Allowance(new BigDecimal(300)).setTaxPercent(new BigDecimal(19))))
|
||||||
.addAllowance(new Allowance(new BigDecimal(600)).setTaxPercent(new BigDecimal(19)))
|
.addAllowance(new Allowance(new BigDecimal(600)).setTaxPercent(new BigDecimal(19)))
|
||||||
);
|
);
|
||||||
String theXML = new String(ze.getProvider().getXML());
|
String theXML = new String(ze.getProvider().getXML());
|
||||||
@@ -645,7 +644,7 @@ public class ZF2PushTest extends TestCase {
|
|||||||
assertEquals("EUR", zi.getInvoiceCurrencyCode());
|
assertEquals("EUR", zi.getInvoiceCurrencyCode());
|
||||||
|
|
||||||
// Reading ZUGFeRD
|
// Reading ZUGFeRD
|
||||||
assertEquals("4046.00", zi.getAmount());
|
assertEquals("10805.20", zi.getAmount());
|
||||||
assertEquals(orgname, zi.getHolder());
|
assertEquals(orgname, zi.getHolder());
|
||||||
assertEquals(number, zi.getForeignReference());
|
assertEquals(number, zi.getForeignReference());
|
||||||
try {
|
try {
|
||||||
@@ -675,8 +674,8 @@ public class ZF2PushTest extends TestCase {
|
|||||||
.setNumber(number)
|
.setNumber(number)
|
||||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, new BigDecimal(1.0)))
|
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, new BigDecimal(1.0)))
|
||||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, new BigDecimal(1.0)))
|
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, new BigDecimal(1.0)))
|
||||||
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, new BigDecimal(1.0)).addCharge(new Charge().setPercent(new BigDecimal(50)).setTaxPercent(new BigDecimal(19))))
|
.addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, new BigDecimal(1.0)).addCharge(new Charge().setPercent(new BigDecimal(50)).setTaxPercent(new BigDecimal(19)).setReasonCode("ABK")))
|
||||||
.addAllowance(new Allowance().setPercent(new BigDecimal(50)).setTaxPercent(new BigDecimal(19)))
|
.addAllowance(new Allowance().setPercent(new BigDecimal(50)).setTaxPercent(new BigDecimal(19)).setReason("Mengenrabatt"))
|
||||||
);
|
);
|
||||||
String theXML = new String(ze.getProvider().getXML());
|
String theXML = new String(ze.getProvider().getXML());
|
||||||
assertTrue(theXML.contains("<rsm:CrossIndustryInvoice"));
|
assertTrue(theXML.contains("<rsm:CrossIndustryInvoice"));
|
||||||
@@ -689,7 +688,7 @@ public class ZF2PushTest extends TestCase {
|
|||||||
ZUGFeRDImporter zi = new ZUGFeRDImporter(TARGET_RELATIVECHARGESALLOWANCESPDF);
|
ZUGFeRDImporter zi = new ZUGFeRDImporter(TARGET_RELATIVECHARGESALLOWANCESPDF);
|
||||||
|
|
||||||
assertEquals("CHF", zi.getInvoiceCurrencyCode());
|
assertEquals("CHF", zi.getInvoiceCurrencyCode());
|
||||||
assertEquals("6.25", zi.getAmount());
|
assertEquals("11.10", zi.getAmount());
|
||||||
assertEquals(orgname, zi.getHolder());
|
assertEquals(orgname, zi.getHolder());
|
||||||
assertEquals(number, zi.getForeignReference());
|
assertEquals(number, zi.getForeignReference());
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -34,12 +34,14 @@ import java.io.InputStream;
|
|||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
@@ -262,9 +264,27 @@ public class ZF2ZInvoiceImporterTest extends ResourceCase {
|
|||||||
}
|
}
|
||||||
assertFalse(hasExceptions);
|
assertFalse(hasExceptions);
|
||||||
TransactionCalculator tc = new TransactionCalculator(invoice);
|
TransactionCalculator tc = new TransactionCalculator(invoice);
|
||||||
assertEquals(new BigDecimal("19.52"), tc.getGrandTotal());
|
assertEquals(new BigDecimal("18.92"), tc.getGrandTotal());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testIBANImport() {
|
||||||
|
File CIIinputFile = getResourceAsFile("cii/lastschrift_iban_bug.xml");
|
||||||
|
try {
|
||||||
|
ZUGFeRDInvoiceImporter zii = new ZUGFeRDInvoiceImporter(new FileInputStream(CIIinputFile));
|
||||||
|
|
||||||
|
|
||||||
|
CalculatedInvoice invoice = new CalculatedInvoice();
|
||||||
|
zii.extractInto(invoice);
|
||||||
|
assertEquals("DE11111111111111111111", invoice.getCreditorReferenceID());
|
||||||
|
assertEquals("DE22222222222222222222", invoice.getSender().getBankDetails().stream().map(BankDetails::getIBAN).collect(Collectors.joining(",")));
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} catch (XPathExpressionException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} catch (ParseException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
public void testBasisQuantityImport() {
|
public void testBasisQuantityImport() {
|
||||||
|
|
||||||
ZUGFeRDInvoiceImporter zii = new ZUGFeRDInvoiceImporter("./target/testout-ZF2newEdge.pdf");
|
ZUGFeRDInvoiceImporter zii = new ZUGFeRDInvoiceImporter("./target/testout-ZF2newEdge.pdf");
|
||||||
|
|||||||
152
library/src/test/resources/cii/lastschrift_iban_bug.xml
Normal file
152
library/src/test/resources/cii/lastschrift_iban_bug.xml
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<rsm:CrossIndustryInvoice xmlns:rsm="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100" xmlns:a="urn:un:unece:uncefact:data:standard:QualifiedDataType:100" xmlns:qdt="urn:un:unece:uncefact:data:standard:QualifiedDataType:10" xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<rsm:ExchangedDocumentContext>
|
||||||
|
<ram:GuidelineSpecifiedDocumentContextParameter>
|
||||||
|
<ram:ID>urn:cen.eu:en16931:2017</ram:ID>
|
||||||
|
</ram:GuidelineSpecifiedDocumentContextParameter>
|
||||||
|
</rsm:ExchangedDocumentContext>
|
||||||
|
<rsm:ExchangedDocument>
|
||||||
|
<ram:ID>123456</ram:ID>
|
||||||
|
<ram:TypeCode>380</ram:TypeCode>
|
||||||
|
<ram:IssueDateTime>
|
||||||
|
<udt:DateTimeString format="102">20250426</udt:DateTimeString>
|
||||||
|
</ram:IssueDateTime>
|
||||||
|
<ram:IncludedNote>
|
||||||
|
<ram:Content>Jahresbeitrag</ram:Content>
|
||||||
|
</ram:IncludedNote>
|
||||||
|
</rsm:ExchangedDocument>
|
||||||
|
<rsm:SupplyChainTradeTransaction>
|
||||||
|
<ram:IncludedSupplyChainTradeLineItem>
|
||||||
|
<ram:AssociatedDocumentLineDocument>
|
||||||
|
<ram:LineID>1</ram:LineID>
|
||||||
|
</ram:AssociatedDocumentLineDocument>
|
||||||
|
<ram:SpecifiedTradeProduct>
|
||||||
|
<ram:Name>Product: Plus</ram:Name>
|
||||||
|
</ram:SpecifiedTradeProduct>
|
||||||
|
<ram:SpecifiedLineTradeAgreement>
|
||||||
|
<ram:NetPriceProductTradePrice>
|
||||||
|
<ram:ChargeAmount>239.00</ram:ChargeAmount>
|
||||||
|
</ram:NetPriceProductTradePrice>
|
||||||
|
</ram:SpecifiedLineTradeAgreement>
|
||||||
|
<ram:SpecifiedLineTradeDelivery>
|
||||||
|
<ram:BilledQuantity unitCode="H87">1.00</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>239.00</ram:LineTotalAmount>
|
||||||
|
</ram:SpecifiedTradeSettlementLineMonetarySummation>
|
||||||
|
</ram:SpecifiedLineTradeSettlement>
|
||||||
|
</ram:IncludedSupplyChainTradeLineItem>
|
||||||
|
<ram:IncludedSupplyChainTradeLineItem>
|
||||||
|
<ram:AssociatedDocumentLineDocument>
|
||||||
|
<ram:LineID>1</ram:LineID>
|
||||||
|
</ram:AssociatedDocumentLineDocument>
|
||||||
|
<ram:SpecifiedTradeProduct>
|
||||||
|
<ram:Name>Getting Started-Rabatt</ram:Name>
|
||||||
|
</ram:SpecifiedTradeProduct>
|
||||||
|
<ram:SpecifiedLineTradeAgreement>
|
||||||
|
<ram:NetPriceProductTradePrice>
|
||||||
|
<ram:ChargeAmount>120.00</ram:ChargeAmount>
|
||||||
|
</ram:NetPriceProductTradePrice>
|
||||||
|
</ram:SpecifiedLineTradeAgreement>
|
||||||
|
<ram:SpecifiedLineTradeDelivery>
|
||||||
|
<ram:BilledQuantity unitCode="H87">-1.00</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>-120.00</ram:LineTotalAmount>
|
||||||
|
</ram:SpecifiedTradeSettlementLineMonetarySummation>
|
||||||
|
</ram:SpecifiedLineTradeSettlement>
|
||||||
|
</ram:IncludedSupplyChainTradeLineItem>
|
||||||
|
<ram:ApplicableHeaderTradeAgreement>
|
||||||
|
<ram:BuyerReference>7777777</ram:BuyerReference>
|
||||||
|
<ram:SellerTradeParty>
|
||||||
|
<ram:Name>---</ram:Name>
|
||||||
|
<ram:DefinedTradeContact>
|
||||||
|
<ram:PersonName>---</ram:PersonName>
|
||||||
|
<ram:DepartmentName>Geschäftsführer</ram:DepartmentName>
|
||||||
|
<ram:TelephoneUniversalCommunication>
|
||||||
|
<ram:CompleteNumber>---</ram:CompleteNumber>
|
||||||
|
</ram:TelephoneUniversalCommunication>
|
||||||
|
<ram:EmailURIUniversalCommunication>
|
||||||
|
<ram:URIID>q@q.com</ram:URIID>
|
||||||
|
</ram:EmailURIUniversalCommunication>
|
||||||
|
</ram:DefinedTradeContact>
|
||||||
|
<ram:PostalTradeAddress>
|
||||||
|
<ram:PostcodeCode>12345</ram:PostcodeCode>
|
||||||
|
<ram:LineOne>Str. 11</ram:LineOne>
|
||||||
|
<ram:CityName>---</ram:CityName>
|
||||||
|
<ram:CountryID>DE</ram:CountryID>
|
||||||
|
</ram:PostalTradeAddress>
|
||||||
|
<ram:URIUniversalCommunication>
|
||||||
|
<ram:URIID schemeID="EM">a@a.com</ram:URIID>
|
||||||
|
</ram:URIUniversalCommunication>
|
||||||
|
<ram:SpecifiedTaxRegistration>
|
||||||
|
<ram:ID schemeID="VA">DE111111111</ram:ID>
|
||||||
|
</ram:SpecifiedTaxRegistration>
|
||||||
|
</ram:SellerTradeParty>
|
||||||
|
<ram:BuyerTradeParty>
|
||||||
|
<ram:Name>a & b GmbH</ram:Name>
|
||||||
|
<ram:PostalTradeAddress>
|
||||||
|
<ram:PostcodeCode>123456</ram:PostcodeCode>
|
||||||
|
<ram:LineOne>--</ram:LineOne>
|
||||||
|
<ram:LineTwo>Str. 17</ram:LineTwo>
|
||||||
|
<ram:CityName>--</ram:CityName>
|
||||||
|
<ram:CountryID>DE</ram:CountryID>
|
||||||
|
</ram:PostalTradeAddress>
|
||||||
|
</ram:BuyerTradeParty>
|
||||||
|
</ram:ApplicableHeaderTradeAgreement>
|
||||||
|
<ram:ApplicableHeaderTradeDelivery/>
|
||||||
|
<ram:ApplicableHeaderTradeSettlement>
|
||||||
|
<ram:CreditorReferenceID>DE11111111111111111111</ram:CreditorReferenceID>
|
||||||
|
<ram:InvoiceCurrencyCode>EUR</ram:InvoiceCurrencyCode>
|
||||||
|
<ram:SpecifiedTradeSettlementPaymentMeans>
|
||||||
|
<ram:TypeCode>59</ram:TypeCode>
|
||||||
|
<ram:PayerPartyDebtorFinancialAccount>
|
||||||
|
<ram:IBANID>DE22222222222222222222</ram:IBANID>
|
||||||
|
</ram:PayerPartyDebtorFinancialAccount>
|
||||||
|
</ram:SpecifiedTradeSettlementPaymentMeans>
|
||||||
|
<ram:ApplicableTradeTax>
|
||||||
|
<ram:CalculatedAmount>22.61</ram:CalculatedAmount>
|
||||||
|
<ram:TypeCode>VAT</ram:TypeCode>
|
||||||
|
<ram:BasisAmount>119.00</ram:BasisAmount>
|
||||||
|
<ram:CategoryCode>S</ram:CategoryCode>
|
||||||
|
<ram:RateApplicablePercent>19.00</ram:RateApplicablePercent>
|
||||||
|
</ram:ApplicableTradeTax>
|
||||||
|
<ram:BillingSpecifiedPeriod>
|
||||||
|
<ram:StartDateTime>
|
||||||
|
<udt:DateTimeString format="102">20250426</udt:DateTimeString>
|
||||||
|
</ram:StartDateTime>
|
||||||
|
<ram:EndDateTime>
|
||||||
|
<udt:DateTimeString format="102">20250525</udt:DateTimeString>
|
||||||
|
</ram:EndDateTime>
|
||||||
|
</ram:BillingSpecifiedPeriod>
|
||||||
|
<ram:SpecifiedTradePaymentTerms>
|
||||||
|
<ram:Description>Zahlbar sofort</ram:Description>
|
||||||
|
<ram:DueDateDateTime>
|
||||||
|
<udt:DateTimeString format="102">20250426</udt:DateTimeString>
|
||||||
|
</ram:DueDateDateTime>
|
||||||
|
</ram:SpecifiedTradePaymentTerms>
|
||||||
|
<ram:SpecifiedTradeSettlementHeaderMonetarySummation>
|
||||||
|
<ram:LineTotalAmount>119.00</ram:LineTotalAmount>
|
||||||
|
<ram:ChargeTotalAmount>0.00</ram:ChargeTotalAmount>
|
||||||
|
<ram:AllowanceTotalAmount>0.00</ram:AllowanceTotalAmount>
|
||||||
|
<ram:TaxBasisTotalAmount>119.00</ram:TaxBasisTotalAmount>
|
||||||
|
<ram:TaxTotalAmount currencyID="EUR">22.61</ram:TaxTotalAmount>
|
||||||
|
<ram:GrandTotalAmount>141.61</ram:GrandTotalAmount>
|
||||||
|
<ram:TotalPrepaidAmount>0.00</ram:TotalPrepaidAmount>
|
||||||
|
<ram:DuePayableAmount>141.61</ram:DuePayableAmount>
|
||||||
|
</ram:SpecifiedTradeSettlementHeaderMonetarySummation>
|
||||||
|
</ram:ApplicableHeaderTradeSettlement>
|
||||||
|
</rsm:SupplyChainTradeTransaction>
|
||||||
|
</rsm:CrossIndustryInvoice>
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1665,7 +1665,7 @@
|
|||||||
<div class="boxtabelle boxinhalt noPaddingTop borderSpacing">
|
<div class="boxtabelle boxinhalt noPaddingTop borderSpacing">
|
||||||
<div class="boxzeile">
|
<div class="boxzeile">
|
||||||
<div class="boxdaten legende ">Discount (net):</div>
|
<div class="boxdaten legende ">Discount (net):</div>
|
||||||
<div id="BT-147" title="BT-147" class="boxdaten wert"></div>
|
<div id="BT-147" title="BT-147" class="boxdaten wert">0,00</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="boxzeile">
|
<div class="boxzeile">
|
||||||
<div class="boxdaten legende ">Net list price:</div>
|
<div class="boxdaten legende ">Net list price:</div>
|
||||||
@@ -1977,7 +1977,7 @@
|
|||||||
<div class="boxtabelle boxinhalt noPaddingTop borderSpacing">
|
<div class="boxtabelle boxinhalt noPaddingTop borderSpacing">
|
||||||
<div class="boxzeile">
|
<div class="boxzeile">
|
||||||
<div class="boxdaten legende ">Discount (net):</div>
|
<div class="boxdaten legende ">Discount (net):</div>
|
||||||
<div id="BT-147" title="BT-147" class="boxdaten wert"></div>
|
<div id="BT-147" title="BT-147" class="boxdaten wert">0,00</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="boxzeile">
|
<div class="boxzeile">
|
||||||
<div class="boxdaten legende ">Net list price:</div>
|
<div class="boxdaten legende ">Net list price:</div>
|
||||||
@@ -2133,7 +2133,7 @@
|
|||||||
<div class="boxtabelle boxinhalt noPaddingTop borderSpacing">
|
<div class="boxtabelle boxinhalt noPaddingTop borderSpacing">
|
||||||
<div class="boxzeile">
|
<div class="boxzeile">
|
||||||
<div class="boxdaten legende ">Discount (net):</div>
|
<div class="boxdaten legende ">Discount (net):</div>
|
||||||
<div id="BT-147" title="BT-147" class="boxdaten wert"></div>
|
<div id="BT-147" title="BT-147" class="boxdaten wert">0,00</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="boxzeile">
|
<div class="boxzeile">
|
||||||
<div class="boxdaten legende ">Net list price:</div>
|
<div class="boxdaten legende ">Net list price:</div>
|
||||||
|
|||||||
@@ -1379,7 +1379,7 @@
|
|||||||
<div class="boxtabelle boxinhalt noPaddingTop borderSpacing">
|
<div class="boxtabelle boxinhalt noPaddingTop borderSpacing">
|
||||||
<div class="boxzeile">
|
<div class="boxzeile">
|
||||||
<div class="boxdaten legende ">Discount (net):</div>
|
<div class="boxdaten legende ">Discount (net):</div>
|
||||||
<div id="BT-147" title="BT-147" class="boxdaten wert"></div>
|
<div id="BT-147" title="BT-147" class="boxdaten wert">0,00</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="boxzeile">
|
<div class="boxzeile">
|
||||||
<div class="boxdaten legende ">Net list price:</div>
|
<div class="boxdaten legende ">Net list price:</div>
|
||||||
@@ -1535,7 +1535,7 @@
|
|||||||
<div class="boxtabelle boxinhalt noPaddingTop borderSpacing">
|
<div class="boxtabelle boxinhalt noPaddingTop borderSpacing">
|
||||||
<div class="boxzeile">
|
<div class="boxzeile">
|
||||||
<div class="boxdaten legende ">Discount (net):</div>
|
<div class="boxdaten legende ">Discount (net):</div>
|
||||||
<div id="BT-147" title="BT-147" class="boxdaten wert"></div>
|
<div id="BT-147" title="BT-147" class="boxdaten wert">0,00</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="boxzeile">
|
<div class="boxzeile">
|
||||||
<div class="boxdaten legende ">Net list price:</div>
|
<div class="boxdaten legende ">Net list price:</div>
|
||||||
@@ -1758,7 +1758,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="boxzeile">
|
<div class="boxzeile">
|
||||||
<div class="boxdaten legende">Process ID:</div>
|
<div class="boxdaten legende">Process ID:</div>
|
||||||
<div id="BT-23" title="BT-23" class="boxdaten wert"></div>
|
<div id="BT-23" title="BT-23" class="boxdaten wert">urn:fdc:peppol.eu:2017:poacc:billing:01:1.0</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="boxzeile">
|
<div class="boxzeile">
|
||||||
<div class="boxdaten legende">Specification ID:</div>
|
<div class="boxdaten legende">Specification ID:</div>
|
||||||
|
|||||||
@@ -1395,7 +1395,7 @@
|
|||||||
<div class="boxtabelle boxinhalt noPaddingTop borderSpacing">
|
<div class="boxtabelle boxinhalt noPaddingTop borderSpacing">
|
||||||
<div class="boxzeile">
|
<div class="boxzeile">
|
||||||
<div class="boxdaten legende ">Remise nette:</div>
|
<div class="boxdaten legende ">Remise nette:</div>
|
||||||
<div id="BT-147" title="BT-147" class="boxdaten wert"></div>
|
<div id="BT-147" title="BT-147" class="boxdaten wert">0,00</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="boxzeile">
|
<div class="boxzeile">
|
||||||
<div class="boxdaten legende ">Prix catalogue (net):</div>
|
<div class="boxdaten legende ">Prix catalogue (net):</div>
|
||||||
@@ -1551,7 +1551,7 @@
|
|||||||
<div class="boxtabelle boxinhalt noPaddingTop borderSpacing">
|
<div class="boxtabelle boxinhalt noPaddingTop borderSpacing">
|
||||||
<div class="boxzeile">
|
<div class="boxzeile">
|
||||||
<div class="boxdaten legende ">Remise nette:</div>
|
<div class="boxdaten legende ">Remise nette:</div>
|
||||||
<div id="BT-147" title="BT-147" class="boxdaten wert"></div>
|
<div id="BT-147" title="BT-147" class="boxdaten wert">0,00</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="boxzeile">
|
<div class="boxzeile">
|
||||||
<div class="boxdaten legende ">Prix catalogue (net):</div>
|
<div class="boxdaten legende ">Prix catalogue (net):</div>
|
||||||
@@ -1707,7 +1707,7 @@
|
|||||||
<div class="boxtabelle boxinhalt noPaddingTop borderSpacing">
|
<div class="boxtabelle boxinhalt noPaddingTop borderSpacing">
|
||||||
<div class="boxzeile">
|
<div class="boxzeile">
|
||||||
<div class="boxdaten legende ">Remise nette:</div>
|
<div class="boxdaten legende ">Remise nette:</div>
|
||||||
<div id="BT-147" title="BT-147" class="boxdaten wert"></div>
|
<div id="BT-147" title="BT-147" class="boxdaten wert">0,00</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="boxzeile">
|
<div class="boxzeile">
|
||||||
<div class="boxdaten legende ">Prix catalogue (net):</div>
|
<div class="boxdaten legende ">Prix catalogue (net):</div>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?><Invoice xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" xmlns:cec="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2">
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<cbc:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0</cbc:CustomizationID>
|
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:cec="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
|
||||||
<cbc:ProfileID>urn:fdc:peppol.eu:2017:poacc:billing:01:1.0</cbc:ProfileID>
|
<cbc:CustomizationID>urn:cen.eu:en16931:2017</cbc:CustomizationID>
|
||||||
<cbc:ID>RE-20201121/508</cbc:ID>
|
<cbc:ID>RE-20201121/508</cbc:ID>
|
||||||
<cbc:IssueDate>2020-11-21</cbc:IssueDate>
|
<cbc:IssueDate>2020-11-21</cbc:IssueDate>
|
||||||
<cbc:DueDate>2020-12-12</cbc:DueDate>
|
<cbc:DueDate>2020-12-12</cbc:DueDate>
|
||||||
|
|||||||
2
pom.xml
2
pom.xml
@@ -3,7 +3,7 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>org.mustangproject</groupId>
|
<groupId>org.mustangproject</groupId>
|
||||||
<artifactId>core</artifactId>
|
<artifactId>core</artifactId>
|
||||||
<version>2.17.0-SNAPSHOT</version> <packaging>pom</packaging>
|
<version>2.17.1-SNAPSHOT</version> <packaging>pom</packaging>
|
||||||
<name>Mustang</name>
|
<name>Mustang</name>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.mustangproject</groupId>
|
<groupId>org.mustangproject</groupId>
|
||||||
<artifactId>core</artifactId>
|
<artifactId>core</artifactId>
|
||||||
<version>2.17.0-SNAPSHOT</version>
|
<version>2.17.1-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>org.mustangproject</groupId>
|
<groupId>org.mustangproject</groupId>
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
<name>Library to validate e-invoices (ZUGFeRD, Factur-X and Xrechnung)</name>
|
<name>Library to validate e-invoices (ZUGFeRD, Factur-X and Xrechnung)</name>
|
||||||
|
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<version>2.17.0-SNAPSHOT</version>
|
<version>2.17.1-SNAPSHOT</version>
|
||||||
<repositories>
|
<repositories>
|
||||||
<repository>
|
<repository>
|
||||||
<!-- for jargs -->
|
<!-- for jargs -->
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>${project.groupId}</groupId>
|
<groupId>${project.groupId}</groupId>
|
||||||
<artifactId>library</artifactId>
|
<artifactId>library</artifactId>
|
||||||
<version>2.17.0-SNAPSHOT</version>
|
<version>2.17.1-SNAPSHOT</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.dom4j</groupId>
|
<groupId>org.dom4j</groupId>
|
||||||
|
|||||||
@@ -61,6 +61,9 @@ public abstract class Validator {
|
|||||||
Source xmlData = new StreamSource(new ByteArrayInputStream(xmlRawData));
|
Source xmlData = new StreamSource(new ByteArrayInputStream(xmlRawData));
|
||||||
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
|
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
|
||||||
try {
|
try {
|
||||||
|
schemaFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
|
||||||
|
schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
|
||||||
|
schemaFactory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
|
||||||
Schema schema = schemaFactory.newSchema(schemaFile);
|
Schema schema = schemaFactory.newSchema(schemaFile);
|
||||||
javax.xml.validation.Validator validator = schema.newValidator();
|
javax.xml.validation.Validator validator = schema.newValidator();
|
||||||
validator.validate(xmlData);
|
validator.validate(xmlData);
|
||||||
|
|||||||
Reference in New Issue
Block a user