MX-ID 0.0.1.pre

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,58 @@
1
+ # encoding: utf-8
2
+ module MX::ID::Auxiliar
3
+
4
+ module ClassMethods
5
+ def en_blanco?(cadena)
6
+ cadena.nil? or cadena.empty?
7
+ end
8
+
9
+ def fecha_con_formato(fecha)
10
+ fecha.strftime("%y%m%d")
11
+ end
12
+
13
+ def obtener_primer_nombre_valido(nombres)
14
+ arr_nombres = nombres.split(" ")
15
+ if arr_nombres.size <= 1
16
+ nombres
17
+ else
18
+ arr_nombres[0] =~ /(JOSE)|(J\.)|J|(MARIA)|(MA)|(MA\.)/ ? arr_nombres[1] : arr_nombres[0]
19
+ end
20
+ end
21
+
22
+ # TODO: Anexar/crear biblioteca para convertir número a palabras y poder hacer esta una clase independiente
23
+ def numero_a_palabras(numero_entero)
24
+ quitar_acentos(::I18n.with_locale(:es) { numero_entero.to_words }).upcase
25
+ end
26
+
27
+ def quitar_acentos(cadena)
28
+ I18n.transliterate(cadena)
29
+ end
30
+
31
+ def fecha_coincide?(dia_str, mes_str, año_str, fecha_coincidente = nil, tipo_fecha = "nacimiento", msg = [])
32
+ errores = false
33
+ begin
34
+ if Date.valid_date?(año_str.to_i, mes_str.to_i, dia_str.to_i)
35
+ unless fecha_coincidente.nil?
36
+ fn = Date.parse("#{año_str}-#{mes_str}-#{dia_str}")
37
+ unless fn.year == fecha_coincidente.year and fn.month == fecha_coincidente.month and fn.day == fecha_coincidente.day
38
+ errores = true
39
+ msg << "La fecha de #{tipo_fecha} no coincide con la fecha de #{tipo_fecha} proporcionada."
40
+ end
41
+ end
42
+ else
43
+ errores = true
44
+ msg << "La fecha de #{tipo_fecha} es incorrecta."
45
+ end
46
+ rescue
47
+ errores = true
48
+ msg << "La fecha de #{tipo_fecha} está mal formada."
49
+ end
50
+ return !errores
51
+ end
52
+ end
53
+
54
+ def self.included(base)
55
+ base.extend ClassMethods
56
+ end
57
+
58
+ end
@@ -0,0 +1,6 @@
1
+ # encoding: utf-8
2
+ module MX
3
+ module ID
4
+ VERSION = "0.0.1.pre"
5
+ end
6
+ end
@@ -0,0 +1,45 @@
1
+ module NumeroRomano
2
+ @digitos_base = {
3
+ 1 => 'I',
4
+ 4 => 'IV',
5
+ 5 => 'V',
6
+ 9 => 'IX',
7
+ 10 => 'X',
8
+ 40 => 'XL',
9
+ 50 => 'L',
10
+ 90 => 'XC',
11
+ 100 => 'C',
12
+ 400 => 'CD',
13
+ 500 => 'D',
14
+ 900 => 'CM',
15
+ 1000 => 'M'
16
+ }
17
+
18
+ def self.a_romano valor
19
+ resultado = ''
20
+ @digitos_base.keys.reverse.each do |decimal|
21
+ while valor >= decimal
22
+ valor -= decimal
23
+ resultado += @digitos_base[decimal]
24
+ end
25
+ end
26
+ resultado
27
+ end
28
+
29
+ def self.a_decimal valor
30
+ valor = valor.upcase
31
+ resultado = 0
32
+ @digitos_base.values.reverse.each do |romano|
33
+ while valor.start_with? romano
34
+ valor = valor.slice(romano.length, valor.length)
35
+ resultado += @digitos_base.key romano
36
+ end
37
+ end
38
+ resultado
39
+ end
40
+
41
+ def self.romano? valor
42
+ valor = valor.upcase
43
+ !(valor.scan(/^M{0,3}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$/).empty?)
44
+ end
45
+ end
@@ -0,0 +1,415 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ describe MX::ID::RFC, :rfc do
4
+
5
+ describe ".persona_fisica" do
6
+ describe "Regla 4ª" do
7
+ context "cuando el apellido paterno de la persona física se componga de una letra" do
8
+ it "es la primera letra del apellido paterno, la primera letra del apellido materno y la a primera y segunda letra del nombre" do
9
+ nombres = "ALVARO"
10
+ apellido_paterno = "DE LA O"
11
+ apellido_materno = "LOZANO"
12
+ fecha_nacimiento = Date.new(1940, 12, 1)
13
+ expect(described_class.persona_fisica(nombres, apellido_paterno, apellido_materno, fecha_nacimiento)).to eq "OLAL401201R99"
14
+ end
15
+ end
16
+
17
+ context "cuando el apellido paterno de la persona física se componga de dos letras" do
18
+ it "es la primera letra del apellido paterno, la primera letra del apellido materno y la a primera y segunda letra del nombre" do
19
+ nombres = "ERNESTO"
20
+ apellido_paterno = "EK"
21
+ apellido_materno = "RIVERA"
22
+ fecha_nacimiento = Date.new(1907, 11, 20)
23
+ expect(described_class.persona_fisica(nombres, apellido_paterno, apellido_materno, fecha_nacimiento)).to eq "ERER0711209E3"
24
+ end
25
+ end
26
+ end
27
+
28
+ describe "Regla 7ª: casos en que la persona física tenga un solo apellido" do
29
+ context "cuando el apellido paterno está en blanco" do
30
+ it "es la primera y segunda letras del apellido materno, más la primera y segunda letras del nombre" do
31
+ nombres = "GERARDO"
32
+ apellido_paterno = ""
33
+ apellido_materno = "ZAFRA"
34
+ fecha_nacimiento = Date.new(1925, 11, 15)
35
+ expect(described_class.persona_fisica(nombres, apellido_paterno, apellido_materno, fecha_nacimiento)).to eq "ZAGE251115EK7"
36
+ end
37
+ end
38
+
39
+ context "cuando el apellido materno está en blanco" do
40
+ it "es la primera y segunda letras del apellido paterno, más la primera y segunda letras del nombre" do
41
+ nombres = "JUAN"
42
+ apellido_paterno = "MARTINEZ"
43
+ apellido_materno = ""
44
+ fecha_nacimiento = Date.new(1942, 1, 16)
45
+ expect(described_class.persona_fisica(nombres, apellido_paterno, apellido_materno, fecha_nacimiento)).to eq "MAJU420116BP3"
46
+ end
47
+ end
48
+ end
49
+
50
+ describe "Regla 10ª: casos en los que aparezcan formando parte del nombre, apellido paterno y apellido materno los caracteres especiales" do
51
+ context "cuando están en forma individual dentro del nombre" do
52
+ it "se interpretan los caracteres especiales" do
53
+ nombres = "LUZ MA."
54
+ apellido_paterno = "FERNANDEZ"
55
+ apellido_materno = "JUAREZ"
56
+ fecha_nacimiento = Date.new(1983, 1, 20)
57
+ expect(described_class.persona_fisica(nombres, apellido_paterno, apellido_materno, fecha_nacimiento)).to eq "FEJL8301207E3"
58
+ end
59
+ end
60
+
61
+ context "cuando están en forma individual dentro del apellido paterno" do
62
+ it "se interpretan los caracteres especiales" do
63
+ nombres = "RUBEN"
64
+ apellido_paterno = "D'ANGELO"
65
+ apellido_materno = "FARGO"
66
+ fecha_nacimiento = Date.new(1971, 1, 8)
67
+ expect(described_class.persona_fisica(nombres, apellido_paterno, apellido_materno, fecha_nacimiento)).to eq "DAFR7101081P4"
68
+ end
69
+ end
70
+ end
71
+
72
+ it 'RUAP791104413' do
73
+ nombres = "PABLO JAVIER"
74
+ apellido_paterno = "RUIZ"
75
+ apellido_materno = "ABRIN"
76
+ fecha_nacimiento = Date.new(1979, 11, 4)
77
+ expect(described_class.persona_fisica(nombres, apellido_paterno, apellido_materno, fecha_nacimiento)).to eq "RUAP791104413"
78
+ end
79
+
80
+ it 'LIOA800822N4A' do
81
+ nombres = "JOSE ANGEL"
82
+ apellido_paterno = "LINARES"
83
+ apellido_materno = "ORRALA"
84
+ fecha_nacimiento = Date.new(1980, 8, 22)
85
+ expect(described_class.persona_fisica(nombres, apellido_paterno, apellido_materno, fecha_nacimiento)).to eq "LIOA800822N4A"
86
+ end
87
+
88
+ it 'IXCA8008222H4' do
89
+ nombres = "ANDRES"
90
+ apellido_paterno = "ICH"
91
+ apellido_materno = "CHEM"
92
+ fecha_nacimiento = Date.new(1980, 8, 22)
93
+ expect(described_class.persona_fisica(nombres, apellido_paterno, apellido_materno, fecha_nacimiento)).to eq "IXCA8008222H4"
94
+ end
95
+ end
96
+
97
+ describe ".persona_moral" do
98
+ describe 'Regla 4ª' do
99
+ context "cuando la denominación o razón social esté compuesta sólo de iniciales" do
100
+ it 'FAZ110304UT4' do
101
+ razon_social = "F.A.Z. SA DE CV"
102
+ fecha_constitucion = Date.new(2011, 3, 4)
103
+ expect(described_class.persona_moral(razon_social, fecha_constitucion)).to eq "FAZ110304ET3"
104
+ end
105
+
106
+ it 'USR110304UT4' do
107
+ razon_social = "U.S. ROBOTICS SA DE CV"
108
+ fecha_constitucion = Date.new(2011, 3, 4)
109
+ expect(described_class.persona_moral(razon_social, fecha_constitucion)).to eq "USR110304S80"
110
+ end
111
+
112
+ it 'HPM841221L9A' do
113
+ razon_social = "H. PRIETO Y MARTINEZ S DE RL"
114
+ fecha_constitucion = Date.new(1984, 12, 21)
115
+ expect(described_class.persona_moral(razon_social, fecha_constitucion)).to eq "HPM841221L9A"
116
+ end
117
+ end
118
+ end
119
+
120
+ describe 'Regla 6ª' do
121
+ context 'Cuando la denominación o razón social se comprende de dos elementos' do
122
+ it 'Para efectos de la conformación de la clave, se tomará la letra inicial de la primera palabra y las dos primeras letras de la segunda' do
123
+ razon_social = "OPERATIVO EVENPLAN SC"
124
+ fecha_constitucion = Date.new(1999, 7, 15)
125
+ expect(described_class.persona_moral(razon_social, fecha_constitucion)).to eq "OEV990715MMA"
126
+ end
127
+ end
128
+ end
129
+
130
+ describe 'Regla 7ª' do
131
+ context 'Cuando la denominación o razón social se compone de un solo elemento' do
132
+ it 'Para efectos de conformación de la clave, se tomarán las tres primeras letras consecutivas del mismo' do
133
+ razon_social = "YOMERO SC"
134
+ fecha_constitucion = Date.new(20011, 7, 15)
135
+ expect(described_class.persona_moral(razon_social, fecha_constitucion)).to eq "YOM110715PR3"
136
+ end
137
+ end
138
+ end
139
+
140
+ describe 'Regla 8ª' do
141
+ context 'Cuando la denominación o razón social se componga de un solo elemento y sus letras no completen las tres requeridas' do
142
+ it 'Para efectos de conformación de la clave, se tomaran las empleadas por el contribuyente y las restantes se suplirán con una “X”' do
143
+ razon_social = "YO SC"
144
+ fecha_constitucion = Date.new(20011, 7, 15)
145
+ expect(described_class.persona_moral(razon_social, fecha_constitucion)).to eq "YOX110715NJ9"
146
+ end
147
+ end
148
+ end
149
+
150
+ describe 'Regla 10ª' do
151
+ context 'Cuando la denominación o razón social contenga en algún o en sus tres primeros elementos números arábigos, o números romanos' do
152
+ context 'se sustituyen los números romanos por números en letra' do
153
+ it 'ESV841221GB1' do
154
+ razon_social = "EDITORIAL SIGLO XXI SA DE CV"
155
+ fecha_constitucion = Date.new(1984, 12, 21)
156
+ expect(described_class.persona_moral(razon_social, fecha_constitucion)).to eq "ESV841221GB1"
157
+ end
158
+ end
159
+
160
+ context 'se sustituyen los números por números en letra' do
161
+ it 'DOC841221R87' do
162
+ razon_social = "EL 12 SA"
163
+ fecha_constitucion = Date.new(1984, 12, 21)
164
+ expect(described_class.persona_moral(razon_social, fecha_constitucion)).to eq "DOC841221R87"
165
+ end
166
+ end
167
+ end
168
+ end
169
+
170
+ describe 'Regla 12ª' do
171
+ context 'Cuando aparezcan formando parte de la denominación o razón social los caracteres especiales' do
172
+ context 'Cuando deben de excluirse para el cálculo del homónimo y del dígito verificador' do
173
+ context 'Cuando están en forma individual dentro del texto de la denominación o razón social (Anexo VI)' do
174
+ it 'SND861121BW5' do
175
+ razon_social = "LA S@NDIA SA DE CV"
176
+ fecha_constitucion = Date.new(1986, 11, 21)
177
+ expect(described_class.persona_moral(razon_social, fecha_constitucion)).to eq "SND861121BW5"
178
+ end
179
+
180
+ it 'ACO861121BW5' do
181
+ razon_social = "@ COMER SA DE CV"
182
+ fecha_constitucion = Date.new(1986, 11, 21)
183
+ expect(described_class.persona_moral(razon_social, fecha_constitucion)).to eq "ACO861121N51"
184
+ end
185
+
186
+ it 'DSU861121CL5' do
187
+ razon_social = "LA / DEL SUR SA"
188
+ fecha_constitucion = Date.new(1986, 11, 21)
189
+ expect(described_class.persona_moral(razon_social, fecha_constitucion)).to eq "DSU861121CL5"
190
+ end
191
+ end
192
+ end
193
+ end
194
+ end
195
+
196
+ it 'CSP020827Q18' do
197
+ razon_social = "CONSULTORIA Y SERVICIOS PETROLEROS SA DE CV"
198
+ fecha_constitucion = Date.new(2002, 8, 27)
199
+ expect(described_class.persona_moral(razon_social, fecha_constitucion)).to eq "CSP020827Q18"
200
+ end
201
+
202
+ it 'MTS110304UT4' do
203
+ razon_social = "MAQUECH TECHNOLOGY SERVICES SA DE CV"
204
+ fecha_constitucion = Date.new(2011, 3, 4)
205
+ expect(described_class.persona_moral(razon_social, fecha_constitucion)).to eq "MTS110304UT4"
206
+ end
207
+ end
208
+
209
+ describe ".valido?" do
210
+ context "la cadena dada es nil" do
211
+ let!(:msgs){ "" }
212
+ let!(:respuesta){ described_class.valido?(nil, nil, msgs) }
213
+
214
+ it "false" do
215
+ expect(respuesta).to be_falsey
216
+ end
217
+
218
+ it "mensaje debe ser 'No debe estar vacío.'" do
219
+ expect(msgs).to eq "No debe estar vacío."
220
+ end
221
+ end
222
+
223
+ context "la cadena dada es la cadena vacía" do
224
+ let!(:msgs){ "" }
225
+ let!(:respuesta){ described_class.valido?("", nil, msgs) }
226
+
227
+ it "false" do
228
+ expect(respuesta).to be_falsey
229
+ end
230
+
231
+ it "mensaje debe ser 'No debe estar vacío.'" do
232
+ expect(msgs).to eq "No debe estar vacío."
233
+ end
234
+ end
235
+
236
+ context "cuando es un RFC inválido" do
237
+ context "cuando las iniciales son incorrectas" do
238
+ context "cuando la fecha de nacimiento proporcionada es nil" do
239
+ let!(:msgs){ "" }
240
+ let!(:respuesta){ described_class.valido?("R12A791504413", nil, msgs) }
241
+ it "false" do
242
+ expect(respuesta).to be_falsey
243
+ end
244
+
245
+ it "mensaje debe ser 'No tiene el formato correcto.'" do
246
+ expect(msgs).to eq "No tiene el formato correcto."
247
+ end
248
+ end
249
+ end
250
+
251
+ context "cuando la fecha es incorrecta" do
252
+ context "cuando la fecha de nacimiento proporcionada es nil" do
253
+ let!(:msgs){ "" }
254
+ let!(:respuesta){ described_class.valido?("RUAP791504411", nil, msgs) }
255
+ it "false" do
256
+ expect(respuesta).to be_falsey
257
+ end
258
+
259
+ it "mensaje debe ser 'La fecha de nacimiento es incorrecta.'" do
260
+ expect(msgs).to eq "La fecha de nacimiento es incorrecta."
261
+ end
262
+ end
263
+
264
+ context "cuando la fecha de nacimiento proporcionada no coincide" do
265
+ let!(:msgs){ "" }
266
+ let!(:respuesta){ described_class.valido?("RUAP79110541A", Date.new(1979, 11, 04), msgs) }
267
+ it "false" do
268
+ expect(respuesta).to be_falsey
269
+ end
270
+
271
+ it "mensaje debe ser 'La fecha de nacimiento no coincide con la fecha de nacimiento proporcionada.'" do
272
+ expect(msgs).to eq "La fecha de nacimiento no coincide con la fecha de nacimiento proporcionada."
273
+ end
274
+ end
275
+ end
276
+ end
277
+
278
+ context "cuando es un RFC válido" do
279
+ context "cuando es de persona moral" do
280
+ let!(:msgs){ "" }
281
+ let!(:respuesta){ described_class.valido?("MTS110304UT4", nil, msgs, false) }
282
+ it "true" do
283
+ expect(respuesta).to be_truthy
284
+ end
285
+
286
+ it "mensaje debe estar en blanco" do
287
+ expect(msgs).to eq ""
288
+ end
289
+
290
+ context "cuando las iniciales son caracteres especiales" do
291
+ let!(:msgs){ "" }
292
+ let!(:respuesta){ described_class.valido?("Ñ&P791104410", nil, msgs, false) }
293
+ it "true" do
294
+ expect(respuesta).to be_truthy
295
+ end
296
+
297
+ it "mensaje debe estar en blanco" do
298
+ expect(msgs).to eq ""
299
+ end
300
+ end
301
+
302
+ context "cuando la fecha de constitución proporcionada es nil" do
303
+ let!(:msgs){ "" }
304
+ let!(:respuesta){ described_class.valido?("MTS110304UT4", nil, msgs, false) }
305
+ it "true" do
306
+ expect(respuesta).to be_truthy
307
+ end
308
+
309
+ it "mensaje debe estar en blanco" do
310
+ expect(msgs).to eq ""
311
+ end
312
+ end
313
+
314
+ context "cuando la fecha de constitución proporcionada no coincide" do
315
+ let!(:msgs){ "" }
316
+ let!(:respuesta){ described_class.valido?("MTS110304UT4", Date.new(1979, 12, 04), msgs, false) }
317
+ it "false" do
318
+ expect(respuesta).to be_falsey
319
+ end
320
+
321
+ it "mensaje debe ser 'La fecha de constitución no coincide con la fecha de constitución proporcionada.'" do
322
+ expect(msgs).to eq "La fecha de constitución no coincide con la fecha de constitución proporcionada."
323
+ end
324
+ end
325
+
326
+ context "cuando la fecha de constitución proporcionada coincide" do
327
+ let!(:msgs){ "" }
328
+ let!(:respuesta){ described_class.valido?("MTS110304UT4", Date.new(2011, 03, 04), msgs, false) }
329
+ it "true" do
330
+ expect(respuesta).to be_truthy
331
+ end
332
+
333
+ it "mensaje debe estar en blanco" do
334
+ expect(msgs).to eq ""
335
+ end
336
+ end
337
+
338
+ context 'cuando el dígito verificador es incorrecto' do
339
+ let!(:msgs){ "" }
340
+ let!(:respuesta){ described_class.valido?("MTS110304UT5", Date.new(2011, 03, 04), msgs, false) }
341
+ it "false" do
342
+ expect(respuesta).to be_falsey
343
+ end
344
+
345
+ it "mensaje debe ser 'El dígito verificador es incorrecto.'" do
346
+ expect(msgs).to eq "El dígito verificador es incorrecto."
347
+ end
348
+ end
349
+ end
350
+
351
+ context "cuando es de persona física" do
352
+ let!(:msgs){ "" }
353
+ let!(:respuesta){ described_class.valido?("RUAP791104413", nil, msgs) }
354
+ it "true" do
355
+ expect(respuesta).to be_truthy
356
+ end
357
+
358
+ it "mensaje debe estar en blanco" do
359
+ expect(msgs).to eq ""
360
+ end
361
+
362
+ context "cuando la fecha de nacimiento proporcionada es nil" do
363
+ let!(:msgs){ "" }
364
+ let!(:respuesta){ described_class.valido?("RUAP791104413", nil, msgs) }
365
+ it "true" do
366
+ expect(respuesta).to be_truthy
367
+ end
368
+
369
+ it "mensaje debe estar en blanco" do
370
+ expect(msgs).to eq ""
371
+ end
372
+ end
373
+
374
+ context "cuando la fecha de nacimiento proporcionada no coincide" do
375
+ let!(:msgs){ "" }
376
+ let!(:respuesta){ described_class.valido?("RUAP791104413", Date.new(1979, 12, 04), msgs) }
377
+ it "false" do
378
+ expect(respuesta).to be_falsey
379
+ end
380
+
381
+ it "mensaje debe ser 'La fecha de nacimiento no coincide con la fecha de nacimiento proporcionada.'" do
382
+ expect(msgs).to eq "La fecha de nacimiento no coincide con la fecha de nacimiento proporcionada."
383
+ end
384
+ end
385
+
386
+ context "cuando la fecha de nacimiento proporcionada coincide" do
387
+ let!(:msgs){ "" }
388
+ let!(:respuesta){ described_class.valido?("RUAP791104413", Date.new(1979, 11, 04), msgs) }
389
+ it "true" do
390
+ expect(respuesta).to be_truthy
391
+ end
392
+
393
+ it "mensaje debe estar en blanco" do
394
+ expect(msgs).to eq ""
395
+ end
396
+ end
397
+ end
398
+
399
+
400
+ end
401
+
402
+ context "cuando el formato del RFC es inválido" do
403
+ let!(:msgs){ "" }
404
+ let!(:respuesta){ described_class.valido?("RUAP791104", nil, msgs) }
405
+ it "false" do
406
+ expect(respuesta).to be_falsey
407
+ end
408
+
409
+ it "mensaje debe ser 'No tiene la longitud correcta (13 caracteres).'" do
410
+ expect(msgs).to eq "No tiene la longitud correcta (13 caracteres)."
411
+ end
412
+ end
413
+ end
414
+
415
+ end