first attempt to create CII files from ZUGFeRD invoices

This commit is contained in:
Jochen Stärk
2017-08-14 20:59:45 +02:00
parent 8612dff895
commit a53de2546e
2 changed files with 63 additions and 4 deletions

View File

@@ -3,9 +3,9 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.mustangproject.ZUGFeRD</groupId> <groupId>org.mustangproject.ZUGFeRD</groupId>
<artifactId>toecount</artifactId> <artifactId>toecount</artifactId>
<version>0.1.0-SNAPSHOT</version> <version>0.2.0-SNAPSHOT</version>
<name>ZUGFeRD PDF checker</name> <name>ZUGFeRD PDF checker</name>
<description>Shows statistics on how many PDFs in a directory are ZUGFeRD-Compliant</description> <description>Shows statistics on how many PDFs in a directory are ZUGFeRD-compliant, allows to combine XML and PDF, extract XML from PDF and migrate XML from ZF1 to ZF2</description>
<repositories> <repositories>
<repository> <repository>
<id>mustang-mvn-repo</id> <id>mustang-mvn-repo</id>

View File

@@ -3,9 +3,11 @@ package toecount;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.regex.Pattern;
import javax.xml.bind.JAXBException; import javax.xml.bind.JAXBException;
import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerException;
@@ -23,11 +25,11 @@ public class Toecount {
} }
private static String getUsage() { private static String getUsage() {
return "Usage: Toecount [-d,--directory] [-l,--listfromstdin] [-i,--ignorefileextension] | [-c,--combine] | [-e,--extract] | [-h,--help]\r\n"; return "Usage: Toecount [-d,--directory] [-l,--listfromstdin] [-i,--ignorefileextension] | [-c,--combine] | [-e,--extract] | [-u,--upgrade] | [-h,--help]\r\n";
} }
private static void printHelp() { private static void printHelp() {
System.out.println("Mustangproject.org's Toecount 0.1.0 \r\n" System.out.println("Mustangproject.org's Toecount 0.2.0 \r\n"
+ "A Apache Public License command line tool for statistics on PDF invoices with\r\n" + "A Apache Public License command line tool for statistics on PDF invoices with\r\n"
+ "ZUGFeRD Metadata (http://www.zugferd.org)\r\n" + "\r\n" + getUsage() + "Count operations" + "ZUGFeRD Metadata (http://www.zugferd.org)\r\n" + "\r\n" + getUsage() + "Count operations"
+ "\t--directory= count ZUGFeRD files in directory to be scanned\r\n" + "\t--directory= count ZUGFeRD files in directory to be scanned\r\n"
@@ -38,6 +40,7 @@ public class Toecount {
+ "Merge operations" + "Merge operations"
+ "\t--combine= combine ZUGFeRD-invoice.xml and invoice.pdf to invoice.zugferd.pdf\r\n" + "\t--combine= combine ZUGFeRD-invoice.xml and invoice.pdf to invoice.zugferd.pdf\r\n"
+ "\t--extract= extract invoice.zugferd.pdf to ZUGFeRD-invoice.xml\r\n" + "\t--extract= extract invoice.zugferd.pdf to ZUGFeRD-invoice.xml\r\n"
+ "\t--upgrade= upgrafe ZUGFeRD-invoice.pdf to ZUGFeRD-2-invoice.xml\r\n"
); );
} }
@@ -51,6 +54,7 @@ public class Toecount {
Option<Boolean> combineOption = parser.addBooleanOption('c', "combine"); Option<Boolean> combineOption = parser.addBooleanOption('c', "combine");
Option<Boolean> extractOption = parser.addBooleanOption('e', "extract"); Option<Boolean> extractOption = parser.addBooleanOption('e', "extract");
Option<Boolean> helpOption = parser.addBooleanOption('h', "help"); Option<Boolean> helpOption = parser.addBooleanOption('h', "help");
Option<Boolean> upgradeOption = parser.addBooleanOption('u', "upgrade");
if (args.length == 0) { if (args.length == 0) {
printUsage(); printUsage();
@@ -75,6 +79,8 @@ public class Toecount {
Boolean helpRequested = parser.getOptionValue(helpOption, Boolean.FALSE); Boolean helpRequested = parser.getOptionValue(helpOption, Boolean.FALSE);
Boolean upgradeRequested = parser.getOptionValue(upgradeOption, Boolean.FALSE);
Boolean ignoreFileExt = parser.getOptionValue(ignoreFileExtOption, Boolean.FALSE); Boolean ignoreFileExt = parser.getOptionValue(ignoreFileExtOption, Boolean.FALSE);
if (helpRequested) { if (helpRequested) {
@@ -160,6 +166,59 @@ public class Toecount {
} }
System.out.println("Written to ZUGFeRD-invoice.xml"); System.out.println("Written to ZUGFeRD-invoice.xml");
} else if (upgradeRequested) {
try {
String xml=new String(Files.readAllBytes(Paths.get("./ZUGFeRD-invoice.xml")),StandardCharsets.UTF_8);
// todo: attributes may also be in single quotes, this one hardcodedly expects double ones
xml=xml.replaceAll(Pattern.quote("\"urn:ferd:CrossIndustryDocument:invoice:1p0"), "\"urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:13");
xml=xml.replaceAll(Pattern.quote("urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:12"), "urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:20");
xml=xml.replaceAll(Pattern.quote("urn:un:unece:uncefact:data:standard:UnqualifiedDataType:15"), "urn:un:unece:uncefact:data:standard:UnqualifiedDataType:20");
xml=xml.replaceAll(Pattern.quote("rsm:CrossIndustryDocument"), "rsm:CrossIndustryInvoice");
xml=xml.replaceAll(Pattern.quote("rsm:SpecifiedExchangedDocumentContext"), "rsm:CIExchangedDocumentContext");
xml=xml.replaceAll(Pattern.quote("rsm:HeaderExchangedDocument"), "rsm:CIIHExchangedDocument");
xml=xml.replaceAll(Pattern.quote("SpecifiedSupplyChainTradeTransaction"), "CIIHSupplyChainTradeTransaction");
xml=xml.replaceAll(Pattern.quote("ram:GuidelineSpecifiedDocumentContextParameter"), "ram:GuidelineSpecifiedDocumentCIContextParameter");
xml=xml.replaceAll(Pattern.quote("ram:IncludedNote"), "ram:IncludedCINote");
xml=xml.replaceAll(Pattern.quote("ram:ApplicableSupplyChainTradeAgreement"), "ram:ApplicableCIIHSupplyChainTradeAgreement");
xml=xml.replaceAll(Pattern.quote("ram:SellerTradeParty"), "ram:SellerCITradeParty");
xml=xml.replaceAll(Pattern.quote("ram:BuyerTradeParty"), "ram:BuyerCITradeParty");
xml=xml.replaceAll(Pattern.quote("ram:ApplicableSupplyChainTradeDelivery"), "ram:ApplicableCIIHSupplyChainTradeDelivery");
xml=xml.replaceAll(Pattern.quote("ram:ApplicableSupplyChainTradeSettlement"), "ram:ApplicableCIIHSupplyChainTradeSettlement");
xml=xml.replaceAll(Pattern.quote("ram:IncludedSupplyChainTradeLineItem"), "ram:IncludedCIILSupplyChainTradeLineItem");
xml=xml.replaceAll(Pattern.quote("ram:AssociatedDocumentLineDocument"), "ram:AssociatedCIILDocumentLineDocument");
xml=xml.replaceAll(Pattern.quote("ram:SpecifiedSupplyChainTradeDelivery"), "ram:SpecifiedCIILSupplyChainTradeDelivery");
xml=xml.replaceAll(Pattern.quote("ram:SpecifiedSupplyChainTradeSettlement"), "ram:SpecifiedCIILSupplyChainTradeSettlement");
xml=xml.replaceAll(Pattern.quote("ram:SpecifiedTradeSettlementMonetarySummation"), "ram:SpecifiedCIILTradeSettlementMonetarySummation");
xml=xml.replaceAll(Pattern.quote("ram:SpecifiedTradeProduct"), "ram:SpecifiedCITradeProduct");
xml=xml.replaceAll(Pattern.quote("ram:ActualDeliverySupplyChainEvent"), "ram:ActualDeliveryCISupplyChainEvent");
xml=xml.replaceAll(Pattern.quote("ram:SpecifiedTradeSettlementPaymentMeans"), "ram:SpecifiedCITradeSettlementPaymentMeans");
xml=xml.replaceAll(Pattern.quote("ram:PayeePartyCreditorFinancialAccount"), "ram:PayeePartyCICreditorFinancialAccount");
xml=xml.replaceAll(Pattern.quote("ram:PayeeSpecifiedCreditorFinancialInstitution"), "ram:PayeeSpecifiedCICreditorFinancialInstitution");
xml=xml.replaceAll(Pattern.quote("ram:ApplicableTradeTax"), "ram:ApplicableCITradeTax");
xml=xml.replaceAll(Pattern.quote("ram:ApplicablePercent"), "ram:RateApplicablePercent");
xml=xml.replaceAll(Pattern.quote("ram:PostalTradeAddress"), "ram:PostalCITradeAddress");
xml=xml.replaceAll(Pattern.quote("ram:SpecifiedTaxRegistration"), "ram:SpecifiedCITaxRegistration");
xml=xml.replaceAll(Pattern.quote("ram:PostalTradeAddress"), "ram:PostalCITradeAddress");
xml=xml.replaceAll(Pattern.quote("ram:SpecifiedTradeSettlementMonetarySummation"), "ram:SpecifiedCITradeSettlementMonetarySummation");
xml=xml.replaceAll(Pattern.quote("ram:SpecifiedTradePaymentTerms"), "ram:SpecifiedCITradePaymentTerms");
xml=xml.replaceAll(Pattern.quote("ram:SpecifiedSupplyChainTradeAgreement"), "ram:SpecifiedCIILSupplyChainTradeAgreement");
xml=xml.replaceAll(Pattern.quote("ram:GrossPriceProductTradePrice"), "ram:GrossPriceProductCITradePrice");
xml=xml.replaceAll(Pattern.quote("ram:NetPriceProductTradePrice"), "ram:NetPriceProductCITradePrice");
// xml=xml.replaceAll("\\<ram:TestIndicator.*\\/ram:TestIndicator>", "");
//remove manually for the time being: xml=xml.replaceAll("ram:TestIndicator>(.*?)/ram:TestIndicator>", "");
// one ram:SpecifiedCIILTradeSettlementMonetarySummation will have to be ram:SpecifiedCIIHTradeSettlementMonetarySummation afterwards
// entfernen <ram:TestIndicator><udt:Indicator>true</udt:Indicator></ram:TestIndicator><!-- Im Echtbetrieb muss der TestIndicator entweder vollständig entfallen oder auf false stehen. -->
// xmlns:rsm="urn:ferd:CrossIndustryDocument:invoice:1p0"
Files.write(Paths.get("./ZUGFeRD-2-invoice.xml"), xml.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Written to ZUGFeRD-2-invoice.xml");
} }
} }
} }