cfdi40 0.0.1.alfa → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/README.md +10 -5
  4. data/README_es-MX.md +62 -0
  5. data/cfdi40.gemspec +2 -2
  6. data/lib/cfdi40/comprobante.rb +215 -20
  7. data/lib/cfdi40/concepto.rb +126 -0
  8. data/lib/cfdi40/conceptos.rb +4 -0
  9. data/lib/cfdi40/emisor.rb +7 -0
  10. data/lib/cfdi40/impuestos.rb +28 -0
  11. data/lib/cfdi40/node.rb +122 -0
  12. data/lib/cfdi40/receptor.rb +11 -0
  13. data/lib/cfdi40/sat_csd.rb +83 -0
  14. data/lib/cfdi40/schema_validator.rb +29 -0
  15. data/lib/cfdi40/traslado.rb +9 -0
  16. data/lib/cfdi40/traslados.rb +17 -0
  17. data/lib/cfdi40/version.rb +1 -1
  18. data/lib/cfdi40.rb +12 -0
  19. data/lib/xsd/README.md +30 -0
  20. data/lib/xsd/catCFDI.xsd +162329 -0
  21. data/lib/xsd/cfdv40.xsd +856 -0
  22. data/lib/xsd/tdCFDI.xsd +157 -0
  23. data/lib/xslt/CartaPorte20.xslt +615 -0
  24. data/lib/xslt/GastosHidrocarburos10.xslt +171 -0
  25. data/lib/xslt/IngresosHidrocarburos.xslt +39 -0
  26. data/lib/xslt/Pagos20.xslt +233 -0
  27. data/lib/xslt/TuristaPasajeroExtranjero.xslt +40 -0
  28. data/lib/xslt/aerolineas.xslt +50 -0
  29. data/lib/xslt/cadenaoriginal.xslt +405 -0
  30. data/lib/xslt/cadenaoriginal_local.xslt +405 -0
  31. data/lib/xslt/certificadodedestruccion.xslt +60 -0
  32. data/lib/xslt/cfdiregistrofiscal.xslt +19 -0
  33. data/lib/xslt/consumodeCombustibles11.xslt +94 -0
  34. data/lib/xslt/detallista.xslt +42 -0
  35. data/lib/xslt/divisas.xslt +13 -0
  36. data/lib/xslt/donat11.xslt +13 -0
  37. data/lib/xslt/iedu.xslt +26 -0
  38. data/lib/xslt/implocal.xslt +39 -0
  39. data/lib/xslt/ine11.xslt +30 -0
  40. data/lib/xslt/leyendasFisc.xslt +28 -0
  41. data/lib/xslt/nomina12.xslt +412 -0
  42. data/lib/xslt/notariospublicos.xslt +301 -0
  43. data/lib/xslt/obrasarteantiguedades.xslt +33 -0
  44. data/lib/xslt/pagoenespecie.xslt +39 -0
  45. data/lib/xslt/pfic.xslt +13 -0
  46. data/lib/xslt/renovacionysustitucionvehiculos.xslt +152 -0
  47. data/lib/xslt/servicioparcialconstruccion.xslt +44 -0
  48. data/lib/xslt/utilerias.xslt +22 -0
  49. data/lib/xslt/valesdedespensa.xslt +70 -0
  50. data/lib/xslt/vehiculousado.xslt +63 -0
  51. metadata +50 -13
@@ -0,0 +1,83 @@
1
+ module Cfdi40
2
+ class SatCsd
3
+ attr_reader :x509_cert
4
+ attr_reader :private_key
5
+
6
+ def cert_path=(path)
7
+ @cert_path = path
8
+ @x509_cert = OpenSSL::X509::Certificate.new(File.read(path))
9
+ end
10
+
11
+ def cert_der=(data)
12
+ @x509_cert = OpenSSL::X509::Certificate.new(data)
13
+ end
14
+
15
+ def load_private_key(key_path, key_pass)
16
+ key_pem = load_key_to_pem(File.read(key_path))
17
+ @private_key = OpenSSL::PKey::RSA.new(key_pem, key_pass)
18
+ end
19
+
20
+ def set_crypted_private_key(key_der, key_pass)
21
+ key_pem = load_key_to_pem(key_der)
22
+ @private_key = OpenSSL::PKey::RSA.new(key_pem, key_pass)
23
+ end
24
+
25
+ def rfc
26
+ return unless subject_data
27
+
28
+ unique_identifier = subject_data.select { |data| data[0] == "x500UniqueIdentifier" }.first
29
+ return unless unique_identifier
30
+
31
+ unique_identifier[1]
32
+ end
33
+
34
+ def name
35
+ return unless subject_data
36
+
37
+ subject_name = subject_data.select { |data| data[0] == "name" }.first
38
+ return unless subject_name
39
+
40
+ subject_name[1]
41
+ end
42
+
43
+ def no_certificado
44
+ return unless x509_cert
45
+
46
+ s = ''
47
+ x509_cert.serial.to_s(16).split('').each_with_index do |c, i|
48
+ next if i.even?
49
+
50
+ s += c
51
+ end
52
+ s
53
+ end
54
+
55
+ def cert64
56
+ return unless x509_cert
57
+
58
+ Base64.strict_encode64 x509_cert.to_der
59
+ end
60
+
61
+ def valid_pair?
62
+ return false unless x509_cert && private_key
63
+
64
+ x509_cert.check_private_key private_key
65
+ end
66
+
67
+ private
68
+
69
+ def subject_data
70
+ return unless x509_cert
71
+
72
+ x509_cert.subject.to_a
73
+ end
74
+
75
+ def load_key_to_pem(key_der)
76
+ array_key_pem = []
77
+ array_key_pem << '-----BEGIN ENCRYPTED PRIVATE KEY-----'
78
+ array_key_pem += Base64.strict_encode64(key_der).scan(/.{1,64}/)
79
+ array_key_pem << '-----END ENCRYPTED PRIVATE KEY-----'
80
+ array_key_pem.join("\n")
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,29 @@
1
+ # Validates Schema Using xsd files
2
+ module Cfdi40
3
+ class SchemaValidator
4
+ # options = Nokogiri::XML::ParseOptions.new.nononet
5
+ # schema = Nokogiri::XML::Schema(Net::HTTP.get('www.sat.gob.mx', '/sitio_internet/cfd/4/cfdv40.xsd'), options)
6
+ # schema = Nokogiri::XML::Schema(File.open("/home/israel/git/cfdi40/lib/xsd/cfdv40.xsd"), options)
7
+
8
+ attr_reader :errors
9
+ LOCAL_XSD_PATH = File.join(File.dirname(__FILE__), '..', 'xsd', 'cfdv40.xsd')
10
+
11
+ # Param xml is xml string
12
+ def initialize(xml)
13
+ @xml_doc = Nokogiri::XML(xml)
14
+ @schema = Nokogiri::XML::Schema(File.open(LOCAL_XSD_PATH))
15
+ end
16
+
17
+ def valid?
18
+ validate unless defined?(@errors)
19
+
20
+ @errors.empty?
21
+ end
22
+
23
+ private
24
+
25
+ def validate
26
+ @errors = @schema.validate(@xml_doc)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,9 @@
1
+ module Cfdi40
2
+ class Traslado < Node
3
+ define_attribute :base, xml_attribute: 'Base', format: :t_Importe
4
+ define_attribute :impuesto, xml_attribute: 'Impuesto'
5
+ define_attribute :tipo_factor, xml_attribute: 'TipoFactor', default: 'Tasa'
6
+ define_attribute :tasa_o_cuota, xml_attribute: 'TasaOCuota', format: :t_Importe
7
+ define_attribute :importe, xml_attribute: 'Importe', format: :t_Importe
8
+ end
9
+ end
@@ -0,0 +1,17 @@
1
+ module Cfdi40
2
+ class Traslados < Node
3
+ def traslado_iva
4
+ return @traslado_iva if defined?(@traslado_iva)
5
+
6
+ @traslado_iva = Traslado.new
7
+ # TODO: FIX magic number
8
+ @traslado_iva.impuesto = '002'
9
+ self.children_nodes << @traslado_iva
10
+ @traslado_iva
11
+ end
12
+
13
+ def traslado_nodes
14
+ children_nodes
15
+ end
16
+ end
17
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Cfdi40
4
- VERSION = "0.0.1.alfa"
4
+ VERSION = "0.0.2"
5
5
  end
data/lib/cfdi40.rb CHANGED
@@ -1,8 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "nokogiri"
4
+ require "base64"
5
+ require "openssl"
4
6
  require_relative "cfdi40/version"
7
+ require_relative "cfdi40/schema_validator"
8
+ require_relative "cfdi40/sat_csd"
9
+ require_relative "cfdi40/node"
5
10
  require_relative "cfdi40/comprobante"
11
+ require_relative "cfdi40/emisor"
12
+ require_relative "cfdi40/receptor"
13
+ require_relative "cfdi40/conceptos"
14
+ require_relative "cfdi40/concepto"
15
+ require_relative "cfdi40/impuestos"
16
+ require_relative "cfdi40/traslados"
17
+ require_relative "cfdi40/traslado"
6
18
 
7
19
  # Leading module and entry point for all features and classes
8
20
  #
data/lib/xsd/README.md ADDED
@@ -0,0 +1,30 @@
1
+ # Local XSD files
2
+
3
+ ## Why?
4
+
5
+ In order to avoid innecesary and redundant reading from SAT site the
6
+ file `cfdv40.xsd` referenced in cfdi standard, has been
7
+ prepared for local access.
8
+
9
+ The `cfdv40.xsd` has been modified to reference the local files
10
+ `tdCFDI.xsd`, `catCFDI.xsd` which are imported schemas. The schema
11
+ `catCFDI.xsd` has 5.8MB
12
+
13
+ ## Use external files
14
+
15
+ If you want to use the schema in the original location must enable the
16
+ external references for Nokogiri:
17
+
18
+ require 'net/http'
19
+
20
+ xml_doc = Nokogiri::XML(xml_string)
21
+
22
+ options = Nokogiri::XML::ParseOptions.new.nononet
23
+ schema = Nokogiri::XML::Schema(Net::HTTP.get('www.sat.gob.mx', '/sitio_internet/cfd/4/cfdv40.xsd'), options)
24
+
25
+ schema.validate(xml_doc)
26
+
27
+ References:
28
+
29
+ https://nokogiri.org/rdoc/Nokogiri/XML/Schema.html
30
+ https://nokogiri.org/rdoc/Nokogiri/XML/ParseOptions.html