OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Blame | Last modification | View Log | RSS feed

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
 * 
 * The contents of this file are subject to the terms of the GNU General Public License Version 3
 * only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
 * copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
 * language governing permissions and limitations under the License.
 * 
 * When distributing the software, include this License Header Notice in each file.
 */
 
 package org.openconcerto.erp.core.supplychain.purchase.importer;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.Namespace;
import org.jdom2.input.SAXBuilder;

import com.lowagie.text.pdf.PRStream;
import com.lowagie.text.pdf.PdfArray;
import com.lowagie.text.pdf.PdfDictionary;
import com.lowagie.text.pdf.PdfName;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfString;

public class FacturXImporter {
    public static final String TYPE_MINIMUM = "urn:factur-x.eu:1p0:minimum";
    public static final String TYPE_BASIC = "urn:cen.eu:en16931:2017:compliant:factur-x.eu:1p0:basic";
    public static final String RSM_NS = "urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100";
    public static final String RAM_NS = "urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100";
    public static final String UDT_NS = "urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100";

    public FacturXImporter() {

    }

    public boolean importFromPDF(File file) throws IOException, JDOMException, ParseException {
        Map<String, byte[]> files = new HashMap<>();

        PdfReader reader = new PdfReader(new FileInputStream(file));
        PdfDictionary root = reader.getCatalog();
        PdfDictionary names = root.getAsDict(PdfName.NAMES); // may be null
        PdfDictionary embeddedFilesDict = names.getAsDict(PdfName.EMBEDDEDFILES); // may be null
        PdfArray embeddedFiles = embeddedFilesDict.getAsArray(PdfName.NAMES); // may be null

        int len = embeddedFiles.size();
        for (int i = 0; i < len; i += 2) {
            PdfString name = embeddedFiles.getAsString(i); // should always be present
            PdfDictionary fileSpec = embeddedFiles.getAsDict(i + 1); // ditto

            PdfDictionary streams = fileSpec.getAsDict(PdfName.EF);
            PRStream stream = null;

            if (streams.contains(PdfName.UF))
                stream = (PRStream) streams.getAsStream(PdfName.UF);
            else
                stream = (PRStream) streams.getAsStream(PdfName.F); // Default stream for backwards
                                                                    // compatibility

            if (stream != null) {
                files.put(name.toUnicodeString(), PdfReader.getStreamBytes((PRStream) stream));
            }
        }

        if (!files.containsKey("factur-x.xml")) {
            return false;
        }
        SAXBuilder builder = new SAXBuilder();

        Namespace nsRMS = Namespace.getNamespace(RSM_NS);
        Namespace nsRAM = Namespace.getNamespace(RAM_NS);
        Namespace nsUDT = Namespace.getNamespace(UDT_NS);

        log(new String(files.get("factur-x.xml")));

        Document document = (Document) builder.build(new ByteArrayInputStream(files.get("factur-x.xml")));
        Element rootNode = document.getRootElement();

        Element exchangedDocumentContext = rootNode.getChild("ExchangedDocumentContext", nsRMS);
        Element guidelineSpecifiedDocumentContextParameter = exchangedDocumentContext.getChild("GuidelineSpecifiedDocumentContextParameter", nsRAM);
        //
        String type = guidelineSpecifiedDocumentContextParameter.getChildText("ID", nsRAM);
        log("type de FacturX : " + type);

        Element exchangedDocument = rootNode.getChild("ExchangedDocument", nsRMS);
        String numeroFacture = exchangedDocument.getChildText("ID", nsRAM);
        log("numéro de facture : " + numeroFacture);
        // Type de facture
        // 380 : Facture commerciale
        // 381 : Avoir (note de crédit)
        // 384 : Facture rectificative
        // 386 : Facture d'acompte
        String typeFacture = exchangedDocument.getChildText("TypeCode", nsRAM);
        log("type de facture : " + typeFacture);

        Element dateTimeString = exchangedDocument.getChild("IssueDateTime", nsRAM).getChild("DateTimeString", nsUDT);
        if (!dateTimeString.getAttributeValue("format").equals("102")) {
            throw new IllegalArgumentException("invalid date format : " + dateTimeString.getAttributeValue("format"));
        }
        String txtDateTimeString = dateTimeString.getText();
        SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd");
        Date dateFacture = df.parse(txtDateTimeString);
        log("date de facture : " + dateFacture);
        String commentaire = "";
        if (exchangedDocument.getChild("IncludedNote", nsRAM) != null && exchangedDocument.getChild("IncludedNote").getChild("Content", nsRAM) != null) {
            commentaire = exchangedDocument.getChild("IncludedNote", nsRAM).getChildText("Content", nsRAM);
        }
        log("commentaire : " + commentaire);
        //
        final Element supplyChainTradeTransaction = rootNode.getChild("SupplyChainTradeTransaction", nsRMS);

        Element applicableHeaderTradeAgreement = supplyChainTradeTransaction.getChild("ApplicableHeaderTradeAgreement", nsRAM);
        Element sellerTradeParty = applicableHeaderTradeAgreement.getChild("SellerTradeParty", nsRAM);
        final String nomFournisseur = sellerTradeParty.getChildText("Name", nsRAM);
        log("nom du fournisseur : " + nomFournisseur);
        Element specifiedLegalOrganization = sellerTradeParty.getChild("SpecifiedLegalOrganization", nsRAM);
        String siretFournisseur = specifiedLegalOrganization.getChildText("ID", nsRAM);
        log("SIRET du fournisseur : " + siretFournisseur);

        Element postalTradeAddress = sellerTradeParty.getChild("PostalTradeAddress", nsRAM);
        String codePays = postalTradeAddress.getChildText("CountryID", nsRAM);
        log("Code pays du fournisseur : " + codePays);

        Element specifiedTaxRegistration = sellerTradeParty.getChild("SpecifiedTaxRegistration", nsRAM);
        String tvaFournisseur = specifiedTaxRegistration.getChildText("ID", nsRAM);
        log("TVA du fournisseur : " + tvaFournisseur);

        //
        // Element applicableHeaderTradeDelivery =
        // supplyChainTradeTransaction.getChild("ApplicableHeaderTradeDelivery", nsRAM);

        //
        Element applicableHeaderTradeSettlement = supplyChainTradeTransaction.getChild("ApplicableHeaderTradeSettlement", nsRAM);
        String codeDevise = applicableHeaderTradeSettlement.getChildText("InvoiceCurrencyCode", nsRAM);
        log("code devise : " + codeDevise);

        Element specifiedTradeSettlementHeaderMonetarySummation = applicableHeaderTradeSettlement.getChild("SpecifiedTradeSettlementHeaderMonetarySummation", nsRAM);
        BigDecimal totalHT = new BigDecimal(specifiedTradeSettlementHeaderMonetarySummation.getChildText("TaxBasisTotalAmount", nsRAM));
        BigDecimal totalTax = new BigDecimal(specifiedTradeSettlementHeaderMonetarySummation.getChildText("TaxTotalAmount", nsRAM));
        BigDecimal totalTTC = new BigDecimal(specifiedTradeSettlementHeaderMonetarySummation.getChildText("GrandTotalAmount", nsRAM));
        BigDecimal totalNetPayer = new BigDecimal(specifiedTradeSettlementHeaderMonetarySummation.getChildText("DuePayableAmount", nsRAM));
        log("total HT  : " + totalHT);
        log("total TVA : " + totalTax);
        log("total TTC : " + totalTTC);
        log("total à payer : " + totalNetPayer);
        return true;

    }

    private void log(String string) {
        System.err.println(string);
    }

    public static void main(String[] args) throws Exception {
        FacturXImporter i = new FacturXImporter();
        i.importFromPDF(new File("test/FacturX/Facture_FR_MINIMUM.pdf"));

    }
}