Die Mustang-Klassen benutzen

Einfache Rechnung

Es gibt eine generelle Klassen-Testdatei die Sie für weitergehende Informationen einsehen können, eine zur XRechnung und eine betreffs des Rechnungsimporters.
Zunächst bauen und konfigurieren wir einen Exporter, der die PDF/A-Datei lädt in die wie unsere Rechnung einbetten:


import org.mustangproject.ZUGFeRD.IZUGFeRDExporter;
import org.mustangproject.ZUGFeRD.ZUGFeRDExporterFromPDFA;
//...
        String sourcePDF="MustangGnuaccountingBeispielRE-20190610_507blanko.pdf";
        try {
            IZUGFeRDExporter ze = new ZUGFeRDExporterFromPDFA().load(sourcePDF).setProducer("My Application").
                    setCreator(System.getProperty("user.name"));
        } catch (IOException e) {
            e.printStackTrace();
        }

Dann erstellen und konfigurieren wir unser Invoice-Objekt:


ze.setTransaction(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", "", "C62", new BigDecimal(19)),
                            new BigDecimal(2.5), new BigDecimal(1.0))));

Sie können mehrere addItem hintereinander hängen. In diesem Fall haben wir eine Rechnung mit der Nummer “X12” mit einem 1,0 mal 19%, 2,50€ “Testprodukt” in der Mengeneinheit “Stück”(C62, vgl. den Units-Reiter in dieser Excel-Datei) mit 19% Umsatzsteuer.
Nun exportieren wir die erstellte ZUGFeRD-Datei mit


ze.export("factur-x.pdf");

Gerne können Sie diese Datei validieren und bitte prüfen Sie mindestens Stichprobenartig dass die berechneten Summen in der eingebetteten XML-Datei denen in der PDF-Datei entsprechen.

Empfänger

Für Deutschland bekommen Sie eine gültige XRechnung wenn Sie die Leitweg-ID als Reference Number angeben, das XRechnung-Profile benutzen und die restlichen Pflichtangaben angeben, wie IBAN, Verkäuferkontakt-E-Mail und Telefon, und Emailaddresse der sendenden und empfangenen Firma:



        TradeParty recipient = new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE").setEmail("info@mueller.com");
        Invoice i = new Invoice().setDueDate(new Date()).setIssueDate(new
                        Date()).setDeliveryDate(new Date())
                .setSender(new TradeParty("Test company", "teststr", "55232", "teststadt", "DE").addTaxID("DE4711").addVATID("DE0815").setContact(new org.mustangproject.Contact("Hans Test", "+49123456789", "test@example.org")).addBankDetails(new org.mustangproject.BankDetails("DE12500105170648489890", "COBADEFXXX")).setEmail("info@example.org"))
                .setRecipient(recipient)
                .setReferenceNumber("991-01484-64")//leitweg-id
                .setNumber("123").addItem(new Item(new Product("Testprodukt", "", "C62", BigDecimal.ZERO), new BigDecimal("1.00"), new BigDecimal(1.0)));

		ZUGFeRD2PullProvider zf2p = new ZUGFeRD2PullProvider();
		zf2p.setProfile(Profiles.getByName("XRechnung"));
		zf2p.generateXML(i);
		String theXML = new String(zf2p.getXML(), StandardCharsets.UTF_8);
	

In Frankreich werden Empfänger über ihre Siret-Nummer identifiziert. Deren Typecode ist 0002, der über setLegalOrganisation gesetzt werden kann:


TradeParty recipient = new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE");
String siret="0815";
String sirenTypeCode="0002";
recipient.setLegalOrganisation(new LegalOrganisation(siret,sirenTypeCode));

Für deutsche Behördenrechnungen kann wie hier beschrieben die Leitweg-ID per invoice.setReferenceNumber() gesetzt werden.

Endbetrag kontrollieren

Um sicherzustellen, dass der von Mustang errechnete Endbetrag dem in Ihrem PDF entspricht können Sie TransactionCalculator verwenden:


		TransactionCalculator tc=new TransactionCalculator(i);
		// tc.getTotalGross() muss jetzt Ihrem Endbetrag entsprechen

Stornorechnung

Um eine Rechnung ganz oder teilweise zu widerrufen verwenden Sie eine negative Menge und übergeben der setCorrection-Methode der Invoice-Klasse die Nummer der zu korrigierenden Rechnung. Die negative Menge führt auch zu einem negativen Zahlbetrag. Folgendes Beispiel wiederruft die Rechnung aus dem vorangegangenem Beispiel:


ze.setTransaction(new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date())
.setSender(new TradeParty(orgname, "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("X13")
.addItem(new Item(new Product("Testproduct", "", "C62", new BigDecimal(19)), new BigDecimal("2.5"), new BigDecimal(-1.0))).setCorrection("X12"));

Kaufmännische Gutschriften

Kaufmännische Gutschriften können mit positiven Mengenangaben und setCreditNote() auf dem Invoice-Objekt implementiert werden:


      IZUGFeRDExporter ze = new ZUGFeRDExporterFromPDFA().load(sourcePDF).setProducer("My Application").
                    setCreator(System.getProperty("user.name"));
            Invoice i = new Invoice().setIssueDate(new Date()).setDueDate(new Date()).setDetailedDeliveryPeriod(new Date(), new Date()).setDeliveryDate(new Date()).setSender(new TradeParty("ACME inc", "teststr", "55232", "teststadt", "DE").addTaxID("4711").addVATID("DE0815").addBankDetails(new BankDetails("DE88200800000970375700", "COBADEFFXXX"))).setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE").addVATID("DE0815")).setNumber("0815")
                    .addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), new BigDecimal(1), new BigDecimal(1)))
                    .addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), new BigDecimal(1), new BigDecimal(10)))
                    .addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), new BigDecimal(1.41), new BigDecimal(3)))
                    .setCreditNote();

            ze.setTransaction(i);
            ze.export("factur-x.pdf");

Rabatte und Zuschläge

Rabatte und Zuschläge können auf Positions- und Dokumentebene gewährt werden und absolut oder prozentual sein. Sie müssen angeben, welchen Umsatzsteuersatz sie betreffen und in einigen Profilen wie EN16931 gibt es keine Zuschläge auf Positionsebene.

Für einen 50% Zuschlag auf Positionsebene mit 19% USt nutzen Sie


.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))))

und für einen 10€ Rabatt auf Dokumentebene hängen Sie bitte folgendes an die Invoice an:


.addAllowance(new Allowance(new BigDecimal(10)).setTaxPercent(new BigDecimal(19)))

Skonto

In den Profilen XRechnung oder Extended können Sie beispielweise 3% Skonto in 7 Tagen und 2% Skonto in 14 Tagen wie folgt hinzufügen:


		Invoice i = new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date())
				.setSender(new TradeParty(orgname,"teststr","55232","teststadt","DE").setEmail("sender@example.com").addTaxID("DE4711").addVATID("DE0815").setContact(new Contact("Hans Test","+49123456789","test@example.org")).addBankDetails(new BankDetails("DE12500105170648489890","COBADEFXXX")))
				.setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE").setEmail("recipient@sample.org"))
				.addCashDiscount(new CashDiscount(new BigDecimal(3),7))
				.addCashDiscount(new CashDiscount(new BigDecimal(2),14))
				.setNumber(number).addItem(new Item(new Product("Testprodukt", "", "C62", BigDecimal.ZERO), amount, new BigDecimal(1.0)));

Dateianhänge

Sie können weitere rechnungsbegründende Unterlagen wie Aufmäße oder Stundenzettel Base64-codiert in die XML-Struktur einhängen oder als zusätzlich ins PDF einzubettende Dateien angeben. Wenn Sie wissen, dass Sie eine PDF/A-1-Datei als Quelle haben können Sie ZUGFeRDExporterFromA1 und dessen Funktionen attachFile und, im Beispiel, ignorePDFAErrors() verwenden, wenn Sie bereits anderweitig sichergestellt haben, dass Ihre Eingabedatei fehlerfrei ist:


 ZUGFeRDExporterFromA1 ze = new ZUGFeRDExporterFromA1().setProducer("My Application")
					 .setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2).ignorePDFAErrors()
					 .load("sourcefile.pdf")) {
			byte[] b = {12, 13};
			ze.attachFile("one.pdf", b, "application/pdf", "Alternative");
			ze.attachFile("two.pdf", b, "application/pdf", "Alternative");
			ze.setTransaction(new Invoice().setDueDate(new Date()).setIssueDate(new Date()).setDeliveryDate(new Date()).setSender(new TradeParty(orgname, "teststr", "55232", "teststadt", "DE").addTaxID(taxID)).setOwnVATID("DE0815").setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE").addVATID("DE4711").setContact(new Contact("Franz Müller", "01779999999", "fr...@mueller.de", "teststr. 12", "55232", "Entenhausen", "DE"))).setNumber(number).addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), price, new BigDecimal(1.0)))

			);
			ze.export("filename.pdf");

Export mit PDF/A-3-Dateien

IZUGFeRDExporter/ZUGFeRDExporterFromPDFA stellt die PDF/A-Version (1 oder 3) selbst fest, wenn Sie wissen, dass Sie immer mit PDF/A-3 Eingabe arbeiten können Sie auch ZUGFeRDExporterFromA3 verwenden sofern bereits eine blanko-PDF/A-3-Datei vorliegt. Da die Factur-x-Datei immer zusätzlich angehängt wird darf diese nicht bereits existieren, das heißt es ist trotz PDF/A-3 leider noch nicht mögliche eine Factur-X/ZUGFeRD-Datei als Eingabe zu verwenden.


 ZUGFeRDExporterFromA3 ze = new ZUGFeRDExporterFromA3().setProducer("My Application")
					 .setCreator(System.getProperty("user.name")).setZUGFeRDVersion(2).ignorePDFAErrors()
					 .load("sourcefile.pdf")) {
...

Lesen

Um Rechnungen in ein Invoice-Objekt zu lesen verwenden Sie extractInvoice aus ZUGFeRDInvoiceImporter


ZUGFeRDInvoiceImporter zii=new ZUGFeRDInvoiceImporter("./target/testout-ZF2new.pdf");
Invoice invoice=zii.extractInvoice(); // surround this with try/catch

Jetzt können Sie beispielsweise die Rechnungsnummer (

invoice.getNumber()

), das Ausstellungsdatum
(

invoice.getIssueDate()

), die Anzahl der Positionen (

invoice.getZFItems().length

), die Menge der zweiten Position (

invoice.getZFItems()[1].getQuantity().toString())

), die Mengeneinheit des Produkts der dritten Position (

invoice.getZFItems()[2].getProduct().getUnit()

), die Straße des Empfängers (

invoice.getRecipient().getStreet()

) auslesen oder wie folgt den Gesamtbetrag berechnen/prüfen:


		TransactionCalculator tc=new TransactionCalculator(invoice);
		assertEquals(new BigDecimal("571.04"),tc.getTotalGross());