Module: Citizenship

Defined in:
lib/citizenship/nib.rb,
lib/citizenship.rb,
lib/citizenship/nif.rb,
lib/citizenship/email.rb,
lib/citizenship/phone.rb,
lib/citizenship/errors.rb,
lib/citizenship/version.rb,
lib/citizenship/zip_code.rb,
lib/citizenship/citizen_card.rb,
lib/citizenship/rails/validators.rb,
lib/citizenship/identification_card.rb

Overview

Defined Under Namespace

Modules: Rails Classes: CitizenCardError, EmailError, Error, IdentificationCardError, NIBError, NIFError, PhoneError, ZipCodeError

Constant Summary collapse

EMAIL_REGEXP =
/\A[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+\z/i
VERSION =
"1.0.0"

Class Method Summary collapse

Class Method Details

.valid_citizen_card!(number) ⇒ Object

Raises:



3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/citizenship/citizen_card.rb', line 3

def self.valid_citizen_card!(number)
  id_number = remove_special_chars(number)

  raise CitizenCardError, :size if id_number.size != 12

  double_digit = false
  conversion_table = ('a'..'z').to_a
  check_digit = id_number.reverse.split('').map do |element|
    #switch letters for the value in the conversion table (see 2.3. on Algoritmo_Num_Documento_CC.pdf)
    is_number?(element) ? element : conversion_table.find_index(element.downcase) + 10
  end.map(&:to_i).map do |digit|
    begin
      if double_digit #starting on the 2nd value double every value steping by 2
        value = digit * 2
        value >= 10 ? value - 9 : value #If the doubling result is 10 or more, subtract 9
      else
        digit
      end
    ensure
      double_digit = not(double_digit)
    end
  end.reduce(:+) #sum everything

  raise CitizenCardError, :invalid_check_digit if check_digit % 10 != 0
  number
end

.valid_citizen_card?(number) ⇒ Boolean

Returns:

  • (Boolean)


30
31
32
33
34
35
# File 'lib/citizenship/citizen_card.rb', line 30

def self.valid_citizen_card?(number)
  valid_citizen_card!(number)
  true
rescue CitizenCardError
  false
end

.valid_email!(email) ⇒ Object

Raises:



4
5
6
7
# File 'lib/citizenship/email.rb', line 4

def self.valid_email!(email)
  raise EmailError, :invalid_email unless email.match(EMAIL_REGEXP)
  email
end

.valid_email?(email) ⇒ Boolean

Returns:

  • (Boolean)


9
10
11
12
13
14
# File 'lib/citizenship/email.rb', line 9

def self.valid_email?(email)
  valid_email!(email)
  true
rescue EmailError
  false
end

.valid_identification_card!(number, check_digit) ⇒ Object



3
4
5
6
7
8
9
# File 'lib/citizenship/identification_card.rb', line 3

def self.valid_identification_card!(number, check_digit)
  id_number, check_digit = String(number).delete(' '), String(check_digit)

  raise IdentificationCardError, :size unless id_number.size == 7 or id_number.size == 8
  raise IdentificationCardError, :invalid_check_digit unless decimal_check_digit_match?(id_number, check_digit)
  number
end

.valid_identification_card?(number, check_digit) ⇒ Boolean

Returns:

  • (Boolean)


11
12
13
14
15
16
# File 'lib/citizenship/identification_card.rb', line 11

def self.valid_identification_card?(number, check_digit)
  valid_identification_card!(number, check_digit)
  true
rescue IdentificationCardError
  false
end

.valid_nib!(nib, options = {}) ⇒ Object

Raises:



3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/citizenship/nib.rb', line 3

def self.valid_nib!(nib, options = {})
  strict = options.fetch(:strict, false)
  bank_codes = ['0007', #BES
                '0010', #BPI
                '0018', #Santander
                '0019', #BBVA
                '0025', #Caixa BI
                '0032', #Barclays
                '0033', #BCP
                '0034', #BNP Paribas
                '0035', #CGD
                '0036', #Montepio
                '0038', #Banif
                '0043', #Deutsche Bank
                '0045', #CA Crédito Agrícola
                '0046', #Banco Popular
                '0061', #BiG
                '0065', #Best
                '0076', #Finibanco
                '0079', #BPN
                '0781', #Direcção Geral do Tesouro
                '5180'] #Caixa Central de Crédito Agrícola Mútuo

  escaped_nib = strict ? nib : remove_special_chars(nib)
  raise NIBError.new(:size) unless escaped_nib.size == 21
  raise NIBError.new(:invalid_bank_code, bank_code: escaped_nib[0..3]) unless bank_codes.include?(escaped_nib[0..3])

  check_digit = escaped_nib[19..20].to_i
  escaped_nib = escaped_nib[0..18]

  conversion_table = [73, 17, 89, 38, 62, 45, 53, 15, 50, 5, 49, 34, 81, 76, 27, 90, 9, 30, 3]
  sum = (0..18).map do |i|
    escaped_nib.slice(i).to_i * conversion_table[i]
  end.reduce(:+)

  control_number = 98 - sum % 97
  raise NIBError.new(:invalid_check_digit) unless check_digit == control_number
  nib
end

.valid_nib?(nib, options = {}) ⇒ Boolean

Returns:

  • (Boolean)


43
44
45
46
47
48
# File 'lib/citizenship/nib.rb', line 43

def self.valid_nib?(nib, options = {})
  valid_nib!(nib, options)
  true
rescue NIBError
  false
end

.valid_nif!(number, options = {}) ⇒ Object

Raises:



3
4
5
6
7
8
9
10
11
12
# File 'lib/citizenship/nif.rb', line 3

def self.valid_nif!(number, options = {})
  strict = options.fetch(:strict, false)
  id_number = strict ? number : String(number).delete(' ')
  first_digit_universe = [1, 2, 5, 6, 8, 9]

  raise NIFError.new(:size) if id_number.size != 9
  raise NIFError.new(:prefix, prefixes: first_digit_universe.join(', ')) unless first_digit_universe.include?(id_number[0].to_i)
  raise NIFError.new(:invalid_check_digit) unless decimal_check_digit_match?(id_number[0..-2], id_number[-1])
  number
end

.valid_nif?(number, options = {}) ⇒ Boolean

Returns:

  • (Boolean)


14
15
16
17
18
19
# File 'lib/citizenship/nif.rb', line 14

def self.valid_nif?(number, options = {})
  valid_nif!(number, options)
  true
rescue NIFError
  false
end

.valid_phone!(number, opts = {}) ⇒ Object

Raises:



2
3
4
5
6
7
8
9
10
11
12
13
# File 'lib/citizenship/phone.rb', line 2

def self.valid_phone!(number, opts = {})
  allow_country_prefix = opts.fetch(:allow_country_prefix, true)
  prefix_whitelist = network_prefix_white_list(opts[:only_prefixes])
  strict = opts.fetch(:strict, false)

  country_prefix = allow_country_prefix ? '((\+351|00351|351)?)' : ''
  regexp_template = "^#{country_prefix}(#{prefix_whitelist}\\d{7})$"

  phone_number = strict ? number : String(number).delete(' ').delete('-')
  raise PhoneError, :invalid_phone_number unless phone_number.match(Regexp.new(regexp_template))
  number
end

.valid_phone?(number, opts = {}) ⇒ Boolean

Returns:

  • (Boolean)


15
16
17
18
19
20
# File 'lib/citizenship/phone.rb', line 15

def self.valid_phone?(number, opts = {})
  valid_phone!(number, opts)
  true
rescue Error
  false
end

.valid_zip_code!(zip_code) ⇒ Object

Raises:



2
3
4
5
6
# File 'lib/citizenship/zip_code.rb', line 2

def self.valid_zip_code!(zip_code)
  regexp = /^(\d{4})-(\d{3})$/
  raise ZipCodeError, :invalid_zip_code unless zip_code.match(regexp)
  zip_code
end

.valid_zip_code?(zip_code) ⇒ Boolean

Returns:

  • (Boolean)


8
9
10
11
12
13
# File 'lib/citizenship/zip_code.rb', line 8

def self.valid_zip_code?(zip_code)
  valid_zip_code!(zip_code)
  true
rescue ZipCodeError
  false
end