Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix missing tax totals #26

Merged
merged 3 commits into from
Jan 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions doc/breakdown.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ type taxInfo struct {
}

func newTipoDesglose(gobl *bill.Invoice) *TipoDesglose {
if gobl.Totals == nil || gobl.Totals.Taxes == nil {
return nil
}
catTotal := gobl.Totals.Taxes.Category(tax.CategoryVAT)
if catTotal == nil {
return nil
Expand Down Expand Up @@ -265,7 +268,7 @@ func (t taxInfo) isNoSujeta(r *tax.RateTotal) bool {
if t.customerRates {
return true
}
return r.Percent == nil && r.Ext[tbai.ExtKeyExemption].Code().In(notSubjectExemptionCodes...)
return r.Percent == nil && r.Ext[tbai.ExtKeyExemption].In(notSubjectExemptionCodes...)
}

func (t taxInfo) causaNoSujeta(r *tax.RateTotal) string {
Expand All @@ -276,5 +279,5 @@ func (t taxInfo) causaNoSujeta(r *tax.RateTotal) string {
}

func (taxInfo) isExenta(r *tax.RateTotal) bool {
return r.Percent == nil && !r.Ext[tbai.ExtKeyExemption].Code().In(notSubjectExemptionCodes...)
return r.Percent == nil && !r.Ext[tbai.ExtKeyExemption].In(notSubjectExemptionCodes...)
}
27 changes: 17 additions & 10 deletions doc/invoice.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package doc
import (
"github.com/invopop/gobl/addons/es/tbai"
"github.com/invopop/gobl/bill"
"github.com/invopop/gobl/cbc"
"github.com/invopop/gobl/num"
"github.com/invopop/gobl/org"
"github.com/invopop/gobl/regimes/es"
"github.com/invopop/gobl/tax"
)
Expand Down Expand Up @@ -109,22 +109,24 @@ func newDatosFactura(inv *bill.Invoice) (*DatosFactura, error) {
}, nil
}

func newDescription(notes []*cbc.Note) (string, error) {
func newDescription(notes []*org.Note) (string, error) {
for _, note := range notes {
if note.Key == cbc.NoteKeyGeneral {
if note.Key == org.NoteKeyGeneral {
return note.Text, nil
}
}
return "", validationErr(`notes: missing note with key '%s'`, cbc.NoteKeyGeneral)
return "", validationErr(`notes: missing note with key '%s'`, org.NoteKeyGeneral)
}

func newImporteTotal(inv *bill.Invoice) string {
totalWithDiscounts := inv.Totals.Total

totalTaxes := num.MakeAmount(0, 2)
for _, category := range inv.Totals.Taxes.Categories {
if !category.Retained {
totalTaxes = totalTaxes.Add(category.Amount)
if inv.Totals.Taxes != nil {
for _, category := range inv.Totals.Taxes.Categories {
if !category.Retained {
totalTaxes = totalTaxes.Add(category.Amount)
}
}
}

Expand All @@ -133,9 +135,11 @@ func newImporteTotal(inv *bill.Invoice) string {

func newRetencionSoportada(inv *bill.Invoice) string {
totalRetention := num.MakeAmount(0, 2)
for _, category := range inv.Totals.Taxes.Categories {
if category.Retained {
totalRetention = totalRetention.Add(category.Amount)
if inv.Totals.Taxes != nil {
for _, category := range inv.Totals.Taxes.Categories {
if category.Retained {
totalRetention = totalRetention.Add(category.Amount)
}
}
}

Expand Down Expand Up @@ -204,6 +208,9 @@ func newFacturasRectificadasSustituidas(inv *bill.Invoice) *FacturasRectificadas
}

func hasSurchargedLines(inv *bill.Invoice) bool {
if inv.Totals == nil || inv.Totals.Taxes == nil {
return false
}
vat := inv.Totals.Taxes.Category(tax.CategoryVAT)
if vat == nil {
return false
Expand Down
7 changes: 3 additions & 4 deletions doc/invoice_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"github.com/invopop/gobl/addons/es/tbai"
"github.com/invopop/gobl/bill"
"github.com/invopop/gobl/cal"
"github.com/invopop/gobl/cbc"
"github.com/invopop/gobl/num"
"github.com/invopop/gobl/org"
"github.com/invopop/gobl/regimes/es"
Expand Down Expand Up @@ -67,8 +66,8 @@ func TestFacturaConversion(t *testing.T) {

t.Run("should fill invoice description from general note", func(t *testing.T) {
goblInvoice := test.LoadInvoice("sample-invoice.json")
goblInvoice.Notes = []*cbc.Note{
{Key: cbc.NoteKeyGeneral, Text: "Description of invoice"},
goblInvoice.Notes = []*org.Note{
{Key: org.NoteKeyGeneral, Text: "Description of invoice"},
}

invoice, _ := doc.NewTicketBAI(goblInvoice, ts, role, doc.ZoneBI)
Expand All @@ -79,7 +78,7 @@ func TestFacturaConversion(t *testing.T) {

t.Run("should return error if no description (general note) found", func(t *testing.T) {
goblInvoice := test.LoadInvoice("sample-invoice.json")
goblInvoice.Notes = []*cbc.Note{}
goblInvoice.Notes = []*org.Note{}

_, err := doc.NewTicketBAI(goblInvoice, ts, role, doc.ZoneBI)

Expand Down
2 changes: 1 addition & 1 deletion doc/parties.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func newDestinatario(party *org.Party) (*IDDestinatario, error) {
}

if len(party.Addresses) > 0 && party.Addresses[0].Code != "" {
d.CodigoPostal = party.Addresses[0].Code
d.CodigoPostal = party.Addresses[0].Code.String()
d.Direccion = formatAddress(party.Addresses[0])
}

Expand Down
5 changes: 4 additions & 1 deletion document.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ func (c *Client) Convert(env *gobl.Envelope) (*doc.TicketBAI, error) {
if inv.Supplier.TaxID.Country != l10n.ES.Tax() {
return nil, ErrValidation.withMessage("only spanish invoices are supported")
}
if inv.Totals == nil || inv.Totals.Taxes == nil {
return nil, ErrValidation.withMessage("missing taxes")
}

zone := zoneFor(inv)
if zone == "" {
Expand All @@ -36,7 +39,7 @@ func (c *Client) Convert(env *gobl.Envelope) (*doc.TicketBAI, error) {
out, err := doc.NewTicketBAI(inv, c.CurrentTime(), c.issuerRole, zone)
if err != nil {
if _, ok := err.(*doc.ValidationError); ok {
return nil, ErrValidation.withMessage(err.Error())
return nil, ErrValidation.withMessage(err.Error()) //nolint:govet
}

return nil, err
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ toolchain go1.22.1

require (
github.com/go-resty/resty/v2 v2.13.1
github.com/invopop/gobl v0.204.2-0.20241105091334-a418e60fb2b5
github.com/invopop/gobl v0.208.0
github.com/invopop/xmldsig v0.10.0
github.com/joho/godotenv v1.5.1
github.com/lestrrat-go/libxml2 v0.0.0-20231124114421-99c71026c2f5
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/invopop/gobl v0.204.2-0.20241105091334-a418e60fb2b5 h1:MLlwU4olYRx1FFa5pLur6PTTaXdaLfT7gscZ6DjkxTw=
github.com/invopop/gobl v0.204.2-0.20241105091334-a418e60fb2b5/go.mod h1:DmPohPel8b3ta4nDKnXRNzWQlB89cN74e0/WwPUEZUU=
github.com/invopop/gobl v0.208.0 h1:qy5GHXELMy7qBtvgLL8m4d/aBgBaxq0bdAaae4a2luE=
github.com/invopop/gobl v0.208.0/go.mod h1:DmPohPel8b3ta4nDKnXRNzWQlB89cN74e0/WwPUEZUU=
github.com/invopop/jsonschema v0.12.0 h1:6ovsNSuvn9wEQVOyc72aycBMVQFKz7cPdMJn10CvzRI=
github.com/invopop/jsonschema v0.12.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0=
github.com/invopop/validation v0.7.0 h1:NBPLqvYGmLZLQuk5jh0PbaBBetJW7f2VEk/BTWJkGBU=
Expand Down
12 changes: 9 additions & 3 deletions test/data/credit-note-es-es-tbai.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"uuid": "0192237d-4943-72a7-b1d0-51dca3e8bc71",
"dig": {
"alg": "sha256",
"val": "f7165b79e26a6d53e163030b0312e80d15f8af189e0eb51d98864cb06c64e9fc"
"val": "c703a148a9395e3a14882d582618fe6503ab4719007715449c752eaf5cc22831"
}
},
"doc": {
Expand Down Expand Up @@ -86,7 +86,10 @@
"item": {
"name": "Development services",
"price": "90.00",
"unit": "h"
"unit": "h",
"ext": {
"es-tbai-product": "services"
}
},
"sum": "1800.00",
"discounts": [
Expand All @@ -110,7 +113,10 @@
"quantity": "1",
"item": {
"name": "Financial service",
"price": "10.00"
"price": "10.00",
"ext": {
"es-tbai-product": "services"
}
},
"sum": "10.00",
"discounts": [
Expand Down
17 changes: 13 additions & 4 deletions test/data/invoice-es-es-b2c.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"uuid": "0192d3c7-2dc5-74cf-b263-5892feb44432",
"dig": {
"alg": "sha256",
"val": "58a808907be339175b8fa53ff5f326f1f074641cfbb653f7f1619763e1f4f2d7"
"val": "57cfc9eb9cc3c8b0013b7ad7ff6fc8b0320d9afbeda923eea05c463bd3cc16cd"
}
},
"doc": {
Expand Down Expand Up @@ -56,7 +56,10 @@
"item": {
"name": "Development services",
"price": "90.00",
"unit": "h"
"unit": "h",
"ext": {
"es-tbai-product": "services"
}
},
"sum": "1800.00",
"discounts": [
Expand All @@ -83,7 +86,10 @@
"quantity": "1",
"item": {
"name": "Some merch",
"price": "90.00"
"price": "90.00",
"ext": {
"es-tbai-product": "services"
}
},
"sum": "90.00",
"taxes": [
Expand All @@ -103,7 +109,10 @@
"quantity": "1",
"item": {
"name": "Some essential needs merch",
"price": "30.00"
"price": "30.00",
"ext": {
"es-tbai-product": "services"
}
},
"sum": "30.00",
"taxes": [
Expand Down
17 changes: 13 additions & 4 deletions test/data/invoice-es-nl-b2c.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"uuid": "0192237d-4965-7c4b-914e-3a62f8e074e5",
"dig": {
"alg": "sha256",
"val": "0ab95209a3a9da3f9e4500a39cd9685f142ff86d42e3d143de14042fe6639749"
"val": "b796c7ee85d32112c3ce7690f4ba5498eaf196ab9df57ea3a2128fe90247b612"
}
},
"doc": {
Expand Down Expand Up @@ -68,7 +68,10 @@
"item": {
"name": "Development services",
"price": "90.00",
"unit": "h"
"unit": "h",
"ext": {
"es-tbai-product": "services"
}
},
"sum": "1800.00",
"discounts": [
Expand Down Expand Up @@ -96,7 +99,10 @@
"quantity": "1",
"item": {
"name": "Some merch",
"price": "90.00"
"price": "90.00",
"ext": {
"es-tbai-product": "services"
}
},
"sum": "90.00",
"taxes": [
Expand All @@ -117,7 +123,10 @@
"quantity": "1",
"item": {
"name": "Some essential needs merch",
"price": "30.00"
"price": "30.00",
"ext": {
"es-tbai-product": "services"
}
},
"sum": "30.00",
"taxes": [
Expand Down
7 changes: 5 additions & 2 deletions test/data/invoice-es-nl-tbai-b2c-explicit.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"uuid": "0192237d-498e-7273-bc95-6a1daf16cb37",
"dig": {
"alg": "sha256",
"val": "bc1cc3c6887e628c94e42d011041522695a73005a3daf4b0f521b9a297e9e97f"
"val": "68b6594f9204664935f572e9fc537e84f680c86a4a325f61ddd646685ffcbde7"
}
},
"doc": {
Expand Down Expand Up @@ -65,7 +65,10 @@
"item": {
"name": "Development services",
"price": "90.00",
"unit": "h"
"unit": "h",
"ext": {
"es-tbai-product": "services"
}
},
"sum": "1800.00",
"discounts": [
Expand Down
7 changes: 5 additions & 2 deletions test/data/invoice-es-nl-tbai-exempt.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"uuid": "0192237d-49c2-79a7-8249-4280119d8ade",
"dig": {
"alg": "sha256",
"val": "0294246ded2b071f8c6eb6011251f3bd254726613b5e7402abcbc2c91e96ecd1"
"val": "f9db4d04b45e555f37068e2d363c153d0a36e29bbdfd828452a78a92491babec"
}
},
"doc": {
Expand Down Expand Up @@ -60,7 +60,10 @@
"item": {
"name": "Development services",
"price": "90.00",
"unit": "h"
"unit": "h",
"ext": {
"es-tbai-product": "services"
}
},
"sum": "1800.00",
"discounts": [
Expand Down
7 changes: 5 additions & 2 deletions test/data/invoice-ss.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"uuid": "0192fbbc-005b-7eea-8973-210ca4c0ffdc",
"dig": {
"alg": "sha256",
"val": "265465a226476105b9339754dd8e8856033fca217b8b6e89a984295de402b4b6"
"val": "38e8aef5c956bd0ca7ab99d559bdb13174a3f6af82feab70e1e7242bfe10abe7"
}
},
"doc": {
Expand Down Expand Up @@ -74,7 +74,10 @@
"quantity": "10",
"item": {
"name": "Item being purchased",
"price": "100.00"
"price": "100.00",
"ext": {
"es-tbai-product": "services"
}
},
"sum": "1000.00",
"discounts": [
Expand Down
7 changes: 5 additions & 2 deletions test/data/invoice-vi.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"uuid": "0192fd51-6cd8-73f2-a182-8c4d3901d125",
"dig": {
"alg": "sha256",
"val": "a9fcef2ca22b63043a5c66137a39f8ad2be7db01c42ad94f4c5c80ee060c49b0"
"val": "6503a793d90d96cefdfd1652d219a43e44472eb5e8f741d43cf86cb8f984b2ec"
}
},
"doc": {
Expand Down Expand Up @@ -74,7 +74,10 @@
"quantity": "10",
"item": {
"name": "Item being purchased",
"price": "100.00"
"price": "100.00",
"ext": {
"es-tbai-product": "services"
}
},
"sum": "1000.00",
"discounts": [
Expand Down
Loading