gobl

package module
v0.205.0 Latest Latest
Warning

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

Go to latest
Published: Nov 12, 2024 License: Apache-2.0 Imports: 26 Imported by: 37

README

GOBL

GOBL Logo

Go Business Language. Core library and Schemas.

Released under the Apache 2.0 LICENSE, Copyright 2021-2024 Invopop S.L..

Lint Test Go Go Report Card codecov GoDoc Latest Tag

Official GOBL documentation site.

Introduction

GOBL, the Go Business Language library and tools, aim to:

  • Help developers build electronic business documents, especially invoices, anywhere in the world.
  • Define a set of open JSON Schema.
  • Build a global database of local tax categories and, whenever practical to do so, provide current and historical tax rates in code.
  • Validate business documents according to local requirements, including tax ID validation.
  • Define the algorithms used to make tax calculations while avoiding rounding errors.
  • Provide built-in support for signing documents using JSON Web Signatures.
  • Output simple and easy-to-read JSON documents that emphasize the use of keys instead of abstract codes, like credit-transfer instead of 30 (UNTDID4461 code for sender-initiated bank or wire transfer).
  • Be flexible enough to support extreme local complexity but produce output that is easily legible in other countries.
  • Build a global community of contributors tired of the complexity of current standards based on XML or EDI.

For examples on what GOBL document data looks like, please see the examples directory.

Community

The complexity around invoicing, particularly electronic invoicing, can quickly become overwhelming. Check out the following resources and get in touch:

  • Documentation contains details on how to use GOBL, and the schema.
  • Builder helps try out GOBL and quickly figure out what is possible, all from your browser.
  • Issues if you have a specific problem with GOBL related to code or usage.
  • Discussions for open discussions about the future of GOBL, complications with a specific country, or any open-ended issues.
  • Pull Requests are very welcome, especially if you'd like to see a new local country or features.
  • Slack for real-time chat about something specific or urgent. We always encourage you to use one of the other options, which are indexed and searchable, but if you'd like to bring something to attention quickly, this is a great resource.

Companion Projects

GOBL makes it easy to create business documents, like invoices, but check out some of the companion projects that help create, use, and convert into other formats:

  • Builder - Available to try at build.gobl.org, this tool makes it easy to build, test, and discover the features of GOBL using the wasm binary in the browser.
  • Generator - Ruby project to convert GOBL JSON Schema into libraries for other languages or documentation.
  • Docs - Content of the official GOBL Documentation Site docs.gobl.org.
  • GOBL for Ruby - Easily build or read GOBL documents in Ruby.

Conversion to local formats

Usage

GOBL is primarily a Go library, so the following instructions assume you'd like to build documents from your own Go applications. See some of the links above if you'd like to develop in another language or use a CLI.

Installation

Run the following command to install the package:

go get github.com/invopop/gobl
Building an Invoice

There are many different ways to get data into GOBL, but for the following example, we're going to try to build an invoice in several steps.

First define a minimal or "partial" GOBL Invoice Document:

inv := &bill.Invoice{
	Series:    "F23",
	Code:      "00010",
	IssueDate: cal.MakeDate(2023, time.May, 11),
	Supplier: &org.Party{
		TaxID: &tax.Identity{
			Country: l10n.US,
		},
		Name:  "Provider One Inc.",
		Alias: "Provider One",
		Emails: []*org.Email{
			{
				Address: "billing@provideone.com",
			},
		},
		Addresses: []*org.Address{
			{
				Number:   "16",
				Street:   "Jessie Street",
				Locality: "San Francisco",
				Region:   "CA",
				Code:     "94105",
				Country:  l10n.US,
			},
		},
	},
	Customer: &org.Party{
		Name: "Sample Customer",
		Emails: []*org.Email{
			{
				Address: "email@sample.com",
			},
		},
	},
	Lines: []*bill.Line{
		{
			Quantity: num.MakeAmount(20, 0),
			Item: &org.Item{
				Name:  "A stylish mug",
				Price: num.MakeAmount(2000, 2),
				Unit:  org.UnitHour,
			},
			Taxes: []*tax.Combo{
				{
					Category: common.TaxCategoryST,
					Percent:  num.NewPercentage(85, 3),
				},
			},
		},
	},
}

Notice that the are no sums or calculations yet. The next step involves "inserting" the invoice document into an "envelope". In GOBL, we use the concept of an envelope to hold data and provide functionality to guarantee that no modifications have been made to the payload.

Insert our previous Invoice into an envelope as follows:

// Prepare an "Envelope"
env := gobl.NewEnvelope()
if err := env.Insert(inv); err != nil {
	panic(err)
}

CLI

This repo contains a gobl CLI tool which can be used to manipulate GOBL documents from the command line or shell scripts.

Build with:

mage -v build

Install with:

mage -v install
Build

Build expects a partial GOBL Envelope or Document, in either YAML or JSON as input. It'll automatically run the Calculate and Validate methods and output JSON data as either an envelope or document, according to the input source.

Example uses:

# Calculate and validate a YAML invoice
gobl build ./examples/es/invoice-es-es.yaml

# Output using indented formatting
gobl build -i ./examples/es/party.yaml

# Set the supplier from an external file
gobl build -i ./examples/es/invoice-es-es.yaml \
    --set-file customer=./examples/es/party.yaml

# Set arbitrary values from the command line. Inputs are parsed as YAML.
gobl build -i ./examples/es/invoice-es-es.yaml \
    --set meta.bar="a long string" \
    --set series="TESTING"

# Set the top-level object:
gobl build -i ./examples/es/invoice-es-es.yaml \
    --set-file .=./examples/es/invoice-es-es.env.yaml

# Insert a document into an envelope
gobl build -i --envelop ./examples/es/invoice-es-es.yaml
Correct

The GOBL CLI makes it easy to use the library and tax regime specific functionality that create a corrective document that reverts or amends a previous document. This is most useful for invoices and issuing refunds for example.

# Correct an invoice with a credit note (this will error for ES invoice!)
gobl correct -i ./examples/es/invoice-es-es.yaml --credit

# Specify tax regime specific details
gobl correct -i -d '{"credit":true,"changes":["line"],"method":"complete"}' \
    ./examples/es/invoice-es-es.yaml
Sign

GOBL encourages users to sign data embedded into envelopes using digital signatures. To get started, you'll need to have a JSON Web Key. Use the following commands to generate one:

# Generate a JSON Web Key and store in ~/.gobl/id_es256.jwk
gobl keygen

# Generate and output a JWK into a new file
gobl keygen ./examples/key.jwk

Use the key to sign documents:

# Add a signature to the envelope using our personal key
gobl sign -i ./examples/es/invoice-es-es.env.yaml

# Add a signature using a specific key
gobl sign -i --key ./examples/key.jwk ./examples/es/invoice-es-es.env.yaml

It is only possible to sign non-draft envelopes, so the CLI will automatically remove this flag during the signing process. This implies that the document must be completely valid before signing.

Development

GOBL uses the go generate command to automatically generate JSON schemas, definitions, and some Go code output. After any changes, be sure to run:

go generate .

Documentation

Overview

Package gobl contains all the base models for GOBL.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrNoDocument is provided when the envelope does not contain a
	// document payload.
	ErrNoDocument = NewError("no-document")

	// ErrValidation is used when a document fails a validation request.
	ErrValidation = NewError("validation")

	// ErrCalculation wraps around errors that we're generated during a
	// call to perform calculations on a document.
	ErrCalculation = NewError("calculation")

	// ErrMarshal is provided when there has been a problem attempting to encode
	// or marshal an object, usually into JSON.
	ErrMarshal = NewError("marshal")

	// ErrUnmarshal is used when that has been a problem attempting to read the
	// source data.
	ErrUnmarshal = NewError("unmarshal")

	// ErrSignature identifies an issue related to signatures.
	ErrSignature = NewError("signature")

	// ErrDigest identifies an issue related to the digest.
	ErrDigest = NewError("digest")

	// ErrInternal is a "catch-all" for errors that are not expected.
	ErrInternal = NewError("internal")

	// ErrUnknownSchema is provided when we attempt to determine the schema for an object
	// or from an ID and cannot find a match.
	ErrUnknownSchema = NewError("unknown-schema")
)
View Source
var EnvelopeSchema = schema.GOBL.Add("envelope")

EnvelopeSchema sets the general definition of the schema ID for this version of the envelope.

Functions

func Parse added in v0.26.1

func Parse(data []byte) (interface{}, error)

Parse unmarshals the provided data and uses the schema ID to determine what type of object we're dealing with. As long as the provided data contains a schema registered in GOBL, a new object instance will be returned.

Types

type Envelope

type Envelope struct {
	// Schema identifies the schema that should be used to understand this document
	Schema schema.ID `json:"$schema" jsonschema:"title=JSON Schema ID"`
	// Details on what the contents are
	Head *head.Header `json:"head" jsonschema:"title=Header"`
	// The data inside the envelope
	Document *schema.Object `json:"doc" jsonschema:"title=Document"`
	// JSON Web Signatures of the header
	Signatures []*dsig.Signature `json:"sigs,omitempty" jsonschema:"title=Signatures"`
}

Envelope wraps around a document adding headers and digital signatures. An Envelope is similar to a regular envelope in the physical world, it keeps the contents safe and helps get the document where its needed.

func Envelop added in v0.20.0

func Envelop(doc interface{}) (*Envelope, error)

Envelop is a convenience method that will build a new envelope and insert the contents document provided in a single swoop. The resulting envelope will still need to be signed afterwards.

func NewEnvelope

func NewEnvelope() *Envelope

NewEnvelope builds a new envelope object ready for data to be inserted and signed. If you are loading data from json, you can safely use a regular `new(Envelope)` call directly.

Example (Complete)
package main

import (
	"encoding/json"
	"fmt"

	"github.com/invopop/gobl"
	"github.com/invopop/gobl/note"
	"github.com/invopop/gobl/uuid"
)

func main() {
	// Prepare a new Envelope with a region
	env := gobl.NewEnvelope()
	env.Head.UUID = uuid.MustParse("871c1e6a-8b5c-11ec-af5f-3e7e00ce5635")

	// Prepare a payload and insert
	msg := &note.Message{
		Content: "sample message content",
	}
	msg.SetUUID(uuid.MustParse("e8c70516-0098-11ef-92c8-0242ac120002"))
	if err := env.Insert(msg); err != nil {
		panic(err.Error())
	}
	if err := env.Validate(); err != nil {
		panic(err.Error())
	}

	data, err := json.MarshalIndent(env, "", "\t")
	if err != nil {
		panic(err.Error())
	}
	fmt.Printf("%v\n", string(data))
}
Output:

{
	"$schema": "https://gobl.org/draft-0/envelope",
	"head": {
		"uuid": "871c1e6a-8b5c-11ec-af5f-3e7e00ce5635",
		"dig": {
			"alg": "sha256",
			"val": "6854b999501883c478f0dbcb929ea1cb33e0e738fd0e74ac8194d1e5b7991980"
		}
	},
	"doc": {
		"$schema": "https://gobl.org/draft-0/note/message",
		"uuid": "e8c70516-0098-11ef-92c8-0242ac120002",
		"content": "sample message content"
	}
}

func (*Envelope) Calculate added in v0.28.0

func (e *Envelope) Calculate() error

Calculate is used to perform calculations on the envelope's document contents to ensure everything looks correct. Headers will be refreshed to ensure they have the latest valid digest.

func (*Envelope) Correct added in v0.40.0

func (e *Envelope) Correct(opts ...schema.Option) (*Envelope, error)

Correct will attempt to build a new envelope as a correction of the current envelope contents, if possible.

func (*Envelope) CorrectionOptionsSchema added in v0.58.1

func (e *Envelope) CorrectionOptionsSchema() (interface{}, error)

CorrectionOptionsSchema will attempt to provide a corrective options JSON Schema that can be used to generate a JSON object to send when correcting a document. If none are available, the result will be nil.

func (*Envelope) Digest added in v0.56.0

func (e *Envelope) Digest() (*dsig.Digest, error)

Digest calculates a digital digest using the canonical JSON of the document.

func (*Envelope) Extract

func (e *Envelope) Extract() interface{}

Extract the contents of the envelope into the provided document type.

func (*Envelope) Insert

func (e *Envelope) Insert(doc interface{}) error

Insert takes the provided document and inserts it into this envelope. Calculate will be called automatically.

func (*Envelope) Replicate added in v0.75.0

func (e *Envelope) Replicate() (*Envelope, error)

Replicate will create a new envelope with the same contents as the current, but with schema specific options applied to remove information that must change between documents, such as stamps, invoice code, date, UUID, etc. The intention here is for users to be able to get a new copy of the original document so that they can issue a new version with updated details, or simply use the original as a template.

func (*Envelope) Sign

func (e *Envelope) Sign(key *dsig.PrivateKey) error

Sign uses the private key to sign the envelope headers. Additional validation rules may be applied to signed documents, so the document will be signed, then validated, and if the validation fails, the signature will be removed.

func (*Envelope) Signed added in v0.200.0

func (e *Envelope) Signed() bool

Signed returns true if the envelope has signatures.

func (*Envelope) Unsign added in v0.200.0

func (e *Envelope) Unsign()

Unsign removes the signatures from the envelope.

func (*Envelope) Validate

func (e *Envelope) Validate() error

Validate ensures that the envelope contains everything it should to be considered valid GoBL.

func (*Envelope) ValidateWithContext added in v0.38.0

func (e *Envelope) ValidateWithContext(ctx context.Context) error

ValidateWithContext ensures that the envelope contains everything it should to be considered valid GoBL.

func (*Envelope) Verify

func (e *Envelope) Verify(keys ...*dsig.PublicKey) error

Verify checks the envelope's signatures to ensure the headers they contain still matches with the current headers. If a list of public keys are provided, they will be used to ensure that the signatures we're signed by at least one of them. If no keys are provided, only the contents will be checked.

func (*Envelope) VerifySignature added in v0.66.1

func (e *Envelope) VerifySignature(sig *dsig.Signature, keys ...*dsig.PublicKey) error

VerifySignature checks a specific signature with the envelope to see if its contents are still valid. If a list of public keys are provided, they will be used to ensure that the signature was signed by at least one of them. If no keys are provided, only the contents will be checked.

type Error

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

An Error provides a structure to better be able to make error comparisons. The contents can also be serialised as JSON ready to send to a client if needed, see [MarshalJSON] method.

func NewError

func NewError(key cbc.Key) *Error

NewError provides a new error with a code that is meant to provide a context.

func (*Error) Error

func (e *Error) Error() string

Error provides a string representation of the error.

func (*Error) Fields added in v0.67.7

func (e *Error) Fields() FieldErrors

Fields returns the errors that are associated with specific fields or nil if there are no field errors available.

func (*Error) Is

func (e *Error) Is(target error) bool

Is checks to see if the target error matches the current error or part of the chain.

func (*Error) Key added in v0.26.1

func (e *Error) Key() cbc.Key

Key provides the error's key.

func (*Error) MarshalJSON added in v0.67.1

func (e *Error) MarshalJSON() ([]byte, error)

MarshalJSON converts the Error into a valid JSON, correctly handling mashaling of cause objects that might not have a valid MarhsalJSON method.

func (*Error) Message added in v0.67.7

func (e *Error) Message() string

Message returns a string representation of the error if it cannot be serialised as a map of field names to sub-errors, see also the [Fields] method.

func (*Error) WithCause

func (e *Error) WithCause(err error) *Error

WithCause is used to copy and add an underlying error to this one, unless the errors is already of type *Error, in which case it will be returned as is.

func (*Error) WithReason added in v0.56.0

func (e *Error) WithReason(msg string, a ...interface{}) *Error

WithReason returns the error with a specific reason.

type FieldErrors added in v0.67.7

type FieldErrors map[string]error // nolint:errname

FieldErrors is a map of field names to errors, which is provided when it was possible to determine that the error was related to a specific field.

func (FieldErrors) Error added in v0.67.7

func (fe FieldErrors) Error() string

Error returns the error string of FieldErrors. This is based on the implementation of validation.Errors.

func (FieldErrors) MarshalJSON added in v0.67.7

func (fe FieldErrors) MarshalJSON() ([]byte, error)

MarshalJSON converts the FieldErrors into a valid JSON. Based on the implementation of validation.Errors.

type Version added in v0.11.0

type Version string

Version defines the semver for this version of GOBL.

const VERSION Version = "v0.205.0"

VERSION is the current version of the GOBL library.

func (Version) Semver added in v0.11.0

func (v Version) Semver() *semver.Version

Semver parses and returns semver

Directories

Path Synopsis
Package addons contains all the base addon packages offerd by GOBL to provide additional tax handling.
Package addons contains all the base addon packages offerd by GOBL to provide additional tax handling.
br/nfse
Package nfse handles extensions and validation rules to issue NFS-e in Brazil.
Package nfse handles extensions and validation rules to issue NFS-e in Brazil.
co/dian
Package dian provides the DIAN UBL 2.1 extensions used in Colombia.
Package dian provides the DIAN UBL 2.1 extensions used in Colombia.
de/xrechnung
Package xrechnung provides extensions and validations for the German XRechnung standard version 3.0.2 for electronic invoicing.
Package xrechnung provides extensions and validations for the German XRechnung standard version 3.0.2 for electronic invoicing.
es/facturae
Package facturae provides the FacturaE addon for Spanish invoices.
Package facturae provides the FacturaE addon for Spanish invoices.
es/tbai
Package tbai provides the TicketBAI addon
Package tbai provides the TicketBAI addon
eu/en16931
Package en16931 defines an addon that will apply rules from the EN 16931 specification to GOBL documents.
Package en16931 defines an addon that will apply rules from the EN 16931 specification to GOBL documents.
gr/mydata
Package mydata handles the extensions and validation rules in order to use GOBL with the Greek MyData format.
Package mydata handles the extensions and validation rules in order to use GOBL with the Greek MyData format.
it/sdi
Package sdi handles the extensions and validation rules in order to use GOBL with the Italian SDI and FatturaPA format.
Package sdi handles the extensions and validation rules in order to use GOBL with the Italian SDI and FatturaPA format.
mx/cfdi
Package cfdi implements the CFDI (Comprobante Fiscal Digital por Internet) extensions and validation rules that need to be applied to GOBL documents in order to comply with the Mexican tax authority (SAT).
Package cfdi implements the CFDI (Comprobante Fiscal Digital por Internet) extensions and validation rules that need to be applied to GOBL documents in order to comply with the Mexican tax authority (SAT).
pt/saft
Package saft provides the SAF-T addon for Portuguese invoices.
Package saft provides the SAF-T addon for Portuguese invoices.
Package bill provides models for dealing with Billing and specifically invoicing.
Package bill provides models for dealing with Billing and specifically invoicing.
Package c14n provides canonical JSON encoding and decoding.
Package c14n provides canonical JSON encoding and decoding.
Package cal provides simple date handling.
Package cal provides simple date handling.
Package catalogues provides a set of re-useable extensions, scenarios, and validators for specific international standards that can be re-used and incorporated by addons or tax regimes.
Package catalogues provides a set of re-useable extensions, scenarios, and validators for specific international standards that can be re-used and incorporated by addons or tax regimes.
iso
Package iso is used to define ISO/IEC extensions and codes that may be used in documents.
Package iso is used to define ISO/IEC extensions and codes that may be used in documents.
untdid
Package untdid defines the UN/EDIFACT data elements contained in the UNTDID (United Nations Trade Data Interchange Directory).
Package untdid defines the UN/EDIFACT data elements contained in the UNTDID (United Nations Trade Data Interchange Directory).
Package cbc provides a set of Common Basic Components.
Package cbc provides a set of Common Basic Components.
cmd
gobl
Package main provides a command-line interface to the GOBL library.
Package main provides a command-line interface to the GOBL library.
Package currency provides models for dealing with currencies.
Package currency provides models for dealing with currencies.
Package data contains both generated and embedded data.
Package data contains both generated and embedded data.
Package dsig provides models for dealing with digital signatures.
Package dsig provides models for dealing with digital signatures.
Package head defines the contents to be used in envelope headers.
Package head defines the contents to be used in envelope headers.
Package i18n provides internationalization models.
Package i18n provides internationalization models.
Package internal contains internal objects that may be used for reference inside GOBL but are not intended for use outside of the library.
Package internal contains internal objects that may be used for reference inside GOBL but are not intended for use outside of the library.
cli
Package cli contains the functionality for the GOBL CLI
Package cli contains the functionality for the GOBL CLI
iotools
Package iotools helps with reading documents.
Package iotools helps with reading documents.
Package l10n provides localization models and data.
Package l10n provides localization models and data.
Package note provides models for generating simple messages.
Package note provides models for generating simple messages.
Package num provides support for dealing with amounts and percentages without rounding errors.
Package num provides support for dealing with amounts and percentages without rounding errors.
Package org contains structures related to organization.
Package org contains structures related to organization.
Package pay handles models related to payments.
Package pay handles models related to payments.
pkg
here
Package here provides creation of here-documents from raw strings.
Package here provides creation of here-documents from raw strings.
Package regimes simple ensures that each of the individually defined tax regimes is loaded correctly and ready to use from other GOBL packages.
Package regimes simple ensures that each of the individually defined tax regimes is loaded correctly and ready to use from other GOBL packages.
at
Package at provides the Austrian tax regime.
Package at provides the Austrian tax regime.
be
Package be defines the tax regime data for Belgium
Package be defines the tax regime data for Belgium
br
Package br provides the tax region definition for Brazil.
Package br provides the tax region definition for Brazil.
ca
Package ca provides models for dealing with Canada.
Package ca provides models for dealing with Canada.
ch
Package ch provides the Swiss tax regime.
Package ch provides the Swiss tax regime.
co
Package co handles tax regime data for Colombia.
Package co handles tax regime data for Colombia.
common
Package common provides re-usable regime related structures and data.
Package common provides re-usable regime related structures and data.
de
Package de provides the tax region definition for Germany.
Package de provides the tax region definition for Germany.
es
Package es provides tax regime support for Spain.
Package es provides tax regime support for Spain.
fr
Package fr provides the tax region definition for France.
Package fr provides the tax region definition for France.
gb
Package gb provides the United Kingdom tax regime.
Package gb provides the United Kingdom tax regime.
gr
Package gr provides the tax region definition for Greece.
Package gr provides the tax region definition for Greece.
it
Package it provides the Italian tax regime.
Package it provides the Italian tax regime.
mx
Package mx provides the Mexican tax regime.
Package mx provides the Mexican tax regime.
nl
Package nl provides the Dutch region definition
Package nl provides the Dutch region definition
pl
Package pl provides the Polish tax regime.
Package pl provides the Polish tax regime.
pt
Package pt provides models for dealing with the Portuguese tax regime.
Package pt provides models for dealing with the Portuguese tax regime.
us
Package us provides models for dealing with the United States of America.
Package us provides models for dealing with the United States of America.
Package schema provides a simple way to register and lookup schemas.
Package schema provides a simple way to register and lookup schemas.
Package tax encapsulates models related to taxation.
Package tax encapsulates models related to taxation.
Package uuid provides a wrapper for handling UUID codes.
Package uuid provides a wrapper for handling UUID codes.
Package main provides a WASM interface to GOBL.
Package main provides a WASM interface to GOBL.
serve
Package main is used to launch a demo site for the wasm.
Package main is used to launch a demo site for the wasm.

Jump to

Keyboard shortcuts

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