Merge branch 'master' into registry-787

# Conflicts:
#	db/structure.sql
This commit is contained in:
Artur Beljajev 2018-04-17 12:38:55 +03:00
commit 96e2136c38
92 changed files with 860 additions and 271 deletions

View file

@ -24,7 +24,7 @@ module Admin
@invoice = Invoice.find_by(id: params[:invoice_id])
@bank_transaction = @bank_statement.bank_transactions.build(
description: @invoice.to_s,
sum: @invoice.sum,
sum: @invoice.total,
reference_no: @invoice.reference_no,
paid_at: Time.zone.now.to_date,
currency: 'EUR'

View file

@ -61,7 +61,6 @@ module Admin
def registrar_params
params.require(:registrar).permit(:name,
:reg_no,
:vat_no,
:street,
:city,
:state,
@ -70,10 +69,12 @@ module Admin
:email,
:phone,
:website,
:billing_email,
:code,
:test_registrar,
:vat_no,
:vat_rate,
:accounting_customer_code,
:billing_email,
:language)
end
end

View file

@ -55,8 +55,8 @@ class Registrar
end
def normalize_search_parameters
params[:q][:sum_cache_gteq].gsub!(',', '.') if params[:q][:sum_cache_gteq]
params[:q][:sum_cache_lteq].gsub!(',', '.') if params[:q][:sum_cache_lteq]
params[:q][:total_gteq].gsub!(',', '.') if params[:q][:total_gteq]
params[:q][:total_lteq].gsub!(',', '.') if params[:q][:total_lteq]
ca_cache = params[:q][:due_date_lteq]
begin

View file

@ -29,7 +29,7 @@ class BankLink
hash["VK_VERSION"] = "008"
hash["VK_SND_ID"] = ENV["payments_#{type}_seller_account"]
hash["VK_STAMP"] = invoice.number
hash["VK_AMOUNT"] = number_with_precision(invoice.sum_cache, :precision => 2, :separator => ".")
hash["VK_AMOUNT"] = number_with_precision(invoice.total, :precision => 2, :separator => ".")
hash["VK_CURR"] = invoice.currency
hash["VK_REF"] = ""
hash["VK_MSG"] = invoice.order
@ -140,7 +140,7 @@ class BankLink
def validate_amount
source = number_with_precision(BigDecimal.new(params["VK_AMOUNT"].to_s), precision: 2, separator: ".")
target = number_with_precision(invoice.sum_cache, precision: 2, separator: ".")
target = number_with_precision(invoice.total, precision: 2, separator: ".")
source == target
end

View file

@ -47,7 +47,7 @@ class BankTransaction < ActiveRecord::Base
return if invoice.binded?
return if invoice.cancelled?
return if invoice.sum != sum
return if invoice.total != sum
create_activity(registrar, invoice)
end
# rubocop: enable Metrics/PerceivedComplexity
@ -76,7 +76,7 @@ class BankTransaction < ActiveRecord::Base
return
end
if invoice.sum != sum
if invoice.total != sum
errors.add(:base, I18n.t('invoice_and_transaction_sums_do_not_match'))
return
end
@ -88,7 +88,7 @@ class BankTransaction < ActiveRecord::Base
create_account_activity(
account: registrar.cash_account,
invoice: invoice,
sum: invoice.sum_without_vat,
sum: invoice.subtotal,
currency: currency,
description: description,
activity_type: AccountActivity::ADD_CREDIT

View file

@ -3,7 +3,7 @@ class Directo < ActiveRecord::Base
belongs_to :item, polymorphic: true
def self.send_receipts
new_trans = Invoice.where(invoice_type: "DEB", in_directo: false).where(cancelled_at: nil)
new_trans = Invoice.where(in_directo: false).where(cancelled_at: nil)
total = new_trans.count
counter = 0
Rails.logger.info("[DIRECTO] Will try to send #{total} invoices")
@ -15,7 +15,7 @@ class Directo < ActiveRecord::Base
group.each do |invoice|
if invoice.account_activity.nil? || invoice.account_activity.bank_transaction.nil? ||
invoice.account_activity.bank_transaction.sum.nil? || invoice.account_activity.bank_transaction.sum != invoice.sum_cache
invoice.account_activity.bank_transaction.sum.nil? || invoice.account_activity.bank_transaction.sum != invoice.total
Rails.logger.info("[DIRECTO] Invoice #{invoice.number} has been skipped")
next
end
@ -29,12 +29,14 @@ class Directo < ActiveRecord::Base
"InvoiceDate" => invoice.created_at.strftime("%Y-%m-%dT%H:%M:%S"),
"PaymentTerm" => Setting.directo_receipt_payment_term,
"Currency" => invoice.currency,
"CustomerCode"=> invoice.buyer.accounting_customer_code
"CustomerCode"=> invoice.buyer.accounting_customer_code,
'TotalVAT' => ActionController::Base.helpers.number_with_precision(invoice.vat_amount, precision: 2, separator: '.')
){
xml.line(
"ProductID" => Setting.directo_receipt_product_name,
"Quantity" => 1,
"UnitPriceWoVAT" => ActionController::Base.helpers.number_with_precision(invoice.sum_cache/(1+invoice.vat_prc), precision: 2, separator: "."),
"UnitPriceWoVAT" => ActionController::Base.helpers.number_with_precision(invoice.subtotal, precision: 2, separator: '.'),
'VATCode' => invoice.buyer_vat_no,
"ProductName" => invoice.order
)
}

View file

@ -209,28 +209,12 @@ class Domain < ActiveRecord::Base
DomainCron.send(__method__)
end
def self.start_delete_period
ActiveSupport::Deprecation.instance.deprecation_warning(DomainCron, __method__)
DomainCron.send(__method__)
end
def self.destroy_delete_candidates
ActiveSupport::Deprecation.instance.deprecation_warning(DomainCron, __method__)
DomainCron.send(__method__)
end
class << self
def included
includes(
:registrant,
:registrar,
:nameservers,
:whois_record,
{ tech_contacts: :registrar },
{ admin_contacts: :registrar }
)
end
def nameserver_required?
Setting.nameserver_required
end

View file

@ -76,29 +76,6 @@ class DomainCron
marked
end
#doing nothing, deprecated
def self.start_delete_period
# begin
# STDOUT << "#{Time.zone.now.utc} - Setting delete_candidate to domains\n" unless Rails.env.test?
#
# d = Domain.where('delete_at <= ?', Time.zone.now)
# marked = 0
# real = 0
# d.each do |domain|
# next unless domain.delete_candidateable?
# real += 1
# domain.statuses << DomainStatus::DELETE_CANDIDATE
# STDOUT << "#{Time.zone.now.utc} DomainCron.start_delete_period: ##{domain.id} (#{domain.name})\n" unless Rails.env.test?
# ::PaperTrail.whodunnit = "cron - #{__method__}"
# domain.save(validate: false) and marked += 1
# end
# ensure # the operator should see what was accomplished
# STDOUT << "#{Time.zone.now.utc} - Finished setting delete_candidate - #{marked} out of #{real} successfully set\n" unless Rails.env.test?
# end
# marked
end
def self.destroy_delete_candidates
STDOUT << "#{Time.zone.now.utc} - Destroying domains\n" unless Rails.env.test?
@ -128,23 +105,4 @@ class DomainCron
STDOUT << "#{Time.zone.now.utc} - Job destroy added for #{c} domains\n" unless Rails.env.test?
end
# rubocop: enable Metrics/AbcSize
# rubocop:enable Rails/FindEach
# rubocop: enable Metrics/LineLength
def self.destroy_with_message(domain)
domain.destroy
bye_bye = domain.versions.last
domain.registrar.messages.create!(
body: "#{I18n.t(:domain_deleted)}: #{domain.name}",
attached_obj_id: bye_bye.id,
attached_obj_type: bye_bye.class.to_s # DomainVersion
)
end
def self.delete_legal_doc_duplicates
Rake::Task['legal_doc:remove_duplicates'].reenable
Rake::Task['legal_doc:remove_duplicates'].invoke
end
end

View file

@ -18,7 +18,7 @@ class Epp::Domain < Domain
after_validation :validate_contacts
def validate_contacts
return true if is_renewal || is_transfer
return true if is_transfer
ok = true
active_admins = admin_domain_contacts.select { |x| !x.marked_for_destruction? }
@ -38,16 +38,6 @@ class Epp::Domain < Domain
ok
end
before_save :link_contacts
def link_contacts
#TODO: cleanup cache if we think to cache dynamic statuses
end
after_destroy :unlink_contacts
def unlink_contacts
#TODO: cleanup cache if we think to cache dynamic statuses
end
class << self
def new_from_epp(frame, current_user)
domain = Epp::Domain.new

View file

@ -27,12 +27,18 @@ class Invoice < ActiveRecord::Base
attr_accessor :billing_email
validates :billing_email, email_format: { message: :invalid }, allow_blank: true
validates :invoice_type, :due_date, :currency, :seller_name,
:seller_iban, :buyer_name, :invoice_items, :vat_prc, presence: true
validates :due_date, :currency, :seller_name,
:seller_iban, :buyer_name, :invoice_items, presence: true
validates :vat_rate, numericality: { greater_than_or_equal_to: 0, less_than: 100 },
allow_nil: true
before_create :set_invoice_number, :check_vat
before_create :set_invoice_number
before_create :apply_default_vat_rate, unless: :vat_rate?
before_create :calculate_total, unless: :total?
before_create :apply_default_buyer_vat_no, unless: :buyer_vat_no?
before_save :check_vat
attribute :vat_rate, ::Type::VATRate.new
attr_readonly :vat_rate
def set_invoice_number
last_no = Invoice.order(number: :desc).where('number IS NOT NULL').limit(1).pluck(:number).first
@ -50,14 +56,6 @@ class Invoice < ActiveRecord::Base
false
end
def check_vat
if buyer.country_code != 'EE' && buyer.vat_no.present?
self.vat_prc = 0
end
end
before_save -> { self.sum_cache = sum }
class << self
def cancel_overdue_invoices
STDOUT << "#{Time.zone.now.utc} - Cancelling overdue invoices\n" unless Rails.env.test?
@ -106,12 +104,12 @@ class Invoice < ActiveRecord::Base
def buyer_country
Country.new(buyer_country_code)
end
# order is used for directo/banklink description
def order
"Order nr. #{number}"
end
def pdf(html)
kit = PDFKit.new(html)
kit.to_pdf
@ -152,15 +150,31 @@ class Invoice < ActiveRecord::Base
invoice_items
end
def sum_without_vat
(items.map(&:item_sum_without_vat).sum).round(2)
def subtotal
invoice_items.map(&:item_sum_without_vat).reduce(:+)
end
def vat
(sum_without_vat * vat_prc).round(2)
def vat_amount
return 0 unless vat_rate
subtotal * vat_rate / 100
end
def sum
(sum_without_vat + vat).round(2)
def total
calculate_total unless total?
read_attribute(:total)
end
private
def apply_default_vat_rate
self.vat_rate = buyer.effective_vat_rate
end
def apply_default_buyer_vat_no
self.buyer_vat_no = buyer.vat_no
end
def calculate_total
self.total = subtotal + vat_amount
end
end

View file

@ -19,6 +19,15 @@ class Registrar < ActiveRecord::Base
validates :language, presence: true
validate :forbid_special_code
validates :vat_rate, presence: true, if: 'foreign_vat_payer? && vat_no.blank?'
validates :vat_rate, absence: true, if: :home_vat_payer?
validates :vat_rate, absence: true, if: 'foreign_vat_payer? && vat_no?'
validates :vat_rate, numericality: { greater_than_or_equal_to: 0, less_than: 100 },
allow_nil: true
validate :forbid_special_code
attribute :vat_rate, ::Type::VATRate.new
after_initialize :set_defaults
before_validation :generate_iso_11649_reference_no
@ -49,12 +58,10 @@ class Registrar < ActiveRecord::Base
# rubocop:disable Metrics/AbcSize
def issue_prepayment_invoice(amount, description = nil)
invoices.create(
invoice_type: 'DEB',
due_date: (Time.zone.now.to_date + Setting.days_to_keep_invoices_active.days).end_of_day,
payment_term: 'prepayment',
description: description,
currency: 'EUR',
vat_prc: Setting.registry_vat_prc,
seller_name: Setting.registry_juridical_name,
seller_reg_no: Setting.registry_reg_no,
seller_iban: Setting.registry_iban,
@ -70,7 +77,7 @@ class Registrar < ActiveRecord::Base
seller_url: Setting.registry_url,
seller_email: Setting.registry_email,
seller_contact_name: Setting.registry_invoice_contact,
buyer_id: id,
buyer: self,
buyer_name: name,
buyer_reg_no: reg_no,
buyer_country_code: country_code,
@ -105,11 +112,6 @@ class Registrar < ActiveRecord::Base
cash_account.account_activities.create!(args)
end
def credit!(args)
args[:currency] = 'EUR'
cash_account.account_activities.create!(args)
end
def address
[street, city, state, zip].reject(&:blank?).compact.join(', ')
end
@ -145,6 +147,14 @@ class Registrar < ActiveRecord::Base
end
end
def effective_vat_rate
if home_vat_payer?
Registry.instance.vat_rate
else
vat_rate
end
end
private
def set_defaults
@ -175,4 +185,12 @@ class Registrar < ActiveRecord::Base
break unless self.class.exists?(reference_no: reference_no)
end
end
def home_vat_payer?
country == Registry.instance.legal_address_country
end
def foreign_vat_payer?
!home_vat_payer?
end
end

11
app/models/registry.rb Normal file
View file

@ -0,0 +1,11 @@
class Registry
include Singleton
def vat_rate
Setting.registry_vat_prc.to_d * 100
end
def legal_address_country
Country.new(Setting.registry_country_code)
end
end

View file

@ -0,0 +1,11 @@
module Type
class VATRate < ActiveRecord::Type::Decimal
def type_cast_from_database(value)
super * 100 if value
end
def type_cast_for_database(value)
super / 100.0 if value
end
end
end

View file

@ -9,20 +9,6 @@ class WhoisRecord < ActiveRecord::Base
after_save :update_whois_server
after_destroy :destroy_whois_record
class << self
def included
includes(
domain: [
:registrant,
:registrar,
:nameservers,
{ tech_contacts: :registrar },
{ admin_contacts: :registrar }
]
)
end
end
def self.find_by_name(name)
WhoisRecord.where("lower(name) = ?", name.downcase)
end

View file

@ -37,7 +37,7 @@
= f.email_field :bcc, class: 'form-control'
.form-group
.col-md-12
= f.label :body, t(:html_body)
= f.label :body, t('admin.mail_templates.html_body')
= liquid_help
.col-md-12
= f.text_area(:body, class: 'form-control', size: '15x15')
@ -48,7 +48,7 @@
.col-md-12
= f.text_area(:text_body, class: 'form-control', size: '15x15')
%hr
%hr
.row
.col-md-12.text-right
= button_tag(t(:save), class: 'btn btn-primary')

View file

@ -1,3 +1,3 @@
= render 'shared/title', name: t(:new_mail_template)
= render 'shared/title', name: t('admin.mail_templates.new_mail_template')
= render 'form', mail_template: @mail_template

View file

@ -7,6 +7,9 @@
<dt><%= Registrar.human_attribute_name :vat_no %></dt>
<dd><%= registrar.vat_no %></dd>
<dt><%= Registrar.human_attribute_name :vat_rate %></dt>
<dd><%= number_to_percentage(registrar.vat_rate, precision: 1) %></dd>
<dt><%= Registrar.human_attribute_name :accounting_customer_code %></dt>
<dd><%= registrar.accounting_customer_code %></dd>

View file

@ -17,6 +17,19 @@
</div>
</div>
<div class="form-group">
<div class="col-md-4 control-label">
<%= f.label :vat_rate %>
</div>
<div class="col-md-3">
<div class="input-group">
<%= f.number_field :vat_rate, min: 0, max: 99.9, step: 0.1,
class: 'form-control' %>
<div class="input-group-addon">%</div>
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-4 control-label">
<%= f.label :accounting_customer_code %>

View file

@ -33,11 +33,11 @@
.col-md-3
.form-group
= f.label t(:minimum_total)
= f.search_field :sum_cache_gteq, class: 'form-control', placeholder: t(:minimum_total), autocomplete: 'off'
= f.search_field :total_gteq, class: 'form-control', placeholder: t(:minimum_total), autocomplete: 'off'
.col-md-3
.form-group
= f.label t(:maximum_total)
= f.search_field :sum_cache_lteq, class: 'form-control', placeholder: t(:maximum_total), autocomplete: 'off'
= f.search_field :total_lteq, class: 'form-control', placeholder: t(:maximum_total), autocomplete: 'off'
.col-md-3{style: 'padding-top: 25px;'}
%button.btn.btn-default
&nbsp;
@ -67,7 +67,7 @@
%td{class: 'text-danger'}= t(:unpaid)
%td= l(x.due_date, format: :date_long)
%td= currency(x.sum)
%td= currency(x.total)
.row
.col-md-12
= paginate @invoices

View file

@ -20,13 +20,13 @@
%tfoot
%tr
%th{colspan: 3}
%th= t(:total_without_vat)
%td= currency(@invoice.sum_without_vat)
%th= Invoice.human_attribute_name :subtotal
%td= number_to_currency @invoice.subtotal
%tr
%th.no-border{colspan: 3}
%th= t('vat', vat_prc: (@invoice.vat_prc * 100).round)
%td= currency(@invoice.vat)
%th= "VAT #{number_to_percentage(@invoice.vat_rate, precision: 1)}"
%td= number_to_currency @invoice.vat_amount
%tr
%th.no-border{colspan: 3}
%th= t(:total)
%td= currency(@invoice.sum)
%td= number_to_currency @invoice.total

View file

@ -238,16 +238,16 @@
%tfoot
%tr
%th{colspan: 3}
%th= t(:total_without_vat)
%td= "#{currency(@invoice.sum_without_vat)} #{@invoice.currency}"
%th= Invoice.human_attribute_name :subtotal
%td= number_to_currency @invoice.subtotal
%tr
%th.no-border{colspan: 3}
%th= t('vat', vat_prc: (@invoice.vat_prc * 100).round)
%td= "#{currency(@invoice.vat)} #{@invoice.currency}"
%th= "VAT #{number_to_percentage(@invoice.vat_rate, precision: 1)}"
%td= number_to_currency @invoice.vat_amount
%tr
%th.no-border{colspan: 3}
%th= t(:total)
%td= "#{currency(@invoice.sum)} #{@invoice.currency}"
%td= number_to_currency @invoice.total
#footer
%hr