diff --git a/CHANGELOG.md b/CHANGELOG.md index 74c177bf0..66ba13df5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,26 @@ +15.09.2020 +* Fixed e-invoice sending issue with QUE [#1683](https://github.com/internetee/registry/pull/1683) + +14.09.2020 +* Restored version logging for registry prices [#980](https://github.com/internetee/registry/pull/980) + +11.09.2020 +* Registrars can now top up their credit accounts without generating invoice in advance [#1101](https://github.com/internetee/registry/issues/1101) +* Fixed typo in admin settings [#371](https://github.com/internetee/registry/issues/371) + +10.09.2020 +* New registrar ref nr are now always created 7 digits long [#1679](https://github.com/internetee/registry/pull/1679) + +08.09.2020 +* Removed bank statement import option [#1674](https://github.com/internetee/registry/pull/1674) +* Fixed error with reference nr not being found in the transaction [#1677](https://github.com/internetee/registry/issues/1677) + +04.09.2020 +* Removed reduntant domains.registered_at db column [#1445](https://github.com/internetee/registry/pull/1445) +* Certificate revocation lists are now hanlded outside of the application code [#1662](https://github.com/internetee/registry/pull/1662) +* Monthly invoices are sent one by one to elliminate reply delay from accounting system [#1671](https://github.com/internetee/registry/pull/1671) +* Fixed poll request ip whitelist issue [#1672](https://github.com/internetee/registry/pull/1672) + 03.09.2020 * Refactored session timeout management [#711](https://github.com/internetee/registry/issues/711) * Improved error handling for epp requests without proper session [#1276](https://github.com/internetee/registry/pull/1276) diff --git a/Gemfile.lock b/Gemfile.lock index f7eb6cf2a..a49c9becb 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -9,7 +9,7 @@ GIT GIT remote: https://github.com/internetee/directo.git - revision: 8ff8a382d004ffb85722a6a7a68a020bd4d7159b + revision: e4ba54f601d1815fd8782a196788730d47861e86 branch: master specs: directo (1.0.1) @@ -18,7 +18,7 @@ GIT GIT remote: https://github.com/internetee/e_invoice.git - revision: b374ffd7be77b559b30c7a0210dc0df5ac3ed723 + revision: 5f8d0029bf1affdbf2bd6e3d1ce87d34066add4d branch: master specs: e_invoice (0.1.0) @@ -165,7 +165,7 @@ GEM coffee-script-source execjs coffee-script-source (1.12.2) - concurrent-ruby (1.1.6) + concurrent-ruby (1.1.7) countries (3.0.1) i18n_data (~> 0.10.0) sixarm_ruby_unaccent (~> 1.1) @@ -238,10 +238,10 @@ GEM http-cookie (1.0.3) domain_name (~> 0.5) httpclient (2.8.3) - httpi (2.4.4) + httpi (2.4.5) rack socksify - i18n (1.8.3) + i18n (1.8.5) concurrent-ruby (~> 1.0) i18n_data (0.10.0) isikukood (0.1.2) @@ -467,7 +467,8 @@ GEM i18n warden (1.2.8) rack (>= 2.0.6) - wasabi (3.5.0) + wasabi (3.6.1) + addressable httpi (~> 2.0) nokogiri (>= 1.4.2) webdrivers (4.4.1) diff --git a/app/controllers/admin/bank_statements_controller.rb b/app/controllers/admin/bank_statements_controller.rb index 1e3b31bf5..4295c155f 100644 --- a/app/controllers/admin/bank_statements_controller.rb +++ b/app/controllers/admin/bank_statements_controller.rb @@ -2,7 +2,7 @@ module Admin class BankStatementsController < BaseController load_and_authorize_resource - before_action :set_bank_statement, only: [:show, :download_import_file, :bind_invoices] + before_action :set_bank_statement, only: %i[show bind_invoices] def index @q = BankStatement.search(params[:q]) @@ -43,22 +43,6 @@ module Admin end end - def import - @bank_statement = BankStatement.new - end - - def create_from_import - @bank_statement = BankStatement.new(bank_statement_params) - - if @bank_statement.import - flash[:notice] = I18n.t('record_created') - redirect_to [:admin, @bank_statement] - else - flash.now[:alert] = I18n.t('failed_to_create_record') - render 'new' - end - end - def bind_invoices @bank_statement.bind_invoices(manual: true) @@ -69,11 +53,6 @@ module Admin redirect_to [:admin, @bank_statement] end - def download_import_file - filename = @bank_statement.import_file_path.split('/').last - send_data File.open(@bank_statement.import_file_path, 'r').read, filename: filename - end - private def set_bank_statement @@ -81,7 +60,7 @@ module Admin end def bank_statement_params - params.require(:bank_statement).permit(:th6_file, :bank_code, :iban, bank_transactions_attributes: [ + params.require(:bank_statement).permit(:bank_code, :iban, bank_transactions_attributes: [ :description, :sum, :currency, :reference_no, :paid_at ]) end diff --git a/app/jobs/directo_invoice_forward_job.rb b/app/jobs/directo_invoice_forward_job.rb index 6c3eb034c..4b2c06e2c 100644 --- a/app/jobs/directo_invoice_forward_job.rb +++ b/app/jobs/directo_invoice_forward_job.rb @@ -2,15 +2,16 @@ class DirectoInvoiceForwardJob < Que::Job def run(monthly: false, dry: false) @dry = dry (@month = Time.zone.now - 1.month) if monthly - api_url = ENV['directo_invoice_url'] - sales_agent = Setting.directo_sales_agent - payment_term = Setting.directo_receipt_payment_term - @prepayment_product_id = Setting.directo_receipt_product_name - @client = DirectoApi::Client.new(api_url, sales_agent, payment_term) + @client = new_directo_client monthly ? send_monthly_invoices : send_receipts end + def new_directo_client + DirectoApi::Client.new(ENV['directo_invoice_url'], Setting.directo_sales_agent, + Setting.directo_receipt_payment_term) + end + def send_receipts unsent_invoices = Invoice.where(in_directo: false).non_cancelled @@ -28,19 +29,18 @@ class DirectoInvoiceForwardJob < Que::Job def send_monthly_invoices Registrar.where.not(test_registrar: true).find_each do |registrar| - fetch_monthly_summary(registrar: registrar) + next unless registrar.cash_account + + @client = new_directo_client + send_invoice_for_registrar(registrar) end - - return unless @client.invoices.count.positive? - - sync_with_directo end - def fetch_monthly_summary(registrar:) - return unless registrar.cash_account - + def send_invoice_for_registrar(registrar) summary = registrar.monthly_summary(month: @month) @client.invoices.add_with_schema(invoice: summary, schema: 'summary') unless summary.nil? + + sync_with_directo if @client.invoices.count.positive? end def assign_monthly_numbers diff --git a/app/jobs/send_e_invoice_job.rb b/app/jobs/send_e_invoice_job.rb index e281db14d..e3880963e 100644 --- a/app/jobs/send_e_invoice_job.rb +++ b/app/jobs/send_e_invoice_job.rb @@ -1,8 +1,8 @@ class SendEInvoiceJob < Que::Job - def run(invoice_id) - invoice = run_condition(Invoice.find_by(id: invoice_id)) + def run(invoice_id, payable = true) + invoice = run_condition(Invoice.find_by(id: invoice_id), payable: payable) - invoice.to_e_invoice.deliver + invoice.to_e_invoice(payable: payable).deliver ActiveRecord::Base.transaction do invoice.update(e_invoice_sent_at: Time.zone.now) log_success(invoice) @@ -15,9 +15,9 @@ class SendEInvoiceJob < Que::Job private - def run_condition(invoice) + def run_condition(invoice, payable: true) destroy unless invoice - destroy if invoice.do_not_send_e_invoice? + destroy if invoice.do_not_send_e_invoice? && payable invoice end diff --git a/app/models/ability.rb b/app/models/ability.rb index 0e18f433a..dce8a515b 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -32,12 +32,14 @@ class Ability def epp # Registrar/api_user dynamic role if @user.registrar.api_ip_white?(@ip) - can :manage, :poll can :manage, Depp::Contact can :manage, :xml_console can :manage, Depp::Domain end + # Poll + can :manage, :poll + # REPP can(:manage, :repp) diff --git a/app/models/bank_statement.rb b/app/models/bank_statement.rb index c73e6bb44..d57f3e4d7 100644 --- a/app/models/bank_statement.rb +++ b/app/models/bank_statement.rb @@ -4,70 +4,17 @@ class BankStatement < ApplicationRecord accepts_nested_attributes_for :bank_transactions - attr_accessor :th6_file - validates :bank_code, :iban, presence: true - FULLY_BINDED = 'fully_binded' - PARTIALLY_BINDED = 'partially_binded' - NOT_BINDED = 'not_binded' - - def import - import_th6_file && save - end - - def import_th6_file - return false unless th6_file - - th6_file.open.each_line do |row| - bt_params = parse_th6_row(row) - next unless bt_params - bank_transactions.build(bt_params) - end - - prepare_dir - self.import_file_path = "#{ENV['bank_statement_import_dir']}/#{Time.zone.now.to_formatted_s(:number)}.txt" - File.open(import_file_path, 'w') { |f| f.write(th6_file.open.read) } - end - - def prepare_dir - dirname = ENV['bank_statement_import_dir'] - FileUtils.mkdir_p(dirname) unless File.directory?(dirname) - end - - def parse_th6_row(row) - return parse_th6_header(row) if row[4, 3].strip == '000' - return if row[4, 3].strip == '999' # skip footer - return unless row[4, 1].strip == '1' # import only transactions - return unless row[266, 2].strip == 'C' # import only Credit transactions - - { - paid_at: DateTime.strptime(row[5, 8].strip, '%Y%m%d'), - bank_reference: row[5, 16].strip, - iban: row[25, 20].strip, - currency: row[45, 3].strip, - buyer_bank_code: row[48, 3].strip, - buyer_iban: row[51, 32].strip, - buyer_name: row[83, 35].strip, - document_no: row[118, 8].strip, - description: row[126, 140].strip, - sum: BigDecimal(row[268, 12].strip) / BigDecimal('100.0'), - reference_no: row[280, 35].strip - } - end - - def parse_th6_header(row) - self.bank_code = row[7, 3].strip - self.iban = row[10, 20].strip - self.queried_at = DateTime.strptime(row[30, 10].strip, '%y%m%d%H%M') - nil - end + FULLY_BINDED = 'fully_binded'.freeze + PARTIALLY_BINDED = 'partially_binded'.freeze + NOT_BINDED = 'not_binded'.freeze # TODO: Cache this to database so it can be used for searching def status if bank_transactions.unbinded.count == bank_transactions.count NOT_BINDED - elsif bank_transactions.unbinded.count == 0 + elsif bank_transactions.unbinded.count.zero? FULLY_BINDED else PARTIALLY_BINDED diff --git a/app/models/bank_transaction.rb b/app/models/bank_transaction.rb index f53a286ba..24bf51e0c 100644 --- a/app/models/bank_transaction.rb +++ b/app/models/bank_transaction.rb @@ -31,20 +31,18 @@ class BankTransaction < ApplicationRecord @registrar ||= Invoice.find_by(reference_no: parsed_ref_number)&.buyer end + def autobindable? + !binded? && registrar && invoice.payable? ? true : false + rescue NoMethodError + false + end + # For successful binding, reference number, invoice id and sum must match with the invoice def autobind_invoice(manual: false) - return if binded? - return unless registrar - return unless invoice - return unless invoice.payable? + return unless autobindable? - channel = if manual - 'admin_payment' - else - 'system_payment' - end - create_internal_payment_record(channel: channel, invoice: invoice, - registrar: registrar) + channel = manual ? 'admin_payment' : 'system_payment' + create_internal_payment_record(channel: channel, invoice: invoice, registrar: registrar) end def create_internal_payment_record(channel: nil, invoice:, registrar:) @@ -93,12 +91,11 @@ class BankTransaction < ApplicationRecord end def create_activity(registrar, invoice) - activity = AccountActivity.new( - account: registrar.cash_account, bank_transaction: self, - invoice: invoice, sum: invoice.subtotal, - currency: currency, description: description, - activity_type: AccountActivity::ADD_CREDIT - ) + activity = AccountActivity.new(account: registrar.cash_account, bank_transaction: self, + invoice: invoice, sum: invoice.subtotal, + currency: currency, description: description, + activity_type: AccountActivity::ADD_CREDIT) + if activity.save reset_pending_registrar_balance_reload true @@ -107,6 +104,10 @@ class BankTransaction < ApplicationRecord end end + def parsed_ref_number + reference_no || ref_number_from_description + end + private def reset_pending_registrar_balance_reload @@ -116,11 +117,12 @@ class BankTransaction < ApplicationRecord registrar.save! end - def parsed_ref_number - reference_no || ref_number_from_description + def ref_number_from_description + matches = description.to_s.scan(Billing::ReferenceNo::MULTI_REGEXP).flatten + matches.detect { |m| break m if m.length == 7 || valid_ref_no?(m) } end - def ref_number_from_description - /(\d{7})/.match(description)[0] + def valid_ref_no?(match) + return true if Billing::ReferenceNo.valid?(match) && Registrar.find_by(reference_no: match) end end diff --git a/app/models/billing/price.rb b/app/models/billing/price.rb index 283a6e5bc..dac458b00 100644 --- a/app/models/billing/price.rb +++ b/app/models/billing/price.rb @@ -1,6 +1,7 @@ module Billing class Price < ApplicationRecord include Concerns::Billing::Price::Expirable + include Versions belongs_to :zone, class_name: 'DNS::Zone', required: true has_many :account_activities diff --git a/app/models/billing/reference_no.rb b/app/models/billing/reference_no.rb index 23812214c..d164f7565 100644 --- a/app/models/billing/reference_no.rb +++ b/app/models/billing/reference_no.rb @@ -1,10 +1,16 @@ module Billing class ReferenceNo - REGEXP = /\A\d{2,20}\z/ + REGEXP = /\A\d{2,20}\z/.freeze + MULTI_REGEXP = /(\d{2,20})/.freeze def self.generate base = Base.generate "#{base}#{base.check_digit}" end + + def self.valid?(ref) + base = Base.new(ref.to_s[0...-1]) + ref.to_s == "#{base}#{base.check_digit}" + end end end diff --git a/app/models/billing/reference_no/base.rb b/app/models/billing/reference_no/base.rb index dcc7718e7..8614f81f8 100644 --- a/app/models/billing/reference_no/base.rb +++ b/app/models/billing/reference_no/base.rb @@ -2,7 +2,7 @@ module Billing class ReferenceNo class Base def self.generate - new(SecureRandom.random_number(1..1_000_000)) + new((SecureRandom.random_number(9e5) + 1e5).to_i) end def initialize(base) diff --git a/app/models/certificate.rb b/app/models/certificate.rb index d2428365a..3bea9e9fc 100644 --- a/app/models/certificate.rb +++ b/app/models/certificate.rb @@ -127,77 +127,20 @@ class Certificate < ApplicationRecord return false end - self.class.update_registry_crl - self.class.reload_apache + self.class.update_crl self end class << self + def tostdout(message) + time = Time.zone.now.utc + STDOUT << "#{time} - #{message}\n" unless Rails.env.test? + end + def update_crl - update_id_crl - update_registry_crl - reload_apache - end - - def update_id_crl - STDOUT << "#{Time.zone.now.utc} - Updating ID CRL\n" unless Rails.env.test? - - _out, _err, _st = Open3.capture3(" - mkdir -p #{ENV['crl_dir']}/crl-id-temp - cd #{ENV['crl_dir']}/crl-id-temp - - wget https://sk.ee/crls/esteid/esteid2007.crl - wget https://sk.ee/crls/juur/crl.crl - wget https://sk.ee/crls/eeccrca/eeccrca.crl - wget https://sk.ee/repository/crls/esteid2011.crl - - openssl crl -in esteid2007.crl -out esteid2007.crl -inform DER - openssl crl -in crl.crl -out crl.crl -inform DER - openssl crl -in eeccrca.crl -out eeccrca.crl -inform DER - openssl crl -in esteid2011.crl -out esteid2011.crl -inform DER - - ln -s crl.crl `openssl crl -hash -noout -in crl.crl`.r0 - ln -s esteid2007.crl `openssl crl -hash -noout -in esteid2007.crl`.r0 - ln -s eeccrca.crl `openssl crl -hash -noout -in eeccrca.crl`.r0 - ln -s esteid2011.crl `openssl crl -hash -noout -in esteid2011.crl`.r0 - - rm -rf #{ENV['crl_dir']}/*.crl #{ENV['crl_dir']}/*.r0 - - mv #{ENV['crl_dir']}/crl-id-temp/* #{ENV['crl_dir']} - - rm -rf #{ENV['crl_dir']}/crl-id-temp - ") - - STDOUT << "#{Time.zone.now.utc} - ID CRL updated\n" unless Rails.env.test? - end - - def update_registry_crl - STDOUT << "#{Time.zone.now.utc} - Updating registry CRL\n" unless Rails.env.test? - - _out, _err, _st = Open3.capture3(" - mkdir -p #{ENV['crl_dir']}/crl-temp - cd #{ENV['crl_dir']}/crl-temp - - openssl ca -config #{ENV['openssl_config_path']} -keyfile #{ENV['ca_key_path']} -cert \ - #{ENV['ca_cert_path']} -gencrl -out #{ENV['crl_dir']}/crl-temp/crl.pem -key \ - '#{ENV['ca_key_password']}' -batch - - ln -s crl.pem `openssl crl -hash -noout -in crl.pem`.r1 - - rm -rf #{ENV['crl_dir']}/*.pem #{ENV['crl_dir']}/*.r1 - - mv #{ENV['crl_dir']}/crl-temp/* #{ENV['crl_dir']} - - rm -rf #{ENV['crl_dir']}/crl-temp - ") - - STDOUT << "#{Time.zone.now.utc} - Registry CRL updated\n" unless Rails.env.test? - end - - def reload_apache - STDOUT << "#{Time.zone.now.utc} - Reloading apache\n" unless Rails.env.test? - _out, _err, _st = Open3.capture3("sudo /etc/init.d/apache2 reload") - STDOUT << "#{Time.zone.now.utc} - Apache reloaded\n" unless Rails.env.test? + tostdout('Running crlupdater') + system('/bin/bash', ENV['crl_updater_path'].to_s) + tostdout('Finished running crlupdater') end def parse_md_from_string(crt) diff --git a/app/models/domain.rb b/app/models/domain.rb index b706744bd..e57117bc2 100644 --- a/app/models/domain.rb +++ b/app/models/domain.rb @@ -18,6 +18,7 @@ class Domain < ApplicationRecord alias_attribute :on_hold_time, :outzone_at alias_attribute :outzone_time, :outzone_at alias_attribute :auth_info, :transfer_code # Old attribute name; for PaperTrail + alias_attribute :registered_at, :created_at # TODO: whois requests ip whitelist for full info for own domains and partial info for other domains # TODO: most inputs should be trimmed before validatation, probably some global logic? @@ -627,7 +628,7 @@ class Domain < ApplicationRecord def as_json(_options) hash = super hash['auth_info'] = hash.delete('transfer_code') # API v1 requirement - hash['valid_from'] = hash['registered_at'] # API v1 requirement + hash['valid_from'] = hash['created_at'] # API v1 requirement hash.delete('statuses_before_force_delete') hash end diff --git a/app/models/epp/domain.rb b/app/models/epp/domain.rb index a6fe58c71..3ed26f0e1 100644 --- a/app/models/epp/domain.rb +++ b/app/models/epp/domain.rb @@ -41,7 +41,6 @@ class Epp::Domain < Domain domain = Epp::Domain.new domain.attributes = domain.attrs_from(frame, current_user) domain.attach_default_contacts - domain.registered_at = Time.zone.now period = domain.period.to_i plural_period_unit_name = (domain.period_unit == 'm' ? 'months' : 'years').to_sym @@ -150,7 +149,6 @@ class Epp::Domain < Domain at[:name] = frame.css('name').text if new_record? at[:registrar_id] = current_user.registrar.try(:id) - at[:registered_at] = Time.zone.now if new_record? period = frame.css('period').text at[:period] = (period.to_i == 0) ? 1 : period.to_i @@ -502,7 +500,7 @@ class Epp::Domain < Domain frame.css('registrant').attr('verified').to_s.downcase != 'yes' if registrant_verification_needed && errors.empty? && verify && - Setting.request_confrimation_on_registrant_change_enabled && + Setting.request_confirmation_on_registrant_change_enabled && unverified_registrant_params registrant_verification_asked!(frame.to_s, current_user.id) unless disputed? end diff --git a/app/models/invoice.rb b/app/models/invoice.rb index a130a90ff..fb625f7b9 100644 --- a/app/models/invoice.rb +++ b/app/models/invoice.rb @@ -99,8 +99,8 @@ class Invoice < ApplicationRecord generator.as_pdf end - def to_e_invoice - generator = Invoice::EInvoiceGenerator.new(self) + def to_e_invoice(payable: true) + generator = Invoice::EInvoiceGenerator.new(self, payable) generator.generate end @@ -112,6 +112,15 @@ class Invoice < ApplicationRecord e_invoice_sent_at.present? end + def self.create_from_transaction!(transaction) + registrar_user = Registrar.find_by(reference_no: transaction.parsed_ref_number) + return unless registrar_user + + vat = VatRateCalculator.new(registrar: registrar_user).calculate + net = (transaction.sum / (1 + (vat / 100))) + registrar_user.issue_prepayment_invoice(net, 'Direct top-up via bank transfer', payable: false) + end + private def apply_default_buyer_vat_no @@ -119,6 +128,6 @@ class Invoice < ApplicationRecord end def calculate_total - self.total = subtotal + vat_amount + self.total = (subtotal + vat_amount).round(3) end end diff --git a/app/models/invoice/e_invoice_generator.rb b/app/models/invoice/e_invoice_generator.rb index 9a2ab2e01..d2963b93e 100644 --- a/app/models/invoice/e_invoice_generator.rb +++ b/app/models/invoice/e_invoice_generator.rb @@ -1,9 +1,11 @@ class Invoice class EInvoiceGenerator attr_reader :invoice + attr_reader :payable - def initialize(invoice) + def initialize(invoice, payable) @invoice = invoice + @payable = payable end def generate @@ -70,9 +72,10 @@ class Invoice i.total = invoice.total i.currency = invoice.currency i.delivery_channel = %i[internet_bank portal] + i.payable = payable end EInvoice::EInvoice.new(date: Time.zone.today, invoice: e_invoice_invoice) end end -end \ No newline at end of file +end diff --git a/app/models/invoice_item.rb b/app/models/invoice_item.rb index ec0c77767..61339f5cb 100644 --- a/app/models/invoice_item.rb +++ b/app/models/invoice_item.rb @@ -5,7 +5,7 @@ class InvoiceItem < ApplicationRecord delegate :vat_rate, to: :invoice def item_sum_without_vat - (price * quantity).round(2) + (price * quantity).round(3) end alias_method :subtotal, :item_sum_without_vat @@ -14,6 +14,6 @@ class InvoiceItem < ApplicationRecord end def total - subtotal + vat_amount + (subtotal + vat_amount) end -end \ No newline at end of file +end diff --git a/app/models/registrar.rb b/app/models/registrar.rb index 470d768b7..e2ffcbfd4 100644 --- a/app/models/registrar.rb +++ b/app/models/registrar.rb @@ -54,7 +54,7 @@ class Registrar < ApplicationRecord end end - def issue_prepayment_invoice(amount, description = nil) + def issue_prepayment_invoice(amount, description = nil, payable: true) vat_rate = ::Invoice::VatRateCalculator.new(registrar: self).calculate invoice = invoices.create!( @@ -99,7 +99,12 @@ class Registrar < ApplicationRecord } ] ) - SendEInvoiceJob.enqueue(invoice.id) + + unless payable + InvoiceMailer.invoice_email(invoice: invoice, recipient: billing_email).deliver_now + end + + SendEInvoiceJob.enqueue(invoice.id, payable) invoice end diff --git a/app/models/version/billing/price_version.rb b/app/models/version/billing/price_version.rb new file mode 100644 index 000000000..7502c18e2 --- /dev/null +++ b/app/models/version/billing/price_version.rb @@ -0,0 +1,7 @@ +module Billing + class PriceVersion < PaperTrail::Version + self.table_name = :log_prices + self.sequence_name = :log_prices_id_seq + end +end + diff --git a/app/models/whois_record.rb b/app/models/whois_record.rb index 4994283c9..3563b9630 100644 --- a/app/models/whois_record.rb +++ b/app/models/whois_record.rb @@ -36,7 +36,7 @@ class WhoisRecord < ApplicationRecord h[:disclaimer] = disclaimer_text if disclaimer_text.present? h[:name] = domain.name h[:status] = domain.statuses.map { |x| status_map[x] || x } - h[:registered] = domain.registered_at.try(:to_s, :iso8601) + h[:registered] = domain.registered_at.iso8601 h[:changed] = domain.updated_at.try(:to_s, :iso8601) h[:expire] = domain.valid_to.to_date.to_s h[:outzone] = domain.outzone_at.try(:to_date).try(:to_s) diff --git a/app/views/admin/bank_statements/import.haml b/app/views/admin/bank_statements/import.haml deleted file mode 100644 index e432abdf1..000000000 --- a/app/views/admin/bank_statements/import.haml +++ /dev/null @@ -1,20 +0,0 @@ -- content_for :actions do - = link_to(t(:back_to_bank_statements), admin_bank_statements_path, class: 'btn btn-default') -= render 'shared/title', name: t(:import_th6_bank_statement) - -= form_for(@bank_statement, url: { action: :create_from_import }, multipart: true) do |f| - = render 'shared/full_errors', object: @bank_statement - - .row - .col-md-8 - .form-group - .col-md-4.control-label - = f.label :th6_file - .col-md-8 - = f.file_field :th6_file - .col-md-4 - %p= t(:bank_statement_desc).html_safe - %hr - .row - .col-md-8.text-right - = button_tag(t(:save), class: 'btn btn-primary') diff --git a/app/views/admin/bank_statements/index.haml b/app/views/admin/bank_statements/index.haml index 2c604c035..f04557b0b 100644 --- a/app/views/admin/bank_statements/index.haml +++ b/app/views/admin/bank_statements/index.haml @@ -1,6 +1,5 @@ - content_for :actions do = link_to(t(:add), new_admin_bank_statement_path, class: 'btn btn-primary') - = link_to(t('.import_btn'), import_admin_bank_statements_path, class: 'btn btn-primary') = render 'shared/title', name: t(:bank_statements) .row diff --git a/app/views/admin/bank_statements/show.haml b/app/views/admin/bank_statements/show.haml index 9797c59bf..ff139012b 100644 --- a/app/views/admin/bank_statements/show.haml +++ b/app/views/admin/bank_statements/show.haml @@ -30,10 +30,6 @@ %dt= t(:created_at) %dd= l(@bank_statement.created_at) - - if @bank_statement.import_file_path - %dt= t(:import_file) - %dd= link_to(t(:download), download_import_file_admin_bank_statement_path(@bank_statement)) - .row .col-sm-6 %h3.text-center-xs diff --git a/app/views/admin/domains/partials/_general.html.erb b/app/views/admin/domains/partials/_general.html.erb index 0151094b9..dd99d45b8 100644 --- a/app/views/admin/domains/partials/_general.html.erb +++ b/app/views/admin/domains/partials/_general.html.erb @@ -10,7 +10,7 @@
<%= t(:name) %>
<%= @domain.name %>
-
<%= t(:registered_at) %>
+
<%= Domain.human_attribute_name :registered_at %>
<%= l(@domain.registered_at) %>
<%= t(:registrar_name) %>
diff --git a/app/views/registrant/domains/partials/_general.html.erb b/app/views/registrant/domains/partials/_general.html.erb index d79980797..38995be01 100644 --- a/app/views/registrant/domains/partials/_general.html.erb +++ b/app/views/registrant/domains/partials/_general.html.erb @@ -10,7 +10,7 @@
<%= t(:name) %>
<%= @domain.name %>
-
<%= t(:registered_at) %>
+
<%= Domain.human_attribute_name :registered_at %>
<%= l(@domain.registered_at) %>
<%= Registrar.model_name.human %>
diff --git a/config/application.yml.sample b/config/application.yml.sample index c35a8a5bb..1b6c40951 100644 --- a/config/application.yml.sample +++ b/config/application.yml.sample @@ -27,13 +27,13 @@ smtp_authentication: 'plain' # 'plain', 'login', 'cram_md5' # app_name: '.EE Registry' zonefile_export_dir: 'export/zonefiles' -bank_statement_import_dir: 'import/bank_statements' legal_documents_dir: 'import/legal_documents' time_zone: 'Tallinn' # more zones by rake time:zones:all openssl_config_path: '/etc/ssl/openssl.cnf' crl_dir: '/home/registry/registry/shared/ca/crl' crl_path: '/home/registry/registry/shared/ca/crl/crl.pem' +crl_updater_path: '/home/registry/registry/shared/ca/crl/crlupdater.sh' ca_cert_path: '/home/registry/registry/shared/ca/certs/ca.crt.pem' ca_key_path: '/home/registry/registry/shared/ca/private/ca.key.pem' ca_key_password: 'your-root-key-password' diff --git a/config/locales/en.yml b/config/locales/en.yml index 6c9877de4..9c5b98a1b 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -195,7 +195,6 @@ en: registrar_name: 'Registrar' owner: 'Registrant' domain_details: 'Domain details' - registered_at: 'Registered at' password: 'Password' valid_from: 'Valid from' general: 'General' @@ -467,7 +466,6 @@ en: paid_at: 'Paid at' invoice: 'Invoice' bank_statements: 'Bank statements' - import_th6_bank_statement: 'Import TH6 bank statement' back_to_bank_statements: 'Back to bank statements' back_to_bank_statement: 'Back to bank statement' back_to_billing: 'Back to billing' @@ -584,7 +582,6 @@ en: valid: Valid object_is_not_eligible_for_renewal: 'Object is not eligible for renewal' object_is_not_holded: 'Object is not holded' - bank_statement_desc: 'Import file row will match only when matching following attributes:
ref number
payment amount
invoice number (the first numerical value in comment field)
.' create_bank_statement: 'Create bank statement' create_bank_transaction: 'Create bank transaction' create_new_invoice: 'Create new invoice' diff --git a/config/routes.rb b/config/routes.rb index 2f341866b..223cf3171 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -213,13 +213,7 @@ Rails.application.routes.draw do resources :bank_statements do resources :bank_transactions - collection do - get 'import' - post 'create_from_import' - end - post 'bind_invoices', on: :member - get 'download_import_file', on: :member end resources :bank_transactions do diff --git a/db/data/20200911104302_fix_typo_in_setting_name.rb b/db/data/20200911104302_fix_typo_in_setting_name.rb new file mode 100644 index 000000000..9dd2b3b2b --- /dev/null +++ b/db/data/20200911104302_fix_typo_in_setting_name.rb @@ -0,0 +1,11 @@ +class FixTypoInSettingName < ActiveRecord::Migration[6.0] + def up + setting = Setting.find_by(code: 'request_confrimation_on_registrant_change_enabled') + setting.update(code: 'request_confirmation_on_registrant_change_enabled') + end + + def down + setting = Setting.find_by(code: 'request_confirmation_on_registrant_change_enabled') + setting.update(code: 'request_confrimation_on_registrant_change_enabled') + end +end diff --git a/db/migrate/20191217013225_remove_domains_registered_at.rb b/db/migrate/20191217013225_remove_domains_registered_at.rb new file mode 100644 index 000000000..458c5ebda --- /dev/null +++ b/db/migrate/20191217013225_remove_domains_registered_at.rb @@ -0,0 +1,5 @@ +class RemoveDomainsRegisteredAt < ActiveRecord::Migration[5.0] + def change + remove_column :domains, :registered_at + end +end diff --git a/db/migrate/20200908131554_remove_import_file_path_from_bank_statements.rb b/db/migrate/20200908131554_remove_import_file_path_from_bank_statements.rb new file mode 100644 index 000000000..a80a1e5a5 --- /dev/null +++ b/db/migrate/20200908131554_remove_import_file_path_from_bank_statements.rb @@ -0,0 +1,9 @@ +class RemoveImportFilePathFromBankStatements < ActiveRecord::Migration[6.0] + def up + remove_column :bank_statements, :import_file_path + end + + def down + add_column :bank_statements, :import_file_path, :string + end +end diff --git a/db/migrate/20200910085157_change_invoice_item_price_scale_to_three_places.rb b/db/migrate/20200910085157_change_invoice_item_price_scale_to_three_places.rb new file mode 100644 index 000000000..f1f41343b --- /dev/null +++ b/db/migrate/20200910085157_change_invoice_item_price_scale_to_three_places.rb @@ -0,0 +1,5 @@ +class ChangeInvoiceItemPriceScaleToThreePlaces < ActiveRecord::Migration[6.0] + def change + change_column :invoice_items, :price, :decimal, precision: 10, scale: 3 + end +end diff --git a/db/migrate/20200910102028_create_version_for_prices.rb b/db/migrate/20200910102028_create_version_for_prices.rb new file mode 100644 index 000000000..85eea737f --- /dev/null +++ b/db/migrate/20200910102028_create_version_for_prices.rb @@ -0,0 +1,26 @@ +class CreateVersionForPrices < ActiveRecord::Migration[6.0] + def up + create_table :log_prices, force: :cascade do |t| + t.string :item_type, null: false + t.integer :item_id, null: false + t.string :event, null: false + t.string :whodunnit + t.json :object + t.json :object_changes + t.datetime :created_at + t.string :session + t.json :children + t.string :uuid + end + + add_index 'log_prices', ['item_type', 'item_id'], name: 'index_log_prices_on_item_type_and_item_id', using: :btree + add_index 'log_prices', ['whodunnit'], name: 'index_log_prices_on_whodunnit', using: :btree + end + + def down + remove_index :log_prices, name: 'index_log_prices_on_item_type_and_item_id' + remove_index :log_prices, name: 'index_log_prices_on_whodunnit' + + drop_table :log_prices + end +end diff --git a/db/seeds.rb b/db/seeds.rb index c74136b9d..691c18b0f 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -26,7 +26,7 @@ ActiveRecord::Base.transaction do SettingEntry.create(code: 'client_side_status_editing_enabled', value: 'false', format: 'boolean', group: 'other') SettingEntry.create(code: 'api_ip_whitelist_enabled', value: 'false', format: 'boolean', group: 'other') SettingEntry.create(code: 'registrar_ip_whitelist_enabled', value: 'false', format: 'boolean', group: 'other') - SettingEntry.create(code: 'request_confrimation_on_registrant_change_enabled', value: 'true', format: 'boolean', group: 'other') + SettingEntry.create(code: 'request_confirmation_on_registrant_change_enabled', value: 'true', format: 'boolean', group: 'other') SettingEntry.create(code: 'request_confirmation_on_domain_deletion_enabled', value: 'true', format: 'boolean', group: 'other') SettingEntry.create(code: 'default_language', value: 'en', format: 'string', group: 'other') SettingEntry.create(code: 'invoice_number_min', value: '131050', format: 'integer', group: 'billing') diff --git a/db/structure.sql b/db/structure.sql index 2c24c8fc7..6a30fbc84 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -371,7 +371,6 @@ CREATE TABLE public.bank_statements ( id integer NOT NULL, bank_code character varying, iban character varying, - import_file_path character varying, queried_at timestamp without time zone, created_at timestamp without time zone, updated_at timestamp without time zone, @@ -778,7 +777,6 @@ CREATE TABLE public.domains ( id integer NOT NULL, name character varying NOT NULL, registrar_id integer NOT NULL, - registered_at timestamp without time zone, valid_to timestamp without time zone NOT NULL, registrant_id integer NOT NULL, transfer_code character varying NOT NULL, @@ -964,7 +962,7 @@ CREATE TABLE public.invoice_items ( description character varying NOT NULL, unit character varying NOT NULL, quantity integer NOT NULL, - price numeric(10,2) NOT NULL, + price numeric(10,3) NOT NULL, created_at timestamp without time zone, updated_at timestamp without time zone, creator_str character varying, @@ -1708,7 +1706,45 @@ ALTER SEQUENCE public.log_payment_orders_id_seq OWNED BY public.log_payment_orde -- --- Name: log_registrant_verifications; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- Name: log_prices; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.log_prices ( + id bigint NOT NULL, + item_type character varying NOT NULL, + item_id integer NOT NULL, + event character varying NOT NULL, + whodunnit character varying, + object json, + object_changes json, + created_at timestamp without time zone, + session character varying, + children json, + uuid character varying +); + + +-- +-- Name: log_prices_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.log_prices_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: log_prices_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.log_prices_id_seq OWNED BY public.log_prices.id; + + +-- +-- Name: log_registrant_verifications; Type: TABLE; Schema: public; Owner: - -- CREATE TABLE public.log_registrant_verifications ( @@ -2094,8 +2130,8 @@ CREATE TABLE public.prices ( price_cents integer NOT NULL, valid_from timestamp without time zone, valid_to timestamp without time zone, - creator_str character varying, updator_str character varying, + creator_str character varying, created_at timestamp without time zone NOT NULL, updated_at timestamp without time zone NOT NULL, duration interval, @@ -2840,7 +2876,14 @@ ALTER TABLE ONLY public.log_payment_orders ALTER COLUMN id SET DEFAULT nextval(' -- --- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- Name: log_prices id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.log_prices ALTER COLUMN id SET DEFAULT nextval('public.log_prices_id_seq'::regclass); + + +-- +-- Name: log_registrant_verifications id; Type: DEFAULT; Schema: public; Owner: - -- ALTER TABLE ONLY public.log_registrant_verifications ALTER COLUMN id SET DEFAULT nextval('public.log_registrant_verifications_id_seq'::regclass); @@ -3306,7 +3349,15 @@ ALTER TABLE ONLY public.log_payment_orders -- --- Name: log_registrant_verifications_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- Name: log_prices log_prices_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.log_prices + ADD CONSTRAINT log_prices_pkey PRIMARY KEY (id); + + +-- +-- Name: log_registrant_verifications log_registrant_verifications_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- ALTER TABLE ONLY public.log_registrant_verifications @@ -4828,6 +4879,7 @@ INSERT INTO "schema_migrations" (version) VALUES ('20191203083643'), ('20191206183853'), ('20191212133136'), +('20191217013225'), ('20191219112434'), ('20191219124429'), ('20191227110904'), @@ -4851,5 +4903,8 @@ INSERT INTO "schema_migrations" (version) VALUES ('20200811074839'), ('20200812090409'), ('20200812125810'), -('20200902131603'); +('20200902131603'), +('20200908131554'), +('20200910085157'), +('20200910102028'); diff --git a/lib/tasks/invoices/process_payments.rake b/lib/tasks/invoices/process_payments.rake index 340aba187..3e02a8838 100644 --- a/lib/tasks/invoices/process_payments.rake +++ b/lib/tasks/invoices/process_payments.rake @@ -36,6 +36,8 @@ namespace :invoices do reference_no: incoming_transaction.payment_reference_number, description: incoming_transaction.payment_description } transaction = bank_statement.bank_transactions.create!(transaction_attributes) + Invoice.create_from_transaction!(transaction) unless transaction.autobindable? + transaction.autobind_invoice end end diff --git a/test/fixtures/domains.yml b/test/fixtures/domains.yml index 87059e68a..c8ea1bfce 100644 --- a/test/fixtures/domains.yml +++ b/test/fixtures/domains.yml @@ -5,7 +5,6 @@ shop: registrar: bestnames registrant: john transfer_code: 65078d5 - registered_at: <%= Time.zone.parse('2010-07-04').to_s(:db) %> valid_to: <%= Time.zone.parse('2010-07-05').to_s(:db) %> outzone_at: <%= Time.zone.parse('2010-07-06').to_s(:db) %> delete_date: 2010-07-07 diff --git a/test/fixtures/setting_entries.yml b/test/fixtures/setting_entries.yml index 067f77c12..78db36465 100644 --- a/test/fixtures/setting_entries.yml +++ b/test/fixtures/setting_entries.yml @@ -182,8 +182,8 @@ registrar_ip_whitelist_enabled: created_at: <%= Time.zone.parse('2010-07-05') %> updated_at: <%= Time.zone.parse('2010-07-05') %> -request_confrimation_on_registrant_change_enabled: - code: request_confrimation_on_registrant_change_enabled +request_confirmation_on_registrant_change_enabled: + code: request_confirmation_on_registrant_change_enabled value: 'true' group: other format: boolean diff --git a/test/integration/epp/domain/update/base_test.rb b/test/integration/epp/domain/update/base_test.rb index de1ba84d8..6ce455948 100644 --- a/test/integration/epp/domain/update/base_test.rb +++ b/test/integration/epp/domain/update/base_test.rb @@ -6,12 +6,12 @@ class EppDomainUpdateBaseTest < EppTestCase setup do @domain = domains(:shop) @original_registrant_change_verification = - Setting.request_confrimation_on_registrant_change_enabled + Setting.request_confirmation_on_registrant_change_enabled ActionMailer::Base.deliveries.clear end teardown do - Setting.request_confrimation_on_registrant_change_enabled = + Setting.request_confirmation_on_registrant_change_enabled = @original_registrant_change_verification end @@ -87,7 +87,7 @@ class EppDomainUpdateBaseTest < EppTestCase end def test_requires_verification_from_current_registrant_when_provided_registrant_is_a_new_one - Setting.request_confrimation_on_registrant_change_enabled = true + Setting.request_confirmation_on_registrant_change_enabled = true new_registrant = contacts(:william).becomes(Registrant) assert_not_equal new_registrant, @domain.registrant @@ -124,7 +124,7 @@ class EppDomainUpdateBaseTest < EppTestCase end def test_requires_verification_from_current_registrant_when_not_yet_verified_by_registrar - Setting.request_confrimation_on_registrant_change_enabled = true + Setting.request_confirmation_on_registrant_change_enabled = true new_registrant = contacts(:william) assert_not_equal new_registrant, @domain.registrant @@ -161,7 +161,7 @@ class EppDomainUpdateBaseTest < EppTestCase end def test_updates_registrant_when_legaldoc_is_not_mandatory - Setting.request_confrimation_on_registrant_change_enabled = true + Setting.request_confirmation_on_registrant_change_enabled = true new_registrant = contacts(:william) assert_not_equal new_registrant, @domain.registrant @@ -197,7 +197,7 @@ class EppDomainUpdateBaseTest < EppTestCase end def test_dows_not_update_registrant_when_legaldoc_is_mandatory - Setting.request_confrimation_on_registrant_change_enabled = true + Setting.request_confirmation_on_registrant_change_enabled = true old_value = Setting.legal_document_is_mandatory Setting.legal_document_is_mandatory = true new_registrant = contacts(:william) @@ -226,7 +226,7 @@ class EppDomainUpdateBaseTest < EppTestCase end def test_skips_verification_when_provided_registrant_is_the_same_as_current_one - Setting.request_confrimation_on_registrant_change_enabled = true + Setting.request_confirmation_on_registrant_change_enabled = true request_xml = <<-XML @@ -260,7 +260,7 @@ class EppDomainUpdateBaseTest < EppTestCase end def test_skips_verification_when_registrant_changed_with_dispute_password - Setting.request_confrimation_on_registrant_change_enabled = true + Setting.request_confirmation_on_registrant_change_enabled = true dispute = disputes(:expired) dispute.update!(starts_at: Time.zone.now, expires_at: Time.zone.now + 5.days, closed: nil) new_registrant = contacts(:william) @@ -303,7 +303,7 @@ class EppDomainUpdateBaseTest < EppTestCase end def test_skips_verification_when_disabled - Setting.request_confrimation_on_registrant_change_enabled = false + Setting.request_confirmation_on_registrant_change_enabled = false new_registrant = contacts(:william).becomes(Registrant) assert_not_equal new_registrant, @domain.registrant @@ -340,7 +340,7 @@ class EppDomainUpdateBaseTest < EppTestCase end def test_skips_verification_from_current_registrant_when_already_verified_by_registrar - Setting.request_confrimation_on_registrant_change_enabled = true + Setting.request_confirmation_on_registrant_change_enabled = true new_registrant = contacts(:william).becomes(Registrant) assert_not_equal new_registrant, @domain.registrant @@ -377,7 +377,7 @@ class EppDomainUpdateBaseTest < EppTestCase end def test_clears_force_delete_when_registrar_changed - Setting.request_confrimation_on_registrant_change_enabled = true + Setting.request_confirmation_on_registrant_change_enabled = true new_registrant = contacts(:william).becomes(Registrant) @domain.schedule_force_delete(type: :fast_track) assert_not_equal new_registrant, @domain.registrant diff --git a/test/jobs/directo_invoice_forward_job_test.rb b/test/jobs/directo_invoice_forward_job_test.rb index 32ae39e7a..4e0edf7e5 100644 --- a/test/jobs/directo_invoice_forward_job_test.rb +++ b/test/jobs/directo_invoice_forward_job_test.rb @@ -151,4 +151,44 @@ class DirectoInvoiceForwardJobTest < ActiveSupport::TestCase DirectoInvoiceForwardJob.run(monthly: true, dry: false) end end + + def test_sends_each_monthly_invoice_separately + WebMock.reset! + + activity = account_activities(:one) + price = billing_prices(:create_one_year) + price.update(duration: '3 years') + activity.update(activity_type: 'create', price: price) + + # Creating account activity for second action + another_activity = activity.dup + another_activity.account = accounts(:two) + + AccountActivity.skip_callback(:create, :after, :update_balance) + another_activity.created_at = Time.zone.parse('2010-07-05 10:00') + another_activity.save + AccountActivity.set_callback(:create, :after, :update_balance) + + response = <<-XML + + + + + XML + + first_registrar_stub = stub_request(:post, ENV['directo_invoice_url']).with do |request| + body = CGI.unescape(request.body) + (body.include? 'StartDate') && (body.include? 'EndDate') && (body.include? 'bestnames') + end.to_return(status: 200, body: response) + + second_registrar_stub = stub_request(:post, ENV['directo_invoice_url']).with do |request| + body = CGI.unescape(request.body) + (body.include? 'StartDate') && (body.include? 'EndDate') && (body.include? 'goodnames') + end.to_return(status: 200, body: response) + + DirectoInvoiceForwardJob.run(monthly: true, dry: false) + + assert_requested first_registrar_stub + assert_requested second_registrar_stub + end end diff --git a/test/jobs/send_e_invoice_job_test.rb b/test/jobs/send_e_invoice_job_test.rb index 384479e92..86d761b42 100644 --- a/test/jobs/send_e_invoice_job_test.rb +++ b/test/jobs/send_e_invoice_job_test.rb @@ -13,7 +13,7 @@ class SendEInvoiceJobTest < ActiveSupport::TestCase EInvoice::Providers::TestProvider.deliveries.clear assert_nothing_raised do - SendEInvoiceJob.enqueue(@invoice.id) + SendEInvoiceJob.enqueue(@invoice.id, true) end @invoice.reload @@ -29,7 +29,7 @@ class SendEInvoiceJobTest < ActiveSupport::TestCase stub_request(:get, "https://testfinance.post.ee/finance/erp/erpServices.wsdl").to_timeout assert_raise HTTPClient::TimeoutError do - SendEInvoiceJob.enqueue(@invoice.id) + SendEInvoiceJob.enqueue(@invoice.id, true) end assert @invoicee_invoice_sent_at.blank? @@ -37,7 +37,7 @@ class SendEInvoiceJobTest < ActiveSupport::TestCase EInvoice::Providers::TestProvider.deliveries.clear assert_nothing_raised do - SendEInvoiceJob.enqueue(@invoice.id) + SendEInvoiceJob.enqueue(@invoice.id, true) end @invoice.reload diff --git a/test/models/bank_transaction_test.rb b/test/models/bank_transaction_test.rb index b8b0f65f7..9a9b02a74 100644 --- a/test/models/bank_transaction_test.rb +++ b/test/models/bank_transaction_test.rb @@ -26,14 +26,12 @@ class BankTransactionTest < ActiveSupport::TestCase another_item.save another_invoice.reload - first_transaction = BankTransaction.new(description: 'invoice #2221', - sum: 10, + first_transaction = BankTransaction.new(sum: 10, description: 'Order nr 1 from registrar 1234567 second number 2345678') first_transaction.create_activity(another_invoice.buyer, another_invoice) - transaction = BankTransaction.new(description: 'invoice #2222', - sum: 10, + transaction = BankTransaction.new(sum: 10, description: 'Order nr 1 from registrar 1234567 second number 2345678') assert_difference 'AccountActivity.count' do @@ -54,8 +52,7 @@ class BankTransactionTest < ActiveSupport::TestCase another_invoice.reload another_invoice.update(reference_no: '1234567', number: '2221', cancelled_at: Time.zone.now) - transaction = BankTransaction.new(description: 'invoice #2222', - sum: 10, + transaction = BankTransaction.new(sum: 10, description: 'Order nr 1 from registrar 1234567 second number 2345678') assert_difference 'AccountActivity.count' do @@ -74,8 +71,7 @@ class BankTransactionTest < ActiveSupport::TestCase another_item.save another_invoice.reload - transaction = BankTransaction.new(description: 'invoice #2222', - sum: 10, + transaction = BankTransaction.new(sum: 10, description: 'Order nr 1 from registrar 1234567 second number 2345678') assert_difference 'AccountActivity.count' do @@ -90,8 +86,7 @@ class BankTransactionTest < ActiveSupport::TestCase def test_matches_against_invoice_nubmber_and_reference_number_in_description create_payable_invoice(number: '2222', total: 10, reference_no: '1234567') - transaction = BankTransaction.new(description: 'invoice #2222', - sum: 10, + transaction = BankTransaction.new(sum: 10, description: 'Order nr 1 from registrar 1234567 second number 2345678') assert_difference 'AccountActivity.count' do @@ -99,6 +94,18 @@ class BankTransactionTest < ActiveSupport::TestCase end end + def test_no_errors_if_no_valid_refnumber_in_description + create_payable_invoice(number: '2222', total: 10, reference_no: '1234567') + transaction = BankTransaction.new(sum: 10, + description: 'Order nr 1 from registrar 123456') + + assert_no_difference 'AccountActivity.count' do + assert_nothing_raised do + transaction.autobind_invoice + end + end + end + def test_resets_pending_registrar_balance_reload registrar = registrar_with_pending_balance_auto_reload create_payable_invoice(number: '2222', total: 10, reference_no: '1111') @@ -149,6 +156,24 @@ class BankTransactionTest < ActiveSupport::TestCase assert transaction.errors.full_messages.include?('Cannot bind cancelled invoice') end + def test_assumes_7_digit_number_is_reference_no_in_desc + statement = BankTransaction.new + statement.description = 'number 1234567 defo valid' + assert_equal '1234567', statement.parsed_ref_number + end + + def test_determines_correct_ref_no_from_description + statement = BankTransaction.new + ref_no = registrars(:bestnames).reference_no + statement.description = "invoice 123 125 55 4521 #{ref_no} 7541 defo valid" + assert_equal ref_no.to_s, statement.parsed_ref_number + end + + def test_parsed_ref_no_returns_nil_if_ref_not_found + statement = BankTransaction.new + statement.description = "all invalid 12 123 55 77777 --" + assert_nil statement.parsed_ref_number + end private def create_payable_invoice(attributes) diff --git a/test/models/domain_test.rb b/test/models/domain_test.rb index ec6f60c52..b4a1d7b47 100644 --- a/test/models/domain_test.rb +++ b/test/models/domain_test.rb @@ -425,6 +425,12 @@ class DomainTest < ActiveSupport::TestCase assert_not(@domain.force_delete_scheduled?) end + def test_aliases_registered_at_to_created_at + created_at = Time.zone.parse('2010-07-05 10:00') + domain = Domain.new(created_at: created_at) + assert_equal created_at, domain.registered_at + end + private def valid_domain diff --git a/test/models/invoice_test.rb b/test/models/invoice_test.rb index 9c1c45610..150e8032c 100644 --- a/test/models/invoice_test.rb +++ b/test/models/invoice_test.rb @@ -1,6 +1,8 @@ require 'test_helper' class InvoiceTest < ActiveSupport::TestCase + include ActionMailer::TestHelper + setup do @invoice = invoices(:one) end @@ -109,4 +111,33 @@ class InvoiceTest < ActiveSupport::TestCase seller_zip: nil) assert_equal 'street, city, state', invoice.seller_address end + + def test_creates_invoice_with_bank_transaction_total + registrar = registrars(:bestnames) + transaction = bank_transactions(:one).dup + transaction.reference_no = registrar.reference_no + transaction.sum = 250 + + invoice = Invoice.create_from_transaction!(transaction) + assert_equal 250, invoice.total + + transaction.sum = 146.88 + invoice = Invoice.create_from_transaction!(transaction) + assert_equal 146.88, invoice.total + + transaction.sum = 0.99 + invoice = Invoice.create_from_transaction!(transaction) + assert_equal 0.99, invoice.total + end + + def test_emails_invoice_after_creating_topup_invoice + registrar = registrars(:bestnames) + transaction = bank_transactions(:one).dup + transaction.reference_no = registrar.reference_no + transaction.sum = 250 + + assert_emails 1 do + Invoice.create_from_transaction!(transaction) + end + end end diff --git a/test/system/admin_area/bank_statement_test.rb b/test/system/admin_area/bank_statement_test.rb index 53cbcc177..6de21b1c3 100644 --- a/test/system/admin_area/bank_statement_test.rb +++ b/test/system/admin_area/bank_statement_test.rb @@ -6,11 +6,48 @@ class AdminAreaBankStatementTest < ApplicationSystemTestCase travel_to Time.zone.parse('2010-07-05 00:30:00') end - def test_import_statement - assert_difference 'BankStatement.count', 1 do - visit import_admin_bank_statements_path - attach_file 'Th6 file', Rails.root.join('test', 'fixtures', 'files', 'bank_statement_test.txt').to_s - click_link_or_button 'Save' - end + def test_can_create_statement_manually + create_bank_statement + assert_text 'Record created' + end + + def test_can_add_transaction_to_statement_manually + create_bank_statement + click_link_or_button 'Add' + assert_text 'Create bank transaction' + + fill_in 'Description', with: 'Invoice with id 123' + fill_in 'Reference number', with: '1232' + fill_in 'Sum', with: '500' + fill_in 'Paid at', with: Time.zone.today.to_s + click_link_or_button 'Save' + assert_text 'Record created' + end + + def test_can_bind_statement_transactions + registrar = registrars(:bestnames) + registrar.issue_prepayment_invoice(amount: 500) + invoice = registrar.invoices.last + + create_bank_statement + click_link_or_button 'Add' + assert_text 'Create bank transaction' + + fill_in 'Description', with: "Invoice with id #{invoice.number}" + fill_in 'Reference number', with: invoice.reference_no + fill_in 'Sum', with: invoice.total + fill_in 'Paid at', with: Time.zone.today.to_s + click_link_or_button 'Save' + + click_link_or_button 'Back to bank statement' + click_link_or_button 'Bind invoices' + + assert_text 'Invoices were fully binded' + end + + def create_bank_statement + visit admin_bank_statements_path + click_link_or_button 'Add' + click_link_or_button 'Save' end end diff --git a/test/system/registrant_area/domains/details_test.rb b/test/system/registrant_area/domains/details_test.rb index 5b2e30ba3..2f61d46be 100644 --- a/test/system/registrant_area/domains/details_test.rb +++ b/test/system/registrant_area/domains/details_test.rb @@ -12,7 +12,7 @@ class RegistrantAreaDomainDetailsTest < ApplicationSystemTestCase visit registrant_domain_url(@domain) assert_text 'Name shop.test' - assert_text "Registered at #{l Time.zone.parse('2010-07-04')}" + assert_text "Registered at #{l @domain.registered_at}" assert_link 'Best Names', href: registrant_registrar_path(@domain.registrar) assert_text 'Transfer code' @@ -73,4 +73,4 @@ class RegistrantAreaDomainDetailsTest < ApplicationSystemTestCase assert_field nil, with: registrant_domain_update_confirm_url(@domain, token: 'a01') end -end \ No newline at end of file +end diff --git a/test/tasks/invoices/process_payments_test.rb b/test/tasks/invoices/process_payments_test.rb index bd447be29..eeaf411cc 100644 --- a/test/tasks/invoices/process_payments_test.rb +++ b/test/tasks/invoices/process_payments_test.rb @@ -82,6 +82,25 @@ class ProcessPaymentsTaskTest < ActiveSupport::TestCase assert payment_order.failed? end + def test_credits_registrar_account_without_invoice_beforehand + registrar = registrars(:bestnames) + + assert_changes -> { registrar.accounts.first.balance } do + run_task + end + + assert_changes -> { registrar.invoices.count } do + run_task + end + end + + def test_topup_creates_invoice_with_total_of_transactioned_amount + registrar = registrars(:bestnames) + run_task + + assert_equal 0.1, registrar.invoices.last.total + end + def test_output assert_output "Transactions processed: 1\n" do run_task