Optimized PaperTrail Versions in Domain Force Delete Process

This commit is contained in:
tsoganov 2025-05-21 15:50:48 +03:00
parent dbd8d77e6e
commit 3e3c42ce7e
6 changed files with 67 additions and 43 deletions

View file

@ -12,8 +12,6 @@ module Domains
# Allow deletion # Allow deletion
statuses.delete(DomainStatus::CLIENT_DELETE_PROHIBITED) statuses.delete(DomainStatus::CLIENT_DELETE_PROHIBITED)
domain.skip_whois_record_update = notify_by_email ? true : false domain.skip_whois_record_update = notify_by_email ? true : false
domain.save(validate: false)
end end
end end
end end

View file

@ -9,7 +9,6 @@ module Domains
domain.force_delete_domain_statuses_history = domain.statuses domain.force_delete_domain_statuses_history = domain.statuses
domain.statuses |= STATUSES_TO_SET domain.statuses |= STATUSES_TO_SET
domain.skip_whois_record_update = true domain.skip_whois_record_update = true
domain.save(validate: false)
end end
end end
end end

View file

@ -3,12 +3,20 @@ module Domains
class SetForceDelete < Base class SetForceDelete < Base
def execute def execute
compose(CheckDiscarded, inputs.to_h) compose(CheckDiscarded, inputs.to_h)
compose(PrepareDomain, inputs.to_h)
compose(SetStatus, inputs.to_h) Domain.transaction do
compose(PostSetProcess, inputs.to_h) compose(PrepareDomain, inputs.to_h)
compose(NotifyRegistrar, inputs.to_h) compose(SetStatus, inputs.to_h)
compose(NotifyByEmail, inputs.to_h) compose(PostSetProcess, inputs.to_h)
compose(NotifyMultiyearsExpirationDomain, inputs.to_h)
# Save the domain once with all accumulated changes
# This will create a single PaperTrail version
domain.save(validate: false)
compose(NotifyRegistrar, inputs.to_h)
compose(NotifyByEmail, inputs.to_h)
compose(NotifyMultiyearsExpirationDomain, inputs.to_h)
end
end end
end end
end end

View file

@ -4,13 +4,12 @@ module Domains
def execute def execute
domain.force_delete_type = type domain.force_delete_type = type
type == :fast_track ? force_delete_fast_track : force_delete_soft 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' set_status_notes
domain.skip_whois_record_update = true domain.skip_whois_record_update = true
domain.force_delete_domain_statuses_history_data = { domain.force_delete_domain_statuses_history_data = {
reason: domain.status_notes[DomainStatus::FORCE_DELETE], reason: domain.status_notes[DomainStatus::FORCE_DELETE],
date: Time.zone.now date: Time.zone.now
} }
domain.save(validate: false)
end end
def force_delete_fast_track def force_delete_fast_track
@ -27,6 +26,11 @@ module Domains
private private
def set_status_notes
domain.status_notes[DomainStatus::FORCE_DELETE] = "Company no: #{domain.registrant.ident}" if reason == 'invalid_company'
domain.status_notes[DomainStatus::FORCE_DELETE] = email if reason == 'invalid_email'
end
def soft_forcedelete_dates(years) def soft_forcedelete_dates(years)
domain.force_delete_start = domain.valid_to - years.years domain.force_delete_start = domain.valid_to - years.years
domain.force_delete_date = domain.force_delete_start + domain.force_delete_date = domain.force_delete_start +

View file

@ -1,38 +1,56 @@
module Domains module Domains
module ForceDeleteEmail module ForceDeleteEmail
# Processes domains with invalid emails by flagging them for force deletion
# when email addresses are identified as invalid or bouncing
class Base < ActiveInteraction::Base class Base < ActiveInteraction::Base
string :email, string :email,
description: 'Bounced email to set ForceDelete from' description: 'Bounced email to set ForceDelete from'
def execute def execute
domain_contacts = Contact.where(email: email).map(&:domain_contacts).flatten # Return early if no affected domains or if any domains are on hold
registrant_ids = Registrant.where(email: email).pluck(:id) affected_domains = find_affected_domains
return if should_skip_processing?(affected_domains)
domains = domain_contacts.map(&:domain).flatten + process_affected_domains(affected_domains)
Domain.where(registrant_id: registrant_ids)
return if expired_or_hold_domains_exists?(domains)
domains.each do |domain|
next if domain.expired?
before_execute_force_delete(domain)
end
end end
private private
def expired_or_hold_domains_exists?(domains) def should_skip_processing?(domains)
domains.empty? || domains_on_hold_exist?(domains)
end
def process_affected_domains(domains)
domains.each do |domain|
next if domain.expired?
process_domain_for_force_delete(domain)
end
end
def find_affected_domains
# Find domains through contacts
contact_domains = Contact.where(email: email).flat_map(&:domain_contacts)
.flat_map(&:domain)
# Find domains through registrants
registrant_domains = Domain.where(registrant_id: Registrant.where(email: email).select(:id))
# Combine and remove duplicates
(contact_domains + registrant_domains).uniq
end
def domains_on_hold_exist?(domains)
domains.any? do |domain| domains.any? do |domain|
domain.statuses.include?(DomainStatus::SERVER_HOLD) && email.include?(domain.name) domain.statuses.include?(DomainStatus::SERVER_HOLD) && email.include?(domain.name)
end end
end end
def before_execute_force_delete(domain) def process_domain_for_force_delete(domain)
if domain.force_delete_scheduled? && !domain.status_notes[DomainStatus::FORCE_DELETE].nil? if domain.force_delete_scheduled? && domain.status_notes[DomainStatus::FORCE_DELETE].present?
added_additional_email_into_notes(domain) add_email_to_notes(domain)
else else
process_force_delete(domain) schedule_force_delete(domain)
end end
end end
@ -43,32 +61,29 @@ module Domains
purge_date: domain.purge_date, purge_date: domain.purge_date,
email: domain.status_notes[DomainStatus::FORCE_DELETE]) email: domain.status_notes[DomainStatus::FORCE_DELETE])
return if domain.registrar.notifications.last.text.include? template return if domain.registrar.notifications.last&.text&.include?(template)
domain.registrar.notifications.create!(text: template) domain.registrar.notifications.create!(text: template)
end end
def process_force_delete(domain) def schedule_force_delete(domain)
domain.schedule_force_delete(type: :soft, domain.schedule_force_delete(
notify_by_email: true, type: :soft,
reason: 'invalid_email', notify_by_email: true,
email: email) reason: 'invalid_email',
save_status_note(domain) email: email
)
end end
def added_additional_email_into_notes(domain) def add_email_to_notes(domain)
return if domain.status_notes[DomainStatus::FORCE_DELETE].include? email return if domain.status_notes[DomainStatus::FORCE_DELETE].include?(email)
# Uncomment if notification is needed
# notify_registrar(domain) # notify_registrar(domain)
domain.status_notes[DomainStatus::FORCE_DELETE].concat(" #{email}") domain.status_notes[DomainStatus::FORCE_DELETE].concat(" #{email}")
domain.save(validate: false) domain.save(validate: false)
end end
def save_status_note(domain)
domain.status_notes[DomainStatus::FORCE_DELETE] = email
domain.save(validate: false)
end
end end
end end
end end

View file

@ -28,8 +28,8 @@ class BaseTest < ActiveSupport::TestCase
prepare_contact prepare_contact
contact = @domain_airport.admin_contacts.first contact = @domain_airport.admin_contacts.first
Domains::ForceDeleteEmail::Base.run(email: contact.email) Domains::ForceDeleteEmail::Base.run(email: contact.email)
@domain_airport.reload @domain_airport.reload
assert @domain_airport.force_delete_scheduled? assert @domain_airport.force_delete_scheduled?