diff --git a/README.md b/README.md index 43ea3671..6c4ecb6c 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ If you set up a Maven project, you can reference the mustang artifact like this: org.mustangproject validator - 2.15.0 + 2.17.0 shaded ``` diff --git a/doc/MustangWriter.java b/doc/MustangWriter.java deleted file mode 100644 index 6cf8670b..00000000 --- a/doc/MustangWriter.java +++ /dev/null @@ -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; - } - -} diff --git a/doc/ZugferdDev.de.adoc b/doc/ZugferdDev.de.adoc new file mode 100644 index 00000000..accca91c --- /dev/null +++ b/doc/ZugferdDev.de.adoc @@ -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 + + + + + +mustang-mvn-repo + +https://raw.github.com/ZUGFeRD/mustangproject/mvn-repo/ + + + + + +und folgender Dependency + + + +org.mustangproject.ZUGFeRD + +mustang + +1.5.1 + + + +Bei der Gelegenheit kann man auch gleich Apache Commons Logging und JAXB +importieren: + + + +commons-logging + +commons-logging + +1.1.1 + + + + + +com.sun.xml.bind + +jaxb-impl + +2.2.5 + + + +== [#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 = +""; + +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 + + org.mustangproject + validator + shaded + 2.17.0 + + +---- + +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(); + } + } +} +---- diff --git a/doc/ZugferdDev.en.pdf b/doc/ZugferdDev.en.pdf index a16e3e9c..c8c206a5 100644 Binary files a/doc/ZugferdDev.en.pdf and b/doc/ZugferdDev.en.pdf differ