Using the Mustang interfaces

Write a ZUGFeRD-PDF file

Please note: This is a sample for Mustangproject 1. Mustang 2 is largely compatible but certain discrepancies may arise and this page needs to be revised in the future.

  1. Create a new class in the src-folder, e.g. MustangWriter with the usual „Public static void main()“ .
  2. Create a run configuration: Run|Run configurations Java Application, click on the “new” icon.
  3. let the main class implement IZUGFeRDExportableTransaction like this
    public class MustangWriter implements IZUGFeRDExportableTransaction {
  4. Even before that, but after package mustangtest;, add the following classes in in the same file:
    
    class Contact implements IZUGFeRDExportableContact {}
    class Item implements IZUGFeRDExportableItem {
        private BigDecimal price, quantity;
        private Product product;
    }
    class Product implements IZUGFeRDExportableProduct {
        private String description, name, unit;
        private BigDecimal VATPercent;
    }         
    class Payment implements IZUGFeRDTradeSettlementPayment {
    }
                           
                                
  5. add the imports by pressing CTRL+SHIFT+O (Windows) or CMD+SHIFT+O (Mac).
  6. Left click left on the main class MustangWriter and press ALT+SHIFT+S
    (Windows)/ALT+CMD+S (Mac), select “Override/Implement Methods” and press return.
  7. Left click on the class name Contact and press ALT+SHIFT+S
    (Windows)/ALT+CMD+S (Mac), select “Override/Implement Methods” and press return.
  8. Click Item, press ALT+SHIFT+S or ALT+CMD+S, this time select „Generate Getters and Setters“. Mark all members and press return.
  9. Stay on Item, refactor again (ALT+SHIFT+S or ALT+CMD+S) and select „Generate Constructor using Fields“. Choose again all member variables and press return.
  10. Item also needs other methods besides the getter/setters, refactor again (ALT+SHIFT+S or ALT+CMD+S) and choose Override/Implement Methods
  11. „Generate Getters and Setters“ for the class (not the member „Product“: Click Product, (ALT+SHIFT+S or ALT+CMD+S) and select „Generate Getters and Setters“. Choose all members and confirm
  12. Click on Product again, press ALT+SHIFT+S and select „Generate Constructor using Fields“. Choose all members again and press return.
  13. Right-click on Payment, select Source|„Override and Implement Methods“. Choose at least getOwnBIC(), getOwnBankName() and getOwnIBAN().
  14. Your skeleton should now look like this
  15. The following methods of Contact should now return the following strings:
    • getCountry(): “DE”
    • getLocation(): “Spielkreis”
    • getName(): “Theodor Est”
    • getStreet(): “Bahnstr. 42”
    • getVATID(): “DE999999999”
    • getZIP(): “88802”;
  16. The following methods of Payment should return the following strings:
    • getOwnBIC(): “COBADEFFXXX”
    • getOwnBankName(): “Commerzbank”
    • getOwnIBAN(): “DE88200800000970375700”
  17. The following methods of the main class should return the following:
    • getCurrency(): “EUR”
    • getDeliveryDate(): newGregorianCalendar(2017,Calendar.NOVEMBER,17).getTime();
    • Pressing CTRLs+SHIFT+O (Windows) or CMD+SHIFT+O (Mac) will import the
      necessary
      GregorianCalendar and Calendar class
    • getDueDate(): newGregorianCalendar(2017,Calendar.DECEMBER,9).getTime();
    • getIssueDate(): newGregorianCalendar(2017,Calendar.NOVEMBER,18).getTime();
    • getNumber(): “RE-20171118/506”
    • getOwnBIC(): “COBADEFFXXX”
    • getOwnBankName(): “Commerzbank”
    • getOwnCountry() “DE”
    • getOwnIBAN(): “DE88 2008 0000 0970 3757 00”
    • getOwnLocation() “Stadthausen”
    • getOwnOrganisationFullPlaintextInfo(): “Bei Spiel GmbH\n”+
      “Ecke 12\n”+
      “12345 Stadthausen\n”+
      “Geschäftsführer: Max Mustermann”
    • getOwnOrganisationName(): “Bei Spiel GmbH”
    • getOwnStreet() “Ecke 12”
    • getOwnTaxID(): “22/815/0815/4”
    • getOwnVATID(): “DE136695976”
    • getOwnZIP() “12345”
    • getRecipient(): new Contact();
    • IZUGFeRDTradeSettlementPayment[] getTradeSettlementPayment(): Payment P = new Payment();
      IZUGFeRDTradeSettlementPayment[] allP = new Payment[1];
      allP[0] = P;
      return allP;
  18. getZFItems() of the main class can now create products and return them as a arrays of items:
    
    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;                        
                        
  19. Now create a “private void” method called apply in the MustangWriter class
  20. Please instantiate this main MustangWriter class in the main method and invoke the apply() function.
  21. In the apply-method you can now
    • create a new ZUGFeRDExporterFromA1Factory, run
    • setProducer and setCreator on it (e.g. ZUGFeRDExporter ze=newZUGFeRDExporterFromA1Factory().setProducer("string").setCreator("string")) and get
      the ZUGFeRDExporter from the factories load("./MustangGnuaccountingBeispielRE-20171118_506new.pdf")
      method.
    • Feel free to use your own PDF/A-1 invoice file.
    • In this chain (.setProducer.setCreator…) you can also insert setZUGFeRDVersion(2)
    • use the PDFattachZugferdFile-method (with the IZUGFeRDExportableTransation, i.e. „this“ as parameter) on the ZUGFeRDExporter and
    • use export() to save the PDF/A-3 file.
    • Finally, add the imports by pressing CTRL+SHIFT+O (Windows) or CMD+SHIFT+O (Mac).

    The apply-method then looks – with according try/catch-blocks- as follows:

    
    private void apply() {
        try {
            System.out.println("Reading Blanko-PDF");
            ZUGFeRDExporter ze = new ZUGFeRDExporterFromA1Factory().setProducer("My Application")
            .setCreator(System.getProperty("user.name"))
            .load("./MustangGnuaccountingBeispielRE-20190610_507blanko.pdf");
            System.out.println("Generating and attaching ZUGFeRD-Data");
            ze.PDFattachZugferdFile(this);
            System.out.println("Writing ZUGFeRD-PDF");
            ze.export("./MustangGnuaccountingBeispielRE-20190610_507new.pdf");
            System.out.println("Done.");
        } catch (IOException e) {
            e.printStackTrace();
        }
    
    }                    
                    
  22. „My Application“ and System.getProperty(“user.name”) are stored in the meta data as „Producer“ (producing application) respectively „Creator“ (author). Please adjust accordingly.
  23. Instanciate a MustangWriter in public static void main and call it’s apply() method.
  24. Start it to write the ZUGFeRD invoice to the file specified in export.
  25. To be APL compliant: Adjust the NOTICE-File for and add it to your application.

End result

Your MustangWriter.java should now look like this.

Upgrade from Mustang 1.x

What Old value New value
Repository github.com/ZUGFeRD… remove (maven central)
Group id org.mustangproject.zugferd org.mustangproject
Artifact id mustang library
Version 1.7.8 2.0.0

If you want you can also embed the validator in your software using validator
as artifact ID. “validator” includes the library functionality but is >20 MB
bigger due to it’s dependencies. ZF2 was possible with Mustang 1 but it is default in Mustang 2, so
you will need to

.setZUGFeRDVersion(1)

if you don’t want ZUGFeRD 2 files.

In the commandline, all actions will have to be invoked via –action=<theaction>, so
–combine changes to –action=combine.</theaction>

PDFattachZugferdFile

is now calle

setTransaction

and instead of a

ZUGFeRDExporterFromA1Factory

the

ZUGFeRDExporterFromA1

will now return a
a class implementing

IZUGFeRDExporter

instead of a

ZUGFeRDExporter

So

ZUGFeRDExporter ze = new ZUGFeRDExporterFromA1Factory().setZUGFeRDConformanceLevel(ZUGFeRDConformanceLevel.COMFORT).load(SOURCE_PDF)) {
IZUGFeRDExporter ze = new ZUGFeRDExporterFromA1().setZUGFeRDVersion(1).setZUGFeRDConformanceLevel(ZUGFeRDConformanceLevel.EN16931).load(SOURCE_PDF)) {

Instead of

Profile.EXTENDED

use

Profiles.getByName("Extended")

If you want to use Profiles from older versions, please specify the version like

Profiles.getByName("Extended")

for an Extended profile of ZF1.

The old Contact class has been corrected to TradeParty. The TradeParty class
can now refer to a (human) Contact from the new Contact() class.