Use Estonian reference number format instead of ISO 11649

This commit is contained in:
Artur Beljajev 2018-10-01 13:43:50 +03:00
parent aa6e8f8a93
commit 5738c17731
25 changed files with 244 additions and 47 deletions

View file

@ -0,0 +1,10 @@
module Billing
class ReferenceNo
REGEXP = /\A\d{2,20}\z/
def self.generate
base = Base.generate
"#{base}#{base.check_digit}"
end
end
end

View file

@ -0,0 +1,48 @@
module Billing
class ReferenceNo
class Base
def self.generate
new(SecureRandom.random_number(1..1_000_000))
end
def initialize(base)
@base = base.to_s
end
def check_digit
amount = amount_after_multiplication
next_number_ending_with_zero(amount) - amount
end
def to_s
base
end
private
attr_reader :base
def next_number_ending_with_zero(number)
next_number = number
loop do
next_number = next_number.next
return next_number if next_number.to_s.end_with?('0')
end
end
def amount_after_multiplication
multipliers = [7, 3, 1]
enumerator = multipliers.cycle
amount = 0
base.reverse.each_char do |char|
digit = char.to_i
amount += (digit * enumerator.next)
end
amount
end
end
end
end

View file

@ -14,9 +14,10 @@ class Registrar < ActiveRecord::Base
delegate :balance, to: :cash_account, allow_nil: true
validates :name, :reg_no, :country_code, :email, :code, presence: true
validates :name, :reference_no, :code, uniqueness: true
validates :name, :code, uniqueness: true
validates :accounting_customer_code, presence: true
validates :language, presence: true
validates :reference_no, format: Billing::ReferenceNo::REGEXP
validate :forbid_special_code
validates :vat_rate, presence: true, if: 'foreign_vat_payer? && vat_no.blank?'
@ -29,7 +30,6 @@ class Registrar < ActiveRecord::Base
attribute :vat_rate, ::Type::VATRate.new
after_initialize :set_defaults
before_validation :generate_iso_11649_reference_no
validates :email, :billing_email,
email_format: { message: :invalid },
@ -167,27 +167,6 @@ class Registrar < ActiveRecord::Base
errors.add(:code, :forbidden) if code == 'CID'
end
def generate_iso_11649_reference_no
return if reference_no.present?
loop do
base = nil
loop do
base = SecureRandom.random_number.to_s.last(8)
break if base.to_i != 0 && base.length == 8
end
control_base = (base + '2715' + '00').to_i
reminder = control_base % 97
check_digits = 98 - reminder
check_digits = check_digits < 10 ? "0#{check_digits}" : check_digits.to_s
self.reference_no = "RF#{check_digits}#{base}"
break unless self.class.exists?(reference_no: reference_no)
end
end
def home_vat_payer?
country == Registry.instance.legal_address_country
end