corrected release notes and history, zf1 test

This commit is contained in:
jstaerk
2020-11-08 20:15:41 +01:00
parent ffe6fd9e1a
commit 71379627c6
6 changed files with 52 additions and 60 deletions

View File

@@ -60,13 +60,7 @@ switch
- *validator not to XR error on ZF files (only notices) - *validator not to XR error on ZF files (only notices)
- *from A3 does not seem tow ork see mustangreaderwriteredgetest:testedgeexport - *from A3 does not seem tow ork see mustangreaderwriteredgetest:testedgeexport
- xmp errors may not show correctly in log - xmp errors may not show correctly in log
- confirm correct generation from pdf/a3 files zf2edgetest - finalize invoiceimporter
- visualization tests
- migration tests
- migration documentation
- *correctiontest exports zf1+zf2?
- *USt 0% wird aus invoice-klasse noch nicht sauber abgefangen
- finalize invoiceimporter
Alpha3 2020-10-24 Alpha3 2020-10-24
Alpha2 2020-09-15 Alpha2 2020-09-15
Alpha1 2020-08-06 Alpha1 2020-08-06

View File

@@ -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. 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 ### 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 `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")`. 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 The old Contact class has been corrected to TradeParty. The TradeParty class
can now refer to a (human) Contact from the new Contact() class. can now refer to a (human) Contact from the new Contact() class.

View File

@@ -182,51 +182,13 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr
} }
xml = xml + " <ram:SellerTradeParty>\n"; xml = xml + " <ram:SellerTradeParty>\n";
if (trans.getOwnForeignOrganisationID()!=null) { xml+= getTradePartyAsXML(trans.getSender(), true);
xml = xml + " <ram:ID>" + XMLTools.encodeXML(trans.getOwnForeignOrganisationID()) + "</ram:ID>\n"; xml+= " </ram:SellerTradeParty>\n"
}
if ((trans.getSender()!=null)&&(trans.getSender().getGlobalID()!=null)&&(trans.getSender().getGlobalIDScheme()!=null)) {
xml = xml + " <ram:GlobalID schemeID=\"" + XMLTools.encodeXML(trans.getSender().getGlobalIDScheme()) + "\">"
+ XMLTools.encodeXML(trans.getSender().getGlobalID()) + "</ram:GlobalID>\n";
}
xml = xml + " <ram:Name>" + XMLTools.encodeXML(trans.getOwnOrganisationName()) + "</ram:Name>\n"; //$NON-NLS-2$
if (trans.getSender().getContact() != null) {
xml = xml + "<ram:DefinedTradeContact>\n" + " <ram:PersonName>" + XMLTools.encodeXML(trans.getSender().getContact().getName())
+ "</ram:PersonName>\n";
if (trans.getSender().getContact().getPhone() != null) {
xml = xml + " <ram:TelephoneUniversalCommunication>\n" + " <ram:CompleteNumber>"
+ XMLTools.encodeXML(trans.getSender().getContact().getPhone()) + "</ram:CompleteNumber>\n"
+ " </ram:TelephoneUniversalCommunication>\n";
}
if (trans.getSender().getContact().getEMail() != null) {
xml = xml + " <ram:EmailURIUniversalCommunication>\n" + " <ram:URIID>"
+ XMLTools.encodeXML(trans.getSender().getContact().getEMail()) + "</ram:URIID>\n"
+ " </ram:EmailURIUniversalCommunication>\n";
}
xml = xml + " </ram:DefinedTradeContact>";
}
xml = xml + " <ram:PostalTradeAddress>\n" + " <ram:PostcodeCode>"
+ XMLTools.encodeXML(trans.getOwnZIP()) + "</ram:PostcodeCode>\n" + " <ram:LineOne>"
+ XMLTools.encodeXML(trans.getOwnStreet()) + "</ram:LineOne>\n" + " <ram:CityName>" + XMLTools.encodeXML(trans.getOwnLocation())
+ "</ram:CityName>\n" + " <ram:CountryID>" + XMLTools.encodeXML(trans.getOwnCountry())
+ "</ram:CountryID>\n" + " </ram:PostalTradeAddress>\n"
+ " <ram:SpecifiedTaxRegistration>\n"
+ " <ram:ID schemeID=\"FC\">" + XMLTools.encodeXML(trans.getOwnTaxID()) + "</ram:ID>\n" //$NON-NLS-2$
+ " </ram:SpecifiedTaxRegistration>\n"
+ " <ram:SpecifiedTaxRegistration>\n"
+ " <ram:ID schemeID=\"VA\">" + XMLTools.encodeXML(trans.getOwnVATID()) + "</ram:ID>\n" //$NON-NLS-2$
+ " </ram:SpecifiedTaxRegistration>\n"
+ " </ram:SellerTradeParty>\n"
+ " <ram:BuyerTradeParty>\n"; + " <ram:BuyerTradeParty>\n";
// + " <ID>GE2020211</ID>\n" // + " <ID>GE2020211</ID>\n"
// + " <GlobalID schemeID=\"0088\">4000001987658</GlobalID>\n" // + " <GlobalID schemeID=\"0088\">4000001987658</GlobalID>\n"
xml+= getTradePartyAsXML(trans.getRecipient()); xml+= getTradePartyAsXML(trans.getRecipient(), false);
if ((trans.getOwnVATID()!=null)&&(trans.getOwnOrganisationName()!=null)) { if ((trans.getOwnVATID()!=null)&&(trans.getOwnOrganisationName()!=null)) {
xml = xml + " <ram:SpecifiedTaxRegistration>\n" + " <ram:ID schemeID=\"VA\">" xml = xml + " <ram:SpecifiedTaxRegistration>\n" + " <ram:ID schemeID=\"VA\">"
+ XMLTools.encodeXML(trans.getOwnVATID()) + "</ram:ID>\n" + XMLTools.encodeXML(trans.getOwnVATID()) + "</ram:ID>\n"
@@ -245,7 +207,7 @@ public class ZUGFeRD1PullProvider extends ZUGFeRD2PullProvider implements IXMLPr
+ " <ram:ApplicableSupplyChainTradeDelivery>\n" ; + " <ram:ApplicableSupplyChainTradeDelivery>\n" ;
if (this.trans.getDeliveryAddress()!=null) { if (this.trans.getDeliveryAddress()!=null) {
xml += "<ram:ShipToTradeParty>"+ xml += "<ram:ShipToTradeParty>"+
getTradePartyAsXML(this.trans.getDeliveryAddress())+ getTradePartyAsXML(this.trans.getDeliveryAddress(), false)+
"</ram:ShipToTradeParty>"; "</ram:ShipToTradeParty>";
} }

View File

@@ -105,7 +105,14 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
return profile; 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 = ""; String xml = "";
// According EN16931 either GlobalID or seller assigned ID might be present for BuyerTradeParty // According EN16931 either GlobalID or seller assigned ID might be present for BuyerTradeParty
// and ShipToTradeParty, but not both. Prefer seller assigned ID for now. // and ShipToTradeParty, but not both. Prefer seller assigned ID for now.
@@ -117,7 +124,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
} }
xml += " <ram:Name>" + XMLTools.encodeXML(party.getName()) + "</ram:Name>\n"; //$NON-NLS-2$ xml += " <ram:Name>" + XMLTools.encodeXML(party.getName()) + "</ram:Name>\n"; //$NON-NLS-2$
if (party.getContact() != null) { if ((party.getContact() != null)&&(isSender||profile==Profiles.getByName("Extended"))) {
xml = xml + "<ram:DefinedTradeContact>\n" + " <ram:PersonName>" + XMLTools.encodeXML(party.getContact().getName()) xml = xml + "<ram:DefinedTradeContact>\n" + " <ram:PersonName>" + XMLTools.encodeXML(party.getContact().getName())
+ "</ram:PersonName>\n"; + "</ram:PersonName>\n";
if (party.getContact().getPhone() != null) { if (party.getContact().getPhone() != null) {
@@ -184,8 +191,8 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
protected String getAllowanceChargeStr(IZUGFeRDAllowanceCharge allowance, IAbsoluteValueProvider item) { protected String getAllowanceChargeStr(IZUGFeRDAllowanceCharge allowance, IAbsoluteValueProvider item) {
String percentage = ""; String percentage = "";
String chargeIndicator = "false"; String chargeIndicator = "false";
if (allowance.getPercent() != null) { if ((allowance.getPercent() != null)&&(profile==Profiles.getByName("Extended"))) {
percentage = "<ram:CalculationPercent>" + allowance.getPercent() + "</ram:CalculationPercent>"; percentage = "<ram:CalculationPercent>" + vatFormat(allowance.getPercent()) + "</ram:CalculationPercent>";
percentage += "<ram:BasisAmount>" + item.getValue() + "</ram:BasisAmount>"; percentage += "<ram:BasisAmount>" + item.getValue() + "</ram:BasisAmount>";
} }
if (allowance.isCharge()) { if (allowance.isCharge()) {
@@ -391,13 +398,13 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
} }
xml = xml + " <ram:SellerTradeParty>\n" xml = xml + " <ram:SellerTradeParty>\n"
+ getTradePartyAsXML(trans.getSender()) + getTradePartyAsXML(trans.getSender(), true)
+ " </ram:SellerTradeParty>\n" + " </ram:SellerTradeParty>\n"
+ " <ram:BuyerTradeParty>\n"; + " <ram:BuyerTradeParty>\n";
// + " <ID>GE2020211</ID>\n" // + " <ID>GE2020211</ID>\n"
// + " <GlobalID schemeID=\"0088\">4000001987658</GlobalID>\n" // + " <GlobalID schemeID=\"0088\">4000001987658</GlobalID>\n"
xml += getTradePartyAsXML(trans.getRecipient()); xml += getTradePartyAsXML(trans.getRecipient(), false);
xml += " </ram:BuyerTradeParty>\n"; xml += " </ram:BuyerTradeParty>\n";
if (trans.getBuyerOrderReferencedDocumentID() != null) { if (trans.getBuyerOrderReferencedDocumentID() != null) {
@@ -431,7 +438,7 @@ public class ZUGFeRD2PullProvider implements IXMLProvider {
+ " <ram:ApplicableHeaderTradeDelivery>\n"; + " <ram:ApplicableHeaderTradeDelivery>\n";
if (this.trans.getDeliveryAddress() != null) { if (this.trans.getDeliveryAddress() != null) {
xml += "<ram:ShipToTradeParty>" + xml += "<ram:ShipToTradeParty>" +
getTradePartyAsXML(this.trans.getDeliveryAddress()) + getTradePartyAsXML(this.trans.getDeliveryAddress(), false) +
"</ram:ShipToTradeParty>"; "</ram:ShipToTradeParty>";
} }

View File

@@ -56,7 +56,7 @@ public class BackwardCompatibilityTest extends TestCase implements IExportableTr
try (InputStream SOURCE_PDF = this.getClass() try (InputStream SOURCE_PDF = this.getClass()
.getResourceAsStream("/MustangGnuaccountingBeispielRE-20190610_507blanko.pdf"); .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.setTransaction(this);
ze.disableAutoClose(true); ze.disableAutoClose(true);

View File

@@ -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");
}
} }