cfdi40 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +2 -0
- data/Gemfile.lock +1 -1
- data/README.md +2 -0
- data/README_es-MX.md +18 -1
- data/lib/cfdi40/comprobante.rb +36 -12
- data/lib/cfdi40/concepto.rb +22 -24
- data/lib/cfdi40/impuestos.rb +2 -2
- data/lib/cfdi40/traslado.rb +2 -2
- data/lib/cfdi40/version.rb +1 -1
- data/lib/xsd/Pagos20.xsd +539 -0
- data/lib/xsd/TimbreFiscalDigitalv11.xsd +83 -0
- data/lib/xsd/catPagos.xsd +9 -0
- data/lib/xsd/cfdv40.xsd +2 -0
- data/lib/xslt/ComercioExterior11.xslt +181 -0
- data/lib/xslt/cadenaoriginal_TFD_1_1.xslt +47 -0
- data/lib/xslt/ecc12.xslt +99 -0
- data/lib/xslt/ine11.xslt +51 -30
- data/lib/xslt/ventavehiculos11.xslt +53 -0
- metadata +9 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d48bd150dec201d3a2b0812d49080313c5e4aec6efd836e5606e9e2edabd822f
|
4
|
+
data.tar.gz: 3f437736ebc91684c7652f217f64a0e04c9e8b18519a18a02397ab4f95ca8db9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4491ff366eeb72c4c6d1792227750e5c3f333d6df52f7d974c05eff8d4d94f30a44e98dfefaf03b1aaa41a8d1407e2765a3ef026617faa071fb86049cbbec9f9
|
7
|
+
data.tar.gz: 77c1ee1687c4b13af13768afa7a5b3ee0c7ab2071a4a3ddbf45d3bedcf4a18bb2a8e56b07bdf1762d6e833c052cf77c1b3272b04a75cb3f28d2c0494b76d66af
|
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
data/README_es-MX.md
CHANGED
@@ -14,7 +14,7 @@ que esta herramienta:
|
|
14
14
|
información esencial para la elaboración del CFDi.
|
15
15
|
* Realice los cálculos complementarios como impuestos,
|
16
16
|
totales, etcétera.
|
17
|
-
* Valide el CFDi contra los
|
17
|
+
* Valide el CFDi contra los XSD
|
18
18
|
* Selle el CFDi.
|
19
19
|
|
20
20
|
# Uso
|
@@ -55,6 +55,23 @@ que esta herramienta:
|
|
55
55
|
|
56
56
|
# Cambios
|
57
57
|
|
58
|
+
# 0.0.5
|
59
|
+
|
60
|
+
* IVA tasa 0 e IVA excento. Los conceptos con iva tasa 0 deben llevar el
|
61
|
+
nodo de traslados de impuestos. Los conceptos excentos de iva no
|
62
|
+
llevan el nodo de traslado. Al agregar el concepto usar `nil` para el
|
63
|
+
IVA cuando sea excento.
|
64
|
+
* Nuevo cálculo de impuestos e importes. El PAC solo acepta 2 decimales
|
65
|
+
en los nodos de traslado. Esto puede generar discrepancias al sumar
|
66
|
+
los conceptos si no se maneja el mismo número de decimales. Solamente
|
67
|
+
el valor unitario se manejará con 6 decimales.
|
68
|
+
|
69
|
+
# 0.0.4
|
70
|
+
|
71
|
+
* Atributos 'Total' y 'Subtotal' van con 2 decimales. Aunque el anexo 20
|
72
|
+
indica que el tipo es `t_Importe` (6 decimales) el PAC acepta solo 2
|
73
|
+
decimales si el CFDi está en pesos mexicanos.
|
74
|
+
|
58
75
|
# 0.0.3
|
59
76
|
|
60
77
|
* Lee RFC en certificados de personas morales. Los certificados de
|
data/lib/cfdi40/comprobante.rb
CHANGED
@@ -60,7 +60,7 @@ module Cfdi40
|
|
60
60
|
@sat_csd ||= SatCsd.new
|
61
61
|
@sat_csd.cert_der = cert_data
|
62
62
|
emisor.rfc = @sat_csd.rfc
|
63
|
-
emisor.nombre
|
63
|
+
emisor.nombre ||= @sat_csd.name
|
64
64
|
@no_certificado = @sat_csd.no_certificado
|
65
65
|
@certificado = @sat_csd.cert64
|
66
66
|
true
|
@@ -82,18 +82,42 @@ module Cfdi40
|
|
82
82
|
@docxml = nil
|
83
83
|
end
|
84
84
|
|
85
|
-
#
|
86
|
-
#
|
87
|
-
#
|
88
|
-
# clave_unidad
|
89
|
-
#
|
90
|
-
# descripcion
|
91
|
-
#
|
92
|
-
#
|
93
|
-
#
|
94
|
-
#
|
85
|
+
# ## Required attributes
|
86
|
+
#
|
87
|
+
# +clave_prod_serv+:: From SAT catalogue
|
88
|
+
# +clave_unidad+:: From SAT catalogue
|
89
|
+
# +cantidad+:: Must be greather than 0
|
90
|
+
# +descripcion+:: Product or service description
|
91
|
+
#
|
92
|
+
# ### Price and Taxes attributes
|
93
|
+
#
|
94
|
+
# +tasa_iva+:: Decimal between 0 and 1. Nil means exempt. Default value is 0.16
|
95
|
+
# +tasa_ieps+:: Decimal between 0 and 1. Nil means exempt. Default value is null
|
96
|
+
# +precio_bruto+:: Price before apply taxes or gross price.
|
97
|
+
# All quantities are calculated based on this price and taxes rate.
|
98
|
+
# +precio_neto+:: Precio after taxes or net price. All quantities are calculated from this prices.
|
99
|
+
# When both, +precio_neto+ and +precio_bruto+ exist, +precio_neto+ is used
|
100
|
+
#
|
101
|
+
# The most common usage requires only the net price (+precio_neto+).
|
102
|
+
#
|
103
|
+
# ## Optional attributes:
|
104
|
+
# +no_identificacion+::
|
105
|
+
# +unidad+::
|
106
|
+
# +descuento+:: PENDING
|
107
|
+
#
|
108
|
+
# ## Special attributes
|
109
|
+
#
|
110
|
+
# ### IEDU attributes
|
111
|
+
#
|
112
|
+
# IEDU node (path: cfdi:Comprobante/cfdi:Conceptos/cfdi:Concepto/cfdi:ComplementoConcepto/iedu:instEducativas) is
|
113
|
+
# generated when one of +iedu_nombre_alumno+, +iedu_curp+, +iedu_nivel_educativo+ exist.
|
114
|
+
#
|
115
|
+
# +iedu_nombre_alumno+::
|
116
|
+
# +iedu_curp+::
|
117
|
+
# +iedu_nivel_educativo+::
|
118
|
+
# +iedu_aut_rvoe+::
|
119
|
+
# +iedu_rfc_pago+::
|
95
120
|
#
|
96
|
-
# TODO: Document accepted attributes and its use
|
97
121
|
def add_concepto(attributes = {})
|
98
122
|
concepto = Concepto.new
|
99
123
|
concepto.parent_node = @conceptos
|
data/lib/cfdi40/concepto.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Represents node 'concepto'
|
2
2
|
#
|
3
|
-
# * Attribute +Importe+ represente gross amount. Gross amount
|
3
|
+
# * Attribute +Importe+ represente gross amount. Gross amount is before taxes and the result of multiply
|
4
4
|
# +ValorUnitario+ by +Cantidad+
|
5
5
|
#
|
6
6
|
module Cfdi40
|
@@ -24,7 +24,7 @@ module Cfdi40
|
|
24
24
|
|
25
25
|
def initialize
|
26
26
|
@tasa_iva = 0.16
|
27
|
-
@tasa_ieps =
|
27
|
+
@tasa_ieps = nil
|
28
28
|
super
|
29
29
|
end
|
30
30
|
|
@@ -33,6 +33,7 @@ module Cfdi40
|
|
33
33
|
def calculate!
|
34
34
|
set_defaults
|
35
35
|
assign_objeto_imp
|
36
|
+
# TODO: accept discount
|
36
37
|
if defined?(@precio_neto) && !@precio_neto.nil?
|
37
38
|
calculate_from_net_price
|
38
39
|
elsif defined?(@precio_bruto) && !@precio_bruto.nil?
|
@@ -61,33 +62,26 @@ module Cfdi40
|
|
61
62
|
|
62
63
|
def calculate_from_net_price
|
63
64
|
set_defaults
|
64
|
-
@
|
65
|
-
|
65
|
+
@precio_neto = @precio_neto.round(2)
|
66
|
+
@precio_bruto = (@precio_neto / ((1 + tasa_iva.to_f) * (1 + tasa_ieps.to_f))).round(6)
|
67
|
+
calculate_taxes
|
66
68
|
update_xml_attributes
|
67
69
|
end
|
68
70
|
|
69
|
-
def breakdown_taxes
|
70
|
-
@base_iva = @importe_neto / (1 + tasa_iva)
|
71
|
-
@iva = @importe_neto - @base_iva
|
72
|
-
@base_ieps = @base_iva / (1 + tasa_ieps)
|
73
|
-
@ieps = @base_iva - @base_ieps
|
74
|
-
@importe_bruto = @base_ieps
|
75
|
-
@precio_bruto = @importe_bruto / @cantidad
|
76
|
-
end
|
77
|
-
|
78
71
|
def calculate_from_gross_price
|
79
|
-
@
|
80
|
-
|
72
|
+
@precio_bruto = @precio_bruto.round(6)
|
73
|
+
calculate_taxes
|
74
|
+
@precio_neto = (@importe_neto / cantidad).round(2)
|
81
75
|
update_xml_attributes
|
82
76
|
end
|
83
77
|
|
84
|
-
def
|
85
|
-
@base_ieps = @
|
86
|
-
@ieps = @base_ieps * tasa_ieps
|
87
|
-
@base_iva = @base_ieps + @ieps
|
88
|
-
@iva = @base_iva * tasa_iva
|
89
|
-
@
|
90
|
-
@
|
78
|
+
def calculate_taxes
|
79
|
+
@base_ieps = (@precio_bruto * cantidad).round(2)
|
80
|
+
@ieps = (@base_ieps * tasa_ieps.to_f).round(2)
|
81
|
+
@base_iva = (@base_ieps + @ieps).round(2)
|
82
|
+
@iva = (@base_iva * tasa_iva.to_f).round(2)
|
83
|
+
@importe_bruto = @base_ieps
|
84
|
+
@importe_neto = (@base_iva + @iva).round(2)
|
91
85
|
end
|
92
86
|
|
93
87
|
def update_xml_attributes
|
@@ -96,7 +90,7 @@ module Cfdi40
|
|
96
90
|
end
|
97
91
|
|
98
92
|
def add_info_to_traslado_iva
|
99
|
-
return
|
93
|
+
return if @tasa_iva.nil?
|
100
94
|
|
101
95
|
traslado_iva_node.importe = @iva
|
102
96
|
traslado_iva_node.base = @base_iva
|
@@ -104,9 +98,13 @@ module Cfdi40
|
|
104
98
|
end
|
105
99
|
|
106
100
|
def assign_objeto_imp
|
101
|
+
#01 No objeto de impuesto.
|
102
|
+
#02 Sí objeto de impuesto.
|
103
|
+
#03 Sí objeto del impuesto y no obligado al desglose.
|
104
|
+
|
107
105
|
return if objeto_impuestos == '03'
|
108
106
|
|
109
|
-
self.objeto_impuestos = (
|
107
|
+
self.objeto_impuestos = (!@tasa_iva.nil? || !@tasa_ieps.nil? ? '02' : '01')
|
110
108
|
end
|
111
109
|
|
112
110
|
def impuestos_node
|
data/lib/cfdi40/impuestos.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Cfdi40
|
2
2
|
class Impuestos < Node
|
3
|
-
define_attribute :total_impuestos_retenidos, xml_attribute: 'TotalImpuestosRetenidos', format: :
|
4
|
-
define_attribute :total_impuestos_trasladados, xml_attribute: 'TotalImpuestosTrasladados', format: :
|
3
|
+
define_attribute :total_impuestos_retenidos, xml_attribute: 'TotalImpuestosRetenidos', format: :t_ImporteMXN
|
4
|
+
define_attribute :total_impuestos_trasladados, xml_attribute: 'TotalImpuestosTrasladados', format: :t_ImporteMXN
|
5
5
|
|
6
6
|
def traslados
|
7
7
|
return @traslados if defined?(@traslados)
|
data/lib/cfdi40/traslado.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
module Cfdi40
|
2
2
|
class Traslado < Node
|
3
|
-
define_attribute :base, xml_attribute: 'Base', format: :
|
3
|
+
define_attribute :base, xml_attribute: 'Base', format: :t_ImporteMXN
|
4
4
|
define_attribute :impuesto, xml_attribute: 'Impuesto'
|
5
5
|
define_attribute :tipo_factor, xml_attribute: 'TipoFactor', default: 'Tasa'
|
6
6
|
define_attribute :tasa_o_cuota, xml_attribute: 'TasaOCuota', format: :t_Importe
|
7
|
-
define_attribute :importe, xml_attribute: 'Importe', format: :
|
7
|
+
define_attribute :importe, xml_attribute: 'Importe', format: :t_ImporteMXN
|
8
8
|
end
|
9
9
|
end
|
data/lib/cfdi40/version.rb
CHANGED