88 "github.com/invopop/gobl/cbc"
99 "github.com/invopop/gobl/l10n"
1010 "github.com/invopop/gobl/num"
11- "github.com/invopop/gobl/regimes/es"
1211 "github.com/invopop/gobl/tax"
1312)
1413
@@ -87,11 +86,6 @@ type DetalleNoSujeta struct {
8786 Importe num.Amount
8887}
8988
90- type taxInfo struct {
91- simplifiedRegime bool
92- customerRates bool
93- }
94-
9589func newTipoDesglose (gobl * bill.Invoice ) * TipoDesglose {
9690 if gobl .Totals == nil || gobl .Totals .Taxes == nil {
9791 return nil
@@ -100,25 +94,24 @@ func newTipoDesglose(gobl *bill.Invoice) *TipoDesglose {
10094 if catTotal == nil {
10195 return nil
10296 }
103- taxInfo := newTaxInfo (gobl )
10497
10598 desglose := & TipoDesglose {}
10699
107100 if gobl .Customer == nil || partyCountry (gobl .Customer ) == l10n .ES .Tax () {
108- desglose .DesgloseFactura = newDesgloseFactura (taxInfo , catTotal .Rates )
101+ desglose .DesgloseFactura = newDesgloseFactura (catTotal .Rates )
109102 } else {
110103 goods , services := splitByTBAIProduct (catTotal .Rates )
111104
112105 desglose .DesgloseTipoOperacion = & DesgloseTipoOperacion {
113- Entrega : newDesgloseFactura (taxInfo , goods ),
114- PrestacionServicios : newDesgloseFactura (taxInfo , services ),
106+ Entrega : newDesgloseFactura (goods ),
107+ PrestacionServicios : newDesgloseFactura (services ),
115108 }
116109 }
117110
118111 return desglose
119112}
120113
121- func newDesgloseFactura (taxInfo taxInfo , rates []* tax.RateTotal ) * DesgloseFactura {
114+ func newDesgloseFactura (rates []* tax.RateTotal ) * DesgloseFactura {
122115 if len (rates ) == 0 {
123116 return nil
124117 }
@@ -132,25 +125,25 @@ func newDesgloseFactura(taxInfo taxInfo, rates []*tax.RateTotal) *DesgloseFactur
132125 }
133126
134127 for _ , rate := range rates {
135- if taxInfo .isNoSujeta (rate ) {
128+ code := rate .Ext .Get (tbai .ExtKeyExempt )
129+ switch {
130+ case code .In (notSubjectExemptionCodes ... ):
136131 df .NoSujeta .appendDetalle (& DetalleNoSujeta {
137- Causa : taxInfo . causaNoSujeta ( rate ),
132+ Causa : code . String ( ),
138133 Importe : rate .Base ,
139134 })
140- } else if taxInfo . isExenta ( rate ) {
135+ case code . In ( exemptExemptionCodes ... ):
141136 df .Sujeta .Exenta .appendDetalle (& DetalleExenta {
142- CausaExencion : rate . Ext . Get ( tbai . ExtKeyExempt ) .String (),
137+ CausaExencion : code .String (),
143138 BaseImponible : rate .Base .Rescale (2 ).String (),
144139 })
145- } else {
140+ default :
146141 dne := df .Sujeta .NoExenta .appendDetalle (& DetalleNoExenta {
147142 TipoNoExenta : nonExemptedType (rate ),
148143 DesgloseIVA : & DesgloseIVA {},
149144 })
150145
151- diva := newDetalleIVA (taxInfo , rate )
152-
153- dne .DesgloseIVA .appendDetalle (diva )
146+ dne .DesgloseIVA .appendDetalle (newDetalleIVA (rate ))
154147 }
155148 }
156149
@@ -217,7 +210,7 @@ func (di *DesgloseIVA) appendDetalle(d *DetalleIVA) *DetalleIVA {
217210 return d
218211}
219212
220- func newDetalleIVA (taxInfo taxInfo , rate * tax.RateTotal ) * DetalleIVA {
213+ func newDetalleIVA (rate * tax.RateTotal ) * DetalleIVA {
221214 percent := num .PercentageZero
222215 if rate .Percent != nil {
223216 percent = * rate .Percent
@@ -233,7 +226,7 @@ func newDetalleIVA(taxInfo taxInfo, rate *tax.RateTotal) *DetalleIVA {
233226 diva .CuotaRecargoEquivalencia = rate .Surcharge .Amount .Rescale (2 ).String ()
234227 }
235228
236- if taxInfo . simplifiedRegime || rate .Ext .Get (tbai .ExtKeyProduct ) == "resale" {
229+ if rate . Ext . Get ( tbai . ExtKeyRegime ) == "52" || rate .Ext .Get (tbai .ExtKeyProduct ) == "resale" {
237230 diva .OperacionEnRecargoDeEquivalenciaORegimenSimplificado = "S"
238231 }
239232
@@ -249,47 +242,19 @@ func formatPercent(percent num.Percentage) string {
249242 return maybeNegative
250243}
251244
252- func newTaxInfo (gobl * bill.Invoice ) taxInfo {
253- return taxInfo {
254- simplifiedRegime : gobl .HasTags (es .TagSimplifiedScheme ),
255- customerRates : gobl .HasTags (tax .TagCustomerRates ),
256- }
257- }
258-
259- // notSubjectExemptionCodes lists the es-tbai-exemption codes that map to
260- // DetalleNoSujeta/Causa.
245+ // es-tbai-exemption codes routed to DetalleNoSujeta.
261246var notSubjectExemptionCodes = []cbc.Code {"OT" , "RL" , "VT" , "IE" }
262247
263- // reverseChargeExemptionCodes lists the es-tbai-exemption codes that map to
264- // DetalleNoExenta/TipoNoExenta = S2.
248+ // es-tbai-exemption codes routed to Sujeta.Exenta.
249+ var exemptExemptionCodes = []cbc.Code {"E1" , "E2" , "E3" , "E4" , "E5" , "E6" }
250+
251+ // es-tbai-exemption codes routed to DetalleNoExenta with TipoNoExenta=S2.
265252var reverseChargeExemptionCodes = []cbc.Code {"S2" }
266253
267- // nonExemptedType returns the TBAI TipoNoExenta value for a subject,
268- // non-exempt tax rate.
254+ // nonExemptedType returns the TipoNoExenta value for a non-exempt rate.
269255func nonExemptedType (r * tax.RateTotal ) string {
270256 if r .Ext .Get (tbai .ExtKeyExempt ).In (reverseChargeExemptionCodes ... ) {
271257 return "S2"
272258 }
273259 return "S1"
274260}
275-
276- func (t taxInfo ) isNoSujeta (r * tax.RateTotal ) bool {
277- if t .customerRates {
278- return true
279- }
280- return r .Percent == nil && r .Ext .Get (tbai .ExtKeyExempt ).In (notSubjectExemptionCodes ... )
281- }
282-
283- func (t taxInfo ) causaNoSujeta (r * tax.RateTotal ) string {
284- if t .customerRates {
285- return "RL"
286- }
287- return r .Ext .Get (tbai .ExtKeyExempt ).String ()
288- }
289-
290- func (taxInfo ) isExenta (r * tax.RateTotal ) bool {
291- code := r .Ext .Get (tbai .ExtKeyExempt )
292- return r .Percent == nil &&
293- ! code .In (notSubjectExemptionCodes ... ) &&
294- ! code .In (reverseChargeExemptionCodes ... )
295- }
0 commit comments