cfdi 0.0.9 → 0.1.0

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.
@@ -0,0 +1,305 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+ <html>
4
+ <head>
5
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
6
+
7
+ <link rel="stylesheet" href="css/full_list.css" type="text/css" media="screen" charset="utf-8" />
8
+
9
+ <link rel="stylesheet" href="css/common.css" type="text/css" media="screen" charset="utf-8" />
10
+
11
+
12
+
13
+ <script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
14
+
15
+ <script type="text/javascript" charset="utf-8" src="js/full_list.js"></script>
16
+
17
+
18
+ <title>Method List</title>
19
+ <base id="base_target" target="_parent" />
20
+ </head>
21
+ <body>
22
+ <script type="text/javascript" charset="utf-8">
23
+ if (window.top.frames.main) {
24
+ document.getElementById('base_target').target = 'main';
25
+ document.body.className = 'frames';
26
+ }
27
+ </script>
28
+ <div id="content">
29
+ <h1 id="full_list_header">Method List</h1>
30
+ <div id="nav">
31
+
32
+ <span><a target="_self" href="class_list.html">
33
+ Classes
34
+ </a></span>
35
+
36
+ <span><a target="_self" href="method_list.html">
37
+ Methods
38
+ </a></span>
39
+
40
+ <span><a target="_self" href="file_list.html">
41
+ Files
42
+ </a></span>
43
+
44
+ </div>
45
+ <div id="search">Search: <input type="text" /></div>
46
+
47
+ <ul id="full_list" class="method">
48
+
49
+
50
+ <li class="r1 ">
51
+ <span class='object_link'><a href="CFDI/ElementoComprobante.html#cadena_original-instance_method" title="CFDI::ElementoComprobante#cadena_original (method)">#cadena_original</a></span>
52
+ <small>CFDI::ElementoComprobante</small>
53
+ </li>
54
+
55
+
56
+ <li class="r2 ">
57
+ <span class='object_link'><a href="CFDI/Comprobante.html#cadena_original-instance_method" title="CFDI::Comprobante#cadena_original (method)">#cadena_original</a></span>
58
+ <small>CFDI::Comprobante</small>
59
+ </li>
60
+
61
+
62
+ <li class="r1 ">
63
+ <span class='object_link'><a href="CFDI/Domicilio.html#calle-instance_method" title="CFDI::Domicilio#calle (method)">#calle</a></span>
64
+ <small>CFDI::Domicilio</small>
65
+ </li>
66
+
67
+
68
+ <li class="r2 ">
69
+ <span class='object_link'><a href="CFDI/Concepto.html#cantidad%3D-instance_method" title="CFDI::Concepto#cantidad= (method)">#cantidad=</a></span>
70
+ <small>CFDI::Concepto</small>
71
+ </li>
72
+
73
+
74
+ <li class="r1 ">
75
+ <span class='object_link'><a href="CFDI/Certificado.html#certifica-instance_method" title="CFDI::Certificado#certifica (method)">#certifica</a></span>
76
+ <small>CFDI::Certificado</small>
77
+ </li>
78
+
79
+
80
+ <li class="r2 ">
81
+ <span class='object_link'><a href="CFDI/Domicilio.html#codigoPostal-instance_method" title="CFDI::Domicilio#codigoPostal (method)">#codigoPostal</a></span>
82
+ <small>CFDI::Domicilio</small>
83
+ </li>
84
+
85
+
86
+ <li class="r1 ">
87
+ <span class='object_link'><a href="CFDI/Domicilio.html#colonia-instance_method" title="CFDI::Domicilio#colonia (method)">#colonia</a></span>
88
+ <small>CFDI::Domicilio</small>
89
+ </li>
90
+
91
+
92
+ <li class="r2 ">
93
+ <span class='object_link'><a href="CFDI/Comprobante.html#complemento%3D-instance_method" title="CFDI::Comprobante#complemento= (method)">#complemento=</a></span>
94
+ <small>CFDI::Comprobante</small>
95
+ </li>
96
+
97
+
98
+ <li class="r1 ">
99
+ <span class='object_link'><a href="CFDI/Comprobante.html#conceptos%3D-instance_method" title="CFDI::Comprobante#conceptos= (method)">#conceptos=</a></span>
100
+ <small>CFDI::Comprobante</small>
101
+ </li>
102
+
103
+
104
+ <li class="r2 ">
105
+ <span class='object_link'><a href="CFDI/Comprobante.html#configure-class_method" title="CFDI::Comprobante.configure (method)">configure</a></span>
106
+ <small>CFDI::Comprobante</small>
107
+ </li>
108
+
109
+
110
+ <li class="r1 ">
111
+ <span class='object_link'><a href="CFDI/ElementoComprobante.html#data-class_method" title="CFDI::ElementoComprobante.data (method)">data</a></span>
112
+ <small>CFDI::ElementoComprobante</small>
113
+ </li>
114
+
115
+
116
+ <li class="r2 ">
117
+ <span class='object_link'><a href="CFDI/Certificado.html#data-instance_method" title="CFDI::Certificado#data (method)">#data</a></span>
118
+ <small>CFDI::Certificado</small>
119
+ </li>
120
+
121
+
122
+ <li class="r1 ">
123
+ <span class='object_link'><a href="CFDI/Entidad.html#domicilioFiscal-instance_method" title="CFDI::Entidad#domicilioFiscal (method)">#domicilioFiscal</a></span>
124
+ <small>CFDI::Entidad</small>
125
+ </li>
126
+
127
+
128
+ <li class="r2 ">
129
+ <span class='object_link'><a href="CFDI/Comprobante.html#emisor%3D-instance_method" title="CFDI::Comprobante#emisor= (method)">#emisor=</a></span>
130
+ <small>CFDI::Comprobante</small>
131
+ </li>
132
+
133
+
134
+ <li class="r1 ">
135
+ <span class='object_link'><a href="CFDI/Domicilio.html#estado-instance_method" title="CFDI::Domicilio#estado (method)">#estado</a></span>
136
+ <small>CFDI::Domicilio</small>
137
+ </li>
138
+
139
+
140
+ <li class="r2 ">
141
+ <span class='object_link'><a href="CFDI/Entidad.html#expedidoEn-instance_method" title="CFDI::Entidad#expedidoEn (method)">#expedidoEn</a></span>
142
+ <small>CFDI::Entidad</small>
143
+ </li>
144
+
145
+
146
+ <li class="r1 ">
147
+ <span class='object_link'><a href="CFDI/Comprobante.html#fecha%3D-instance_method" title="CFDI::Comprobante#fecha= (method)">#fecha=</a></span>
148
+ <small>CFDI::Comprobante</small>
149
+ </li>
150
+
151
+
152
+ <li class="r2 ">
153
+ <span class='object_link'><a href="CFDI.html#from_xml-class_method" title="CFDI.from_xml (method)">from_xml</a></span>
154
+ <small>CFDI</small>
155
+ </li>
156
+
157
+
158
+ <li class="r1 ">
159
+ <span class='object_link'><a href="CFDI/Concepto.html#importe-instance_method" title="CFDI::Concepto#importe (method)">#importe</a></span>
160
+ <small>CFDI::Concepto</small>
161
+ </li>
162
+
163
+
164
+ <li class="r2 ">
165
+ <span class='object_link'><a href="CFDI/Comprobante.html#initialize-instance_method" title="CFDI::Comprobante#initialize (method)">#initialize</a></span>
166
+ <small>CFDI::Comprobante</small>
167
+ </li>
168
+
169
+
170
+ <li class="r1 ">
171
+ <span class='object_link'><a href="CFDI/Key.html#initialize-instance_method" title="CFDI::Key#initialize (method)">#initialize</a></span>
172
+ <small>CFDI::Key</small>
173
+ </li>
174
+
175
+
176
+ <li class="r2 ">
177
+ <span class='object_link'><a href="CFDI/ElementoComprobante.html#initialize-instance_method" title="CFDI::ElementoComprobante#initialize (method)">#initialize</a></span>
178
+ <small>CFDI::ElementoComprobante</small>
179
+ </li>
180
+
181
+
182
+ <li class="r1 ">
183
+ <span class='object_link'><a href="CFDI/Certificado.html#initialize-instance_method" title="CFDI::Certificado#initialize (method)">#initialize</a></span>
184
+ <small>CFDI::Certificado</small>
185
+ </li>
186
+
187
+
188
+ <li class="r2 ">
189
+ <span class='object_link'><a href="CFDI/Domicilio.html#localidad-instance_method" title="CFDI::Domicilio#localidad (method)">#localidad</a></span>
190
+ <small>CFDI::Domicilio</small>
191
+ </li>
192
+
193
+
194
+ <li class="r1 ">
195
+ <span class='object_link'><a href="CFDI/Domicilio.html#municipio-instance_method" title="CFDI::Domicilio#municipio (method)">#municipio</a></span>
196
+ <small>CFDI::Domicilio</small>
197
+ </li>
198
+
199
+
200
+ <li class="r2 ">
201
+ <span class='object_link'><a href="CFDI/Certificado.html#noCertificado-instance_method" title="CFDI::Certificado#noCertificado (method)">#noCertificado</a></span>
202
+ <small>CFDI::Certificado</small>
203
+ </li>
204
+
205
+
206
+ <li class="r1 ">
207
+ <span class='object_link'><a href="CFDI/Domicilio.html#noExterior-instance_method" title="CFDI::Domicilio#noExterior (method)">#noExterior</a></span>
208
+ <small>CFDI::Domicilio</small>
209
+ </li>
210
+
211
+
212
+ <li class="r2 ">
213
+ <span class='object_link'><a href="CFDI/Domicilio.html#noInterior-instance_method" title="CFDI::Domicilio#noInterior (method)">#noInterior</a></span>
214
+ <small>CFDI::Domicilio</small>
215
+ </li>
216
+
217
+
218
+ <li class="r1 ">
219
+ <span class='object_link'><a href="CFDI/Entidad.html#nombre-instance_method" title="CFDI::Entidad#nombre (method)">#nombre</a></span>
220
+ <small>CFDI::Entidad</small>
221
+ </li>
222
+
223
+
224
+ <li class="r2 ">
225
+ <span class='object_link'><a href="CFDI/Domicilio.html#pais-instance_method" title="CFDI::Domicilio#pais (method)">#pais</a></span>
226
+ <small>CFDI::Domicilio</small>
227
+ </li>
228
+
229
+
230
+ <li class="r1 ">
231
+ <span class='object_link'><a href="CFDI/Comprobante.html#receptor%3D-instance_method" title="CFDI::Comprobante#receptor= (method)">#receptor=</a></span>
232
+ <small>CFDI::Comprobante</small>
233
+ </li>
234
+
235
+
236
+ <li class="r2 ">
237
+ <span class='object_link'><a href="CFDI/Domicilio.html#referencia-instance_method" title="CFDI::Domicilio#referencia (method)">#referencia</a></span>
238
+ <small>CFDI::Domicilio</small>
239
+ </li>
240
+
241
+
242
+ <li class="r1 ">
243
+ <span class='object_link'><a href="CFDI/Entidad.html#regimenFiscal-instance_method" title="CFDI::Entidad#regimenFiscal (method)">#regimenFiscal</a></span>
244
+ <small>CFDI::Entidad</small>
245
+ </li>
246
+
247
+
248
+ <li class="r2 ">
249
+ <span class='object_link'><a href="CFDI/Entidad.html#rfc-instance_method" title="CFDI::Entidad#rfc (method)">#rfc</a></span>
250
+ <small>CFDI::Entidad</small>
251
+ </li>
252
+
253
+
254
+ <li class="r1 ">
255
+ <span class='object_link'><a href="CFDI/Key.html#sella-instance_method" title="CFDI::Key#sella (method)">#sella</a></span>
256
+ <small>CFDI::Key</small>
257
+ </li>
258
+
259
+
260
+ <li class="r2 ">
261
+ <span class='object_link'><a href="CFDI/Comprobante.html#subTotal-instance_method" title="CFDI::Comprobante#subTotal (method)">#subTotal</a></span>
262
+ <small>CFDI::Comprobante</small>
263
+ </li>
264
+
265
+
266
+ <li class="r1 ">
267
+ <span class='object_link'><a href="CFDI/Comprobante.html#to_h-instance_method" title="CFDI::Comprobante#to_h (method)">#to_h</a></span>
268
+ <small>CFDI::Comprobante</small>
269
+ </li>
270
+
271
+
272
+ <li class="r2 ">
273
+ <span class='object_link'><a href="CFDI/ElementoComprobante.html#to_h-instance_method" title="CFDI::ElementoComprobante#to_h (method)">#to_h</a></span>
274
+ <small>CFDI::ElementoComprobante</small>
275
+ </li>
276
+
277
+
278
+ <li class="r1 ">
279
+ <span class='object_link'><a href="Float.html#to_s-instance_method" title="Float#to_s (method)">#to_s</a></span>
280
+ <small>Float</small>
281
+ </li>
282
+
283
+
284
+ <li class="r2 ">
285
+ <span class='object_link'><a href="CFDI/Comprobante.html#to_xml-instance_method" title="CFDI::Comprobante#to_xml (method)">#to_xml</a></span>
286
+ <small>CFDI::Comprobante</small>
287
+ </li>
288
+
289
+
290
+ <li class="r1 ">
291
+ <span class='object_link'><a href="CFDI/Comprobante.html#total-instance_method" title="CFDI::Comprobante#total (method)">#total</a></span>
292
+ <small>CFDI::Comprobante</small>
293
+ </li>
294
+
295
+
296
+ <li class="r2 ">
297
+ <span class='object_link'><a href="CFDI/Concepto.html#valorUnitario%3D-instance_method" title="CFDI::Concepto#valorUnitario= (method)">#valorUnitario=</a></span>
298
+ <small>CFDI::Concepto</small>
299
+ </li>
300
+
301
+
302
+ </ul>
303
+ </div>
304
+ </body>
305
+ </html>
@@ -0,0 +1,114 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4
+ <head>
5
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
6
+ <title>
7
+ Top Level Namespace
8
+
9
+ &mdash; Documentation by YARD 0.8.7.2
10
+
11
+ </title>
12
+
13
+ <link rel="stylesheet" href="css/style.css" type="text/css" charset="utf-8" />
14
+
15
+ <link rel="stylesheet" href="css/common.css" type="text/css" charset="utf-8" />
16
+
17
+ <script type="text/javascript" charset="utf-8">
18
+ hasFrames = window.top.frames.main ? true : false;
19
+ relpath = '';
20
+ framesUrl = "frames.html#!" + escape(window.location.href);
21
+ </script>
22
+
23
+
24
+ <script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
25
+
26
+ <script type="text/javascript" charset="utf-8" src="js/app.js"></script>
27
+
28
+
29
+ </head>
30
+ <body>
31
+ <div id="header">
32
+ <div id="menu">
33
+
34
+ <a href="_index.html">Index</a> &raquo;
35
+
36
+
37
+ <span class="title">Top Level Namespace</span>
38
+
39
+
40
+ <div class="noframes"><span class="title">(</span><a href="." target="_top">no frames</a><span class="title">)</span></div>
41
+ </div>
42
+
43
+ <div id="search">
44
+
45
+ <a class="full_list_link" id="class_list_link"
46
+ href="class_list.html">
47
+ Class List
48
+ </a>
49
+
50
+ <a class="full_list_link" id="method_list_link"
51
+ href="method_list.html">
52
+ Method List
53
+ </a>
54
+
55
+ <a class="full_list_link" id="file_list_link"
56
+ href="file_list.html">
57
+ File List
58
+ </a>
59
+
60
+ </div>
61
+ <div class="clear"></div>
62
+ </div>
63
+
64
+ <iframe id="search_frame"></iframe>
65
+
66
+ <div id="content"><h1>Top Level Namespace
67
+
68
+
69
+
70
+ </h1>
71
+
72
+ <dl class="box">
73
+
74
+
75
+
76
+
77
+
78
+
79
+
80
+
81
+ </dl>
82
+ <div class="clear"></div>
83
+
84
+ <h2>Defined Under Namespace</h2>
85
+ <p class="children">
86
+
87
+
88
+ <strong class="modules">Modules:</strong> <span class='object_link'><a href="CFDI.html" title="CFDI (module)">CFDI</a></span>
89
+
90
+
91
+
92
+ <strong class="classes">Classes:</strong> <span class='object_link'><a href="Float.html" title="Float (class)">Float</a></span>
93
+
94
+
95
+ </p>
96
+
97
+
98
+
99
+
100
+
101
+
102
+
103
+
104
+
105
+ </div>
106
+
107
+ <div id="footer">
108
+ Generated on Wed Oct 30 20:47:07 2013 by
109
+ <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
110
+ 0.8.7.2 (ruby-2.0.0).
111
+ </div>
112
+
113
+ </body>
114
+ </html>
data/lib/certificado.rb CHANGED
@@ -2,10 +2,20 @@ module CFDI
2
2
 
3
3
  require 'openssl'
4
4
 
5
+ # Certificados en formato X590
6
+ #
7
+ # En español, el archivo `.cer`
5
8
  class Certificado < OpenSSL::X509::Certificate
6
9
 
7
- attr_reader :noCertificado, :data
8
-
10
+ # el número de certificado
11
+ attr_reader :noCertificado
12
+ # el certificado en Base64
13
+ attr_reader :data
14
+
15
+ # Importar un certificado de sellado
16
+ # @param file [IO, String] El `path` del certificado o un objeto #IO
17
+ #
18
+ # @return [CFDI::Certificado] Un certificado
9
19
  def initialize (file)
10
20
 
11
21
  if file.is_a? String
@@ -23,6 +33,11 @@ module CFDI
23
33
 
24
34
  end
25
35
 
36
+
37
+ # Certifica una factura
38
+ # @param factura [CFDI::Comprobante] El comprobante a certificar
39
+ #
40
+ # @return [CFDI::Comprobante] El comprobante certificado (con `#noCertificado` y `#certificado`)
26
41
  def certifica factura
27
42
 
28
43
  factura.noCertificado = @noCertificado
data/lib/cfdi.rb CHANGED
@@ -10,12 +10,16 @@ require_relative 'xml.rb'
10
10
  require_relative 'certificado.rb'
11
11
  require_relative 'key.rb'
12
12
 
13
+ # Comprobantes fiscales digitales por los internets
14
+ #
15
+ # El sistema de generación y sellado de facturas es una patada en los genitales. Este gem pretende ser una bolsa de hielos. Igual va a doler, pero espero que al menos no quede moretón.
13
16
  module CFDI
14
17
 
15
18
  require 'nokogiri'
16
19
  require 'time'
17
20
  require 'base64'
18
21
 
19
- VERSION = '0.0.9'
22
+ # La versión de este gem
23
+ VERSION = '0.1.0'
20
24
 
21
25
  end
data/lib/complemento.rb CHANGED
@@ -1,7 +1,9 @@
1
1
  module CFDI
2
2
 
3
+ # Un complemento fiscal, o Timbre
3
4
  class Complemento < ElementoComprobante
4
5
 
6
+ # los datos del timbre
5
7
  @cadenaOriginal = [:UUID, :FechaTimbrado, :selloCFD, :noCertificadoSAT, :selloSAT, :version]
6
8
  attr_accessor *@cadenaOriginal
7
9
 
data/lib/comprobante.rb CHANGED
@@ -1,7 +1,12 @@
1
1
  module CFDI
2
+ # La clase principal para crear Comprobantes
2
3
  class Comprobante
3
4
 
5
+ # los datos para la cadena original en el órden correcto
6
+ # @private
4
7
  @@datosCadena = [:version, :fecha, :tipoDeComprobante, :formaDePago, :condicionesDePago, :subTotal, :TipoCambio, :moneda, :total, :metodoDePago, :lugarExpedicion, :NumCtaPago]
8
+ # Todos los datos del comprobante
9
+ # @private
5
10
  @@data = @@datosCadena+[:emisor, :receptor, :conceptos, :serie, :folio, :sello, :noCertificado, :certificado, :conceptos, :complemento, :cancelada, :impuestos]
6
11
  attr_accessor *@@data
7
12
 
@@ -18,10 +23,37 @@ module CFDI
18
23
  }
19
24
  }
20
25
 
21
- def configure (options)
22
- @@options.merge! options
26
+ # Configurar las opciones default de los comprobantes
27
+ #
28
+ # == Parameters:
29
+ # options::
30
+ # Las opciones del comprobante: tasa (de impuestos), defaults: un Hash con la moneda (pesos), version (3.2), TipoCambio (1), y tipoDeComprobante (ingreso)
31
+ #
32
+ # @return [Hash]
33
+ #
34
+ def self.configure (options)
35
+ @@options = Comprobante.rmerge @@options, options
36
+ @@options
23
37
  end
24
38
 
39
+ # Crear un comprobante nuevo
40
+ #
41
+ # @param data [Hash] Los datos de un comprobante
42
+ # @option data [String] :version ('3.2') La version del CFDI
43
+ # @option data [String] :fecha ('') La fecha del CFDI
44
+ # @option data [String] :tipoDeComprobante ('ingreso') El tipo de Comprobante
45
+ # @option data [String] :formaDePago ('') La forma de pago (pago en una sóla exhibición?)
46
+ # @option data [String] :condicionesDePago ('') Las condiciones de pago (Efectos fiscales al pago?)
47
+ # @option data [String] :TipoCambio (1) El tipo de cambio para la moneda de este CFDI'
48
+ # @option data [String] :moneda ('pesos') La moneda de pago
49
+ # @option data [String] :metodoDePago ('') El método de pago (depósito bancario? efectivo?)
50
+ # @option data [String] :lugarExpedicion ('') El lugar dónde se expide la factura (Nutopía, México?)
51
+ # @option data [String] :NumCtaPago (nil) El número de cuenta para el pago
52
+ #
53
+ # @param options [Hash] Las opciones para este comprobante
54
+ # @see [Comprobante@@options] Opciones
55
+ #
56
+ # @return {CFDI::Comprobante}
25
57
  def initialize (data={}, options={})
26
58
  #hack porque dup se caga con instance variables
27
59
  opts = Marshal::load(Marshal.dump(@@options))
@@ -34,6 +66,10 @@ module CFDI
34
66
  end
35
67
  end
36
68
 
69
+
70
+ # Regresa el subtotal de este comprobante, tomando el importe de cada concepto
71
+ #
72
+ # @return [Float] El subtotal del comprobante
37
73
  def subTotal
38
74
  ret = 0
39
75
  @conceptos.each do |c|
@@ -42,44 +78,81 @@ module CFDI
42
78
  ret
43
79
  end
44
80
 
81
+
82
+ # Regresa el total
83
+ #
84
+ # @return [Float] El subtotal multiplicado por la tasa
45
85
  def total
46
86
  self.subTotal+(self.subTotal*@opciones[:tasa])
47
87
  end
48
88
 
89
+
90
+ # Asigna un emisor de tipo {CFDI::Entidad}
91
+ # @param emisor [Hash, CFDI::Entidad] Los datos de un emisor
92
+ #
93
+ # @return [CFDI::Entidad] Una entidad
49
94
  def emisor= emisor
50
95
  emisor = Entidad.new emisor unless emisor.is_a? Entidad
51
96
  @emisor = emisor;
52
97
  end
53
98
 
99
+
100
+ # Asigna un receptor
101
+ # @param receptor [Hash, CFDI::Entidad] Los datos de un receptor
102
+ #
103
+ # @return [CFDI::Entidad] Una entidad
54
104
  def receptor= receptor
55
105
  receptor = Entidad.new receptor unless receptor.is_a? Entidad
56
106
  @receptor = receptor;
107
+ receptor
57
108
  end
58
109
 
110
+ # Agrega uno o varios conceptos
111
+ # @param conceptos [Array, Hash, CFDI::Concepto] Uno o varios conceptos
112
+ #
113
+ # En caso de darle un Hash o un {CFDI::Concepto}, agrega este a los conceptos, de otro modo, sobreescribe los conceptos pre-existentes
114
+ #
115
+ # @return [Array] Los conceptos de este comprobante
59
116
  def conceptos= conceptos
60
117
  if conceptos.is_a? Array
61
118
  conceptos.map! do |concepto|
62
119
  concepto = Concepto.new concepto unless concepto.is_a? Concepto
63
120
  end
64
121
  elsif conceptos.is_a? Hash
65
- conceptos = [Concepto.new(concepto)]
122
+ conceptos << Concepto.new(concepto)
66
123
  elsif conceptos.is_a? Concepto
67
- conceptos = [conceptos]
124
+ conceptos << conceptos
68
125
  end
69
126
 
70
127
  @conceptos = conceptos
128
+ conceptos
71
129
  end
72
130
 
131
+
132
+ # Asigna un complemento al comprobante
133
+ # @param complemento [Hash, CFDI::Complemento] El complemento a agregar
134
+ #
135
+ # @return [CFDI::Complemento]
73
136
  def complemento= complemento
74
137
  complemento = Complemento.new complemento unless complemento.is_a? Complemento
75
138
  @complemento = complemento
139
+ complemento
76
140
  end
77
141
 
142
+
143
+ # Asigna una fecha al comprobante
144
+ # @param fecha [Time, String] La fecha y hora (YYYY-MM-DDTHH:mm:SS) de la emisión
145
+ #
146
+ # @return [String] la fecha en formato '%FT%R:%S'
78
147
  def fecha= fecha
79
148
  fecha = fecha.strftime('%FT%R:%S') unless fecha.is_a? String
80
149
  @fecha = fecha
81
150
  end
82
-
151
+
152
+
153
+ # El comprobante como XML
154
+ #
155
+ # @return [String] El comprobante namespaceado en versión 3.2 (porque soy un huevón)
83
156
  def to_xml
84
157
  ns = {
85
158
  'xmlns:cfdi' => "http://www.sat.gob.mx/cfd/3",
@@ -155,7 +228,11 @@ module CFDI
155
228
  end
156
229
  @builder.to_xml
157
230
  end
158
-
231
+
232
+
233
+ # Un hash con todos los datos del comprobante, listo para Hash.to_json
234
+ #
235
+ # @return [Hash] El comprobante como Hash
159
236
  def to_h
160
237
  hash = {}
161
238
  @@data.each do |key|
@@ -166,6 +243,10 @@ module CFDI
166
243
  return hash
167
244
  end
168
245
 
246
+
247
+ # La cadena original del CFDI
248
+ #
249
+ # @return [String] Separada por pipes, because fuck you that's why
169
250
  def cadena_original
170
251
  params = []
171
252
 
@@ -195,6 +276,16 @@ module CFDI
195
276
  return "||#{params.join '|'}||"
196
277
  end
197
278
 
279
+ # @private
280
+ def self.rmerge defaults, other_hash
281
+ result = defaults.merge(other_hash) do |key, oldval, newval|
282
+ oldval = oldval.to_hash if oldval.respond_to?(:to_hash)
283
+ newval = newval.to_hash if newval.respond_to?(:to_hash)
284
+ oldval.class.to_s == 'Hash' && newval.class.to_s == 'Hash' ? Comprobante.rmerge(oldval, newval) : newval
285
+ end
286
+ result
287
+ end
288
+
198
289
  private
199
290
  def deep_to_h value
200
291