This page provides an overview of the major invoice components processed during conversion between GOBL and UBL formats. Invoice components represent distinct functional areas of an invoice such as parties, line items, payment terms, and totals. Understanding the component architecture is essential for working with the conversion system.
For detailed information about specific components, see:
For the overall conversion pipeline architecture, see Conversion System.
Sources: invoice.go1-216 ubl.go1-177
The conversion system processes invoices by breaking them into distinct components, each handled by specialized converter functions. The ublInvoice orchestrator delegates component conversion to dedicated functions during GOBL→UBL conversion, while the Invoice.Convert method delegates to parser functions during UBL→GOBL parsing.
Sources: invoice.go101-194
Sources: invoice_parse.go1-200 lines_parse.go1-308 charges_parse.go1-299
The invoice structure contains the following major components, each with corresponding GOBL and UBL representations:
| Component | GOBL Structure | UBL Structure | Converter (GOBL→UBL) | Parser (UBL→GOBL) | Subsection |
|---|---|---|---|---|---|
| Supplier Party | bill.Invoice.Supplier | Invoice.AccountingSupplierParty | newParty() | goblParty() | 4.1 |
| Customer Party | bill.Invoice.Customer | Invoice.AccountingCustomerParty | newParty() | goblParty() | 4.1 |
| Line Items | bill.Invoice.Lines[] | Invoice.InvoiceLines[] | addLines() | goblAddLines() | 4.2 |
| Charges | bill.Invoice.Charges[] | Invoice.AllowanceCharge[] | addCharges() | goblAddCharges() | 4.3 |
| Discounts | bill.Invoice.Discounts[] | Invoice.AllowanceCharge[] | addCharges() | goblAddCharges() | 4.3 |
| Tax Totals | bill.Invoice.Totals.Taxes | Invoice.TaxTotal[] | addTotals() | Built from TaxTotal | 4.4 |
| Monetary Totals | bill.Invoice.Totals | Invoice.LegalMonetaryTotal | addTotals() | Calculated | 4.4 |
| Payment Means | bill.Invoice.Payment | Invoice.PaymentMeans[] | addPayment() | goblAddPayment() | 4.5 |
| Payment Terms | bill.Invoice.Payment | Invoice.PaymentTerms[] | addPayment() | goblAddPayment() | 4.5 |
| Delivery | bill.Invoice.Delivery | Invoice.Delivery[] | newDelivery() | goblAddDelivery() | 4.6 |
| Ordering Info | bill.Invoice.Ordering | Invoice.OrderReference | addOrdering() | goblAddOrdering() | 4.7 |
| Attachments | bill.Invoice.Attachments[] | Invoice.AdditionalDocumentReference[] | addAttachments() | goblAddAttachments() | 4.8 |
| Preceding Invoices | bill.Invoice.Preceding[] | Invoice.BillingReference[] | addPreceding() | Parsed from BillingReference | 4.7 |
Sources: invoice.go30-99 ubl.go1-177
The Invoice struct represents the root element of both UBL Invoice and CreditNote documents. The structure uses XML namespaces to organize elements into common basic components (cbc:) and common aggregate components (cac:):
Sources: invoice.go30-99 common.go14-21
The ublInvoice function processes components in a specific order during GOBL→UBL conversion:
This order ensures that dependent data (like totals) is calculated after prerequisite data (like lines and charges) is processed.
Sources: invoice.go179-192
A critical preprocessing step during UBL→GOBL parsing is the construction of a tax category map using buildTaxCategoryMap(). This map stores exemption codes and other tax information from the invoice-level TaxTotal structure, which is then used to enrich line items and charges during parsing:
The map key is constructed using buildTaxCategoryKey() which combines the tax scheme ID, category ID, and optionally the percent (for standard-rate "S" categories):
"VAT:S:20" (includes percent)"VAT:E" (no percent)"VAT:AE" (no percent)This design allows lines and charges that omit the percent element to still match the appropriate tax category from the invoice-level totals.
Sources: totals.go140-161 common.go140-165 lines_parse.go26-27 charges_parse.go19-20
Several patterns are shared across component converters:
Components use tax extensions to preserve UBL-specific codes and identifiers:
For more on extensions, see Extension System.
Sources: lines_parse.go187-229 charges_parse.go52-135
All numeric strings from UBL are normalized using normalizeNumericString() before parsing:
" 123.45 " → "123.45"".07" → "0.07"This ensures consistent parsing of amounts, percentages, and quantities across all components.
Sources: common.go167-181
All monetary amounts include a currencyID attribute in UBL. During conversion:
invoice.Currency is added to all Amount structsSources: common.go53-57 totals.go47-76
Line items and charges may use percentage-based calculations that require base amounts:
Price.BaseQuantity indicates how many units the price applies toMultiplierFactorNumeric with BaseAmount calculates percentage adjustmentsThe parser calculates required precision dynamically using calculateRequiredPrecision() to avoid rounding errors when dividing prices by base quantities.
Sources: lines_parse.go52-64 lines_parse.go138-156 charges_parse.go76-95
Some components depend on data from other components:
During UBL→GOBL parsing, the tax category map is built first from TaxTotal, then passed to line and charge parsers. During GOBL→UBL conversion, lines and charges are added before totals are calculated.
Sources: invoice.go179-192 lines_parse.go18-40 charges_parse.go14-50
Each component may have validation requirements enforced by the conversion system or by GOBL's validation framework:
| Component | Key Validation Rules |
|---|---|
| Parties | Tax ID format, address country codes, endpoint ID schemes |
| Lines | Quantity > 0, price present, tax category defined |
| Charges/Discounts | Amount or percent required, tax category optional |
| Totals | Sum consistency, tax calculation accuracy |
| Payment | Valid payment means codes, IBAN format for credit transfers |
| Delivery | UBL-CR-394 compliance (DeliveryParty with DeliveryLocation) |
| Ordering | Valid order ID format |
| Attachments | URI format, document type codes |
Validation errors are returned during the ensureAddons() and addon calculation steps.
Sources: ubl.go122-148
Refresh this wiki