class Norma43::Models::Account::SpanishIban

Constants

ACCOUNT_NUMBER_RANGE
BANK_CODE_RANGE
CCC_FORMAT_STRING
CCC_MODULUS
CCC_WEIGHTS
COUNTRY_CODE
IBAN_FORMAT_STRING
IBAN_MODULUS
MAX_BANK_CODE_SIZE

Attributes

account_number[R]
bank_code[R]
branch_code[R]

Public Class Methods

from_account(account) click to toggle source
# File lib/norma43/models/account/spanish_iban.rb, line 17
def self.from_account(account)
  return nil unless valid_numbers?(account.bank_code, account.branch_code, account.account_number)

  new(
    bank_code: account.bank_code,
    branch_code: account.branch_code,
    account_number: account.account_number
  ).to_s
end
new(bank_code:, branch_code:, account_number:) click to toggle source
# File lib/norma43/models/account/spanish_iban.rb, line 27
def initialize(bank_code:, branch_code:, account_number:)
  @bank_code, @branch_code, @account_number =
    if self.class.valid_numbers?(bank_code, branch_code, account_number)
      [bank_code, branch_code, account_number]
    else
      [nil, nil, nil]
    end
end
valid_numbers?(bank_code, branch_code, account_number) click to toggle source
# File lib/norma43/models/account/spanish_iban.rb, line 45
def self.valid_numbers?(bank_code, branch_code, account_number)
  return false unless BANK_CODE_RANGE.include?(bank_code)
  return false unless BRANCH_CODE_RANGE.include?(branch_code)
  return false unless ACCOUNT_NUMBER_RANGE.include?(account_number)
  true
end

Public Instance Methods

to_s() click to toggle source
# File lib/norma43/models/account/spanish_iban.rb, line 36
def to_s
  return "" if [bank_code, branch_code, account_number].any?(nil)

  iban
end

Private Instance Methods

calculate_ccc() click to toggle source
# File lib/norma43/models/account/spanish_iban.rb, line 70
def calculate_ccc
  format_string = CCC_FORMAT_STRING
  bank_with_branch_number = (bank_code * 10**MAX_BRANCH_CODE_SIZE) + branch_code

  bank_with_branch_check_digit, account_number_check_digit = [
    bank_with_branch_number, account_number
  ].map { |number| calculate_spanish_checksum_digit(number) }

  checksum_number = bank_with_branch_check_digit * 10 + account_number_check_digit

  sprintf(format_string,
    bank_code: bank_code,
    branch_code: branch_code,
    checksum_number: checksum_number,
    account_number: account_number)
end
calculate_country_number() click to toggle source
# File lib/norma43/models/account/spanish_iban.rb, line 66
def calculate_country_number
  COUNTRY_CODE.chars.map { |char| char.to_i(36) }.join
end
calculate_iban_checksum_number(number) click to toggle source
# File lib/norma43/models/account/spanish_iban.rb, line 100
def calculate_iban_checksum_number(number)
  modulus = IBAN_MODULUS
  (modulus + 1) - (number % modulus)
end
calculate_spanish_checksum_digit(number) click to toggle source
# File lib/norma43/models/account/spanish_iban.rb, line 87
def calculate_spanish_checksum_digit(number)
  modulus = CCC_MODULUS

  reminder = CCC_WEIGHTS.map.with_index { |weight, order_of_magnitude|
    digit_at_position = (number / 10**order_of_magnitude) % 10

    digit_at_position * weight
  }.sum % modulus

  return reminder if reminder.zero? || reminder == 1
  modulus - reminder
end
iban() click to toggle source
# File lib/norma43/models/account/spanish_iban.rb, line 52
def iban
  format_string = IBAN_FORMAT_STRING
  country_code = COUNTRY_CODE
  country_number = calculate_country_number
  ccc = calculate_ccc
  number = "#{ccc}#{country_number}00".to_i
  checksum_number = calculate_iban_checksum_number(number)

  sprintf(format_string,
    country_code: country_code,
    checksum_number: checksum_number,
    ccc: ccc)
end