lib/cfita/codice_fiscale.rb in cfita-0.0.5 vs lib/cfita/codice_fiscale.rb in cfita-0.0.6

- old
+ new

@@ -1,9 +1,9 @@ # frozen_string_literal: true require 'active_support/all' -require 'cfita/codici_catastali' +require 'cfita/codici_catastali.rb' module Cfita # Controllo codice fiscale italiano class CodiceFiscale attr_reader :fiscal_code, @@ -14,27 +14,32 @@ def self.ccat @ccat ||= JSON.parse(open('ccat.json')) end - def initialize(fiscal_code, birth_place: nil, birth_date: nil) + def initialize( + fiscal_code, + birth_place: nil, + birth_date: nil, + name: nil, + surname: nil + ) @fiscal_code = fiscal_code.upcase.strip @birth_place = birth_place&.upcase @birth_date = birth_date && (birth_date.is_a?(Date) ? birth_date : Date.parse(birth_date)) - @data = {} + @name = name&.parameterize&.upcase + @surname = surname&.parameterize&.upcase @errors = [] parse end def to_s fiscal_code end - def valid?(birth_place: nil) - result = errors.empty? - result = birth_place?(birth_place) if result && birth_place - result + def valid? + errors.empty? end private def parse @@ -43,14 +48,52 @@ return if errors.any? check_checksum return if errors.any? + check_name + check_surname check_birth_date check_birth_place end + def check_name + return unless @name + + a, b, c, d = consonants(@name) + name_code = ( + (d ? [a, c, d] : [a, b, c]).compact.join + + vowels(@name).join + + 'XXX' + )[0..2] + + errors << "Il nome non corrisponde al codice '#{name_code}'" unless name_code == @fiscal_code[3..5] + end + + def check_surname + return unless @surname + + surname_code = ( + consonants(@surname).join + + vowels(@surname).join + + 'XXX' + )[0..2] + + errors << "Il cognome non corrisponde al codice '#{surname_code}'" unless surname_code == @fiscal_code[0..2] + end + + VOWELS = 'AEIOU'.chars.freeze + CONSONANTS = (('A'..'Z').to_a - VOWELS).freeze + + def vowels(word) + word.chars.select { |char| char.in? VOWELS } + end + + def consonants(word) + word.chars.select { |char| char.in? CONSONANTS } + end + def check_size size = @fiscal_code.size errors << "Lunghezza errata (#{size})" unless size == 16 end @@ -99,11 +142,11 @@ @errors << "Luogo di nascita #{@birth_place} non coerente, al codice catastale #{codice_catastale} corrisponde a #{birth_places.join(' o a ')}" end end end - MESI = 'ABCDEHLMPRST'.freeze + MESI = 'ABCDEHLMPRST' def check_birth_date yy = cifre(6..7) return if @errors.any? @@ -127,12 +170,12 @@ else @birth_date = date end end - def yy2yyyy(yy) + def yy2yyyy(year_as_yy) Date.today.year - - (Date.today.year % 100 + 100 - yy ) % 100 + (Date.today.year % 100 + 100 - year_as_yy) % 100 end def cifre(range) result = 0 range.each do |position|