-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #396 from invopop/br-regime
Brazil regime
- Loading branch information
Showing
12 changed files
with
498 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# 🇧🇷 GOBL Brazil Tax Regime | ||
|
||
Example BR GOBL files can be found in the [`examples`](./examples) (YAML uncalculated documents) and [`examples/out`](./examples/out) (JSON calculated envelopes) subdirectories. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
// Package br provides the tax region definition for Brazil. | ||
package br | ||
|
||
import ( | ||
"github.com/invopop/gobl/bill" | ||
"github.com/invopop/gobl/cbc" | ||
"github.com/invopop/gobl/currency" | ||
"github.com/invopop/gobl/i18n" | ||
"github.com/invopop/gobl/regimes/common" | ||
"github.com/invopop/gobl/tax" | ||
) | ||
|
||
func init() { | ||
tax.RegisterRegimeDef(New()) | ||
} | ||
|
||
// New provides the tax region definition | ||
func New() *tax.RegimeDef { | ||
return &tax.RegimeDef{ | ||
Country: "BR", | ||
Currency: currency.BRL, | ||
Name: i18n.String{ | ||
i18n.EN: "Brazil", | ||
i18n.PT: "Brasil", | ||
}, | ||
TimeZone: "America/Sao_Paulo", | ||
Validator: Validate, | ||
Tags: []*tax.TagSet{ | ||
common.InvoiceTags(), | ||
}, | ||
Categories: taxCategories, | ||
Corrections: []*tax.CorrectionDefinition{ | ||
{ | ||
Schema: bill.ShortSchemaInvoice, | ||
Types: []cbc.Key{ | ||
bill.InvoiceTypeCreditNote, | ||
}, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
// 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) | ||
} | ||
return nil | ||
} | ||
|
||
// Normalize will attempt to clean the object passed to it. | ||
func Normalize(doc interface{}) { | ||
switch obj := doc.(type) { | ||
case *tax.Identity: | ||
tax.NormalizeIdentity(obj) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
$schema: "https://gobl.org/draft-0/bill/invoice" | ||
uuid: "3aea7b56-59d8-4beb-90bd-f8f280d852a0" | ||
currency: "BRL" | ||
issue_date: "2023-04-21" | ||
series: "SAMPLE" | ||
code: "001" | ||
|
||
supplier: | ||
tax_id: | ||
country: "BR" | ||
name: "TechSolutions Brasil Ltda." | ||
emails: | ||
- addr: "[email protected]" | ||
addresses: | ||
- num: "595" | ||
street: "Rua Haddock Lobo" | ||
locality: "São Paulo" | ||
region: "SP" | ||
code: "01311-000" | ||
country: "BR" | ||
|
||
customer: | ||
name: "Sample Consumer" | ||
emails: | ||
- addr: "[email protected]" | ||
|
||
lines: | ||
- quantity: 20 | ||
item: | ||
name: "Development services" | ||
price: "90.00" | ||
unit: "h" | ||
discounts: | ||
- percent: "10%" | ||
reason: "Special discount" | ||
taxes: | ||
- cat: ISS | ||
percent: "15%" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
{ | ||
"$schema": "https://gobl.org/draft-0/envelope", | ||
"head": { | ||
"uuid": "8a51fd30-2a27-11ee-be56-0242ac120002", | ||
"dig": { | ||
"alg": "sha256", | ||
"val": "5b7bb418d378de68d73da3f12f211648c5238e8ba916f4f5f00b2712f24d2476" | ||
} | ||
}, | ||
"doc": { | ||
"$schema": "https://gobl.org/draft-0/bill/invoice", | ||
"$regime": "BR", | ||
"uuid": "3aea7b56-59d8-4beb-90bd-f8f280d852a0", | ||
"type": "standard", | ||
"series": "SAMPLE", | ||
"code": "001", | ||
"issue_date": "2023-04-21", | ||
"currency": "BRL", | ||
"supplier": { | ||
"name": "TechSolutions Brasil Ltda.", | ||
"tax_id": { | ||
"country": "BR" | ||
}, | ||
"addresses": [ | ||
{ | ||
"num": "595", | ||
"street": "Rua Haddock Lobo", | ||
"locality": "São Paulo", | ||
"region": "SP", | ||
"code": "01311-000", | ||
"country": "BR" | ||
} | ||
], | ||
"emails": [ | ||
{ | ||
"addr": "[email protected]" | ||
} | ||
] | ||
}, | ||
"customer": { | ||
"name": "Sample Consumer", | ||
"emails": [ | ||
{ | ||
"addr": "[email protected]" | ||
} | ||
] | ||
}, | ||
"lines": [ | ||
{ | ||
"i": 1, | ||
"quantity": "20", | ||
"item": { | ||
"name": "Development services", | ||
"price": "90.00", | ||
"unit": "h" | ||
}, | ||
"sum": "1800.00", | ||
"discounts": [ | ||
{ | ||
"percent": "10%", | ||
"amount": "180.00", | ||
"reason": "Special discount" | ||
} | ||
], | ||
"taxes": [ | ||
{ | ||
"cat": "ISS", | ||
"percent": "15%" | ||
} | ||
], | ||
"total": "1620.00" | ||
} | ||
], | ||
"totals": { | ||
"sum": "1620.00", | ||
"total": "1620.00", | ||
"taxes": { | ||
"categories": [ | ||
{ | ||
"code": "ISS", | ||
"rates": [ | ||
{ | ||
"base": "1620.00", | ||
"percent": "15%", | ||
"amount": "243.00" | ||
} | ||
], | ||
"amount": "243.00" | ||
} | ||
], | ||
"sum": "243.00" | ||
}, | ||
"tax": "243.00", | ||
"total_with_tax": "1863.00", | ||
"payable": "1863.00" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package br | ||
|
||
import ( | ||
"github.com/invopop/gobl/bill" | ||
"github.com/invopop/validation" | ||
) | ||
|
||
func validateInvoice(inv *bill.Invoice) error { | ||
return validation.ValidateStruct(inv, | ||
validation.Field(&inv.Supplier, validation.Required), | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package br_test | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/invopop/gobl/bill" | ||
"github.com/invopop/gobl/org" | ||
"github.com/invopop/gobl/regimes/br" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestInvoiceValidation(t *testing.T) { | ||
t.Run("supplier required", func(t *testing.T) { | ||
inv := new(bill.Invoice) | ||
err := br.Validate(inv) | ||
if assert.Error(t, err) { | ||
assert.Contains(t, err.Error(), "supplier: cannot be blank") | ||
} | ||
}) | ||
|
||
t.Run("valid invoice", func(t *testing.T) { | ||
inv := &bill.Invoice{ | ||
Supplier: &org.Party{ | ||
Name: "Test Supplier", | ||
}, | ||
} | ||
err := br.Validate(inv) | ||
assert.NoError(t, err) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
package br | ||
|
||
import ( | ||
"github.com/invopop/gobl/cbc" | ||
"github.com/invopop/gobl/i18n" | ||
"github.com/invopop/gobl/tax" | ||
) | ||
|
||
// Tax categories specific for Brazil. | ||
const ( | ||
TaxCategoryISS cbc.Code = "ISS" | ||
TaxCategoryICMS cbc.Code = "ICMS" | ||
TaxCategoryIPI cbc.Code = "IPI" | ||
TaxCategoryPIS cbc.Code = "PIS" | ||
TaxCategoryCOFINS cbc.Code = "COFINS" | ||
) | ||
|
||
var taxCategories = []*tax.CategoryDef{ | ||
// | ||
// Municipal Service Tax (ISS) | ||
// | ||
{ | ||
Code: TaxCategoryISS, | ||
Name: i18n.String{ | ||
i18n.EN: "ISS", | ||
i18n.PT: "ISS", | ||
}, | ||
Title: i18n.String{ | ||
i18n.EN: "Municipal Service Tax", | ||
i18n.PT: "Imposto Sobre Serviços", | ||
}, | ||
Retained: false, | ||
}, | ||
// | ||
// State value-added tax (ICMS) | ||
// | ||
{ | ||
Code: TaxCategoryICMS, | ||
Name: i18n.String{ | ||
i18n.EN: "ICMS", | ||
i18n.PT: "ICMS", | ||
}, | ||
Title: i18n.String{ | ||
i18n.EN: "State value-added tax", | ||
i18n.PT: "Imposto sobre Circulação de Mercadorias e Serviços", | ||
}, | ||
Retained: false, | ||
}, | ||
// | ||
// Federal value-added Tax (IPI) | ||
// | ||
{ | ||
Code: TaxCategoryIPI, | ||
Name: i18n.String{ | ||
i18n.EN: "IPI", | ||
i18n.PT: "IPI", | ||
}, | ||
Title: i18n.String{ | ||
i18n.EN: "Federal value-added Tax", | ||
i18n.PT: "Imposto sobre Produtos Industrializados", | ||
}, | ||
Retained: false, | ||
}, | ||
// | ||
// Social Integration Program (PIS) | ||
// | ||
{ | ||
Code: TaxCategoryPIS, | ||
Name: i18n.String{ | ||
i18n.EN: "PIS", | ||
i18n.PT: "PIS", | ||
}, | ||
Title: i18n.String{ | ||
i18n.EN: "Social Integration Program", | ||
i18n.PT: "Programa de Integração Social", | ||
}, | ||
Retained: true, | ||
}, | ||
// | ||
// Contribution for the Financing of Social Security (COFINS) | ||
// | ||
{ | ||
Code: TaxCategoryCOFINS, | ||
Name: i18n.String{ | ||
i18n.EN: "COFINS", | ||
i18n.PT: "COFINS", | ||
}, | ||
Title: i18n.String{ | ||
i18n.EN: "Contribution for the Financing of Social Security", | ||
i18n.PT: "Contribuição para o Financiamento da Seguridade Social", | ||
}, | ||
Retained: true, | ||
}, | ||
} |
Oops, something went wrong.