mirror of
https://github.com/internetee/registry.git
synced 2025-06-11 07:04:47 +02:00
parent
026c36d066
commit
7d72d9cb34
8 changed files with 121 additions and 94 deletions
|
@ -32,9 +32,11 @@ class Invoice < ActiveRecord::Base
|
||||||
validates :vat_rate, numericality: { greater_than_or_equal_to: 0, less_than: 100 },
|
validates :vat_rate, numericality: { greater_than_or_equal_to: 0, less_than: 100 },
|
||||||
allow_nil: true
|
allow_nil: true
|
||||||
|
|
||||||
before_create :set_invoice_number, :check_vat
|
after_initialize :apply_defaults
|
||||||
|
before_create :set_invoice_number
|
||||||
|
|
||||||
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
|
||||||
|
@ -52,12 +54,6 @@ class Invoice < ActiveRecord::Base
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_vat
|
|
||||||
if buyer.country_code != 'EE' && buyer.vat_no.present?
|
|
||||||
self.vat_rate = 0
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
before_save -> { self.sum_cache = sum }
|
before_save -> { self.sum_cache = sum }
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
|
@ -159,10 +155,17 @@ class Invoice < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def vat
|
def vat
|
||||||
|
return 0 unless vat_rate
|
||||||
(sum_without_vat * vat_rate).round(2)
|
(sum_without_vat * vat_rate).round(2)
|
||||||
end
|
end
|
||||||
|
|
||||||
def sum
|
def sum
|
||||||
(sum_without_vat + vat).round(2)
|
(sum_without_vat + vat).round(2)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def apply_defaults
|
||||||
|
self.vat_rate = buyer.effective_vat_rate unless vat_rate
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,8 +18,8 @@ class Registrar < ActiveRecord::Base
|
||||||
validates :accounting_customer_code, presence: true
|
validates :accounting_customer_code, presence: true
|
||||||
validates :language, presence: true
|
validates :language, presence: true
|
||||||
|
|
||||||
validates :vat_rate, presence: true, if: :vat_rate_required?
|
validates :vat_rate, presence: true, if: 'foreign_vat_payer? && vat_no.blank?'
|
||||||
validates :vat_rate, absence: true, if: :local_vat_payer?
|
validates :vat_rate, absence: true, if: :home_vat_payer?
|
||||||
validates :vat_rate, absence: true, if: 'foreign_vat_payer? && vat_no?'
|
validates :vat_rate, absence: true, if: 'foreign_vat_payer? && vat_no?'
|
||||||
validates :vat_rate, numericality: { greater_than_or_equal_to: 0, less_than: 100 },
|
validates :vat_rate, numericality: { greater_than_or_equal_to: 0, less_than: 100 },
|
||||||
allow_nil: true
|
allow_nil: true
|
||||||
|
@ -56,22 +56,11 @@ class Registrar < ActiveRecord::Base
|
||||||
# rubocop:disable Metrics/MethodLength
|
# rubocop:disable Metrics/MethodLength
|
||||||
# rubocop:disable Metrics/AbcSize
|
# rubocop:disable Metrics/AbcSize
|
||||||
def issue_prepayment_invoice(amount, description = nil)
|
def issue_prepayment_invoice(amount, description = nil)
|
||||||
vat_rate = if local_vat_payer?
|
|
||||||
Registry.instance.vat_rate
|
|
||||||
else
|
|
||||||
if vat_no.blank?
|
|
||||||
self.vat_rate
|
|
||||||
else
|
|
||||||
nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
invoices.create(
|
invoices.create(
|
||||||
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_rate: vat_rate,
|
|
||||||
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,
|
||||||
|
@ -157,6 +146,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
|
||||||
|
@ -188,15 +185,11 @@ class Registrar < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def local_vat_payer?
|
def home_vat_payer?
|
||||||
country == Registry.instance.legal_address_country
|
country == Registry.instance.legal_address_country
|
||||||
end
|
end
|
||||||
|
|
||||||
def foreign_vat_payer?
|
def foreign_vat_payer?
|
||||||
!local_vat_payer?
|
!home_vat_payer?
|
||||||
end
|
|
||||||
|
|
||||||
def vat_rate_required?
|
|
||||||
foreign_vat_payer? && vat_no.blank?
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,19 +1,11 @@
|
||||||
module Type
|
module Type
|
||||||
class VATRate < ActiveRecord::Type::Value
|
class VATRate < ActiveRecord::Type::Decimal
|
||||||
def type_cast_from_user(value)
|
|
||||||
if value.blank?
|
|
||||||
nil
|
|
||||||
else
|
|
||||||
super
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def type_cast_from_database(value)
|
def type_cast_from_database(value)
|
||||||
BigDecimal(value) * 100 if value
|
super * 100 if value
|
||||||
end
|
end
|
||||||
|
|
||||||
def type_cast_for_database(value)
|
def type_cast_for_database(value)
|
||||||
BigDecimal(value) / 100.0 if value
|
super / 100.0 if value
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
1
test/fixtures/invoices.yml
vendored
1
test/fixtures/invoices.yml
vendored
|
@ -4,6 +4,7 @@ DEFAULTS: &DEFAULTS
|
||||||
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_rate: 0.2
|
vat_rate: 0.2
|
||||||
|
|
||||||
|
|
3
test/fixtures/registrars.yml
vendored
3
test/fixtures/registrars.yml
vendored
|
@ -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
|
||||||
|
|
||||||
|
|
51
test/models/invoice/vat_rate_test.rb
Normal file
51
test/models/invoice/vat_rate_test.rb
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
require 'test_helper'
|
||||||
|
|
||||||
|
class InvoiceVATRateTest < ActiveSupport::TestCase
|
||||||
|
def setup
|
||||||
|
@invoice = invoices(:valid)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_valid_without_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)
|
||||||
|
|
||||||
|
registrar.stub(:effective_vat_rate, 55) do
|
||||||
|
invoice = Invoice.new(buyer: registrar)
|
||||||
|
assert_equal 55, invoice.vat_rate
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_vat_rate_cannot_be_updated
|
||||||
|
@invoice.vat_rate = 21
|
||||||
|
@invoice.save!
|
||||||
|
@invoice.reload
|
||||||
|
refute_equal 21, @invoice.vat_rate
|
||||||
|
end
|
||||||
|
end
|
|
@ -8,23 +8,4 @@ class InvoiceTest < ActiveSupport::TestCase
|
||||||
def test_valid
|
def test_valid
|
||||||
assert @invoice.valid?
|
assert @invoice.valid?
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_valid_without_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 = 1
|
|
||||||
assert @invoice.valid?
|
|
||||||
|
|
||||||
@invoice.vat_rate = 99.9
|
|
||||||
assert @invoice.valid?
|
|
||||||
|
|
||||||
@invoice.vat_rate = 100
|
|
||||||
assert @invoice.invalid?
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,28 +13,6 @@ class RegistrarVATTest < ActiveSupport::TestCase
|
||||||
assert @registrar.valid?
|
assert @registrar.valid?
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_requires_vat_rate_when_registrar_is_foreign_vat_payer_and_vat_no_is_absent
|
|
||||||
@registrar.vat_no = ''
|
|
||||||
|
|
||||||
Registry.instance.stub(:legal_address_country, Country.new('GB')) do
|
|
||||||
@registrar.vat_rate = ''
|
|
||||||
assert @registrar.invalid?
|
|
||||||
assert @registrar.errors.added?(:vat_rate, :blank)
|
|
||||||
|
|
||||||
@registrar.vat_rate = -1
|
|
||||||
assert @registrar.invalid?
|
|
||||||
|
|
||||||
@registrar.vat_rate = 1
|
|
||||||
assert @registrar.valid?
|
|
||||||
|
|
||||||
@registrar.vat_rate = 99.9
|
|
||||||
assert @registrar.valid?
|
|
||||||
|
|
||||||
@registrar.vat_rate = 100
|
|
||||||
assert @registrar.invalid?
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_vat_is_not_applied_when_registrar_is_local_vat_payer
|
def test_vat_is_not_applied_when_registrar_is_local_vat_payer
|
||||||
@registrar.vat_rate = 1
|
@registrar.vat_rate = 1
|
||||||
assert @registrar.invalid?
|
assert @registrar.invalid?
|
||||||
|
@ -43,30 +21,57 @@ class RegistrarVATTest < ActiveSupport::TestCase
|
||||||
assert @registrar.valid?
|
assert @registrar.valid?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_requires_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)
|
||||||
|
end
|
||||||
|
|
||||||
def test_vat_is_not_applied_when_registrar_is_foreign_vat_payer_and_vat_no_is_present
|
def test_vat_is_not_applied_when_registrar_is_foreign_vat_payer_and_vat_no_is_present
|
||||||
|
@registrar.country_code = 'DE'
|
||||||
@registrar.vat_no = 'valid'
|
@registrar.vat_no = 'valid'
|
||||||
|
|
||||||
Registry.instance.stub(:legal_address_country, Country.new('GB')) do
|
@registrar.vat_rate = 1
|
||||||
@registrar.vat_rate = 1
|
assert @registrar.invalid?
|
||||||
assert @registrar.invalid?
|
|
||||||
|
|
||||||
@registrar.vat_rate = nil
|
@registrar.vat_rate = nil
|
||||||
assert @registrar.valid?
|
assert @registrar.valid?
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
def test_serializes_and_deserializes_vat_rate
|
def test_serializes_and_deserializes_vat_rate
|
||||||
@registrar.vat_rate = '25.5'
|
@registrar.country_code = 'DE'
|
||||||
|
@registrar.vat_rate = BigDecimal('25.5')
|
||||||
Registry.instance.stub(:legal_address_country, Country.new('GB')) do
|
@registrar.save!
|
||||||
@registrar.save!
|
|
||||||
end
|
|
||||||
|
|
||||||
@registrar.reload
|
@registrar.reload
|
||||||
assert_equal 25.5, @registrar.vat_rate
|
assert_equal BigDecimal('25.5'), @registrar.vat_rate
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_treats_empty_vat_rate_as_absent
|
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 = ''
|
@registrar.vat_rate = ''
|
||||||
assert_nil @registrar.vat_rate
|
assert_nil @registrar.vat_rate
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue