Skip to content

Commit

Permalink
Update to latest GOBL
Browse files Browse the repository at this point in the history
  • Loading branch information
cavalle committed Nov 28, 2023
1 parent cc7d5be commit a7c3458
Show file tree
Hide file tree
Showing 17 changed files with 145 additions and 666 deletions.
21 changes: 12 additions & 9 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,31 @@ toolchain go1.21.4

require (
github.com/go-resty/resty/v2 v2.7.0
github.com/invopop/gobl v0.38.0
github.com/invopop/gobl v0.63.1
github.com/invopop/xmldsig v0.6.1
github.com/lestrrat-go/libxml2 v0.0.0-20231124114421-99c71026c2f5
github.com/sigurn/crc8 v0.0.0-20220107193325-2243fe600f9f
github.com/stretchr/testify v1.8.4
)

require (
cloud.google.com/go v0.99.0 // indirect
github.com/Masterminds/semver/v3 v3.1.1 // indirect
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect
cloud.google.com/go v0.110.2 // indirect
github.com/Masterminds/semver/v3 v3.2.1 // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/bahlo/generic-list-go v0.2.0 // indirect
github.com/beevik/etree v1.1.0 // indirect
github.com/buger/jsonparser v1.1.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/google/uuid v1.1.2 // indirect
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 // indirect
github.com/invopop/jsonschema v0.7.0 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/invopop/jsonschema v0.12.0 // indirect
github.com/invopop/validation v0.3.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/square/go-jose/v3 v3.0.0-20200630053402-0a67ce9b0693 // indirect
golang.org/x/crypto v0.6.0 // indirect
golang.org/x/net v0.6.0 // indirect
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
golang.org/x/crypto v0.9.0 // indirect
golang.org/x/net v0.10.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
software.sslmate.com/src/go-pkcs12 v0.2.0 // indirect
)
586 changes: 28 additions & 558 deletions go.sum

Large diffs are not rendered by default.

43 changes: 17 additions & 26 deletions internal/doc/breakdown.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"github.com/invopop/gobl/bill"
"github.com/invopop/gobl/l10n"
"github.com/invopop/gobl/num"
"github.com/invopop/gobl/regimes/common"
"github.com/invopop/gobl/regimes/es"
"github.com/invopop/gobl/tax"
)
Expand Down Expand Up @@ -115,9 +114,9 @@ func newTipoDesglose(gobl *bill.Invoice) *TipoDesglose {
switch scheme {
case es.TagSimplifiedScheme:
taxInfo.simplifiedRegime = true
case common.TagReverseCharge:
case tax.TagReverseCharge:
taxInfo.reverseCharge = true
case common.TagCustomerRates:
case tax.TagCustomerRates:
taxInfo.customerRates = true
}
}
Expand Down Expand Up @@ -155,7 +154,7 @@ func filterGoodsLines(gobl *bill.Invoice) []*bill.Line {
lines := []*bill.Line{}

for _, line := range gobl.Lines {
if line.Item.Meta != nil && line.Item.Meta["product"] == goods {
if line.Item.Key == es.ItemGoods {
lines = append(lines, line)
}
}
Expand All @@ -167,7 +166,7 @@ func filterServiceLines(gobl *bill.Invoice) []*bill.Line {
lines := []*bill.Line{}

for _, line := range gobl.Lines {
if line.Item.Meta == nil || line.Item.Meta["product"] != goods {
if line.Item.Key != es.ItemGoods {
lines = append(lines, line)
}
}
Expand Down Expand Up @@ -314,32 +313,32 @@ func sumAmountsPerType(lines []*bill.Line) (map[string]sumDetail, map[string]sum
discount := calculateDiscounts(line)
// TODO: Handle charges
taxableAmount := line.Item.Price.Multiply(line.Quantity).Subtract(discount)
lineSurcharged := line.Item.Meta["source"] == "provider"
lineSurcharged := line.Item.Key == es.ItemResale

for _, tax := range line.Taxes {
if tax.Category == common.TaxCategoryVAT && tax.Percent.IsZero() {
for _, t := range line.Taxes {
if t.Category == tax.CategoryVAT && t.Rate == tax.RateExempt {
exempted = updateAmount(
exempted,
exemptionKey(line),
t.Ext[es.ExtKeyTBAIExemption].String(),
taxableAmount,
num.MakePercentage(0, 0),
surcharge(tax),
surcharge(t),
)
} else if tax.Category == common.TaxCategoryVAT && lineSurcharged {
} else if t.Category == tax.CategoryVAT && lineSurcharged {
surcharged = updateAmount(
surcharged,
taxKey(tax),
taxKey(t),
taxableAmount,
tax.Percent,
surcharge(tax),
*t.Percent,
surcharge(t),
)
} else if tax.Category == common.TaxCategoryVAT {
} else if t.Category == tax.CategoryVAT {
nonExempted = updateAmount(
nonExempted,
taxKey(tax),
taxKey(t),
taxableAmount,
tax.Percent,
surcharge(tax),
*t.Percent,
surcharge(t),
)
}
}
Expand All @@ -357,14 +356,6 @@ func formatPercent(percent num.Percentage) string {
return maybeNegative
}

func exemptionKey(line *bill.Line) string {
if line.Item.Meta != nil && line.Item.Meta["exempt"] != "" {
return line.Item.Meta["exempt"]
}

return "E6"
}

func taxKey(tax *tax.Combo) string {
key := tax.Percent.String()
if tax.Surcharge != nil {
Expand Down
43 changes: 28 additions & 15 deletions internal/doc/breakdown_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"github.com/invopop/gobl/l10n"
"github.com/invopop/gobl/num"
"github.com/invopop/gobl/org"
"github.com/invopop/gobl/regimes/common"
"github.com/invopop/gobl/regimes/es"
"github.com/invopop/gobl/tax"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -56,7 +55,7 @@ func TestDesgloseConversion(t *testing.T) {
t.Run("should distinguish goods from services when customer from other country",
func(t *testing.T) {
goblInvoice := invoiceFromCountry("GB")
goblInvoice.Lines[0].Item.Meta = map[cbc.Key]string{"product": "goods"}
goblInvoice.Lines[0].Item.Key = es.ItemGoods

invoice, _ := doc.NewTicketBAI(goblInvoice, ts)

Expand All @@ -68,7 +67,7 @@ func TestDesgloseConversion(t *testing.T) {
t.Run("should use services instead of goods as default when customer from other country",
func(t *testing.T) {
goblInvoice := invoiceFromCountry("GB")
goblInvoice.Lines[0].Item.Meta = map[cbc.Key]string{}
goblInvoice.Lines[0].Item.Key = cbc.KeyEmpty

invoice, _ := doc.NewTicketBAI(goblInvoice, ts)

Expand All @@ -91,7 +90,7 @@ func TestDesgloseConversion(t *testing.T) {
Item: &org.Item{
Name: "A",
Price: num.MakeAmount(20, 0),
Meta: map[cbc.Key]string{"product": "goods"},
Key: es.ItemGoods,
},
},
}
Expand Down Expand Up @@ -120,7 +119,7 @@ func TestDesgloseConversion(t *testing.T) {
Item: &org.Item{
Name: "A",
Price: num.MakeAmount(20, 0),
Meta: map[cbc.Key]string{"product": "goods"},
Key: es.ItemGoods,
},
Taxes: tax.Set{&tax.Combo{Category: "VAT", Rate: "standard"}},
},
Expand All @@ -143,7 +142,7 @@ func TestDesgloseConversion(t *testing.T) {
Quantity: num.MakeAmount(100, 0),
Item: &org.Item{Name: "A", Price: num.MakeAmount(10, 0)},
Discounts: []*bill.LineDiscount{DiscountOf(100)},
Taxes: tax.Set{&tax.Combo{Category: "IRPF", Rate: "standard"}},
Taxes: tax.Set{&tax.Combo{Category: "IRPF", Rate: "pro"}},
}}
_ = goblInvoice.Calculate()

Expand All @@ -156,7 +155,7 @@ func TestDesgloseConversion(t *testing.T) {

t.Run("should change No Sujeta cause when taxes are paid in other EU country", func(t *testing.T) {
goblInvoice := invoiceFromCountry("ES")
goblInvoice.Tax = &bill.Tax{Tags: []cbc.Key{common.TagCustomerRates}}
goblInvoice.Tax = &bill.Tax{Tags: []cbc.Key{tax.TagCustomerRates}}
goblInvoice.Lines = []*bill.Line{{
Index: 1,
Quantity: num.MakeAmount(100, 0),
Expand Down Expand Up @@ -219,7 +218,7 @@ func TestDesgloseConversion(t *testing.T) {
Index: 1,
Quantity: num.MakeAmount(100, 0),
Item: &org.Item{Name: "A", Price: num.MakeAmount(10, 0)},
Taxes: tax.Set{&tax.Combo{Category: common.TaxCategoryVAT, Rate: common.TaxRateStandard}},
Taxes: tax.Set{&tax.Combo{Category: tax.CategoryVAT, Rate: tax.RateStandard}},
}}
_ = goblInvoice.Calculate()

Expand Down Expand Up @@ -267,7 +266,7 @@ func TestDesgloseConversion(t *testing.T) {
Item: &org.Item{
Name: "A",
Price: num.MakeAmount(10, 0),
Meta: cbc.Meta{"source": "provider"},
Key: es.ItemResale,
},
Taxes: tax.Set{&tax.Combo{Category: "VAT", Rate: "standard"}},
},
Expand All @@ -290,7 +289,7 @@ func TestDesgloseConversion(t *testing.T) {
Index: 1,
Quantity: num.MakeAmount(100, 0),
Item: &org.Item{Name: "A", Price: num.MakeAmount(10, 0)},
Taxes: tax.Set{&tax.Combo{Category: "VAT", Rate: "zero"}},
Taxes: tax.Set{&tax.Combo{Category: tax.CategoryVAT, Rate: tax.RateExempt}},
}}
_ = goblInvoice.Calculate()

Expand All @@ -309,19 +308,33 @@ func TestDesgloseConversion(t *testing.T) {
Item: &org.Item{
Name: "A",
Price: num.MakeAmount(10, 0),
Meta: cbc.Meta{"exempt": "E1"},
},
Taxes: tax.Set{&tax.Combo{Category: "VAT", Rate: "zero"}},
Taxes: tax.Set{
&tax.Combo{
Category: tax.CategoryVAT,
Rate: tax.RateExempt,
Ext: cbc.CodeMap{
es.ExtKeyTBAIExemption: "E1",
},
},
},
},
{
Index: 2,
Quantity: num.MakeAmount(1, 0),
Item: &org.Item{
Name: "A",
Price: num.MakeAmount(20, 0),
Meta: cbc.Meta{"exempt": "E2"},
},
Taxes: tax.Set{&tax.Combo{Category: "VAT", Rate: "zero"}},
Taxes: tax.Set{
&tax.Combo{
Category: tax.CategoryVAT,
Rate: tax.RateExempt,
Ext: cbc.CodeMap{
es.ExtKeyTBAIExemption: "E2",
},
},
},
},
}
_ = goblInvoice.Calculate()
Expand Down Expand Up @@ -357,7 +370,7 @@ func TestDesgloseConversion(t *testing.T) {

t.Run("should mark tax details if there is reverse charge", func(t *testing.T) {
goblInvoice := invoiceFromCountry("ES")
goblInvoice.Tax = &bill.Tax{Tags: []cbc.Key{common.TagReverseCharge}}
goblInvoice.Tax = &bill.Tax{Tags: []cbc.Key{tax.TagReverseCharge}}
goblInvoice.Lines = []*bill.Line{{
Index: 1,
Quantity: num.MakeAmount(100, 0),
Expand Down
8 changes: 1 addition & 7 deletions internal/doc/discounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,5 @@ import (
)

func calculateDiscounts(line *bill.Line) num.Amount {
total := num.MakeAmount(0, 0)

for _, discount := range line.Discounts {
total = total.Add(discount.Amount)
}

return total
return line.Sum.Subtract(line.Total)
}
5 changes: 4 additions & 1 deletion internal/doc/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,10 @@ func NewTicketBAI(inv *bill.Invoice, ts time.Time) (*TicketBAI, error) {
return nil, err
}

goblWithoutIncludedTaxes := inv.RemoveIncludedTaxes(2)
goblWithoutIncludedTaxes, err := inv.RemoveIncludedTaxes()
if err != nil {
return nil, err
}

doc := &TicketBAI{
TNamespace: ticketBAINamespace,
Expand Down
3 changes: 2 additions & 1 deletion internal/doc/doc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/invopop/gobl.ticketbai/internal/doc"
"github.com/invopop/gobl.ticketbai/test"
"github.com/invopop/gobl/regimes/es"
"github.com/invopop/gobl/tax"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -75,7 +76,7 @@ func TestInvoiceConversion(t *testing.T) {
t.Run("should change the document type from the default (02) if stated", func(t *testing.T) {
goblInvoice, _ := test.LoadInvoice("sample-invoice.json")
goblInvoice.Customer.TaxID = &tax.Identity{
Country: "GB", Code: "PP-123456-S", Source: tax.SourceKeyPermit,
Country: "GB", Code: "PP-123456-S", Type: es.TaxIdentityTypeResident,
}

invoice, _ := doc.NewTicketBAI(goblInvoice, ts)
Expand Down
7 changes: 3 additions & 4 deletions internal/doc/invoice.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (
"github.com/invopop/gobl/bill"
"github.com/invopop/gobl/cbc"
"github.com/invopop/gobl/num"
"github.com/invopop/gobl/regimes/common"
"github.com/invopop/gobl/regimes/es"
"github.com/invopop/gobl/tax"
)

// Factura contains the invoice info
Expand Down Expand Up @@ -50,7 +50,7 @@ type IDClave struct {

func newCabeceraFactura(inv *bill.Invoice, ts time.Time) *CabeceraFactura {
simplifiedInvoice := "N"
if inv.Tax.ContainsTag(common.TagSimplified) {
if inv.Tax.ContainsTag(tax.TagSimplified) {
simplifiedInvoice = "S"
}

Expand Down Expand Up @@ -163,8 +163,7 @@ func newClaves(inv *bill.Invoice) []IDClave {

func hasSurchargedLines(inv *bill.Invoice) bool {
for _, line := range inv.Lines {
ct := line.Taxes.Get(common.TaxCategoryVAT)
if ct != nil && es.TagProvider.In(ct.Tags...) {
if line.Item.Key == es.ItemResale {
return true
}
}
Expand Down
12 changes: 8 additions & 4 deletions internal/doc/invoice_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"github.com/invopop/gobl/cbc"
"github.com/invopop/gobl/num"
"github.com/invopop/gobl/org"
"github.com/invopop/gobl/regimes/common"
"github.com/invopop/gobl/regimes/es"
"github.com/invopop/gobl/tax"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -45,7 +44,7 @@ func TestFacturaConversion(t *testing.T) {
t.Run("should mark an invoice as simplified (ticket)", func(t *testing.T) {
goblInvoice, _ := test.LoadInvoice("sample-invoice.json")
goblInvoice.Tax = &bill.Tax{
Tags: []cbc.Key{common.TagSimplified},
Tags: []cbc.Key{tax.TagSimplified},
}

invoice, _ := doc.NewTicketBAI(goblInvoice, ts)
Expand Down Expand Up @@ -176,9 +175,14 @@ func TestFacturaConversion(t *testing.T) {
Item: &org.Item{
Name: "A",
Price: num.MakeAmount(10, 0),
Meta: cbc.Meta{"source": "provider"},
Key: es.ItemResale,
},
Taxes: tax.Set{
&tax.Combo{
Category: "VAT",
Rate: "standard",
},
},
Taxes: tax.Set{&tax.Combo{Category: "VAT", Rate: "standard"}},
}}
_ = goblInvoice.Calculate()

Expand Down
Loading

0 comments on commit a7c3458

Please sign in to comment.