Skip to content

Commit

Permalink
Merge pull request #221 from invopop/add-ca-n-de
Browse files Browse the repository at this point in the history
Add CA and DE tax regimes
  • Loading branch information
samlown authored Nov 24, 2023
2 parents 0b1b4a3 + 337e07f commit 0c180f7
Show file tree
Hide file tree
Showing 15 changed files with 807 additions and 0 deletions.
3 changes: 3 additions & 0 deletions regimes/ca/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# 🇨🇦 GOBL Canada Tax Regime

Example Canada GOBL files can be found in the [`examples`](./examples) (YAML uncalculated documents) and [`examples/out`](./examples/out) (JSON calculated envelopes) subdirectories.
129 changes: 129 additions & 0 deletions regimes/ca/ca.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
// Package ca provides models for dealing with Canada.
package ca

import (
"github.com/invopop/gobl/bill"
"github.com/invopop/gobl/cal"
"github.com/invopop/gobl/cbc"
"github.com/invopop/gobl/currency"
"github.com/invopop/gobl/i18n"
"github.com/invopop/gobl/l10n"
"github.com/invopop/gobl/num"
"github.com/invopop/gobl/tax"
)

func init() {
tax.RegisterRegime(New())
}

// Tax categories specific for Canada.
const (
TaxCategoryHST cbc.Code = "HST"
TaxCategoryPST cbc.Code = "PST"
)

// New provides the tax region definition
func New() *tax.Regime {
return &tax.Regime{
Country: l10n.CA,
Currency: currency.CAD,
Name: i18n.String{
i18n.EN: "Canada",
},
TimeZone: "America/Toronto", // Toronto
Validator: Validate,
Categories: []*tax.Category{
//
// General Sales Tax (GST)
//
{
Code: tax.CategoryGST,
Name: i18n.String{
i18n.EN: "GST",
},
Title: i18n.String{
i18n.EN: "General Sales Tax",
},
Sources: []*tax.Source{
{
Title: i18n.String{
i18n.EN: "GST/HST provincial rates table",
},
URL: "https://www.canada.ca/en/revenue-agency/services/tax/businesses/topics/gst-hst-businesses/charge-collect-which-rate/calculator.html",
},
},
Retained: false,
Rates: []*tax.Rate{
{
Key: tax.RateZero,
Name: i18n.String{
i18n.EN: "Zero Rate",
},
Description: i18n.String{
i18n.EN: "Some supplies are zero-rated under the GST, mainly: basic groceries, agricultural products, farm livestock, most fishery products such, prescription drugs and drug-dispensing services, certain medical devices, feminine hygiene products, exports, many transportation services where the origin or destination is outside Canada",
},
Values: []*tax.RateValue{
{
Percent: num.MakePercentage(0, 3),
},
},
},
{
Key: tax.RateStandard,
Name: i18n.String{
i18n.EN: "Standard rate",
},
Description: i18n.String{
i18n.EN: "For the majority of sales of goods and services: it applies to all products or services for which no other rate is expressly provided.",
},

Values: []*tax.RateValue{
{
Since: cal.NewDate(2022, 1, 1),
Percent: num.MakePercentage(5, 2),
},
},
},
},
},
//
// Harmonized Sales Tax (HST)
//
{
Code: TaxCategoryHST,
Name: i18n.String{
i18n.EN: "HST",
},
Title: i18n.String{
i18n.EN: "Harmonized Sales Tax",
},
// TODO: determine local rates
Rates: []*tax.Rate{},
},

//
// Provincial Sales Tax (PST)
//
{
Code: TaxCategoryPST,
Name: i18n.String{
i18n.EN: "PST",
},
Title: i18n.String{
i18n.EN: "Provincial Sales Tax",
},
// TODO: determine local rates
Rates: []*tax.Rate{},
},
},
}
}

// 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)
}
return nil
}
37 changes: 37 additions & 0 deletions regimes/ca/examples/invoice-ca-ca.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
$schema: "https://gobl.org/draft-0/bill/invoice"
currency: "CAD"
issue_date: "2023-04-21"
series: "SAMPLE"
code: "001"

supplier:
tax_id:
country: "CA"
name: "Provide One Inc."
emails:
- addr: "[email protected]"
addresses:
- num: "151"
street: "O'Connor Street"
locality: "Ottawa"
region: "ON"
code: "K2P 2L8"
country: "CA"

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: GST
percent: "8.5%"
97 changes: 97 additions & 0 deletions regimes/ca/examples/out/invoice-ca-ca.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
{
"$schema": "https://gobl.org/draft-0/envelope",
"head": {
"uuid": "8a51fd30-2a27-11ee-be56-0242ac120002",
"dig": {
"alg": "sha256",
"val": "3d1cd0dd9fb113e244bddbdb7cefdb8be5c1a9ab3d60928cc225303cc1a2326b"
},
"draft": true
},
"doc": {
"$schema": "https://gobl.org/draft-0/bill/invoice",
"type": "standard",
"series": "SAMPLE",
"code": "001",
"issue_date": "2023-04-21",
"currency": "CAD",
"supplier": {
"name": "Provide One Inc.",
"tax_id": {
"country": "CA"
},
"addresses": [
{
"num": "151",
"street": "O'Connor Street",
"locality": "Ottawa",
"region": "ON",
"code": "K2P 2L8",
"country": "CA"
}
],
"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": "GST",
"percent": "8.5%"
}
],
"total": "1620.00"
}
],
"totals": {
"sum": "1620.00",
"total": "1620.00",
"taxes": {
"categories": [
{
"code": "GST",
"rates": [
{
"base": "1620.00",
"percent": "8.5%",
"amount": "137.70"
}
],
"amount": "137.70"
}
],
"sum": "137.70"
},
"tax": "137.70",
"total_with_tax": "1757.70",
"payable": "1757.70"
}
}
}
27 changes: 27 additions & 0 deletions regimes/ca/invoice_validator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package ca

import (
"github.com/invopop/gobl/bill"
"github.com/invopop/gobl/currency"
"github.com/invopop/validation"
)

// invoiceValidator adds validation checks to invoices which are relevant
// for the region.
type invoiceValidator struct {
inv *bill.Invoice
}

func validateInvoice(inv *bill.Invoice) error {
v := &invoiceValidator{inv: inv}
return v.validate()
}

func (v *invoiceValidator) validate() error {
inv := v.inv
return validation.ValidateStruct(inv,
validation.Field(&inv.Currency, validation.In(currency.CAD)),
validation.Field(&inv.Supplier, validation.Required),
validation.Field(&inv.Customer),
)
}
6 changes: 6 additions & 0 deletions regimes/common/invoice_tags.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ var invoiceTags = []*tax.KeyDefinition{
i18n.EN: "Simplified Invoice",
i18n.ES: "Factura Simplificada",
i18n.IT: "Fattura Semplificata",
i18n.DE: "Vereinfachte Rechnung",
},
Desc: i18n.String{
i18n.EN: "Used for B2C transactions when the client details are not available, check with local authorities for limits.",
i18n.ES: "Usado para transacciones B2C cuando los detalles del cliente no están disponibles, consulte con las autoridades locales para los límites.",
i18n.IT: "Utilizzato per le transazioni B2C quando i dettagli del cliente non sono disponibili, controllare con le autorità locali per i limiti.",
i18n.DE: "Wird für B2C-Transaktionen verwendet, wenn die Kundendaten nicht verfügbar sind. Bitte wenden Sie sich an die örtlichen Behörden, um die Grenzwerte zu ermitteln.",
},
},

Expand All @@ -31,6 +33,7 @@ var invoiceTags = []*tax.KeyDefinition{
i18n.EN: "Reverse Charge",
i18n.ES: "Inversión del Sujeto Pasivo",
i18n.IT: "Inversione del soggetto passivo",
i18n.DE: "Umkehr der Steuerschuld",
},
},

Expand All @@ -43,6 +46,7 @@ var invoiceTags = []*tax.KeyDefinition{
i18n.EN: "Self-billed",
i18n.ES: "Facturación por el destinatario",
i18n.IT: "Autofattura",
i18n.DE: "Rechnung durch den Leistungsempfänger",
},
},

Expand All @@ -52,6 +56,8 @@ var invoiceTags = []*tax.KeyDefinition{
Name: i18n.String{
i18n.EN: "Customer rates",
i18n.ES: "Tarifas aplicables al destinatario",
i18n.IT: "Aliquote applicabili al destinatario",
i18n.DE: "Kundensätze",
},
},
}
Expand Down
3 changes: 3 additions & 0 deletions regimes/de/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# 🇩🇪 GOBL Germany Tax Regime

Example DE GOBL files can be found in the [`examples`](./examples) (YAML uncalculated documents) and [`examples/out`](./examples/out) (JSON calculated envelopes) subdirectories.
Loading

0 comments on commit 0c180f7

Please sign in to comment.