From 6a0122613854abeee5f25c579a8abb292e60262d Mon Sep 17 00:00:00 2001 From: Artur Beljajev Date: Mon, 27 Nov 2017 11:11:06 +0200 Subject: [PATCH] Update VAT #623 --- app/models/invoice.rb | 5 ++- app/models/registrar.rb | 38 +++++++++++++++---- test/fixtures/invoices.yml | 8 ++++ .../admin/invoices/invoice_details_test.rb | 19 ++++++++++ .../admin/registrars/show_registrar_test.rb | 2 +- .../invoices/invoice_details_test.rb | 19 ++++++++++ test/models/invoice_test.rb | 31 +++++++++++++-- test/models/registrar_test.rb | 24 +++++++++--- 8 files changed, 126 insertions(+), 20 deletions(-) create mode 100644 test/integration/admin/invoices/invoice_details_test.rb create mode 100644 test/integration/registrar/invoices/invoice_details_test.rb diff --git a/app/models/invoice.rb b/app/models/invoice.rb index 37eb8a72c..90fa380e1 100644 --- a/app/models/invoice.rb +++ b/app/models/invoice.rb @@ -29,6 +29,7 @@ class Invoice < ActiveRecord::Base validates :invoice_type, :due_date, :currency, :seller_name, :seller_iban, :buyer_name, :invoice_items, :vat_rate, presence: true + validates :vat_rate, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 99 }, allow_nil: true before_create :set_invoice_number, :check_vat @@ -106,12 +107,12 @@ class Invoice < ActiveRecord::Base def buyer_country Country.new(buyer_country_code) end - + # order is used for directo/banklink description def order "Order nr. #{number}" end - + def pdf(html) kit = PDFKit.new(html) kit.to_pdf diff --git a/app/models/registrar.rb b/app/models/registrar.rb index 393bd56f2..dd7a7a9f5 100644 --- a/app/models/registrar.rb +++ b/app/models/registrar.rb @@ -1,3 +1,21 @@ +class VATRateType < ActiveRecord::Type::Value + def type_cast_from_user(value) + if value.blank? + nil + else + super + end + end + + def type_cast_from_database(value) + BigDecimal.new(value) * 100 if value + end + + def type_cast_for_database(value) + BigDecimal.new(value) / 100 if value + end +end + class Registrar < ActiveRecord::Base include Versions # version/registrar_version.rb @@ -23,16 +41,9 @@ class Registrar < ActiveRecord::Base validates :vat_rate, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 99 }, allow_nil: true validate :forbidden_codes + attribute :vat_rate, VATRateType.new after_initialize :set_defaults - before_save do - self.vat_rate = vat_rate / 100.0 if vat_rate - end - - after_find do |registrar| - registrar.vat_rate = registrar.vat_rate * 100 if registrar.vat_rate - end - def forbidden_codes return true unless ['CID'].include? code errors.add(:code, I18n.t(:forbidden_code)) @@ -87,6 +98,16 @@ class Registrar < ActiveRecord::Base # rubocop:disable Metrics/MethodLength # rubocop:disable Metrics/AbcSize def issue_prepayment_invoice(amount, description = nil) + vat_rate = if local_vat_payer? + Setting.registry_vat_prc + else + if vat_no.blank? + self.vat_rate + else + nil + end + end + invoices.create( invoice_type: 'DEB', due_date: (Time.zone.now.to_date + Setting.days_to_keep_invoices_active.days).end_of_day, @@ -94,6 +115,7 @@ class Registrar < ActiveRecord::Base description: description, currency: 'EUR', vat_rate: Setting.registry_vat_prc, + vat_rate: vat_rate, seller_name: Setting.registry_juridical_name, seller_reg_no: Setting.registry_reg_no, seller_iban: Setting.registry_iban, diff --git a/test/fixtures/invoices.yml b/test/fixtures/invoices.yml index 04cedc153..bdd8ea033 100644 --- a/test/fixtures/invoices.yml +++ b/test/fixtures/invoices.yml @@ -30,3 +30,11 @@ outstanding: overdue: <<: *DEFAULTS due_date: <%= Date.parse '2010-07-03' %> + +with_vat: + <<: *DEFAULTS + vat_rate: 0.2 + +without_vat: + <<: *DEFAULTS + vat_rate: null diff --git a/test/integration/admin/invoices/invoice_details_test.rb b/test/integration/admin/invoices/invoice_details_test.rb new file mode 100644 index 000000000..8a67771ea --- /dev/null +++ b/test/integration/admin/invoices/invoice_details_test.rb @@ -0,0 +1,19 @@ +require 'test_helper' + +class InvoiceDetailsTest < ActionDispatch::IntegrationTest + def setup + login_as users(:admin) + end + + def test_with_vat + invoice = invoices(:with_vat) + visit admin_invoice_path(invoice) + assert_selector '.total', text: 'VAT' + end + + def test_without_vat + invoice = invoices(:without_vat) + visit admin_invoice_path(invoice) + assert_no_selector '.total', text: 'VAT' + end +end diff --git a/test/integration/admin/registrars/show_registrar_test.rb b/test/integration/admin/registrars/show_registrar_test.rb index f13748191..d4ed927bd 100644 --- a/test/integration/admin/registrars/show_registrar_test.rb +++ b/test/integration/admin/registrars/show_registrar_test.rb @@ -17,7 +17,7 @@ class ShowRegistrarTest < ActionDispatch::IntegrationTest assert_text 'Language English' end - def test_vat_number + def test_vat_no assert_text 'US12345' end diff --git a/test/integration/registrar/invoices/invoice_details_test.rb b/test/integration/registrar/invoices/invoice_details_test.rb new file mode 100644 index 000000000..d3961faf3 --- /dev/null +++ b/test/integration/registrar/invoices/invoice_details_test.rb @@ -0,0 +1,19 @@ +require 'test_helper' + +class InvoiceDetailsTest < ActionDispatch::IntegrationTest + def setup + login_as users(:api) + end + + def test_with_vat + invoice = invoices(:with_vat) + visit registrar_invoice_path(invoice) + assert_selector '.total', text: 'VAT' + end + + def test_without_vat + invoice = invoices(:without_vat) + visit registrar_invoice_path(invoice) + assert_no_selector '.total', text: 'VAT' + end +end diff --git a/test/models/invoice_test.rb b/test/models/invoice_test.rb index c89c37626..770a88590 100644 --- a/test/models/invoice_test.rb +++ b/test/models/invoice_test.rb @@ -1,9 +1,34 @@ require 'test_helper' class InvoiceTest < ActiveSupport::TestCase + def setup + @invoice = invoices(:valid) + end + + def test_valid + assert @invoice.valid? + end + def test_invalid_without_vat_rate - invoice = Invoice.new(vat_rate: nil) - invoice.validate - assert invoice.errors.added?(:vat_rate, :blank) + @invoice.vat_rate = nil + assert @invoice.invalid? + end + + def test_allows_absent_vat_rate + @invoice.vat_rate = nil + @invoice.validate + assert @invoice.valid? + end + + def test_rejects_negative_vat_rate + @invoice.vat_rate = -1 + @invoice.validate + assert @invoice.invalid? + end + + def test_rejects_vat_rate_greater_than_max + @invoice.vat_rate = 100 + @invoice.validate + assert @invoice.invalid? end end diff --git a/test/models/registrar_test.rb b/test/models/registrar_test.rb index 3ace52ba7..96328d38c 100644 --- a/test/models/registrar_test.rb +++ b/test/models/registrar_test.rb @@ -39,7 +39,7 @@ class RegistrarTest < ActiveSupport::TestCase assert_equal 'de', registrar.language end - def test_rejects_vat_number_when_local_vat_payer + def test_rejects_vat_no_when_local_vat_payer Registry.instance.stub(:legal_address_country, Country.new('US')) do @registrar.vat_no = 'US1' @registrar.validate @@ -67,11 +67,6 @@ class RegistrarTest < ActiveSupport::TestCase assert @registrar.invalid? end - def test_converts_integer_vat_rate_to_fractional - @registrar = registrars(:foreign_vat_payer_with_rate) - assert_equal 20, @registrar.vat_rate - end - def test_requires_vat_rate_when_foreign_vat_payer_without_number Registry.instance.stub(:legal_address_country, Country.new('GB')) do @registrar.vat_no = nil @@ -88,4 +83,21 @@ class RegistrarTest < ActiveSupport::TestCase assert @registrar.invalid? end end + + def test_serializes_and_deserializes_vat_rate + valid_attributes = registrars(:valid).attributes.except('id').merge({ name: 'uniq1', + reg_no: 'uniq1', + code: 'uniq1', + country_code: 'GB' }) + registrar = Registrar.new(valid_attributes) + registrar.vat_rate = 55 + registrar.save! + registrar.reload + assert_equal 55, registrar.vat_rate + end + + def test_treats_empty_vat_rate_as_absent + @registrar.vat_rate = '' + assert_nil @registrar.vat_rate + end end