diff --git a/History.md b/History.md
index 3e577055..4bfc257a 100644
--- a/History.md
+++ b/History.md
@@ -60,13 +60,7 @@ switch
- *validator not to XR error on ZF files (only notices)
- *from A3 does not seem tow ork see mustangreaderwriteredgetest:testedgeexport
- xmp errors may not show correctly in log
-- confirm correct generation from pdf/a3 files zf2edgetest
-- visualization tests
-- migration tests
-- migration documentation
-- *correctiontest exports zf1+zf2?
-- *USt 0% wird aus invoice-klasse noch nicht sauber abgefangen
-- finalize invoiceimporter
+- finalize invoiceimporter
Alpha3 2020-10-24
Alpha2 2020-09-15
Alpha1 2020-08-06
diff --git a/Release_Notes.md b/Release_Notes.md
index 1ad825f1..f8c53e82 100644
--- a/Release_Notes.md
+++ b/Release_Notes.md
@@ -3,11 +3,21 @@
On it's official website you can [download](https://www.mustangproject.org/files/Mustang-CLI-2.0.0-alpha3.jar) a alpha release of Mustang 2.
-It integrates the successor of the ZUGFeRD [Validator ZUV](https://github.com/ZUGFeRD/ZUV/) in it's command line tool and can be used as library.
+* Factur-X/ZUGFeRD 2 is now the default. In Mustangproject 1.x one had to select ZUGFeRD version 2 if that was desired, in Mustangproject 2 one now has to select ZUGFeRD version 1 if version 2 is not appropriate.
+* Mustang is now available via Maven Central, which makes it even easier to use the Mustang library. Apart from making it easier in Maven because there is no longer the need to mention the custom repository, it also makes it possible to use Mustang in Gradle projects
+* ZUGFeRD 2.1.1 is now supported with it's XRechnung "reference profile". The previous stable version, Mustang 1.7.8, only supported ZUGFeRD 2.1.
+* There is now an experimental visualization feature and an improved experimental upgrade functionality from ZF1 XML to ZF2 XML.
+* Mustang now supports percentual and absolute charges and allowances on both item and document level
+* Mustang can now embed additional invoice-accompanying files like plans or worklists into the PDFs
+* Additionally to the usual interface-based architecture there are now also classes for invoice, tradeparty etc., which makes it easier to develop in the Mustang library. Please feel free to have a look at it's tests on https://github.com/ZUGFeRD/mustangproject/blob/master/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2PushTest.java.
+* Mustang now includes a validator, which can check the syntactical correctness of an e-invoice.
+The validator component has previously been developed under the name ZUGFeRD and VeraPDF "ZUV".
+It is now mature enought to be merged into the Mustang mainstream project.
+ZUV already was the validator behind https://www.zugferd-community.net/de/open_community/validation with around 1,000 validations/month alone,
+supports ZUGFeRD 1 and ZUGFeRD 2 and can be used via commandline.
+Additionally, the Mustang validator now also supports XRechnung 2, can now also be used as library and supports validation of whole directory trees.
-Additionally, the default changed from ZUGFeRD 1 to ZUGFeRD 2.1.1 (previously you had to enable that, now you have to specify that you want to use ZF1 if that's the case), it's now available via Maven Central and additionally to the old Interface-style pullProvider requiring you to implement methods there is now also a "normal", class-orientierted, halfway fluent "Push-Provider". It's describe below, if you are impatient please feel free to have a look at it's tests on https://github.com/ZUGFeRD/mustangproject/blob/master/library/src/test/java/org/mustangproject/ZUGFeRD/ZF2PushTest.java.
-This is a preview release, please do not (yet) use it in production.
### Use on command line
`java -jar Mustang-CLI-2.0.0-alpha3.jar --action=combine` embedds a XML into a PDF (A-1) file and exports as PDF/A-3
@@ -91,6 +101,8 @@ changes to
```
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.
diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD1PullProvider.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD1PullProvider.java
index 2452651d..898c177d 100644
--- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD1PullProvider.java
+++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD1PullProvider.java
@@ -182,51 +182,13 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr
}
xml = xml + " \n";
- if (trans.getOwnForeignOrganisationID()!=null) {
- xml = xml + " " + XMLTools.encodeXML(trans.getOwnForeignOrganisationID()) + "\n";
- }
-
- if ((trans.getSender()!=null)&&(trans.getSender().getGlobalID()!=null)&&(trans.getSender().getGlobalIDScheme()!=null)) {
- xml = xml + " "
- + XMLTools.encodeXML(trans.getSender().getGlobalID()) + "\n";
- }
- xml = xml + " " + XMLTools.encodeXML(trans.getOwnOrganisationName()) + "\n"; //$NON-NLS-2$
-
- if (trans.getSender().getContact() != null) {
- xml = xml + "\n" + " " + XMLTools.encodeXML(trans.getSender().getContact().getName())
- + "\n";
- if (trans.getSender().getContact().getPhone() != null) {
-
- xml = xml + " \n" + " "
- + XMLTools.encodeXML(trans.getSender().getContact().getPhone()) + "\n"
- + " \n";
- }
- if (trans.getSender().getContact().getEMail() != null) {
-
- xml = xml + " \n" + " "
- + XMLTools.encodeXML(trans.getSender().getContact().getEMail()) + "\n"
- + " \n";
- }
- xml = xml + " ";
-
- }
- xml = xml + " \n" + " "
- + XMLTools.encodeXML(trans.getOwnZIP()) + "\n" + " "
- + XMLTools.encodeXML(trans.getOwnStreet()) + "\n" + " " + XMLTools.encodeXML(trans.getOwnLocation())
- + "\n" + " " + XMLTools.encodeXML(trans.getOwnCountry())
- + "\n" + " \n"
- + " \n"
- + " " + XMLTools.encodeXML(trans.getOwnTaxID()) + "\n" //$NON-NLS-2$
- + " \n"
- + " \n"
- + " " + XMLTools.encodeXML(trans.getOwnVATID()) + "\n" //$NON-NLS-2$
- + " \n"
- + " \n"
+ xml+= getTradePartyAsXML(trans.getSender(), true);
+ xml+= " \n"
+ " \n";
// + " GE2020211\n"
// + " 4000001987658\n"
- xml+= getTradePartyAsXML(trans.getRecipient());
+ xml+= getTradePartyAsXML(trans.getRecipient(), false);
if ((trans.getOwnVATID()!=null)&&(trans.getOwnOrganisationName()!=null)) {
xml = xml + " \n" + " "
+ XMLTools.encodeXML(trans.getOwnVATID()) + "\n"
@@ -245,7 +207,7 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr
+ " \n" ;
if (this.trans.getDeliveryAddress()!=null) {
xml += ""+
- getTradePartyAsXML(this.trans.getDeliveryAddress())+
+ getTradePartyAsXML(this.trans.getDeliveryAddress(), false)+
"";
}
diff --git a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java
index da1e0cb1..b9d96e5a 100644
--- a/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java
+++ b/library/src/main/java/org/mustangproject/ZUGFeRD/ZUGFeRD2PullProvider.java
@@ -105,7 +105,14 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
return profile;
}
- protected String getTradePartyAsXML(IZUGFeRDExportableTradeParty party) {
+ /***
+ * returns the UN/CEFACT CII XML for companies(tradeparties), which is actually
+ * the same for ZF1 (v 2013b) and ZF2 (v 2016b)
+ * @param party
+ * @param isSender some attributes are allowed only for senders in certain profiles
+ * @return
+ */
+ protected String getTradePartyAsXML(IZUGFeRDExportableTradeParty party, boolean isSender) {
String xml = "";
// According EN16931 either GlobalID or seller assigned ID might be present for BuyerTradeParty
// and ShipToTradeParty, but not both. Prefer seller assigned ID for now.
@@ -117,7 +124,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
}
xml += " " + XMLTools.encodeXML(party.getName()) + "\n"; //$NON-NLS-2$
- if (party.getContact() != null) {
+ if ((party.getContact() != null)&&(isSender||profile==Profiles.getByName("Extended"))) {
xml = xml + "\n" + " " + XMLTools.encodeXML(party.getContact().getName())
+ "\n";
if (party.getContact().getPhone() != null) {
@@ -184,8 +191,8 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
protected String getAllowanceChargeStr(IZUGFeRDAllowanceCharge allowance, IAbsoluteValueProvider item) {
String percentage = "";
String chargeIndicator = "false";
- if (allowance.getPercent() != null) {
- percentage = "" + allowance.getPercent() + "";
+ if ((allowance.getPercent() != null)&&(profile==Profiles.getByName("Extended"))) {
+ percentage = "" + vatFormat(allowance.getPercent()) + "";
percentage += "" + item.getValue() + "";
}
if (allowance.isCharge()) {
@@ -391,13 +398,13 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
}
xml = xml + " \n"
- + getTradePartyAsXML(trans.getSender())
+ + getTradePartyAsXML(trans.getSender(), true)
+ " \n"
+ " \n";
// + " GE2020211\n"
// + " 4000001987658\n"
- xml += getTradePartyAsXML(trans.getRecipient());
+ xml += getTradePartyAsXML(trans.getRecipient(), false);
xml += " \n";
if (trans.getBuyerOrderReferencedDocumentID() != null) {
@@ -431,7 +438,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
+ " \n";
if (this.trans.getDeliveryAddress() != null) {
xml += "" +
- getTradePartyAsXML(this.trans.getDeliveryAddress()) +
+ getTradePartyAsXML(this.trans.getDeliveryAddress(), false) +
"";
}
diff --git a/library/src/test/java/org/mustangproject/ZUGFeRD/BackwardCompatibilityTest.java b/library/src/test/java/org/mustangproject/ZUGFeRD/BackwardCompatibilityTest.java
index 6732c354..d07325a5 100644
--- a/library/src/test/java/org/mustangproject/ZUGFeRD/BackwardCompatibilityTest.java
+++ b/library/src/test/java/org/mustangproject/ZUGFeRD/BackwardCompatibilityTest.java
@@ -56,7 +56,7 @@ public class BackwardCompatibilityTest extends TestCase implements IExportableTr
try (InputStream SOURCE_PDF = this.getClass()
.getResourceAsStream("/MustangGnuaccountingBeispielRE-20190610_507blanko.pdf");
- IZUGFeRDExporter ze = new ZUGFeRDExporterFromA1().setZUGFeRDVersion(1).setProfile("EN16931").load(SOURCE_PDF)) {
+ IZUGFeRDExporter ze = new ZUGFeRDExporterFromA1().setZUGFeRDVersion(1).setProfile(Profiles.getByName("Extended",1)).load(SOURCE_PDF)) {
ze.setTransaction(this);
ze.disableAutoClose(true);
diff --git a/validator/src/test/java/org/mustangproject/validator/LibraryTest.java b/validator/src/test/java/org/mustangproject/validator/LibraryTest.java
index dc574808..2e9191cb 100644
--- a/validator/src/test/java/org/mustangproject/validator/LibraryTest.java
+++ b/validator/src/test/java/org/mustangproject/validator/LibraryTest.java
@@ -118,4 +118,21 @@ public class LibraryTest extends ResourceCase {
}
+ public void testZF1validity() {
+ File tempFile = new File("../library/target/testout-MustangGnuaccountingBeispielRE-20171118_506zf1.pdf");
+ assertTrue(tempFile.exists());
+ ZUGFeRDValidator zfv = new ZUGFeRDValidator();
+
+ String res = zfv.validate(tempFile.getAbsolutePath());
+
+
+ assertThat(res).valueByXPath("/validation/pdf/summary/@status")
+ .isEqualTo("valid");
+
+ assertThat(res).valueByXPath("/validation/xml/summary/@status")
+ .isEqualTo("valid");
+
+ assertThat(res).valueByXPath("/validation/summary/@status")
+ .isEqualTo("valid");
+ }
}