cfdi40 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README_es-MX.md +23 -1
- data/lib/cfdi40/complemento_concepto.rb +12 -0
- data/lib/cfdi40/comprobante.rb +16 -6
- data/lib/cfdi40/concepto.rb +38 -0
- data/lib/cfdi40/impuestos.rb +1 -0
- data/lib/cfdi40/inst_educativas.rb +17 -0
- data/lib/cfdi40/node.rb +35 -2
- data/lib/cfdi40/sat_csd.rb +11 -5
- data/lib/cfdi40/traslados.rb +1 -0
- data/lib/cfdi40/version.rb +1 -1
- data/lib/cfdi40.rb +2 -0
- data/lib/xsd/README.md +7 -3
- data/lib/xsd/cfdv40.xsd +1 -0
- data/lib/xsd/iedu.xsd +84 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bb9a12ec72926735a554f302b13993914393c626cc4dcd797791dfcf0ed8191a
|
4
|
+
data.tar.gz: 4bc4708eb4c2c0671fa11c81dbcb40a8a8c9a585d2fa02531137efeee942a9d0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f41d5ee33e1e705d2b12b2c623cd6b197d2c93c1a9e5d994ffc38630954fc4cb6ed6a1c2ae084513bfa6991f7c1bf67b4cc609ebbca3c2d1c99d74167897f470
|
7
|
+
data.tar.gz: 9f55e7a93233c1c8121d26424c2a7604d36b58f6695b104dc64ea39091e16bb45f3da10231ff4367e75c56d843fd724284b2adae053617244a2295227d3bc41d
|
data/Gemfile.lock
CHANGED
data/README_es-MX.md
CHANGED
@@ -24,7 +24,7 @@ que esta herramienta:
|
|
24
24
|
# Inicia un cfdi
|
25
25
|
cfdi = Cfdi40.new
|
26
26
|
|
27
|
-
# Datos del emisor
|
27
|
+
# Datos del emisor. RFC y Nombre se extraen del certificado
|
28
28
|
cfdi.lugar_expedicion = '06000'
|
29
29
|
cfdi.emisor.regimen_fiscal = '612'
|
30
30
|
|
@@ -53,6 +53,28 @@ que esta herramienta:
|
|
53
53
|
# Genera CFDI firmado
|
54
54
|
xml_string = cfdi.to_xml
|
55
55
|
|
56
|
+
# Cambios
|
57
|
+
|
58
|
+
# 0.0.3
|
59
|
+
|
60
|
+
* Lee RFC en certificados de personas morales. Los certificados de
|
61
|
+
personas morales tienen el RFC de la persona moral y el del
|
62
|
+
representante legal en el `UniqueIdentifier` del `Subject` del
|
63
|
+
certificado
|
64
|
+
* Actepta llaves previamente descifradas en formato PEM.
|
65
|
+
|
66
|
+
# 0.0.2
|
67
|
+
|
68
|
+
* Definición básica de la intefaz.
|
69
|
+
* Carga certificado y llave desde archivo.
|
70
|
+
* Acepta certificado y llave previamente leídos.
|
71
|
+
* Genera CFDI de ingresos básico. Con desglose de impuestos, sello
|
72
|
+
digital
|
73
|
+
* Valida correspondencia de certificado y llave
|
74
|
+
|
75
|
+
# 0.0.1
|
76
|
+
|
77
|
+
* Versión inicial. Esqueleto para desarrollo
|
56
78
|
|
57
79
|
# ¿Que sigue?
|
58
80
|
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Cfdi40
|
2
|
+
class ComplementoConcepto < Node
|
3
|
+
def inst_educativas_node
|
4
|
+
return @inst_educativas_node if defined?(@inst_educativas_node)
|
5
|
+
|
6
|
+
@inst_educativas_node = InstEducativas.new
|
7
|
+
@inst_educativas_node.parent_node = self
|
8
|
+
self.children_nodes << @inst_educativas_node
|
9
|
+
@inst_educativas_node
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
data/lib/cfdi40/comprobante.rb
CHANGED
@@ -32,14 +32,17 @@ module Cfdi40
|
|
32
32
|
|
33
33
|
attr_reader :emisor, :receptor, :x509_cert, :conceptos, :private_key
|
34
34
|
attr_reader :errors
|
35
|
-
attr_writer :
|
35
|
+
attr_writer :key_data, :key_pass
|
36
36
|
|
37
37
|
def initialize
|
38
38
|
super
|
39
39
|
@errors = []
|
40
40
|
@conceptos = Conceptos.new
|
41
|
+
@conceptos.parent_node = self
|
41
42
|
@emisor = Emisor.new
|
43
|
+
@emisor.parent_node = self
|
42
44
|
@receptor = Receptor.new
|
45
|
+
@receptor.parent_node = self
|
43
46
|
@sat_csd = SatCsd.new
|
44
47
|
@fecha ||= Time.now.strftime("%Y-%m-%dT%H:%M:%S")
|
45
48
|
@children_nodes = [@emisor, @receptor, @conceptos]
|
@@ -64,7 +67,7 @@ module Cfdi40
|
|
64
67
|
end
|
65
68
|
|
66
69
|
def key_path=(path)
|
67
|
-
@
|
70
|
+
@key_data = File.read(path)
|
68
71
|
end
|
69
72
|
|
70
73
|
def sign
|
@@ -89,8 +92,11 @@ module Cfdi40
|
|
89
92
|
# importe
|
90
93
|
# descuento
|
91
94
|
# objeto_imp
|
95
|
+
#
|
96
|
+
# TODO: Document accepted attributes and its use
|
92
97
|
def add_concepto(attributes = {})
|
93
98
|
concepto = Concepto.new
|
99
|
+
concepto.parent_node = @conceptos
|
94
100
|
attributes.each do |key, value|
|
95
101
|
method_name = "#{key}=".to_sym
|
96
102
|
if concepto.respond_to?(method_name)
|
@@ -154,15 +160,18 @@ module Cfdi40
|
|
154
160
|
def calculate!
|
155
161
|
@subtotal = @conceptos.children_nodes.map(&:importe).sum
|
156
162
|
@total = @conceptos.children_nodes.map(&:importe_neto).sum
|
157
|
-
|
163
|
+
add_traslados_summary_node
|
158
164
|
end
|
159
165
|
|
160
|
-
def
|
166
|
+
def add_traslados_summary_node
|
167
|
+
return if traslados_summary.empty?
|
168
|
+
|
161
169
|
impuestos.total_impuestos_trasladados = 0
|
162
170
|
traslados.children_nodes = []
|
163
171
|
traslados_summary.each do |key, value|
|
164
172
|
#TODO: Sumar los impuestos y agregarlos a los nodos globales de traslados
|
165
173
|
traslado = Traslado.new
|
174
|
+
traslado.parent_node = impuestos
|
166
175
|
traslado.impuesto, traslado.tasa_o_cuota, traslado.tipo_factor = key
|
167
176
|
traslado.base = value[:base]
|
168
177
|
traslado.importe = value[:importe]
|
@@ -196,6 +205,7 @@ module Cfdi40
|
|
196
205
|
return @impuestos if defined?(@impuestos)
|
197
206
|
|
198
207
|
@impuestos = Impuestos.new
|
208
|
+
@impuestos.parent_node = self
|
199
209
|
@children_nodes << @impuestos
|
200
210
|
@impuestos
|
201
211
|
end
|
@@ -216,10 +226,10 @@ module Cfdi40
|
|
216
226
|
end
|
217
227
|
|
218
228
|
def load_private_key
|
219
|
-
return unless defined?(@
|
229
|
+
return unless defined?(@key_data) && defined?(@key_pass)
|
220
230
|
|
221
231
|
@sat_csd ||= SatCsd.new
|
222
|
-
@sat_csd.
|
232
|
+
@sat_csd.set_private_key(@key_data, @key_pass)
|
223
233
|
end
|
224
234
|
end
|
225
235
|
end
|
data/lib/cfdi40/concepto.rb
CHANGED
@@ -19,6 +19,9 @@ module Cfdi40
|
|
19
19
|
attr_accessor :tasa_iva, :tasa_ieps, :precio_neto, :precio_bruto
|
20
20
|
attr_reader :iva, :ieps, :base_iva, :importe_neto, :importe_bruto
|
21
21
|
|
22
|
+
# accesors for instEducativas
|
23
|
+
attr_accessor :iedu_nombre_alumno, :iedu_curp, :iedu_nivel_educativo, :iedu_aut_rvoe, :iedu_rfc_pago
|
24
|
+
|
22
25
|
def initialize
|
23
26
|
@tasa_iva = 0.16
|
24
27
|
@tasa_ieps = 0
|
@@ -40,6 +43,7 @@ module Cfdi40
|
|
40
43
|
end
|
41
44
|
add_info_to_traslado_iva
|
42
45
|
# TODO: add_info_to_traslado_ieps if @ieps > 0
|
46
|
+
add_inst_educativas
|
43
47
|
true
|
44
48
|
end
|
45
49
|
|
@@ -113,6 +117,7 @@ module Cfdi40
|
|
113
117
|
return if @impuestos_node
|
114
118
|
|
115
119
|
@impuestos_node = Impuestos.new
|
120
|
+
@impuestos_node.parent_node = self
|
116
121
|
self.children_nodes << @impuestos_node
|
117
122
|
@impuestos_node
|
118
123
|
end
|
@@ -122,5 +127,38 @@ module Cfdi40
|
|
122
127
|
|
123
128
|
impuestos_node.traslado_iva
|
124
129
|
end
|
130
|
+
|
131
|
+
def add_inst_educativas
|
132
|
+
return unless inst_educativas_present?
|
133
|
+
|
134
|
+
inst_educativas_node.nombre_alumno = iedu_nombre_alumno
|
135
|
+
inst_educativas_node.curp = iedu_curp
|
136
|
+
inst_educativas_node.nivel_educativo = iedu_nivel_educativo
|
137
|
+
inst_educativas_node.aut_rvoe = iedu_aut_rvoe
|
138
|
+
inst_educativas_node.rfc_pago = iedu_rfc_pago
|
139
|
+
end
|
140
|
+
|
141
|
+
def inst_educativas_present?
|
142
|
+
return false if iedu_nombre_alumno.nil?
|
143
|
+
return false if iedu_nivel_educativo.nil?
|
144
|
+
return false if iedu_aut_rvoe.nil?
|
145
|
+
|
146
|
+
true
|
147
|
+
end
|
148
|
+
|
149
|
+
def concepto_complemento_node
|
150
|
+
return @complemento_concepto_node if defined?(@complemento_concepto_node)
|
151
|
+
|
152
|
+
@complemento_concepto_node = ComplementoConcepto.new
|
153
|
+
@complemento_concepto_node.parent_node = self
|
154
|
+
self.children_nodes << @complemento_concepto_node
|
155
|
+
@complemento_concepto_node
|
156
|
+
end
|
157
|
+
|
158
|
+
def inst_educativas_node
|
159
|
+
return nil unless concepto_complemento_node.is_a?(ComplementoConcepto)
|
160
|
+
|
161
|
+
concepto_complemento_node.inst_educativas_node
|
162
|
+
end
|
125
163
|
end
|
126
164
|
end
|
data/lib/cfdi40/impuestos.rb
CHANGED
@@ -0,0 +1,17 @@
|
|
1
|
+
module Cfdi40
|
2
|
+
class InstEducativas < Node
|
3
|
+
define_element_name 'instEducativas'
|
4
|
+
define_namespace "xsi", "http://www.w3.org/2001/XMLSchema-instance"
|
5
|
+
define_namespace "iedu", "http://www.sat.gob.mx/iedu"
|
6
|
+
define_attribute :schema_location,
|
7
|
+
xml_attribute: 'xsi:schemaLocation',
|
8
|
+
readonly: true,
|
9
|
+
default: "http://www.sat.gob.mx/iedu http://www.sat.gob.mx/sitio_internet/cfd/iedu/iedu.xsd"
|
10
|
+
define_attribute :version, xml_attribute: 'version', readonly: true, default: '1.0'
|
11
|
+
define_attribute :nombre_alumno, xml_attribute: 'nombreAlumno'
|
12
|
+
define_attribute :curp, xml_attribute: 'CURP'
|
13
|
+
define_attribute :nivel_educativo, xml_attribute: 'nivelEducativo'
|
14
|
+
define_attribute :aut_rvoe, xml_attribute: 'autRVOE'
|
15
|
+
define_attribute :rfc_pago, xml_attribute: 'rfcPago'
|
16
|
+
end
|
17
|
+
end
|
data/lib/cfdi40/node.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
module Cfdi40
|
2
2
|
class Node
|
3
3
|
# Nokigir XML Document for the xml_node
|
4
|
-
attr_accessor :xml_document, :xml_parent, :children_nodes
|
4
|
+
attr_accessor :xml_document, :xml_parent, :children_nodes, :parent_node
|
5
|
+
attr_writer :element_name
|
5
6
|
|
6
7
|
def initialize
|
7
8
|
self.class.verify_class_variables
|
@@ -20,6 +21,7 @@ module Cfdi40
|
|
20
21
|
@@default_values[name] ||= {}
|
21
22
|
@@formats ||= {}
|
22
23
|
@@formats[name] ||= {}
|
24
|
+
@@element_names ||= {}
|
23
25
|
end
|
24
26
|
|
25
27
|
def self.define_attribute(accessor, xml_attribute:, default: nil, format: nil, readonly: false)
|
@@ -43,6 +45,11 @@ module Cfdi40
|
|
43
45
|
@@namespaces[name][namespace] = value
|
44
46
|
end
|
45
47
|
|
48
|
+
def self.define_element_name(value)
|
49
|
+
verify_class_variables
|
50
|
+
@@element_names[name] = value.to_s
|
51
|
+
end
|
52
|
+
|
46
53
|
def self.namespaces
|
47
54
|
@@namespaces[name]
|
48
55
|
end
|
@@ -59,6 +66,11 @@ module Cfdi40
|
|
59
66
|
@@formats[name]
|
60
67
|
end
|
61
68
|
|
69
|
+
def self.element_name
|
70
|
+
verify_class_variables
|
71
|
+
@@element_names[name]
|
72
|
+
end
|
73
|
+
|
62
74
|
def set_defaults
|
63
75
|
return if self.class.default_values.nil?
|
64
76
|
|
@@ -75,18 +87,39 @@ module Cfdi40
|
|
75
87
|
instance_variable_get("@#{accessor}".to_sym).nil?
|
76
88
|
end
|
77
89
|
|
90
|
+
def current_namespace
|
91
|
+
return unless self.class.respond_to?(:namespaces)
|
92
|
+
if self.class.namespaces.empty?
|
93
|
+
return parent_node.current_namespace unless parent_node.nil?
|
94
|
+
end
|
95
|
+
|
96
|
+
self.class.namespaces.keys.last
|
97
|
+
end
|
98
|
+
|
78
99
|
def create_xml_node
|
79
100
|
set_defaults
|
80
101
|
if self.respond_to?(:before_add, true)
|
81
102
|
self.before_add
|
82
103
|
end
|
83
|
-
xml_node = xml_document.create_element(
|
104
|
+
xml_node = xml_document.create_element(expanded_element_name)
|
84
105
|
add_namespaces_to(xml_node)
|
85
106
|
add_attributes_to(xml_node)
|
86
107
|
add_children_to(xml_node)
|
87
108
|
xml_parent.add_child xml_node
|
88
109
|
end
|
89
110
|
|
111
|
+
# Returns setted @element_name or use class_name
|
112
|
+
def element_name
|
113
|
+
return self.class.element_name unless self.class.element_name.nil? || self.class.element_name == ''
|
114
|
+
|
115
|
+
self.class.name.split('::').last
|
116
|
+
end
|
117
|
+
|
118
|
+
def expanded_element_name
|
119
|
+
return element_name unless current_namespace
|
120
|
+
"#{current_namespace}:#{element_name}"
|
121
|
+
end
|
122
|
+
|
90
123
|
def add_namespaces_to(xml_node)
|
91
124
|
self.class.namespaces.each do |namespace, value|
|
92
125
|
xml_node.add_namespace namespace, value
|
data/lib/cfdi40/sat_csd.rb
CHANGED
@@ -13,12 +13,12 @@ module Cfdi40
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def load_private_key(key_path, key_pass)
|
16
|
-
key_pem =
|
16
|
+
key_pem = key_to_pem(File.read(key_path))
|
17
17
|
@private_key = OpenSSL::PKey::RSA.new(key_pem, key_pass)
|
18
18
|
end
|
19
19
|
|
20
|
-
def
|
21
|
-
key_pem =
|
20
|
+
def set_private_key(key_data, key_pass = nil)
|
21
|
+
key_pem = (pem_format?(key_data) ? key_data : key_to_pem(key_data))
|
22
22
|
@private_key = OpenSSL::PKey::RSA.new(key_pem, key_pass)
|
23
23
|
end
|
24
24
|
|
@@ -28,7 +28,7 @@ module Cfdi40
|
|
28
28
|
unique_identifier = subject_data.select { |data| data[0] == "x500UniqueIdentifier" }.first
|
29
29
|
return unless unique_identifier
|
30
30
|
|
31
|
-
unique_identifier[1]
|
31
|
+
unique_identifier[1].split(" / ").first
|
32
32
|
end
|
33
33
|
|
34
34
|
def name
|
@@ -72,12 +72,18 @@ module Cfdi40
|
|
72
72
|
x509_cert.subject.to_a
|
73
73
|
end
|
74
74
|
|
75
|
-
def
|
75
|
+
def key_to_pem(key_der)
|
76
76
|
array_key_pem = []
|
77
77
|
array_key_pem << '-----BEGIN ENCRYPTED PRIVATE KEY-----'
|
78
78
|
array_key_pem += Base64.strict_encode64(key_der).scan(/.{1,64}/)
|
79
79
|
array_key_pem << '-----END ENCRYPTED PRIVATE KEY-----'
|
80
80
|
array_key_pem.join("\n")
|
81
81
|
end
|
82
|
+
|
83
|
+
def pem_format?(data)
|
84
|
+
return false unless data.valid_encoding?
|
85
|
+
|
86
|
+
data.match?(/BEGIN/)
|
87
|
+
end
|
82
88
|
end
|
83
89
|
end
|
data/lib/cfdi40/traslados.rb
CHANGED
data/lib/cfdi40/version.rb
CHANGED
data/lib/cfdi40.rb
CHANGED
@@ -15,6 +15,8 @@ require_relative "cfdi40/concepto"
|
|
15
15
|
require_relative "cfdi40/impuestos"
|
16
16
|
require_relative "cfdi40/traslados"
|
17
17
|
require_relative "cfdi40/traslado"
|
18
|
+
require_relative "cfdi40/complemento_concepto"
|
19
|
+
require_relative "cfdi40/inst_educativas"
|
18
20
|
|
19
21
|
# Leading module and entry point for all features and classes
|
20
22
|
#
|
data/lib/xsd/README.md
CHANGED
@@ -6,9 +6,13 @@ In order to avoid innecesary and redundant reading from SAT site the
|
|
6
6
|
file `cfdv40.xsd` referenced in cfdi standard, has been
|
7
7
|
prepared for local access.
|
8
8
|
|
9
|
-
The `cfdv40.xsd` has been modified to reference the local files
|
10
|
-
|
11
|
-
`
|
9
|
+
The `cfdv40.xsd` has been modified to reference the local files:
|
10
|
+
|
11
|
+
* `tdCFDI.xsd`,
|
12
|
+
* `catCFDI.xsd` this file has 5.8MB
|
13
|
+
* `iedu.xsd`
|
14
|
+
|
15
|
+
Local files are imported schemas.
|
12
16
|
|
13
17
|
## Use external files
|
14
18
|
|
data/lib/xsd/cfdv40.xsd
CHANGED
@@ -7,6 +7,7 @@
|
|
7
7
|
-->
|
8
8
|
<xs:import namespace="http://www.sat.gob.mx/sitio_internet/cfd/catalogos" schemaLocation="catCFDI.xsd"/>
|
9
9
|
<xs:import namespace="http://www.sat.gob.mx/sitio_internet/cfd/tipoDatos/tdCFDI" schemaLocation="tdCFDI.xsd"/>
|
10
|
+
<xs:import namespace="http://www.sat.gob.mx/iedu" schemaLocation="iedu.xsd"/>
|
10
11
|
|
11
12
|
<xs:element name="Comprobante">
|
12
13
|
<xs:annotation>
|
data/lib/xsd/iedu.xsd
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:iedu="http://www.sat.gob.mx/iedu" targetNamespace="http://www.sat.gob.mx/iedu" elementFormDefault="qualified" attributeFormDefault="unqualified">
|
3
|
+
<xs:element name="instEducativas">
|
4
|
+
<xs:annotation>
|
5
|
+
<xs:documentation>Complemento concepto para la expedición de comprobantes fiscales por parte de Instituciones Educativas Privadas, para los efectos del artículo primero y cuarto del decreto por el que se otorga un estímulo fiscal a las personas físicas en relación con los pagos por servicios educativos </xs:documentation>
|
6
|
+
</xs:annotation>
|
7
|
+
<xs:complexType>
|
8
|
+
<xs:attribute name="version" use="required" fixed="1.0">
|
9
|
+
<xs:annotation>
|
10
|
+
<xs:documentation>Atributo requerido con valor prefijado a 1.0 que indica la versión del estándar bajo el que se encuentra expresado el complemento concepto al comprobante.</xs:documentation>
|
11
|
+
</xs:annotation>
|
12
|
+
<xs:simpleType>
|
13
|
+
<xs:restriction base="xs:string">
|
14
|
+
<xs:whiteSpace value="collapse"/>
|
15
|
+
</xs:restriction>
|
16
|
+
</xs:simpleType>
|
17
|
+
</xs:attribute>
|
18
|
+
<xs:attribute name="nombreAlumno" use="required">
|
19
|
+
<xs:annotation>
|
20
|
+
<xs:documentation>Atributo requerido para indicar el nombre del Alumno </xs:documentation>
|
21
|
+
</xs:annotation>
|
22
|
+
<xs:simpleType>
|
23
|
+
<xs:restriction base="xs:string"/>
|
24
|
+
</xs:simpleType>
|
25
|
+
</xs:attribute>
|
26
|
+
<xs:attribute name="CURP" type="iedu:tCURP" use="required">
|
27
|
+
<xs:annotation>
|
28
|
+
<xs:documentation>Atributo requerido para indicar la CURP del alumno de la institución educativa</xs:documentation>
|
29
|
+
</xs:annotation>
|
30
|
+
</xs:attribute>
|
31
|
+
<xs:attribute name="nivelEducativo" use="required">
|
32
|
+
<xs:annotation>
|
33
|
+
<xs:documentation>Atributo requerido para indicar el nivel educativo que cursa el alumno</xs:documentation>
|
34
|
+
</xs:annotation>
|
35
|
+
<xs:simpleType>
|
36
|
+
<xs:restriction base="xs:string">
|
37
|
+
<xs:enumeration value="Preescolar"/>
|
38
|
+
<xs:enumeration value="Primaria"/>
|
39
|
+
<xs:enumeration value="Secundaria"/>
|
40
|
+
<xs:enumeration value="Profesional técnico"/>
|
41
|
+
<xs:enumeration value="Bachillerato o su equivalente"/>
|
42
|
+
</xs:restriction>
|
43
|
+
</xs:simpleType>
|
44
|
+
</xs:attribute>
|
45
|
+
<xs:attribute name="autRVOE" use="required">
|
46
|
+
<xs:annotation>
|
47
|
+
<xs:documentation>Atributo requerido para especificar la clave del centro de trabajo o el reconocimiento de validez oficial de estudios en los términos de la Ley General de Educación que tenga la institución educativa privada donde se realiza el pago.</xs:documentation>
|
48
|
+
</xs:annotation>
|
49
|
+
<xs:simpleType>
|
50
|
+
<xs:restriction base="xs:string">
|
51
|
+
<xs:minLength value="1"/>
|
52
|
+
<xs:whiteSpace value="collapse"/>
|
53
|
+
</xs:restriction>
|
54
|
+
</xs:simpleType>
|
55
|
+
</xs:attribute>
|
56
|
+
<xs:attribute name="rfcPago" type="iedu:tRFC" use="optional">
|
57
|
+
<xs:annotation>
|
58
|
+
<xs:documentation>Atributo opcional para indicar el RFC de quien realiza el pago cuando sea diferente a quien recibe el servicio</xs:documentation>
|
59
|
+
</xs:annotation>
|
60
|
+
</xs:attribute>
|
61
|
+
</xs:complexType>
|
62
|
+
</xs:element>
|
63
|
+
<xs:simpleType name="tRFC">
|
64
|
+
<xs:annotation>
|
65
|
+
<xs:documentation>Tipo definido para la expresión de RFC's de contribuyentes. Cabe hacer la mención que debido a las reglas definidas por el estándar XML en el caso de que un RFC dado incluya un caracter ampersand, dicho caracter deberá ser expresado mediante la secuencia de escape especificado como parte del estándar. En la definición del tipo se expresa una longitud mínima y máxima, sin embargo la longitud puede ser redefinida como una extensión según se determina el uso particular</xs:documentation>
|
66
|
+
</xs:annotation>
|
67
|
+
<xs:restriction base="xs:string">
|
68
|
+
<xs:minLength value="12"/>
|
69
|
+
<xs:maxLength value="13"/>
|
70
|
+
<xs:whiteSpace value="collapse"/>
|
71
|
+
<xs:pattern value="[A-Z,Ñ,&]{3,4}[0-9]{2}[0-1][0-9][0-3][0-9][A-Z,0-9]?[A-Z,0-9]?[0-9,A-Z]?"/>
|
72
|
+
</xs:restriction>
|
73
|
+
</xs:simpleType>
|
74
|
+
<xs:simpleType name="tCURP">
|
75
|
+
<xs:annotation>
|
76
|
+
<xs:documentation>Tipo definido para la expresión de una CURP. </xs:documentation>
|
77
|
+
</xs:annotation>
|
78
|
+
<xs:restriction base="xs:string">
|
79
|
+
<xs:whiteSpace value="collapse"/>
|
80
|
+
<xs:length value="18"/>
|
81
|
+
<xs:pattern value="[A-Z][A,E,I,O,U,X][A-Z]{2}[0-9]{2}[0-1][0-9][0-3][0-9][M,H][A-Z]{2}[B,C,D,F,G,H,J,K,L,M,N,Ñ,P,Q,R,S,T,V,W,X,Y,Z]{3}[0-9,A-Z][0-9]"/>
|
82
|
+
</xs:restriction>
|
83
|
+
</xs:simpleType>
|
84
|
+
</xs:schema>
|
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.0.
|
4
|
+
version: 0.0.3
|
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: 2023-03-
|
11
|
+
date: 2023-03-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -43,11 +43,13 @@ files:
|
|
43
43
|
- Rakefile
|
44
44
|
- cfdi40.gemspec
|
45
45
|
- lib/cfdi40.rb
|
46
|
+
- lib/cfdi40/complemento_concepto.rb
|
46
47
|
- lib/cfdi40/comprobante.rb
|
47
48
|
- lib/cfdi40/concepto.rb
|
48
49
|
- lib/cfdi40/conceptos.rb
|
49
50
|
- lib/cfdi40/emisor.rb
|
50
51
|
- lib/cfdi40/impuestos.rb
|
52
|
+
- lib/cfdi40/inst_educativas.rb
|
51
53
|
- lib/cfdi40/node.rb
|
52
54
|
- lib/cfdi40/receptor.rb
|
53
55
|
- lib/cfdi40/sat_csd.rb
|
@@ -58,6 +60,7 @@ files:
|
|
58
60
|
- lib/xsd/README.md
|
59
61
|
- lib/xsd/catCFDI.xsd
|
60
62
|
- lib/xsd/cfdv40.xsd
|
63
|
+
- lib/xsd/iedu.xsd
|
61
64
|
- lib/xsd/tdCFDI.xsd
|
62
65
|
- lib/xslt/CartaPorte20.xslt
|
63
66
|
- lib/xslt/GastosHidrocarburos10.xslt
|