From 07adde2a558ff9cd94260ea6befdd9a415f2c9ac Mon Sep 17 00:00:00 2001 From: Adrian Arencibia Date: Sat, 21 Feb 2026 11:54:04 +0100 Subject: [PATCH 01/11] Add Chile vat tax regime --- data/regimes/cl.json | 115 ++++++++++++++++++ data/schemas/tax/regime-code.json | 4 + examples/cl/invoice-standard.json | 92 ++++++++++++++ examples/cl/out/invoice-standard.json | 134 +++++++++++++++++++++ regimes/cl/README.md | 114 ++++++++++++++++++ regimes/cl/cl.go | 71 +++++++++++ regimes/cl/tax_categories.go | 73 ++++++++++++ regimes/cl/tax_identity.go | 138 +++++++++++++++++++++ regimes/cl/tax_identity_test.go | 165 ++++++++++++++++++++++++++ regimes/regimes.go | 1 + 10 files changed, 907 insertions(+) create mode 100644 data/regimes/cl.json create mode 100644 examples/cl/invoice-standard.json create mode 100644 examples/cl/out/invoice-standard.json create mode 100644 regimes/cl/README.md create mode 100644 regimes/cl/cl.go create mode 100644 regimes/cl/tax_categories.go create mode 100644 regimes/cl/tax_identity.go create mode 100644 regimes/cl/tax_identity_test.go diff --git a/data/regimes/cl.json b/data/regimes/cl.json new file mode 100644 index 000000000..b944ef412 --- /dev/null +++ b/data/regimes/cl.json @@ -0,0 +1,115 @@ +{ + "$schema": "https://gobl.org/draft-0/tax/regime-def", + "name": { + "en": "Chile", + "es": "Chile" + }, + "description": { + "en": "Chile's tax system is administered by the SII (Servicio de Impuestos Internos), which oversees the collection of IVA (Impuesto al Valor Agregado), the country's value-added tax.\n\nTaxpayers are identified using the RUT (Rol Único Tributario), an 8-digit number with a check digit calculated using the modulo 11 algorithm. The check digit can be 0-9 or K, and RUTs are formatted as XX.XXX.XXX-Y.\n\nChile applies a single standard IVA rate of 19%, effective since October 1, 2003, when it was increased from 18% by Ley 19888. Unlike many other countries, Chile does not have reduced or super-reduced VAT rates.\n\nElectronic invoicing has been mandatory in Chile since 2018 for B2B transactions and since 2021 for B2C transactions. The system is based on DTEs (Documentos Tributarios Electrónicos - Electronic Tax Documents) that must be validated by the SII before being sent to the recipient. The validation process is known as \"prior validation,\" where documents are transmitted to the SII first, validated, returned to the issuer, and then forwarded to the customer. Recipients have 8 days to accept or reject documents; otherwise, they are considered tacitly accepted.\n\nCommon document types include Factura Electrónica (electronic invoice), Boleta Electrónica (electronic receipt), Nota de Crédito Electrónica (electronic credit note), Nota de Débito Electrónica (electronic debit note), and Guía de Despacho (dispatch guide). All DTEs must be archived for 6 years in the XML format validated by the SII.", + "es": "El sistema tributario de Chile es administrado por el SII (Servicio de Impuestos Internos), que supervisa la recaudación del IVA (Impuesto al Valor Agregado).\n\nLos contribuyentes se identifican mediante el RUT (Rol Único Tributario), un número de 8 dígitos con un dígito verificador calculado mediante el algoritmo módulo 11. El dígito verificador puede ser 0-9 o K, y los RUT se formatean como XX.XXX.XXX-Y.\n\nChile aplica una tasa única de IVA del 19%, vigente desde el 1 de octubre de 2003, cuando fue aumentada del 18% mediante la Ley 19888. A diferencia de muchos otros países, Chile no tiene tasas reducidas o super-reducidas de IVA.\n\nLa facturación electrónica es obligatoria en Chile desde 2018 para transacciones B2B y desde 2021 para transacciones B2C. El sistema se basa en DTEs (Documentos Tributarios Electrónicos) que deben ser validados por el SII antes de enviarse al receptor. El proceso de validación se conoce como \"validación previa\", donde los documentos se transmiten primero al SII, se validan, se devuelven al emisor y luego se reenvían al cliente. Los receptores tienen 8 días para aceptar o rechazar documentos; de lo contrario, se consideran aceptados tácitamente.\n\nLos tipos de documentos comunes incluyen Factura Electrónica, Boleta Electrónica, Nota de Crédito Electrónica, Nota de Débito Electrónica y Guía de Despacho. Todos los DTEs deben archivarse durante 6 años en el formato XML validado por el SII." + }, + "time_zone": "America/Santiago", + "country": "CL", + "currency": "CLP", + "tax_scheme": "VAT", + "categories": [ + { + "code": "VAT", + "name": { + "en": "VAT", + "es": "IVA" + }, + "title": { + "en": "Value Added Tax", + "es": "Impuesto al Valor Agregado" + }, + "desc": { + "en": "Chile's IVA (Impuesto al Valor Agregado) is a consumption tax applied to the sale of goods and services. Chile has applied a single standard rate of 19% since October 1, 2003, making it one of the simpler VAT systems in Latin America with no reduced or super-reduced rates.\n\nThe IVA applies to most goods and services unless specifically exempted. Common exemptions include certain financial services, educational services, and healthcare services. The tax is administered by the SII (Servicio de Impuestos Internos) and is a significant source of government revenue.", + "es": "El IVA (Impuesto al Valor Agregado) de Chile es un impuesto al consumo aplicado a la venta de bienes y servicios. Chile aplica una tasa estándar única del 19% desde el 1 de octubre de 2003, lo que lo convierte en uno de los sistemas de IVA más simples de América Latina, sin tasas reducidas o super-reducidas.\n\nEl IVA se aplica a la mayoría de los bienes y servicios a menos que estén específicamente exentos. Las exenciones comunes incluyen ciertos servicios financieros, servicios educativos y servicios de salud. El impuesto es administrado por el SII (Servicio de Impuestos Internos) y es una fuente importante de ingresos del gobierno." + }, + "keys": [ + { + "key": "standard", + "name": { + "en": "Standard" + } + }, + { + "key": "zero", + "name": { + "en": "Zero" + } + }, + { + "key": "reverse-charge", + "name": { + "en": "Reverse charge" + }, + "no_percent": true + }, + { + "key": "exempt", + "name": { + "en": "Exempt" + }, + "no_percent": true + }, + { + "key": "export", + "name": { + "en": "Export" + }, + "no_percent": true + }, + { + "key": "intra-community", + "name": { + "en": "Intra-community" + }, + "no_percent": true + }, + { + "key": "outside-scope", + "name": { + "en": "Outside scope" + }, + "no_percent": true + } + ], + "rates": [ + { + "rate": "general", + "keys": [ + "standard" + ], + "name": { + "en": "General Rate", + "es": "Tasa General" + }, + "values": [ + { + "since": "2003-10-01", + "percent": "19%" + } + ] + } + ], + "sources": [ + { + "title": { + "en": "Decreto Ley Nº 825 - Law on VAT and Services", + "es": "Decreto Ley Nº 825 - Ley sobre Impuesto a las Ventas y Servicios" + }, + "url": "https://www.sii.cl/normativa_legislacion/sobreventasyservicios.pdf" + }, + { + "title": { + "en": "Ley 19888 - Law establishing 19% VAT rate", + "es": "Ley 19888 - Ley que establece la tasa del IVA en 19%" + }, + "url": "https://www.bcn.cl/leychile/Navegar?idNorma=213493" + } + ] + } + ] +} \ No newline at end of file diff --git a/data/schemas/tax/regime-code.json b/data/schemas/tax/regime-code.json index fa812446d..c9f8a722a 100644 --- a/data/schemas/tax/regime-code.json +++ b/data/schemas/tax/regime-code.json @@ -30,6 +30,10 @@ "const": "CH", "title": "Switzerland" }, + { + "const": "CL", + "title": "Chile" + }, { "const": "CO", "title": "Colombia" diff --git a/examples/cl/invoice-standard.json b/examples/cl/invoice-standard.json new file mode 100644 index 000000000..993fa7355 --- /dev/null +++ b/examples/cl/invoice-standard.json @@ -0,0 +1,92 @@ +{ + "$schema": "https://gobl.org/draft-0/bill/invoice", + "$regime": "CL", + "uuid": "3aea7b56-59d8-4beb-90bd-f8f280d852a0", + "code": "F001-00000123", + "issue_date": "2025-01-15", + "currency": "CLP", + "supplier": { + "name": "Empresa Ejemplo SpA", + "tax_id": { + "country": "CL", + "code": "713254975" + }, + "addresses": [ + { + "street": "Av. Libertador Bernardo O'Higgins 1234", + "locality": "Santiago", + "region": "Región Metropolitana", + "code": "8320000", + "country": "CL" + } + ], + "emails": [ + { + "addr": "ventas@empresaejemplo.cl" + } + ] + }, + "customer": { + "name": "Cliente Comercial Ltda.", + "tax_id": { + "country": "CL", + "code": "77668208K" + }, + "addresses": [ + { + "street": "Av. Providencia 2500", + "locality": "Providencia", + "region": "Región Metropolitana", + "code": "7500000", + "country": "CL" + } + ], + "emails": [ + { + "addr": "compras@clientecomercial.cl" + } + ] + }, + "lines": [ + { + "quantity": "10", + "item": { + "name": "Servicios de consultoría", + "price": "50000" + }, + "taxes": [ + { + "cat": "VAT", + "key": "standard", + "rate": "general", + "percent": "19%" + } + ] + }, + { + "quantity": "5", + "item": { + "name": "Desarrollo de software", + "price": "100000" + }, + "taxes": [ + { + "cat": "VAT", + "key": "standard", + "rate": "general", + "percent": "19%" + } + ] + } + ], + "payment": { + "terms": { + "due_dates": [ + { + "date": "2025-02-15", + "percent": "100%" + } + ] + } + } +} diff --git a/examples/cl/out/invoice-standard.json b/examples/cl/out/invoice-standard.json new file mode 100644 index 000000000..d53bba09c --- /dev/null +++ b/examples/cl/out/invoice-standard.json @@ -0,0 +1,134 @@ +{ + "$schema": "https://gobl.org/draft-0/envelope", + "head": { + "uuid": "8a51fd30-2a27-11ee-be56-0242ac120002", + "dig": { + "alg": "sha256", + "val": "ed4173954975a415330a436aa48305ba9f21c690a69999434c6f5dd3b81fd58a" + } + }, + "doc": { + "$schema": "https://gobl.org/draft-0/bill/invoice", + "$regime": "CL", + "uuid": "3aea7b56-59d8-4beb-90bd-f8f280d852a0", + "type": "standard", + "code": "F001-00000123", + "issue_date": "2025-01-15", + "currency": "CLP", + "supplier": { + "name": "Empresa Ejemplo SpA", + "tax_id": { + "country": "CL", + "code": "713254975" + }, + "addresses": [ + { + "street": "Av. Libertador Bernardo O'Higgins 1234", + "locality": "Santiago", + "region": "Región Metropolitana", + "code": "8320000", + "country": "CL" + } + ], + "emails": [ + { + "addr": "ventas@empresaejemplo.cl" + } + ] + }, + "customer": { + "name": "Cliente Comercial Ltda.", + "tax_id": { + "country": "CL", + "code": "77668208K" + }, + "addresses": [ + { + "street": "Av. Providencia 2500", + "locality": "Providencia", + "region": "Región Metropolitana", + "code": "7500000", + "country": "CL" + } + ], + "emails": [ + { + "addr": "compras@clientecomercial.cl" + } + ] + }, + "lines": [ + { + "i": 1, + "quantity": "10", + "item": { + "name": "Servicios de consultoría", + "price": "50000" + }, + "sum": "500000", + "taxes": [ + { + "cat": "VAT", + "key": "standard", + "rate": "general", + "percent": "19%" + } + ], + "total": "500000" + }, + { + "i": 2, + "quantity": "5", + "item": { + "name": "Desarrollo de software", + "price": "100000" + }, + "sum": "500000", + "taxes": [ + { + "cat": "VAT", + "key": "standard", + "rate": "general", + "percent": "19%" + } + ], + "total": "500000" + } + ], + "payment": { + "terms": { + "due_dates": [ + { + "date": "2025-02-15", + "amount": "1190000", + "percent": "100%" + } + ] + } + }, + "totals": { + "sum": "1000000", + "total": "1000000", + "taxes": { + "categories": [ + { + "code": "VAT", + "rates": [ + { + "key": "standard", + "base": "1000000", + "percent": "19%", + "amount": "190000" + } + ], + "amount": "190000" + } + ], + "sum": "190000" + }, + "tax": "190000", + "total_with_tax": "1190000", + "payable": "1190000" + } + } +} \ No newline at end of file diff --git a/regimes/cl/README.md b/regimes/cl/README.md new file mode 100644 index 000000000..a8319143f --- /dev/null +++ b/regimes/cl/README.md @@ -0,0 +1,114 @@ +# Chile (CL) - Tax Regime + +Chile's tax regime implementation for GOBL based on the requirements of the Chilean Tax Authority (Servicio de Impuestos Internos - SII). + +## Tax Categories + +### IVA (Impuesto al Valor Agregado) + +Chile's Value Added Tax (VAT) is called IVA. The consumption tax was introduced in December 1974 through [Decreto Ley Nº 825](https://www.sii.cl/normativa_legislacion/sobreventasyservicios.pdf). + +- **Standard Rate**: 19% (effective October 1, 2003) +- **Historical Rate**: 18% (prior to October 1, 2003) + +The current 19% rate was established by [Ley 19888](https://www.bcn.cl/leychile/Navegar?idNorma=213493), published August 13, 2003, which amended Article 14 of the VAT law to increase the rate from 18% to 19%. Chile applies a single VAT rate with no reduced rates. + +**Source**: [Law No. 21.210](https://www.sii.cl/vat/faq1_eng.html) confirmed the 19% rate applies to digital services provided by non-resident taxpayers. + +## Tax Identity + +Chile uses the **RUT** (Rol Único Tributario) as the primary tax identification number for both individuals and legal entities, issued and maintained by the SII. + +### RUT Format + +The RUT consists of: +- **Numeric portion**: 6 to 8 digits +- **Check digit**: Single character (0-9 or K) +- **Total length**: 7 to 9 characters (after normalization) +- **Display format**: `XX.XXX.XXX-Y` where dots and hyphen are used for readability +- **Normalized format**: Removes all separators (e.g., `713254975`, `77668208K`) + +Modern RUTs typically have 8-9 total digits, while older RUTs may have 7. The SII now handles RUT numbers ranging from 7 to 9 digits in total length. + +### Check Digit Calculation + +The check digit is calculated using the **Modulo 11 algorithm**, which is the exclusive validation method mandated by the SII for RUT verification in Chile. + +**Implementation Note**: This algorithm is implemented in the `calculateRUTCheckDigit` function in `tax_identity.go`. + +**Sources**: +- [Rol Único Tributario - Wikipedia](https://es.wikipedia.org/wiki/Rol_%C3%9Anico_Tributario) +- [Modificaciones para manejo de RUT de 7 a 9 dígitos](https://help.getcirrus.com/es/articles/8515715-modificaciones-para-manejo-de-rut-de-7-a-9-digitos-chile) + +### Validation and Normalization + +GOBL implements comprehensive RUT validation and normalization to ensure data consistency and compliance with SII standards. + +#### Normalization Process + +When processing a RUT, GOBL automatically: + +1. **Removes formatting characters**: Strips all dots (`.`) and hyphens (`-`) +2. **Normalizes case**: Converts lowercase `k` to uppercase `K` for the check digit + +**Examples**: +- `71.325.497-5` → `713254975` +- `7.766.820-8K` → `77668208K` +- `12.345.678-5` → `123456785` + +## Electronic Invoicing + +Chile has a mandatory electronic invoicing system managed by SII, based on **DTE** (Documentos Tributarios Electrónicos - Electronic Tax Documents). + +### Implementation Timeline + +- **2001**: E-invoicing implemented as voluntary scheme +- **2014**: VAT e-invoicing made mandatory for established organizations +- **March 2018**: B2B e-invoicing made mandatory +- **March 2021**: B2C e-invoicing made mandatory + +### Validation Process + +The Chilean system uses **prior validation** by the SII: +1. DTEs must be transmitted to SII for validation before being sent to customers +2. Once validated, SII returns the document to the issuer +3. Document is forwarded to recipient +4. Recipient has 8 days to accept or reject +5. If no action taken, document is considered tacitly accepted + +### Document Types + +Main DTEs required by SII: +- **Factura Electrónica** (Electronic Invoice) +- **Boleta Electrónica** (Electronic Receipt) +- **Nota de Crédito Electrónica** (Electronic Credit Note) +- **Nota de Débito Electrónica** (Electronic Debit Note) +- **Guía de Despacho** (Dispatch Guide) +- **Factura de Exportación** (Export Invoice) + +### Archiving Requirements + +- DTEs must be archived for **6 years** +- Must be kept in the **XML format** validated by SII + +**Sources**: +- [SII Electronic Invoicing System](https://www.chileatiende.gob.cl/fichas/13505-emision-de-documentos-tributarios-electronicos-dte-sistema-de-facturacion-gratuito-del-sii) +- [Electronic Invoicing in Chile - EDICOM](https://edicomgroup.com/electronic-invoicing/chile) +- [What is Electronic Invoicing - SII](https://www.sii.cl/factura_electronica/que_es_fact_elect.htm) + +## References + +### Official Sources +- [Servicio de Impuestos Internos (SII)](https://www.sii.cl/) - Chilean Tax Authority +- [Decreto Ley Nº 825 - VAT Law](https://www.sii.cl/normativa_legislacion/sobreventasyservicios.pdf) - Law on VAT and Services (1974) +- [Ley 19888](https://www.bcn.cl/leychile/Navegar?idNorma=213493) - Law establishing 19% VAT rate (2003) +- [IVA Digital - SII](https://www.sii.cl/vat/faq1_eng.html) - Official VAT information (English) + +### Tax Identification +- [Rol Único Tributario - Wikipedia](https://es.wikipedia.org/wiki/Rol_%C3%9Anico_Tributario) +- [RUT Format Changes (7-9 digits) - Cirrus Help Center](https://help.getcirrus.com/es/articles/8515715-modificaciones-para-manejo-de-rut-de-7-a-9-digitos-chile) + +### Electronic Invoicing +- [DTE System - ChileAtiende](https://www.chileatiende.gob.cl/fichas/13505-emision-de-documentos-tributarios-electronicos-dte-sistema-de-facturacion-gratuito-del-sii) +- [Electronic Invoicing Overview - EDICOM](https://edicomgroup.com/electronic-invoicing/chile) +- [SII Electronic Invoice Information](https://www.sii.cl/factura_electronica/que_es_fact_elect.htm) diff --git a/regimes/cl/cl.go b/regimes/cl/cl.go new file mode 100644 index 000000000..8b6f18c4d --- /dev/null +++ b/regimes/cl/cl.go @@ -0,0 +1,71 @@ +// Package cl handles tax regime data for Chile. +package cl + +import ( + "github.com/invopop/gobl/currency" + "github.com/invopop/gobl/i18n" + "github.com/invopop/gobl/pkg/here" + "github.com/invopop/gobl/tax" +) + +func init() { + tax.RegisterRegimeDef(New()) +} + +// New provides the tax region definition +func New() *tax.RegimeDef { + return &tax.RegimeDef{ + Country: "CL", + Currency: currency.CLP, + TaxScheme: tax.CategoryVAT, + Name: i18n.String{ + i18n.EN: "Chile", + i18n.ES: "Chile", + }, + Description: i18n.String{ + i18n.EN: here.Doc(` + Chile's tax system is administered by the SII (Servicio de Impuestos Internos), which oversees the collection of IVA (Impuesto al Valor Agregado), the country's value-added tax. + + Taxpayers are identified using the RUT (Rol Único Tributario), an 8-digit number with a check digit calculated using the modulo 11 algorithm. The check digit can be 0-9 or K, and RUTs are formatted as XX.XXX.XXX-Y. + + Chile applies a single standard IVA rate of 19%, effective since October 1, 2003, when it was increased from 18% by Ley 19888. Unlike many other countries, Chile does not have reduced or super-reduced VAT rates. + + Electronic invoicing has been mandatory in Chile since 2018 for B2B transactions and since 2021 for B2C transactions. The system is based on DTEs (Documentos Tributarios Electrónicos - Electronic Tax Documents) that must be validated by the SII before being sent to the recipient. The validation process is known as "prior validation," where documents are transmitted to the SII first, validated, returned to the issuer, and then forwarded to the customer. Recipients have 8 days to accept or reject documents; otherwise, they are considered tacitly accepted. + + Common document types include Factura Electrónica (electronic invoice), Boleta Electrónica (electronic receipt), Nota de Crédito Electrónica (electronic credit note), Nota de Débito Electrónica (electronic debit note), and Guía de Despacho (dispatch guide). All DTEs must be archived for 6 years in the XML format validated by the SII. + `), + i18n.ES: here.Doc(` + El sistema tributario de Chile es administrado por el SII (Servicio de Impuestos Internos), que supervisa la recaudación del IVA (Impuesto al Valor Agregado). + + Los contribuyentes se identifican mediante el RUT (Rol Único Tributario), un número de 8 dígitos con un dígito verificador calculado mediante el algoritmo módulo 11. El dígito verificador puede ser 0-9 o K, y los RUT se formatean como XX.XXX.XXX-Y. + + Chile aplica una tasa única de IVA del 19%, vigente desde el 1 de octubre de 2003, cuando fue aumentada del 18% mediante la Ley 19888. A diferencia de muchos otros países, Chile no tiene tasas reducidas o super-reducidas de IVA. + + La facturación electrónica es obligatoria en Chile desde 2018 para transacciones B2B y desde 2021 para transacciones B2C. El sistema se basa en DTEs (Documentos Tributarios Electrónicos) que deben ser validados por el SII antes de enviarse al receptor. El proceso de validación se conoce como "validación previa", donde los documentos se transmiten primero al SII, se validan, se devuelven al emisor y luego se reenvían al cliente. Los receptores tienen 8 días para aceptar o rechazar documentos; de lo contrario, se consideran aceptados tácitamente. + + Los tipos de documentos comunes incluyen Factura Electrónica, Boleta Electrónica, Nota de Crédito Electrónica, Nota de Débito Electrónica y Guía de Despacho. Todos los DTEs deben archivarse durante 6 años en el formato XML validado por el SII. + `), + }, + TimeZone: "America/Santiago", + Validator: Validate, + Normalizer: Normalize, + Categories: taxCategories, + } +} + +// Normalize will attempt to clean the object passed to it. +func Normalize(doc any) { + switch obj := doc.(type) { + case *tax.Identity: + normalizeTaxIdentity(obj) + } +} + +// Validate checks the document type and determines if it can be validated. +func Validate(doc interface{}) error { + switch obj := doc.(type) { + case *tax.Identity: + return validateTaxIdentity(obj) + } + return nil +} diff --git a/regimes/cl/tax_categories.go b/regimes/cl/tax_categories.go new file mode 100644 index 000000000..b402271a2 --- /dev/null +++ b/regimes/cl/tax_categories.go @@ -0,0 +1,73 @@ +package cl + +import ( + "github.com/invopop/gobl/cal" + "github.com/invopop/gobl/cbc" + "github.com/invopop/gobl/i18n" + "github.com/invopop/gobl/num" + "github.com/invopop/gobl/pkg/here" + "github.com/invopop/gobl/tax" +) + +var taxCategories = []*tax.CategoryDef{ + // + // VAT (IVA - Impuesto al Valor Agregado) + // + { + Code: tax.CategoryVAT, + Name: i18n.String{ + i18n.EN: "VAT", + i18n.ES: "IVA", + }, + Title: i18n.String{ + i18n.EN: "Value Added Tax", + i18n.ES: "Impuesto al Valor Agregado", + }, + Description: &i18n.String{ + i18n.EN: here.Doc(` + Chile's IVA (Impuesto al Valor Agregado) is a consumption tax applied to the sale of goods and services. Chile has applied a single standard rate of 19% since October 1, 2003, making it one of the simpler VAT systems in Latin America with no reduced or super-reduced rates. + + The IVA applies to most goods and services unless specifically exempted. Common exemptions include certain financial services, educational services, and healthcare services. The tax is administered by the SII (Servicio de Impuestos Internos) and is a significant source of government revenue. + `), + i18n.ES: here.Doc(` + El IVA (Impuesto al Valor Agregado) de Chile es un impuesto al consumo aplicado a la venta de bienes y servicios. Chile aplica una tasa estándar única del 19% desde el 1 de octubre de 2003, lo que lo convierte en uno de los sistemas de IVA más simples de América Latina, sin tasas reducidas o super-reducidas. + + El IVA se aplica a la mayoría de los bienes y servicios a menos que estén específicamente exentos. Las exenciones comunes incluyen ciertos servicios financieros, servicios educativos y servicios de salud. El impuesto es administrado por el SII (Servicio de Impuestos Internos) y es una fuente importante de ingresos del gobierno. + `), + }, + Sources: []*cbc.Source{ + { + Title: i18n.String{ + i18n.EN: "Decreto Ley Nº 825 - Law on VAT and Services", + i18n.ES: "Decreto Ley Nº 825 - Ley sobre Impuesto a las Ventas y Servicios", + }, + URL: "https://www.sii.cl/normativa_legislacion/sobreventasyservicios.pdf", + }, + { + Title: i18n.String{ + i18n.EN: "Ley 19888 - Law establishing 19% VAT rate", + i18n.ES: "Ley 19888 - Ley que establece la tasa del IVA en 19%", + }, + URL: "https://www.bcn.cl/leychile/Navegar?idNorma=213493", + }, + }, + Retained: false, + Keys: tax.GlobalVATKeys(), + Rates: []*tax.RateDef{ + { + Keys: []cbc.Key{tax.KeyStandard}, + Rate: tax.RateGeneral, + Name: i18n.String{ + i18n.EN: "General Rate", + i18n.ES: "Tasa General", + }, + Values: []*tax.RateValueDef{ + { + Since: cal.NewDate(2003, 10, 1), + Percent: num.MakePercentage(19, 2), + }, + }, + }, + }, + }, +} diff --git a/regimes/cl/tax_identity.go b/regimes/cl/tax_identity.go new file mode 100644 index 000000000..eca0a0f06 --- /dev/null +++ b/regimes/cl/tax_identity.go @@ -0,0 +1,138 @@ +package cl + +import ( + "errors" + "regexp" + "strconv" + "strings" + + "github.com/invopop/gobl/cbc" + "github.com/invopop/gobl/tax" + "github.com/invopop/validation" +) + +var ( + // rutPattern matches normalized Chilean RUT format (no separators). + // Format: 6-8 digits followed by a check digit (0-9 or K/k), for a total of 7-9 characters. + // Modern RUTs typically have 8-9 digits total; older RUTs may have 7. + // Examples: "713254975" (9), "77668208K" (9), "10000009" (8) + rutPattern = regexp.MustCompile(`^(\d{6,8})([\dKk])$`) +) + +// validateTaxIdentity checks to ensure the RUT code looks okay. +func validateTaxIdentity(tID *tax.Identity) error { + return validation.ValidateStruct(tID, + validation.Field(&tID.Code, + validation.When( + tID.Country.In("CL"), + validation.By(validateRUT), + ), + ), + ) +} + +// normalizeTaxIdentity will remove any whitespace or separation characters from +// the tax code and also make sure the default type is set. +func normalizeTaxIdentity(tID *tax.Identity) { + if tID == nil { + return + } + tax.NormalizeIdentity(tID) +} + +// validateRUT validates a Chilean RUT (Rol Único Tributario) tax identification number. +// +// The RUT consists of a number (6-8 digits) followed by a check digit calculated +// using the modulo 11 algorithm. The check digit can be 0-9 or K (for check value 10). +// Total length: 7-9 characters. +// +// Validation process: +// 1. Verify the RUT matches the expected format (6-8 digits + check digit = 7-9 total) +// 2. Calculate the expected check digit using modulo 11 algorithm +// 3. Compare the calculated check digit with the provided one +// +// Returns nil if valid, or an error describing the validation failure. +func validateRUT(value interface{}) error { + code, ok := value.(cbc.Code) + if !ok || code == "" { + return nil + } + + str := strings.ToUpper(string(code)) + + matches := rutPattern.FindStringSubmatch(str) + if matches == nil { + return errors.New("invalid RUT format") + } + + number := matches[1] + checkDigit := matches[2] + + expected, err := calculateRUTCheckDigit(number) + if err != nil { + return err + } + + if expected != checkDigit { + return errors.New("invalid RUT check digit") + } + + return nil +} + +// calculateRUTCheckDigit calculates the check digit for a Chilean RUT using the modulo 11 algorithm. +// +// The algorithm works as follows: +// 1. Process each digit from right to left +// 2. Multiply each digit by a factor that cycles through 2, 3, 4, 5, 6, 7 +// 3. Sum all the products +// 4. Calculate: 11 - (sum mod 11) +// 5. Special cases: result 11 → "0", result 10 → "K" +// +// Example for RUT 71325497: +// +// 7*2 + 9*3 + 4*4 + 5*5 + 2*6 + 3*7 + 1*2 + 7*3 = 14+27+16+25+12+21+2+21 = 138 +// 11 - (138 mod 11) = 11 - 6 = 5 +// Result: "713254975" +// +// Parameters: +// +// rut: The numeric portion of the RUT as a string (without check digit) +// +// Returns: +// +// The calculated check digit as a string ("0"-"9" or "K"), or an error if conversion fails +func calculateRUTCheckDigit(rut string) (string, error) { + num, err := strconv.Atoi(rut) + if err != nil { + return "", err + } + + // Apply modulo 11 algorithm + // Process digits from right to left, multiplying by factors 2-7 cyclically + sum := 0 + multiplier := 2 + + for num > 0 { + digit := num % 10 + sum += digit * multiplier + + num /= 10 + + multiplier++ + if multiplier > 7 { + multiplier = 2 + } + } + + remainder := 11 - (sum % 11) + + switch remainder { + case 11: + return "0", nil + case 10: + return "K", nil + default: + return strconv.Itoa(remainder), nil + } +} diff --git a/regimes/cl/tax_identity_test.go b/regimes/cl/tax_identity_test.go new file mode 100644 index 000000000..63a60e52f --- /dev/null +++ b/regimes/cl/tax_identity_test.go @@ -0,0 +1,165 @@ +package cl_test + +import ( + "testing" + + "github.com/invopop/gobl/cbc" + "github.com/invopop/gobl/l10n" + "github.com/invopop/gobl/regimes/cl" + "github.com/invopop/gobl/tax" + "github.com/stretchr/testify/assert" +) + +func TestNormalizeTaxIdentity(t *testing.T) { + t.Parallel() + + var tID *tax.Identity + assert.NotPanics(t, func() { + cl.Normalize(tID) + }) + + tests := []struct { + Code cbc.Code + Expected cbc.Code + }{ + { + Code: "12.345.678-5", + Expected: "123456785", + }, + { + Code: "11.111.111-1", + Expected: "111111111", + }, + { + Code: "12345678-5", + Expected: "123456785", + }, + { + Code: "76.123.456-K", + Expected: "76123456K", + }, + } + for _, tt := range tests { + tt := tt + t.Run(string(tt.Code), func(t *testing.T) { + t.Parallel() + tID := &tax.Identity{Country: "CL", Code: tt.Code} + cl.Normalize(tID) + assert.Equal(t, tt.Expected, tID.Code) + }) + } +} + +func TestValidateTaxIdentity(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + country l10n.TaxCountryCode + code cbc.Code + err string + }{ + { + name: "valid RUT 1", + country: "CL", + code: "713254975", + }, + { + name: "valid RUT 2", + country: "CL", + code: "111111111", + }, + { + name: "valid RUT 3", + country: "CL", + code: "100000008", + }, + { + name: "valid RUT 4 with K", + country: "CL", + code: "77668208K", + }, + { + name: "valid RUT 5 with lowercase k", + country: "CL", + code: "77668208k", + }, + { + name: "valid short RUT", + country: "CL", + code: "10000009", + }, + { + name: "valid RUT with check digit 0", + country: "CL", + code: "10000130", + }, + { + name: "empty code", + country: "CL", + code: "", + }, + { + name: "too short - less than 7 digits", + country: "CL", + code: "12345", + err: "invalid RUT format", + }, + { + name: "invalid check digit", + country: "CL", + code: "123456780", + err: "invalid RUT check digit", + }, + { + name: "too long", + country: "CL", + code: "1234567890123", + err: "invalid RUT format", + }, + { + name: "invalid characters", + country: "CL", + code: "1234567A5", + err: "invalid RUT format", + }, + { + name: "wrong check digit K when should be number", + country: "CL", + code: "12345678K", + err: "invalid RUT check digit", + }, + { + name: "non-CL country - should not validate", + country: "AR", + code: "invalid", + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + tID := &tax.Identity{Country: tt.country, Code: tt.code} + err := cl.Validate(tID) + if tt.err == "" { + assert.NoError(t, err) + } else { + if assert.Error(t, err) { + assert.Contains(t, err.Error(), tt.err) + } + } + }) + } +} + +func TestValidateOtherDocuments(t *testing.T) { + t.Parallel() + + type unsupportedDoc struct{} + err := cl.Validate(&unsupportedDoc{}) + assert.NoError(t, err) + + err = cl.Validate(nil) + assert.NoError(t, err) +} diff --git a/regimes/regimes.go b/regimes/regimes.go index ff3cb73a8..806e42569 100644 --- a/regimes/regimes.go +++ b/regimes/regimes.go @@ -12,6 +12,7 @@ import ( _ "github.com/invopop/gobl/regimes/br" _ "github.com/invopop/gobl/regimes/ca" _ "github.com/invopop/gobl/regimes/ch" + _ "github.com/invopop/gobl/regimes/cl" _ "github.com/invopop/gobl/regimes/co" _ "github.com/invopop/gobl/regimes/de" _ "github.com/invopop/gobl/regimes/dk" From 5d821131750087a2a5644cbb8bfc0b7293e83f26 Mon Sep 17 00:00:00 2001 From: Adrian Arencibia Date: Sat, 21 Feb 2026 12:38:31 +0100 Subject: [PATCH 02/11] Update changelog and added nil pointer validations --- CHANGELOG.md | 3 +++ regimes/cl/tax_identity.go | 3 +++ regimes/cl/tax_identity_test.go | 5 +++++ 3 files changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a70a390d3..3f7685d2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p - `gr-mydata-v1`: Corrected exemption codes 3 and 4 mapping to `outside-scope` +### Added +- `cl`: Added the Chilean regime + ## [v0.308.0] - 2026-02-17 ### Removed diff --git a/regimes/cl/tax_identity.go b/regimes/cl/tax_identity.go index eca0a0f06..dd4b48629 100644 --- a/regimes/cl/tax_identity.go +++ b/regimes/cl/tax_identity.go @@ -21,6 +21,9 @@ var ( // validateTaxIdentity checks to ensure the RUT code looks okay. func validateTaxIdentity(tID *tax.Identity) error { + if tID == nil { + return nil + } return validation.ValidateStruct(tID, validation.Field(&tID.Code, validation.When( diff --git a/regimes/cl/tax_identity_test.go b/regimes/cl/tax_identity_test.go index 63a60e52f..4571bbb8b 100644 --- a/regimes/cl/tax_identity_test.go +++ b/regimes/cl/tax_identity_test.go @@ -162,4 +162,9 @@ func TestValidateOtherDocuments(t *testing.T) { err = cl.Validate(nil) assert.NoError(t, err) + + // Test with nil tax.Identity specifically + var nilIdentity *tax.Identity + err = cl.Validate(nilIdentity) + assert.NoError(t, err) } From 14fda7c12eb4cf1a555183be2fafcd5479154fc7 Mon Sep 17 00:00:00 2001 From: Adrian Arencibia Date: Sat, 21 Feb 2026 12:58:44 +0100 Subject: [PATCH 03/11] Update rut validation to handle leading zeros --- regimes/cl/tax_identity.go | 22 ++++++++++------------ regimes/cl/tax_identity_test.go | 6 ++++++ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/regimes/cl/tax_identity.go b/regimes/cl/tax_identity.go index dd4b48629..50e9851f7 100644 --- a/regimes/cl/tax_identity.go +++ b/regimes/cl/tax_identity.go @@ -15,8 +15,9 @@ var ( // rutPattern matches normalized Chilean RUT format (no separators). // Format: 6-8 digits followed by a check digit (0-9 or K/k), for a total of 7-9 characters. // Modern RUTs typically have 8-9 digits total; older RUTs may have 7. + // Leading zeros are not allowed as real Chilean RUTs don't start with zero. // Examples: "713254975" (9), "77668208K" (9), "10000009" (8) - rutPattern = regexp.MustCompile(`^(\d{6,8})([\dKk])$`) + rutPattern = regexp.MustCompile(`^([1-9]\d{5,7})([\dKk])$`) ) // validateTaxIdentity checks to ensure the RUT code looks okay. @@ -106,21 +107,18 @@ func validateRUT(value interface{}) error { // // The calculated check digit as a string ("0"-"9" or "K"), or an error if conversion fails func calculateRUTCheckDigit(rut string) (string, error) { - num, err := strconv.Atoi(rut) - if err != nil { - return "", err - } - - // Apply modulo 11 algorithm - // Process digits from right to left, multiplying by factors 2-7 cyclically sum := 0 multiplier := 2 - for num > 0 { - digit := num % 10 - sum += digit * multiplier + // Process digits from right to left + for i := len(rut) - 1; i >= 0; i-- { + digit := int(rut[i] - '0') - num /= 10 + if digit < 0 || digit > 9 { + return "", strconv.ErrSyntax + } + + sum += digit * multiplier multiplier++ if multiplier > 7 { diff --git a/regimes/cl/tax_identity_test.go b/regimes/cl/tax_identity_test.go index 4571bbb8b..918ab386b 100644 --- a/regimes/cl/tax_identity_test.go +++ b/regimes/cl/tax_identity_test.go @@ -123,6 +123,12 @@ func TestValidateTaxIdentity(t *testing.T) { code: "1234567A5", err: "invalid RUT format", }, + { + name: "leading zero not allowed", + country: "CL", + code: "012345674", + err: "invalid RUT format", + }, { name: "wrong check digit K when should be number", country: "CL", From 09ad3c64b0440ffcf5f8de8c760feab1dd321771 Mon Sep 17 00:00:00 2001 From: Adrian Arencibia Date: Sat, 21 Feb 2026 13:02:06 +0100 Subject: [PATCH 04/11] Update readme --- regimes/cl/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/regimes/cl/README.md b/regimes/cl/README.md index a8319143f..6c0e75c81 100644 --- a/regimes/cl/README.md +++ b/regimes/cl/README.md @@ -53,7 +53,7 @@ When processing a RUT, GOBL automatically: **Examples**: - `71.325.497-5` → `713254975` -- `7.766.820-8K` → `77668208K` +- `77.668.208-k` → `77668208K` - `12.345.678-5` → `123456785` ## Electronic Invoicing From a7d40e05719f3a0c18b6cda5670768dac68bdda6 Mon Sep 17 00:00:00 2001 From: Adrian Arencibia Date: Sat, 21 Feb 2026 13:14:27 +0100 Subject: [PATCH 05/11] Update regime description for rut details --- data/regimes/cl.json | 4 ++-- regimes/cl/cl.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/data/regimes/cl.json b/data/regimes/cl.json index b944ef412..97a02c654 100644 --- a/data/regimes/cl.json +++ b/data/regimes/cl.json @@ -5,8 +5,8 @@ "es": "Chile" }, "description": { - "en": "Chile's tax system is administered by the SII (Servicio de Impuestos Internos), which oversees the collection of IVA (Impuesto al Valor Agregado), the country's value-added tax.\n\nTaxpayers are identified using the RUT (Rol Único Tributario), an 8-digit number with a check digit calculated using the modulo 11 algorithm. The check digit can be 0-9 or K, and RUTs are formatted as XX.XXX.XXX-Y.\n\nChile applies a single standard IVA rate of 19%, effective since October 1, 2003, when it was increased from 18% by Ley 19888. Unlike many other countries, Chile does not have reduced or super-reduced VAT rates.\n\nElectronic invoicing has been mandatory in Chile since 2018 for B2B transactions and since 2021 for B2C transactions. The system is based on DTEs (Documentos Tributarios Electrónicos - Electronic Tax Documents) that must be validated by the SII before being sent to the recipient. The validation process is known as \"prior validation,\" where documents are transmitted to the SII first, validated, returned to the issuer, and then forwarded to the customer. Recipients have 8 days to accept or reject documents; otherwise, they are considered tacitly accepted.\n\nCommon document types include Factura Electrónica (electronic invoice), Boleta Electrónica (electronic receipt), Nota de Crédito Electrónica (electronic credit note), Nota de Débito Electrónica (electronic debit note), and Guía de Despacho (dispatch guide). All DTEs must be archived for 6 years in the XML format validated by the SII.", - "es": "El sistema tributario de Chile es administrado por el SII (Servicio de Impuestos Internos), que supervisa la recaudación del IVA (Impuesto al Valor Agregado).\n\nLos contribuyentes se identifican mediante el RUT (Rol Único Tributario), un número de 8 dígitos con un dígito verificador calculado mediante el algoritmo módulo 11. El dígito verificador puede ser 0-9 o K, y los RUT se formatean como XX.XXX.XXX-Y.\n\nChile aplica una tasa única de IVA del 19%, vigente desde el 1 de octubre de 2003, cuando fue aumentada del 18% mediante la Ley 19888. A diferencia de muchos otros países, Chile no tiene tasas reducidas o super-reducidas de IVA.\n\nLa facturación electrónica es obligatoria en Chile desde 2018 para transacciones B2B y desde 2021 para transacciones B2C. El sistema se basa en DTEs (Documentos Tributarios Electrónicos) que deben ser validados por el SII antes de enviarse al receptor. El proceso de validación se conoce como \"validación previa\", donde los documentos se transmiten primero al SII, se validan, se devuelven al emisor y luego se reenvían al cliente. Los receptores tienen 8 días para aceptar o rechazar documentos; de lo contrario, se consideran aceptados tácitamente.\n\nLos tipos de documentos comunes incluyen Factura Electrónica, Boleta Electrónica, Nota de Crédito Electrónica, Nota de Débito Electrónica y Guía de Despacho. Todos los DTEs deben archivarse durante 6 años en el formato XML validado por el SII." + "en": "Chile's tax system is administered by the SII (Servicio de Impuestos Internos), which oversees the collection of IVA (Impuesto al Valor Agregado), the country's value-added tax.\n\nTaxpayers are identified using the RUT (Rol Único Tributario), an 6-8 digits number with a check digit calculated using the modulo 11 algorithm. The check digit can be 0-9 or K, and RUTs are formatted as XX.XXX.XXX-Y.\n\nChile applies a single standard IVA rate of 19%, effective since October 1, 2003, when it was increased from 18% by Ley 19888. Unlike many other countries, Chile does not have reduced or super-reduced VAT rates.\n\nElectronic invoicing has been mandatory in Chile since 2018 for B2B transactions and since 2021 for B2C transactions. The system is based on DTEs (Documentos Tributarios Electrónicos - Electronic Tax Documents) that must be validated by the SII before being sent to the recipient. The validation process is known as \"prior validation,\" where documents are transmitted to the SII first, validated, returned to the issuer, and then forwarded to the customer. Recipients have 8 days to accept or reject documents; otherwise, they are considered tacitly accepted.\n\nCommon document types include Factura Electrónica (electronic invoice), Boleta Electrónica (electronic receipt), Nota de Crédito Electrónica (electronic credit note), Nota de Débito Electrónica (electronic debit note), and Guía de Despacho (dispatch guide). All DTEs must be archived for 6 years in the XML format validated by the SII.", + "es": "El sistema tributario de Chile es administrado por el SII (Servicio de Impuestos Internos), que supervisa la recaudación del IVA (Impuesto al Valor Agregado).\n\nLos contribuyentes se identifican mediante el RUT (Rol Único Tributario), un número de 6-8 dígitos con un dígito verificador calculado mediante el algoritmo módulo 11. El dígito verificador puede ser 0-9 o K, y los RUT se formatean como XX.XXX.XXX-Y.\n\nChile aplica una tasa única de IVA del 19%, vigente desde el 1 de octubre de 2003, cuando fue aumentada del 18% mediante la Ley 19888. A diferencia de muchos otros países, Chile no tiene tasas reducidas o super-reducidas de IVA.\n\nLa facturación electrónica es obligatoria en Chile desde 2018 para transacciones B2B y desde 2021 para transacciones B2C. El sistema se basa en DTEs (Documentos Tributarios Electrónicos) que deben ser validados por el SII antes de enviarse al receptor. El proceso de validación se conoce como \"validación previa\", donde los documentos se transmiten primero al SII, se validan, se devuelven al emisor y luego se reenvían al cliente. Los receptores tienen 8 días para aceptar o rechazar documentos; de lo contrario, se consideran aceptados tácitamente.\n\nLos tipos de documentos comunes incluyen Factura Electrónica, Boleta Electrónica, Nota de Crédito Electrónica, Nota de Débito Electrónica y Guía de Despacho. Todos los DTEs deben archivarse durante 6 años en el formato XML validado por el SII." }, "time_zone": "America/Santiago", "country": "CL", diff --git a/regimes/cl/cl.go b/regimes/cl/cl.go index 8b6f18c4d..217c7aaff 100644 --- a/regimes/cl/cl.go +++ b/regimes/cl/cl.go @@ -26,7 +26,7 @@ func New() *tax.RegimeDef { i18n.EN: here.Doc(` Chile's tax system is administered by the SII (Servicio de Impuestos Internos), which oversees the collection of IVA (Impuesto al Valor Agregado), the country's value-added tax. - Taxpayers are identified using the RUT (Rol Único Tributario), an 8-digit number with a check digit calculated using the modulo 11 algorithm. The check digit can be 0-9 or K, and RUTs are formatted as XX.XXX.XXX-Y. + Taxpayers are identified using the RUT (Rol Único Tributario), an 6-8 digits number with a check digit calculated using the modulo 11 algorithm. The check digit can be 0-9 or K, and RUTs are formatted as XX.XXX.XXX-Y. Chile applies a single standard IVA rate of 19%, effective since October 1, 2003, when it was increased from 18% by Ley 19888. Unlike many other countries, Chile does not have reduced or super-reduced VAT rates. @@ -37,7 +37,7 @@ func New() *tax.RegimeDef { i18n.ES: here.Doc(` El sistema tributario de Chile es administrado por el SII (Servicio de Impuestos Internos), que supervisa la recaudación del IVA (Impuesto al Valor Agregado). - Los contribuyentes se identifican mediante el RUT (Rol Único Tributario), un número de 8 dígitos con un dígito verificador calculado mediante el algoritmo módulo 11. El dígito verificador puede ser 0-9 o K, y los RUT se formatean como XX.XXX.XXX-Y. + Los contribuyentes se identifican mediante el RUT (Rol Único Tributario), un número de 6-8 dígitos con un dígito verificador calculado mediante el algoritmo módulo 11. El dígito verificador puede ser 0-9 o K, y los RUT se formatean como XX.XXX.XXX-Y. Chile aplica una tasa única de IVA del 19%, vigente desde el 1 de octubre de 2003, cuando fue aumentada del 18% mediante la Ley 19888. A diferencia de muchos otros países, Chile no tiene tasas reducidas o super-reducidas de IVA. From 9401d0138b84a07a5f54c6c07aee98e3a266bfeb Mon Sep 17 00:00:00 2001 From: Adrian Arencibia Date: Sat, 21 Feb 2026 13:21:53 +0100 Subject: [PATCH 06/11] Fix typo in description --- data/regimes/cl.json | 2 +- regimes/cl/cl.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/regimes/cl.json b/data/regimes/cl.json index 97a02c654..76cd7d8a1 100644 --- a/data/regimes/cl.json +++ b/data/regimes/cl.json @@ -5,7 +5,7 @@ "es": "Chile" }, "description": { - "en": "Chile's tax system is administered by the SII (Servicio de Impuestos Internos), which oversees the collection of IVA (Impuesto al Valor Agregado), the country's value-added tax.\n\nTaxpayers are identified using the RUT (Rol Único Tributario), an 6-8 digits number with a check digit calculated using the modulo 11 algorithm. The check digit can be 0-9 or K, and RUTs are formatted as XX.XXX.XXX-Y.\n\nChile applies a single standard IVA rate of 19%, effective since October 1, 2003, when it was increased from 18% by Ley 19888. Unlike many other countries, Chile does not have reduced or super-reduced VAT rates.\n\nElectronic invoicing has been mandatory in Chile since 2018 for B2B transactions and since 2021 for B2C transactions. The system is based on DTEs (Documentos Tributarios Electrónicos - Electronic Tax Documents) that must be validated by the SII before being sent to the recipient. The validation process is known as \"prior validation,\" where documents are transmitted to the SII first, validated, returned to the issuer, and then forwarded to the customer. Recipients have 8 days to accept or reject documents; otherwise, they are considered tacitly accepted.\n\nCommon document types include Factura Electrónica (electronic invoice), Boleta Electrónica (electronic receipt), Nota de Crédito Electrónica (electronic credit note), Nota de Débito Electrónica (electronic debit note), and Guía de Despacho (dispatch guide). All DTEs must be archived for 6 years in the XML format validated by the SII.", + "en": "Chile's tax system is administered by the SII (Servicio de Impuestos Internos), which oversees the collection of IVA (Impuesto al Valor Agregado), the country's value-added tax.\n\nTaxpayers are identified using the RUT (Rol Único Tributario), a 6-8 digits number with a check digit calculated using the modulo 11 algorithm. The check digit can be 0-9 or K, and RUTs are formatted as XX.XXX.XXX-Y.\n\nChile applies a single standard IVA rate of 19%, effective since October 1, 2003, when it was increased from 18% by Ley 19888. Unlike many other countries, Chile does not have reduced or super-reduced VAT rates.\n\nElectronic invoicing has been mandatory in Chile since 2018 for B2B transactions and since 2021 for B2C transactions. The system is based on DTEs (Documentos Tributarios Electrónicos - Electronic Tax Documents) that must be validated by the SII before being sent to the recipient. The validation process is known as \"prior validation,\" where documents are transmitted to the SII first, validated, returned to the issuer, and then forwarded to the customer. Recipients have 8 days to accept or reject documents; otherwise, they are considered tacitly accepted.\n\nCommon document types include Factura Electrónica (electronic invoice), Boleta Electrónica (electronic receipt), Nota de Crédito Electrónica (electronic credit note), Nota de Débito Electrónica (electronic debit note), and Guía de Despacho (dispatch guide). All DTEs must be archived for 6 years in the XML format validated by the SII.", "es": "El sistema tributario de Chile es administrado por el SII (Servicio de Impuestos Internos), que supervisa la recaudación del IVA (Impuesto al Valor Agregado).\n\nLos contribuyentes se identifican mediante el RUT (Rol Único Tributario), un número de 6-8 dígitos con un dígito verificador calculado mediante el algoritmo módulo 11. El dígito verificador puede ser 0-9 o K, y los RUT se formatean como XX.XXX.XXX-Y.\n\nChile aplica una tasa única de IVA del 19%, vigente desde el 1 de octubre de 2003, cuando fue aumentada del 18% mediante la Ley 19888. A diferencia de muchos otros países, Chile no tiene tasas reducidas o super-reducidas de IVA.\n\nLa facturación electrónica es obligatoria en Chile desde 2018 para transacciones B2B y desde 2021 para transacciones B2C. El sistema se basa en DTEs (Documentos Tributarios Electrónicos) que deben ser validados por el SII antes de enviarse al receptor. El proceso de validación se conoce como \"validación previa\", donde los documentos se transmiten primero al SII, se validan, se devuelven al emisor y luego se reenvían al cliente. Los receptores tienen 8 días para aceptar o rechazar documentos; de lo contrario, se consideran aceptados tácitamente.\n\nLos tipos de documentos comunes incluyen Factura Electrónica, Boleta Electrónica, Nota de Crédito Electrónica, Nota de Débito Electrónica y Guía de Despacho. Todos los DTEs deben archivarse durante 6 años en el formato XML validado por el SII." }, "time_zone": "America/Santiago", diff --git a/regimes/cl/cl.go b/regimes/cl/cl.go index 217c7aaff..e9e465b06 100644 --- a/regimes/cl/cl.go +++ b/regimes/cl/cl.go @@ -26,7 +26,7 @@ func New() *tax.RegimeDef { i18n.EN: here.Doc(` Chile's tax system is administered by the SII (Servicio de Impuestos Internos), which oversees the collection of IVA (Impuesto al Valor Agregado), the country's value-added tax. - Taxpayers are identified using the RUT (Rol Único Tributario), an 6-8 digits number with a check digit calculated using the modulo 11 algorithm. The check digit can be 0-9 or K, and RUTs are formatted as XX.XXX.XXX-Y. + Taxpayers are identified using the RUT (Rol Único Tributario), a 6-8 digits number with a check digit calculated using the modulo 11 algorithm. The check digit can be 0-9 or K, and RUTs are formatted as XX.XXX.XXX-Y. Chile applies a single standard IVA rate of 19%, effective since October 1, 2003, when it was increased from 18% by Ley 19888. Unlike many other countries, Chile does not have reduced or super-reduced VAT rates. From 467297b33c2471cdef853f8b23709594d1d6f873 Mon Sep 17 00:00:00 2001 From: Adrian Arencibia Date: Wed, 25 Feb 2026 15:52:52 +0100 Subject: [PATCH 07/11] Add CL historical 18% VAT rate --- data/regimes/cl.json | 5 +++++ regimes/cl/tax_categories.go | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/data/regimes/cl.json b/data/regimes/cl.json index 76cd7d8a1..9025798df 100644 --- a/data/regimes/cl.json +++ b/data/regimes/cl.json @@ -87,6 +87,11 @@ "es": "Tasa General" }, "values": [ + { + "since": "1990-07-01", + "percent": "18%", + "disabled": true + }, { "since": "2003-10-01", "percent": "19%" diff --git a/regimes/cl/tax_categories.go b/regimes/cl/tax_categories.go index b402271a2..a0069eff1 100644 --- a/regimes/cl/tax_categories.go +++ b/regimes/cl/tax_categories.go @@ -62,6 +62,11 @@ var taxCategories = []*tax.CategoryDef{ i18n.ES: "Tasa General", }, Values: []*tax.RateValueDef{ + { + Since: cal.NewDate(1990, 7, 1), + Percent: num.MakePercentage(18, 2), + Disabled: true, + }, { Since: cal.NewDate(2003, 10, 1), Percent: num.MakePercentage(19, 2), From b05d18e9e3771d5a02db540099a4dbeaea33bebb Mon Sep 17 00:00:00 2001 From: Adrian Arencibia Date: Wed, 25 Feb 2026 21:29:02 +0100 Subject: [PATCH 08/11] Fix pr comments. Add more validations and extra documentation --- data/regimes/cl.json | 13 +- .../cl/invoice-simplified-with-customer.json | 66 ++++ examples/cl/invoice-simplified.json | 67 ++++ .../out/invoice-simplified-with-customer.json | 107 ++++++ examples/cl/out/invoice-simplified.json | 108 +++++++ regimes/cl/README.md | 114 ------- regimes/cl/cl.go | 28 +- regimes/cl/invoices.go | 102 ++++++ regimes/cl/invoices_test.go | 306 ++++++++++++++++++ regimes/cl/tax_categories.go | 9 +- regimes/cl/tax_identity.go | 20 +- 11 files changed, 808 insertions(+), 132 deletions(-) create mode 100644 examples/cl/invoice-simplified-with-customer.json create mode 100644 examples/cl/invoice-simplified.json create mode 100644 examples/cl/out/invoice-simplified-with-customer.json create mode 100644 examples/cl/out/invoice-simplified.json delete mode 100644 regimes/cl/README.md create mode 100644 regimes/cl/invoices.go create mode 100644 regimes/cl/invoices_test.go diff --git a/data/regimes/cl.json b/data/regimes/cl.json index 9025798df..30c961901 100644 --- a/data/regimes/cl.json +++ b/data/regimes/cl.json @@ -5,8 +5,8 @@ "es": "Chile" }, "description": { - "en": "Chile's tax system is administered by the SII (Servicio de Impuestos Internos), which oversees the collection of IVA (Impuesto al Valor Agregado), the country's value-added tax.\n\nTaxpayers are identified using the RUT (Rol Único Tributario), a 6-8 digits number with a check digit calculated using the modulo 11 algorithm. The check digit can be 0-9 or K, and RUTs are formatted as XX.XXX.XXX-Y.\n\nChile applies a single standard IVA rate of 19%, effective since October 1, 2003, when it was increased from 18% by Ley 19888. Unlike many other countries, Chile does not have reduced or super-reduced VAT rates.\n\nElectronic invoicing has been mandatory in Chile since 2018 for B2B transactions and since 2021 for B2C transactions. The system is based on DTEs (Documentos Tributarios Electrónicos - Electronic Tax Documents) that must be validated by the SII before being sent to the recipient. The validation process is known as \"prior validation,\" where documents are transmitted to the SII first, validated, returned to the issuer, and then forwarded to the customer. Recipients have 8 days to accept or reject documents; otherwise, they are considered tacitly accepted.\n\nCommon document types include Factura Electrónica (electronic invoice), Boleta Electrónica (electronic receipt), Nota de Crédito Electrónica (electronic credit note), Nota de Débito Electrónica (electronic debit note), and Guía de Despacho (dispatch guide). All DTEs must be archived for 6 years in the XML format validated by the SII.", - "es": "El sistema tributario de Chile es administrado por el SII (Servicio de Impuestos Internos), que supervisa la recaudación del IVA (Impuesto al Valor Agregado).\n\nLos contribuyentes se identifican mediante el RUT (Rol Único Tributario), un número de 6-8 dígitos con un dígito verificador calculado mediante el algoritmo módulo 11. El dígito verificador puede ser 0-9 o K, y los RUT se formatean como XX.XXX.XXX-Y.\n\nChile aplica una tasa única de IVA del 19%, vigente desde el 1 de octubre de 2003, cuando fue aumentada del 18% mediante la Ley 19888. A diferencia de muchos otros países, Chile no tiene tasas reducidas o super-reducidas de IVA.\n\nLa facturación electrónica es obligatoria en Chile desde 2018 para transacciones B2B y desde 2021 para transacciones B2C. El sistema se basa en DTEs (Documentos Tributarios Electrónicos) que deben ser validados por el SII antes de enviarse al receptor. El proceso de validación se conoce como \"validación previa\", donde los documentos se transmiten primero al SII, se validan, se devuelven al emisor y luego se reenvían al cliente. Los receptores tienen 8 días para aceptar o rechazar documentos; de lo contrario, se consideran aceptados tácitamente.\n\nLos tipos de documentos comunes incluyen Factura Electrónica, Boleta Electrónica, Nota de Crédito Electrónica, Nota de Débito Electrónica y Guía de Despacho. Todos los DTEs deben archivarse durante 6 años en el formato XML validado por el SII." + "en": "Chile's tax system is administered by the SII (Servicio de Impuestos Internos), which oversees the collection of IVA (Impuesto al Valor Agregado), the country's value-added tax.\n\nTaxpayers are identified using the RUT (Rol Único Tributario), a 6-8 digits number with a check digit calculated using the modulo 11 algorithm. The check digit can be 0-9 or K, and RUTs are formatted as XX.XXX.XXX-Y. Both supplier and customer RUT are mandatory for Facturas Electrónicas (B2B invoices), while customer RUT is optional for Boletas Electrónicas (B2C receipts). Supplier address is always required, and customer address is required for B2B transactions.\n\nChile applies a single standard IVA rate of 19%, effective since October 1, 2003, when it was increased from 18% by Ley 19888. Unlike many other countries, Chile does not have reduced or super-reduced VAT rates.\n\nElectronic invoicing has been mandatory in Chile since 2018 for B2B transactions and since 2021 for B2C transactions. The system is based on DTEs (Documentos Tributarios Electrónicos - Electronic Tax Documents) that must be validated by the SII before being sent to the recipient. The validation process is known as \"prior validation,\" where documents are transmitted to the SII first, validated, returned to the issuer, and then forwarded to the customer. Recipients have 8 days to accept or reject documents; otherwise, they are considered tacitly accepted.\n\nCommon document types include Factura Electrónica (electronic invoice for B2B), Boleta Electrónica (electronic receipt for B2C), Nota de Crédito Electrónica (electronic credit note), Nota de Débito Electrónica (electronic debit note), and Guía de Despacho (dispatch guide). Use the \"simplified\" tag to indicate Boletas Electrónicas, which have relaxed customer identification requirements. All DTEs must be archived for 6 years in the XML format validated by the SII.\n\nAdditional SII requirements include Giro Comercial (business activity) for both parties, complete address details (Dirección, Ciudad, Comuna), and clear item descriptions (Resolution 36/2024, effective July 2024).", + "es": "El sistema tributario de Chile es administrado por el SII (Servicio de Impuestos Internos), que supervisa la recaudación del IVA (Impuesto al Valor Agregado).\n\nLos contribuyentes se identifican mediante el RUT (Rol Único Tributario), un número de 6-8 dígitos con un dígito verificador calculado mediante el algoritmo módulo 11. El dígito verificador puede ser 0-9 o K, y los RUT se formatean como XX.XXX.XXX-Y. El RUT del emisor y receptor es obligatorio para Facturas Electrónicas (B2B), mientras que el RUT del receptor es opcional para Boletas Electrónicas (B2C). La dirección del emisor es siempre requerida, y la dirección del receptor es requerida para transacciones B2B.\n\nChile aplica una tasa única de IVA del 19%, vigente desde el 1 de octubre de 2003, cuando fue aumentada del 18% mediante la Ley 19888. A diferencia de muchos otros países, Chile no tiene tasas reducidas o super-reducidas de IVA.\n\nLa facturación electrónica es obligatoria en Chile desde 2018 para transacciones B2B y desde 2021 para transacciones B2C. El sistema se basa en DTEs (Documentos Tributarios Electrónicos) que deben ser validados por el SII antes de enviarse al receptor. El proceso de validación se conoce como \"validación previa\", donde los documentos se transmiten primero al SII, se validan, se devuelven al emisor y luego se reenvían al cliente. Los receptores tienen 8 días para aceptar o rechazar documentos; de lo contrario, se consideran aceptados tácitamente.\n\nLos tipos de documentos comunes incluyen Factura Electrónica (factura para B2B), Boleta Electrónica (boleta para B2C), Nota de Crédito Electrónica, Nota de Débito Electrónica y Guía de Despacho. Use la etiqueta \"simplified\" para indicar Boletas Electrónicas, que tienen requisitos de identificación del cliente más flexibles. Todos los DTEs deben archivarse durante 6 años en el formato XML validado por el SII.\n\nRequisitos adicionales del SII incluyen Giro Comercial (actividad económica) para ambas partes, detalles completos de dirección (Dirección, Ciudad, Comuna), y descripciones claras de los ítems (Resolución 36/2024, vigente desde julio 2024)." }, "time_zone": "America/Santiago", "country": "CL", @@ -87,14 +87,13 @@ "es": "Tasa General" }, "values": [ - { - "since": "1990-07-01", - "percent": "18%", - "disabled": true - }, { "since": "2003-10-01", "percent": "19%" + }, + { + "since": "1990-07-01", + "percent": "18%" } ] } diff --git a/examples/cl/invoice-simplified-with-customer.json b/examples/cl/invoice-simplified-with-customer.json new file mode 100644 index 000000000..de39822d2 --- /dev/null +++ b/examples/cl/invoice-simplified-with-customer.json @@ -0,0 +1,66 @@ +{ + "$schema": "https://gobl.org/draft-0/bill/invoice", + "$regime": "CL", + "$tags": [ + "simplified" + ], + "uuid": "9f3c8b72-1ab5-4d9e-9c3f-f4e2d3c4b5a6", + "code": "B001-00000789", + "issue_date": "2025-01-20", + "currency": "CLP", + "supplier": { + "name": "Tienda de Electrónica Tech Store", + "tax_id": { + "country": "CL", + "code": "713254975" + }, + "addresses": [ + { + "street": "Av. Apoquindo 3500", + "locality": "Las Condes", + "region": "Región Metropolitana", + "code": "7550000", + "country": "CL" + } + ] + }, + "customer": { + "name": "Juan Pérez", + "tax_id": { + "country": "CL", + "code": "77668208K" + } + }, + "lines": [ + { + "quantity": "1", + "item": { + "name": "Notebook HP Pavilion 15", + "price": "599000" + }, + "taxes": [ + { + "cat": "VAT", + "key": "standard", + "rate": "general", + "percent": "19%" + } + ] + }, + { + "quantity": "1", + "item": { + "name": "Mouse inalámbrico", + "price": "15000" + }, + "taxes": [ + { + "cat": "VAT", + "key": "standard", + "rate": "general", + "percent": "19%" + } + ] + } + ] +} diff --git a/examples/cl/invoice-simplified.json b/examples/cl/invoice-simplified.json new file mode 100644 index 000000000..5ed837c3a --- /dev/null +++ b/examples/cl/invoice-simplified.json @@ -0,0 +1,67 @@ +{ + "$schema": "https://gobl.org/draft-0/bill/invoice", + "$regime": "CL", + "$tags": [ + "simplified" + ], + "uuid": "8d51fd61-9db6-41cf-8d44-e3a1e1b48d9a", + "code": "B001-00000456", + "issue_date": "2025-01-15", + "currency": "CLP", + "supplier": { + "name": "Restaurante El Buen Sabor", + "tax_id": { + "country": "CL", + "code": "713254975" + }, + "addresses": [ + { + "street": "Av. Providencia 1234", + "locality": "Providencia", + "region": "Región Metropolitana", + "code": "7500000", + "country": "CL" + } + ], + "emails": [ + { + "addr": "contacto@buensabor.cl" + } + ] + }, + "customer": { + "name": "Cliente Final" + }, + "lines": [ + { + "quantity": "2", + "item": { + "name": "Almuerzo Ejecutivo", + "price": "8500" + }, + "taxes": [ + { + "cat": "VAT", + "key": "standard", + "rate": "general", + "percent": "19%" + } + ] + }, + { + "quantity": "2", + "item": { + "name": "Bebida", + "price": "2000" + }, + "taxes": [ + { + "cat": "VAT", + "key": "standard", + "rate": "general", + "percent": "19%" + } + ] + } + ] +} diff --git a/examples/cl/out/invoice-simplified-with-customer.json b/examples/cl/out/invoice-simplified-with-customer.json new file mode 100644 index 000000000..103a37075 --- /dev/null +++ b/examples/cl/out/invoice-simplified-with-customer.json @@ -0,0 +1,107 @@ +{ + "$schema": "https://gobl.org/draft-0/envelope", + "head": { + "uuid": "8a51fd30-2a27-11ee-be56-0242ac120002", + "dig": { + "alg": "sha256", + "val": "fc37df36fc7e90f616eb8cb98c127dde40f54b8cdc13b44de2461d079873ccdb" + } + }, + "doc": { + "$schema": "https://gobl.org/draft-0/bill/invoice", + "$regime": "CL", + "$tags": [ + "simplified" + ], + "uuid": "9f3c8b72-1ab5-4d9e-9c3f-f4e2d3c4b5a6", + "type": "standard", + "code": "B001-00000789", + "issue_date": "2025-01-20", + "currency": "CLP", + "supplier": { + "name": "Tienda de Electrónica Tech Store", + "tax_id": { + "country": "CL", + "code": "713254975" + }, + "addresses": [ + { + "street": "Av. Apoquindo 3500", + "locality": "Las Condes", + "region": "Región Metropolitana", + "code": "7550000", + "country": "CL" + } + ] + }, + "customer": { + "name": "Juan Pérez", + "tax_id": { + "country": "CL", + "code": "77668208K" + } + }, + "lines": [ + { + "i": 1, + "quantity": "1", + "item": { + "name": "Notebook HP Pavilion 15", + "price": "599000" + }, + "sum": "599000", + "taxes": [ + { + "cat": "VAT", + "key": "standard", + "rate": "general", + "percent": "19%" + } + ], + "total": "599000" + }, + { + "i": 2, + "quantity": "1", + "item": { + "name": "Mouse inalámbrico", + "price": "15000" + }, + "sum": "15000", + "taxes": [ + { + "cat": "VAT", + "key": "standard", + "rate": "general", + "percent": "19%" + } + ], + "total": "15000" + } + ], + "totals": { + "sum": "614000", + "total": "614000", + "taxes": { + "categories": [ + { + "code": "VAT", + "rates": [ + { + "key": "standard", + "base": "614000", + "percent": "19%", + "amount": "116660" + } + ], + "amount": "116660" + } + ], + "sum": "116660" + }, + "tax": "116660", + "total_with_tax": "730660", + "payable": "730660" + } + } +} \ No newline at end of file diff --git a/examples/cl/out/invoice-simplified.json b/examples/cl/out/invoice-simplified.json new file mode 100644 index 000000000..63261884a --- /dev/null +++ b/examples/cl/out/invoice-simplified.json @@ -0,0 +1,108 @@ +{ + "$schema": "https://gobl.org/draft-0/envelope", + "head": { + "uuid": "8a51fd30-2a27-11ee-be56-0242ac120002", + "dig": { + "alg": "sha256", + "val": "7ac00af90933266101a735fd93dedb014451ecf3ae08e74f444f84de40d53e12" + } + }, + "doc": { + "$schema": "https://gobl.org/draft-0/bill/invoice", + "$regime": "CL", + "$tags": [ + "simplified" + ], + "uuid": "8d51fd61-9db6-41cf-8d44-e3a1e1b48d9a", + "type": "standard", + "code": "B001-00000456", + "issue_date": "2025-01-15", + "currency": "CLP", + "supplier": { + "name": "Restaurante El Buen Sabor", + "tax_id": { + "country": "CL", + "code": "713254975" + }, + "addresses": [ + { + "street": "Av. Providencia 1234", + "locality": "Providencia", + "region": "Región Metropolitana", + "code": "7500000", + "country": "CL" + } + ], + "emails": [ + { + "addr": "contacto@buensabor.cl" + } + ] + }, + "customer": { + "name": "Cliente Final" + }, + "lines": [ + { + "i": 1, + "quantity": "2", + "item": { + "name": "Almuerzo Ejecutivo", + "price": "8500" + }, + "sum": "17000", + "taxes": [ + { + "cat": "VAT", + "key": "standard", + "rate": "general", + "percent": "19%" + } + ], + "total": "17000" + }, + { + "i": 2, + "quantity": "2", + "item": { + "name": "Bebida", + "price": "2000" + }, + "sum": "4000", + "taxes": [ + { + "cat": "VAT", + "key": "standard", + "rate": "general", + "percent": "19%" + } + ], + "total": "4000" + } + ], + "totals": { + "sum": "21000", + "total": "21000", + "taxes": { + "categories": [ + { + "code": "VAT", + "rates": [ + { + "key": "standard", + "base": "21000", + "percent": "19%", + "amount": "3990" + } + ], + "amount": "3990" + } + ], + "sum": "3990" + }, + "tax": "3990", + "total_with_tax": "24990", + "payable": "24990" + } + } +} \ No newline at end of file diff --git a/regimes/cl/README.md b/regimes/cl/README.md deleted file mode 100644 index 6c0e75c81..000000000 --- a/regimes/cl/README.md +++ /dev/null @@ -1,114 +0,0 @@ -# Chile (CL) - Tax Regime - -Chile's tax regime implementation for GOBL based on the requirements of the Chilean Tax Authority (Servicio de Impuestos Internos - SII). - -## Tax Categories - -### IVA (Impuesto al Valor Agregado) - -Chile's Value Added Tax (VAT) is called IVA. The consumption tax was introduced in December 1974 through [Decreto Ley Nº 825](https://www.sii.cl/normativa_legislacion/sobreventasyservicios.pdf). - -- **Standard Rate**: 19% (effective October 1, 2003) -- **Historical Rate**: 18% (prior to October 1, 2003) - -The current 19% rate was established by [Ley 19888](https://www.bcn.cl/leychile/Navegar?idNorma=213493), published August 13, 2003, which amended Article 14 of the VAT law to increase the rate from 18% to 19%. Chile applies a single VAT rate with no reduced rates. - -**Source**: [Law No. 21.210](https://www.sii.cl/vat/faq1_eng.html) confirmed the 19% rate applies to digital services provided by non-resident taxpayers. - -## Tax Identity - -Chile uses the **RUT** (Rol Único Tributario) as the primary tax identification number for both individuals and legal entities, issued and maintained by the SII. - -### RUT Format - -The RUT consists of: -- **Numeric portion**: 6 to 8 digits -- **Check digit**: Single character (0-9 or K) -- **Total length**: 7 to 9 characters (after normalization) -- **Display format**: `XX.XXX.XXX-Y` where dots and hyphen are used for readability -- **Normalized format**: Removes all separators (e.g., `713254975`, `77668208K`) - -Modern RUTs typically have 8-9 total digits, while older RUTs may have 7. The SII now handles RUT numbers ranging from 7 to 9 digits in total length. - -### Check Digit Calculation - -The check digit is calculated using the **Modulo 11 algorithm**, which is the exclusive validation method mandated by the SII for RUT verification in Chile. - -**Implementation Note**: This algorithm is implemented in the `calculateRUTCheckDigit` function in `tax_identity.go`. - -**Sources**: -- [Rol Único Tributario - Wikipedia](https://es.wikipedia.org/wiki/Rol_%C3%9Anico_Tributario) -- [Modificaciones para manejo de RUT de 7 a 9 dígitos](https://help.getcirrus.com/es/articles/8515715-modificaciones-para-manejo-de-rut-de-7-a-9-digitos-chile) - -### Validation and Normalization - -GOBL implements comprehensive RUT validation and normalization to ensure data consistency and compliance with SII standards. - -#### Normalization Process - -When processing a RUT, GOBL automatically: - -1. **Removes formatting characters**: Strips all dots (`.`) and hyphens (`-`) -2. **Normalizes case**: Converts lowercase `k` to uppercase `K` for the check digit - -**Examples**: -- `71.325.497-5` → `713254975` -- `77.668.208-k` → `77668208K` -- `12.345.678-5` → `123456785` - -## Electronic Invoicing - -Chile has a mandatory electronic invoicing system managed by SII, based on **DTE** (Documentos Tributarios Electrónicos - Electronic Tax Documents). - -### Implementation Timeline - -- **2001**: E-invoicing implemented as voluntary scheme -- **2014**: VAT e-invoicing made mandatory for established organizations -- **March 2018**: B2B e-invoicing made mandatory -- **March 2021**: B2C e-invoicing made mandatory - -### Validation Process - -The Chilean system uses **prior validation** by the SII: -1. DTEs must be transmitted to SII for validation before being sent to customers -2. Once validated, SII returns the document to the issuer -3. Document is forwarded to recipient -4. Recipient has 8 days to accept or reject -5. If no action taken, document is considered tacitly accepted - -### Document Types - -Main DTEs required by SII: -- **Factura Electrónica** (Electronic Invoice) -- **Boleta Electrónica** (Electronic Receipt) -- **Nota de Crédito Electrónica** (Electronic Credit Note) -- **Nota de Débito Electrónica** (Electronic Debit Note) -- **Guía de Despacho** (Dispatch Guide) -- **Factura de Exportación** (Export Invoice) - -### Archiving Requirements - -- DTEs must be archived for **6 years** -- Must be kept in the **XML format** validated by SII - -**Sources**: -- [SII Electronic Invoicing System](https://www.chileatiende.gob.cl/fichas/13505-emision-de-documentos-tributarios-electronicos-dte-sistema-de-facturacion-gratuito-del-sii) -- [Electronic Invoicing in Chile - EDICOM](https://edicomgroup.com/electronic-invoicing/chile) -- [What is Electronic Invoicing - SII](https://www.sii.cl/factura_electronica/que_es_fact_elect.htm) - -## References - -### Official Sources -- [Servicio de Impuestos Internos (SII)](https://www.sii.cl/) - Chilean Tax Authority -- [Decreto Ley Nº 825 - VAT Law](https://www.sii.cl/normativa_legislacion/sobreventasyservicios.pdf) - Law on VAT and Services (1974) -- [Ley 19888](https://www.bcn.cl/leychile/Navegar?idNorma=213493) - Law establishing 19% VAT rate (2003) -- [IVA Digital - SII](https://www.sii.cl/vat/faq1_eng.html) - Official VAT information (English) - -### Tax Identification -- [Rol Único Tributario - Wikipedia](https://es.wikipedia.org/wiki/Rol_%C3%9Anico_Tributario) -- [RUT Format Changes (7-9 digits) - Cirrus Help Center](https://help.getcirrus.com/es/articles/8515715-modificaciones-para-manejo-de-rut-de-7-a-9-digitos-chile) - -### Electronic Invoicing -- [DTE System - ChileAtiende](https://www.chileatiende.gob.cl/fichas/13505-emision-de-documentos-tributarios-electronicos-dte-sistema-de-facturacion-gratuito-del-sii) -- [Electronic Invoicing Overview - EDICOM](https://edicomgroup.com/electronic-invoicing/chile) -- [SII Electronic Invoice Information](https://www.sii.cl/factura_electronica/que_es_fact_elect.htm) diff --git a/regimes/cl/cl.go b/regimes/cl/cl.go index e9e465b06..746b24311 100644 --- a/regimes/cl/cl.go +++ b/regimes/cl/cl.go @@ -1,7 +1,21 @@ // Package cl handles tax regime data for Chile. +// +// This package implements validation and normalization for Chilean tax documents +// according to the requirements of the SII (Servicio de Impuestos Internos). +// +// Key regulations: +// - Decreto Ley Nº 825 (1974): VAT Law - https://www.sii.cl/normativa_legislacion/sobreventasyservicios.pdf +// - Ley 19888 (2003): Established 19% VAT rate - https://www.bcn.cl/leychile/Navegar?idNorma=213493 +// - Resolution 36/2024: Item description requirements (effective July 2024) +// +// Electronic invoicing references: +// - SII Electronic Invoicing Portal: https://www.sii.cl/factura_electronica/ +// - DTE Format Specification: https://www.sii.cl/factura_electronica/factura_mercado/formato_dte.pdf +// - Boleta Format Specification: https://www.sii.cl/factura_electronica/factura_mercado/formato_boletas_elec_202306.pdf package cl import ( + "github.com/invopop/gobl/bill" "github.com/invopop/gobl/currency" "github.com/invopop/gobl/i18n" "github.com/invopop/gobl/pkg/here" @@ -26,24 +40,28 @@ func New() *tax.RegimeDef { i18n.EN: here.Doc(` Chile's tax system is administered by the SII (Servicio de Impuestos Internos), which oversees the collection of IVA (Impuesto al Valor Agregado), the country's value-added tax. - Taxpayers are identified using the RUT (Rol Único Tributario), a 6-8 digits number with a check digit calculated using the modulo 11 algorithm. The check digit can be 0-9 or K, and RUTs are formatted as XX.XXX.XXX-Y. + Taxpayers are identified using the RUT (Rol Único Tributario), a 6-8 digits number with a check digit calculated using the modulo 11 algorithm. The check digit can be 0-9 or K, and RUTs are formatted as XX.XXX.XXX-Y. Both supplier and customer RUT are mandatory for Facturas Electrónicas (B2B invoices), while customer RUT is optional for Boletas Electrónicas (B2C receipts). Supplier address is always required, and customer address is required for B2B transactions. Chile applies a single standard IVA rate of 19%, effective since October 1, 2003, when it was increased from 18% by Ley 19888. Unlike many other countries, Chile does not have reduced or super-reduced VAT rates. Electronic invoicing has been mandatory in Chile since 2018 for B2B transactions and since 2021 for B2C transactions. The system is based on DTEs (Documentos Tributarios Electrónicos - Electronic Tax Documents) that must be validated by the SII before being sent to the recipient. The validation process is known as "prior validation," where documents are transmitted to the SII first, validated, returned to the issuer, and then forwarded to the customer. Recipients have 8 days to accept or reject documents; otherwise, they are considered tacitly accepted. - Common document types include Factura Electrónica (electronic invoice), Boleta Electrónica (electronic receipt), Nota de Crédito Electrónica (electronic credit note), Nota de Débito Electrónica (electronic debit note), and Guía de Despacho (dispatch guide). All DTEs must be archived for 6 years in the XML format validated by the SII. + Common document types include Factura Electrónica (electronic invoice for B2B), Boleta Electrónica (electronic receipt for B2C), Nota de Crédito Electrónica (electronic credit note), Nota de Débito Electrónica (electronic debit note), and Guía de Despacho (dispatch guide). Use the "simplified" tag to indicate Boletas Electrónicas, which have relaxed customer identification requirements. All DTEs must be archived for 6 years in the XML format validated by the SII. + + Additional SII requirements include Giro Comercial (business activity) for both parties, complete address details (Dirección, Ciudad, Comuna), and clear item descriptions (Resolution 36/2024, effective July 2024). `), i18n.ES: here.Doc(` El sistema tributario de Chile es administrado por el SII (Servicio de Impuestos Internos), que supervisa la recaudación del IVA (Impuesto al Valor Agregado). - Los contribuyentes se identifican mediante el RUT (Rol Único Tributario), un número de 6-8 dígitos con un dígito verificador calculado mediante el algoritmo módulo 11. El dígito verificador puede ser 0-9 o K, y los RUT se formatean como XX.XXX.XXX-Y. + Los contribuyentes se identifican mediante el RUT (Rol Único Tributario), un número de 6-8 dígitos con un dígito verificador calculado mediante el algoritmo módulo 11. El dígito verificador puede ser 0-9 o K, y los RUT se formatean como XX.XXX.XXX-Y. El RUT del emisor y receptor es obligatorio para Facturas Electrónicas (B2B), mientras que el RUT del receptor es opcional para Boletas Electrónicas (B2C). La dirección del emisor es siempre requerida, y la dirección del receptor es requerida para transacciones B2B. Chile aplica una tasa única de IVA del 19%, vigente desde el 1 de octubre de 2003, cuando fue aumentada del 18% mediante la Ley 19888. A diferencia de muchos otros países, Chile no tiene tasas reducidas o super-reducidas de IVA. La facturación electrónica es obligatoria en Chile desde 2018 para transacciones B2B y desde 2021 para transacciones B2C. El sistema se basa en DTEs (Documentos Tributarios Electrónicos) que deben ser validados por el SII antes de enviarse al receptor. El proceso de validación se conoce como "validación previa", donde los documentos se transmiten primero al SII, se validan, se devuelven al emisor y luego se reenvían al cliente. Los receptores tienen 8 días para aceptar o rechazar documentos; de lo contrario, se consideran aceptados tácitamente. - Los tipos de documentos comunes incluyen Factura Electrónica, Boleta Electrónica, Nota de Crédito Electrónica, Nota de Débito Electrónica y Guía de Despacho. Todos los DTEs deben archivarse durante 6 años en el formato XML validado por el SII. + Los tipos de documentos comunes incluyen Factura Electrónica (factura para B2B), Boleta Electrónica (boleta para B2C), Nota de Crédito Electrónica, Nota de Débito Electrónica y Guía de Despacho. Use la etiqueta "simplified" para indicar Boletas Electrónicas, que tienen requisitos de identificación del cliente más flexibles. Todos los DTEs deben archivarse durante 6 años en el formato XML validado por el SII. + + Requisitos adicionales del SII incluyen Giro Comercial (actividad económica) para ambas partes, detalles completos de dirección (Dirección, Ciudad, Comuna), y descripciones claras de los ítems (Resolución 36/2024, vigente desde julio 2024). `), }, TimeZone: "America/Santiago", @@ -64,6 +82,8 @@ func Normalize(doc any) { // Validate checks the document type and determines if it can be validated. func Validate(doc interface{}) error { switch obj := doc.(type) { + case *bill.Invoice: + return validateInvoice(obj) case *tax.Identity: return validateTaxIdentity(obj) } diff --git a/regimes/cl/invoices.go b/regimes/cl/invoices.go new file mode 100644 index 000000000..a6a7f630f --- /dev/null +++ b/regimes/cl/invoices.go @@ -0,0 +1,102 @@ +package cl + +import ( + "github.com/invopop/gobl/bill" + "github.com/invopop/gobl/org" + "github.com/invopop/gobl/tax" + "github.com/invopop/validation" +) + +// invoiceValidator validates Chilean invoices according to SII requirements. +// +// Validation enforces: +// - Supplier: RUT and address required for all DTEs +// - Customer: RUT and address required for Facturas (B2B), optional for Boletas (B2C) +// +// Use tax.TagSimplified to indicate a Boleta Electrónica (B2C receipt). +// +// Additional SII requirements (documented but not validated): Giro Comercial, Comuna, +// payment terms, and item descriptions per Resolution 36/2024. +// +// References: +// - https://www.sii.cl/factura_electronica/factura_mercado/formato_dte.pdf +// - https://www.sii.cl/factura_electronica/factura_mercado/formato_boletas_elec_202306.pdf +type invoiceValidator struct { + inv *bill.Invoice +} + +func validateInvoice(inv *bill.Invoice) error { + if inv == nil { + return nil + } + v := &invoiceValidator{inv: inv} + return v.validate() +} + +func (v *invoiceValidator) validate() error { + inv := v.inv + return validation.ValidateStruct(inv, + validation.Field(&inv.Supplier, + validation.Required, + validation.By(v.supplier), + validation.Skip, + ), + validation.Field(&inv.Customer, + validation.By(v.customer), + validation.Skip, + ), + ) +} + +func (v *invoiceValidator) supplier(value interface{}) error { + obj, _ := value.(*org.Party) + if obj == nil { + return nil + } + return validation.ValidateStruct(obj, + // RUT required for all DTEs (mandatory since 2018/2021 for B2B/B2C) + validation.Field(&obj.TaxID, + validation.Required, + tax.RequireIdentityCode, + validation.Skip, + ), + // Address required (Dirección, Ciudad, Comuna) + validation.Field(&obj.Addresses, + validation.Required, + validation.Length(1, 0), + validation.Skip, + ), + ) +} + +func (v *invoiceValidator) customer(value interface{}) error { + obj, _ := value.(*org.Party) + if obj == nil { + return nil + } + + inv := v.inv + // Facturas (B2B): RUT and address required + // Boletas (B2C with tax.TagSimplified): RUT and address optional + // Note: High-value boletas (>135 UF) will require RUT from Sep 2025 + isB2B := !inv.Tags.HasTags(tax.TagSimplified) + + return validation.ValidateStruct(obj, + validation.Field(&obj.TaxID, + validation.When( + isB2B, + validation.Required, + tax.RequireIdentityCode, + ), + validation.Skip, + ), + validation.Field(&obj.Addresses, + validation.When( + isB2B, + validation.Required, + validation.Length(1, 0), + ), + validation.Skip, + ), + ) +} diff --git a/regimes/cl/invoices_test.go b/regimes/cl/invoices_test.go new file mode 100644 index 000000000..2c1cf49ea --- /dev/null +++ b/regimes/cl/invoices_test.go @@ -0,0 +1,306 @@ +package cl_test + +import ( + "testing" + + "github.com/invopop/gobl/bill" + "github.com/invopop/gobl/cal" + "github.com/invopop/gobl/num" + "github.com/invopop/gobl/org" + "github.com/invopop/gobl/regimes/cl" + "github.com/invopop/gobl/tax" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func testInvoiceStandard(t *testing.T) *bill.Invoice { + t.Helper() + return &bill.Invoice{ + Code: "TEST-001", + Currency: "CLP", + Supplier: &org.Party{ + Name: "Test Supplier", + TaxID: &tax.Identity{ + Country: "CL", + Code: "713254975", + }, + Addresses: []*org.Address{ + { + Street: "Av. Libertador Bernardo O'Higgins", + Number: "1234", + Locality: "Santiago", + Region: "Región Metropolitana", + Code: "8320000", + Country: "CL", + }, + }, + }, + Customer: &org.Party{ + Name: "Test Customer", + TaxID: &tax.Identity{ + Country: "CL", + Code: "77668208K", // Valid customer RUT + }, + Addresses: []*org.Address{ + { + Street: "Av. Providencia", + Number: "567", + Locality: "Providencia", + Region: "Región Metropolitana", + Code: "7500000", + Country: "CL", + }, + }, + }, + IssueDate: cal.MakeDate(2024, 1, 1), + Lines: []*bill.Line{ + { + Quantity: num.MakeAmount(1, 0), + Item: &org.Item{ + Name: "Test Item", + Price: num.NewAmount(10000, 0), + }, + Taxes: tax.Set{ + { + Category: "VAT", + Rate: "standard", + }, + }, + }, + }, + } +} + +func TestInvoiceValidation(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + setupInv func(*bill.Invoice) + expectError string + }{ + { + name: "valid invoice", + setupInv: func(_ *bill.Invoice) {}, + }, + { + name: "missing supplier", + setupInv: func(inv *bill.Invoice) { + inv.SetRegime("CL") + inv.Supplier = nil + }, + expectError: "supplier: cannot be blank", + }, + { + name: "supplier without tax ID", + setupInv: func(inv *bill.Invoice) { + inv.SetRegime("CL") + inv.Supplier.TaxID = nil + }, + expectError: "tax_id: cannot be blank", + }, + { + name: "supplier with tax ID but no code", + setupInv: func(inv *bill.Invoice) { + inv.SetRegime("CL") + inv.Supplier.TaxID.Code = "" + }, + expectError: "code: cannot be blank", + }, + { + name: "invalid RUT check digit", + setupInv: func(inv *bill.Invoice) { + inv.SetRegime("CL") + inv.Supplier.TaxID.Code = "713254976" // Invalid check digit + }, + expectError: "invalid RUT check digit", + }, + { + name: "supplier without address", + setupInv: func(inv *bill.Invoice) { + inv.SetRegime("CL") + inv.Supplier.Addresses = nil + }, + expectError: "addresses", + }, + { + name: "supplier with empty addresses array", + setupInv: func(inv *bill.Invoice) { + inv.SetRegime("CL") + inv.Supplier.Addresses = []*org.Address{} + }, + expectError: "addresses", + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + inv := testInvoiceStandard(t) + tt.setupInv(inv) + require.NoError(t, inv.Calculate()) + + err := inv.Validate() + if tt.expectError == "" { + assert.NoError(t, err) + } else { + if assert.Error(t, err) { + assert.Contains(t, err.Error(), tt.expectError) + } + } + }) + } + + // Separate test for regime-specific validation via cl.Validate + t.Run("regime-specific validation via cl.Validate", func(t *testing.T) { + t.Parallel() + inv := &bill.Invoice{ + Supplier: &org.Party{ + Name: "Test Supplier", + TaxID: &tax.Identity{ + Country: "CL", + Code: "713254975", + }, + Addresses: []*org.Address{ + { + Street: "Test Street", + Locality: "Santiago", + }, + }, + }, + } + err := cl.Validate(inv) + assert.NoError(t, err) + }) +} + +func TestInvoiceCustomerValidation(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + setupInv func(*bill.Invoice) + expectError string + }{ + { + name: "B2B invoice - customer without RUT", + setupInv: func(inv *bill.Invoice) { + inv.SetRegime("CL") + inv.Customer.TaxID = nil + }, + expectError: "tax_id: cannot be blank", + }, + { + name: "B2B invoice - customer with RUT but no code", + setupInv: func(inv *bill.Invoice) { + inv.SetRegime("CL") + inv.Customer.TaxID = &tax.Identity{ + Country: "CL", + } + }, + expectError: "code: cannot be blank", + }, + { + name: "B2B invoice - customer with valid RUT", + setupInv: func(inv *bill.Invoice) { + inv.SetRegime("CL") + inv.Customer.TaxID = &tax.Identity{ + Country: "CL", + Code: "77668208K", + } + }, + }, + { + name: "B2B invoice - customer with invalid RUT check digit", + setupInv: func(inv *bill.Invoice) { + inv.SetRegime("CL") + inv.Customer.TaxID = &tax.Identity{ + Country: "CL", + Code: "77668208X", // Invalid check digit + } + }, + expectError: "invalid RUT", + }, + { + name: "B2B invoice - customer without address", + setupInv: func(inv *bill.Invoice) { + inv.SetRegime("CL") + inv.Customer.Addresses = nil + }, + expectError: "addresses", + }, + { + name: "B2B invoice - customer with empty addresses array", + setupInv: func(inv *bill.Invoice) { + inv.SetRegime("CL") + inv.Customer.Addresses = []*org.Address{} + }, + expectError: "addresses", + }, + { + name: "B2C boleta - no customer required", + setupInv: func(inv *bill.Invoice) { + inv.SetRegime("CL") + inv.SetTags(tax.TagSimplified) + inv.Customer = nil + }, + }, + { + name: "B2C boleta - customer without RUT is valid", + setupInv: func(inv *bill.Invoice) { + inv.SetRegime("CL") + inv.SetTags(tax.TagSimplified) + inv.Customer.TaxID = nil + }, + }, + { + name: "B2C boleta - customer with RUT is also valid", + setupInv: func(inv *bill.Invoice) { + inv.SetRegime("CL") + inv.SetTags(tax.TagSimplified) + inv.Customer.TaxID = &tax.Identity{ + Country: "CL", + Code: "77668208K", + } + }, + }, + { + name: "B2C boleta - customer without address is valid", + setupInv: func(inv *bill.Invoice) { + inv.SetRegime("CL") + inv.SetTags(tax.TagSimplified) + inv.Customer.Addresses = nil + }, + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + inv := testInvoiceStandard(t) + tt.setupInv(inv) + require.NoError(t, inv.Calculate()) + + err := inv.Validate() + if tt.expectError == "" { + assert.NoError(t, err) + } else { + if assert.Error(t, err) { + assert.Contains(t, err.Error(), tt.expectError) + } + } + }) + } +} + +func TestInvoiceNilSafety(t *testing.T) { + t.Parallel() + + t.Run("nil invoice should not panic", func(t *testing.T) { + t.Parallel() + err := cl.Validate((*bill.Invoice)(nil)) + assert.NoError(t, err) + }) +} diff --git a/regimes/cl/tax_categories.go b/regimes/cl/tax_categories.go index a0069eff1..ab8aab018 100644 --- a/regimes/cl/tax_categories.go +++ b/regimes/cl/tax_categories.go @@ -62,15 +62,14 @@ var taxCategories = []*tax.CategoryDef{ i18n.ES: "Tasa General", }, Values: []*tax.RateValueDef{ - { - Since: cal.NewDate(1990, 7, 1), - Percent: num.MakePercentage(18, 2), - Disabled: true, - }, { Since: cal.NewDate(2003, 10, 1), Percent: num.MakePercentage(19, 2), }, + { + Since: cal.NewDate(1990, 7, 1), + Percent: num.MakePercentage(18, 2), + }, }, }, }, diff --git a/regimes/cl/tax_identity.go b/regimes/cl/tax_identity.go index 50e9851f7..3a4a3c80d 100644 --- a/regimes/cl/tax_identity.go +++ b/regimes/cl/tax_identity.go @@ -35,8 +35,18 @@ func validateTaxIdentity(tID *tax.Identity) error { ) } -// normalizeTaxIdentity will remove any whitespace or separation characters from -// the tax code and also make sure the default type is set. +// normalizeTaxIdentity removes formatting characters from Chilean RUT numbers. +// +// Normalization process: +// 1. Removes all dots (.) and hyphens (-) +// 2. Converts lowercase 'k' to uppercase 'K' for check digits +// +// Examples: +// - "71.325.497-5" → "713254975" +// - "77.668.208-k" → "77668208K" +// - "12.345.678-5" → "123456785" +// +// Reference: https://en.wikipedia.org/wiki/National_identification_number#Chile func normalizeTaxIdentity(tID *tax.Identity) { if tID == nil { return @@ -56,6 +66,10 @@ func normalizeTaxIdentity(tID *tax.Identity) { // 3. Compare the calculated check digit with the provided one // // Returns nil if valid, or an error describing the validation failure. +// +// References: +// - RUT Format: https://es.wikipedia.org/wiki/Rol_%C3%9Anico_Tributario +// - RUT Length Updates (7-9 digits): https://help.getcirrus.com/es/articles/8515715-modificaciones-para-manejo-de-rut-de-7-a-9-digitos-chile func validateRUT(value interface{}) error { code, ok := value.(cbc.Code) if !ok || code == "" { @@ -106,6 +120,8 @@ func validateRUT(value interface{}) error { // Returns: // // The calculated check digit as a string ("0"-"9" or "K"), or an error if conversion fails +// +// Reference: https://es.wikipedia.org/wiki/Rol_%C3%9Anico_Tributario#Algoritmo func calculateRUTCheckDigit(rut string) (string, error) { sum := 0 multiplier := 2 From 91e3c1c300e1ca3a713b6db43371ea1abf181e1d Mon Sep 17 00:00:00 2001 From: Adrian Arencibia Date: Wed, 25 Feb 2026 21:47:25 +0100 Subject: [PATCH 09/11] Fix errors message normalization --- data/regimes/cl.json | 2 +- regimes/cl/cl.go | 2 +- regimes/cl/invoices_test.go | 4 ++-- regimes/cl/tax_identity.go | 4 ++-- regimes/cl/tax_identity_test.go | 12 ++++++------ 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/data/regimes/cl.json b/data/regimes/cl.json index 30c961901..7b35109da 100644 --- a/data/regimes/cl.json +++ b/data/regimes/cl.json @@ -5,7 +5,7 @@ "es": "Chile" }, "description": { - "en": "Chile's tax system is administered by the SII (Servicio de Impuestos Internos), which oversees the collection of IVA (Impuesto al Valor Agregado), the country's value-added tax.\n\nTaxpayers are identified using the RUT (Rol Único Tributario), a 6-8 digits number with a check digit calculated using the modulo 11 algorithm. The check digit can be 0-9 or K, and RUTs are formatted as XX.XXX.XXX-Y. Both supplier and customer RUT are mandatory for Facturas Electrónicas (B2B invoices), while customer RUT is optional for Boletas Electrónicas (B2C receipts). Supplier address is always required, and customer address is required for B2B transactions.\n\nChile applies a single standard IVA rate of 19%, effective since October 1, 2003, when it was increased from 18% by Ley 19888. Unlike many other countries, Chile does not have reduced or super-reduced VAT rates.\n\nElectronic invoicing has been mandatory in Chile since 2018 for B2B transactions and since 2021 for B2C transactions. The system is based on DTEs (Documentos Tributarios Electrónicos - Electronic Tax Documents) that must be validated by the SII before being sent to the recipient. The validation process is known as \"prior validation,\" where documents are transmitted to the SII first, validated, returned to the issuer, and then forwarded to the customer. Recipients have 8 days to accept or reject documents; otherwise, they are considered tacitly accepted.\n\nCommon document types include Factura Electrónica (electronic invoice for B2B), Boleta Electrónica (electronic receipt for B2C), Nota de Crédito Electrónica (electronic credit note), Nota de Débito Electrónica (electronic debit note), and Guía de Despacho (dispatch guide). Use the \"simplified\" tag to indicate Boletas Electrónicas, which have relaxed customer identification requirements. All DTEs must be archived for 6 years in the XML format validated by the SII.\n\nAdditional SII requirements include Giro Comercial (business activity) for both parties, complete address details (Dirección, Ciudad, Comuna), and clear item descriptions (Resolution 36/2024, effective July 2024).", + "en": "Chile's tax system is administered by the SII (Servicio de Impuestos Internos), which oversees the collection of IVA (Impuesto al Valor Agregado), the country's value-added tax.\n\nTaxpayers are identified using the RUT (Rol Único Tributario), a 6-8 digit number with a check digit calculated using the modulo 11 algorithm. The check digit can be 0-9 or K, and RUTs are formatted as XX.XXX.XXX-Y. Both supplier and customer RUT are mandatory for Facturas Electrónicas (B2B invoices), while customer RUT is optional for Boletas Electrónicas (B2C receipts). Supplier address is always required, and customer address is required for B2B transactions.\n\nChile applies a single standard IVA rate of 19%, effective since October 1, 2003, when it was increased from 18% by Ley 19888. Unlike many other countries, Chile does not have reduced or super-reduced VAT rates.\n\nElectronic invoicing has been mandatory in Chile since 2018 for B2B transactions and since 2021 for B2C transactions. The system is based on DTEs (Documentos Tributarios Electrónicos - Electronic Tax Documents) that must be validated by the SII before being sent to the recipient. The validation process is known as \"prior validation,\" where documents are transmitted to the SII first, validated, returned to the issuer, and then forwarded to the customer. Recipients have 8 days to accept or reject documents; otherwise, they are considered tacitly accepted.\n\nCommon document types include Factura Electrónica (electronic invoice for B2B), Boleta Electrónica (electronic receipt for B2C), Nota de Crédito Electrónica (electronic credit note), Nota de Débito Electrónica (electronic debit note), and Guía de Despacho (dispatch guide). Use the \"simplified\" tag to indicate Boletas Electrónicas, which have relaxed customer identification requirements. All DTEs must be archived for 6 years in the XML format validated by the SII.\n\nAdditional SII requirements include Giro Comercial (business activity) for both parties, complete address details (Dirección, Ciudad, Comuna), and clear item descriptions (Resolution 36/2024, effective July 2024).", "es": "El sistema tributario de Chile es administrado por el SII (Servicio de Impuestos Internos), que supervisa la recaudación del IVA (Impuesto al Valor Agregado).\n\nLos contribuyentes se identifican mediante el RUT (Rol Único Tributario), un número de 6-8 dígitos con un dígito verificador calculado mediante el algoritmo módulo 11. El dígito verificador puede ser 0-9 o K, y los RUT se formatean como XX.XXX.XXX-Y. El RUT del emisor y receptor es obligatorio para Facturas Electrónicas (B2B), mientras que el RUT del receptor es opcional para Boletas Electrónicas (B2C). La dirección del emisor es siempre requerida, y la dirección del receptor es requerida para transacciones B2B.\n\nChile aplica una tasa única de IVA del 19%, vigente desde el 1 de octubre de 2003, cuando fue aumentada del 18% mediante la Ley 19888. A diferencia de muchos otros países, Chile no tiene tasas reducidas o super-reducidas de IVA.\n\nLa facturación electrónica es obligatoria en Chile desde 2018 para transacciones B2B y desde 2021 para transacciones B2C. El sistema se basa en DTEs (Documentos Tributarios Electrónicos) que deben ser validados por el SII antes de enviarse al receptor. El proceso de validación se conoce como \"validación previa\", donde los documentos se transmiten primero al SII, se validan, se devuelven al emisor y luego se reenvían al cliente. Los receptores tienen 8 días para aceptar o rechazar documentos; de lo contrario, se consideran aceptados tácitamente.\n\nLos tipos de documentos comunes incluyen Factura Electrónica (factura para B2B), Boleta Electrónica (boleta para B2C), Nota de Crédito Electrónica, Nota de Débito Electrónica y Guía de Despacho. Use la etiqueta \"simplified\" para indicar Boletas Electrónicas, que tienen requisitos de identificación del cliente más flexibles. Todos los DTEs deben archivarse durante 6 años en el formato XML validado por el SII.\n\nRequisitos adicionales del SII incluyen Giro Comercial (actividad económica) para ambas partes, detalles completos de dirección (Dirección, Ciudad, Comuna), y descripciones claras de los ítems (Resolución 36/2024, vigente desde julio 2024)." }, "time_zone": "America/Santiago", diff --git a/regimes/cl/cl.go b/regimes/cl/cl.go index 746b24311..e007d3462 100644 --- a/regimes/cl/cl.go +++ b/regimes/cl/cl.go @@ -40,7 +40,7 @@ func New() *tax.RegimeDef { i18n.EN: here.Doc(` Chile's tax system is administered by the SII (Servicio de Impuestos Internos), which oversees the collection of IVA (Impuesto al Valor Agregado), the country's value-added tax. - Taxpayers are identified using the RUT (Rol Único Tributario), a 6-8 digits number with a check digit calculated using the modulo 11 algorithm. The check digit can be 0-9 or K, and RUTs are formatted as XX.XXX.XXX-Y. Both supplier and customer RUT are mandatory for Facturas Electrónicas (B2B invoices), while customer RUT is optional for Boletas Electrónicas (B2C receipts). Supplier address is always required, and customer address is required for B2B transactions. + Taxpayers are identified using the RUT (Rol Único Tributario), a 6-8 digit number with a check digit calculated using the modulo 11 algorithm. The check digit can be 0-9 or K, and RUTs are formatted as XX.XXX.XXX-Y. Both supplier and customer RUT are mandatory for Facturas Electrónicas (B2B invoices), while customer RUT is optional for Boletas Electrónicas (B2C receipts). Supplier address is always required, and customer address is required for B2B transactions. Chile applies a single standard IVA rate of 19%, effective since October 1, 2003, when it was increased from 18% by Ley 19888. Unlike many other countries, Chile does not have reduced or super-reduced VAT rates. diff --git a/regimes/cl/invoices_test.go b/regimes/cl/invoices_test.go index 2c1cf49ea..9303e0d51 100644 --- a/regimes/cl/invoices_test.go +++ b/regimes/cl/invoices_test.go @@ -113,7 +113,7 @@ func TestInvoiceValidation(t *testing.T) { inv.SetRegime("CL") inv.Supplier.TaxID.Code = "713254976" // Invalid check digit }, - expectError: "invalid RUT check digit", + expectError: "invalid check digit", }, { name: "supplier without address", @@ -220,7 +220,7 @@ func TestInvoiceCustomerValidation(t *testing.T) { Code: "77668208X", // Invalid check digit } }, - expectError: "invalid RUT", + expectError: "invalid format", }, { name: "B2B invoice - customer without address", diff --git a/regimes/cl/tax_identity.go b/regimes/cl/tax_identity.go index 3a4a3c80d..263d0a85b 100644 --- a/regimes/cl/tax_identity.go +++ b/regimes/cl/tax_identity.go @@ -80,7 +80,7 @@ func validateRUT(value interface{}) error { matches := rutPattern.FindStringSubmatch(str) if matches == nil { - return errors.New("invalid RUT format") + return errors.New("invalid format") } number := matches[1] @@ -92,7 +92,7 @@ func validateRUT(value interface{}) error { } if expected != checkDigit { - return errors.New("invalid RUT check digit") + return errors.New("invalid check digit") } return nil diff --git a/regimes/cl/tax_identity_test.go b/regimes/cl/tax_identity_test.go index 918ab386b..0039468a5 100644 --- a/regimes/cl/tax_identity_test.go +++ b/regimes/cl/tax_identity_test.go @@ -103,37 +103,37 @@ func TestValidateTaxIdentity(t *testing.T) { name: "too short - less than 7 digits", country: "CL", code: "12345", - err: "invalid RUT format", + err: "invalid format", }, { name: "invalid check digit", country: "CL", code: "123456780", - err: "invalid RUT check digit", + err: "invalid check digit", }, { name: "too long", country: "CL", code: "1234567890123", - err: "invalid RUT format", + err: "invalid format", }, { name: "invalid characters", country: "CL", code: "1234567A5", - err: "invalid RUT format", + err: "invalid format", }, { name: "leading zero not allowed", country: "CL", code: "012345674", - err: "invalid RUT format", + err: "invalid format", }, { name: "wrong check digit K when should be number", country: "CL", code: "12345678K", - err: "invalid RUT check digit", + err: "invalid check digit", }, { name: "non-CL country - should not validate", From c6b713bddc9281b6da850ac3bb067a37a6a7b0c2 Mon Sep 17 00:00:00 2001 From: Adrian Arencibia Date: Wed, 25 Feb 2026 22:00:24 +0100 Subject: [PATCH 10/11] Fix tests structure --- regimes/cl/invoices_test.go | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/regimes/cl/invoices_test.go b/regimes/cl/invoices_test.go index 9303e0d51..c6b7e49a7 100644 --- a/regimes/cl/invoices_test.go +++ b/regimes/cl/invoices_test.go @@ -18,6 +18,7 @@ func testInvoiceStandard(t *testing.T) *bill.Invoice { return &bill.Invoice{ Code: "TEST-001", Currency: "CLP", + Regime: tax.WithRegime("CL"), Supplier: &org.Party{ Name: "Test Supplier", TaxID: &tax.Identity{ @@ -86,7 +87,6 @@ func TestInvoiceValidation(t *testing.T) { { name: "missing supplier", setupInv: func(inv *bill.Invoice) { - inv.SetRegime("CL") inv.Supplier = nil }, expectError: "supplier: cannot be blank", @@ -94,7 +94,6 @@ func TestInvoiceValidation(t *testing.T) { { name: "supplier without tax ID", setupInv: func(inv *bill.Invoice) { - inv.SetRegime("CL") inv.Supplier.TaxID = nil }, expectError: "tax_id: cannot be blank", @@ -102,7 +101,6 @@ func TestInvoiceValidation(t *testing.T) { { name: "supplier with tax ID but no code", setupInv: func(inv *bill.Invoice) { - inv.SetRegime("CL") inv.Supplier.TaxID.Code = "" }, expectError: "code: cannot be blank", @@ -110,7 +108,6 @@ func TestInvoiceValidation(t *testing.T) { { name: "invalid RUT check digit", setupInv: func(inv *bill.Invoice) { - inv.SetRegime("CL") inv.Supplier.TaxID.Code = "713254976" // Invalid check digit }, expectError: "invalid check digit", @@ -118,7 +115,6 @@ func TestInvoiceValidation(t *testing.T) { { name: "supplier without address", setupInv: func(inv *bill.Invoice) { - inv.SetRegime("CL") inv.Supplier.Addresses = nil }, expectError: "addresses", @@ -126,7 +122,6 @@ func TestInvoiceValidation(t *testing.T) { { name: "supplier with empty addresses array", setupInv: func(inv *bill.Invoice) { - inv.SetRegime("CL") inv.Supplier.Addresses = []*org.Address{} }, expectError: "addresses", @@ -186,7 +181,6 @@ func TestInvoiceCustomerValidation(t *testing.T) { { name: "B2B invoice - customer without RUT", setupInv: func(inv *bill.Invoice) { - inv.SetRegime("CL") inv.Customer.TaxID = nil }, expectError: "tax_id: cannot be blank", @@ -194,7 +188,6 @@ func TestInvoiceCustomerValidation(t *testing.T) { { name: "B2B invoice - customer with RUT but no code", setupInv: func(inv *bill.Invoice) { - inv.SetRegime("CL") inv.Customer.TaxID = &tax.Identity{ Country: "CL", } @@ -204,7 +197,6 @@ func TestInvoiceCustomerValidation(t *testing.T) { { name: "B2B invoice - customer with valid RUT", setupInv: func(inv *bill.Invoice) { - inv.SetRegime("CL") inv.Customer.TaxID = &tax.Identity{ Country: "CL", Code: "77668208K", @@ -214,7 +206,6 @@ func TestInvoiceCustomerValidation(t *testing.T) { { name: "B2B invoice - customer with invalid RUT check digit", setupInv: func(inv *bill.Invoice) { - inv.SetRegime("CL") inv.Customer.TaxID = &tax.Identity{ Country: "CL", Code: "77668208X", // Invalid check digit @@ -225,7 +216,6 @@ func TestInvoiceCustomerValidation(t *testing.T) { { name: "B2B invoice - customer without address", setupInv: func(inv *bill.Invoice) { - inv.SetRegime("CL") inv.Customer.Addresses = nil }, expectError: "addresses", @@ -233,7 +223,6 @@ func TestInvoiceCustomerValidation(t *testing.T) { { name: "B2B invoice - customer with empty addresses array", setupInv: func(inv *bill.Invoice) { - inv.SetRegime("CL") inv.Customer.Addresses = []*org.Address{} }, expectError: "addresses", @@ -241,7 +230,6 @@ func TestInvoiceCustomerValidation(t *testing.T) { { name: "B2C boleta - no customer required", setupInv: func(inv *bill.Invoice) { - inv.SetRegime("CL") inv.SetTags(tax.TagSimplified) inv.Customer = nil }, @@ -249,7 +237,6 @@ func TestInvoiceCustomerValidation(t *testing.T) { { name: "B2C boleta - customer without RUT is valid", setupInv: func(inv *bill.Invoice) { - inv.SetRegime("CL") inv.SetTags(tax.TagSimplified) inv.Customer.TaxID = nil }, @@ -257,7 +244,6 @@ func TestInvoiceCustomerValidation(t *testing.T) { { name: "B2C boleta - customer with RUT is also valid", setupInv: func(inv *bill.Invoice) { - inv.SetRegime("CL") inv.SetTags(tax.TagSimplified) inv.Customer.TaxID = &tax.Identity{ Country: "CL", @@ -268,7 +254,6 @@ func TestInvoiceCustomerValidation(t *testing.T) { { name: "B2C boleta - customer without address is valid", setupInv: func(inv *bill.Invoice) { - inv.SetRegime("CL") inv.SetTags(tax.TagSimplified) inv.Customer.Addresses = nil }, From a4709d09cdf10b87bb2102994e0b70acf978e639 Mon Sep 17 00:00:00 2001 From: Adrian Arencibia Date: Fri, 27 Feb 2026 20:14:08 +0100 Subject: [PATCH 11/11] Merge with master and add more test cases --- data/schemas/tax/regime-code.json | 4 ++++ regimes/cl/invoices.go | 13 ++++++++----- regimes/cl/invoices_test.go | 8 ++++++++ 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/data/schemas/tax/regime-code.json b/data/schemas/tax/regime-code.json index c4b6e938a..540f2cea1 100644 --- a/data/schemas/tax/regime-code.json +++ b/data/schemas/tax/regime-code.json @@ -33,6 +33,10 @@ "const": "CH", "title": "Switzerland" }, + { + "const": "CL", + "title": "Chile" + }, { "const": "CO", "title": "Colombia" diff --git a/regimes/cl/invoices.go b/regimes/cl/invoices.go index a6a7f630f..fd78345a4 100644 --- a/regimes/cl/invoices.go +++ b/regimes/cl/invoices.go @@ -70,17 +70,20 @@ func (v *invoiceValidator) supplier(value interface{}) error { } func (v *invoiceValidator) customer(value interface{}) error { - obj, _ := value.(*org.Party) - if obj == nil { - return nil - } - inv := v.inv // Facturas (B2B): RUT and address required // Boletas (B2C with tax.TagSimplified): RUT and address optional // Note: High-value boletas (>135 UF) will require RUT from Sep 2025 isB2B := !inv.Tags.HasTags(tax.TagSimplified) + obj, _ := value.(*org.Party) + if obj == nil { + if isB2B { + return validation.NewError("validation_required", "customer is required for B2B invoices") + } + return nil + } + return validation.ValidateStruct(obj, validation.Field(&obj.TaxID, validation.When( diff --git a/regimes/cl/invoices_test.go b/regimes/cl/invoices_test.go index c6b7e49a7..8c3ea3bef 100644 --- a/regimes/cl/invoices_test.go +++ b/regimes/cl/invoices_test.go @@ -165,6 +165,7 @@ func TestInvoiceValidation(t *testing.T) { }, }, } + inv.SetTags(tax.TagSimplified) err := cl.Validate(inv) assert.NoError(t, err) }) @@ -227,6 +228,13 @@ func TestInvoiceCustomerValidation(t *testing.T) { }, expectError: "addresses", }, + { + name: "B2B invoice - missing customer should fail", + setupInv: func(inv *bill.Invoice) { + inv.Customer = nil + }, + expectError: "customer is required for B2B invoices", + }, { name: "B2C boleta - no customer required", setupInv: func(inv *bill.Invoice) {