Cross Industry Invoice (CII) XML — build and parse (pure Elixir, via Saxy).
Maps between Facturx.Invoice and the EN 16931 CII vocabulary
(rsm:CrossIndustryInvoice, ram:*, udt:*). Element order follows the CII
schema so the output validates.
Summary
Functions
@spec build( Facturx.Invoice.t(), keyword() ) :: {:ok, binary()} | {:error, term()}
Build the CII XML for invoice.
Options
:profile— overridesinvoice.profile.:validate_business_process— check BT-23 (:business_process) againstFacturx.business_processes/0, returning{:error, {:invalid_business_process, code}}. Defaults tofalse, because that list is the French one whereas BT-23 is an EN 16931 term whose values are not restricted (Peppol usesurn:fdc:peppol.eu:…, Chorus Pro usedA1/A2).:validate_vat_point_date— check BT-8 (:tax_due_date_type_code, or a per-entry:due_date_type_code) againstFacturx.vat_point_date_codes/0, returning{:error, {:invalid_vat_point_date_code, code}}. Defaults totrue, the other way round, because this list is imposed by EN 16931 itself (rule BR-CL-06): a value outside it is invalid in CII whatever the jurisdiction.
Both accept a per-call value or a default from the application environment, the option winning:
config :facturx, Facturx.CII, validate_business_process: trueRebuilding third-party documents
parse/1 validates nothing, so a document you received may carry codes these
checks reject — a BT-8 of 3/35/432 (the UBL values) is common in
UBL→CII conversions. build/2 on such a struct fails by design; pass
validate_vat_point_date: false to reproduce it as-is.
Notes
nil and "" are both treated as absent and emit no element. A
:tax_due_date_type_code with an empty :tax_breakdown has nowhere to go and
returns {:error, {:vat_point_date_unemittable, code}} rather than being
dropped silently.
@spec parse(binary()) :: {:ok, Facturx.Invoice.t()} | {:error, term()}
Parse a CII XML binary into an Facturx.Invoice.