diff --git a/Gemfile b/Gemfile index c4e916929..241eeda24 100644 --- a/Gemfile +++ b/Gemfile @@ -67,9 +67,7 @@ gem 'jquery-ui-rails', '6.0.1' gem 'pdfkit' gem 'redis' gem 'sidekiq', '~> 7.0' - -gem 'company_register', github: 'internetee/company_register', - branch: 'issues-with-upcoming-data' +gem 'company_register', github: 'internetee/company_register', branch: :master gem 'domain_name' gem 'e_invoice', github: 'internetee/e_invoice', branch: :master gem 'haml', '~> 6.0' diff --git a/Gemfile.lock b/Gemfile.lock index ace0966c2..51bd77843 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ GIT remote: https://github.com/internetee/company_register.git - revision: 1e91fec78212d7e549a1c2362c011761a447bbcd - branch: issues-with-upcoming-data + revision: 2c31da54c57db13324161eeb8db7e9f81af81987 + branch: master specs: company_register (0.1.0) activesupport @@ -214,7 +214,7 @@ GEM activerecord (>= 5.a) database_cleaner-core (~> 2.0.0) database_cleaner-core (2.0.1) - date (3.3.4) + date (3.4.1) devise (4.8.0) bcrypt (~> 3.0) orm_adapter (~> 0.1) @@ -347,9 +347,9 @@ GEM net-protocol net-pop (0.1.2) net-protocol - net-protocol (0.1.3) + net-protocol (0.2.2) timeout - net-smtp (0.3.3) + net-smtp (0.5.1) net-protocol netrc (0.11.0) newrelic-infinite_tracing (8.1.0) @@ -520,7 +520,7 @@ GEM tilt (2.0.11) time (0.3.0) date - timeout (0.3.0) + timeout (0.4.3) truemail (3.0.3) simpleidn (~> 0.2.1) tzinfo (2.0.6) diff --git a/app/interactions/actions/contact_create.rb b/app/interactions/actions/contact_create.rb index b9d1d6596..dfa2d1299 100644 --- a/app/interactions/actions/contact_create.rb +++ b/app/interactions/actions/contact_create.rb @@ -14,7 +14,7 @@ module Actions maybe_attach_legal_doc maybe_validate_ident maybe_change_email - # maybe_company_is_relevant + maybe_company_is_relevant commit maybe_validate_phone_number maybe_validate_contact @@ -79,16 +79,17 @@ module Actions @error = true end - # def maybe_company_is_relevant - # return true unless contact.org? + def maybe_company_is_relevant + return true unless contact.org? + return true unless contact.ident_country_code == 'EE' - # company_status = contact.return_company_status + company_status = contact.return_company_status - # return if [Contact::REGISTERED, Contact::LIQUIDATED].include? company_status - # contact.add_epp_error('2003', nil, 'ident', I18n.t('errors.messages.company_not_registered')) + return true if [Contact::REGISTERED, Contact::LIQUIDATED].include? company_status + contact.add_epp_error('2003', nil, 'ident', I18n.t('errors.messages.company_not_registered')) - # @error = true - # end + @error = true + end def maybe_attach_legal_doc ::Actions::BaseAction.attach_legal_doc_to_new(contact, legal_document, domain: false) diff --git a/app/interactions/domains/cancel_force_delete/clear_force_delete_data.rb b/app/interactions/domains/cancel_force_delete/clear_force_delete_data.rb index 1e6bcccd9..cfd522589 100644 --- a/app/interactions/domains/cancel_force_delete/clear_force_delete_data.rb +++ b/app/interactions/domains/cancel_force_delete/clear_force_delete_data.rb @@ -6,6 +6,7 @@ module Domains domain.force_delete_date = nil domain.force_delete_start = nil domain.status_notes[DomainStatus::FORCE_DELETE] = nil + domain.skip_whois_record_update = false domain.save(validate: false) end end diff --git a/app/interactions/domains/cancel_force_delete/remove_force_delete_statuses.rb b/app/interactions/domains/cancel_force_delete/remove_force_delete_statuses.rb index bc4122f80..77c8eba5e 100644 --- a/app/interactions/domains/cancel_force_delete/remove_force_delete_statuses.rb +++ b/app/interactions/domains/cancel_force_delete/remove_force_delete_statuses.rb @@ -14,6 +14,7 @@ module Domains domain.admin_store_statuses_history -= domain_statuses unless domain.admin_store_statuses_history.nil? rejected_statuses = domain.statuses.reject { |a| domain_statuses.include? a } domain.statuses = rejected_statuses + domain.skip_whois_record_update = true domain.save(validate: false) end end diff --git a/app/interactions/domains/cancel_force_delete/restore_statuses_before_force_delete.rb b/app/interactions/domains/cancel_force_delete/restore_statuses_before_force_delete.rb index f913d68b9..6d3a91063 100644 --- a/app/interactions/domains/cancel_force_delete/restore_statuses_before_force_delete.rb +++ b/app/interactions/domains/cancel_force_delete/restore_statuses_before_force_delete.rb @@ -8,6 +8,7 @@ module Domains domain.force_delete_domain_statuses_history = nil domain.admin_store_statuses_history = nil + domain.skip_whois_record_update = true domain.save(validate: false) end end diff --git a/app/interactions/domains/force_delete/base.rb b/app/interactions/domains/force_delete/base.rb index 712d0c08e..31093c839 100644 --- a/app/interactions/domains/force_delete/base.rb +++ b/app/interactions/domains/force_delete/base.rb @@ -16,6 +16,9 @@ module Domains string :email, default: nil, description: 'Possible invalid email to notify on' + string :notes, + default: nil, + description: 'Notes to add reason to the force delete' validates :type, inclusion: { in: %i[fast_track soft] } end diff --git a/app/interactions/domains/force_delete/notify_by_email.rb b/app/interactions/domains/force_delete/notify_by_email.rb index e512657b0..0e704ee99 100644 --- a/app/interactions/domains/force_delete/notify_by_email.rb +++ b/app/interactions/domains/force_delete/notify_by_email.rb @@ -4,6 +4,7 @@ module Domains def execute return unless notify_by_email + domain.skip_whois_record_update = false if type == :fast_track send_email domain.update(contact_notification_sent_date: Time.zone.today) diff --git a/app/interactions/domains/force_delete/notify_registrar.rb b/app/interactions/domains/force_delete/notify_registrar.rb index 279fac584..2e209a4c3 100644 --- a/app/interactions/domains/force_delete/notify_registrar.rb +++ b/app/interactions/domains/force_delete/notify_registrar.rb @@ -11,7 +11,8 @@ module Domains ident: domain.registrant.ident, domain_name: domain.name, outzone_date: domain.outzone_date, - purge_date: domain.purge_date) + purge_date: domain.purge_date, + notes: notes) else I18n.t('force_delete_set_on_domain', domain_name: domain.name, @@ -30,7 +31,8 @@ module Domains ident: domain.registrant.ident, domain_name: domain.name, outzone_date: domain.outzone_date, - purge_date: domain.purge_date) + purge_date: domain.purge_date, + notes: notes) else I18n.t('force_delete_auto_email', domain_name: domain.name, diff --git a/app/interactions/domains/force_delete/post_set_process.rb b/app/interactions/domains/force_delete/post_set_process.rb index 0c7ae061c..036fd3531 100644 --- a/app/interactions/domains/force_delete/post_set_process.rb +++ b/app/interactions/domains/force_delete/post_set_process.rb @@ -11,6 +11,7 @@ module Domains # Allow deletion statuses.delete(DomainStatus::CLIENT_DELETE_PROHIBITED) + domain.skip_whois_record_update = notify_by_email ? true : false domain.save(validate: false) end diff --git a/app/interactions/domains/force_delete/prepare_domain.rb b/app/interactions/domains/force_delete/prepare_domain.rb index 116957a87..be05ce480 100644 --- a/app/interactions/domains/force_delete/prepare_domain.rb +++ b/app/interactions/domains/force_delete/prepare_domain.rb @@ -8,6 +8,7 @@ module Domains def execute domain.force_delete_domain_statuses_history = domain.statuses domain.statuses |= STATUSES_TO_SET + domain.skip_whois_record_update = true domain.save(validate: false) end end diff --git a/app/interactions/domains/force_delete/set_status.rb b/app/interactions/domains/force_delete/set_status.rb index 770903d5a..cedef18d5 100644 --- a/app/interactions/domains/force_delete/set_status.rb +++ b/app/interactions/domains/force_delete/set_status.rb @@ -4,6 +4,8 @@ module Domains def execute domain.force_delete_type = type type == :fast_track ? force_delete_fast_track : force_delete_soft + domain.status_notes[DomainStatus::FORCE_DELETE] = "Company no: #{domain.registrant.ident}" if reason == 'invalid_company' + domain.skip_whois_record_update = true domain.save(validate: false) end @@ -12,8 +14,6 @@ module Domains expire_warning_period_days + redemption_grace_period_days domain.force_delete_start = Time.zone.today + 1.day - - domain.status_notes[DomainStatus::FORCE_DELETE] = "Company no: #{domain.registrant.ident}" if reason == 'invalid_company' end def force_delete_soft diff --git a/app/jobs/company_register_status_job.rb b/app/jobs/company_register_status_job.rb index b40b55b00..7f0e525a6 100644 --- a/app/jobs/company_register_status_job.rb +++ b/app/jobs/company_register_status_job.rb @@ -3,6 +3,13 @@ require 'zip' class CompanyRegisterStatusJob < ApplicationJob PAYMENT_STATEMENT_BUSINESS_REGISTRY_REASON = 'Kustutamiskanne dokumentide hoidjata' + REGISTRY_STATUSES = { + Contact::REGISTERED => 'registered', + Contact::LIQUIDATED => 'liquidated', + Contact::BANKRUPT => 'bankrupt', + Contact::DELETED => 'deleted' + } + queue_as :default def perform(days_interval = 14, spam_time_delay = 1, batch_size = 100) @@ -22,43 +29,64 @@ class CompanyRegisterStatusJob < ApplicationJob sleep spam_time_delay company_status = contact.return_company_status - contact.update!(company_register_status: company_status, checked_company_at: Time.zone.now) + + handle_company_statuses(contact, company_status) + status = company_status.blank? ? Contact::DELETED : company_status + + update_validation_company_status(contact:contact , status: status) + end + + def handle_company_statuses(contact, company_status) + return if company_status == Contact::BANKRUPT case company_status when Contact::REGISTERED lift_force_delete(contact) if check_for_force_delete(contact) when Contact::LIQUIDATED - ContactInformMailer.company_liquidation(contact: contact).deliver_now + send_email_for_liquidation(contact) else - delete_process(contact) + delete_process(contact, company_status) end + end - status = company_status.blank? ? Contact::DELETED : company_status - update_validation_company_status(contact:contact , status: status) + def send_email_for_liquidation(contact) + return if contact.company_register_status == Contact::LIQUIDATED + + ContactInformMailer.company_liquidation(contact: contact).deliver_now end def sampling_registrant_contact(days_interval) - Registrant.where(ident_type: 'org', ident_country_code: 'EE').where( - "(company_register_status IS NULL OR checked_company_at IS NULL) OR - (company_register_status = ? AND checked_company_at < ?) OR - company_register_status IN (?)", - Contact::REGISTERED, days_interval.days.ago, [Contact::LIQUIDATED, Contact::BANKRUPT, Contact::DELETED] - ) + Contact.joins(:registrant_domains) + .where(ident_type: 'org', ident_country_code: 'EE') + .where( + "(company_register_status IS NULL OR checked_company_at IS NULL) OR + (company_register_status = ? AND checked_company_at < ?) OR + company_register_status IN (?)", + Contact::REGISTERED, days_interval.days.ago, [Contact::LIQUIDATED, Contact::BANKRUPT, Contact::DELETED] + ) + .distinct end def update_validation_company_status(contact:, status:) contact.update(company_register_status: status, checked_company_at: Time.zone.now) end - def schedule_force_delete(contact) + def schedule_force_delete(contact, company_status) contact.registrant_domains.each do |domain| next if domain.force_delete_scheduled? + company_status = if company_status.nil? + 'Contact not found in EE business registry' + else + "Contact has status #{REGISTRY_STATUSES[company_status]}" + end + domain.schedule_force_delete( type: :fast_track, notify_by_email: true, reason: 'invalid_company', - email: contact.email + email: contact.email, + notes: company_status ) end end @@ -66,29 +94,42 @@ class CompanyRegisterStatusJob < ApplicationJob def check_for_force_delete(contact) contact.registrant_domains.any? do |domain| notes = domain.status_notes[DomainStatus::FORCE_DELETE] - notes && notes.include?("Company no: #{contact.ident}") + notes_check = notes && notes.include?("Company no: #{contact.ident}") + + if !notes_check && domain.force_delete_data.present? + domain.template_name == 'invalid_company' + else + notes_check + end end end def lift_force_delete(contact) - contact.registrant_domains.each(&:cancel_force_delete) + contact.registrant_domains.each do |domain| + next unless domain.force_delete_scheduled? + + domain.cancel_force_delete + end end - def delete_process(contact) + def delete_process(contact, company_status) + Rails.logger.info("Processing company details for contact #{contact.id} with ident: #{contact.ident} (#{contact.ident.class})") company_details_response = contact.return_company_details if company_details_response.empty? - schedule_force_delete(contact) + Rails.logger.info("Empty company details response for contact #{contact.id}") + schedule_force_delete(contact, company_status) return end kandeliik_tekstina = extract_kandeliik_tekstina(company_details_response) + Rails.logger.info("Kandeliik tekstina for contact #{contact.id}: #{kandeliik_tekstina}") if kandeliik_tekstina == PAYMENT_STATEMENT_BUSINESS_REGISTRY_REASON - soft_delete_company(contact) + soft_delete_company(contact, company_status) else - schedule_force_delete(contact) + schedule_force_delete(contact, company_status) end end @@ -98,9 +139,18 @@ class CompanyRegisterStatusJob < ApplicationJob company_details_response.first.kandeliik.last.last.kandeliik_tekstina end - def soft_delete_company(contact) + def soft_delete_company(contact, company_status) contact.registrant_domains.reject { |domain| domain.force_delete_scheduled? }.each do |domain| - domain.schedule_force_delete(type: :soft) + next if domain.force_delete_scheduled? + + company_status = company_status.nil? ? 'No information' : REGISTRY_STATUSES[company_status] + + domain.schedule_force_delete( + type: :soft, + notify_by_email: true, + reason: 'invalid_company', + email: contact.email, + notes: "Contact has status #{company_status}") end puts "Soft delete process initiated for company: #{contact.name} with ID: #{contact.id}" diff --git a/app/models/concerns/domain/force_delete.rb b/app/models/concerns/domain/force_delete.rb index e0f98ea84..6a7949fef 100644 --- a/app/models/concerns/domain/force_delete.rb +++ b/app/models/concerns/domain/force_delete.rb @@ -47,9 +47,9 @@ module Domain::ForceDelete statuses.include?(DomainStatus::FORCE_DELETE) end - def schedule_force_delete(type: :fast_track, notify_by_email: false, reason: nil, email: nil) + def schedule_force_delete(type: :fast_track, notify_by_email: false, reason: nil, email: nil, notes: nil) Domains::ForceDelete::SetForceDelete.run(domain: self, type: type, reason: reason, - notify_by_email: notify_by_email, email: email) + notify_by_email: notify_by_email, email: email, notes: notes) end def cancel_force_delete diff --git a/app/models/contact.rb b/app/models/contact.rb index 51c5ecd2c..0e5d9de06 100644 --- a/app/models/contact.rb +++ b/app/models/contact.rb @@ -87,6 +87,11 @@ class Contact < ApplicationRecord after_save :update_related_whois_records before_validation :clear_address_modifications, if: -> { !self.class.address_processing? } + # TODO: remove after testing + after_save do + Rails.logger.info "Contact saved or updated: #{id}" + end + self.ignored_columns = %w[legacy_id legacy_history_id] ORG = 'org'.freeze diff --git a/app/models/contact/company_register.rb b/app/models/contact/company_register.rb index 4f036dd97..803867ecf 100644 --- a/app/models/contact/company_register.rb +++ b/app/models/contact/company_register.rb @@ -26,8 +26,8 @@ module Contact::CompanyRegister def return_company_details return unless org? - - company_register.company_details(registration_number: ident) + + company_register.company_details(registration_number: ident.to_s) rescue CompanyRegister::NotAvailableError [] end diff --git a/app/models/domain.rb b/app/models/domain.rb index 389d361ba..14536b764 100644 --- a/app/models/domain.rb +++ b/app/models/domain.rb @@ -89,6 +89,8 @@ class Domain < ApplicationRecord has_many :registrant_verifications, dependent: :destroy has_one :csync_record, dependent: :destroy + attribute :skip_whois_record_update, :boolean, default: false + after_initialize do self.pending_json = {} if pending_json.blank? self.statuses = [] if statuses.nil? @@ -721,6 +723,8 @@ class Domain < ApplicationRecord end def update_whois_record + return if skip_whois_record_update + UpdateWhoisRecordJob.set(wait: 1.minute).perform_later name, 'domain' end diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb index 1ddfb9c5e..b2d067a2f 100644 --- a/config/initializers/sidekiq.rb +++ b/config/initializers/sidekiq.rb @@ -1 +1,35 @@ require 'sidekiq/web' # Require at the top of the initializer + +Sidekiq.configure_server do |config| + config.logger.level = Logger::INFO + + # Custom job logging format + Sidekiq.logger.formatter = proc do |severity, datetime, progname, msg| + thread_id = Thread.current.object_id.to_s(36) + process_id = Process.pid + + # Skip messages containing "start" or "Performed" + next nil if msg.to_s == 'start' || msg.to_s.include?('Performed') + + # Skip "fail" message as we'll get detailed error after + next nil if msg.to_s == 'fail' + + # Store job info when job starts + if msg.to_s.start_with?('Performing') + Thread.current[:current_job_info] = msg.to_s + end + + # Add job info to done message + if msg.to_s == 'done' && Thread.current[:current_job_info] + job_info = Thread.current[:current_job_info].sub('Performing', 'Completed') + msg = job_info + end + + "#{datetime.utc.iso8601(3)} pid=#{process_id} tid=#{thread_id} #{severity}: #{msg}\n" + end +end + +# Client configuration (if needed) +Sidekiq.configure_client do |config| + config.logger.level = Logger::INFO +end diff --git a/config/locales/en.yml b/config/locales/en.yml index 164398e90..ba9120f18 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -676,7 +676,7 @@ en: actions: Actions contact_has_been_archived: 'Contact with code %{contact_code} has been archieved because it has been orphaned for longer than %{orphan_months} months.' dns_policy_violation: "Data management policy violation: DNSKEY does not match or not found in the authoritative nameservers" - invalid_ident: 'Force delete set on domain %{domain_name}. Outzone date: %{outzone_date}. Purge date: %{purge_date}. Invalid ident %{ident}' + invalid_ident: 'Force delete set on domain %{domain_name}. Outzone date: %{outzone_date}. Purge date: %{purge_date}. Invalid ident %{ident}. %{notes}' number: currency: diff --git a/test/integration/repp/v1/contacts/create_test.rb b/test/integration/repp/v1/contacts/create_test.rb index bcb196f1a..505aabfe1 100644 --- a/test/integration/repp/v1/contacts/create_test.rb +++ b/test/integration/repp/v1/contacts/create_test.rb @@ -188,39 +188,38 @@ class ReppV1ContactsCreateTest < ActionDispatch::IntegrationTest ENV['shunter_enabled'] = 'false' end - # def test_returns_error_response_if_company_not_existed - # original_new_method = CompanyRegister::Client.method(:new) - # CompanyRegister::Client.define_singleton_method(:new) do - # object = original_new_method.call - # def object.simple_data(registration_number:) - # [Company.new('1234567', 'ACME Ltd', 'K')] - # end - # object - # end + def test_returns_error_response_if_company_not_existed + original_new_method = CompanyRegister::Client.method(:new) + CompanyRegister::Client.define_singleton_method(:new) do + object = original_new_method.call + def object.simple_data(registration_number:) + [Company.new('1234567', 'ACME Ltd', 'K')] + end + object + end - # request_body = { - # "contact": { - # "name": 'Donald Trump', - # "phone": '+372.51111112', - # "email": 'donald@trumptower.com', - # "ident": { - # "ident_type": 'org', - # "ident_country_code": 'EE', - # "ident": '70000313', - # }, - # }, - # } + request_body = { + "contact": { + "name": 'Donald Trump', + "phone": '+372.51111112', + "email": 'donald@trumptower.com', + "ident": { + "ident_type": 'org', + "ident_country_code": 'EE', + "ident": '70000313', + }, + }, + } - # post '/repp/v1/contacts', headers: @auth_headers, params: request_body - # json = JSON.parse(response.body, symbolize_names: true) + post '/repp/v1/contacts', headers: @auth_headers, params: request_body + json = JSON.parse(response.body, symbolize_names: true) - # assert_response :bad_request - # assert_equal 2003, json[:code] - # puts json[:message] - # assert json[:message].include? 'Company is not registered' + assert_response :bad_request + assert_equal 2003, json[:code] + assert json[:message].include? 'Company is not registered' - # CompanyRegister::Client.define_singleton_method(:new, original_new_method) - # end + CompanyRegister::Client.define_singleton_method(:new, original_new_method) + end def test_contact_created_with_existed_company original_new_method = CompanyRegister::Client.method(:new) diff --git a/test/interactions/force_delete_email/base_test.rb b/test/interactions/force_delete_email/base_test.rb index ffca7b3c5..b5842850f 100644 --- a/test/interactions/force_delete_email/base_test.rb +++ b/test/interactions/force_delete_email/base_test.rb @@ -4,6 +4,7 @@ class BaseTest < ActiveSupport::TestCase setup do @domain = domains(:shop) @domain_airport = domains(:airport) + travel_to Time.zone.parse('2010-07-05 00:30:00') end def test_hold_domains_force_delete_email @@ -58,21 +59,6 @@ class BaseTest < ActiveSupport::TestCase Setting.redemption_grace_period.days).to_date end - def test_should_send_poll_message_about_45_days_to_registrar - refute @domain_airport.force_delete_scheduled? - @domain_airport.update!(valid_to: Time.zone.now + 3.years - 1.month - 4.days) - @domain_airport.reload - prepare_contact - - contact = @domain_airport.admin_contacts.first - - assert_difference -> { @domain_airport.registrar.notifications.count } do - Domains::ForceDeleteEmail::Base.run(email: contact.email) - end - - @domain_airport.reload - end - private def prepare_contact diff --git a/test/jobs/company_register_status_job_test.rb b/test/jobs/company_register_status_job_test.rb index aff3785f9..dad0f5da5 100644 --- a/test/jobs/company_register_status_job_test.rb +++ b/test/jobs/company_register_status_job_test.rb @@ -184,7 +184,8 @@ class CompanyRegisterStatusJobTest < ActiveSupport::TestCase ident: @registrant_acme.ident, domain_name: @registrant_acme.registrant_domains.first.name, outzone_date: @registrant_acme.registrant_domains.first.outzone_date, - purge_date: @registrant_acme.registrant_domains.first.purge_date) + purge_date: @registrant_acme.registrant_domains.first.purge_date, + notes: "Contact has status deleted") assert_equal @registrant_acme.registrant_domains.first.registrar.notifications.last.text, template CompanyRegister::Client.define_singleton_method(:new, original_new_method) @@ -303,7 +304,7 @@ class CompanyRegisterStatusJobTest < ActiveSupport::TestCase @registrant_acme.reload - assert @registrant_acme.registrant_domains.all?(&:force_delete_scheduled?) + assert_not @registrant_acme.registrant_domains.all?(&:force_delete_scheduled?) assert_equal Contact::BANKRUPT, @registrant_acme.company_register_status CompanyRegister::Client.define_singleton_method(:new, original_new_method) diff --git a/test/models/domain/force_delete_test.rb b/test/models/domain/force_delete_test.rb index c889056a2..afdd92a9d 100644 --- a/test/models/domain/force_delete_test.rb +++ b/test/models/domain/force_delete_test.rb @@ -532,7 +532,7 @@ class ForceDeleteTest < ActionMailer::TestCase assert_equal Date.parse('2010-09-19'), @domain.force_delete_date.to_date assert_equal Date.parse('2010-08-05'), @domain.force_delete_start.to_date - assert_enqueued_jobs 8 + assert_enqueued_jobs 6 end def prepare_bounced_email_address(email)