cfdi40 0.0.1.alfa → 0.0.2

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.
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