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

@ -14,6 +14,7 @@ module Admin
def create
@registrar = Registrar.new(registrar_params)
@registrar.reference_no = ::Billing::ReferenceNo.generate
if @registrar.valid?
@registrar.transaction do

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

View file

@ -2,6 +2,7 @@
<div class="panel-heading">
<%= t '.header' %>
</div>
<div class="panel-body">
<dl class="dl-horizontal">
<dt><%= Registrar.human_attribute_name :vat_no %></dt>
@ -15,6 +16,9 @@
<dt><%= Registrar.human_attribute_name :billing_email %></dt>
<dd><%= registrar.billing_email %></dd>
<dt><%= Registrar.human_attribute_name :reference_no %></dt>
<dd><%= registrar.reference_no %></dd>
</dl>
</div>
</div>

View file

@ -11,9 +11,6 @@
<dt><%= Registrar.human_attribute_name :reg_no %></dt>
<dd><%= registrar.reg_no %></dd>
<dt><%= Registrar.human_attribute_name :reference_no %></dt>
<dd><%= registrar.reference_no %></dd>
<dt><%= Registrar.human_attribute_name :code %></dt>
<dd><%= registrar.code %></dd>

View file

@ -47,6 +47,24 @@
<%= f.email_field :billing_email, class: 'form-control' %>
</div>
</div>
<div class="form-group">
<% if f.object.new_record? %>
<div class="col-md-offset-4 col-md-8">
<%= t '.no_reference_no_hint' %>
</div>
<% else %>
<div class="col-md-4 control-label">
<%= f.label :reference_no %>
</div>
<div class="col-md-7">
<%= f.text_field :reference_no, disabled: true,
title: t('.disabled_reference_no_hint'),
class: 'form-control' %>
</div>
<% end %>
</div>
</div>
</div>
</div>