cfdi 0.1.5 → 0.1.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/Rakefile +8 -1
- data/examples/crear_factura.rb +12 -2
- data/examples/data/cfdi.xml +1 -1
- data/lib/addenda.rb +19 -0
- data/lib/cfdi.rb +2 -1
- data/lib/comprobante.rb +29 -0
- data/lib/comun.rb +20 -0
- data/lib/concepto.rb +1 -1
- data/test/comprobante_spec.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fdf6b9c68a005bb346923cad06e85e4d1209cb1b
|
4
|
+
data.tar.gz: 5eb74e5667ffe85d3a841207505766d051757476
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 53beb4378b46f8e5ec4e40517567022314880bea300633417a6cfb98c72bdb74e1235e3a04bf9e0197cc17d63b8f299a455723a5156b553664e03f6732c83166
|
7
|
+
data.tar.gz: 7626c0293517f697833398bd07e644f621a80f8914e9e6f3ad775a9602440d11e0b67944147b77cedd67f1e19a030d5da7dc9e15235c3d210f2ff298d87524b4
|
data/Rakefile
CHANGED
data/examples/crear_factura.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require_relative 'cfdi'
|
1
|
+
require_relative '../lib/cfdi'
|
2
2
|
require 'json'
|
3
3
|
require 'time'
|
4
4
|
|
@@ -10,7 +10,7 @@ certificado = CFDI::Certificado.new './data/cert.cer'
|
|
10
10
|
llave = CFDI::Key.new './data/key.pem', 'somePassword'
|
11
11
|
|
12
12
|
# Así instanciamos el comprobante nuevo
|
13
|
-
factura = CFDI::Comprobante.new
|
13
|
+
factura = CFDI::Comprobante.new({
|
14
14
|
folio: 1,
|
15
15
|
serie: 'A',
|
16
16
|
fecha: Time.now,
|
@@ -64,6 +64,16 @@ factura.conceptos << CFDI::Concepto.new({
|
|
64
64
|
# Todavía no agarro bien el pedo sobre como salen los impuestos, pull request?
|
65
65
|
factura.impuestos << {impuesto: 'IVA'}
|
66
66
|
|
67
|
+
factura.addenda= {
|
68
|
+
nombre: 'poo',
|
69
|
+
namespace: 'http://surrealista.mx/xsd/poo',
|
70
|
+
xsd: 'http://surrealista.mx/xsd/poo/poo.xsd',
|
71
|
+
data: {
|
72
|
+
caca: 'popo',
|
73
|
+
pipi: 'pedos'
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
67
77
|
# Esto hace que se le agregue al comprobante el certificado y su número de serie (noCertificado)
|
68
78
|
certificado.certifica factura
|
69
79
|
|
data/examples/data/cfdi.xml
CHANGED
@@ -9,7 +9,7 @@
|
|
9
9
|
<cfdi:Domicilio referencia="Sin Referencia" estado="Nutopía" pais="Nutopía"/>
|
10
10
|
</cfdi:Receptor>
|
11
11
|
<cfdi:Conceptos>
|
12
|
-
<cfdi:Concepto cantidad="2" unidad="Kilos" noIdentificacion="KDV" descripcion="Verga" valorUnitario="5500.00" importe="11000.00">
|
12
|
+
<cfdi:Concepto cantidad="2" unidad="Kilos" noIdentificacion="KDV" descripcion="Verga Ción" valorUnitario="5500.00" importe="11000.00">
|
13
13
|
<cfdi:ComplementoConcepto/>
|
14
14
|
</cfdi:Concepto>
|
15
15
|
</cfdi:Conceptos>
|
data/lib/addenda.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
module CFDI
|
2
|
+
|
3
|
+
# Un concepto del comprobante
|
4
|
+
class Addenda
|
5
|
+
|
6
|
+
attr_accessor *[:nombre, :namespace, :xsd, :data]
|
7
|
+
|
8
|
+
def initialize data={}
|
9
|
+
#puts self.class
|
10
|
+
data.each do |k,v|
|
11
|
+
method = "#{k}=".to_sym
|
12
|
+
next if !self.respond_to? method
|
13
|
+
self.send method, v
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end #Addenda
|
18
|
+
|
19
|
+
end #CFDI
|
data/lib/cfdi.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
gem 'nokogiri', '< 1.6', '>= 1.4.0'
|
3
3
|
|
4
4
|
require_relative 'comun.rb'
|
5
|
+
require_relative 'addenda.rb'
|
5
6
|
require_relative 'comprobante.rb'
|
6
7
|
require_relative 'entidad.rb'
|
7
8
|
require_relative 'concepto.rb'
|
@@ -20,6 +21,6 @@ module CFDI
|
|
20
21
|
require 'base64'
|
21
22
|
|
22
23
|
# La versión de este gem
|
23
|
-
VERSION = '0.1.
|
24
|
+
VERSION = '0.1.6'
|
24
25
|
|
25
26
|
end
|
data/lib/comprobante.rb
CHANGED
@@ -9,6 +9,8 @@ module CFDI
|
|
9
9
|
# @private
|
10
10
|
@@data = @@datosCadena+[:emisor, :receptor, :conceptos, :serie, :folio, :sello, :noCertificado, :certificado, :conceptos, :complemento, :cancelada, :impuestos]
|
11
11
|
attr_accessor *@@data
|
12
|
+
|
13
|
+
@addenda = nil
|
12
14
|
|
13
15
|
@@options = {
|
14
16
|
tasa: 0.16,
|
@@ -66,6 +68,12 @@ module CFDI
|
|
66
68
|
end
|
67
69
|
end
|
68
70
|
|
71
|
+
|
72
|
+
def addenda= addenda
|
73
|
+
addenda = Addenda.new addenda unless addenda.is_a? Addenda
|
74
|
+
@addenda = addenda
|
75
|
+
end
|
76
|
+
|
69
77
|
|
70
78
|
# Regresa el subtotal de este comprobante, tomando el importe de cada concepto
|
71
79
|
#
|
@@ -174,6 +182,12 @@ module CFDI
|
|
174
182
|
ns[:TipoCambio] = @TipoCambio if @TipoCambio
|
175
183
|
ns[:NumCtaPago] = @NumCtaPago if @NumCtaPago && @NumCtaPago!=''
|
176
184
|
|
185
|
+
if (@addenda)
|
186
|
+
# Si tenemos addenda, entonces creamos el campo "xmlns:ElNombre" y agregamos sus definiciones al SchemaLocation
|
187
|
+
ns["xmlns:#{@addenda.nombre}"] = @addenda.namespace
|
188
|
+
ns['xsi:schemaLocation'] += ' '+[@addenda.namespace, @addenda.xsd].join(' ')
|
189
|
+
end
|
190
|
+
|
177
191
|
if @noCertificado
|
178
192
|
ns[:noCertificado] = @noCertificado
|
179
193
|
ns[:certificado] = @certificado
|
@@ -224,6 +238,21 @@ module CFDI
|
|
224
238
|
|
225
239
|
end
|
226
240
|
}
|
241
|
+
|
242
|
+
if (@addenda)
|
243
|
+
xml.Addenda {
|
244
|
+
@addenda.data.each do |k,v|
|
245
|
+
if v.is_a? Hash
|
246
|
+
xml[@addenda.nombre].send(k, v)
|
247
|
+
elsif v.is_a? Array
|
248
|
+
xml[@addenda.nombre].send(k, v)
|
249
|
+
else
|
250
|
+
xml[@addenda.nombre].send(k, v)
|
251
|
+
end
|
252
|
+
end
|
253
|
+
}
|
254
|
+
end
|
255
|
+
|
227
256
|
end
|
228
257
|
end
|
229
258
|
@builder.to_xml
|
data/lib/comun.rb
CHANGED
@@ -8,6 +8,26 @@ class Float
|
|
8
8
|
sprintf('%.2f', self)
|
9
9
|
end
|
10
10
|
|
11
|
+
end
|
12
|
+
# Y quiero que los strings no tengan espacios extraños
|
13
|
+
class String
|
14
|
+
|
15
|
+
# Limpia whitespace de extremos y espacios repetidos
|
16
|
+
#
|
17
|
+
# @return [String] Una copia del string sin espacios extraños
|
18
|
+
def squish
|
19
|
+
dup.squish!
|
20
|
+
end
|
21
|
+
|
22
|
+
# Lo mismo que squish, pero destructivo
|
23
|
+
#
|
24
|
+
# @return [String] El string original sin espacios extraños
|
25
|
+
def squish!
|
26
|
+
strip!
|
27
|
+
gsub!(/\s(\s+)/, ' ')
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
11
31
|
end
|
12
32
|
|
13
33
|
module CFDI
|
data/lib/concepto.rb
CHANGED
data/test/comprobante_spec.rb
CHANGED
@@ -40,7 +40,7 @@ describe CFDI::Comprobante do
|
|
40
40
|
|
41
41
|
it "debe de generar un comprobante desde XML" do
|
42
42
|
comprobante = CFDI.from_xml(File.read('./examples/data/cfdi.xml'))
|
43
|
-
returns = {:version=>"3.2", :fecha=>"2013-10-15T01:33:32", :tipoDeComprobante=>"ingreso", :formaDePago=>"PAGO EN UNA SOLA EXHIBICION", :condicionesDePago=>"Sera marcada como pagada en cuanto el receptor haya cubierto el pago.", :subTotal=>11000.0, :TipoCambio=>1, :moneda=>"pesos", :total=>12760.0, :metodoDePago=>"Transferencia Bancaria", :lugarExpedicion=>"Nutopia, Nutopia", :NumCtaPago=>nil, :emisor=>{:rfc=>"XAXX010101000", :nombre=>"Me cago en sus estándares S.A. de C.V.", :domicilioFiscal=>{:calle=>"Calle Feliz", :noExterior=>"42", :noInterior=>"314", :colonia=>"Centro", :localidad=>"No se que sea esto, pero va", :referencia=>"Sin Referencia", :municipio=>"Nutopía", :estado=>"Nutopía", :pais=>"Nutopía", :codigoPostal=>"31415"}, :expedidoEn=>{:calle=>"Calle Feliz", :noExterior=>"42", :noInterior=>nil, :colonia=>"Centro", :localidad=>"No se que sea esto, pero va", :referencia=>"Sin Referencia", :municipio=>"Nutopía", :estado=>"Nutopía", :pais=>"Nutopía", :codigoPostal=>"31415"}, :regimenFiscal=>"Pruebas Fiscales"}, :receptor=>{:rfc=>"XAXX010101000", :nombre=>"El SAT apesta S. de R.L.", :domicilioFiscal=>{:calle=>nil, :noExterior=>nil, :noInterior=>nil, :colonia=>nil, :localidad=>nil, :referencia=>"Sin Referencia", :municipio=>nil, :estado=>"Nutopía", :pais=>"Nutopía", :codigoPostal=>nil}, :expedidoEn=>nil, :regimenFiscal=>nil}, :conceptos=>[{:cantidad=>2, :unidad=>"Kilos", :noIdentificacion=>"KDV", :descripcion=>"Verga", :valorUnitario=>5500.0, :importe=>11000.0}], :serie=>nil, :folio=>"1", :sello=>"igFu7Q9Z98n6xFSLMv7a2y8ZlJCO+pgTX3xDAUt5xSpX3dHOKXkTHBAf4P/oHHDm3xkYkaNBfPEzpVFDrRVjL2rvkR5T9rsFqb4cl6DOo4RrRIpSR9vojLp7mFWiON9H6OFPi2b9PVAnyIx1Skb5iGIAmSQIhVYyt2DSauObY2c=", :noCertificado=>"20001000000200000293", :certificado=>"MIIE2jCCA8KgAwIBAgIUMjAwMDEwMDAwMDAyMDAwMDAyOTMwDQYJKoZIhvcNAQEFBQAwggFcMRowGAYDVQQDDBFBLkMuIDIgZGUgcHJ1ZWJhczEvMC0GA1UECgwmU2VydmljaW8gZGUgQWRtaW5pc3RyYWNpw7NuIFRyaWJ1dGFyaWExODA2BgNVBAsML0FkbWluaXN0cmFjacOzbiBkZSBTZWd1cmlkYWQgZGUgbGEgSW5mb3JtYWNpw7NuMSkwJwYJKoZIhvcNAQkBFhphc2lzbmV0QHBydWViYXMuc2F0LmdvYi5teDEmMCQGA1UECQwdQXYuIEhpZGFsZ28gNzcsIENvbC4gR3VlcnJlcm8xDjAMBgNVBBEMBTA2MzAwMQswCQYDVQQGEwJNWDEZMBcGA1UECAwQRGlzdHJpdG8gRmVkZXJhbDESMBAGA1UEBwwJQ295b2Fjw6FuMTQwMgYJKoZIhvcNAQkCDCVSZXNwb25zYWJsZTogQXJhY2VsaSBHYW5kYXJhIEJhdXRpc3RhMB4XDTEyMTAyNjE5MjI0M1oXDTE2MTAyNjE5MjI0M1owggFTMUkwRwYDVQQDE0BBU09DSUFDSU9OIERFIEFHUklDVUxUT1JFUyBERUwgRElTVFJJVE8gREUgUklFR08gMDA0IERPTiBNQVJUSU4gMWEwXwYDVQQpE1hBU09DSUFDSU9OIERFIEFHUklDVUxUT1JFUyBERUwgRElTVFJJVE8gREUgUklFR08gMDA0IERPTiBNQVJUSU4gQ09BSFVJTEEgWSBOVUVWTyBMRU9OIEFDMUkwRwYDVQQKE0BBU09DSUFDSU9OIERFIEFHUklDVUxUT1JFUyBERUwgRElTVFJJVE8gREUgUklFR08gMDA0IERPTiBNQVJUSU4gMSUwIwYDVQQtExxBQUQ5OTA4MTRCUDcgLyBIRUdUNzYxMDAzNFMyMR4wHAYDVQQFExUgLyBIRUdUNzYxMDAzTURGUk5OMDkxETAPBgNVBAsTCFNlcnZpZG9yMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDlrI9loozd+UcW7YHtqJimQjzX9wHIUcc1KZyBBB8/5fZsgZ/smWS4Sd6HnPs9GSTtnTmM4bEgx28N3ulUshaaBEtZo3tsjwkBV/yVQ3SRyMDkqBA2NEjbcum+e/MdCMHiPI1eSGHEpdESt55a0S6N24PW732Xm3ZbGgOp1tht1wIDAQABox0wGzAMBgNVHRMBAf8EAjAAMAsGA1UdDwQEAwIGwDANBgkqhkiG9w0BAQUFAAOCAQEAuoPXe+BBIrmJn+IGeI+m97OlP3RC4Ct3amjGmZICbvhI9BTBLCL/PzQjjWBwU0MG8uK6e/gcB9f+klPiXhQTeI1YKzFtWrzctpNEJYo0KXMgvDiputKphQ324dP0nzkKUfXlRIzScJJCSgRw9ZifKWN0D9qTdkNkjk83ToPgwnldg5lzU62woXo4AKbcuabAYOVoC7owM5bfNuWJe566UzD6i5PFY15jYMzi1+ICriDItCv3S+JdqyrBrX3RloZhdyXqs2Htxfw4b1OcYboPCu4+9qM3OV02wyGKlGQMhfrXNwYyj8huxS1pHghEROM2Zs0paZUOy+6ajM+Xh0LX2w==", :complemento=>nil, :cancelada=>nil, :impuestos=>[{:impuesto=>"IVA"}]}
|
43
|
+
returns = {:version=>"3.2", :fecha=>"2013-10-15T01:33:32", :tipoDeComprobante=>"ingreso", :formaDePago=>"PAGO EN UNA SOLA EXHIBICION", :condicionesDePago=>"Sera marcada como pagada en cuanto el receptor haya cubierto el pago.", :subTotal=>11000.0, :TipoCambio=>1, :moneda=>"pesos", :total=>12760.0, :metodoDePago=>"Transferencia Bancaria", :lugarExpedicion=>"Nutopia, Nutopia", :NumCtaPago=>nil, :emisor=>{:rfc=>"XAXX010101000", :nombre=>"Me cago en sus estándares S.A. de C.V.", :domicilioFiscal=>{:calle=>"Calle Feliz", :noExterior=>"42", :noInterior=>"314", :colonia=>"Centro", :localidad=>"No se que sea esto, pero va", :referencia=>"Sin Referencia", :municipio=>"Nutopía", :estado=>"Nutopía", :pais=>"Nutopía", :codigoPostal=>"31415"}, :expedidoEn=>{:calle=>"Calle Feliz", :noExterior=>"42", :noInterior=>nil, :colonia=>"Centro", :localidad=>"No se que sea esto, pero va", :referencia=>"Sin Referencia", :municipio=>"Nutopía", :estado=>"Nutopía", :pais=>"Nutopía", :codigoPostal=>"31415"}, :regimenFiscal=>"Pruebas Fiscales"}, :receptor=>{:rfc=>"XAXX010101000", :nombre=>"El SAT apesta S. de R.L.", :domicilioFiscal=>{:calle=>nil, :noExterior=>nil, :noInterior=>nil, :colonia=>nil, :localidad=>nil, :referencia=>"Sin Referencia", :municipio=>nil, :estado=>"Nutopía", :pais=>"Nutopía", :codigoPostal=>nil}, :expedidoEn=>nil, :regimenFiscal=>nil}, :conceptos=>[{:cantidad=>2, :unidad=>"Kilos", :noIdentificacion=>"KDV", :descripcion=>"Verga Ción", :valorUnitario=>5500.0, :importe=>11000.0}], :serie=>nil, :folio=>"1", :sello=>"igFu7Q9Z98n6xFSLMv7a2y8ZlJCO+pgTX3xDAUt5xSpX3dHOKXkTHBAf4P/oHHDm3xkYkaNBfPEzpVFDrRVjL2rvkR5T9rsFqb4cl6DOo4RrRIpSR9vojLp7mFWiON9H6OFPi2b9PVAnyIx1Skb5iGIAmSQIhVYyt2DSauObY2c=", :noCertificado=>"20001000000200000293", :certificado=>"MIIE2jCCA8KgAwIBAgIUMjAwMDEwMDAwMDAyMDAwMDAyOTMwDQYJKoZIhvcNAQEFBQAwggFcMRowGAYDVQQDDBFBLkMuIDIgZGUgcHJ1ZWJhczEvMC0GA1UECgwmU2VydmljaW8gZGUgQWRtaW5pc3RyYWNpw7NuIFRyaWJ1dGFyaWExODA2BgNVBAsML0FkbWluaXN0cmFjacOzbiBkZSBTZWd1cmlkYWQgZGUgbGEgSW5mb3JtYWNpw7NuMSkwJwYJKoZIhvcNAQkBFhphc2lzbmV0QHBydWViYXMuc2F0LmdvYi5teDEmMCQGA1UECQwdQXYuIEhpZGFsZ28gNzcsIENvbC4gR3VlcnJlcm8xDjAMBgNVBBEMBTA2MzAwMQswCQYDVQQGEwJNWDEZMBcGA1UECAwQRGlzdHJpdG8gRmVkZXJhbDESMBAGA1UEBwwJQ295b2Fjw6FuMTQwMgYJKoZIhvcNAQkCDCVSZXNwb25zYWJsZTogQXJhY2VsaSBHYW5kYXJhIEJhdXRpc3RhMB4XDTEyMTAyNjE5MjI0M1oXDTE2MTAyNjE5MjI0M1owggFTMUkwRwYDVQQDE0BBU09DSUFDSU9OIERFIEFHUklDVUxUT1JFUyBERUwgRElTVFJJVE8gREUgUklFR08gMDA0IERPTiBNQVJUSU4gMWEwXwYDVQQpE1hBU09DSUFDSU9OIERFIEFHUklDVUxUT1JFUyBERUwgRElTVFJJVE8gREUgUklFR08gMDA0IERPTiBNQVJUSU4gQ09BSFVJTEEgWSBOVUVWTyBMRU9OIEFDMUkwRwYDVQQKE0BBU09DSUFDSU9OIERFIEFHUklDVUxUT1JFUyBERUwgRElTVFJJVE8gREUgUklFR08gMDA0IERPTiBNQVJUSU4gMSUwIwYDVQQtExxBQUQ5OTA4MTRCUDcgLyBIRUdUNzYxMDAzNFMyMR4wHAYDVQQFExUgLyBIRUdUNzYxMDAzTURGUk5OMDkxETAPBgNVBAsTCFNlcnZpZG9yMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDlrI9loozd+UcW7YHtqJimQjzX9wHIUcc1KZyBBB8/5fZsgZ/smWS4Sd6HnPs9GSTtnTmM4bEgx28N3ulUshaaBEtZo3tsjwkBV/yVQ3SRyMDkqBA2NEjbcum+e/MdCMHiPI1eSGHEpdESt55a0S6N24PW732Xm3ZbGgOp1tht1wIDAQABox0wGzAMBgNVHRMBAf8EAjAAMAsGA1UdDwQEAwIGwDANBgkqhkiG9w0BAQUFAAOCAQEAuoPXe+BBIrmJn+IGeI+m97OlP3RC4Ct3amjGmZICbvhI9BTBLCL/PzQjjWBwU0MG8uK6e/gcB9f+klPiXhQTeI1YKzFtWrzctpNEJYo0KXMgvDiputKphQ324dP0nzkKUfXlRIzScJJCSgRw9ZifKWN0D9qTdkNkjk83ToPgwnldg5lzU62woXo4AKbcuabAYOVoC7owM5bfNuWJe566UzD6i5PFY15jYMzi1+ICriDItCv3S+JdqyrBrX3RloZhdyXqs2Htxfw4b1OcYboPCu4+9qM3OV02wyGKlGQMhfrXNwYyj8huxS1pHghEROM2Zs0paZUOy+6ajM+Xh0LX2w==", :complemento=>nil, :cancelada=>nil, :impuestos=>[{:impuesto=>"IVA"}]}
|
44
44
|
comprobante.to_h.should be_eql(returns)
|
45
45
|
end
|
46
46
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cfdi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Roberto Hidalgo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2014-02-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -77,6 +77,7 @@ files:
|
|
77
77
|
- examples/data/_empty
|
78
78
|
- examples/data/cfdi.xml
|
79
79
|
- examples/desde_xml.rb
|
80
|
+
- lib/addenda.rb
|
80
81
|
- lib/certificado.rb
|
81
82
|
- lib/cfdi.rb
|
82
83
|
- lib/complemento.rb
|