cfdi40 0.4.2 → 0.4.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6fb15d8d4d0e081acf97f51f3b7d42709a3c0f0e2dc11772a7104cad40b9ca42
4
- data.tar.gz: 7c01a9c38907d5728070828a220f3c7d4168b76658f4e5f44efcef428870b7df
3
+ metadata.gz: c5d902e16b11421579d59b2cf22aac71d40602829d952e43825c38f448689b67
4
+ data.tar.gz: 5f1a7d20d12018956c459cce25ea08701778c87a5ac5b665da7760dff72699b4
5
5
  SHA512:
6
- metadata.gz: 53d81cf68988fdaf98557009fb7b90dd24e996d6e313c5cf432ea49c7fe6f3d3cec6cb8129300508ffab6b7c0f42a081c144f0df2e0643482182074061702af7
7
- data.tar.gz: 88f608a836522680e4540744ae111957f98db192b4dcbc28f3d271fbfe9be6a1b0b30f996ba2ca49bd8dbcc732a81bfdefe42ba6a3bee3bb2729b77b29b8f891
6
+ metadata.gz: 77abcb157daa8154ec16bd2c1fc847715034f78905f44a7dd94a29c5274121d38d781bcf5ec504b7dbf0661ecd8964773260be691db742158d2eeef34b3e80fc
7
+ data.tar.gz: '0638c1cbaeb96408dac0f3822a8f198d32452d99fa6af66b8a28fc1fcd16ad95ee274221aa8b2069b40ffaf15bd23223cd0fbe0752553f63767b5ea21659e05a'
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cfdi40 (0.4.2)
4
+ cfdi40 (0.4.4)
5
5
  nokogiri (>= 1.10.10)
6
6
 
7
7
  GEM
@@ -28,6 +28,19 @@ module Cfdi40
28
28
  @pagos
29
29
  end
30
30
 
31
+ def load_pagos(pagos_node)
32
+ @pagos = Cfdi40::Pagos.new
33
+ @pagos.load_from_ng_node(pagos_node)
34
+ @pagos.parent_node = self
35
+ totales_node = pagos_node.xpath("//pago20:Totales", Cfdi40::Pagos::NG_NAMESPACE).first
36
+ @pagos.load_totales(totales_node) unless totales_node.nil?
37
+ pagos_node.xpath("//pago20:Pago", Cfdi40::Pagos::NG_NAMESPACE).each do |pago_node|
38
+ @pagos.load_pago(pago_node)
39
+ end
40
+ @children_nodes << @pagos
41
+ @pagos
42
+ end
43
+
31
44
  def timbre
32
45
  @children_nodes.select { |children| children.is_a?(Cfdi40::Timbre) }.first
33
46
  end
@@ -32,7 +32,7 @@ module Cfdi40
32
32
  define_attribute :confirmacion, xml_attribute: "Confirmacion"
33
33
 
34
34
  attr_reader :emisor, :receptor, :conceptos, :private_key, :sat_csd, :errors, :cadena_original
35
- attr_writer :key_data, :key_pass
35
+ attr_writer :key_data, :key_pass, :namespace_pagos_on_root
36
36
  attr_accessor :loaded_xml
37
37
 
38
38
  def initialize
@@ -47,6 +47,7 @@ module Cfdi40
47
47
  @sat_csd = SatCsd.new
48
48
  @fecha ||= Time.now
49
49
  @children_nodes = [@emisor, @receptor, @conceptos]
50
+ @namespace_pagos_on_root = false
50
51
  set_defaults
51
52
  end
52
53
 
@@ -214,6 +215,8 @@ module Cfdi40
214
215
  return loaded_xml if !loaded_xml.nil? && signed?
215
216
 
216
217
  sign unless signed?
218
+ return xml_string_ns_pagos_on_root if @namespace_pagos_on_root && pago_nodes.count > 0
219
+
217
220
  docxml.to_xml
218
221
  end
219
222
 
@@ -290,12 +293,24 @@ module Cfdi40
290
293
  timbre
291
294
  end
292
295
 
296
+ def load_pagos(pagos_node)
297
+ complemento.load_pagos(pagos_node)
298
+ end
299
+
293
300
  def timbre
294
301
  return nil unless defined?(@complemento)
295
302
 
296
303
  complemento.timbre
297
304
  end
298
305
 
306
+ # Some PACs require that the namespace pago20 be placed in root node
307
+ def add_namespace_pagos_to_root
308
+ self.class.define_namespace "pago20", "http://www.sat.gob.mx/Pagos20"
309
+ @schema_location += " http://www.sat.gob.mx/Pagos20 " \
310
+ "http://www.sat.gob.mx/sitio_internet/cfd/Pagos/Pagos20.xsd"
311
+ true
312
+ end
313
+
299
314
  private
300
315
 
301
316
  def add_node_concepto_actividad_pago
@@ -395,5 +410,16 @@ module Cfdi40
395
410
  @children_nodes << @complemento
396
411
  @complemento
397
412
  end
413
+
414
+ # Creates a new XML an change and puts the namespace pagos on root element.
415
+ def xml_string_ns_pagos_on_root
416
+ tmp_nkgdoc = Nokogiri::XML(docxml.to_xml)
417
+ tmp_nkgdoc.root["xmlns:pago20"] = "http://www.sat.gob.mx/Pagos20"
418
+ unless tmp_nkgdoc.root["xsi:schemaLocation"].include?("Pagos20")
419
+ tmp_nkgdoc.root["xsi:schemaLocation"] += " http://www.sat.gob.mx/Pagos20" \
420
+ " http://www.sat.gob.mx/sitio_internet/cfd/Pagos/Pagos20.xsd"
421
+ end
422
+ tmp_nkgdoc.to_xml
423
+ end
398
424
  end
399
425
  end
@@ -6,7 +6,7 @@ module Cfdi40
6
6
  define_attribute :serie, xml_attribute: "Serie"
7
7
  define_attribute :folio, xml_attribute: "Folio"
8
8
  define_attribute :moneda_dr, xml_attribute: "MonedaDR", default: "MXN"
9
- define_attribute :equivalencia_dr, xml_attribute: "EquivalenciaDR", default: "1", format: :decimal
9
+ define_attribute :equivalencia_dr, xml_attribute: "EquivalenciaDR", default: "1"
10
10
  define_attribute :num_parcialidad, xml_attribute: "NumParcialidad"
11
11
  define_attribute :imp_saldo_ant, xml_attribute: "ImpSaldoAnt", format: :t_ImporteMXN
12
12
  define_attribute :imp_pagado, xml_attribute: "ImpPagado", format: :t_ImporteMXN
@@ -64,5 +64,15 @@ module Cfdi40
64
64
  @children_nodes << @impuestos_dr
65
65
  @impuestos_dr
66
66
  end
67
+
68
+ def load_impuestos_dr(impuestos_dr_node)
69
+ @impuestos_dr = ImpuestosDR.new
70
+ @impuestos_dr.load_from_ng_node(impuestos_dr_node)
71
+ @impuestos_dr.parent_node = self
72
+ @children_nodes << @impuestos_dr
73
+ tr_dr_node = impuestos_dr_node.xpath("//pago20:TrasladosDR", Cfdi40::Pagos::NG_NAMESPACE).first
74
+ @impuestos_dr.load_traslados_dr(tr_dr_node) unless tr_dr_node.nil?
75
+ @impuestos_dr
76
+ end
67
77
  end
68
78
  end
@@ -10,5 +10,16 @@ module Cfdi40
10
10
  @children_nodes << @traslados_dr
11
11
  @traslados_dr
12
12
  end
13
+
14
+ def load_traslados_dr(traslados_dr_node)
15
+ @traslados_dr = TrasladosDR.new
16
+ @traslados_dr.load_from_ng_node(traslados_dr_node)
17
+ @traslados_dr.parent_node = self
18
+ @children_nodes << @traslados_dr
19
+ traslados_dr_node.xpath("//pago20:TrasladoDR", Cfdi40::Pagos::NG_NAMESPACE).each do |tr_dr_node|
20
+ @traslados_dr.load_traslado_dr(tr_dr_node)
21
+ end
22
+ @traslados_dr
23
+ end
13
24
  end
14
25
  end
@@ -9,5 +9,19 @@ module Cfdi40
9
9
  add_child_node @traslados_p
10
10
  @traslados_p
11
11
  end
12
+
13
+ def traslados_p_node
14
+ @children_nodes.select {|child| child.instance_of?(Cfdi40::TrasladosP) }.first
15
+ end
16
+
17
+ def load_traslados_p_node(ng_node)
18
+ @traslados_p = TrasladosP.new
19
+ @traslados_p.load_from_ng_node(ng_node)
20
+ add_child_node @traslados_p
21
+ ng_node.xpath("//pago20:TrasladoP", { "pago20" => "http://www.sat.gob.mx/Pagos20" }).each do |trsld_p_node|
22
+ @traslados_p.load_traslado_p(trsld_p_node)
23
+ end
24
+ @traslados_p
25
+ end
12
26
  end
13
27
  end
data/lib/cfdi40/node.rb CHANGED
@@ -277,7 +277,5 @@ module Cfdi40
277
277
 
278
278
  parent_node&.clean_cached_xml
279
279
  end
280
-
281
-
282
280
  end
283
281
  end
data/lib/cfdi40/pago.rb CHANGED
@@ -38,7 +38,7 @@ module Cfdi40
38
38
 
39
39
  @docto_relacionados =
40
40
  @children_nodes.select do |child|
41
- child if child.instance_of?(::Cfdi40::DoctoRelacionado)
41
+ child.instance_of?(::Cfdi40::DoctoRelacionado)
42
42
  end
43
43
  end
44
44
 
@@ -55,5 +55,28 @@ module Cfdi40
55
55
  end
56
56
  @summary = summary
57
57
  end
58
+
59
+ def load_dr(dr_node)
60
+ dr = DoctoRelacionado.new
61
+ dr.load_from_ng_node(dr_node)
62
+ dr.parent_node = self
63
+ @children_nodes << dr
64
+ imp_dr_node = dr_node.xpath("//pago20:ImpuestosDR", Cfdi40::Pagos::NG_NAMESPACE).first
65
+ dr.load_impuestos_dr(imp_dr_node) unless imp_dr_node.nil?
66
+ dr
67
+ end
68
+
69
+ def impuestos_p_node
70
+ @children_nodes.select { |child| child.instance_of?(Cfdi40::ImpuestosP) }.first
71
+ end
72
+
73
+ def load_impuestos_p(ng_node)
74
+ imp_p = ImpuestosP.new
75
+ imp_p.load_from_ng_node(ng_node)
76
+ add_child_node imp_p
77
+ trns_p_node = ng_node.xpath("//pago20:TrasladosP", { "pago20" => "http://www.sat.gob.mx/Pagos20" }).first
78
+ imp_p.load_traslados_p_node(trns_p_node)
79
+ imp_p
80
+ end
58
81
  end
59
82
  end
data/lib/cfdi40/pagos.rb CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Cfdi40
4
4
  class Pagos < Node
5
+ NG_NAMESPACE = { "pago20" => "http://www.sat.gob.mx/Pagos20" }
5
6
  define_namespace "pago20", "http://www.sat.gob.mx/Pagos20"
6
7
  define_attribute :schema_location,
7
8
  xml_attribute: "xsi:schemaLocation",
@@ -98,5 +99,25 @@ module Cfdi40
98
99
  def pago_nodes
99
100
  @children_nodes.select { |node| node.instance_of?(::Cfdi40::Pago) }
100
101
  end
102
+
103
+ def load_pago(pago_node)
104
+ pago = Pago.new
105
+ pago.load_from_ng_node(pago_node)
106
+ add_child_node pago
107
+ pago_node.xpath("//pago20:DoctoRelacionado", { "pago20" => "http://www.sat.gob.mx/Pagos20" }).each do |dr_node|
108
+ pago.load_dr(dr_node)
109
+ end
110
+ imp_p_node = pago_node.xpath("//pago20:ImpuestosP", { "pago20" => "http://www.sat.gob.mx/Pagos20" }).first
111
+ pago.load_impuestos_p(imp_p_node) if imp_p_node
112
+ pago
113
+ end
114
+
115
+ def load_totales(totales_node)
116
+ cp_totales = CpTotales.new
117
+ cp_totales.load_from_ng_node(totales_node)
118
+ cp_totales.parent_node = self
119
+ @children_nodes << cp_totales
120
+ cp_totales
121
+ end
101
122
  end
102
123
  end
@@ -2,5 +2,12 @@
2
2
 
3
3
  module Cfdi40
4
4
  class TrasladosDR < Node
5
+ def load_traslado_dr(tr_dr_node)
6
+ tr_dr = TrasladoDR.new
7
+ tr_dr.load_from_ng_node(tr_dr_node)
8
+ tr_dr.parent_node = self
9
+ @children_nodes << tr_dr
10
+ tr_dr
11
+ end
5
12
  end
6
13
  end
@@ -14,5 +14,16 @@ module Cfdi40
14
14
  add_child_node traslado_p
15
15
  end
16
16
  end
17
+
18
+ def traslado_p_nodes
19
+ @children_nodes.select { |child| child.instance_of?(Cfdi40::TrasladoP) }
20
+ end
21
+
22
+ def load_traslado_p(ng_node)
23
+ traslado_p = TrasladoP.new
24
+ traslado_p.load_from_ng_node(ng_node)
25
+ add_child_node traslado_p
26
+ traslado_p
27
+ end
17
28
  end
18
29
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Cfdi40
4
- VERSION = "0.4.2"
4
+ VERSION = "0.4.4"
5
5
  end
@@ -17,6 +17,7 @@ module Cfdi40
17
17
  load_receptor
18
18
  load_conceptos
19
19
  load_impuestos
20
+ load_pagos
20
21
  load_tfd
21
22
 
22
23
  @cfdi.lock if readonly?
@@ -71,5 +72,12 @@ module Cfdi40
71
72
 
72
73
  @cfdi.load_tfd(tfd_node)
73
74
  end
75
+
76
+ def load_pagos
77
+ pagos_node = xml_doc.xpath("//pago20:Pagos", Cfdi40::Pagos::NG_NAMESPACE).first
78
+ return if pagos_node.nil?
79
+
80
+ @cfdi.load_pagos(pagos_node)
81
+ end
74
82
  end
75
83
  end
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.4.2
4
+ version: 0.4.4
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: 2025-12-04 00:00:00.000000000 Z
11
+ date: 2025-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri