einvoice

package module
v0.0.20 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 28, 2025 License: BSD-3-Clause Imports: 13 Imported by: 0

README

Go Reference Go Report Card Releases

einvoice - a Go library to read, write and verify electronic invoices

Work in progress

This library will be used to read, write and verify electronic invoices (XML) which conform to the EN 16931 standard.

Installation

go get github.com/speedata/einvoice

Usage

invoice, err := einvoice.ParseXMLFile(filename)
if err != nil {
	...
}
// now invoice contains all the information from the XML file
// check for validation violations
err = invoice.Validate()
if err != nil {
	var valErr *einvoice.ValidationError
	if errors.As(err, &valErr) {
		for _, v := range valErr.Violations() {
			fmt.Printf("Rule %s: %s\n", v.Rule, v.Text)
		}
	}
}

Building and validating an invoice programmatically:

import "errors"

func buildInvoice() error {
	inv := &einvoice.Invoice{
		InvoiceNumber: "INV-001",
		// ... set all required fields
	}

	// Validate before writing
	if err := inv.Validate(); err != nil {
		var valErr *einvoice.ValidationError
		if errors.As(err, &valErr) {
			for _, v := range valErr.Violations() {
				fmt.Printf("Rule %s: %s\n", v.Rule, v.Text)
			}
		}
		return err
	}

	return inv.Write(os.Stdout)
}

Round-trip: parsing and writing back:

func dothings() error {
	inv, err := einvoice.ParseXMLFile("...")
	if err != nil {
		return err
	}

	// Write back in the same format (CII or UBL)
	return inv.Write(os.Stdout)
}
Intelligent Validation with Auto-Detection

The Validate() method automatically detects and applies the appropriate validation rules:

  • EN 16931 Core Rules: Always validated for all invoices
  • PEPPOL BIS Billing 3.0: Auto-detected based on specification identifier (BT-24)
  • Country-Specific Rules: Auto-detected based on seller country (future: DK, IT, NL, NO, SE)

Example of a PEPPOL invoice being automatically validated:

inv := &einvoice.Invoice{
	GuidelineSpecifiedDocumentContextParameter: "urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0",
	BPSpecifiedDocumentContextParameter: "urn:fdc:peppol.eu:2017:poacc:billing:01:1.0",
	// ... other fields
}

// Automatically validates both EN 16931 AND PEPPOL rules
if err := inv.Validate(); err != nil {
	// Handle validation errors
}

No need to call separate validation methods - Validate() handles everything automatically!

There is a dedicated example in the documentation.

Command Line Tool

A CLI tool is available for validating invoices from the command line.

Installation
go install github.com/speedata/einvoice/cmd/einvoice@latest
Usage

Validate an invoice and display violations in human-readable format:

einvoice validate invoice.xml

Output validation results as JSON (useful for automation and CI/CD):

einvoice validate --format json invoice.xml
Exit Codes
  • 0 - Invoice is valid (no violations)
  • 1 - Error occurred (file not found, parse error, etc.)
  • 2 - Invoice has validation violations

These exit codes make it easy to integrate the validator into shell scripts and CI/CD pipelines:

if einvoice validate invoice.xml; then
    echo "Invoice is valid!"
else
    echo "Validation failed"
fi

Current status

  • Reading and writing of EN 16931 invoices in both formats:
    • ZUGFeRD/Factur-X (CII format)
    • UBL 2.1 (Invoice and CreditNote)
  • Intelligent validation with auto-detection:
    • EN 16931 Core Rules: BR-1 to BR-65, BR-CO-, BR-DEC-
    • VAT Category Rules: BR-S-, BR-AE-, BR-E-, BR-Z-, BR-G-, BR-IC-, BR-IG-, BR-IP-, BR-O-*
    • PEPPOL BIS Billing 3.0: Auto-detected and validated (PEPPOL-EN16931-R*)
    • Single Validate() method handles all rule sets automatically
  • XML output for all ZUGFeRD profiles (Minimum, BasicWL, Basic, EN16931, Extended, XRechnung)
  • UBL 2.1 Invoice and CreditNote output with full EN 16931 compliance
  • Profile detection based on specification identifier URN (BT-24)
  • Format auto-detection when parsing (automatically recognizes CII or UBL)
  • Round-trip support: parse and write back in the same format

Contributing

We welcome contributions! Please see CONTRIBUTING.md for:

  • Development setup and prerequisites
  • Running tests and checking coverage
  • Code style and conventions
  • Pull request process
  • How to work with test fixtures

Test Fixtures

Test fixtures are organized by profile and format in the testdata/ directory. See testdata/README.md for:

  • Directory structure and organization
  • Fixture sources and provenance (from official EN 16931 and PEPPOL test suites)
  • How to add new fixtures
  • Usage patterns in tests

Documentation

Index

Examples

Constants

View Source
const (
	// EAS0002 is SIRENE - French business registry system identifier.
	EAS0002 = "0002"

	// EAS0007 is Organisationsnummer - Swedish legal entity identifier.
	EAS0007 = "0007"

	// EAS0009 is SIRET-CODE - French establishment identifier.
	EAS0009 = "0009"

	// EAS0037 is LY-tunnus - Finnish organization identifier.
	EAS0037 = "0037"

	// EAS0060 is Data Universal Numbering System (D-U-N-S) Number.
	// Widely used international business identifier (9 digits).
	EAS0060 = "0060"

	// EAS0088 is EAN Location Code / Global Location Number (GLN).
	// Used for identifying parties and locations in supply chains (13 digits).
	EAS0088 = "0088"

	// EAS0096 is Danish CVR (Central Business Register) number.
	EAS0096 = "0096"

	// EAS0130 is Global Legal Entity Identifier (LEI).
	// ISO 17442 standard identifier for legal entities (20 alphanumeric characters).
	EAS0130 = "0130"

	// EAS0135 is Swiss Business Identification Number (UIDB).
	// Also known as Enterprise Identification Number (IDI/IDE/IDI).
	EAS0135 = "0135"

	// EAS0183 is the older code for Swiss Business Identification Number (UIDB).
	// Deprecated in favor of EAS0135, but still in use for compatibility.
	EAS0183 = "0183"

	// EAS0184 is Dutch Chamber of Commerce number (KvK).
	EAS0184 = "0184"

	// EAS0188 is Belgian Crossroad Bank of Enterprises (CBE/KBO) number.
	EAS0188 = "0188"

	// EAS0190 is Norwegian Organization Number (Organisasjonsnummer).
	EAS0190 = "0190"

	// EAS0192 is German Leitweg-ID for routing to German public entities.
	EAS0192 = "0192"

	// EAS0195 is Singapore Nationwide E-Invoice Framework (InvoiceNow) identifier.
	EAS0195 = "0195"

	// EAS0196 is Icelandic national identifier (Kennitala).
	EAS0196 = "0196"

	// EAS0198 is Irish VAT registration number.
	EAS0198 = "0198"

	// EAS0204 is Portuguese VAT registration number (NIPC).
	EAS0204 = "0204"

	// EAS0208 is Belgian VAT registration number.
	EAS0208 = "0208"

	// EAS0209 is Spanish VAT registration number (NIF).
	EAS0209 = "0209"

	// EAS0210 is Italian VAT registration number (Partita IVA).
	EAS0210 = "0210"

	// EAS0211 is Dutch VAT registration number.
	EAS0211 = "0211"

	// EAS0212 is Norwegian VAT registration number (MVA).
	EAS0212 = "0212"

	// EAS0213 is Swiss VAT registration number (MWST/TVA/IVA).
	EAS0213 = "0213"

	// EAS9901 is Danish NEMHANDELSSYSTEM identifier (NemHandel).
	EAS9901 = "9901"

	// EAS9906 is Italian Codice Fiscale (tax code for individuals and entities).
	EAS9906 = "9906"

	// EAS9907 is French CHORUS Pro identifier.
	EAS9907 = "9907"

	// EAS9910 is Hungarian VAT registration number.
	EAS9910 = "9910"

	// EAS9913 is Austrian Ergänzungsregister für sonstige Betroffene (ERsB) number.
	EAS9913 = "9913"

	// EAS9914 is Austrian Firmenregister (FN) - company register number.
	EAS9914 = "9914"

	// EAS9915 is Austrian Umsatzsteueridentifikationsnummer (UID) - VAT number.
	EAS9915 = "9915"

	// EAS9918 is Latvian VAT registration number.
	EAS9918 = "9918"

	// EAS9919 is Maltese VAT registration number.
	EAS9919 = "9919"

	// EAS9920 is Slovenian VAT registration number.
	EAS9920 = "9920"

	// EAS9922 is Croatian VAT registration number (OIB).
	EAS9922 = "9922"

	// EAS9923 is Luxembourgish VAT registration number.
	EAS9923 = "9923"

	// EAS9925 is United Kingdom VAT registration number.
	EAS9925 = "9925"

	// EAS9926 is Bosnia and Herzegovina VAT registration number.
	EAS9926 = "9926"

	// EAS9927 is EU VAT registration number (generic EU VAT).
	EAS9927 = "9927"

	// EAS9928 is Belgian Crossroad Bank of Social Security number (CBSS/KSZ).
	EAS9928 = "9928"

	// EAS9929 is French SIRENE - INSEE identifier (alternative to 0002).
	EAS9929 = "9929"

	// EAS9930 is German Umsatzsteuernummer (VAT number).
	EAS9930 = "9930"

	// EAS9931 is Estonian VAT registration number.
	EAS9931 = "9931"

	// EAS9933 is Finnish Organization Identifier (Y-tunnus).
	EAS9933 = "9933"

	// EAS9934 is Swedish Organization Number (Organisationsnummer).
	EAS9934 = "9934"

	// EAS9935 is Austrian Government Agency identifier (GovAgency).
	EAS9935 = "9935"

	// EAS9936 is Norwegian Public Sector identifier.
	EAS9936 = "9936"

	// EAS9937 is Dutch Overheid identifier (Government).
	EAS9937 = "9937"

	// EAS9938 is Welsh public sector identifier.
	EAS9938 = "9938"

	// EAS9939 is Cypriot VAT registration number.
	EAS9939 = "9939"

	// EAS9940 is Danish CVR-nummer (Central Business Register).
	EAS9940 = "9940"

	// EAS9941 is Italian Sistema di Interscambio (SDI) identifier.
	// Used for the Italian electronic invoicing system.
	EAS9941 = "9941"

	// EAS9942 is German Leitweg-ID (routing identifier for public entities).
	EAS9942 = "9942"

	// EAS9943 is Estonian e-Delivery identifier.
	EAS9943 = "9943"

	// EAS9944 is Netherlands PEPPOL identifier.
	EAS9944 = "9944"

	// EAS9945 is Polish REGON (National Business Registry Number).
	EAS9945 = "9945"

	// EAS9946 is Italian SFE (Sistema Fatturazione Elettronica) identifier.
	EAS9946 = "9946"

	// EAS9947 is Romanian VAT registration number.
	EAS9947 = "9947"

	// EAS9948 is German Steuernummer (tax number).
	EAS9948 = "9948"

	// EAS9949 is Greek VAT registration number.
	EAS9949 = "9949"

	// EAS9950 is Spanish Código de Identificación Fiscal (CIF).
	EAS9950 = "9950"

	// EAS9951 is Portuguese NIPC (Número de Identificação de Pessoa Coletiva).
	EAS9951 = "9951"

	// EAS9952 is Hungarian Adószám (Tax Number).
	EAS9952 = "9952"

	// EAS9953 is Bulgarian VAT registration number.
	EAS9953 = "9953"

	// EAS9955 is Czech VAT registration number (DIČ).
	EAS9955 = "9955"

	// EAS9956 is Latvian Pievienotās vērtības nodokļa (PVN) reģistrācijas numurs.
	EAS9956 = "9956"

	// EAS9957 is French SIRET number (alternative to 0009).
	EAS9957 = "9957"

	// EAS9958 is German Vergabenummer (procurement identifier).
	EAS9958 = "9958"
)

PEPPOL Electronic Address Scheme (EAS) Codes

These constants represent commonly used Electronic Address Scheme identifiers for BT-34 (Seller electronic address) and BT-49 (Buyer electronic address).

EAS codes identify the scheme that an electronic address identifier is based on. The complete list is maintained by the Digital European Programme and updated twice yearly.

Usage: Set these as the scheme for Party.URIUniversalCommunicationScheme

Reference: https://docs.peppol.eu/poacc/billing/3.0/codelist/eas/ Full list: https://ec.europa.eu/digital-building-blocks (EAS Code List v13+)

View Source
const (
	// SpecFacturXMinimum is the Factur-X Minimum profile (lowest level).
	// Use for basic invoice data without line details.
	// Version: 1.0.7
	SpecFacturXMinimum = "urn:factur-x.eu:1p0:minimum"

	// SpecFacturXBasicWL is the Factur-X Basic WL (Without Lines) profile.
	// Use when invoice totals are needed but line item details are not required.
	// Version: 1.0.7
	SpecFacturXBasicWL = "urn:factur-x.eu:1p0:basicwl"

	// SpecFacturXBasic is the Factur-X Basic profile (EN 16931 subset).
	// This is EN 16931 compliant and includes essential invoice line items.
	// Version: 1.0.7
	SpecFacturXBasic = "urn:cen.eu:en16931:2017#compliant#urn:factur-x.eu:1p0:basic"

	// SpecFacturXBasicAlt is an alternative format for Factur-X Basic profile.
	// Uses colons instead of hash symbols. Some systems accept this variant.
	// Version: 1.0
	SpecFacturXBasicAlt = "urn:cen.eu:en16931:2017:compliant:factur-x.eu:1p0:basic"

	// SpecFacturXExtended is the Factur-X Extended profile (most comprehensive).
	// This is EN 16931 conformant (superset) and includes advanced features.
	// Use for complex invoicing scenarios with all optional data.
	// Version: 1.0.7
	SpecFacturXExtended = "urn:cen.eu:en16931:2017#conformant#urn:factur-x.eu:1p0:extended"
)

Factur-X Specification Identifiers

Factur-X is the French/European standard for electronic invoicing, developed jointly by French and German organizations. It's based on the Cross Industry Invoice (CII) format and provides multiple profile levels.

View Source
const (
	// SpecZUGFeRDMinimum is the ZUGFeRD 2.0 Minimum profile.
	// Equivalent to Factur-X Minimum. German variant.
	// Version: 2.0+
	SpecZUGFeRDMinimum = "urn:zugferd.de:2p0:minimum"

	// SpecZUGFeRDBasic is the ZUGFeRD 2.0 Basic profile (EN 16931 subset).
	// Equivalent to Factur-X Basic. German variant.
	// Version: 2.0+
	SpecZUGFeRDBasic = "urn:cen.eu:en16931:2017#compliant#urn:zugferd.de:2p0:basic"

	// SpecZUGFeRDExtended is the ZUGFeRD 2.0 Extended profile.
	// Equivalent to Factur-X Extended. German variant.
	// Version: 2.0+
	SpecZUGFeRDExtended = "urn:cen.eu:en16931:2017#conformant#urn:zugferd.de:2p0:extended"
)

ZUGFeRD Specification Identifiers

ZUGFeRD is the German standard for electronic invoicing. Version 2.0 and later are aligned with Factur-X. ZUGFeRD 2.x is technically equivalent to Factur-X 1.0.

View Source
const (
	// SpecXRechnung20 is the XRechnung 2.0 specification identifier.
	// Required for German public sector invoicing (B2G).
	// This is EN 16931 compliant with German extensions.
	// Version: 2.0
	SpecXRechnung20 = "urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.0"

	// SpecXRechnung21 is the XRechnung 2.1 specification identifier.
	// Required for German public sector invoicing (B2G).
	// This is EN 16931 compliant with German extensions.
	// Version: 2.1
	SpecXRechnung21 = "urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.1"

	// SpecXRechnung22 is the XRechnung 2.2 specification identifier.
	// Required for German public sector invoicing (B2G).
	// This is EN 16931 compliant with German extensions.
	// Version: 2.2
	SpecXRechnung22 = "urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.2"

	// SpecXRechnung23 is the XRechnung 2.3 specification identifier.
	// Required for German public sector invoicing (B2G).
	// This is EN 16931 compliant with German extensions.
	// Version: 2.3
	SpecXRechnung23 = "urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.3"

	// SpecXRechnung30 is the XRechnung 3.0 specification identifier.
	// Required for German public sector invoicing (B2G).
	// This is EN 16931 compliant with German extensions.
	// Version: 3.0
	SpecXRechnung30 = "urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0"
)

XRechnung Specification Identifiers

XRechnung is the German implementation of EN 16931, required for invoices to German public sector entities. It adds German-specific business rules and extensions to the base EN 16931 standard.

View Source
const (
	// BPPEPPOLBilling01 is the standard PEPPOL BIS Billing 3.0 process (most common).
	// Use this for standard billing invoices and credit notes.
	BPPEPPOLBilling01 = "urn:fdc:peppol.eu:2017:poacc:billing:01:1.0"
)

PEPPOL BIS Billing 3.0 Business Process Identifiers (BT-23)

These constants represent valid ProfileID values for PEPPOL BIS Billing 3.0. The business process identifier specifies the business process context in which the transaction appears, enabling the buyer to process the invoice appropriately.

Reference: PEPPOL-EN16931-R007 requires format: urn:fdc:peppol.eu:2017:poacc:billing:NN:1.0 Documentation: https://docs.peppol.eu/poacc/billing/3.0/

View Source
const (
	// SpecEN16931 is the pure EN 16931:2017 specification.
	// This is the base European standard without any country or domain extensions.
	// Use for standard EN 16931 compliant invoices.
	SpecEN16931 = "urn:cen.eu:en16931:2017"
)

EN 16931 Specification Identifier

EN 16931 is the European standard for electronic invoicing, mandated by the European Directive 2014/55/EU for invoices to public sector buyers.

View Source
const (
	// SpecPEPPOLBilling30 is the PEPPOL BIS Billing 3.0 specification identifier.
	// This is the required value per PEPPOL-EN16931-R004.
	SpecPEPPOLBilling30 = "urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0"
)

PEPPOL BIS Billing 3.0 Specification Identifiers (BT-24)

These constants represent valid CustomizationID values for PEPPOL BIS Billing 3.0. The specification identifier identifies the technical specification containing the total set of rules regarding semantic content, cardinalities, and business rules.

Reference: PEPPOL-EN16931-R004 requires the exact value below for PEPPOL BIS Billing 3.0 Documentation: https://docs.peppol.eu/poacc/billing/3.0/

Variables

View Source
var ErrUnsupportedSchema = errors.New("unsupported schema")

ErrUnsupportedSchema is returned when the library does not recognize the schema.

View Source
var ErrWrite = errors.New("creating the XML failed")

Functions

func GetProfileName added in v0.0.14

func GetProfileName(urn string) string

GetProfileName returns a human-readable name for a profile URN. This is useful for display purposes and user interfaces.

Returns the profile name (e.g., "Factur-X Basic", "XRechnung 3.0") or "Unknown" if the URN is not recognized.

func IsProfileURN added in v0.0.14

func IsProfileURN(urn string) bool

IsProfileURN checks if the given string is a recognized profile specification URN. This helper function can validate user input or configuration values.

Returns true if the URN matches any known profile specification identifier.

func ValidateBusinessProcessID added in v0.0.14

func ValidateBusinessProcessID(id string) error

ValidateBusinessProcessID validates that a business process identifier (BT-23) conforms to the PEPPOL-EN16931-R007 format requirement.

The format must be: urn:fdc:peppol.eu:2017:poacc:billing:NN:1.0 where NN is a two-digit process number (e.g., "01" for standard billing).

Returns nil if valid, error otherwise.

func ValidateEASCode added in v0.0.14

func ValidateEASCode(code string) error

ValidateEASCode validates that an Electronic Address Scheme code is in the correct 4-digit format (e.g., "0088", "9901").

Note: This only validates the format, not whether the code is registered in the official EAS code list. For the complete list, see: https://docs.peppol.eu/poacc/billing/3.0/codelist/eas/

Returns nil if valid, error otherwise.

func ValidatePEPPOLSpecificationID added in v0.0.14

func ValidatePEPPOLSpecificationID(id string) error

ValidatePEPPOLSpecificationID validates that a specification identifier (BT-24) matches the PEPPOL BIS Billing 3.0 requirement (PEPPOL-EN16931-R004).

This is ONLY required if you need full PEPPOL BIS Billing 3.0 compliance. You can use PEPPOL business process (BT-23) with ANY specification identifier (BT-24).

For full PEPPOL BIS Billing 3.0, the specification identifier must be exactly: urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0

Returns nil if valid, error otherwise.

Types

type AllowanceCharge

type AllowanceCharge struct {
	ChargeIndicator                       bool            // BG-20, BG-21, BG-27, BG-28
	CalculationPercent                    decimal.Decimal // BT-94, BT-101, BT-138, BT-143
	BasisAmount                           decimal.Decimal // BT-93, BT-100, BT-137, BT-142
	ActualAmount                          decimal.Decimal // BT-92, BT-99, BT-136, BT-141
	ReasonCode                            string          // BT-98, BT-105, BT-140, BT-145
	Reason                                string          // BT-97, BT-104, BT-139, BT-144
	CategoryTradeTaxType                  string          // BT-95, BT-102
	CategoryTradeTaxCategoryCode          string          // BT-95, BT-102
	CategoryTradeTaxRateApplicablePercent decimal.Decimal // BT-96, BT-103
}

AllowanceCharge specifies charges and deductions.

type Characteristic

type Characteristic struct {
	Description string // BT-160
	Value       string // BT-161
}

Characteristic add details to a product, BG-32.

type Classification added in v0.0.2

type Classification struct {
	ClassCode     string
	ListID        string
	ListVersionID string
}

Classification specifies a product classification, BT-158.

type CodeDocument added in v0.0.2

type CodeDocument int

CodeDocument contains the UNTDID 1001 document code.

func (CodeDocument) String added in v0.0.2

func (cd CodeDocument) String() string

type CodePartyType added in v0.0.2

type CodePartyType int

CodePartyType distinguishes between seller, buyer, ..

const (
	CUnknownParty CodePartyType = iota
	CSellerParty
	CBuyerParty
	CShipToParty
	CPayeeParty
)

CodePartyType represents the type of the party.

type CodeProfileType added in v0.0.2

type CodeProfileType int

CodeProfileType represents the CII subtype (extended, minimum, ...)

const (
	// CProfileUnknown is the unknown profile, zero value.
	CProfileUnknown CodeProfileType = iota
	// CProfileMinimum urn:factur-x.eu:1p0:minimum.
	CProfileMinimum
	// CProfileBasicWL urn:factur-x.eu:1p0:basicwl.
	CProfileBasicWL
	// CProfileBasic urn:cen.eu:en16931:2017#compliant#urn:factur-x.eu:1p0:basic.
	CProfileBasic
	// CProfileEN16931 (previously Comfort) represents urn:cen.eu:en16931:2017.
	CProfileEN16931
	// CProfileExtended represents the urn:cen.eu:en16931:2017#conformant#urn:factur-x.eu:1p0:extended schema.
	CProfileExtended
	// CProfileXRechnung represents an XRechnung invoice.
	CProfileXRechnung
)

Don't change the order. extended > EN16931 > basic > basicwl > minimum.

func (CodeProfileType) String added in v0.0.2

func (cp CodeProfileType) String() string

func (CodeProfileType) ToProfileName added in v0.0.2

func (cp CodeProfileType) ToProfileName() string

ToProfileName returns the identifier for this profile such as urn:cen.eu:en16931:2017.

type CodeSchemaType added in v0.0.2

type CodeSchemaType int

CodeSchemaType represents the type of the invoice (CII or UBL).

const (
	SchemaTypeUnknown CodeSchemaType = iota // Zero value for programmatically created invoices
	CII                                     // ZUGFeRD/Factur-X (Cross Industry Invoice)
	UBL                                     // Universal Business Language
)

CodeSchemaType is the main XML flavor. Currently only CII is supported.

func (CodeSchemaType) String added in v0.0.2

func (cp CodeSchemaType) String() string

type DefinedTradeContact added in v0.0.6

type DefinedTradeContact struct {
	PersonName     string // BT-41, BT-56
	DepartmentName string // BT-41, BT-56
	EMail          string // BT-43, BT-58
	PhoneNumber    string // BT-44, BT-57

}

DefinedTradeContact represents a person. BG-6, BG-9.

type Document added in v0.0.2

type Document struct {
	IssuerAssignedID       string // BT-17, BT-18, BT-122
	URIID                  string // BT-18, BT-124
	TypeCode               string // BT-17: 50, BT-18: 130  BT-122: 916
	ReferenceTypeCode      string // BT-18
	Name                   string // BT-123
	AttachmentBinaryObject []byte // BT-125
	AttachmentMimeCode     string // BT-125
	AttachmentFilename     string // BT-125
}

Document contains a reference to a document or the document itself.

type GlobalID added in v0.0.2

type GlobalID struct {
	ID     string
	Scheme string
}

GlobalID stores a ISO/EIC 6523 encoded ID.

type Invoice

type Invoice struct {
	GuidelineSpecifiedDocumentContextParameter string                       // BT-24 (Specification identifier URN)
	DespatchAdviceReferencedDocument           string                       // BT-16
	ReceivingAdviceReferencedDocument          string                       // BT-15
	BuyerReference                             string                       // BT-10
	BPSpecifiedDocumentContextParameter        string                       // BT-23
	PayeeTradeParty                            *Party                       // BG-10
	PaymentMeans                               []PaymentMeans               // BG-16
	BillingSpecifiedPeriodStart                time.Time                    // BT-73
	BillingSpecifiedPeriodEnd                  time.Time                    // BT-74
	InvoiceDate                                time.Time                    // BT-2
	CreditorReferenceID                        string                       // BT-90
	PaymentReference                           string                       // BT-83
	TaxCurrencyCode                            string                       // BT-6
	InvoiceCurrencyCode                        string                       // BT-5
	LineTotal                                  decimal.Decimal              // BT-106
	AllowanceTotal                             decimal.Decimal              // BT-107
	ChargeTotal                                decimal.Decimal              // BT-108
	TaxBasisTotal                              decimal.Decimal              // BT-109
	TaxTotalCurrency                           string                       // BT-110
	TaxTotal                                   decimal.Decimal              // BT-110
	TaxTotalAccountingCurrency                 string                       // BT-111
	TaxTotalAccounting                         decimal.Decimal              // BT-111
	GrandTotal                                 decimal.Decimal              // BT-112
	TotalPrepaid                               decimal.Decimal              // BT-113
	RoundingAmount                             decimal.Decimal              // BT-114
	DuePayableAmount                           decimal.Decimal              // BT-115
	Buyer                                      Party                        // BG-7
	SellerTaxRepresentativeTradeParty          *Party                       // BG-11
	SellerOrderReferencedDocument              string                       // BT-14
	BuyerOrderReferencedDocument               string                       // BT-13
	ContractReferencedDocument                 string                       // BT-12
	AdditionalReferencedDocument               []Document                   // BG-24
	SpecifiedProcuringProjectID                string                       // BT-11
	SpecifiedProcuringProjectName              string                       // BT-11
	Seller                                     Party                        // BG-4
	OccurrenceDateTime                         time.Time                    // BT-72
	Notes                                      []Note                       // BG-1
	InvoiceLines                               []InvoiceLine                // BG-25
	InvoiceNumber                              string                       // BT-1
	InvoiceTypeCode                            CodeDocument                 // BT-3
	TradeTaxes                                 []TradeTax                   // BG-23
	SpecifiedTradeAllowanceCharge              []AllowanceCharge            // BG-20, BG-21
	ShipTo                                     *Party                       // BG-13
	SpecifiedTradePaymentTerms                 []SpecifiedTradePaymentTerms // BT-20
	SchemaType                                 CodeSchemaType               // UBL or CII
	InvoiceReferencedDocument                  []ReferencedDocument         // BG-3
	ReceivableSpecifiedTradeAccountingAccount  string                       // BT-19
	// contains filtered or unexported fields
}

Invoice is the main element of the e-invoice.

func ParseReader

func ParseReader(r io.Reader) (*Invoice, error)

ParseReader reads the XML from the reader and auto-detects the format (CII or UBL). It detects the format by examining the root element namespace and routes to the appropriate parser. Each parser handles its own namespace setup.

func ParseXMLFile

func ParseXMLFile(filename string) (*Invoice, error)

ParseXMLFile reads the XML file at filename.

func (*Invoice) IsBasic added in v0.0.14

func (inv *Invoice) IsBasic() bool

IsBasic checks if the invoice uses the Basic profile. URN: urn:cen.eu:en16931:2017#compliant#urn:factur-x.eu:1p0:basic

func (*Invoice) IsBasicWL added in v0.0.14

func (inv *Invoice) IsBasicWL() bool

IsBasicWL checks if the invoice uses the Basic WL (Without Lines) profile. URN: urn:factur-x.eu:1p0:basicwl

func (*Invoice) IsEN16931 added in v0.0.14

func (inv *Invoice) IsEN16931() bool

IsEN16931 checks if the invoice uses the EN 16931 profile. URN: urn:cen.eu:en16931:2017

func (*Invoice) IsExtended added in v0.0.14

func (inv *Invoice) IsExtended() bool

IsExtended checks if the invoice uses the Extended profile. URN: urn:cen.eu:en16931:2017#conformant#urn:factur-x.eu:1p0:extended

func (*Invoice) IsMinimum added in v0.0.14

func (inv *Invoice) IsMinimum() bool

IsMinimum checks if the invoice uses the Minimum profile. URN: urn:factur-x.eu:1p0:minimum or urn:zugferd.de:2p0:minimum

func (*Invoice) IsXRechnung added in v0.0.14

func (inv *Invoice) IsXRechnung() bool

IsXRechnung checks if the invoice uses the XRechnung profile. Supports XRechnung 2.0, 2.1, 2.2, 2.3, and 3.0. URN examples:

  • urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0
  • urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.1

func (*Invoice) MeetsProfileLevel added in v0.0.14

func (inv *Invoice) MeetsProfileLevel(minLevel int) bool

MeetsProfileLevel checks if the invoice meets or exceeds a minimum profile level. This replaces the old Profile enum comparison (inv.Profile >= targetProfile).

Example: inv.MeetsProfileLevel(3) returns true if profile is Basic, EN16931, Extended, or XRechnung

func (*Invoice) ProfileLevel added in v0.0.14

func (inv *Invoice) ProfileLevel() int

ProfileLevel returns an integer representing the profile hierarchy level. Higher numbers indicate more inclusive profiles. This is used by the writer to determine which fields to include.

Levels: 0=Unknown, 1=Minimum, 2=BasicWL, 3=Basic, 4=EN16931/PEPPOL/XRechnung, 5=Extended

func (*Invoice) UpdateApplicableTradeTax added in v0.0.7

func (inv *Invoice) UpdateApplicableTradeTax(exemptReason map[string]string)

UpdateApplicableTradeTax removes the existing trade tax lines in the invoice and re-creates new ones from the line items and document-level allowances/charges. er is a map that contains exemption reasons for each category code. According to BR-45 and category-specific rules (BR-S-8, BR-AE-8, BR-E-8, etc.), the VAT category taxable amount must include: - Sum of invoice line net amounts for that category - Minus document level allowance amounts for that category - Plus document level charge amounts for that category

func (*Invoice) UpdateTotals added in v0.0.7

func (inv *Invoice) UpdateTotals()

UpdateTotals recalculates all monetary totals according to EN 16931 business rules. This function implements the following business rules in calculation order: - BR-CO-10: LineTotal (BT-106) = Sum of all invoice line net amounts (BT-131) - BR-CO-11: AllowanceTotal (BT-107) = Sum of all document level allowance amounts (BT-92) - BR-CO-12: ChargeTotal (BT-108) = Sum of all document level charge amounts (BT-99) - BR-CO-13: TaxBasisTotal (BT-109) = LineTotal - AllowanceTotal + ChargeTotal - BR-CO-15: GrandTotal (BT-112) = TaxBasisTotal + TaxTotal (BT-110) - BR-CO-16: DuePayableAmount (BT-115) = GrandTotal - TotalPrepaid (BT-113) + RoundingAmount (BT-114)

Profile handling: Only recalculate for EN 16931 profiles that support line items. - Level 0 (unknown): Skip - may not follow EN 16931 calculation rules - Level 1 (Minimum): Skip - no line items by design, totals provided directly - Level 2 (BasicWL): Skip - no line items by design, totals provided directly - Level 3+ (Basic, EN16931, Extended, etc.): Calculate - have line items

func (*Invoice) UsesPEPPOLBusinessProcess added in v0.0.14

func (inv *Invoice) UsesPEPPOLBusinessProcess() bool

UsesPEPPOLBusinessProcess checks if an invoice uses a PEPPOL business process (BT-23).

This only checks the business process identifier format, NOT the specification. You can use PEPPOL business process with any specification (Factur-X, EN16931, etc.).

Returns true if BT-23 is set to a valid PEPPOL business process URN.

func (*Invoice) Validate added in v0.0.11

func (inv *Invoice) Validate() error

Validate checks the invoice against applicable business rules with intelligent auto-detection.

The method automatically detects which validation rules to apply based on: - Specification identifier (BT-24) for PEPPOL BIS Billing 3.0 detection - Seller country for country-specific rules (DK, IT, NL, NO, SE)

All invoices are validated against EN 16931 core rules. Additional rules are applied automatically when the invoice metadata indicates they are required.

This method clears any previous violations and performs a fresh validation. Returns a ValidationError if violations exist, nil if invoice is valid.

This method should be called: - After building an invoice programmatically - After modifying invoice data (e.g., after UpdateTotals) - Before writing XML to ensure compliance

Example:

err := inv.Validate()
if err != nil {
    var valErr *ValidationError
    if errors.As(err, &valErr) {
        for _, v := range valErr.Violations() {
            fmt.Printf("Rule %s: %s\n", v.Rule.Code, v.Text)
        }
    }
    return err
}

func (*Invoice) Write added in v0.0.2

func (inv *Invoice) Write(w io.Writer) error

Write writes the invoice as XML to the given writer.

The output format is determined by the SchemaType field:

  • UBL: Outputs UBL 2.1 XML with <Invoice> root (InvoiceTypeCode 380) or <CreditNote> root (InvoiceTypeCode 381)
  • CII or SchemaTypeUnknown: Outputs ZUGFeRD/Factur-X CII format with rsm/ram/udt/qdt namespaces

Programmatically created invoices have SchemaTypeUnknown (zero value) and default to CII format for backwards compatibility.

Write does not perform validation. Consider calling Validate() before Write() to ensure the invoice meets EN 16931 requirements. You should also call UpdateApplicableTradeTax() and UpdateTotals() to calculate monetary values.

Returns ErrUnsupportedSchema if SchemaType is not recognized.

Example for CII format:

inv := &einvoice.Invoice{
	SchemaType: einvoice.CII, // or omit for default
	InvoiceNumber: "INV-001",
	// ... set required fields
}
inv.UpdateApplicableTradeTax(nil)
inv.UpdateTotals()
if err := inv.Validate(); err != nil {
	// handle validation errors
}
err := inv.Write(os.Stdout)

Example for UBL format:

inv := &einvoice.Invoice{
	SchemaType: einvoice.UBL,
	InvoiceNumber: "INV-001",
	InvoiceTypeCode: 380, // 380 = Invoice, 381 = CreditNote
	// ... set required fields
}
inv.UpdateApplicableTradeTax(nil)
inv.UpdateTotals()
err := inv.Write(os.Stdout)
Example
fixedDate, _ := time.Parse("02.01.2006", "31.12.2025")
fourteenDays := time.Hour * 24 * 14
inv := Invoice{
	InvoiceNumber:   "1234",
	InvoiceTypeCode: 380,
	GuidelineSpecifiedDocumentContextParameter: SpecEN16931,
	InvoiceDate:         fixedDate,
	OccurrenceDateTime:  fixedDate.Add(-fourteenDays),
	InvoiceCurrencyCode: "EUR",
	TaxCurrencyCode:     "EUR",
	Notes: []Note{{
		Text: "Some text",
	}},
	Seller: Party{
		Name:              "Company name",
		VATaxRegistration: "DE123456",
		PostalAddress: &PostalAddress{
			Line1:        "Line one",
			Line2:        "Line two",
			City:         "City",
			PostcodeCode: "12345",
			CountryID:    "DE",
		},
		DefinedTradeContact: []DefinedTradeContact{{
			PersonName: "Jon Doe",
			EMail:      "doe@example.com",
		}},
	},
	Buyer: Party{
		Name: "Buyer",
		PostalAddress: &PostalAddress{
			Line1:        "Buyer line 1",
			Line2:        "Buyer line 2",
			City:         "Buyercity",
			PostcodeCode: "33441",
			CountryID:    "FR",
		},
		DefinedTradeContact: []DefinedTradeContact{{
			PersonName: "Buyer Person",
		}},
		VATaxRegistration: "FR4441112",
	},
	PaymentMeans: []PaymentMeans{
		{
			TypeCode:                                      30,
			PayeePartyCreditorFinancialAccountIBAN:        "DE123455958381",
			PayeePartyCreditorFinancialAccountName:        "My own bank",
			PayeeSpecifiedCreditorFinancialInstitutionBIC: "BANKDEFXXX",
		},
	},
	SpecifiedTradePaymentTerms: []SpecifiedTradePaymentTerms{{
		DueDate: fixedDate.Add(fourteenDays),
	}},
	InvoiceLines: []InvoiceLine{
		{
			LineID:                   "1",
			ItemName:                 "Item name one",
			BilledQuantity:           decimal.NewFromFloat(12.5),
			BilledQuantityUnit:       "C62",
			NetPrice:                 decimal.NewFromInt(100),
			TaxRateApplicablePercent: decimal.NewFromInt(19),
			Total:                    decimal.NewFromInt(1250),
			TaxTypeCode:              "VAT",
			TaxCategoryCode:          "S",
		},
		{
			LineID:                   "2",
			ItemName:                 "Item name two",
			BilledQuantity:           decimal.NewFromFloat(2),
			BilledQuantityUnit:       "HUR",
			NetPrice:                 decimal.NewFromInt(200),
			TaxRateApplicablePercent: decimal.NewFromInt(0),
			Total:                    decimal.NewFromInt(400),
			TaxTypeCode:              "VAT",
			TaxCategoryCode:          "AE",
		},
	},
}

inv.UpdateApplicableTradeTax(map[string]string{"AE": "Reason for reverse charge"})
inv.UpdateTotals()
if err := inv.Write(os.Stdout); err != nil {
	panic(err.Error())
}
Output:

<rsm:CrossIndustryInvoice xmlns:rsm="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100" xmlns:qdt="urn:un:unece:uncefact:data:standard:QualifiedDataType:100" xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100">
  <rsm:ExchangedDocumentContext>
    <ram:GuidelineSpecifiedDocumentContextParameter>
      <ram:ID>urn:cen.eu:en16931:2017</ram:ID>
    </ram:GuidelineSpecifiedDocumentContextParameter>
  </rsm:ExchangedDocumentContext>
  <rsm:ExchangedDocument>
    <ram:ID>1234</ram:ID>
    <ram:TypeCode>380</ram:TypeCode>
    <ram:IssueDateTime>
      <udt:DateTimeString format="102">20251231</udt:DateTimeString>
    </ram:IssueDateTime>
    <ram:IncludedNote>
      <ram:Content>Some text</ram:Content>
    </ram:IncludedNote>
  </rsm:ExchangedDocument>
  <rsm:SupplyChainTradeTransaction>
    <ram:IncludedSupplyChainTradeLineItem>
      <ram:AssociatedDocumentLineDocument>
        <ram:LineID>1</ram:LineID>
      </ram:AssociatedDocumentLineDocument>
      <ram:SpecifiedTradeProduct>
        <ram:Name>Item name one</ram:Name>
      </ram:SpecifiedTradeProduct>
      <ram:SpecifiedLineTradeAgreement>
        <ram:NetPriceProductTradePrice>
          <ram:ChargeAmount>100</ram:ChargeAmount>
        </ram:NetPriceProductTradePrice>
      </ram:SpecifiedLineTradeAgreement>
      <ram:SpecifiedLineTradeDelivery>
        <ram:BilledQuantity unitCode="C62">12.5000</ram:BilledQuantity>
      </ram:SpecifiedLineTradeDelivery>
      <ram:SpecifiedLineTradeSettlement>
        <ram:ApplicableTradeTax>
          <ram:TypeCode>VAT</ram:TypeCode>
          <ram:CategoryCode>S</ram:CategoryCode>
          <ram:RateApplicablePercent>19</ram:RateApplicablePercent>
        </ram:ApplicableTradeTax>
        <ram:SpecifiedTradeSettlementLineMonetarySummation>
          <ram:LineTotalAmount>1250.00</ram:LineTotalAmount>
        </ram:SpecifiedTradeSettlementLineMonetarySummation>
      </ram:SpecifiedLineTradeSettlement>
    </ram:IncludedSupplyChainTradeLineItem>
    <ram:IncludedSupplyChainTradeLineItem>
      <ram:AssociatedDocumentLineDocument>
        <ram:LineID>2</ram:LineID>
      </ram:AssociatedDocumentLineDocument>
      <ram:SpecifiedTradeProduct>
        <ram:Name>Item name two</ram:Name>
      </ram:SpecifiedTradeProduct>
      <ram:SpecifiedLineTradeAgreement>
        <ram:NetPriceProductTradePrice>
          <ram:ChargeAmount>200</ram:ChargeAmount>
        </ram:NetPriceProductTradePrice>
      </ram:SpecifiedLineTradeAgreement>
      <ram:SpecifiedLineTradeDelivery>
        <ram:BilledQuantity unitCode="HUR">2.0000</ram:BilledQuantity>
      </ram:SpecifiedLineTradeDelivery>
      <ram:SpecifiedLineTradeSettlement>
        <ram:ApplicableTradeTax>
          <ram:TypeCode>VAT</ram:TypeCode>
          <ram:CategoryCode>AE</ram:CategoryCode>
          <ram:RateApplicablePercent>0</ram:RateApplicablePercent>
        </ram:ApplicableTradeTax>
        <ram:SpecifiedTradeSettlementLineMonetarySummation>
          <ram:LineTotalAmount>400.00</ram:LineTotalAmount>
        </ram:SpecifiedTradeSettlementLineMonetarySummation>
      </ram:SpecifiedLineTradeSettlement>
    </ram:IncludedSupplyChainTradeLineItem>
    <ram:ApplicableHeaderTradeAgreement>
      <ram:SellerTradeParty>
        <ram:Name>Company name</ram:Name>
        <ram:DefinedTradeContact>
          <ram:PersonName>Jon Doe</ram:PersonName>
          <ram:EmailURIUniversalCommunication>
            <ram:URIID>doe@example.com</ram:URIID>
          </ram:EmailURIUniversalCommunication>
        </ram:DefinedTradeContact>
        <ram:PostalTradeAddress>
          <ram:PostcodeCode>12345</ram:PostcodeCode>
          <ram:LineOne>Line one</ram:LineOne>
          <ram:LineTwo>Line two</ram:LineTwo>
          <ram:CityName>City</ram:CityName>
          <ram:CountryID>DE</ram:CountryID>
        </ram:PostalTradeAddress>
        <ram:SpecifiedTaxRegistration>
          <ram:ID schemeID="VA">DE123456</ram:ID>
        </ram:SpecifiedTaxRegistration>
      </ram:SellerTradeParty>
      <ram:BuyerTradeParty>
        <ram:Name>Buyer</ram:Name>
        <ram:DefinedTradeContact>
          <ram:PersonName>Buyer Person</ram:PersonName>
        </ram:DefinedTradeContact>
        <ram:PostalTradeAddress>
          <ram:PostcodeCode>33441</ram:PostcodeCode>
          <ram:LineOne>Buyer line 1</ram:LineOne>
          <ram:LineTwo>Buyer line 2</ram:LineTwo>
          <ram:CityName>Buyercity</ram:CityName>
          <ram:CountryID>FR</ram:CountryID>
        </ram:PostalTradeAddress>
        <ram:SpecifiedTaxRegistration>
          <ram:ID schemeID="VA">FR4441112</ram:ID>
        </ram:SpecifiedTaxRegistration>
      </ram:BuyerTradeParty>
    </ram:ApplicableHeaderTradeAgreement>
    <ram:ApplicableHeaderTradeDelivery>
      <ram:ActualDeliverySupplyChainEvent>
        <ram:OccurrenceDateTime>
          <udt:DateTimeString format="102">20251217</udt:DateTimeString>
        </ram:OccurrenceDateTime>
      </ram:ActualDeliverySupplyChainEvent>
    </ram:ApplicableHeaderTradeDelivery>
    <ram:ApplicableHeaderTradeSettlement>
      <ram:InvoiceCurrencyCode>EUR</ram:InvoiceCurrencyCode>
      <ram:SpecifiedTradeSettlementPaymentMeans>
        <ram:TypeCode>30</ram:TypeCode>
        <ram:PayeePartyCreditorFinancialAccount>
          <ram:IBANID>DE123455958381</ram:IBANID>
          <ram:AccountName>My own bank</ram:AccountName>
        </ram:PayeePartyCreditorFinancialAccount>
        <ram:PayeeSpecifiedCreditorFinancialInstitution>
          <ram:BICID>BANKDEFXXX</ram:BICID>
        </ram:PayeeSpecifiedCreditorFinancialInstitution>
      </ram:SpecifiedTradeSettlementPaymentMeans>
      <ram:ApplicableTradeTax>
        <ram:CalculatedAmount>237.50</ram:CalculatedAmount>
        <ram:TypeCode>VAT</ram:TypeCode>
        <ram:BasisAmount>1250.00</ram:BasisAmount>
        <ram:CategoryCode>S</ram:CategoryCode>
        <ram:RateApplicablePercent>19</ram:RateApplicablePercent>
      </ram:ApplicableTradeTax>
      <ram:ApplicableTradeTax>
        <ram:CalculatedAmount>0.00</ram:CalculatedAmount>
        <ram:TypeCode>VAT</ram:TypeCode>
        <ram:ExemptionReason>Reason for reverse charge</ram:ExemptionReason>
        <ram:BasisAmount>400.00</ram:BasisAmount>
        <ram:CategoryCode>AE</ram:CategoryCode>
        <ram:RateApplicablePercent>0</ram:RateApplicablePercent>
      </ram:ApplicableTradeTax>
      <ram:SpecifiedTradePaymentTerms>
        <ram:DueDateDateTime>
          <udt:DateTimeString format="102">20260114</udt:DateTimeString>
        </ram:DueDateDateTime>
      </ram:SpecifiedTradePaymentTerms>
      <ram:SpecifiedTradeSettlementHeaderMonetarySummation>
        <ram:LineTotalAmount>1650.00</ram:LineTotalAmount>
        <ram:TaxBasisTotalAmount>1650.00</ram:TaxBasisTotalAmount>
        <ram:TaxTotalAmount currencyID="EUR">237.50</ram:TaxTotalAmount>
        <ram:GrandTotalAmount>1887.50</ram:GrandTotalAmount>
        <ram:DuePayableAmount>1887.50</ram:DuePayableAmount>
      </ram:SpecifiedTradeSettlementHeaderMonetarySummation>
    </ram:ApplicableHeaderTradeSettlement>
  </rsm:SupplyChainTradeTransaction>
</rsm:CrossIndustryInvoice>

type InvoiceLine added in v0.0.3

type InvoiceLine struct {
	LineID                                    string            // BT-126
	ArticleNumber                             string            // BT-155 seller assigned ID
	ArticleNumberBuyer                        string            // BT-156 buyer assigned ID
	ItemName                                  string            // BT-153
	AdditionalReferencedDocumentID            string            // BT-128
	AdditionalReferencedDocumentTypeCode      string            // BT-128
	AdditionalReferencedDocumentRefTypeCode   string            // BT-128
	BillingSpecifiedPeriodStart               time.Time         // BT-134
	BillingSpecifiedPeriodEnd                 time.Time         // BT-135
	BuyerOrderReferencedDocument              string            // BT-132
	Note                                      string            // BT-127
	GlobalID                                  string            // BT-157
	GlobalIDType                              string            // BT-157
	Characteristics                           []Characteristic  // BG-32
	ProductClassification                     []Classification  // BT-158, UNTDID 7143
	Description                               string            // BT-154 (optional)
	OriginTradeCountry                        string            // BT-159 (optional) alpha-2 code ISO 3166-1 such as DE, US,...
	ReceivableSpecifiedTradeAccountingAccount string            // BT-133
	GrossPrice                                decimal.Decimal   // BT-148
	BasisQuantity                             decimal.Decimal   // BT-149
	BasisQuantityUnit                         string            // BT-149
	InvoiceLineAllowances                     []AllowanceCharge // BG-27
	InvoiceLineCharges                        []AllowanceCharge // BG-28
	AppliedTradeAllowanceCharge               []AllowanceCharge // BT-147
	NetPrice                                  decimal.Decimal   // BT-146
	NetBilledQuantity                         decimal.Decimal   // BT-149
	NetBilledQuantityUnit                     string            // BT-150
	BilledQuantity                            decimal.Decimal   // BT-129
	BilledQuantityUnit                        string            // BT-130
	TaxTypeCode                               string            // BT-151 must be VAT
	TaxCategoryCode                           string            // BT-151
	TaxRateApplicablePercent                  decimal.Decimal   // BT-152
	Total                                     decimal.Decimal   // BT-131
	// contains filtered or unexported fields
}

InvoiceLine represents one position of items.

type Note added in v0.0.2

type Note struct {
	Text        string // BT-22
	SubjectCode string // BT-21
}

Note contains text and the subject code.

func (Note) String added in v0.0.2

func (n Note) String() string

type Party

type Party struct {
	ID                              []string                    // BT-29, BT-46, BT-60, BT-71
	GlobalID                        []GlobalID                  // BT-29, BT-64, BT-60, BT-71
	Name                            string                      // BT-27, BT-44, BT-59, BT-62, BT-70
	DefinedTradeContact             []DefinedTradeContact       // BG-9
	Description                     string                      // BT-33
	URIUniversalCommunication       string                      // BT-34, BT-49
	URIUniversalCommunicationScheme string                      // BT-34, BT-49
	PostalAddress                   *PostalAddress              // BG-5, BG-8
	SpecifiedLegalOrganization      *SpecifiedLegalOrganization // BT-30, BT-47, BT-61
	VATaxRegistration               string                      // BT-31, BT-48, BT-63
	FCTaxRegistration               string                      // BT-32
}

Party represents buyer and seller.

type PaymentMeans

type PaymentMeans struct {
	TypeCode                                             int    // BT-81
	Information                                          string // BT-82
	PayeePartyCreditorFinancialAccountIBAN               string // BT-84
	PayeePartyCreditorFinancialAccountName               string // BT-85
	PayeePartyCreditorFinancialAccountProprietaryID      string // BT-84
	PayeeSpecifiedCreditorFinancialInstitutionBIC        string // BT-86
	PayerPartyDebtorFinancialAccountIBAN                 string // BT-91
	ApplicableTradeSettlementFinancialCardID             string // BT-87
	ApplicableTradeSettlementFinancialCardCardholderName string // BT-88
	// contains filtered or unexported fields
}

PaymentMeans represents a payment means.

type PostalAddress added in v0.0.3

type PostalAddress struct {
	CountryID              string
	PostcodeCode           string // BT-38, BT-53, BT-67, BT-78
	Line1                  string // BT-35, BT-50, BT-64, BT-75
	Line2                  string // BT-36, BT-51, BT-65, BT-76
	Line3                  string // BT-162, BT-163, BT-164, BT-165
	City                   string // BT-37, BT-52, BT-66, BT-77
	CountrySubDivisionName string // BT-39, BT-54, BT-68, BT-79
}

A PostalAddress belongs to the seller, buyer and some other entities.

type ReferencedDocument added in v0.0.6

type ReferencedDocument struct {
	ID   string    // BT-25
	Date time.Time // BT-26

}

ReferencedDocument links to a previous invoice BG-3.

type SemanticError added in v0.0.3

type SemanticError struct {
	Rule rules.Rule // The business rule that was violated
	Text string     // Human-readable description with actual values
}

SemanticError contains a business rule violation found during validation.

type SpecifiedLegalOrganization added in v0.0.6

type SpecifiedLegalOrganization struct {
	ID                  string //  BT-30, BT-47, BT-61
	Scheme              string // BT-30, BT-61
	TradingBusinessName string // BT-28, BT-45

}

SpecifiedLegalOrganization represents a division BT-30, BT-47, BT-61.

type SpecifiedTradePaymentTerms added in v0.0.4

type SpecifiedTradePaymentTerms struct {
	Description          string    // BT-20
	DueDate              time.Time // BT-9
	DirectDebitMandateID string    // BT-89

}

SpecifiedTradePaymentTerms is unbounded in extended.

type TradeTax added in v0.0.2

type TradeTax struct {
	CalculatedAmount    decimal.Decimal // BT-117
	BasisAmount         decimal.Decimal // BT-116
	TypeCode            string          // BT-118-0
	CategoryCode        string          // BT-118
	Percent             decimal.Decimal // BT-119
	ExemptionReason     string          // BT-120
	ExemptionReasonCode string          // BT-121
	TaxPointDate        time.Time       // BT-7
	DueDateTypeCode     string          // BT-8
}

TradeTax is the VAT breakdown for each percentage.

func (TradeTax) String added in v0.0.7

func (tt TradeTax) String() string

type ValidationError added in v0.0.11

type ValidationError struct {
	// contains filtered or unexported fields
}

ValidationError is returned when invoice validation fails. It contains all EN 16931 business rule violations found during validation.

Example usage:

err := inv.Validate()
if err != nil {
    var valErr *ValidationError
    if errors.As(err, &valErr) {
        for _, v := range valErr.Violations() {
            fmt.Printf("Rule %s: %s\n", v.Rule.Code, v.Text)
        }
    }
}

func (*ValidationError) Count added in v0.0.11

func (e *ValidationError) Count() int

Count returns the number of validation violations.

func (*ValidationError) Error added in v0.0.11

func (e *ValidationError) Error() string

Error implements the error interface. Returns a human-readable description of the validation failure.

func (*ValidationError) HasRule added in v0.0.11

func (e *ValidationError) HasRule(rule rules.Rule) bool

HasRule checks if a specific business rule violation exists. Accepts a Rule constant (e.g., rules.BR1, rules.BRS8, rules.BRCO14).

Example:

if valErr.HasRule(rules.BR1) {
    // Handle missing specification identifier
}

func (*ValidationError) HasRuleCode added in v0.0.12

func (e *ValidationError) HasRuleCode(code string) bool

HasRuleCode checks if a specific business rule code violation exists. The code parameter should be a business rule identifier string like "BR-1", "BR-S-8", etc.

Example:

if valErr.HasRuleCode("BR-1") {
    // Handle missing specification identifier
}

func (*ValidationError) Violations added in v0.0.11

func (e *ValidationError) Violations() []SemanticError

Violations returns a copy of all validation violations. This ensures the internal violations slice cannot be modified externally.

Directories

Path Synopsis
cmd
einvoice command
Command einvoice validates electronic invoices against EN 16931 business rules.
Command einvoice validates electronic invoices against EN 16931 business rules.
gencodelists command
gencodelists generates code lists for human-readable descriptions of codes used in electronic invoicing (UNTDID, UNECE, etc.).
gencodelists generates code lists for human-readable descriptions of codes used in electronic invoicing (UNTDID, UNECE, etc.).
genrules command
genrules generates Go code from EN 16931 schematron specifications.
genrules generates Go code from EN 16931 schematron specifications.
pkg
codelists
Package codelists provides human-readable descriptions for standard code lists used in electronic invoicing (UNTDID, UNECE, etc.).
Package codelists provides human-readable descriptions for standard code lists used in electronic invoicing (UNTDID, UNECE, etc.).
Package rules contains EN 16931 business rule definitions.
Package rules contains EN 16931 business rule definitions.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL