Class: Israeli::Validators::BankAccount

Inherits:
Object
  • Object
show all
Defined in:
lib/israeli/validators/bank_account.rb

Overview

Validates Israeli bank account numbers.

Supports two formats:

  • Domestic: 13 digits (2-digit bank + 3-digit branch + 8-digit account)
  • IBAN: 23 characters (IL + 2 check digits + 19 BBAN digits)

Examples:

Domestic validation

Israeli::Validators::BankAccount.valid?("4985622815429")    # => true
Israeli::Validators::BankAccount.valid?("49-856-22815429")  # => true

IBAN validation

Israeli::Validators::BankAccount.valid?("IL620108000000099999999") # => true

See Also:

Constant Summary collapse

DOMESTIC_PATTERN =

Domestic format: 2 (bank) + 3 (branch) + 8 (account) = 13 digits

/\A\d{13}\z/
IBAN_PATTERN =

IBAN format: IL + 2 check digits + 19 BBAN digits = 23 characters

/\AIL\d{21}\z/

Class Method Summary collapse

Class Method Details

.format(value, style: :domestic) ⇒ String?

Formats a bank account to a specified style.

Examples:

BankAccount.format("4985622815429")              # => "49-856-22815429"
BankAccount.format("4985622815429", style: :compact) # => "4985622815429"

Parameters:

  • value (String, nil)

    The bank account to format

  • style (Symbol) (defaults to: :domestic)

    :domestic (XX-XXX-XXXXXXXX) or :iban

Returns:

  • (String, nil)

    Formatted bank account, or nil if invalid



133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/israeli/validators/bank_account.rb', line 133

def self.format(value, style: :domestic)
  digits = Sanitizer.digits_only(value)

  if valid_domestic?(digits)
    case style
    when :domestic
      "#{digits[0..1]}-#{digits[2..4]}-#{digits[5..12]}"
    else
      digits
    end
  elsif valid_iban?(normalize_iban(value))
    normalize_iban(value)
  end
end

.invalid_reason(value, format: :any) ⇒ Symbol?

Returns the reason why a bank account is invalid.

Examples:

Israeli::Validators::BankAccount.invalid_reason("123")  # => :wrong_length

Parameters:

  • value (String, nil)

    The bank account to check

  • format (Symbol) (defaults to: :any)

    Format to validate: :domestic, :iban, or :any

Returns:

  • (Symbol, nil)

    Reason code or nil if valid

    • :blank - Input is nil or empty
    • :wrong_length - Incorrect number of digits/characters
    • :invalid_checksum - IBAN mod 97 checksum failed
    • :invalid_format - Does not match domestic or IBAN pattern


86
87
88
89
90
91
92
93
94
95
# File 'lib/israeli/validators/bank_account.rb', line 86

def self.invalid_reason(value, format: :any)
  return :blank if value.nil? || value.to_s.strip.empty?

  case format
  when :domestic then domestic_invalid_reason(value)
  when :iban then iban_invalid_reason(value)
  when :any then any_format_invalid_reason(value)
  else :invalid_format
  end
end

.valid?(value, format: :any) ⇒ Boolean

Validates an Israeli bank account number.

Parameters:

  • value (String, nil)

    The bank account to validate

  • format (Symbol) (defaults to: :any)

    Format to validate: :domestic, :iban, or :any

Returns:

  • (Boolean)

    true if valid, false otherwise



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/israeli/validators/bank_account.rb', line 31

def self.valid?(value, format: :any)
  return false if value.nil?

  case format
  when :domestic
    valid_domestic?(Sanitizer.digits_only(value))
  when :iban
    valid_iban?(normalize_iban(value))
  when :any
    valid_domestic?(Sanitizer.digits_only(value)) ||
      valid_iban?(normalize_iban(value))
  else
    false
  end
end

.valid_domestic?(digits) ⇒ Boolean

Validates a domestic Israeli bank account (13 digits).

Parameters:

  • digits (String, nil)

    Digits-only bank account

Returns:

  • (Boolean)


51
52
53
54
55
# File 'lib/israeli/validators/bank_account.rb', line 51

def self.valid_domestic?(digits)
  return false if digits.nil?

  digits.match?(DOMESTIC_PATTERN)
end

.valid_iban?(iban) ⇒ Boolean

Validates an Israeli IBAN with mod 97 checksum.

Parameters:

  • iban (String, nil)

    Normalized IBAN (uppercase, no spaces)

Returns:

  • (Boolean)


61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/israeli/validators/bank_account.rb', line 61

def self.valid_iban?(iban)
  return false if iban.nil?
  return false unless iban.match?(IBAN_PATTERN)

  # IBAN mod 97 validation
  # 1. Move first 4 chars to end
  # 2. Convert letters to numbers (A=10, B=11, ..., Z=35)
  # 3. Calculate mod 97, must equal 1
  rearranged = iban[4..] + iban[0..3]
  numeric = rearranged.gsub(/[A-Z]/) { |c| (c.ord - 55).to_s }
  numeric.to_i % 97 == 1
end