Artigo Técnico

Faturas Eletrónicas ZUGFeRD e Factur-X em Delphi com o HotPDF

O HotPDF permite gerar, detetar e validar faturas eletrónicas ZUGFeRD e Factur-X a partir de Delphi e C++Builder. O método AddFacturXAssociatedFile integra o ficheiro XML da fatura (no padrão EN 16931) num contentor PDF/A-3; DetectFacturXInvoice identifica faturas híbridas recebidas; e HPDFValidateEInvoice executa a validação das regras de negócio Schematron EN 16931 sobre o XML incorporado. Este artigo detalha estes três passos, clarificando os limites do motor de validação

A necessidade destas operações é frequente: a Alemanha e a França estão a implementar a faturação eletrónica estruturada obrigatória para transações B2B internas, convergindo os regulamentos para o mesmo modelo híbrido: a fatura em PDF emitida pelo ERP deve conter um ficheiro XML equivalente legível por máquina. Aplicações de contabilidade ou ERP em Delphi que geram faturas em PDF simples enfrentam prazos estritos para migrar para Factur-X ou ZUGFeRD, cuja diferença é meramente comercial, tratando-se do mesmo padrão franco-alemão publicado sob duas marcas

O que define um PDF como fatura Factur-X válida?

Uma fatura Factur-X válida consiste num ficheiro PDF/A-3 (ISO 19005-3) que incorpora exatamente um XML de faturação estruturado como ficheiro associado, referenciado no catálogo e declarado nos metadados XMP. Três camadas devem estar em conformidade: em primeiro lugar, o contentor deve respeitar o perfil PDF/A-3 (que, ao contrário de PDF/A-1 e PDF/A-2, suporta anexos de qualquer tipo); em segundo lugar, o XML da fatura (nomeado factur-x.xml ou xrechnung.xml na variante alemã XRechnung) deve estar registado no array /AF do catálogo e na árvore /Names /EmbeddedFiles, contendo o atributo AFRelationship com a definição Alternative (indicando representação equivalente à fatura visualizada); em terceiro lugar, o esquema de extensão XMP da Factur-X deve listar o anexo, o nível de conformidade e o tipo de documento, permitindo ao destinatário classificar a fatura sem processar o XML

Os dados do XML respeitam o modelo semântico EN 16931 (Norma Europeia que define a estrutura de dados da fatura: adquirente, fornecedor, itens, IVA e total a pagar, cada um com um identificador de termo de negócio, como BT-1 para o número da fatura, BT-5 para a divisa, etc.). A validação decorre em duas camadas: a validação de esquema (XML schema validation), que confirma a estrutura do documento CII; e as regras de negócio Schematron, que validam a coerência dos dados (como verificar se a regra BR-CO-15 se cumpre e se o total cobrado corresponde à soma líquida mais o IVA, ou se os termos obrigatórios do perfil estão presentes). Um ficheiro que cumpra o esquema pode ser uma fatura inválida perante as regras de negócio, razão pela qual existe a validação Schematron

Por que razão o ZUGFeRD 2.5 não exige um contentor diferente

O ZUGFeRD 2.5 não introduz alterações ao nível do contentor PDF: os URNs de referência, o esquema XMP e o token de versão são idênticos aos de ZUGFeRD 2.3 e Factur-X 1.0. Esta particularidade costuma surpreender: a especificação Factur-X 1.09 declara explicitamente que a versão no URI do esquema de extensão PDF/A é independente da versão do XML da fatura, mantendo-se a versão das instâncias Factur-X em 1.0 (tanto na propriedade XMP fx:Version quanto no termo BT-24 de factur-x.xml). As amostras oficiais do ZUGFeRD 2.5 confirmam-no: todos os ficheiros incorporam factur-x.xml sob a referência urn:factur-x.eu:1p0 com a versão 1.0. As novidades da versão 2.5 restringem-se ao modelo de dados XML (novos elementos como sub-linhas e lotes), camada esta que compete à sua aplicação estruturar e não à biblioteca PDF gerir

O HotPDF implementa esta lógica nativamente: o método AddFacturXAssociatedFile aceita o argumento Version e normaliza-o via HPDFFacturXNormalizeVersion ao gravar a especificação XMP, pelo que argumentos como 2p5 geram o token correto em vez de gravar uma versão XMP incompatível com os validadores. O processo de deteção trata o valor como equivalente, assegurando a simetria. Se um utilitário referir a gravação de um contentor específico para ZUGFeRD 2.5, saiba que a especificação oficial o desmente

Incorporar o XML de faturação em Delphi

O método THotPDF.AddFacturXAssociatedFile converte o fluxo de escrita PDF/A-3 numa fatura Factur-X numa única chamada: incorpora os bytes do XML como ficheiro associado, regista o ficheiro factur-x.xml no array /AF e na árvore /Names /EmbeddedFiles do catálogo, gerando os metadados XMP correspondentes. A fatura visual é desenhada normalmente na tela (canvas) do HotPDF; o processamento do anexo requer apenas uma linha de código entre BeginDoc e EndDoc

var
  Pdf: THotPDF;
  InvoiceXML, UBLXML: TBytes;
begin
  Pdf := THotPDF.Create(nil);
  try
    Pdf.FileName := 'invoice-2026-0042.pdf';
    Pdf.PDFACompliance := '3B';            // contentor PDF/A-3b
    Pdf.BeginDoc;
    // incorporar o XML de faturação EN 16931 CII como factur-x.xml
    InvoiceXML := BuildInvoiceXML;         // gerado pela camada de negócio da sua aplicação
    Pdf.AddFacturXAssociatedFile(InvoiceXML, 'EN 16931');
    // opcional: associar um fluxo UBL como vista complementar
    UBLXML := BuildUBLXML;
    Pdf.AddUBLSupplementaryFile(UBLXML);   // factur-xubl.xml, Alternative
    // ... desenhar a página visual da fatura aqui ...
    Pdf.EndDoc;
  finally
    Pdf.Free;
  end;
end;

As definições padrão cumprem a especificação: nome factur-x.xml, relação Alternative e versão 1.0. O método AddUBLSupplementaryFile implementa a secção 6.4 de Factur-X 1.09, que possibilita anexar um fluxo UBL homólogo nomeado factur-xubl.xml (com o tipo MIME application/xml e relação Alternative). A ordenação é relevante: a representação UBL constitui uma vista complementar e não a fatura principal, exigindo que o HotPDF a insira apenas após o registo do CII master por AddFacturXAssociatedFile. Certifique-se de que a imagem desenhada e o XML incorporado contêm os mesmos valores (a incoerência entre totais é uma das falhas que o modelo híbrido visa mitigar). Definições adicionais de conformidade PDF/A-3, como perfis de saída e incorporação de fontes, são abordadas no artigo sobre validação PDF/A, PDF/X e PDF/UA em Delphi

Como identificar faturas Factur-X em documentos recebidos?

O método THotPDF.DetectFacturXInvoice suporta o fluxo de receção da aplicação: carrega o ficheiro PDF e reporta se este se enquadra na especificação híbrida, indicando o perfil e os anexos. A chamada devolve o registo THPDFFacturXInvoiceInfo com o nome do XML, o nome e tipo declarados em XMP, a versão, o nível de conformidade, a referência URN e a propriedade AFRelationship. Dois argumentos adicionais reportam vistas complementares: UBLFileName para anexos factur-xubl.xml, e EDIFACTFileName para fluxos EDIFACT (nenhum afeta a deteção, dado que a existência de complementos exige a presença do CII master anterior):

var
  Reader: THotPDF;
  Info: THPDFFacturXInvoiceInfo;
begin
  Reader := THotPDF.Create(nil);
  try
    if Reader.LoadFromFile('incoming-invoice.pdf') <= 0 then
      raise Exception.Create('No pages loaded.');
    if Reader.DetectFacturXInvoice(Info) then
    begin
      Writeln('Invoice XML:    ', string(Info.FileName));
      Writeln('Conformance:    ', string(Info.ConformanceLevel));
      Writeln('Guideline URN:  ', string(Info.GuidelineID));
      Writeln('Relationship:   ', string(Info.AFRelationship));
      if Info.UBLFileName <> '' then
        Writeln('UBL view:       ', string(Info.UBLFileName));
    end
    else
      Writeln('Not a Factur-X / ZUGFeRD hybrid invoice.');
  finally
    Reader.Free;
  end;
end;

O processo de deteção analisa as marcações oficiais de conformidade (a extensão XMP e o registo de ficheiros associados) e não apenas o nome dos anexos. A árvore de objetos expõe os metadados do dicionário Info e XMP para consulta ou retificação, processo este analisado no artigo sobre edição de metadados em PDFs

Regras de negócio e esquemas: a validação EN 16931

O método HPDFValidateEInvoice, disponível na unidade HPDFEInvoiceValidator, executa ambas as camadas de validação: primeiro a estrutura do contentor por ValidateFacturXInvoice e, depois, as regras de negócio Schematron EN 16931 sobre o XML extraído. O HotPDF inclui os cinco perfis de regras Factur-X 1.09 (MINIMUM, BASIC WL, BASIC, EN 16931 e EXTENDED) na pasta Lib/resources/Schematron/, selecionando HPDFSchematronFileForProfile a definição de acordo com o nível de conformidade (associando faturas EN 16931 à definição Factur-X_1.09_EN16931.sch). O método devolve True se a estrutura estiver correta e nenhuma regra de negócio for violada

uses HPDFEInvoiceValidator;

var
  Reader: THotPDF;
  Report: THPDFEInvoiceValidationReport;
  I: Integer;
begin
  Reader := THotPDF.Create(nil);
  try
    Reader.LoadFromFile('incoming-invoice.pdf');
    if HPDFValidateEInvoice(Reader, SchematronDir, Report) then
      Writeln('Container and business rules: OK')
    else
      Writeln('Validation found issues.');
    if Report.BusinessRulesEvaluated then
    begin
      Writeln(Report.BusinessSummary.Evaluated, ' rules evaluated, ',
        Report.BusinessSummary.Skipped, ' skipped (XPath 2.0)');
      for I := 0 to High(Report.BusinessRules) do
        if (not Report.BusinessRules[I].Skipped) and
           (Report.BusinessRules[I].Severity = stsError) then
          Writeln(string(Report.BusinessRules[I].RuleID), ': ',
            string(Report.BusinessRules[I].Message));
    end;
  finally
    Reader.Free;
  end;
end;

Cada registo em BusinessRules contém o identificador da regra (como BR-45, BR-CO-17 e restantes definições da norma EN 16931), o contexto XPath correspondente, a expressão de teste e o nível de erro definido no Schematron. Isto permite identificar o termo incoerente em caso de falha de validação, facilitando o diagnóstico. Aplicações que gerem relatórios de conformidade estruturados para arquivos PDF podem integrar estes resultados no fluxo abordado no artigo sobre automatização de relatórios preflight em PDF

Limitações no motor de validação

O motor Schematron assenta na MSXML do Windows, que suporta XPath 1.0. O ficheiro de regras EN 16931 declara a propriedade queryBinding="xslt2" e contém 424 validações, a maioria das quais recorre a funções de XPath 1.0 (como string-length ou substring-after) executadas nativamente. Uma minoria depende de expressões de XPath 2.0 (como conversões xs:decimal ou a função exists()); o HotPDF analisa a expressão de teste previamente para detetar termos XPath 2.0, marcando as regras correspondentes como Skipped com severidade informativa para evitar leituras incorretas. O registo de resumo detalha as contagens de regras avaliadas e ignoradas. Em versões antigas como o Delphi 7, onde a MSXML não está disponível, a unidade compila um bloco neutro reportando o motor como indisponível sem alterar a validação do contentor; o motor completo exige o Delphi XE2 ou posterior

Outra limitação relevante: a validação bem-sucedida em HPDFValidateEInvoice indica conformidade da estrutura e das regras de negócio avaliadas, não constituindo garantia de conformidade fiscal. Regras alfandegárias nacionais, requisitos de clientes e obrigações jurídicas estão fora do âmbito da biblioteca. Utilize o validador como ferramenta de diagnóstico para evitar a emissão de ficheiros malformados ou detetar inconsistências na receção, execute validadores XPath 2.0 dedicados se exigido no fluxo de homologação e consulte assessores fiscais para validar os dados do negócio. As APIs de anexo, deteção e validação integram o HotPDF Component para Delphi e C++Builder, acompanhado de exemplos de faturação eletrónica cobrindo os perfis ZUGFeRD e Factur-X