The extension system provides a mechanism for preserving UBL-specific standardized codes within GOBL data structures during bidirectional conversion. When converting between UBL XML and GOBL JSON formats, many UBL fields use standardized code lists (UNTDID, CEF, ISO) that don't have direct equivalents in GOBL's domain model. Extensions allow these codes to be stored alongside GOBL's semantic fields, ensuring that information is preserved during round-trip conversions.
For information about the core conversion processes, see Conversion System. For details about specific document components that use extensions, see Document Components.
Extensions in GOBL are implemented through the tax.Extensions type, which is a map structure (map[cbc.Key]cbc.Code) that stores key-value pairs. Various GOBL entities include an Ext field of this type, allowing arbitrary metadata to be attached without modifying the core GOBL schema.
Extension Storage in GOBL Entities
Sources: payment_parse.go132-135 lines_parse.go161-163 party.go223-225 charges.go47-50
The system uses predefined extension keys from three main catalogues within the GOBL ecosystem. These keys are constants that identify the type of code being stored.
UNTDID (United Nations Trade Data Interchange Directory) provides standardized codes for international trade. The following keys are used:
| Extension Key | Purpose | UBL Field | Example Value |
|---|---|---|---|
untdid.ExtKeyPaymentMeans | Payment method code | PaymentMeansCode | "30" (credit transfer) |
untdid.ExtKeyTaxCategory | Tax category classification | ClassifiedTaxCategory/ID | "S" (standard rate) |
untdid.ExtKeyCharge | Charge reason code | AllowanceChargeReasonCode | "SAA" (service charge) |
untdid.ExtKeyAllowance | Discount/allowance reason code | AllowanceChargeReasonCode | "95" (discount) |
Sources: payment_parse.go16-25 lines_parse.go161-163 charges.go47-50 charges.go78-80
CEF (Core Invoice Vocabulary) codes are defined by the European Union for e-invoicing standards:
| Extension Key | Purpose | UBL Field | Example Value |
|---|---|---|---|
cef.ExtKeyVATEX | VAT exemption reason code | TaxExemptionReasonCode | "VATEX-EU-132" (intra-community supply) |
Sources: lines_parse.go167-172
ISO codes provide international identifiers for various business entities:
| Extension Key | Purpose | UBL Field | Example Value |
|---|---|---|---|
iso.ExtKeySchemeID | Identification scheme code | schemeID attribute | "0088" (GLN), "0184" (DUNS) |
Sources: lines_parse.go212-215 party.go223-225 party.go263-264
When parsing UBL documents into GOBL, extension codes are extracted from UBL XML elements and stored in the corresponding GOBL entity's Ext field. This preserves information that would otherwise be lost in the semantic mapping.
Extension Extraction Flow
Sources: payment_parse.go129-155 lines_parse.go149-195 lines_parse.go197-232
Payment means codes are extracted from PaymentMeansCode elements and stored in payment instructions:
goblInvoiceInstructions creates payment instructionsinstructions.Ext[untdid.ExtKeyPaymentMeans]goblPaymentMeansCode functionTax category codes are extracted from ClassifiedTaxCategory elements:
goblConvertLineItemTaxes processes tax information on line itemsline.Taxes[0].Ext[untdid.ExtKeyTaxCategory]line.Taxes[0].Ext[cef.ExtKeyVATEX] if presentScheme identifiers are extracted from schemeID attributes on various ID elements:
party.go223-225 party.go263-264 party.go353-357
CompanyID, PartyIdentification/ID, and item identifiersidentity.Ext[iso.ExtKeySchemeID]StandardItemIdentification/ID/@schemeIDWhen converting GOBL documents to UBL XML, extension values are retrieved and injected into the appropriate UBL elements. This restores the original standardized codes in the output document.
Extension Injection Flow
Sources: payment.go charges.go36-122 party.go122-272
payment.go (referenced but not shown in provided files)
inst.Ext.Get(untdid.ExtKeyPaymentMeans)PaymentMeans.PaymentMeansCode.ValuemakeTaxCategory retrieves extension codest.Ext.Get(untdid.ExtKeyTaxCategory) populates TaxCategory.IDcharges.go47-50 charges.go78-80
ch.Ext.Get(untdid.ExtKeyCharge) populates AllowanceChargeReasonCode for chargesd.Ext.Get(untdid.ExtKeyAllowance) populates AllowanceChargeReasonCode for discountsparty.go223-225 party.go263-264 party.go353-357 party.go386-389
id.Ext[iso.ExtKeySchemeID]schemeID attribute on ID elementsThe standard pattern for reading extension values uses the Get method or direct map access:
Examples in Codebase:
The standard pattern for writing extension values creates the Extensions map if needed and assigns the code:
Examples in Codebase:
Payment instructions use extensions to preserve UNTDID payment means codes:
Extension Structure
Sources: payment_parse.go129-155 payment_parse.go16-25
The Key field stores a semantic identifier (e.g., pay.MeansKeyCreditTransfer), while the extension preserves the original UNTDID code ("30"). This allows round-trip conversion without information loss.
Tax categories on line items use two types of extensions:
Extension Structure
Sources: lines_parse.go149-195
The Category field identifies the tax scheme (e.g., "VAT"), while extensions store the specific UNTDID category code and CEF exemption reason code. This allows proper reconstruction of complex tax scenarios.
Charges and discounts use extensions to preserve business reason codes:
Extension Structure
Sources: charges.go47-50 charges.go78-80 charges.go104-107
The Reason field contains a human-readable explanation, while the extension preserves the standardized UNTDID code for machine processing.
Party and item identities use extensions to preserve identification scheme codes:
Extension Structure
Sources: lines_parse.go209-219 party.go223-225 party.go263-264 party.go353-357
The extension stores the ISO 6523 ICD (International Code Designator) which identifies the numbering scheme used for the identifier.
The extension system ensures that UBL documents can be parsed to GOBL and converted back to UBL without losing standardized codes:
Round-Trip Data Flow
Sources: ubl.go47-88 (Parse), ubl.go90-120 (Convert), payment_parse.go129-155 lines_parse.go149-195 charges.go47-50 party.go223-225
This table summarizes all extension keys used in the codebase with their corresponding UBL fields and usage contexts:
| Extension Key | Catalogue | UBL Element Path | GOBL Entity | Conversion Direction | Example Value |
|---|---|---|---|---|---|
untdid.ExtKeyPaymentMeans | UNTDID 4461 | PaymentMeans/PaymentMeansCode | pay.Instructions | Both | "30", "48", "49" |
untdid.ExtKeyTaxCategory | UNTDID 5305 | ClassifiedTaxCategory/ID | tax.Combo | Both | "S", "E", "AE" |
untdid.ExtKeyCharge | UNTDID 7161 | AllowanceCharge/AllowanceChargeReasonCode | bill.Charge | Both | "SAA", "FC" |
untdid.ExtKeyAllowance | UNTDID 5189 | AllowanceCharge/AllowanceChargeReasonCode | bill.Discount | Both | "95", "100" |
cef.ExtKeyVATEX | CEF | TaxCategory/TaxExemptionReasonCode | tax.Combo | Both | "VATEX-EU-132" |
iso.ExtKeySchemeID | ISO 6523 | ID/@schemeID | org.Identity | Both | "0088", "0184" |
Sources: payment_parse.go16-25 lines_parse.go7-14 party.go1-10 charges.go1-8
if entity.Ext != nil { ... }Ext: tax.Extensions{}Get() method for safe extension access: entity.Ext.Get(key).String()if code != "" { ... }untdid.ExtKeyX, cef.ExtKeyX, iso.ExtKeyX) rather than string literalsSources: payment_parse.go129-155 lines_parse.go149-195 charges.go36-122 party.go122-272
Refresh this wiki