mirror of
https://github.com/internetee/registry.git
synced 2025-06-08 13:44:47 +02:00
commit
b02df5ef02
45 changed files with 512 additions and 121 deletions
|
@ -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'
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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?
|
||||
|
@ -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
|
||||
|
|
|
@ -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
11
app/models/registry.rb
Normal 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
|
11
app/models/type/vat_rate.rb
Normal file
11
app/models/type/vat_rate.rb
Normal 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
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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 %>
|
||||
|
|
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -15,7 +15,7 @@ require 'rails/all'
|
|||
# you've limited to :test, :development, or :production.
|
||||
Bundler.require(*Rails.groups)
|
||||
|
||||
module Registry
|
||||
module DomainNameRegistry
|
||||
class Application < Rails::Application
|
||||
# Settings in config/environments/* take precedence over those specified here.
|
||||
# Application configuration should go into files in config/initializers
|
||||
|
|
|
@ -19,6 +19,12 @@ en:
|
|||
billing:
|
||||
header: Billing
|
||||
|
||||
edit:
|
||||
header: Edit registrar
|
||||
|
||||
billing:
|
||||
header: Billing
|
||||
|
||||
create:
|
||||
created: Registrar has been successfully created
|
||||
|
||||
|
|
|
@ -538,7 +538,6 @@ en:
|
|||
invoice_number: Invoice no.
|
||||
seller: 'Seller'
|
||||
prepayment: 'Prepayment'
|
||||
vat: 'VAT (%{vat_prc}%)'
|
||||
unpaid: 'Unpaid'
|
||||
your_current_account_balance_is: 'Your current account balance is %{balance} %{currency}'
|
||||
billing: 'Billing'
|
||||
|
@ -556,7 +555,6 @@ en:
|
|||
unit: 'Unit'
|
||||
price: 'Price'
|
||||
total: 'Total'
|
||||
total_without_vat: 'Total without VAT'
|
||||
paid_at: 'Paid at'
|
||||
invoice: 'Invoice'
|
||||
bank_statements: 'Bank statements'
|
||||
|
@ -762,5 +760,6 @@ en:
|
|||
|
||||
attributes:
|
||||
vat_no: VAT number
|
||||
vat_rate: VAT rate
|
||||
ipv4: IPv4
|
||||
ipv6: IPv6
|
||||
|
|
5
db/migrate/20180228055259_add_registrars_vat_rate.rb
Normal file
5
db/migrate/20180228055259_add_registrars_vat_rate.rb
Normal file
|
@ -0,0 +1,5 @@
|
|||
class AddRegistrarsVatRate < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :registrars, :vat_rate, :decimal, precision: 4, scale: 3
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
class RenameInvoicesVatPrcToVatRate < ActiveRecord::Migration
|
||||
def change
|
||||
rename_column :invoices, :vat_prc, :vat_rate
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
class ChangeInvoicesVatRateType < ActiveRecord::Migration
|
||||
def change
|
||||
change_column :invoices, :vat_rate, :decimal, precision: 4, scale: 3
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
class ChangeInvoiceVatRateToNull < ActiveRecord::Migration
|
||||
def change
|
||||
change_column_null :invoices, :vat_rate, true
|
||||
end
|
||||
end
|
5
db/migrate/20180228074442_remove_registrars_vat.rb
Normal file
5
db/migrate/20180228074442_remove_registrars_vat.rb
Normal file
|
@ -0,0 +1,5 @@
|
|||
class RemoveRegistrarsVat < ActiveRecord::Migration
|
||||
def change
|
||||
remove_column :registrars, :vat, :boolean
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
class RemoveInvoicesInvoiceType < ActiveRecord::Migration
|
||||
def change
|
||||
remove_column :invoices, :invoice_type, :string
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
class RenameInvoicesSumCacheToTotal < ActiveRecord::Migration
|
||||
def change
|
||||
rename_column :invoices, :sum_cache, :total
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
class ChangeInvoicesTotalToNotNull < ActiveRecord::Migration
|
||||
def change
|
||||
change_column_null :invoices, :total, false
|
||||
end
|
||||
end
|
5
db/migrate/20180314122722_add_invoices_buyer_vat_no.rb
Normal file
5
db/migrate/20180314122722_add_invoices_buyer_vat_no.rb
Normal file
|
@ -0,0 +1,5 @@
|
|||
class AddInvoicesBuyerVatNo < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :invoices, :buyer_vat_no, :string
|
||||
end
|
||||
end
|
|
@ -998,13 +998,12 @@ CREATE TABLE invoices (
|
|||
id integer NOT NULL,
|
||||
created_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,
|
||||
payment_term character varying,
|
||||
currency character varying NOT NULL,
|
||||
description character varying,
|
||||
reference_no character varying,
|
||||
vat_prc numeric(10,2) NOT NULL,
|
||||
vat_rate numeric(4,3),
|
||||
paid_at timestamp without time zone,
|
||||
seller_id integer,
|
||||
seller_name character varying NOT NULL,
|
||||
|
@ -1037,8 +1036,9 @@ CREATE TABLE invoices (
|
|||
updator_str character varying,
|
||||
number integer,
|
||||
cancelled_at timestamp without time zone,
|
||||
sum_cache numeric(10,2),
|
||||
in_directo boolean DEFAULT false
|
||||
total numeric(10,2) NOT NULL,
|
||||
in_directo boolean DEFAULT false,
|
||||
buyer_vat_no character varying
|
||||
);
|
||||
|
||||
|
||||
|
@ -2154,11 +2154,11 @@ CREATE TABLE registrars (
|
|||
code character varying NOT NULL,
|
||||
website character varying,
|
||||
accounting_customer_code character varying NOT NULL,
|
||||
vat boolean,
|
||||
legacy_id integer,
|
||||
reference_no character varying,
|
||||
test_registrar boolean DEFAULT false,
|
||||
language character varying NOT NULL
|
||||
language character varying NOT NULL,
|
||||
vat_rate numeric(4,3)
|
||||
);
|
||||
|
||||
|
||||
|
@ -4669,6 +4669,16 @@ INSERT INTO schema_migrations (version) VALUES ('20180214213743');
|
|||
|
||||
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 ('20180306181538');
|
||||
|
@ -4695,3 +4705,11 @@ INSERT INTO schema_migrations (version) VALUES ('20180309053921');
|
|||
|
||||
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');
|
||||
|
||||
|
|
|
@ -1489,7 +1489,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="-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="-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="-2309.3" font-family="Times,serif" font-size="14.00">reference_no :string</text>
|
||||
</g>
|
||||
|
@ -1614,13 +1613,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="-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="-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="-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="-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="-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="-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>
|
||||
|
@ -1653,7 +1651,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="-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="-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>
|
||||
<!-- Registrar->Invoice -->
|
||||
<g id="edge64" class="edge"><title>Registrar->Invoice</title>
|
||||
|
|
Before Width: | Height: | Size: 220 KiB After Width: | Height: | Size: 220 KiB |
|
@ -87,7 +87,6 @@ namespace :import do
|
|||
zip: x.postalcode.try(:strip),
|
||||
url: x.url.try(:strip),
|
||||
accounting_customer_code: x.directo_handle.try(:strip),
|
||||
vat: x.vat,
|
||||
legacy_id: x.id,
|
||||
creator_str: user,
|
||||
updator_str: user,
|
||||
|
|
|
@ -3,12 +3,11 @@ FactoryBot.define do
|
|||
buyer_name 'Registrar 1'
|
||||
currency { 'EUR' }
|
||||
due_date { Time.zone.now.to_date + 1.day }
|
||||
invoice_type 'DEB'
|
||||
seller_iban { '123' }
|
||||
seller_name { 'EIS' }
|
||||
seller_city { 'Tallinn' }
|
||||
seller_street { 'Paldiski mnt. 123' }
|
||||
vat_prc 0.2
|
||||
vat_rate 0.2
|
||||
buyer { FactoryBot.create(:registrar) }
|
||||
|
||||
after :build do |invoice|
|
||||
|
|
|
@ -13,10 +13,8 @@ describe Invoice do
|
|||
"Currency is missing",
|
||||
"Due date is missing",
|
||||
"Invoice items is missing",
|
||||
"Invoice type is missing",
|
||||
"Seller iban is missing",
|
||||
"Seller name is missing",
|
||||
"Vat prc is missing"
|
||||
])
|
||||
end
|
||||
|
||||
|
@ -52,20 +50,6 @@ describe Invoice do
|
|||
@invoice.seller_address.should == 'Paldiski mnt. 123, Tallinn'
|
||||
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
|
||||
create(:invoice, created_at: Time.zone.now - 35.days, due_date: Time.zone.now - 30.days)
|
||||
Invoice.cancel_overdue_invoices
|
||||
|
|
18
test/fixtures/invoice_items.yml
vendored
18
test/fixtures/invoice_items.yml
vendored
|
@ -1,13 +1,13 @@
|
|||
DEFAULTS: &DEFAULTS
|
||||
one:
|
||||
description: Acme services
|
||||
price: 5
|
||||
amount: 1
|
||||
unit: pc
|
||||
invoice: valid
|
||||
|
||||
two:
|
||||
description: Acme services
|
||||
price: 5
|
||||
amount: 2
|
||||
unit: pc
|
||||
price: 5
|
||||
|
||||
valid:
|
||||
<<: *DEFAULTS
|
||||
invoice: valid
|
||||
|
||||
another:
|
||||
<<: *DEFAULTS
|
||||
invoice: valid
|
||||
|
|
7
test/fixtures/invoices.yml
vendored
7
test/fixtures/invoices.yml
vendored
|
@ -1,12 +1,13 @@
|
|||
DEFAULTS: &DEFAULTS
|
||||
created_at: <%= Date.parse '2010-07-05' %>
|
||||
due_date: <%= Date.parse '2010-07-06' %>
|
||||
invoice_type: DEB
|
||||
currency: EUR
|
||||
seller_name: John Doe
|
||||
seller_iban: 1234
|
||||
buyer: bestnames
|
||||
buyer_name: Jane Doe
|
||||
vat_prc: 0.2
|
||||
vat_rate: 0.1
|
||||
total: 16.50
|
||||
|
||||
valid:
|
||||
<<: *DEFAULTS
|
||||
|
@ -21,7 +22,7 @@ cancelled:
|
|||
|
||||
paid:
|
||||
<<: *DEFAULTS
|
||||
sum_cache: 1
|
||||
total: 1
|
||||
|
||||
outstanding:
|
||||
<<: *DEFAULTS
|
||||
|
|
23
test/fixtures/registrars.yml
vendored
23
test/fixtures/registrars.yml
vendored
|
@ -17,7 +17,8 @@ goodnames:
|
|||
reg_no: 12345
|
||||
code: goodnames
|
||||
email: info@goodnames.test
|
||||
country_code: US
|
||||
country_code: DE
|
||||
vat_no: DE123456789
|
||||
accounting_customer_code: goodnames
|
||||
language: en
|
||||
|
||||
|
@ -29,3 +30,23 @@ not_in_use:
|
|||
country_code: US
|
||||
accounting_customer_code: any
|
||||
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
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
require 'test_helper'
|
||||
|
||||
class AdminAreaNewMailTemplateTest < ActionDispatch::IntegrationTest
|
||||
def setup
|
||||
setup do
|
||||
login_as users(:admin)
|
||||
end
|
||||
|
||||
|
|
18
test/integration/admin/registrars/details_test.rb
Normal file
18
test/integration/admin/registrars/details_test.rb
Normal 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
|
|
@ -12,6 +12,7 @@ class AdminAreaNewRegistrarTest < ActionDispatch::IntegrationTest
|
|||
fill_in 'Name', with: 'Brand new names'
|
||||
fill_in 'Reg no', with: '55555555'
|
||||
fill_in 'Contact e-mail', with: 'test@example.com'
|
||||
select 'United States', from: 'Country'
|
||||
fill_in 'Accounting customer code', with: 'test'
|
||||
fill_in 'Code', with: 'test'
|
||||
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
require 'test_helper'
|
||||
|
||||
class ShowRegistrarTest < ActionDispatch::IntegrationTest
|
||||
include ActionView::Helpers::NumberHelper
|
||||
|
||||
setup do
|
||||
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
|
25
test/integration/registrar/billing/balance_top_up_test.rb
Normal file
25
test/integration/registrar/billing/balance_top_up_test.rb
Normal 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
|
109
test/models/invoice_test.rb
Normal file
109
test/models/invoice_test.rb
Normal 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
|
97
test/models/registrar/vat_test.rb
Normal file
97
test/models/registrar/vat_test.rb
Normal 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
|
|
@ -29,7 +29,7 @@ class RegistrarTest < ActiveSupport::TestCase
|
|||
assert @registrar.invalid?
|
||||
end
|
||||
|
||||
def test_requires_country_code
|
||||
def test_invalid_without_country_code
|
||||
@registrar.country_code = ''
|
||||
assert @registrar.invalid?
|
||||
end
|
||||
|
|
16
test/models/registry_test.rb
Normal file
16
test/models/registry_test.rb
Normal 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
|
|
@ -14,6 +14,7 @@ require 'webmock/minitest'
|
|||
require 'support/rails5_assetions' # Remove once upgraded to Rails 5
|
||||
|
||||
Setting.address_processing = false
|
||||
Setting.registry_country_code = 'US'
|
||||
|
||||
class ActiveSupport::TestCase
|
||||
include FactoryBot::Syntax::Methods
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue