cfdi40 0.0.5 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README_es-MX.md +50 -0
- data/lib/cfdi40/complemento.rb +18 -0
- data/lib/cfdi40/comprobante.rb +46 -1
- data/lib/cfdi40/concepto.rb +3 -1
- data/lib/cfdi40/docto_relacionado.rb +66 -0
- data/lib/cfdi40/impuestos_dr.rb +12 -0
- data/lib/cfdi40/impuestos_p.rb +12 -0
- data/lib/cfdi40/node.rb +10 -1
- data/lib/cfdi40/pago.rb +56 -0
- data/lib/cfdi40/pagos.rb +73 -0
- data/lib/cfdi40/totales.rb +15 -0
- data/lib/cfdi40/traslado_dr.rb +18 -0
- data/lib/cfdi40/traslado_p.rb +9 -0
- data/lib/cfdi40/traslados_dr.rb +5 -0
- data/lib/cfdi40/traslados_p.rb +16 -0
- data/lib/cfdi40/version.rb +1 -1
- data/lib/cfdi40.rb +11 -0
- metadata +13 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 55ca7f3a64dc87b4b19cbb5d389f71ccd624b70e7c5af601d97dd4dd6e1599db
|
4
|
+
data.tar.gz: 9cab2e03e554d96d47ff328c6c520782036ee9b561f11586c42bd353a3112f1d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '0310189ea57acabe4fffc77ed24d1b02aab3d49e0afafd47d1abf7df10856d19a5a00b89d302138c6b43b036e8af5d52671d922b274e10613f1d57d76b732e1e'
|
7
|
+
data.tar.gz: 719ed8d0e569dd621edf7ee702271b7c468c2e6b4606297f650cac39b6cb199d06d881f07b15e56599d214da3481651987348cfc24997e6a1843939ea933c711
|
data/Gemfile.lock
CHANGED
data/README_es-MX.md
CHANGED
@@ -53,8 +53,58 @@ que esta herramienta:
|
|
53
53
|
# Genera CFDI firmado
|
54
54
|
xml_string = cfdi.to_xml
|
55
55
|
|
56
|
+
## Ejemplo CFDI con complemento de pago
|
57
|
+
|
58
|
+
# Inicia un cfdi
|
59
|
+
cfdi = Cfdi40.new
|
60
|
+
cfdi.tipo_de_comprobante = 'P'
|
61
|
+
|
62
|
+
# Datos del emisor.
|
63
|
+
# RFC y Nombre se extraen del certificado si no existen
|
64
|
+
cfdi.lugar_expedicion = '06000'
|
65
|
+
cfdi.emisor.regimen_fiscal = '612'
|
66
|
+
|
67
|
+
# Datos del receptor
|
68
|
+
cfdi.receptor.nombre = 'JUAN PUEBLO BUENO'
|
69
|
+
cfdi.receptor.rfc = 'XAXX010101000'
|
70
|
+
cfdi.receptor.domicilio_fiscal = '06000'
|
71
|
+
cfdi.receptor.regimen_fiscal = '616'
|
72
|
+
cfdi.receptor.uso_cfdi = 'CP01'
|
73
|
+
|
74
|
+
# Agrega un concepto en pesos,
|
75
|
+
# precio final al cliente (neto)
|
76
|
+
# causa IVA con tasa de 16% (default)
|
77
|
+
cfdi.add_pago(
|
78
|
+
monto: 200.17,
|
79
|
+
uuid: 'e40229b3-5c4b-46fb-9ba8-707df828a5bc',
|
80
|
+
serie: 'A',
|
81
|
+
folio: '12345',
|
82
|
+
num_parcialidad: 2,
|
83
|
+
fecha_pago: '2023-04-01T12:20:34',
|
84
|
+
forma_pago: '01',
|
85
|
+
importe_saldo_anterior: 845.673
|
86
|
+
)
|
87
|
+
|
88
|
+
# Archivos CSD
|
89
|
+
cfdi.cert_path = '/path_to/certificado.cer'
|
90
|
+
cfdi.key_path = '/path_to/llave_privada.key'
|
91
|
+
cfdi.key_pass = 'contraseña'
|
92
|
+
|
93
|
+
# Genera CFDI firmado
|
94
|
+
xml_string = cfdi.to_xml
|
95
|
+
|
96
|
+
|
97
|
+
# Lo que sigue
|
98
|
+
|
99
|
+
* Nodo de Traslados cuando hay tasa de IEPS
|
100
|
+
* Retenciones de impuestos
|
101
|
+
* CFDI de pagos con varios pagos y varios documentos en cada pago
|
102
|
+
|
56
103
|
# Cambios
|
57
104
|
|
105
|
+
# 0.0.6
|
106
|
+
* CFDi con complemento de pagos
|
107
|
+
|
58
108
|
# 0.0.5
|
59
109
|
|
60
110
|
* IVA tasa 0 e IVA excento. Los conceptos con iva tasa 0 deben llevar el
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Cfdi40
|
2
|
+
class Complemento < Node
|
3
|
+
# See Comprobante#add_pago
|
4
|
+
def add_pago(attributes={})
|
5
|
+
pagos.totales_node
|
6
|
+
pagos.add_pago(attributes)
|
7
|
+
end
|
8
|
+
|
9
|
+
def pagos
|
10
|
+
return @pagos if defined?(@pagos)
|
11
|
+
|
12
|
+
@pagos = Pagos.new
|
13
|
+
@pagos.parent_node = self
|
14
|
+
@children_nodes << @pagos
|
15
|
+
@pagos
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/cfdi40/comprobante.rb
CHANGED
@@ -119,6 +119,8 @@ module Cfdi40
|
|
119
119
|
# +iedu_rfc_pago+::
|
120
120
|
#
|
121
121
|
def add_concepto(attributes = {})
|
122
|
+
raise Error, 'CFDi tipo pago no acepta conceptos' if tipo_de_comprobante == 'P'
|
123
|
+
|
122
124
|
concepto = Concepto.new
|
123
125
|
concepto.parent_node = @conceptos
|
124
126
|
attributes.each do |key, value|
|
@@ -135,6 +137,23 @@ module Cfdi40
|
|
135
137
|
concepto
|
136
138
|
end
|
137
139
|
|
140
|
+
# TODO: Doc params add_pago
|
141
|
+
# monto
|
142
|
+
# uuid
|
143
|
+
# folio
|
144
|
+
# serie
|
145
|
+
# num_parcialidad
|
146
|
+
# fecha_pago
|
147
|
+
# forma_pago
|
148
|
+
# importe_saldo_anterior
|
149
|
+
# objeto_impuestos
|
150
|
+
def add_pago(attributes = {})
|
151
|
+
raise Error, "CFDi debe ser tipo 'P'" unless tipo_de_comprobante == 'P'
|
152
|
+
|
153
|
+
add_node_concepto_actividad_pago
|
154
|
+
complemento.add_pago(attributes)
|
155
|
+
end
|
156
|
+
|
138
157
|
def to_s
|
139
158
|
to_xml
|
140
159
|
end
|
@@ -167,6 +186,23 @@ module Cfdi40
|
|
167
186
|
|
168
187
|
private
|
169
188
|
|
189
|
+
def add_node_concepto_actividad_pago
|
190
|
+
return if defined?(@concepto_actividad)
|
191
|
+
|
192
|
+
@receptor.uso_cfdi = 'CP01'
|
193
|
+
@concepto_actividad = Concepto.new
|
194
|
+
@concepto_actividad.clave_prod_serv = '84111506'
|
195
|
+
@concepto_actividad.cantidad = 1
|
196
|
+
@concepto_actividad.clave_unidad = 'ACT'
|
197
|
+
@concepto_actividad.descripcion = 'Pago'
|
198
|
+
@concepto_actividad.precio_bruto = 0
|
199
|
+
@concepto_actividad.tasa_iva = nil
|
200
|
+
@concepto_actividad.objeto_impuestos = '01'
|
201
|
+
@concepto_actividad.calculate!
|
202
|
+
@conceptos.add_child_node @concepto_actividad
|
203
|
+
calculate!
|
204
|
+
end
|
205
|
+
|
170
206
|
def docxml
|
171
207
|
return @docxml if defined?(@docxml) && !@docxml.nil?
|
172
208
|
|
@@ -245,7 +281,7 @@ module Cfdi40
|
|
245
281
|
impuestos_node.traslados
|
246
282
|
end
|
247
283
|
|
248
|
-
# Eliminar
|
284
|
+
# TODO: Eliminar
|
249
285
|
def traslado_iva_node
|
250
286
|
impuestos_node.traslado_iva
|
251
287
|
end
|
@@ -256,5 +292,14 @@ module Cfdi40
|
|
256
292
|
@sat_csd ||= SatCsd.new
|
257
293
|
@sat_csd.set_private_key(@key_data, (defined?(@key_pass) ? @key_pass : nil))
|
258
294
|
end
|
295
|
+
|
296
|
+
def complemento
|
297
|
+
return @complemento if defined?(@complemento)
|
298
|
+
|
299
|
+
@complemento = Complemento.new
|
300
|
+
@complemento.parent_node = self
|
301
|
+
@children_nodes << @complemento
|
302
|
+
@complemento
|
303
|
+
end
|
259
304
|
end
|
260
305
|
end
|
data/lib/cfdi40/concepto.rb
CHANGED
@@ -71,7 +71,9 @@ module Cfdi40
|
|
71
71
|
def calculate_from_gross_price
|
72
72
|
@precio_bruto = @precio_bruto.round(6)
|
73
73
|
calculate_taxes
|
74
|
-
|
74
|
+
# May be can not be rounded with 2 decimals.
|
75
|
+
# Example gross_price = 1.99512
|
76
|
+
@precio_neto = (@importe_neto / cantidad).round(6)
|
75
77
|
update_xml_attributes
|
76
78
|
end
|
77
79
|
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Cfdi40
|
2
|
+
class DoctoRelacionado < Node
|
3
|
+
define_attribute :id_documento, xml_attribute: 'IdDocumento'
|
4
|
+
define_attribute :serie, xml_attribute: 'Serie'
|
5
|
+
define_attribute :folio, xml_attribute: 'Folio'
|
6
|
+
define_attribute :moneda_dr, xml_attribute: 'MonedaDR', default: 'MXN'
|
7
|
+
define_attribute :equivalencia_dr, xml_attribute: 'EquivalenciaDR'
|
8
|
+
define_attribute :num_parcialidad, xml_attribute: 'NumParcialidad'
|
9
|
+
define_attribute :imp_saldo_ant, xml_attribute: 'ImpSaldoAnt', format: :t_ImporteMXN
|
10
|
+
define_attribute :imp_pagado, xml_attribute: 'ImpPagado', format: :t_ImporteMXN
|
11
|
+
define_attribute :imp_saldo_insoluto, xml_attribute: 'ImpSaldoInsoluto', format: :t_ImporteMXN
|
12
|
+
define_attribute :objeto_imp_dr, xml_attribute: 'ObjetoImpDR', default: '02'
|
13
|
+
|
14
|
+
def calculate!
|
15
|
+
self.imp_saldo_insoluto = (imp_saldo_ant - imp_pagado).round(2)
|
16
|
+
add_impuestos
|
17
|
+
end
|
18
|
+
|
19
|
+
# Add nodes for 'traslado_dr' and/or 'retencion_dr' and intermetiate nodes
|
20
|
+
def add_impuestos
|
21
|
+
add_traslado if objeto_imp_dr == '02'
|
22
|
+
end
|
23
|
+
|
24
|
+
def add_traslado
|
25
|
+
return unless objeto_imp_dr == '02'
|
26
|
+
|
27
|
+
# Taxes values for IVA rate 0.16 assumming that all 'conceptos' in the realted document
|
28
|
+
# has the same tax rate. This could not be true but the is the most common case.
|
29
|
+
traslado_dr = TrasladoDR.new
|
30
|
+
traslado_dr.monto_pago = imp_pagado.round(2)
|
31
|
+
traslado_dr.calculate!
|
32
|
+
traslados_dr.add_child_node(traslado_dr)
|
33
|
+
traslado_dr
|
34
|
+
end
|
35
|
+
|
36
|
+
# Return a hash. The key is an array [impuesto, tipo_factor, tasa_o_cuot]
|
37
|
+
# and the value is another hash with the keys :base, :importe
|
38
|
+
def traslados_summary
|
39
|
+
return {} unless defined?(@traslados_dr)
|
40
|
+
|
41
|
+
summary = {}
|
42
|
+
@traslados_dr.children_nodes.each do |traslado_dr|
|
43
|
+
key = [traslado_dr.impuesto_dr, traslado_dr.tipo_factor_dr, traslado_dr.tasa_o_cuota_dr]
|
44
|
+
summary[key] ||= { base: 0, importe: 0 }
|
45
|
+
summary[key][:base] += traslado_dr.base_dr.to_f
|
46
|
+
summary[key][:importe] += traslado_dr.importe_dr.to_f
|
47
|
+
end
|
48
|
+
summary
|
49
|
+
end
|
50
|
+
|
51
|
+
def traslados_dr
|
52
|
+
return @traslados_dr if defined?(@traslados_dr)
|
53
|
+
|
54
|
+
@traslados_dr = impuestos_dr.traslados_dr
|
55
|
+
end
|
56
|
+
|
57
|
+
def impuestos_dr
|
58
|
+
return @impuestos_dr if defined?(@impuestos_dr)
|
59
|
+
|
60
|
+
@impuestos_dr = ImpuestosDR.new
|
61
|
+
@impuestos_dr.parent_node = self
|
62
|
+
@children_nodes << @impuestos_dr
|
63
|
+
@impuestos_dr
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/lib/cfdi40/node.rb
CHANGED
@@ -7,6 +7,7 @@ module Cfdi40
|
|
7
7
|
def initialize
|
8
8
|
self.class.verify_class_variables
|
9
9
|
@children_nodes = []
|
10
|
+
set_defaults
|
10
11
|
end
|
11
12
|
|
12
13
|
# Use class variables to define attributes used to create nodes
|
@@ -87,6 +88,13 @@ module Cfdi40
|
|
87
88
|
instance_variable_get("@#{accessor}".to_sym).nil?
|
88
89
|
end
|
89
90
|
|
91
|
+
def add_child_node(child_node)
|
92
|
+
raise Error, 'child_node must be a Node object' unless child_node.is_a?(Node)
|
93
|
+
|
94
|
+
child_node.parent_node = self
|
95
|
+
@children_nodes << child_node
|
96
|
+
end
|
97
|
+
|
90
98
|
def current_namespace
|
91
99
|
return unless self.class.respond_to?(:namespaces)
|
92
100
|
if self.class.namespaces.empty?
|
@@ -97,7 +105,8 @@ module Cfdi40
|
|
97
105
|
end
|
98
106
|
|
99
107
|
def create_xml_node
|
100
|
-
set_defaults
|
108
|
+
# TODO: Quitar la siguiente linea (set_defaults) si funciona poniendo los defaults en initialize
|
109
|
+
# set_defaults
|
101
110
|
if self.respond_to?(:before_add, true)
|
102
111
|
self.before_add
|
103
112
|
end
|
data/lib/cfdi40/pago.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
module Cfdi40
|
2
|
+
class Pago < Node
|
3
|
+
define_attribute :monto, xml_attribute: 'Monto'
|
4
|
+
define_attribute :fecha_pago, xml_attribute: 'FechaPago'
|
5
|
+
define_attribute :forma_pago, xml_attribute: 'FormaDePagoP'
|
6
|
+
define_attribute :moneda, xml_attribute: 'MonedaP', readonly: true, default: 'MXN'
|
7
|
+
define_attribute :tipo_cambio, xml_attribute: 'TipoCambioP', readonly: true, default: '1'
|
8
|
+
|
9
|
+
attr_accessor :uuid, :serie, :folio, :num_parcialidad, :importe_saldo_anterior, :objeto_impuestos
|
10
|
+
|
11
|
+
# Generate docto_relacionado node
|
12
|
+
# Data for dcto_relacionado node is obtained from de accessors
|
13
|
+
# uuid, serie, folio
|
14
|
+
def add_docto_relacionado
|
15
|
+
docto_relacionado = DoctoRelacionado.new
|
16
|
+
docto_relacionado.parent_node = self
|
17
|
+
docto_relacionado.id_documento = uuid
|
18
|
+
docto_relacionado.serie = serie
|
19
|
+
docto_relacionado.folio = folio
|
20
|
+
docto_relacionado.num_parcialidad = num_parcialidad
|
21
|
+
docto_relacionado.imp_saldo_ant = importe_saldo_anterior.round(2)
|
22
|
+
docto_relacionado.imp_pagado = monto
|
23
|
+
docto_relacionado.calculate!
|
24
|
+
@children_nodes << docto_relacionado
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_impuestos_p
|
28
|
+
impuestos_p = ImpuestosP.new
|
29
|
+
add_child_node impuestos_p
|
30
|
+
impuestos_p.traslados_p.add_traslado_p_nodes
|
31
|
+
end
|
32
|
+
|
33
|
+
def docto_relacionados
|
34
|
+
return @docto_relacionados if defined?(@docto_relacionados)
|
35
|
+
|
36
|
+
@docto_relacionados =
|
37
|
+
@children_nodes.select do |child|
|
38
|
+
child if child.class.name == 'Cfdi40::DoctoRelacionado'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def traslados_summary
|
43
|
+
return @summary if defined?(@summary)
|
44
|
+
|
45
|
+
summary = {}
|
46
|
+
docto_relacionados.each do |docto|
|
47
|
+
docto.traslados_summary.each do |key, data|
|
48
|
+
summary[key] ||= {base: 0, importe: 0}
|
49
|
+
summary[key][:base] += data[:base]
|
50
|
+
summary[key][:importe] += data[:importe]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
@summary = summary
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/cfdi40/pagos.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
module Cfdi40
|
2
|
+
class Pagos < Node
|
3
|
+
define_namespace "pago20", "http://www.sat.gob.mx/Pagos20"
|
4
|
+
define_attribute :schema_location,
|
5
|
+
xml_attribute: 'xsi:schemaLocation',
|
6
|
+
readonly: true,
|
7
|
+
default: "http://www.sat.gob.mx/Pagos20 " \
|
8
|
+
"http://www.sat.gob.mx/sitio_internet/cfd/Pagos/Pagos20.xsd"
|
9
|
+
define_attribute :version, xml_attribute: 'Version', readonly: true, default: '2.0'
|
10
|
+
|
11
|
+
def add_pago(attributes={})
|
12
|
+
pago = Pago.new
|
13
|
+
pago.parent_node = self
|
14
|
+
attributes.each do |key, value|
|
15
|
+
method_name = "#{key}=".to_sym
|
16
|
+
if pago.respond_to?(method_name)
|
17
|
+
pago.public_send(method_name, value)
|
18
|
+
else
|
19
|
+
raise Error, ":#{key} no se puede asignar al nodo Pago"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
pago.monto = pago.monto.round(2)
|
23
|
+
pago.add_docto_relacionado
|
24
|
+
pago.add_impuestos_p
|
25
|
+
@children_nodes << pago
|
26
|
+
update_totales
|
27
|
+
true
|
28
|
+
end
|
29
|
+
|
30
|
+
def update_totales
|
31
|
+
update_totales_traslado_iva16
|
32
|
+
update_total_monto
|
33
|
+
end
|
34
|
+
|
35
|
+
def update_totales_traslado_iva16
|
36
|
+
key = ['002', 'Tasa', '0.160000']
|
37
|
+
return if traslados_summary[key].nil?
|
38
|
+
|
39
|
+
totales_node.base_iva16 = traslados_summary[key][:base]
|
40
|
+
totales_node.importe_iva16 = traslados_summary[key][:importe]
|
41
|
+
end
|
42
|
+
|
43
|
+
def update_total_monto
|
44
|
+
totales_node.monto_total = pago_nodes.map(&:monto).sum
|
45
|
+
end
|
46
|
+
|
47
|
+
def traslados_summary
|
48
|
+
@traslados_summary if defined?(@traslados_summary)
|
49
|
+
|
50
|
+
summary = {}
|
51
|
+
pago_nodes.each do |pago|
|
52
|
+
pago.traslados_summary.each do |key, data|
|
53
|
+
summary[key] ||= { base: 0, importe: 0 }
|
54
|
+
summary[key][:base] += data[:base]
|
55
|
+
summary[key][:importe] += data[:importe]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
@traslados_summary = summary
|
59
|
+
end
|
60
|
+
|
61
|
+
def totales_node
|
62
|
+
return @totales_node if defined?(@totales_node)
|
63
|
+
|
64
|
+
@totales_node = Totales.new
|
65
|
+
add_child_node @totales_node
|
66
|
+
@totales_node
|
67
|
+
end
|
68
|
+
|
69
|
+
def pago_nodes
|
70
|
+
@children_nodes.select { |node| node.class.name == 'Cfdi40::Pago' }
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Cfdi40
|
2
|
+
class Totales < Node
|
3
|
+
define_attribute :ret_iva, xml_attribute: 'TotalRetencionesIVA'
|
4
|
+
define_attribute :ret_isr, xml_attribute: 'TotalRetencionesISR'
|
5
|
+
define_attribute :ret_ieps, xml_attribute: 'TotalRetencionesIEPS'
|
6
|
+
define_attribute :base_iva16, xml_attribute: 'TotalTrasladosBaseIVA16'
|
7
|
+
define_attribute :importe_iva16, xml_attribute: 'TotalTrasladosImpuestoIVA16'
|
8
|
+
define_attribute :base_iva8, xml_attribute: 'TotalTrasladosBaseIVA8'
|
9
|
+
define_attribute :importe_iva8, xml_attribute: 'TotalTrasladosImpuestoIVA8'
|
10
|
+
define_attribute :base_iva0, xml_attribute: 'TotalTrasladosBaseIVA0'
|
11
|
+
define_attribute :importe_iva0, xml_attribute: 'TotalTrasladosImpuestoIVA0'
|
12
|
+
define_attribute :base_iva_excento, xml_attribute: 'TotalTrasladosBaseIVAExento'
|
13
|
+
define_attribute :monto_total, xml_attribute: 'MontoTotalPagos'
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Cfdi40
|
2
|
+
class TrasladoDR < Node
|
3
|
+
define_attribute :base_dr, xml_attribute: 'BaseDR', format: :t_ImporteMXN
|
4
|
+
define_attribute :impuesto_dr, xml_attribute: 'ImpuestoDR', default: '002'
|
5
|
+
define_attribute :tipo_factor_dr, xml_attribute: 'TipoFactorDR', default: 'Tasa'
|
6
|
+
define_attribute :tasa_o_cuota_dr, xml_attribute: 'TasaOCuotaDR', default: '0.160000', format: :t_Importe
|
7
|
+
define_attribute :importe_dr, xml_attribute: 'ImporteDR', format: :t_ImporteMXN
|
8
|
+
|
9
|
+
attr_accessor :monto_pago
|
10
|
+
|
11
|
+
def calculate!
|
12
|
+
self.base_dr = (monto_pago / (1 + tasa_o_cuota_dr.to_f)).round(2)
|
13
|
+
self.importe_dr = (monto_pago - base_dr).round(2)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module Cfdi40
|
2
|
+
class TrasladoP < Node
|
3
|
+
define_attribute :base_p, xml_attribute: 'BaseP', format: :t_ImporteMXN
|
4
|
+
define_attribute :impuesto_p, xml_attribute: 'ImpuestoP', default: '002'
|
5
|
+
define_attribute :tipo_factor_p, xml_attribute: 'TipoFactorP', default: 'Tasa'
|
6
|
+
define_attribute :tasa_o_cuota_p, xml_attribute: 'TasaOCuotaP', default: '0.160000', format: :t_Importe
|
7
|
+
define_attribute :importe_p, xml_attribute: 'ImporteP', format: :t_ImporteMXN
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Cfdi40
|
2
|
+
class TrasladosP < Node
|
3
|
+
def add_traslado_p_nodes
|
4
|
+
pago = parent_node.parent_node
|
5
|
+
pago.traslados_summary.each do |key, data|
|
6
|
+
traslado_p = TrasladoP.new
|
7
|
+
traslado_p.impuesto_p = key[0]
|
8
|
+
traslado_p.tipo_factor_p = key[1]
|
9
|
+
traslado_p.tasa_o_cuota_p = key[2]
|
10
|
+
traslado_p.base_p = data[:base]
|
11
|
+
traslado_p.importe_p = data[:importe]
|
12
|
+
add_child_node traslado_p
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/cfdi40/version.rb
CHANGED
data/lib/cfdi40.rb
CHANGED
@@ -17,6 +17,17 @@ require_relative "cfdi40/traslados"
|
|
17
17
|
require_relative "cfdi40/traslado"
|
18
18
|
require_relative "cfdi40/complemento_concepto"
|
19
19
|
require_relative "cfdi40/inst_educativas"
|
20
|
+
require_relative "cfdi40/complemento"
|
21
|
+
require_relative "cfdi40/pagos"
|
22
|
+
require_relative "cfdi40/pago"
|
23
|
+
require_relative "cfdi40/docto_relacionado"
|
24
|
+
require_relative "cfdi40/impuestos_dr"
|
25
|
+
require_relative "cfdi40/traslados_dr"
|
26
|
+
require_relative "cfdi40/traslado_dr"
|
27
|
+
require_relative "cfdi40/impuestos_p"
|
28
|
+
require_relative "cfdi40/traslados_p"
|
29
|
+
require_relative "cfdi40/traslado_p"
|
30
|
+
require_relative "cfdi40/totales.rb"
|
20
31
|
|
21
32
|
# Leading module and entry point for all features and classes
|
22
33
|
#
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cfdi40
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Israel Benítez
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-04-
|
11
|
+
date: 2023-04-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -43,19 +43,30 @@ files:
|
|
43
43
|
- Rakefile
|
44
44
|
- cfdi40.gemspec
|
45
45
|
- lib/cfdi40.rb
|
46
|
+
- lib/cfdi40/complemento.rb
|
46
47
|
- lib/cfdi40/complemento_concepto.rb
|
47
48
|
- lib/cfdi40/comprobante.rb
|
48
49
|
- lib/cfdi40/concepto.rb
|
49
50
|
- lib/cfdi40/conceptos.rb
|
51
|
+
- lib/cfdi40/docto_relacionado.rb
|
50
52
|
- lib/cfdi40/emisor.rb
|
51
53
|
- lib/cfdi40/impuestos.rb
|
54
|
+
- lib/cfdi40/impuestos_dr.rb
|
55
|
+
- lib/cfdi40/impuestos_p.rb
|
52
56
|
- lib/cfdi40/inst_educativas.rb
|
53
57
|
- lib/cfdi40/node.rb
|
58
|
+
- lib/cfdi40/pago.rb
|
59
|
+
- lib/cfdi40/pagos.rb
|
54
60
|
- lib/cfdi40/receptor.rb
|
55
61
|
- lib/cfdi40/sat_csd.rb
|
56
62
|
- lib/cfdi40/schema_validator.rb
|
63
|
+
- lib/cfdi40/totales.rb
|
57
64
|
- lib/cfdi40/traslado.rb
|
65
|
+
- lib/cfdi40/traslado_dr.rb
|
66
|
+
- lib/cfdi40/traslado_p.rb
|
58
67
|
- lib/cfdi40/traslados.rb
|
68
|
+
- lib/cfdi40/traslados_dr.rb
|
69
|
+
- lib/cfdi40/traslados_p.rb
|
59
70
|
- lib/cfdi40/version.rb
|
60
71
|
- lib/xsd/Pagos20.xsd
|
61
72
|
- lib/xsd/README.md
|