Skip to content

Commit 83642bb

Browse files
committed
Add support to no tax code customer
1 parent 385498d commit 83642bb

5 files changed

Lines changed: 79 additions & 39 deletions

File tree

convert/breakdown_test.go

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ func TestDesgloseConversion(t *testing.T) {
5757
t.Run("should distinguish goods from services when customer from other country",
5858
func(t *testing.T) {
5959
goblInvoice := invoiceFromCountry("GB")
60-
goblInvoice.Lines[0].Item.Key = "goods"
60+
goblInvoice.Lines[0].Item.Key = org.ItemKeyGoods
6161
_ = goblInvoice.Calculate()
6262

6363
invoice, _ := convert.NewTicketBAI(goblInvoice, ts, role, convert.ZoneBI)
@@ -93,8 +93,8 @@ func TestDesgloseConversion(t *testing.T) {
9393
},
9494
Taxes: tax.Set{
9595
&tax.Combo{
96-
Category: "VAT",
97-
Rate: "standard",
96+
Category: tax.CategoryVAT,
97+
Rate: rateStandard,
9898
},
9999
},
100100
},
@@ -108,8 +108,8 @@ func TestDesgloseConversion(t *testing.T) {
108108
},
109109
Taxes: tax.Set{
110110
&tax.Combo{
111-
Category: "VAT",
112-
Rate: "standard",
111+
Category: tax.CategoryVAT,
112+
Rate: rateStandard,
113113
},
114114
},
115115
},
@@ -123,7 +123,7 @@ func TestDesgloseConversion(t *testing.T) {
123123
},
124124
Taxes: tax.Set{
125125
&tax.Combo{
126-
Category: "VAT",
126+
Category: tax.CategoryVAT,
127127
Rate: "reduced",
128128
},
129129
},
@@ -152,7 +152,7 @@ func TestDesgloseConversion(t *testing.T) {
152152
Index: 1,
153153
Quantity: num.MakeAmount(1, 0),
154154
Item: &org.Item{Name: "A", Price: num.NewAmount(10, 0)},
155-
Taxes: tax.Set{&tax.Combo{Category: "VAT", Rate: "standard"}},
155+
Taxes: tax.Set{&tax.Combo{Category: tax.CategoryVAT, Rate: rateStandard}},
156156
},
157157
{
158158
Index: 2,
@@ -164,8 +164,8 @@ func TestDesgloseConversion(t *testing.T) {
164164
},
165165
Taxes: tax.Set{
166166
&tax.Combo{
167-
Category: "VAT",
168-
Rate: "standard",
167+
Category: tax.CategoryVAT,
168+
Rate: rateStandard,
169169
},
170170
},
171171
},
@@ -192,9 +192,9 @@ func TestDesgloseConversion(t *testing.T) {
192192
},
193193
Discounts: []*bill.LineDiscount{DiscountOf(100)},
194194
Taxes: tax.Set{
195-
&tax.Combo{Category: "IRPF", Rate: "pro"},
195+
&tax.Combo{Category: es.TaxCategoryIRPF, Rate: rateIRPFPro},
196196
&tax.Combo{
197-
Category: "VAT",
197+
Category: tax.CategoryVAT,
198198
Ext: tax.Extensions{
199199
tbai.ExtKeyExempt: "OT",
200200
},
@@ -218,7 +218,7 @@ func TestDesgloseConversion(t *testing.T) {
218218
Item: &org.Item{Name: "A", Price: num.NewAmount(10, 0)},
219219
Taxes: tax.Set{
220220
&tax.Combo{
221-
Category: "VAT",
221+
Category: tax.CategoryVAT,
222222
Ext: tax.Extensions{tbai.ExtKeyExempt: "RL"},
223223
},
224224
},
@@ -240,7 +240,7 @@ func TestDesgloseConversion(t *testing.T) {
240240
Discounts: []*bill.LineDiscount{DiscountOf(100)},
241241
Taxes: tax.Set{
242242
&tax.Combo{
243-
Category: "VAT",
243+
Category: tax.CategoryVAT,
244244
Ext: tax.Extensions{tbai.ExtKeyExempt: "RL"},
245245
},
246246
},
@@ -260,8 +260,8 @@ func TestDesgloseConversion(t *testing.T) {
260260
Quantity: num.MakeAmount(100, 0),
261261
Item: &org.Item{Name: "A", Price: num.NewAmount(10, 0)},
262262
Taxes: tax.Set{
263-
&tax.Combo{Category: "VAT", Rate: "standard"},
264-
&tax.Combo{Category: "VAT", Rate: "reduced"},
263+
&tax.Combo{Category: tax.CategoryVAT, Rate: rateStandard},
264+
&tax.Combo{Category: tax.CategoryVAT, Rate: "reduced"},
265265
},
266266
}}
267267
_ = goblInvoice.Calculate()
@@ -306,7 +306,7 @@ func TestDesgloseConversion(t *testing.T) {
306306
Quantity: num.MakeAmount(100, 0),
307307
Item: &org.Item{Name: "A", Price: num.NewAmount(10, 0)},
308308
Taxes: tax.Set{
309-
&tax.Combo{Category: "VAT", Rate: "standard+eqs"},
309+
&tax.Combo{Category: tax.CategoryVAT, Rate: "standard+eqs"},
310310
},
311311
}}
312312
_ = goblInvoice.Calculate()
@@ -326,28 +326,28 @@ func TestDesgloseConversion(t *testing.T) {
326326
Index: 1,
327327
Quantity: num.MakeAmount(1, 0),
328328
Item: &org.Item{
329-
Key: "services",
329+
Key: org.ItemKeyServices,
330330
Name: "A",
331331
Price: num.NewAmount(10, 0),
332332
},
333333
Taxes: tax.Set{
334334
&tax.Combo{
335-
Category: "VAT",
336-
Rate: "standard",
335+
Category: tax.CategoryVAT,
336+
Rate: rateStandard,
337337
},
338338
},
339339
},
340340
{
341341
Index: 2,
342342
Quantity: num.MakeAmount(100, 0),
343343
Item: &org.Item{
344-
Key: "goods",
344+
Key: org.ItemKeyGoods,
345345
Name: "A",
346346
Price: num.NewAmount(10, 0),
347347
},
348348
Taxes: tax.Set{
349349
&tax.Combo{
350-
Category: "VAT",
350+
Category: tax.CategoryVAT,
351351
Rate: "general",
352352
Ext: tax.Extensions{tbai.ExtKeyProduct: "resale"},
353353
},
@@ -440,7 +440,7 @@ func TestDesgloseConversion(t *testing.T) {
440440
Index: 1,
441441
Quantity: num.MakeAmount(100, 0),
442442
Item: &org.Item{Name: "A", Price: num.NewAmount(10, 0)},
443-
Taxes: tax.Set{&tax.Combo{Category: "VAT", Rate: "standard"}},
443+
Taxes: tax.Set{&tax.Combo{Category: tax.CategoryVAT, Rate: rateStandard}},
444444
}}
445445
_ = goblInvoice.Calculate()
446446

@@ -458,7 +458,7 @@ func TestDesgloseConversion(t *testing.T) {
458458
Index: 1,
459459
Quantity: num.MakeAmount(100, 0),
460460
Item: &org.Item{Name: "A", Price: num.NewAmount(10, 0)},
461-
Taxes: tax.Set{&tax.Combo{Category: "VAT", Rate: "standard"}},
461+
Taxes: tax.Set{&tax.Combo{Category: tax.CategoryVAT, Rate: rateStandard}},
462462
}}
463463
_ = goblInvoice.Calculate()
464464

convert/doc_test.go

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import (
1818
"github.com/stretchr/testify/require"
1919
)
2020

21+
const passportCode = "PP123456S"
22+
2123
func TestInvoiceConversion(t *testing.T) {
2224
ts, err := time.Parse(time.RFC3339, "2022-02-01T04:00:00Z")
2325
require.NoError(t, err)
@@ -101,18 +103,47 @@ func TestInvoiceConversion(t *testing.T) {
101103
goblInvoice.Customer.TaxID = nil
102104
goblInvoice.Customer.Identities = []*org.Identity{
103105
{
104-
Key: "passport",
105-
Code: "PP123456S",
106+
Key: org.IdentityKeyPassport,
107+
Code: passportCode,
106108
},
107109
}
108110
invoice, _ := convert.NewTicketBAI(goblInvoice, ts, role, convert.ZoneBI)
109111

110112
dest := invoice.Sujetos.Destinatarios.IDDestinatario[0]
111113
assert.Equal(t, "03", dest.IDOtro.IDType)
112-
assert.Equal(t, "PP123456S", dest.IDOtro.ID)
114+
assert.Equal(t, passportCode, dest.IDOtro.ID)
113115
assert.Empty(t, dest.IDOtro.CodigoPais)
114116
})
115117

118+
t.Run("should use identities when Spanish customer has tax ID without code", func(t *testing.T) {
119+
goblInvoice := test.LoadInvoice("sample-invoice.json")
120+
goblInvoice.Customer.TaxID = &tax.Identity{Country: "ES"}
121+
goblInvoice.Customer.Identities = []*org.Identity{
122+
{Key: org.IdentityKeyPassport, Code: passportCode},
123+
}
124+
invoice, _ := convert.NewTicketBAI(goblInvoice, ts, role, convert.ZoneBI)
125+
126+
dest := invoice.Sujetos.Destinatarios.IDDestinatario[0]
127+
assert.Empty(t, dest.NIF)
128+
assert.Equal(t, "03", dest.IDOtro.IDType)
129+
assert.Equal(t, passportCode, dest.IDOtro.ID)
130+
assert.Equal(t, "ES", dest.IDOtro.CodigoPais)
131+
})
132+
133+
t.Run("should use identity country as CodigoPais when no tax ID", func(t *testing.T) {
134+
goblInvoice := test.LoadInvoice("sample-invoice.json")
135+
goblInvoice.Customer.TaxID = nil
136+
goblInvoice.Customer.Identities = []*org.Identity{
137+
{Country: "ES", Key: org.IdentityKeyPassport, Code: passportCode},
138+
}
139+
invoice, _ := convert.NewTicketBAI(goblInvoice, ts, role, convert.ZoneBI)
140+
141+
dest := invoice.Sujetos.Destinatarios.IDDestinatario[0]
142+
assert.Equal(t, "03", dest.IDOtro.IDType)
143+
assert.Equal(t, passportCode, dest.IDOtro.ID)
144+
assert.Equal(t, "ES", dest.IDOtro.CodigoPais)
145+
})
146+
116147
t.Run("should allow having no customer (useful for simplied invoices)", func(t *testing.T) {
117148
goblInvoice := test.LoadInvoice("sample-invoice.json")
118149
goblInvoice.Customer = nil

convert/invoice_test.go

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/invopop/gobl/addons/es/tbai"
1010
"github.com/invopop/gobl/bill"
1111
"github.com/invopop/gobl/cal"
12+
"github.com/invopop/gobl/cbc"
1213
"github.com/invopop/gobl/num"
1314
"github.com/invopop/gobl/org"
1415
"github.com/invopop/gobl/regimes/es"
@@ -17,6 +18,11 @@ import (
1718
"github.com/stretchr/testify/require"
1819
)
1920

21+
const (
22+
rateStandard cbc.Key = "standard"
23+
rateIRPFPro cbc.Key = "pro"
24+
)
25+
2026
func TestFacturaConversion(t *testing.T) {
2127
ts, err := time.Parse(time.RFC3339, "2022-08-15T22:15:05+02:00")
2228
require.NoError(t, err)
@@ -92,7 +98,7 @@ func TestFacturaConversion(t *testing.T) {
9298
Quantity: num.MakeAmount(100, 0),
9399
Item: &org.Item{Name: "A", Price: num.NewAmount(11, 0)},
94100
Discounts: []*bill.LineDiscount{DiscountOf(100)},
95-
Taxes: tax.Set{&tax.Combo{Category: "VAT", Rate: "standard"}},
101+
Taxes: tax.Set{&tax.Combo{Category: tax.CategoryVAT, Rate: rateStandard}},
96102
}}
97103
_ = goblInvoice.Calculate()
98104

@@ -109,8 +115,8 @@ func TestFacturaConversion(t *testing.T) {
109115
Quantity: num.MakeAmount(100, 0),
110116
Item: &org.Item{Name: "A", Price: num.NewAmount(10, 0)},
111117
Taxes: tax.Set{
112-
&tax.Combo{Category: "VAT", Rate: "standard"},
113-
&tax.Combo{Category: "IRPF", Rate: "pro"},
118+
&tax.Combo{Category: tax.CategoryVAT, Rate: rateStandard},
119+
&tax.Combo{Category: es.TaxCategoryIRPF, Rate: rateIRPFPro},
114120
},
115121
}}
116122
_ = goblInvoice.Calculate()
@@ -128,8 +134,8 @@ func TestFacturaConversion(t *testing.T) {
128134
Quantity: num.MakeAmount(100, 0),
129135
Item: &org.Item{Name: "A", Price: num.NewAmount(10, 0)},
130136
Taxes: tax.Set{
131-
&tax.Combo{Category: "VAT", Rate: "standard"},
132-
&tax.Combo{Category: "IRPF", Rate: "pro"},
137+
&tax.Combo{Category: tax.CategoryVAT, Rate: rateStandard},
138+
&tax.Combo{Category: es.TaxCategoryIRPF, Rate: rateIRPFPro},
133139
},
134140
}}
135141
_ = goblInvoice.Calculate()
@@ -147,7 +153,7 @@ func TestFacturaConversion(t *testing.T) {
147153
Quantity: num.MakeAmount(100, 0),
148154
Item: &org.Item{Name: "A", Price: num.NewAmount(10, 0)},
149155
Taxes: tax.Set{
150-
&tax.Combo{Category: "VAT", Rate: "standard"},
156+
&tax.Combo{Category: tax.CategoryVAT, Rate: rateStandard},
151157
},
152158
}}
153159
_ = goblInvoice.Calculate()
@@ -174,14 +180,14 @@ func TestFacturaConversion(t *testing.T) {
174180
Index: 1,
175181
Quantity: num.MakeAmount(100, 0),
176182
Item: &org.Item{
177-
Key: "goods",
183+
Key: org.ItemKeyGoods,
178184
Name: "A",
179185
Price: num.NewAmount(10, 0),
180186
},
181187
Taxes: tax.Set{
182188
&tax.Combo{
183-
Category: "VAT",
184-
Rate: "standard",
189+
Category: tax.CategoryVAT,
190+
Rate: rateStandard,
185191
Ext: tax.Extensions{tbai.ExtKeyProduct: "resale"},
186192
},
187193
},

convert/lines_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ func TestLines(t *testing.T) {
2525
Index: 1,
2626
Quantity: num.MakeAmount(100, 0),
2727
Item: &org.Item{Name: "A", Price: num.NewAmount(10, 0)},
28-
Taxes: tax.Set{&tax.Combo{Category: "VAT", Rate: "standard"}},
28+
Taxes: tax.Set{&tax.Combo{Category: tax.CategoryVAT, Rate: rateStandard}},
2929
}}
3030
_ = goblInvoice.Calculate()
3131

@@ -46,7 +46,7 @@ func TestLines(t *testing.T) {
4646
Quantity: num.MakeAmount(100, 0),
4747
Item: &org.Item{Name: "A", Price: num.NewAmount(11, 0)},
4848
Discounts: []*bill.LineDiscount{DiscountOf(100)},
49-
Taxes: tax.Set{&tax.Combo{Category: "VAT", Rate: "standard"}},
49+
Taxes: tax.Set{&tax.Combo{Category: tax.CategoryVAT, Rate: rateStandard}},
5050
}}
5151
_ = goblInvoice.Calculate()
5252

@@ -65,7 +65,7 @@ func TestLines(t *testing.T) {
6565
Index: 1,
6666
Quantity: num.MakeAmount(10, 0),
6767
Item: &org.Item{Name: "A", Price: num.NewAmount(121, 0)},
68-
Taxes: tax.Set{&tax.Combo{Category: "VAT", Rate: "standard"}},
68+
Taxes: tax.Set{&tax.Combo{Category: tax.CategoryVAT, Rate: rateStandard}},
6969
}}
7070
require.NoError(t, inv.Calculate())
7171
require.NoError(t, inv.RemoveIncludedTaxes())

convert/parties.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ func newDestinatario(party *org.Party) *IDDestinatario {
6565
ApellidosNombreRazonSocial: party.Name,
6666
}
6767

68-
if partyTaxCountry(party) == "ES" {
68+
if partyTaxCountry(party) == "ES" && party.TaxID.Code != "" {
6969
d.NIF = party.TaxID.Code.String()
7070
} else {
7171
d.IDOtro = otherIdentity(party)
@@ -103,6 +103,9 @@ func otherIdentity(party *org.Party) *IDOtro {
103103

104104
oid.IDType = it
105105
oid.ID = id.Code.String()
106+
if id.Country != "" {
107+
oid.CodigoPais = id.Country.String()
108+
}
106109
return oid
107110
}
108111

0 commit comments

Comments
 (0)