facturacr 0.1.4 → 1.0
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/README.md +11 -10
- data/facturacr.gemspec +8 -8
- data/lib/facturacr.rb +1 -0
- data/lib/facturacr/api.rb +6 -2
- data/lib/facturacr/builder.rb +7 -1
- data/lib/facturacr/cli.rb +16 -29
- data/lib/facturacr/cli/generate.rb +9 -6
- data/lib/facturacr/data_provider.rb +21 -0
- data/lib/facturacr/document.rb +1 -0
- data/lib/facturacr/document/exoneration.rb +7 -5
- data/lib/facturacr/document/item.rb +2 -2
- data/lib/facturacr/document/tax.rb +5 -1
- data/lib/facturacr/reception_message.rb +25 -22
- data/lib/facturacr/signed_document.rb +10 -8
- data/lib/facturacr/signer/signer.rb +149 -119
- data/lib/facturacr/version.rb +1 -1
- data/lib/facturacr/xml_document.rb +155 -150
- data/resources/data.yml +2 -2
- data/resources/test.p12 +0 -0
- data/resources/test.sign.crt +31 -0
- data/resources/test.sign.key +52 -0
- data/resources/test.sign.pem +83 -0
- metadata +36 -32
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: db381bbaa82171a178d543ba768b109dda40ce9b
|
4
|
+
data.tar.gz: 3dd2171473e12c9f578c9d21d12d18fe600d587d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 86db7abd0fc67508f335f56de8d561a7fdbc7bc55147821a2bb07c919f3d2f7e0d5159d6edcf2e971c9914677f11d4d58e1c6b50e533a6b669d028ea220252db
|
7
|
+
data.tar.gz: f16d24d241f22cc0e70d4672d46528dffbbe1b6e7fb85d21add0754635658c2d39341de002aff4192a0128ce9130db47c4ca0376d01c3e689431387a83bedf93
|
data/README.md
CHANGED
@@ -5,7 +5,7 @@ Esta librería implementa los procesos de facturación electrónica del Minister
|
|
5
5
|
Actualmente cuenta con las siguientes características:
|
6
6
|
|
7
7
|
- Generación de XML
|
8
|
-
- Firmado de XML (
|
8
|
+
- Firmado de XML (XADES-EPES en ruby y java)
|
9
9
|
- Comunicación con el API del ministerio de hacienda
|
10
10
|
- Línea de comando para realizar los procesos
|
11
11
|
|
@@ -71,13 +71,20 @@ FE.configure do |config|
|
|
71
71
|
end
|
72
72
|
```
|
73
73
|
|
74
|
-
Para firmar documentos
|
74
|
+
Para firmar documentos, existen dos métodos:
|
75
|
+
-Con java, se invoca un JAR con 4 argumentos. Este método es muy lento debido a que el proceso principal ejecuta el jar en otro proceso. Fue la primera implementación mientras se desarrollaba la implementación nativa en Ruby.
|
75
76
|
```ruby
|
76
|
-
|
77
77
|
signer = FE::JavaSigner.new FE.configuration.key_path, FE.configuration.key_password, "/path/to/unsigned.xml", "/path/to/signed.xml"
|
78
78
|
signer.sign
|
79
79
|
```
|
80
|
-
|
80
|
+
-La implementación nativa en ruby:
|
81
|
+
```ruby
|
82
|
+
xml_provider = FE::DataProvider.new :string, "<?xml version="1.0"?><FacturaElectronica> ... </FacturaElectornica>"
|
83
|
+
key_provider = FE::DataProvider.new :file, FE.configuration.key_path
|
84
|
+
signer = FE::Signer.new xml_provider: xml_provider, key_provider: key_provider, pin: FE.configuration.key_password, output_path: "/path/to/signed.xml"
|
85
|
+
signer.sign
|
86
|
+
```
|
87
|
+
Esta implementación permite además evitar la lectura y escritura de archivos en el disco duro, lo que permite realizar el firmado de manera mucho más rápida.
|
81
88
|
|
82
89
|
Para enviar documentos al API
|
83
90
|
```ruby
|
@@ -169,12 +176,6 @@ Para enviar documentos
|
|
169
176
|
|
170
177
|
$ facturacr send_document /path/to/signed.xml
|
171
178
|
|
172
|
-
## To Do
|
173
|
-
|
174
|
-
- Mejorar y extender la generación de XML
|
175
|
-
- Implemntar un mapeo más sencillo para generación de XML
|
176
|
-
- Implementar Aceptación y Rechazo
|
177
|
-
- Finalizar el firmador en ruby
|
178
179
|
|
179
180
|
## Development
|
180
181
|
|
data/facturacr.gemspec
CHANGED
@@ -19,13 +19,13 @@ Gem::Specification.new do |spec|
|
|
19
19
|
|
20
20
|
spec.add_development_dependency "bundler", "~> 1.10"
|
21
21
|
spec.add_development_dependency "rake", "~> 10.0"
|
22
|
-
spec.add_development_dependency "minitest"
|
23
|
-
spec.add_development_dependency "minitest-colorize"
|
22
|
+
spec.add_development_dependency "minitest", '~> 5.11'
|
23
|
+
spec.add_development_dependency "minitest-colorize", '~> 0.0'
|
24
24
|
|
25
|
-
spec.add_dependency 'rest-client'
|
26
|
-
spec.add_dependency 'nokogiri'
|
27
|
-
spec.add_dependency 'colorize'
|
28
|
-
spec.add_dependency 'thor'
|
29
|
-
spec.add_dependency 'activemodel'
|
30
|
-
spec.add_dependency 'awesome_print'
|
25
|
+
spec.add_dependency 'rest-client', '~> 2.0'
|
26
|
+
spec.add_dependency 'nokogiri', '~> 1.8'
|
27
|
+
spec.add_dependency 'colorize', '~> 0.8'
|
28
|
+
spec.add_dependency 'thor', '~> 0.20'
|
29
|
+
spec.add_dependency 'activemodel', '>= 3.2'
|
30
|
+
spec.add_dependency 'awesome_print', '~> 1.8'
|
31
31
|
end
|
data/lib/facturacr.rb
CHANGED
data/lib/facturacr/api.rb
CHANGED
@@ -7,7 +7,7 @@ require 'json'
|
|
7
7
|
module FE
|
8
8
|
class Api
|
9
9
|
|
10
|
-
attr_accessor :authentication_endpoint, :document_endpoint, :username, :password, :client_id, :errors
|
10
|
+
attr_accessor :authentication_endpoint, :document_endpoint, :username, :password, :client_id, :errors, :check_location
|
11
11
|
|
12
12
|
def initialize(configuration = nil)
|
13
13
|
@authentication_endpoint = (configuration || FE.configuration).authentication_endpoint
|
@@ -32,7 +32,11 @@ module FE
|
|
32
32
|
def send_document(payload)
|
33
33
|
authenticate
|
34
34
|
response = RestClient.post "#{@document_endpoint}/recepcion", payload.to_json, {:Authorization=> "bearer #{@token}", content_type: :json}
|
35
|
-
|
35
|
+
if response.code.eql?(200) || response.code.eql?(202)
|
36
|
+
@check_location = response.headers[:location]
|
37
|
+
puts "CheckLocation: #{@check_location}"
|
38
|
+
return true
|
39
|
+
end
|
36
40
|
rescue => e
|
37
41
|
@errors[:request] = {message: e.message, response: e.response}
|
38
42
|
return false
|
data/lib/facturacr/builder.rb
CHANGED
@@ -92,7 +92,12 @@ module FE
|
|
92
92
|
taxes = []
|
93
93
|
if txs.is_a?(Array) && txs.first.is_a?(Hash)
|
94
94
|
txs.each do |t|
|
95
|
-
|
95
|
+
exo = t.delete(:exoneration)
|
96
|
+
if exo && exo.is_a?(Hash)
|
97
|
+
t[:exoneration] = FE::Document::Exoneration.new(exo)
|
98
|
+
end
|
99
|
+
|
100
|
+
taxes << FE::Document::Tax.new(t)
|
96
101
|
end
|
97
102
|
else
|
98
103
|
taxes = txs
|
@@ -258,5 +263,6 @@ module FE
|
|
258
263
|
FE::Document::Reference.new args
|
259
264
|
end
|
260
265
|
|
266
|
+
|
261
267
|
end
|
262
268
|
end
|
data/lib/facturacr/cli.rb
CHANGED
@@ -3,29 +3,7 @@ require 'awesome_print'
|
|
3
3
|
require 'facturacr'
|
4
4
|
require 'facturacr/cli/generate'
|
5
5
|
require 'fileutils'
|
6
|
-
=begin
|
7
|
-
require 'facturacr/document'
|
8
|
-
require 'facturacr/document/fax'
|
9
|
-
require 'facturacr/document/identification_document'
|
10
|
-
require 'facturacr/document/issuer'
|
11
|
-
require 'facturacr/document/receiver'
|
12
|
-
require 'facturacr/document/location'
|
13
|
-
require 'facturacr/document/phone_type'
|
14
|
-
require 'facturacr/document/phone'
|
15
|
-
require 'facturacr/document/item'
|
16
|
-
require 'facturacr/document/tax'
|
17
|
-
require 'facturacr/document/summary'
|
18
|
-
require 'facturacr/document/regulation'
|
19
|
-
require 'facturacr/document/reference'
|
20
6
|
|
21
|
-
require 'facturacr/invoice'
|
22
|
-
require 'facturacr/credit_note'
|
23
|
-
require 'facturacr/signer/signer'
|
24
|
-
require 'facturacr/api'
|
25
|
-
require 'facturacr/signed_document'
|
26
|
-
require 'facturacr/builder'
|
27
|
-
require 'facturacr/xml_document'
|
28
|
-
=end
|
29
7
|
module FE
|
30
8
|
|
31
9
|
module Utils
|
@@ -56,28 +34,37 @@ module FE
|
|
56
34
|
desc "sign XML_IN XML_OUT", "signs the xml document and stores the signed document in the output path"
|
57
35
|
method_option :config_file, aliases: '-c', desc: "default configuration file", default: "tmp/config.yml"
|
58
36
|
def sign(xml_in, xml_out)
|
37
|
+
start = Time.now
|
59
38
|
FE::Utils.configure(options[:config_file])
|
60
|
-
|
39
|
+
|
40
|
+
key_provider = FE::DataProvider.new(:file, FE.configuration.key_path)
|
41
|
+
document_provider = FE::DataProvider.new(:file, xml_in)
|
42
|
+
signer_args = {xml_provider: document_provider, key_provider: key_provider, pin: FE.configuration.key_password, output_path: xml_out }
|
43
|
+
signer = FE::Signer.new signer_args
|
61
44
|
signer.sign
|
45
|
+
puts "Signature: #{Time.now - start} sec.".blue
|
62
46
|
end
|
63
47
|
|
64
48
|
desc "send_document SIGNED_XML", "sends the SIGNED_XML file to the API"
|
65
49
|
method_option :config_file, aliases: '-c', desc: "default configuration file", default: "tmp/config.yml"
|
66
50
|
def send_document(path)
|
67
51
|
FE::Utils.configure(options[:config_file])
|
68
|
-
xml_document = FE::XmlDocument.new(path)
|
52
|
+
xml_document = FE::XmlDocument.new(DataProvider.new :file, path)
|
69
53
|
document = xml_document.document
|
70
|
-
if document.is_a?(FE::ReceptionMessage)
|
71
|
-
document.receiver_id_type = "02"
|
72
|
-
end
|
73
54
|
signed_document = FE::SignedDocument.new(document,path)
|
74
55
|
api = FE::Api.new
|
75
|
-
|
56
|
+
payload = signed_document.payload
|
57
|
+
if api.send_document(payload)
|
76
58
|
puts "Document Sent".green
|
77
59
|
puts "KEY: #{document.key}"
|
78
60
|
puts "Wait 5 seconds before check..."
|
79
61
|
sleep 5
|
80
|
-
|
62
|
+
if document.is_a?(FE::ReceptionMessage)
|
63
|
+
check_key = api.check_location.split("/").last
|
64
|
+
else
|
65
|
+
check_key = document.key
|
66
|
+
end
|
67
|
+
invoke :check, [check_key], :config_file=>options[:config_file]
|
81
68
|
else
|
82
69
|
puts "ERROR".red
|
83
70
|
ap api.errors
|
@@ -11,6 +11,7 @@ module FE
|
|
11
11
|
method_option :data_path, default: "tmp/data.yml"
|
12
12
|
method_option :output_path, desc: "path to save the output"
|
13
13
|
def invoice
|
14
|
+
start = Time.now
|
14
15
|
data = YAML.load_file(options[:data_path]).with_indifferent_access
|
15
16
|
builder = FE::Builder.new
|
16
17
|
|
@@ -27,6 +28,8 @@ module FE
|
|
27
28
|
write(invoice, output_path)
|
28
29
|
print_details(invoice)
|
29
30
|
sign(output_path, options) if options[:sign]
|
31
|
+
end_at = Time.now
|
32
|
+
puts "Total Time: #{end_at - start} sec."
|
30
33
|
send_document("#{output_path}.signed.xml") if options[:sign] && options[:send]
|
31
34
|
|
32
35
|
end
|
@@ -140,7 +143,7 @@ module FE
|
|
140
143
|
method_option :document_situation, desc: "the situation of the document", default: "1"
|
141
144
|
method_option :config_file, aliases: '-c', desc: "default configuration file", default: "tmp/config.yml"
|
142
145
|
def reception_message
|
143
|
-
doc = XmlDocument.new(options[:xml_in])
|
146
|
+
doc = XmlDocument.new(DataProvider.new(:file, options[:xml_in]))
|
144
147
|
|
145
148
|
builder = FE::Builder.new
|
146
149
|
|
@@ -150,17 +153,17 @@ module FE
|
|
150
153
|
key: doc.document.key,
|
151
154
|
date: doc.document.date,
|
152
155
|
number: options[:number],
|
153
|
-
issuer_id_number: doc.document.
|
154
|
-
issuer_id_type: doc.document.
|
155
|
-
receiver_id_number: doc.document.
|
156
|
-
receiver_id_type: doc.document.
|
156
|
+
issuer_id_number: doc.document.issuer.identification_document.id_number,
|
157
|
+
issuer_id_type: doc.document.issuer.identification_document.document_type,
|
158
|
+
receiver_id_number: doc.document.receiver.identification_document.id_number,
|
159
|
+
receiver_id_type: doc.document.receiver.identification_document.document_type,
|
157
160
|
message: options[:action],
|
158
161
|
tax: doc.document.summary.tax_total,
|
159
162
|
total: doc.document.summary.net_total,
|
160
163
|
document_situation: options[:document_situation]
|
161
164
|
})
|
162
165
|
|
163
|
-
message.security_code =
|
166
|
+
message.security_code = 8.times.map{ rand(0..9) }.join
|
164
167
|
if options[:output_path]
|
165
168
|
output_path = options[:output_path]
|
166
169
|
else
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module FE
|
2
|
+
|
3
|
+
class DataProvider
|
4
|
+
SOURCES = [:string, :file]
|
5
|
+
|
6
|
+
attr_accessor :contents
|
7
|
+
|
8
|
+
def initialize(source, data)
|
9
|
+
source = source.to_s.to_sym
|
10
|
+
raise ArgumentError, "source (#{source}) is not valid" if !SOURCES.include?(source)
|
11
|
+
raise ArgumentError, "#{data} does not exist" if soruce.eql?(:file) && !File.exists?(data)
|
12
|
+
|
13
|
+
if source.eql?(:string)
|
14
|
+
@contents = data
|
15
|
+
elsif source.eql?(:file)
|
16
|
+
@contents = File.read(data)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
data/lib/facturacr/document.rb
CHANGED
@@ -12,7 +12,7 @@ module FE
|
|
12
12
|
"05" => "Zonas Francas",
|
13
13
|
"99" => "Otros"
|
14
14
|
}
|
15
|
-
attr_accessor :document_type, :document_number, :institution, :date, :total_tax, :percentage
|
15
|
+
attr_accessor :document_type, :document_number, :institution, :date, :total_tax, :percentage, :net_total
|
16
16
|
|
17
17
|
validates :document_type, presence: true, inclusion: DOCUMENT_TYPES.keys
|
18
18
|
validates :document_number, presence: true
|
@@ -25,9 +25,11 @@ module FE
|
|
25
25
|
@document_type = args[:document_type]
|
26
26
|
@document_number = args[:document_number]
|
27
27
|
@institution = args[:institution]
|
28
|
-
@date = args[:date]
|
28
|
+
@date = args[:date]
|
29
29
|
@total_tax = args[:total_tax]
|
30
|
-
|
30
|
+
if args[:net_total].present?
|
31
|
+
@percentage = ((@total_tax / args[:net_total].to_f)*100).to_i
|
32
|
+
end
|
31
33
|
end
|
32
34
|
|
33
35
|
def build_xml(node)
|
@@ -35,10 +37,10 @@ module FE
|
|
35
37
|
node = Nokogiri::XML::Builder.new if node.nil?
|
36
38
|
|
37
39
|
node.Exoneracion do |xml|
|
38
|
-
xml.
|
40
|
+
xml.TipoDocumento @document_type
|
39
41
|
xml.NumeroDocumento @document_number
|
40
42
|
xml.NombreInstitucion @institution
|
41
|
-
xml.FechaEmision @date
|
43
|
+
xml.FechaEmision @date.xmlschema
|
42
44
|
xml.MontoImpuesto @total_tax
|
43
45
|
xml.PorcentajeCompra @percentage
|
44
46
|
end
|
@@ -4,7 +4,7 @@ module FE
|
|
4
4
|
include ActiveModel::Validations
|
5
5
|
|
6
6
|
attr_accessor :line_number, :code, :quantity, :unit, :description, :unit_price, :total,
|
7
|
-
:discount, :discount_reason, :subtotal, :taxes, :
|
7
|
+
:discount, :discount_reason, :subtotal, :taxes, :net_total
|
8
8
|
|
9
9
|
validates :line_number, presence: true
|
10
10
|
validates :quantity, presence: true, numericality: {greater_than: 0}
|
@@ -49,7 +49,7 @@ module FE
|
|
49
49
|
x.Detalle @description
|
50
50
|
x.PrecioUnitario @unit_price
|
51
51
|
x.MontoTotal @total
|
52
|
-
x.
|
52
|
+
x.MontoDescuento @discount if @discount.present?
|
53
53
|
x.NaturalezaDescuento @discount_reason if @discount_reason.present?
|
54
54
|
x.SubTotal @subtotal
|
55
55
|
@taxes.each do |tax|
|
@@ -19,13 +19,14 @@ module FE
|
|
19
19
|
"11"=>"Impuesto Selectivo de Consumo Compras Autorizadas",
|
20
20
|
"99"=>"Otros"
|
21
21
|
}
|
22
|
-
attr_accessor :code, :rate, :total
|
22
|
+
attr_accessor :code, :rate, :total, :exoneration
|
23
23
|
|
24
24
|
validates :code, presence: true, inclusion: TAX_CODES.keys
|
25
25
|
def initialize(args={})
|
26
26
|
@code = args[:code]
|
27
27
|
@rate = args[:rate]
|
28
28
|
@total = args[:total]
|
29
|
+
@exoneration = args[:exoneration]
|
29
30
|
end
|
30
31
|
|
31
32
|
def build_xml(node)
|
@@ -36,6 +37,9 @@ module FE
|
|
36
37
|
xml.Codigo @code
|
37
38
|
xml.Tarifa @rate
|
38
39
|
xml.Monto @total
|
40
|
+
if @exoneration.present?
|
41
|
+
@exoneration.build_xml(xml)
|
42
|
+
end
|
39
43
|
end
|
40
44
|
end
|
41
45
|
|
@@ -9,7 +9,7 @@ module FE
|
|
9
9
|
"2" => "Aceptacion Parcial",
|
10
10
|
"3" => "Rechazado"
|
11
11
|
}
|
12
|
-
attr_accessor :key, :date, :issuer_id_number, :receiver_id_number, :message, :details, :tax, :total, :number, :receiver_id_type, :security_code, :document_situation
|
12
|
+
attr_accessor :key, :date, :issuer_id_number, :receiver_id_number, :message, :details, :tax, :total, :number, :receiver_id_type, :security_code, :document_situation, :issuer_id_type
|
13
13
|
|
14
14
|
validates :date, presence: true
|
15
15
|
validates :issuer_id_number, presence: true, length: {is: 12}
|
@@ -19,10 +19,13 @@ module FE
|
|
19
19
|
validates :total, presence: true, numericality: true
|
20
20
|
validates :number, presence: true
|
21
21
|
validates :security_code, presence: true, length: {is: 8}
|
22
|
+
validates :issuer_id_type, presence: true
|
23
|
+
validates :receiver_id_type, presence: true
|
22
24
|
|
23
25
|
def initialize(args = {})
|
24
26
|
@key = args[:key]
|
25
27
|
@date = args[:date]
|
28
|
+
@issuer_id_type = args[:issuer_id_type]
|
26
29
|
@issuer_id_number = args[:issuer_id_number]
|
27
30
|
@receiver_id_type = args[:receiver_id_type]
|
28
31
|
@receiver_id_number = args[:receiver_id_number]
|
@@ -40,22 +43,6 @@ module FE
|
|
40
43
|
}
|
41
44
|
end
|
42
45
|
|
43
|
-
def key
|
44
|
-
raise "Documento inválido: #{errors.messages}" unless valid?
|
45
|
-
country = "506"
|
46
|
-
day = "%02d" % @date.day
|
47
|
-
month = "%02d" % @date.month
|
48
|
-
year = "%02d" % (@date.year - 2000)
|
49
|
-
id_number = @receiver_id_number.rjust(12,"0")
|
50
|
-
|
51
|
-
situation = @document_situation
|
52
|
-
security_code = @security_code
|
53
|
-
|
54
|
-
result = "#{country}#{day}#{month}#{year}#{id_number}#{sequence}#{situation}#{security_code}"
|
55
|
-
raise "The key is invalid: #{result}" unless result.length.eql?(50)
|
56
|
-
|
57
|
-
result
|
58
|
-
end
|
59
46
|
|
60
47
|
def headquarters
|
61
48
|
@headquarters ||= "001"
|
@@ -84,15 +71,15 @@ module FE
|
|
84
71
|
builder = Nokogiri::XML::Builder.new
|
85
72
|
|
86
73
|
builder.MensajeReceptor(@namespaces) do |xml|
|
87
|
-
xml.Clave key
|
74
|
+
xml.Clave @key
|
88
75
|
xml.NumeroCedulaEmisor @issuer_id_number
|
89
76
|
xml.FechaEmisionDoc @date.xmlschema
|
90
77
|
xml.Mensaje @message
|
91
78
|
xml.DetalleMensaje @details if @details
|
92
|
-
xml.MontoTotalImpuesto @tax
|
79
|
+
xml.MontoTotalImpuesto @tax.to_f
|
93
80
|
xml.TotalFactura @total
|
94
81
|
xml.NumeroCedulaReceptor @receiver_id_number
|
95
|
-
xml.
|
82
|
+
xml.NumeroConsecutivoReceptor sequence
|
96
83
|
end
|
97
84
|
|
98
85
|
builder
|
@@ -103,16 +90,32 @@ module FE
|
|
103
90
|
end
|
104
91
|
|
105
92
|
def api_payload
|
93
|
+
|
106
94
|
payload = {}
|
107
|
-
payload[:clave] = key
|
95
|
+
payload[:clave] = @key
|
108
96
|
payload[:fecha] = @date.xmlschema
|
109
97
|
payload[:emisor] = {
|
110
|
-
tipoIdentificacion: @
|
98
|
+
tipoIdentificacion: infer_id_type(@issuer_id_number),
|
99
|
+
numeroIdentificacion: @issuer_id_number
|
100
|
+
}
|
101
|
+
payload[:receptor] = {
|
102
|
+
tipoIdentificacion: infer_id_type(@receiver_id_number),
|
111
103
|
numeroIdentificacion: @receiver_id_number
|
112
104
|
}
|
105
|
+
payload[:consecutivoReceptor] = sequence
|
113
106
|
payload
|
114
107
|
end
|
115
108
|
|
109
|
+
def infer_id_type(id_number)
|
110
|
+
if id_number.to_i.to_s.size == 9
|
111
|
+
"01"
|
112
|
+
elsif id_number.to_i.to_s.size == 10
|
113
|
+
"02"
|
114
|
+
elsif id_number.to_i.to_S.size == 11
|
115
|
+
"03"
|
116
|
+
end
|
117
|
+
end
|
116
118
|
|
117
119
|
end
|
120
|
+
|
118
121
|
end
|