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

1
.reek
View file

@ -289,7 +289,6 @@ DuplicateMethodCall:
- Domain#renewable? - Domain#renewable?
- Domain#set_graceful_expired - Domain#set_graceful_expired
- DomainCron#self.clean_expired_pendings - DomainCron#self.clean_expired_pendings
- DomainCron#self.delete_legal_doc_duplicates
- DomainCron#self.destroy_delete_candidates - DomainCron#self.destroy_delete_candidates
- DomainCron#self.start_expire_period - DomainCron#self.start_expire_period
- DomainCron#self.start_redemption_grace_period - DomainCron#self.start_redemption_grace_period

View file

@ -1,3 +1,12 @@
03.04.2018
* BUG: Fixed bug with sometimes failing bank-link payments [#642](https://github.com/internetee/registry/issues/642)
* EPP: Domain and associated objects are now validated on domain renew [#678](https://github.com/internetee/registry/issues/678)
* Admin: drop uniqueness requirement from registrar's registry number field [#776](https://github.com/internetee/registry/issues/776)
* Security: Loofah gem update to 2.2.2 [#783](https://github.com/internetee/registry/pull/783)
* Disabled spellcheck for browsers to cleanup UI [#759](https://github.com/internetee/registry/issues/759)
* Admin: refactored registrar management [#770](https://github.com/internetee/registry/pull/770)
* Fix structure.sql [#796](https://github.com/internetee/registry/pull/796)
19.03.2018 19.03.2018
* EPP transfer and REPP bulk transfer reuses contact objects [#746](https://github.com/internetee/registry/issues/746) * EPP transfer and REPP bulk transfer reuses contact objects [#746](https://github.com/internetee/registry/issues/746)
* Gems: Rack (1.6.9) and Rack-protection (1.5.5) update [#768](https://github.com/internetee/registry/issues/768) * Gems: Rack (1.6.9) and Rack-protection (1.5.5) update [#768](https://github.com/internetee/registry/issues/768)

23
Dockerfile Normal file
View file

@ -0,0 +1,23 @@
FROM ruby:2.2
MAINTAINER maciej.szlosarczyk@internet.ee
RUN apt-get update > /dev/null && apt-get install -y > /dev/null \
build-essential \
nodejs \
imagemagick \
postgresql-client
RUN apt-get install -y > /dev/null \
qt5-default \
libqt5webkit5-dev \
gstreamer1.0-plugins-base \
gstreamer1.0-tools \
qtdeclarative5-dev \
gstreamer1.0-x
RUN mkdir -p /opt/webapps/app/tmp/pids
WORKDIR /opt/webapps/app
COPY Gemfile Gemfile.lock ./
RUN gem install bundler && bundle install --jobs 20 --retry 5
EXPOSE 3000

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -3,7 +3,7 @@ class Directo < ActiveRecord::Base
belongs_to :item, polymorphic: true belongs_to :item, polymorphic: true
def self.send_receipts 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 total = new_trans.count
counter = 0 counter = 0
Rails.logger.info("[DIRECTO] Will try to send #{total} invoices") Rails.logger.info("[DIRECTO] Will try to send #{total} invoices")
@ -15,7 +15,7 @@ class Directo < ActiveRecord::Base
group.each do |invoice| group.each do |invoice|
if invoice.account_activity.nil? || invoice.account_activity.bank_transaction.nil? || 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") Rails.logger.info("[DIRECTO] Invoice #{invoice.number} has been skipped")
next next
end end
@ -29,12 +29,14 @@ class Directo < ActiveRecord::Base
"InvoiceDate" => invoice.created_at.strftime("%Y-%m-%dT%H:%M:%S"), "InvoiceDate" => invoice.created_at.strftime("%Y-%m-%dT%H:%M:%S"),
"PaymentTerm" => Setting.directo_receipt_payment_term, "PaymentTerm" => Setting.directo_receipt_payment_term,
"Currency" => invoice.currency, "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( xml.line(
"ProductID" => Setting.directo_receipt_product_name, "ProductID" => Setting.directo_receipt_product_name,
"Quantity" => 1, "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 "ProductName" => invoice.order
) )
} }

View file

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

View file

@ -76,29 +76,6 @@ class DomainCron
marked marked
end 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 def self.destroy_delete_candidates
STDOUT << "#{Time.zone.now.utc} - Destroying domains\n" unless Rails.env.test? 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? STDOUT << "#{Time.zone.now.utc} - Job destroy added for #{c} domains\n" unless Rails.env.test?
end 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 end

View file

@ -18,7 +18,7 @@ class Epp::Domain < Domain
after_validation :validate_contacts after_validation :validate_contacts
def validate_contacts def validate_contacts
return true if is_renewal || is_transfer return true if is_transfer
ok = true ok = true
active_admins = admin_domain_contacts.select { |x| !x.marked_for_destruction? } active_admins = admin_domain_contacts.select { |x| !x.marked_for_destruction? }
@ -38,16 +38,6 @@ class Epp::Domain < Domain
ok ok
end 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 class << self
def new_from_epp(frame, current_user) def new_from_epp(frame, current_user)
domain = Epp::Domain.new domain = Epp::Domain.new

View file

@ -27,12 +27,18 @@ class Invoice < ActiveRecord::Base
attr_accessor :billing_email attr_accessor :billing_email
validates :billing_email, email_format: { message: :invalid }, allow_blank: true validates :billing_email, email_format: { message: :invalid }, allow_blank: true
validates :invoice_type, :due_date, :currency, :seller_name, validates :due_date, :currency, :seller_name,
:seller_iban, :buyer_name, :invoice_items, :vat_prc, presence: true :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 def set_invoice_number
last_no = Invoice.order(number: :desc).where('number IS NOT NULL').limit(1).pluck(:number).first 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 false
end 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 class << self
def cancel_overdue_invoices def cancel_overdue_invoices
STDOUT << "#{Time.zone.now.utc} - Cancelling overdue invoices\n" unless Rails.env.test? STDOUT << "#{Time.zone.now.utc} - Cancelling overdue invoices\n" unless Rails.env.test?
@ -106,12 +104,12 @@ class Invoice < ActiveRecord::Base
def buyer_country def buyer_country
Country.new(buyer_country_code) Country.new(buyer_country_code)
end end
# order is used for directo/banklink description # order is used for directo/banklink description
def order def order
"Order nr. #{number}" "Order nr. #{number}"
end end
def pdf(html) def pdf(html)
kit = PDFKit.new(html) kit = PDFKit.new(html)
kit.to_pdf kit.to_pdf
@ -152,15 +150,31 @@ class Invoice < ActiveRecord::Base
invoice_items invoice_items
end end
def sum_without_vat def subtotal
(items.map(&:item_sum_without_vat).sum).round(2) invoice_items.map(&:item_sum_without_vat).reduce(:+)
end end
def vat def vat_amount
(sum_without_vat * vat_prc).round(2) return 0 unless vat_rate
subtotal * vat_rate / 100
end end
def sum def total
(sum_without_vat + vat).round(2) 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
end end

View file

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

View file

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

View file

@ -7,6 +7,9 @@
<dt><%= Registrar.human_attribute_name :vat_no %></dt> <dt><%= Registrar.human_attribute_name :vat_no %></dt>
<dd><%= registrar.vat_no %></dd> <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> <dt><%= Registrar.human_attribute_name :accounting_customer_code %></dt>
<dd><%= registrar.accounting_customer_code %></dd> <dd><%= registrar.accounting_customer_code %></dd>

View file

@ -17,6 +17,19 @@
</div> </div>
</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="form-group">
<div class="col-md-4 control-label"> <div class="col-md-4 control-label">
<%= f.label :accounting_customer_code %> <%= f.label :accounting_customer_code %>

View file

@ -33,11 +33,11 @@
.col-md-3 .col-md-3
.form-group .form-group
= f.label t(:minimum_total) = 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 .col-md-3
.form-group .form-group
= f.label t(:maximum_total) = 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;'} .col-md-3{style: 'padding-top: 25px;'}
%button.btn.btn-default %button.btn.btn-default
&nbsp; &nbsp;
@ -67,7 +67,7 @@
%td{class: 'text-danger'}= t(:unpaid) %td{class: 'text-danger'}= t(:unpaid)
%td= l(x.due_date, format: :date_long) %td= l(x.due_date, format: :date_long)
%td= currency(x.sum) %td= currency(x.total)
.row .row
.col-md-12 .col-md-12
= paginate @invoices = paginate @invoices

View file

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

View file

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

View file

@ -15,7 +15,13 @@ require 'rails/all'
# you've limited to :test, :development, or :production. # you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups) Bundler.require(*Rails.groups)
module Registry # Add "db" to the list hosts on which you can run `rake db:setup:all`
# Only allow that in test and development.
if ['development', 'test'].include?(Rails.env)
ActiveRecord::Tasks::DatabaseTasks::LOCAL_HOSTS << "db"
end
module DomainNameRegistry
class Application < Rails::Application class Application < Rails::Application
# Settings in config/environments/* take precedence over those specified here. # Settings in config/environments/* take precedence over those specified here.
# Application configuration should go into files in config/initializers # Application configuration should go into files in config/initializers

View file

@ -4,14 +4,14 @@
# Registrant example is at database-example-registrant.yml file # Registrant example is at database-example-registrant.yml file
default: &default default: &default
host: localhost
adapter: postgresql adapter: postgresql
encoding: unicode encoding: unicode
pool: 5 pool: <%= ENV.fetch("APP_DB_MAX_THREADS") { 5 } %>
username: registry host: <%= ENV.fetch("APP_DBHOST") { "localhost" } %>
password: registry_pwd username: <%= ENV.fetch("APP_DBUSER") { "postgres" } %>
password:
# #
# Staging config For EPP, REPP, Admin, Registrar # Staging config For EPP, REPP, Admin, Registrar
# #
@ -27,7 +27,7 @@ api_log_staging:
<<: *default <<: *default
database: registry_api_log_staging database: registry_api_log_staging
# #
# Production config For EPP, REPP, Admin, Registrar # Production config For EPP, REPP, Admin, Registrar
# #
production: production:

View file

@ -43,6 +43,7 @@ Rails.application.configure do
config.log_level = :debug config.log_level = :debug
config.active_job.queue_adapter = :test config.active_job.queue_adapter = :test
config.logger = ActiveSupport::Logger.new(nil) config.logger = ActiveSupport::Logger.new(nil)
config.active_support.test_order = :random # :random is the default in Rails 5
end end
# In this mode, any jobs you queue will be run in the same thread, synchronously # In this mode, any jobs you queue will be run in the same thread, synchronously

View file

@ -1,8 +0,0 @@
# Log all user issues raised by active record
# rubocop: disable Metrics/LineLength
class ActiveRecord::Base
after_validation do |m|
Rails.logger.info "USER MSG: ACTIVERECORD: #{m.class} ##{m.id} #{m.errors.full_messages} #{m.errors['epp_errors']}" if m.errors.present?
true
end
end

View file

@ -0,0 +1,5 @@
en:
admin:
mail_templates:
html_body: HTML body
new_mail_template: New mail template

View file

@ -19,6 +19,12 @@ en:
billing: billing:
header: Billing header: Billing
edit:
header: Edit registrar
billing:
header: Billing
create: create:
created: Registrar has been successfully created created: Registrar has been successfully created

View file

@ -538,7 +538,6 @@ en:
invoice_number: Invoice no. invoice_number: Invoice no.
seller: 'Seller' seller: 'Seller'
prepayment: 'Prepayment' prepayment: 'Prepayment'
vat: 'VAT (%{vat_prc}%)'
unpaid: 'Unpaid' unpaid: 'Unpaid'
your_current_account_balance_is: 'Your current account balance is %{balance} %{currency}' your_current_account_balance_is: 'Your current account balance is %{balance} %{currency}'
billing: 'Billing' billing: 'Billing'
@ -556,7 +555,6 @@ en:
unit: 'Unit' unit: 'Unit'
price: 'Price' price: 'Price'
total: 'Total' total: 'Total'
total_without_vat: 'Total without VAT'
paid_at: 'Paid at' paid_at: 'Paid at'
invoice: 'Invoice' invoice: 'Invoice'
bank_statements: 'Bank statements' bank_statements: 'Bank statements'
@ -731,7 +729,6 @@ en:
is_registrant: 'Is registrant' is_registrant: 'Is registrant'
force_delete_set_on_domain: 'Force delete set on domain %{domain_name}' force_delete_set_on_domain: 'Force delete set on domain %{domain_name}'
mail_templates: Mail Templates mail_templates: Mail Templates
new_mail_template: New mail template
failure: "It was not saved" failure: "It was not saved"
contact_is_not_valid: 'Contact %{value} is not valid, please fix the invalid contact' contact_is_not_valid: 'Contact %{value} is not valid, please fix the invalid contact'
welcome_to_eis_registrar_portal: 'Welcome to EIS Registrar portal' welcome_to_eis_registrar_portal: 'Welcome to EIS Registrar portal'
@ -763,5 +760,6 @@ en:
attributes: attributes:
vat_no: VAT number vat_no: VAT number
vat_rate: VAT rate
ipv4: IPv4 ipv4: IPv4
ipv6: IPv6 ipv6: IPv6

View file

@ -46,10 +46,6 @@ if @cron_group == 'registry'
runner 'DomainCron.start_expire_period' runner 'DomainCron.start_expire_period'
end end
every 50.minutes do
runner 'DomainCron.start_delete_period'
end
every 52.minutes do every 52.minutes do
runner 'DomainCron.start_redemption_grace_period' runner 'DomainCron.start_redemption_grace_period'
end end

View file

@ -0,0 +1,5 @@
class AddRegistrarsVatRate < ActiveRecord::Migration
def change
add_column :registrars, :vat_rate, :decimal, precision: 4, scale: 3
end
end

View file

@ -0,0 +1,5 @@
class RenameInvoicesVatPrcToVatRate < ActiveRecord::Migration
def change
rename_column :invoices, :vat_prc, :vat_rate
end
end

View file

@ -0,0 +1,5 @@
class ChangeInvoicesVatRateType < ActiveRecord::Migration
def change
change_column :invoices, :vat_rate, :decimal, precision: 4, scale: 3
end
end

View file

@ -0,0 +1,5 @@
class ChangeInvoiceVatRateToNull < ActiveRecord::Migration
def change
change_column_null :invoices, :vat_rate, true
end
end

View file

@ -0,0 +1,5 @@
class RemoveRegistrarsVat < ActiveRecord::Migration
def change
remove_column :registrars, :vat, :boolean
end
end

View file

@ -0,0 +1,5 @@
class RemoveInvoicesInvoiceType < ActiveRecord::Migration
def change
remove_column :invoices, :invoice_type, :string
end
end

View file

@ -0,0 +1,5 @@
class RenameInvoicesSumCacheToTotal < ActiveRecord::Migration
def change
rename_column :invoices, :sum_cache, :total
end
end

View file

@ -0,0 +1,5 @@
class ChangeInvoicesTotalToNotNull < ActiveRecord::Migration
def change
change_column_null :invoices, :total, false
end
end

View file

@ -0,0 +1,5 @@
class AddInvoicesBuyerVatNo < ActiveRecord::Migration
def change
add_column :invoices, :buyer_vat_no, :string
end
end

View file

@ -997,13 +997,12 @@ CREATE TABLE invoices (
id integer NOT NULL, id integer NOT NULL,
created_at timestamp without time zone NOT NULL, created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL, updated_at timestamp without time zone NOT NULL,
invoice_type character varying NOT NULL,
due_date timestamp without time zone NOT NULL, due_date timestamp without time zone NOT NULL,
payment_term character varying, payment_term character varying,
currency character varying NOT NULL, currency character varying NOT NULL,
description character varying, description character varying,
reference_no character varying, reference_no character varying,
vat_prc numeric(10,2) NOT NULL, vat_rate numeric(4,3),
paid_at timestamp without time zone, paid_at timestamp without time zone,
seller_id integer, seller_id integer,
seller_name character varying NOT NULL, seller_name character varying NOT NULL,
@ -1036,8 +1035,9 @@ CREATE TABLE invoices (
updator_str character varying, updator_str character varying,
number integer, number integer,
cancelled_at timestamp without time zone, cancelled_at timestamp without time zone,
sum_cache numeric(10,2), total numeric(10,2) NOT NULL,
in_directo boolean DEFAULT false in_directo boolean DEFAULT false,
buyer_vat_no character varying
); );
@ -2153,11 +2153,11 @@ CREATE TABLE registrars (
code character varying NOT NULL, code character varying NOT NULL,
website character varying, website character varying,
accounting_customer_code character varying NOT NULL, accounting_customer_code character varying NOT NULL,
vat boolean,
legacy_id integer, legacy_id integer,
reference_no character varying, reference_no character varying,
test_registrar boolean DEFAULT false, test_registrar boolean DEFAULT false,
language character varying NOT NULL language character varying NOT NULL,
vat_rate numeric(4,3)
); );
@ -4668,6 +4668,16 @@ INSERT INTO schema_migrations (version) VALUES ('20180214213743');
INSERT INTO schema_migrations (version) VALUES ('20180218004148'); INSERT INTO schema_migrations (version) VALUES ('20180218004148');
INSERT INTO schema_migrations (version) VALUES ('20180228055259');
INSERT INTO schema_migrations (version) VALUES ('20180228064342');
INSERT INTO schema_migrations (version) VALUES ('20180228070102');
INSERT INTO schema_migrations (version) VALUES ('20180228070431');
INSERT INTO schema_migrations (version) VALUES ('20180228074442');
INSERT INTO schema_migrations (version) VALUES ('20180306180401'); INSERT INTO schema_migrations (version) VALUES ('20180306180401');
INSERT INTO schema_migrations (version) VALUES ('20180306181538'); INSERT INTO schema_migrations (version) VALUES ('20180306181538');
@ -4694,5 +4704,13 @@ INSERT INTO schema_migrations (version) VALUES ('20180309053921');
INSERT INTO schema_migrations (version) VALUES ('20180309054510'); INSERT INTO schema_migrations (version) VALUES ('20180309054510');
INSERT INTO schema_migrations (version) VALUES ('20180310142630');
INSERT INTO schema_migrations (version) VALUES ('20180313090437');
INSERT INTO schema_migrations (version) VALUES ('20180313124751');
INSERT INTO schema_migrations (version) VALUES ('20180314122722');
INSERT INTO schema_migrations (version) VALUES ('20180327151906'); INSERT INTO schema_migrations (version) VALUES ('20180327151906');

View file

@ -1488,7 +1488,6 @@
<text text-anchor="start" x="1600.5" y="-2399.3" font-family="Times,serif" font-size="14.00">zip :string</text> <text text-anchor="start" x="1600.5" y="-2399.3" font-family="Times,serif" font-size="14.00">zip :string</text>
<text text-anchor="start" x="1600.5" y="-2384.3" font-family="Times,serif" font-size="14.00">code :string</text> <text text-anchor="start" x="1600.5" y="-2384.3" font-family="Times,serif" font-size="14.00">code :string</text>
<text text-anchor="start" x="1600.5" y="-2369.3" font-family="Times,serif" font-size="14.00">url :string</text> <text text-anchor="start" x="1600.5" y="-2369.3" font-family="Times,serif" font-size="14.00">url :string</text>
<text text-anchor="start" x="1600.5" y="-2339.3" font-family="Times,serif" font-size="14.00">vat :boolean</text>
<text text-anchor="start" x="1600.5" y="-2324.3" font-family="Times,serif" font-size="14.00">legacy_id :integer</text> <text text-anchor="start" x="1600.5" y="-2324.3" font-family="Times,serif" font-size="14.00">legacy_id :integer</text>
<text text-anchor="start" x="1600.5" y="-2309.3" font-family="Times,serif" font-size="14.00">reference_no :string</text> <text text-anchor="start" x="1600.5" y="-2309.3" font-family="Times,serif" font-size="14.00">reference_no :string</text>
</g> </g>
@ -1613,13 +1612,12 @@
<text text-anchor="start" x="121.5" y="-1571.3" font-family="Times,serif" font-size="14.00">id :integer</text> <text text-anchor="start" x="121.5" y="-1571.3" font-family="Times,serif" font-size="14.00">id :integer</text>
<text text-anchor="start" x="121.5" y="-1556.3" font-family="Times,serif" font-size="14.00">created_at :datetime</text> <text text-anchor="start" x="121.5" y="-1556.3" font-family="Times,serif" font-size="14.00">created_at :datetime</text>
<text text-anchor="start" x="121.5" y="-1541.3" font-family="Times,serif" font-size="14.00">updated_at :datetime</text> <text text-anchor="start" x="121.5" y="-1541.3" font-family="Times,serif" font-size="14.00">updated_at :datetime</text>
<text text-anchor="start" x="121.5" y="-1526.3" font-family="Times,serif" font-size="14.00">invoice_type :string</text>
<text text-anchor="start" x="121.5" y="-1511.3" font-family="Times,serif" font-size="14.00">due_date :datetime</text> <text text-anchor="start" x="121.5" y="-1511.3" font-family="Times,serif" font-size="14.00">due_date :datetime</text>
<text text-anchor="start" x="121.5" y="-1496.3" font-family="Times,serif" font-size="14.00">payment_term :string</text> <text text-anchor="start" x="121.5" y="-1496.3" font-family="Times,serif" font-size="14.00">payment_term :string</text>
<text text-anchor="start" x="121.5" y="-1481.3" font-family="Times,serif" font-size="14.00">currency :string</text> <text text-anchor="start" x="121.5" y="-1481.3" font-family="Times,serif" font-size="14.00">currency :string</text>
<text text-anchor="start" x="121.5" y="-1466.3" font-family="Times,serif" font-size="14.00">description :string</text> <text text-anchor="start" x="121.5" y="-1466.3" font-family="Times,serif" font-size="14.00">description :string</text>
<text text-anchor="start" x="121.5" y="-1451.3" font-family="Times,serif" font-size="14.00">reference_no :string</text> <text text-anchor="start" x="121.5" y="-1451.3" font-family="Times,serif" font-size="14.00">reference_no :string</text>
<text text-anchor="start" x="121.5" y="-1436.3" font-family="Times,serif" font-size="14.00">vat_prc :decimal</text> <text text-anchor="start" x="121.5" y="-1436.3" font-family="Times,serif" font-size="14.00">vat_rate :decimal</text>
<text text-anchor="start" x="121.5" y="-1421.3" font-family="Times,serif" font-size="14.00">paid_at :datetime</text> <text text-anchor="start" x="121.5" y="-1421.3" font-family="Times,serif" font-size="14.00">paid_at :datetime</text>
<text text-anchor="start" x="121.5" y="-1406.3" font-family="Times,serif" font-size="14.00">seller_id :integer</text> <text text-anchor="start" x="121.5" y="-1406.3" font-family="Times,serif" font-size="14.00">seller_id :integer</text>
<text text-anchor="start" x="121.5" y="-1391.3" font-family="Times,serif" font-size="14.00">seller_name :string</text> <text text-anchor="start" x="121.5" y="-1391.3" font-family="Times,serif" font-size="14.00">seller_name :string</text>
@ -1652,7 +1650,7 @@
<text text-anchor="start" x="121.5" y="-986.3" font-family="Times,serif" font-size="14.00">updator_str :string</text> <text text-anchor="start" x="121.5" y="-986.3" font-family="Times,serif" font-size="14.00">updator_str :string</text>
<text text-anchor="start" x="121.5" y="-971.3" font-family="Times,serif" font-size="14.00">number :integer</text> <text text-anchor="start" x="121.5" y="-971.3" font-family="Times,serif" font-size="14.00">number :integer</text>
<text text-anchor="start" x="121.5" y="-956.3" font-family="Times,serif" font-size="14.00">cancelled_at :datetime</text> <text text-anchor="start" x="121.5" y="-956.3" font-family="Times,serif" font-size="14.00">cancelled_at :datetime</text>
<text text-anchor="start" x="121.5" y="-941.3" font-family="Times,serif" font-size="14.00">sum_cache :decimal</text> <text text-anchor="start" x="121.5" y="-941.3" font-family="Times,serif" font-size="14.00">total :decimal</text>
</g> </g>
<!-- Registrar&#45;&gt;Invoice --> <!-- Registrar&#45;&gt;Invoice -->
<g id="edge64" class="edge"><title>Registrar&#45;&gt;Invoice</title> <g id="edge64" class="edge"><title>Registrar&#45;&gt;Invoice</title>

Before

Width:  |  Height:  |  Size: 220 KiB

After

Width:  |  Height:  |  Size: 220 KiB

Before After
Before After

33
docker-compose.yml Normal file
View file

@ -0,0 +1,33 @@
version: "3.2"
services:
app:
tty: true
stdin_open: true
build:
context: .
dockerfile: Dockerfile
links:
- db
environment:
- APP_DBHOST=db
volumes:
- .:/opt/webapps/app
ports:
- "3000:3000"
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails server -p 3000 -b '0.0.0.0'"
web:
image: nginx
volumes:
- ./docker/nginx.template:/etc/nginx/conf.d/nginx.template
ports:
- "80:80"
links:
- app
environment:
APP: 'app'
command: /bin/bash -c "envsubst '$$APP' < /etc/nginx/conf.d/nginx.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"
db:
image: postgres:9.4

6
docker/docker_dev.sh Executable file
View file

@ -0,0 +1,6 @@
# /bin/sh
docker-compose down
docker-compose build
docker-compose run app rake db:setup:all
docker-compose run app rake db:migrate
docker-compose run app rake dev:prime

8
docker/docker_test.sh Executable file
View file

@ -0,0 +1,8 @@
# /bin/sh
docker-compose down
docker-compose build
# Setup test database
docker-compose run app rake db:setup:all test
# Finally run tests to check if everything is in order
docker-compose run app rspec

29
docker/nginx.template Normal file
View file

@ -0,0 +1,29 @@
log_format le_json '{ "time": "$time_iso8601", '
'"remote_addr": "$remote_addr", '
'"remote_user": "$remote_user", '
'"body_bytes_sent": "$body_bytes_sent", '
'"request_time": "$request_time", '
'"status": "$status", '
'"request": "$request", '
'"request_method": "$request_method", '
'"http_referrer": "$http_referer", '
'"http_user_agent": "$http_user_agent" }';
upstream app {
server ${APP}:3000;
}
server {
listen 80;
access_log /var/log/nginx/access.log le_json;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app;
break;
}
}

View file

@ -87,7 +87,6 @@ namespace :import do
zip: x.postalcode.try(:strip), zip: x.postalcode.try(:strip),
url: x.url.try(:strip), url: x.url.try(:strip),
accounting_customer_code: x.directo_handle.try(:strip), accounting_customer_code: x.directo_handle.try(:strip),
vat: x.vat,
legacy_id: x.id, legacy_id: x.id,
creator_str: user, creator_str: user,
updator_str: user, updator_str: user,

View file

@ -3,12 +3,11 @@ FactoryBot.define do
buyer_name 'Registrar 1' buyer_name 'Registrar 1'
currency { 'EUR' } currency { 'EUR' }
due_date { Time.zone.now.to_date + 1.day } due_date { Time.zone.now.to_date + 1.day }
invoice_type 'DEB'
seller_iban { '123' } seller_iban { '123' }
seller_name { 'EIS' } seller_name { 'EIS' }
seller_city { 'Tallinn' } seller_city { 'Tallinn' }
seller_street { 'Paldiski mnt. 123' } seller_street { 'Paldiski mnt. 123' }
vat_prc 0.2 vat_rate 0.2
buyer { FactoryBot.create(:registrar) } buyer { FactoryBot.create(:registrar) }
after :build do |invoice| after :build do |invoice|

View file

@ -13,10 +13,8 @@ describe Invoice do
"Currency is missing", "Currency is missing",
"Due date is missing", "Due date is missing",
"Invoice items is missing", "Invoice items is missing",
"Invoice type is missing",
"Seller iban is missing", "Seller iban is missing",
"Seller name is missing", "Seller name is missing",
"Vat prc is missing"
]) ])
end end
@ -52,20 +50,6 @@ describe Invoice do
@invoice.seller_address.should == 'Paldiski mnt. 123, Tallinn' @invoice.seller_address.should == 'Paldiski mnt. 123, Tallinn'
end end
it 'should calculate sums correctly' do
@invoice = create(:invoice)
@invoice.vat_prc.should == BigDecimal.new('0.2')
@invoice.sum_without_vat.should == BigDecimal.new('300.0')
@invoice.vat.should == BigDecimal.new('60.0')
@invoice.sum.should == BigDecimal.new('360.0')
ii = @invoice.items.first
ii.item_sum_without_vat.should == BigDecimal.new('150.0')
ii = @invoice.items.last
ii.item_sum_without_vat.should == BigDecimal.new('150.0')
end
it 'should cancel overdue invoices' do it 'should cancel overdue invoices' do
create(:invoice, created_at: Time.zone.now - 35.days, due_date: Time.zone.now - 30.days) create(:invoice, created_at: Time.zone.now - 35.days, due_date: Time.zone.now - 30.days)
Invoice.cancel_overdue_invoices Invoice.cancel_overdue_invoices

View file

@ -1,7 +1,31 @@
cash: create_one_month:
duration: 1 year duration: 1 month
price_cents: 500 price_cents: 100
operation_category: create operation_category: create
valid_from: 2010-07-05 valid_from: 2010-07-05
valid_to: 2010-07-05 valid_to: 2010-07-05
zone: test zone: test
renew_one_month:
duration: 1 month
price_cents: 100
operation_category: renew
valid_from: 2010-07-05
valid_to: 2010-07-05
zone: test
create_one_year:
duration: 1 year
price_cents: 1000
operation_category: create
valid_from: 2010-07-05
valid_to: 2010-07-05
zone: test
renew_one_year:
duration: 1 year
price_cents: 1000
operation_category: renew
valid_from: 2010-07-05
valid_to: 2010-07-05
zone: test

View file

@ -40,7 +40,7 @@ metro:
invalid: invalid:
name: invalid.test name: invalid.test
transfer_code: any transfer_code: 1438d6
valid_to: 2010-07-05 valid_to: <%= Time.zone.parse('2010-07-05').utc.to_s(:db) %>
registrar: bestnames registrar: bestnames
registrant: invalid registrant: invalid

View file

@ -1,13 +1,13 @@
DEFAULTS: &DEFAULTS one:
description: Acme services description: Acme services
price: 5
amount: 1
unit: pc
invoice: valid
two:
description: Acme services
price: 5
amount: 2 amount: 2
unit: pc unit: pc
price: 5
valid:
<<: *DEFAULTS
invoice: valid
another:
<<: *DEFAULTS
invoice: valid invoice: valid

View file

@ -1,12 +1,13 @@
DEFAULTS: &DEFAULTS DEFAULTS: &DEFAULTS
created_at: <%= Date.parse '2010-07-05' %> created_at: <%= Date.parse '2010-07-05' %>
due_date: <%= Date.parse '2010-07-06' %> due_date: <%= Date.parse '2010-07-06' %>
invoice_type: DEB
currency: EUR currency: EUR
seller_name: John Doe seller_name: John Doe
seller_iban: 1234 seller_iban: 1234
buyer: bestnames
buyer_name: Jane Doe buyer_name: Jane Doe
vat_prc: 0.2 vat_rate: 0.1
total: 16.50
valid: valid:
<<: *DEFAULTS <<: *DEFAULTS
@ -21,7 +22,7 @@ cancelled:
paid: paid:
<<: *DEFAULTS <<: *DEFAULTS
sum_cache: 1 total: 1
outstanding: outstanding:
<<: *DEFAULTS <<: *DEFAULTS

View file

@ -17,7 +17,8 @@ goodnames:
reg_no: 12345 reg_no: 12345
code: goodnames code: goodnames
email: info@goodnames.test email: info@goodnames.test
country_code: US country_code: DE
vat_no: DE123456789
accounting_customer_code: goodnames accounting_customer_code: goodnames
language: en language: en
@ -29,3 +30,23 @@ not_in_use:
country_code: US country_code: US
accounting_customer_code: any accounting_customer_code: any
language: en language: en
complete:
name: Complete Names
reg_no: 123456
code: completenames
email: completenames@example.com
country_code: US
accounting_customer_code: US0001
language: en
vat_no: US12345
vat_rate: 0.05
not_in_use:
name: any
reg_no: any
code: any
email: any@example.com
country_code: US
accounting_customer_code: any
language: en

View file

@ -3,7 +3,7 @@ require 'test_helper'
class AdminAreaDomainForceDeleteTest < ActionDispatch::IntegrationTest class AdminAreaDomainForceDeleteTest < ActionDispatch::IntegrationTest
include ActionMailer::TestHelper include ActionMailer::TestHelper
def setup setup do
login_as users(:admin) login_as users(:admin)
@domain = domains(:shop) @domain = domains(:shop)
ActionMailer::Base.deliveries.clear ActionMailer::Base.deliveries.clear

View file

@ -1,7 +1,7 @@
require 'test_helper' require 'test_helper'
class AdminDomainsTestTest < ActionDispatch::IntegrationTest class AdminDomainsTestTest < ActionDispatch::IntegrationTest
def setup setup do
login_as users(:admin) login_as users(:admin)
end end

View file

@ -0,0 +1,14 @@
require 'test_helper'
class AdminAreaNewMailTemplateTest < ActionDispatch::IntegrationTest
setup do
login_as users(:admin)
end
def test_new_mail_template_does_not_throw_template_error
visit admin_mail_templates_url
click_link_or_button 'New'
assert_text "HTML body"
assert_text "New mail template"
end
end

View file

@ -1,7 +1,7 @@
require 'test_helper' require 'test_helper'
class AdminAreaDeleteRegistrarTest < ActionDispatch::IntegrationTest class AdminAreaDeleteRegistrarTest < ActionDispatch::IntegrationTest
def setup setup do
login_as users(:admin) login_as users(:admin)
end end

View file

@ -0,0 +1,18 @@
require 'test_helper'
class AdminAreaRegistrarDetailsTest < ActionDispatch::IntegrationTest
include ActionView::Helpers::NumberHelper
setup do
login_as users(:admin)
@registrar = registrars(:complete)
end
def test_registrar_details
visit admin_registrar_path(@registrar)
assert_text 'Accounting customer code US0001'
assert_text 'VAT number US12345'
assert_text 'VAT rate 5.0%'
assert_text 'Language English'
end
end

View file

@ -1,7 +1,7 @@
require 'test_helper' require 'test_helper'
class AdminAreaEditRegistrarTest < ActionDispatch::IntegrationTest class AdminAreaEditRegistrarTest < ActionDispatch::IntegrationTest
def setup setup do
login_as users(:admin) login_as users(:admin)
@registrar = registrars(:bestnames) @registrar = registrars(:bestnames)
end end

View file

@ -1,7 +1,7 @@
require 'test_helper' require 'test_helper'
class AdminAreaNewRegistrarTest < ActionDispatch::IntegrationTest class AdminAreaNewRegistrarTest < ActionDispatch::IntegrationTest
def setup setup do
login_as users(:admin) login_as users(:admin)
end end
@ -12,6 +12,7 @@ class AdminAreaNewRegistrarTest < ActionDispatch::IntegrationTest
fill_in 'Name', with: 'Brand new names' fill_in 'Name', with: 'Brand new names'
fill_in 'Reg no', with: '55555555' fill_in 'Reg no', with: '55555555'
fill_in 'Contact e-mail', with: 'test@example.com' fill_in 'Contact e-mail', with: 'test@example.com'
select 'United States', from: 'Country'
fill_in 'Accounting customer code', with: 'test' fill_in 'Accounting customer code', with: 'test'
fill_in 'Code', with: 'test' fill_in 'Code', with: 'test'

View file

@ -1,19 +0,0 @@
require 'test_helper'
class ShowRegistrarTest < ActionDispatch::IntegrationTest
include ActionView::Helpers::NumberHelper
def setup
login_as users(:admin)
@registrar = registrars(:bestnames)
visit admin_registrar_path(@registrar)
end
def test_accounting_customer_code
assert_text 'bestnames'
end
def test_language
assert_text 'Language English'
end
end

View file

@ -1,7 +1,7 @@
require 'test_helper' require 'test_helper'
class APIDomainTransfersTest < ActionDispatch::IntegrationTest class APIDomainTransfersTest < ActionDispatch::IntegrationTest
def setup setup do
@domain = domains(:shop) @domain = domains(:shop)
@new_registrar = registrars(:goodnames) @new_registrar = registrars(:goodnames)
Setting.transfer_wait_time = 0 # Auto-approval Setting.transfer_wait_time = 0 # Auto-approval

View file

@ -1,7 +1,7 @@
require 'test_helper' require 'test_helper'
class EppDomainCreateTransferCodeTest < ActionDispatch::IntegrationTest class EppDomainCreateTransferCodeTest < ActionDispatch::IntegrationTest
def setup setup do
travel_to Time.zone.parse('2010-07-05') travel_to Time.zone.parse('2010-07-05')
end end

View file

@ -0,0 +1,32 @@
require 'test_helper'
class EppDomainRenewTest < ActionDispatch::IntegrationTest
self.use_transactional_fixtures = false
setup do
travel_to Time.zone.parse('2010-07-05')
end
def test_domain_cannot_be_renewed_when_invalid
request_xml = <<-XML
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<epp xmlns="https://epp.tld.ee/schema/epp-ee-1.0.xsd">
<command>
<renew>
<domain:renew xmlns:domain="https://epp.tld.ee/schema/domain-eis-1.0.xsd">
<domain:name>invalid.test</domain:name>
<domain:curExpDate>2010-07-05</domain:curExpDate>
<domain:period unit="m">1</domain:period>
</domain:renew>
</renew>
</command>
</epp>
XML
assert_no_changes -> { domains(:invalid).valid_to } do
post '/epp/command/renew', { frame: request_xml }, 'HTTP_COOKIE' => 'session=api_bestnames'
end
assert_equal '2304', Nokogiri::XML(response.body).at_css('result')[:code],
Nokogiri::XML(response.body).css('result').text
end
end

View file

@ -1,7 +1,7 @@
require 'test_helper' require 'test_helper'
class EppDomainTransferRequestTest < ActionDispatch::IntegrationTest class EppDomainTransferRequestTest < ActionDispatch::IntegrationTest
def setup setup do
@domain = domains(:shop) @domain = domains(:shop)
@new_registrar = registrars(:goodnames) @new_registrar = registrars(:goodnames)
Setting.transfer_wait_time = 0 Setting.transfer_wait_time = 0

View file

@ -1,7 +1,7 @@
require 'test_helper' require 'test_helper'
class EppLoginSessionLimitTest < ActionDispatch::IntegrationTest class EppLoginSessionLimitTest < ActionDispatch::IntegrationTest
def setup setup do
travel_to Time.zone.parse('2010-07-05') travel_to Time.zone.parse('2010-07-05')
EppSession.delete_all EppSession.delete_all
end end

View file

@ -1,7 +1,7 @@
require 'test_helper' require 'test_helper'
class RegistrantDomainsTest < ActionDispatch::IntegrationTest class RegistrantDomainsTest < ActionDispatch::IntegrationTest
def setup setup do
login_as users(:registrant) login_as users(:registrant)
Setting.days_to_keep_business_registry_cache = 1 Setting.days_to_keep_business_registry_cache = 1

View file

@ -0,0 +1,25 @@
require 'test_helper'
class BalanceTopUpTest < ActionDispatch::IntegrationTest
setup do
login_as users(:api_bestnames)
end
def test_creates_new_invoice
Setting.registry_vat_prc = 0.1
visit registrar_invoices_url
click_link_or_button 'Add deposit'
fill_in 'Amount', with: '25.5'
assert_difference 'Invoice.count' do
click_link_or_button 'Add'
end
invoice = Invoice.last
assert_equal BigDecimal(10), invoice.vat_rate
assert_equal BigDecimal('28.05'), invoice.total
assert_text 'Please pay the following invoice'
end
end

View file

@ -1,7 +1,7 @@
require 'test_helper' require 'test_helper'
class RegistrarDomainTransfersTest < ActionDispatch::IntegrationTest class RegistrarDomainTransfersTest < ActionDispatch::IntegrationTest
def setup setup do
WebMock.reset! WebMock.reset!
login_as users(:api_goodnames) login_as users(:api_goodnames)
end end

View file

@ -9,7 +9,7 @@ class RegistrarDomainsTest < ActionDispatch::IntegrationTest
Domain,Transfer code,Registrant name,Registrant code,Date of expiry Domain,Transfer code,Registrant name,Registrant code,Date of expiry
library.test,45118f5,Acme Ltd,acme-ltd-001,2010-07-05 library.test,45118f5,Acme Ltd,acme-ltd-001,2010-07-05
shop.test,65078d5,John,john-001,2010-07-05 shop.test,65078d5,John,john-001,2010-07-05
invalid.test,any,any,any,2010-07-05 invalid.test,1438d6,any,any,2010-07-05
airport.test,55438j5,John,john-001,2010-07-05 airport.test,55438j5,John,john-001,2010-07-05
CSV CSV

View file

@ -1,7 +1,7 @@
require 'test_helper' require 'test_helper'
class RegistrarNameserverReplacementTest < ActionDispatch::IntegrationTest class RegistrarNameserverReplacementTest < ActionDispatch::IntegrationTest
def setup setup do
WebMock.reset! WebMock.reset!
login_as users(:api_goodnames) login_as users(:api_goodnames)
end end

View file

@ -1,7 +1,7 @@
require 'test_helper' require 'test_helper'
class ContactTest < ActiveSupport::TestCase class ContactTest < ActiveSupport::TestCase
def setup setup do
@contact = contacts(:john) @contact = contacts(:john)
end end

View file

@ -12,11 +12,16 @@ class ContactIdenticalTest < ActiveSupport::TestCase
org_name org_name
] ]
def setup setup do
@original_address_processing = Setting.address_processing
@contact = contacts(:william) @contact = contacts(:william)
@identical = contacts(:identical_to_william) @identical = contacts(:identical_to_william)
end end
teardown do
Setting.address_processing = @original_address_processing
end
def test_returns_identical def test_returns_identical
assert_equal @identical, @contact.identical(@identical.registrar) assert_equal @identical, @contact.identical(@identical.registrar)
end end
@ -33,30 +38,24 @@ class ContactIdenticalTest < ActiveSupport::TestCase
assert_nil @contact.identical(@identical.registrar) assert_nil @contact.identical(@identical.registrar)
end end
def test_takes_address_into_account_when_processing_enabled def test_takes_address_into_account_when_address_processing_is_on
Setting.address_processing = true
Contact.address_attribute_names.each do |attribute| Contact.address_attribute_names.each do |attribute|
previous_value = @identical.public_send(attribute) previous_value = @identical.public_send(attribute)
@identical.update_attribute(attribute, 'other') @identical.update_attribute(attribute, 'other')
assert_nil @contact.identical(@identical.registrar)
Contact.stub :address_processing?, true do
assert_nil @contact.identical(@identical.registrar)
end
@identical.update_attribute(attribute, previous_value) @identical.update_attribute(attribute, previous_value)
end end
end end
def test_ignores_address_when_processing_disabled def test_ignores_address_when_address_processing_is_off
Setting.address_processing = false Setting.address_processing = false
Contact.address_attribute_names.each do |attribute| Contact.address_attribute_names.each do |attribute|
previous_value = @identical.public_send(attribute) previous_value = @identical.public_send(attribute)
@identical.update_attribute(attribute, 'other') @identical.update_attribute(attribute, 'other')
assert_equal @identical, @contact.identical(@identical.registrar)
Contact.stub :address_processing?, false do
assert_equal @identical, @contact.identical(@identical.registrar)
end
@identical.update_attribute(attribute, previous_value) @identical.update_attribute(attribute, previous_value)
end end
end end

View file

@ -1,10 +1,15 @@
require 'test_helper' require 'test_helper'
class ContactPostalAddressTest < ActiveSupport::TestCase class ContactPostalAddressTest < ActiveSupport::TestCase
def setup setup do
@original_address_processing = Setting.address_processing
@contact = contacts(:john) @contact = contacts(:john)
end end
teardown do
Setting.address_processing = @original_address_processing
end
def test_invalid_if_country_code_is_invalid_and_address_processing_is_on def test_invalid_if_country_code_is_invalid_and_address_processing_is_on
Setting.address_processing = true Setting.address_processing = true
@contact.country_code = 'invalid' @contact.country_code = 'invalid'

View file

@ -1,7 +1,7 @@
require 'test_helper' require 'test_helper'
class ContactTransferTest < ActiveSupport::TestCase class ContactTransferTest < ActiveSupport::TestCase
def setup setup do
@contact = contacts(:john) @contact = contacts(:john)
@new_registrar = registrars(:goodnames) @new_registrar = registrars(:goodnames)
end end

View file

@ -1,7 +1,7 @@
require 'test_helper' require 'test_helper'
class DomainTest < ActiveSupport::TestCase class DomainTest < ActiveSupport::TestCase
def setup setup do
@domain = domains(:shop) @domain = domains(:shop)
end end

View file

@ -1,7 +1,7 @@
require 'test_helper' require 'test_helper'
class DomainTransferableTest < ActiveSupport::TestCase class DomainTransferableTest < ActiveSupport::TestCase
def setup setup do
@domain = domains(:shop) @domain = domains(:shop)
@new_registrar = registrars(:goodnames) @new_registrar = registrars(:goodnames)
end end

View file

@ -1,7 +1,7 @@
require 'test_helper' require 'test_helper'
class DomainTransferTest < ActiveSupport::TestCase class DomainTransferTest < ActiveSupport::TestCase
def setup setup do
@domain_transfer = domain_transfers(:shop) @domain_transfer = domain_transfers(:shop)
end end

View file

@ -1,7 +1,7 @@
require 'test_helper' require 'test_helper'
class EppSessionTest < ActiveSupport::TestCase class EppSessionTest < ActiveSupport::TestCase
def setup setup do
@epp_session = epp_sessions(:api_bestnames) @epp_session = epp_sessions(:api_bestnames)
end end

109
test/models/invoice_test.rb Normal file
View file

@ -0,0 +1,109 @@
require 'test_helper'
class InvoiceTest < ActiveSupport::TestCase
setup do
@invoice = invoices(:valid)
end
def test_valid
assert @invoice.valid?
end
def test_optional_vat_rate
@invoice.vat_rate = nil
assert @invoice.valid?
end
def test_vat_rate_validation
@invoice.vat_rate = -1
assert @invoice.invalid?
@invoice.vat_rate = 0
assert @invoice.valid?
@invoice.vat_rate = 99.9
assert @invoice.valid?
@invoice.vat_rate = 100
assert @invoice.invalid?
end
def test_serializes_and_deserializes_vat_rate
invoice = @invoice.dup
invoice.invoice_items = @invoice.invoice_items
invoice.vat_rate = BigDecimal('25.5')
invoice.save!
invoice.reload
assert_equal BigDecimal('25.5'), invoice.vat_rate
end
def test_vat_rate_defaults_to_effective_vat_rate_of_a_registrar
registrar = registrars(:bestnames)
invoice = @invoice.dup
invoice.vat_rate = nil
invoice.buyer = registrar
invoice.invoice_items = @invoice.invoice_items
registrar.stub(:effective_vat_rate, BigDecimal(55)) do
invoice.save!
end
assert_equal BigDecimal(55), invoice.vat_rate
end
def test_vat_rate_cannot_be_updated
@invoice.vat_rate = BigDecimal(21)
@invoice.save!
@invoice.reload
refute_equal BigDecimal(21), @invoice.vat_rate
end
def test_calculates_vat_amount
assert_equal BigDecimal('1.5'), @invoice.vat_amount
end
def test_vat_amount_is_zero_when_vat_rate_is_blank
@invoice.vat_rate = nil
assert_equal 0, @invoice.vat_amount
end
def test_calculates_subtotal
line_item = InvoiceItem.new
invoice = Invoice.new(invoice_items: [line_item, line_item])
line_item.stub(:item_sum_without_vat, BigDecimal('2.5')) do
assert_equal BigDecimal(5), invoice.subtotal
end
end
def test_returns_persisted_total
assert_equal BigDecimal('16.50'), @invoice.total
end
def test_calculates_total
line_item = InvoiceItem.new
invoice = Invoice.new
invoice.vat_rate = 10
invoice.invoice_items = [line_item, line_item]
line_item.stub(:item_sum_without_vat, BigDecimal('2.5')) do
assert_equal BigDecimal('5.50'), invoice.total
end
end
def test_valid_without_buyer_vat_no
@invoice.buyer_vat_no = ''
assert @invoice.valid?
end
def test_buyer_vat_no_is_taken_from_registrar_by_default
registrar = registrars(:bestnames)
registrar.vat_no = 'US1234'
invoice = @invoice.dup
invoice.buyer_vat_no = nil
invoice.buyer = registrar
invoice.invoice_items = @invoice.invoice_items
invoice.save!
assert_equal 'US1234', invoice.buyer_vat_no
end
end

View file

@ -1,7 +1,7 @@
require 'test_helper' require 'test_helper'
class MessageTest < ActiveSupport::TestCase class MessageTest < ActiveSupport::TestCase
def setup setup do
@message = messages(:greeting) @message = messages(:greeting)
end end

View file

@ -1,7 +1,7 @@
require 'test_helper' require 'test_helper'
class NameserverGlueRecordTest < ActiveSupport::TestCase class NameserverGlueRecordTest < ActiveSupport::TestCase
def setup setup do
@nameserver = nameservers(:shop_ns1) @nameserver = nameservers(:shop_ns1)
end end

View file

@ -1,7 +1,7 @@
require 'test_helper' require 'test_helper'
class NameserverTest < ActiveSupport::TestCase class NameserverTest < ActiveSupport::TestCase
def setup setup do
@nameserver = nameservers(:shop_ns1) @nameserver = nameservers(:shop_ns1)
end end

View file

@ -1,7 +1,7 @@
require 'test_helper' require 'test_helper'
class RegistrarCodeTest < ActiveSupport::TestCase class RegistrarCodeTest < ActiveSupport::TestCase
def setup setup do
@registrar = registrars(:bestnames).dup @registrar = registrars(:bestnames).dup
end end

View file

@ -1,7 +1,7 @@
require 'test_helper' require 'test_helper'
class DeleteRegistrarTest < ActiveSupport::TestCase class DeleteRegistrarTest < ActiveSupport::TestCase
def setup setup do
@registrar = registrars(:not_in_use) @registrar = registrars(:not_in_use)
end end

View file

@ -0,0 +1,97 @@
require 'test_helper'
class RegistrarVATTest < ActiveSupport::TestCase
setup do
@registrar = registrars(:bestnames)
end
def test_optional_vat_no
@registrar.vat_no = ''
assert @registrar.valid?
@registrar.vat_no = 'any'
assert @registrar.valid?
end
def test_apply_vat_rate_from_registry_when_registrar_is_local_vat_payer
Setting.registry_country_code = 'US'
@registrar.country_code = 'US'
Registry.instance.stub(:vat_rate, BigDecimal('5.5')) do
assert_equal BigDecimal('5.5'), @registrar.effective_vat_rate
end
end
def test_require_no_vat_rate_when_registrar_is_local_vat_payer
@registrar.vat_rate = 1
assert @registrar.invalid?
@registrar.vat_rate = nil
assert @registrar.valid?
end
def test_apply_vat_rate_from_registrar_when_registrar_is_foreign_vat_payer
Setting.registry_country_code = 'US'
@registrar.country_code = 'DE'
@registrar.vat_rate = BigDecimal('5.6')
assert_equal BigDecimal('5.6'), @registrar.effective_vat_rate
end
def test_require_vat_rate_when_registrar_is_foreign_vat_payer_and_vat_no_is_absent
@registrar.country_code = 'DE'
@registrar.vat_no = ''
@registrar.vat_rate = ''
assert @registrar.invalid?
assert @registrar.errors.added?(:vat_rate, :blank)
@registrar.vat_rate = 5
assert @registrar.valid?
end
def test_require_no_vat_rate_when_registrar_is_foreign_vat_payer_and_vat_no_is_present
@registrar.country_code = 'DE'
@registrar.vat_no = 'valid'
@registrar.vat_rate = 1
assert @registrar.invalid?
@registrar.vat_rate = nil
assert @registrar.valid?
end
def test_vat_rate_validation
@registrar.country_code = 'DE'
@registrar.vat_no = ''
@registrar.vat_rate = -1
assert @registrar.invalid?
@registrar.vat_rate = 0
assert @registrar.valid?
@registrar.vat_rate = 99.9
assert @registrar.valid?
@registrar.vat_rate = 100
assert @registrar.invalid?
end
def test_serializes_and_deserializes_vat_rate
@registrar.country_code = 'DE'
@registrar.vat_rate = BigDecimal('25.5')
@registrar.save!
@registrar.reload
assert_equal BigDecimal('25.5'), @registrar.vat_rate
end
def test_parses_vat_rate_as_a_string
@registrar.vat_rate = '25.5'
assert_equal BigDecimal('25.5'), @registrar.vat_rate
end
def test_treats_empty_vat_rate_as_nil
@registrar.vat_rate = ''
assert_nil @registrar.vat_rate
end
end

View file

@ -1,7 +1,7 @@
require 'test_helper' require 'test_helper'
class RegistrarTest < ActiveSupport::TestCase class RegistrarTest < ActiveSupport::TestCase
def setup setup do
@registrar = registrars(:bestnames) @registrar = registrars(:bestnames)
end end
@ -29,7 +29,7 @@ class RegistrarTest < ActiveSupport::TestCase
assert @registrar.invalid? assert @registrar.invalid?
end end
def test_requires_country_code def test_invalid_without_country_code
@registrar.country_code = '' @registrar.country_code = ''
assert @registrar.invalid? assert @registrar.invalid?
end end

View file

@ -0,0 +1,16 @@
require 'test_helper'
class RegistryTest < ActiveSupport::TestCase
setup do
@registry = Registry.send(:new)
end
def test_implements_singleton
assert_equal Registry.instance.object_id, Registry.instance.object_id
end
def test_vat_rate
Setting.registry_vat_prc = 0.25
assert_equal BigDecimal(25), @registry.vat_rate
end
end

View file

@ -0,0 +1,94 @@
module ActiveSupport
module Testing
module Assertions
UNTRACKED = Object.new # :nodoc:
# Assertion that the result of evaluating an expression is changed before
# and after invoking the passed in block.
#
# assert_changes 'Status.all_good?' do
# post :create, params: { status: { ok: false } }
# end
#
# You can pass the block as a string to be evaluated in the context of
# the block. A lambda can be passed for the block as well.
#
# assert_changes -> { Status.all_good? } do
# post :create, params: { status: { ok: false } }
# end
#
# The assertion is useful to test side effects. The passed block can be
# anything that can be converted to string with #to_s.
#
# assert_changes :@object do
# @object = 42
# end
#
# The keyword arguments :from and :to can be given to specify the
# expected initial value and the expected value after the block was
# executed.
#
# assert_changes :@object, from: nil, to: :foo do
# @object = :foo
# end
#
# An error message can be specified.
#
# assert_changes -> { Status.all_good? }, 'Expected the status to be bad' do
# post :create, params: { status: { incident: true } }
# end
def assert_changes(expression, message = nil, from: UNTRACKED, to: UNTRACKED, &block)
exp = expression.respond_to?(:call) ? expression : -> { eval(expression.to_s, block.binding) }
before = exp.call
retval = yield
unless from == UNTRACKED
error = "#{expression.inspect} isn't #{from.inspect}"
error = "#{message}.\n#{error}" if message
assert from === before, error
end
after = exp.call
if to == UNTRACKED
error = "#{expression.inspect} didn't changed"
error = "#{message}.\n#{error}" if message
assert_not_equal before, after, error
else
error = "#{expression.inspect} didn't change to #{to}"
error = "#{message}.\n#{error}" if message
assert to === after, error
end
retval
end
# Assertion that the result of evaluating an expression is changed before
# and after invoking the passed in block.
#
# assert_no_changes 'Status.all_good?' do
# post :create, params: { status: { ok: true } }
# end
#
# An error message can be specified.
#
# assert_no_changes -> { Status.all_good? }, 'Expected the status to be good' do
# post :create, params: { status: { ok: false } }
# end
def assert_no_changes(expression, message = nil, &block)
exp = expression.respond_to?(:call) ? expression : -> { eval(expression.to_s, block.binding) }
before = exp.call
retval = yield
after = exp.call
error = "#{expression.inspect} did change to #{after}"
error = "#{message}.\n#{error}" if message
assert_equal before, after, error
retval
end
end
end
end

View file

@ -11,14 +11,20 @@ require 'minitest/mock'
require 'capybara/rails' require 'capybara/rails'
require 'capybara/minitest' require 'capybara/minitest'
require 'webmock/minitest' require 'webmock/minitest'
require 'support/rails5_assetions' # Remove once upgraded to Rails 5
Setting.address_processing = false Setting.address_processing = false
Setting.registry_country_code = 'US'
class ActiveSupport::TestCase class ActiveSupport::TestCase
include FactoryBot::Syntax::Methods include FactoryBot::Syntax::Methods
ActiveRecord::Migration.check_pending! ActiveRecord::Migration.check_pending!
fixtures :all fixtures :all
teardown do
travel_back
end
end end
class ActionDispatch::IntegrationTest class ActionDispatch::IntegrationTest
@ -27,8 +33,9 @@ class ActionDispatch::IntegrationTest
include Capybara::Minitest::Assertions include Capybara::Minitest::Assertions
include AbstractController::Translation include AbstractController::Translation
def teardown teardown do
Warden.test_reset! Warden.test_reset!
WebMock.reset!
Capybara.reset_sessions! Capybara.reset_sessions!
Capybara.use_default_driver Capybara.use_default_driver
end end