Facturx (Facturx v0.3.0)

Copy Markdown View Source

Factur-X / ZUGFeRD hybrid e-invoices in pure Elixir.

A Factur-X invoice is a PDF/A-3 document with a machine-readable CII XML (EN 16931) embedded inside it. This module is the public facade; the work is split across:

See docs/adr/0001-perimetre-et-architecture.md for scope decisions.

Summary

Types

Factur-X / ZUGFeRD conformance profiles, from leanest to richest.

Functions

Build a CII XML binary from an Facturx.Invoice struct.

The invoicing framework codes (BT-23) accepted by the French mandate.

Extract the embedded CII XML (and metadata) from a Factur-X PDF.

Build a Factur-X PDF: embed the CII XML for invoice into a PDF/A-3.

Parse a CII XML binary into an Facturx.Invoice struct.

The supported Factur-X profiles.

Validate CII XML against the EN 16931 Schematron (business rules).

Validate CII XML against the EN 16931 XSD (structure/types).

The VAT point date codes (BT-8) allowed by EN 16931 in CII syntax.

Types

profile()

@type profile() :: :minimum | :basic_wl | :basic | :en16931 | :extended

Factur-X / ZUGFeRD conformance profiles, from leanest to richest.

Functions

build(invoice, opts \\ [])

@spec build(
  Facturx.Invoice.t(),
  keyword()
) :: {:ok, binary()} | {:error, term()}

Build a CII XML binary from an Facturx.Invoice struct.

business_processes()

@spec business_processes() :: [String.t()]

The invoicing framework codes (BT-23) accepted by the French mandate.

B1/S1/M1  goods / services / mixed
B2/S2/M2  same, already paid
B4/S4/M4  same, final invoice after a down payment
S5        services, filed by a subcontractor
S6        services, filed by a co-contractor
B7/S7     goods / services already e-reported (VAT already collected)

extract(pdf)

@spec extract(binary()) ::
  {:ok, %{xml: binary(), profile: profile() | nil, filename: String.t()}}
  | {:error, term()}

Extract the embedded CII XML (and metadata) from a Factur-X PDF.

generate(pdf_a3, invoice_or_xml, opts \\ [])

@spec generate(binary(), Facturx.Invoice.t() | binary(), keyword()) ::
  {:ok, binary()} | {:error, term()}

Build a Factur-X PDF: embed the CII XML for invoice into a PDF/A-3.

pdf_a3 must already be a valid PDF/A-3 (the visual invoice). Pass either an Facturx.Invoice struct or a ready CII XML binary as the payload.

parse(xml)

@spec parse(binary()) :: {:ok, Facturx.Invoice.t()} | {:error, term()}

Parse a CII XML binary into an Facturx.Invoice struct.

profiles()

@spec profiles() :: [profile()]

The supported Factur-X profiles.

validate(xml, opts \\ [])

@spec validate(
  binary(),
  keyword()
) :: {:ok, :valid} | {:error, {:invalid, [map()]}} | {:error, term()}

Validate CII XML against the EN 16931 Schematron (business rules).

Optional: requires a reachable Saxon endpoint (:endpoint opt) and the req dependency. See Facturx.Validate.

validate_xsd(xml, opts \\ [])

@spec validate_xsd(
  binary(),
  keyword()
) :: {:ok, :valid} | {:error, {:invalid, [String.t()]}} | {:error, term()}

Validate CII XML against the EN 16931 XSD (structure/types).

Pure Elixir, in-process (OTP :xmerl_xsd) — no external tool. See Facturx.XSD.

vat_point_date_codes()

@spec vat_point_date_codes() :: [String.t()]

The VAT point date codes (BT-8) allowed by EN 16931 in CII syntax.

"5"   date of invoice    VAT due on invoicing ("TVA sur les débits")
"29"  delivery date      VAT due on delivery (goods)
"72"  date of payment    VAT due on collection ("à l'encaissement")

Unlike BT-23, this list is imposed by the standard (not by France), so it is always enforced.