business contact validation + tests

This commit is contained in:
oleghasjanov 2024-09-24 15:04:02 +03:00
parent 4ed6e90893
commit 6ff5e55a24
23 changed files with 962 additions and 2 deletions

View file

@ -6,10 +6,27 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
postgresql-client \ postgresql-client \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
RUN apt-get remove -y google-chrome-stable
RUN apt-get purge -y google-chrome-stable
RUN apt-get autoremove -y && apt-get clean
ENV CHROME_VERSION="128.0.6613.137"
RUN wget -q "https://storage.googleapis.com/chrome-for-testing-public/${CHROME_VERSION}/linux64/chrome-linux64.zip" \
&& unzip chrome-linux64.zip -d /opt/ \
&& rm chrome-linux64.zip
RUN wget -q "https://storage.googleapis.com/chrome-for-testing-public/${CHROME_VERSION}/linux64/chromedriver-linux64.zip" \
&& unzip chromedriver-linux64.zip -d /opt/ \
&& mv /opt/chromedriver-linux64/chromedriver /usr/local/bin/ \
&& rm -rf chromedriver-linux64.zip /opt/chromedriver-linux64
RUN mkdir -p /opt/webapps/app/tmp/pids RUN mkdir -p /opt/webapps/app/tmp/pids
WORKDIR /opt/webapps/app WORKDIR /opt/webapps/app
COPY Gemfile Gemfile.lock ./ COPY Gemfile Gemfile.lock ./
# ADD vendor/gems/omniauth-tara ./vendor/gems/omniauth-tara # ADD vendor/gems/omniauth-tara ./vendor/gems/omniauth-tara
RUN gem install bundler && bundle install --jobs 20 --retry 5 RUN gem install bundler && bundle install --jobs 20 --retry 5
ENV PATH="/opt/chrome-linux64:${PATH}"
EXPOSE 3000 EXPOSE 3000

View file

@ -0,0 +1,17 @@
# Steps to Update company_status.rake
- [x] Modify the CSV output to include the contact type (role) information
- [x] Filter the output to include only Estonian organization type contacts
- [ ] Ensure only registrant contacts are included in the output
- [ ] Remove duplicate entries for the same organization
- [ ] Add a column to indicate if the contact is deleted due to an overdue annual statement
- [ ] Create a separate CSV file for invalid registrant contacts
- [ ] Update the existing CSV output to include only contacts that fail validation against the business registry and whitelist
- [ ] Add error handling and logging for better debugging
- [ ] Update the task description and comments to reflect the new functionality
- [ ] Add a new rake task or option to generate the separate registrant-only CSV file
- [ ] Implement validation against the business registry for Estonian organization contacts
- [ ] Implement validation against the whitelist for Estonian organization contacts
- [ ] Optimize the code for better performance, especially when dealing with large datasets
- [ ] Add unit tests for the new functionality
- [ ] Update the documentation to reflect the changes and new output format

View file

@ -14,6 +14,7 @@ module Actions
maybe_attach_legal_doc maybe_attach_legal_doc
validate_ident validate_ident
maybe_change_email maybe_change_email
maybe_company_is_relevant
commit commit
validate_contact validate_contact
end end
@ -77,6 +78,16 @@ module Actions
@error = true @error = true
end end
def maybe_company_is_relevant
return true unless contact.org?
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'))
@error = true
end
def maybe_attach_legal_doc def maybe_attach_legal_doc
::Actions::BaseAction.attach_legal_doc_to_new(contact, legal_document, domain: false) ::Actions::BaseAction.attach_legal_doc_to_new(contact, legal_document, domain: false)
end end

View file

@ -12,6 +12,8 @@ module Domains
expire_warning_period_days + expire_warning_period_days +
redemption_grace_period_days redemption_grace_period_days
domain.force_delete_start = Time.zone.today + 1.day 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 end
def force_delete_soft def force_delete_soft

View file

@ -0,0 +1,113 @@
require 'zip'
class CompanyRegisterStatusJob < ApplicationJob
PAYMENT_STATEMENT_BUSINESS_REGISTRY_REASON = 'Kustutamiskanne dokumentide hoidjata'
queue_as :default
def perform(days_interval = 14, spam_time_delay = 1, batch_size = 100)
sampling_registrant_contact(days_interval).find_in_batches(batch_size: batch_size) do |contacts|
contacts.reject { |contact| whitelisted_company?(contact) }.each { |contact| proceed_company_status(contact, spam_time_delay) }
end
end
private
def proceed_company_status(contact, spam_time_delay)
# avoid spamming company register
sleep spam_time_delay
company_status = contact.return_company_status
contact.update!(company_register_status: company_status, checked_company_at: Time.zone.now)
puts "company id #{contact.id} status: #{company_status}"
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
else
delete_process(contact)
end
status = company_status.blank? ? Contact::DELETED : company_status
update_validation_company_status(contact:contact , status: status)
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]
)
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)
contact.domains.each do |domain|
next if domain.schedule_force_delete?
domain.schedule_force_delete(
type: :fast_track,
notify_by_email: true,
reason: 'invalid_company',
email: contact.email
)
end
end
def check_for_force_delete(contact)
contact.domains.any? && domain.status_notes[DomainStatus::FORCE_DELETE].include?("Company no: #{contact.ident}") do |domain|
domain.schedule_force_delete?
end
end
def lift_force_delete(contact)
contact.domains.each(&:lift_force_delete)
end
def delete_process(contact)
company_details_response = contact.return_company_details
if company_details_response.empty?
schedule_force_delete(contact)
return
end
kandeliik_tekstina = extract_kandeliik_tekstina(company_details_response)
if kandeliik_tekstina == PAYMENT_STATEMENT_BUSINESS_REGISTRY_REASON
soft_delete_company(contact)
else
schedule_force_delete(contact)
end
end
private
def extract_kandeliik_tekstina(company_details_response)
company_details_response.first.kandeliik.last.last.kandeliik_tekstina
end
def soft_delete_company(contact)
contact.domains.reject { |domain| domain.force_delete_scheduled? }.each do |domain|
domain.schedule_force_delete(type: :soft)
end
puts "Soft delete process initiated for company: #{contact.name} with ID: #{contact.id}"
end
def whitelisted_companies
@whitelisted_companies ||= ENV['whitelist_companies'].split(',')
end
def whitelisted_company?(contact)
whitelisted_companies.include?(contact.ident)
end
end

View file

@ -19,6 +19,13 @@ class ContactInformMailer < ApplicationMailer
mail(to: contact.email, subject: subject) mail(to: contact.email, subject: subject)
end end
def company_liquidation(contact:)
@registrant = contact
subject = "Kas soovite oma .ee domeeni säilitada? / Do you wish to preserve your .ee registration?"
mail(to: contact.email, subject: subject)
end
private private
def address_processing def address_processing

View file

@ -32,7 +32,7 @@ module Domain::ForceDelete
def notification_template(explicit: nil) def notification_template(explicit: nil)
reason = explicit&.downcase reason = explicit&.downcase
return reason if %w[invalid_email invalid_phone].include?(reason) return reason if %w[invalid_email invalid_phone invalid_company].include?(reason)
if contact_emails_verification_failed.present? if contact_emails_verification_failed.present?
'invalid_email' 'invalid_email'

View file

@ -8,6 +8,7 @@ class Contact < ApplicationRecord
include Contact::Transferable include Contact::Transferable
include Contact::Identical include Contact::Identical
include Contact::Archivable include Contact::Archivable
include Contact::CompanyRegister
include EmailVerifable include EmailVerifable
belongs_to :original, class_name: 'Contact' belongs_to :original, class_name: 'Contact'

View file

@ -0,0 +1,38 @@
module Contact::CompanyRegister
extend ActiveSupport::Concern
REGISTERED = 'R'.freeze
LIQUIDATED = 'L'.freeze
BANKRUPT = 'N'.freeze
DELETED = 'K'.freeze
def company_is_relevant?
company_register_status == REGISTERED && company_register_status == LIQUIDATED
end
def return_company_status
return if return_company_data.blank?
return_company_data.first[:status]
end
def return_company_data
return unless org?
company_register.simple_data(registration_number: ident)
rescue CompanyRegister::NotAvailableError
[]
end
def return_company_details
return unless org?
company_register.company_details(registration_number: ident)
rescue CompanyRegister::NotAvailableError
[]
end
def company_register
@company_register ||= CompanyRegister::Client.new
end
end

View file

@ -0,0 +1,34 @@
<p>Lugupeetud ettevõtte <%= @registrant.name %> esindaja,</p>
<p>Eesti Interneti Sihtasutusele (EIS) on äriregistri vahendusel teatavaks saanud, et ettevõtte <%= @registrant.name %> äriregistrikoodiga <%= @registrant.ident %> suhtes käib likvideerimismenetlus. Tuletame teile meelde, et tulenevalt .ee domeenireeglitest peab domeeni registreerijaks olema eksisteeriv era- või juriidiline isik. Seega käivitame ettevõtte likvideerimise järel sellele kuuluvate registreeringute kustutusmenetluse. Kustutusmenetluse tulemusena eemaldatakse .ee domeeninimi registrist ning vabaneb kõigile soovijatele taaskord registreerimiseks.</p>
<p>Kui soovite ettevõttele kuuluvaid registreeritud domeene ka edaspidi kasutada, soovitame teil ette valmistada registreeringute üleandmine uuele omanikule enne praeguse omaniku likvideerimist. Lähemalt leiate selle kohta infot meie kodulehelt.</p>
<p>.ee domeeni registris kuuluvad ettevõttele <%= @registrant.ident %> järgmised registreeringud:</p>
<ul>
<% @registrant.domains.each do |domain| %>
<li><%= domain.name %></li>
<% end %>
</ul>
<p>Lisaküsimuste korral võtke palun ühendust oma registripidajaga:</p>
<%= render 'mailers/shared/registrar/registrar.et.html', registrar: @registrant.registrar %>
<%= render 'mailers/shared/signatures/signature.et.html' %>
<hr>
<p>Dear representative of <%= @registrant.name %>,</p>
<p>The Estonian Internet Foundation (EIS) has found through the Estonian business register that the company <%= @registrant.name %> with the business registry code <%= @registrant.ident %> is in liquidation proceedings. Please note that according to the .ee domain regulation, the registrant of the domain must be an existing private or legal entity. Therefore, the registry will start the registration deletion procedure once the liquidation of the company has been finalized. After the registration deletion procedure, the domain name will be open to register again for everyone.</p>
<p>If you want to continue to use the registered domains belonging to your company, we recommend you to prepare the transfer of the registrations to the new owner before the liquidation of the current owner will be finalized. Learn more on our website.</p>
<p>The following registrations belong to the company <%= @registrant.ident %> in the .ee domain register:</p>
<ul>
<% @registrant.domains.each do |domain| %>
<li><%= domain.name %></li>
<% end %>
</ul>
<p>Should you have additional questions, please contact your registrar:</p>
<%= render 'mailers/shared/registrar/registrar.en.html', registrar: @registrant.registrar %>
<%= render 'mailers/shared/signatures/signature.en.html' %>
<hr>

View file

@ -0,0 +1,32 @@
Lugupeetud ettevõtte <%= @registrant.name %> esindaja
Eesti Interneti Sihtasutusele (EIS) on äriregistri vahendusel teatavaks saanud, et ettevõtte <%= @registrant.name %> äriregistrikoodiga <%= @registrant.ident %> suhtes käib likvideerimismenetlus. Tuletame teile meelde, et tulenevalt .ee domeenireeglitest peab domeeni registreerijaks olema eksisteeriv era- või juriidiline isik. Seega käivitame ettevõtte likvideerimise järel sellele kuuluvate registreeringute kustutusmenetluse. Kustutusmenetluse tulemusena eemaldatakse .ee domeeninimi registrist ning vabaneb kõigile soovijatele taaskord registreerimiseks.
Kui soovite ettevõttele kuuluvaid registreeritud domeene ka edaspidi kasutada, soovitame teil ette valmistada registreeringute üleandmine uuele omanikule enne praeguse omaniku likvideerimist. Lähemalt leiate selle kohta infot meie kodulehelt.
.ee domeeni registris kuuluvad ettevõttele <%= @registrant.ident %> järgmised registreeringud:
<% @registrant.domains.each do |domain| %>
<%= domain.name %>
<% end %>
Lisaküsimuste korral võtke palun ühendust oma registripidajaga:
<%= render 'mailers/shared/registrar/registrar.et.html', registrar: @registrant.registrar %>
<%= render 'mailers/shared/signatures/signature.et.html' %>
---
Dear representative of <%= @registrant.name %>,
The Estonian Internet Foundation (EIS) has found through the Estonian business register that the company <%= @registrant.name %> with the business registry code <%= @registrant.ident %> is in liquidation proceedings. Please note that according to the .ee domain regulation, the registrant of the domain must be an existing private or legal entity. Therefore, the registry will start the registration deletion procedure once the liquidation of the company has been finalized. After the registration deletion procedure, the domain name will be open to register again for everyone.
If you want to continue to use the registered domains belonging to your company, we recommend you to prepare the transfer of the registrations to the new owner before the liquidation of the current owner will be finalized. Learn more on our website.
The following registrations belong to the company <%= @registrant.ident %> in the .ee domain register:
<% @registrant.domains.each do |domain| %>
<%= domain.name %>
<% end %>
Should you have additional questions, please contact your registrar:
<%= render 'mailers/shared/registrar/registrar.en.html', registrar: @registrant.registrar %>
<%= render 'mailers/shared/signatures/signature.en.html' %>

View file

@ -0,0 +1,45 @@
<p>Lugupeetud domeeni <%= @domain.name %> registreerija/halduskontakt</p>
<p>Eesti Interneti Sihtasutusele on saanud teatavaks, et juriidiline isik registrikoodiga <%= @domain.registrant.ident %> on äriregistrist kustutatud.</p>
<p>Kuna äriregistrist kustutatud juriidiline isik ei saa olla domeeni registreerijaks, algas domeeni <%= @domain.name %> suhtes 45 päevane kustutusmenetlus. Menetluse käigus on domeen 15 esimest päeva internetis kättesaadav.</p>
<p>Domeeni suhtes õigust omaval isikul on võimalus esitada domeeni <%= @domain.name %> registripidajale <%= @registrar.name %> domeeni üleandmise taotlus koos seda tõendava dokumendiga.</p>
<p>Kui kontaktandmed ei ole <%= @delete_period_length %> päeva jooksul parandatud, läheb domeen <%= @domain.name %> <%= @domain.force_delete_date %> domeenioksjonile <a href="https://auction.internet.ee">.ee oksjonikeskkonda</a>. Juhul kui domeenile <%= @domain.name %> ei tehta oksjonil 24h möödudes pakkumist, domeen vabaneb ja on registreerimiseks vabalt kättesaadav kõigile huvilistele. Muude võimalike oksjoni tulemuste kohta loe <a href="https://www.internet.ee/domeenid/domeenide-oksjonikeskkonna-kasutajatingimused#3-oksjonikeskkonna-enampakkumisel-osalemise-tingimused">siit</a>.</p>
<p>Lisaküsimuste korral võtke palun ühendust oma registripidajaga:</p>
<%= render 'mailers/shared/registrar/registrar.et.html', registrar: @registrar %>
<%= render 'mailers/shared/signatures/signature.et.html' %>
<hr>
<p>Dear registrant/administrative contact of .ee domain,</p>
<p>Estonian Internet Foundation has learned that the legal person with registry code <%= @domain.registrant.ident %> has been deleted from the Business Registry.</p>
<p>As a terminated legal person cannot be the registrant of a domain, a 45-day deletion process has started for the <%= @domain.name %> domain. For the first 15 days the domain will remain available on the Internet during the deletion process.</p>
<p>The registrant holding a right to the domain name <%= @domain.name %> can submit a domain name transfer application to the registrar <%= @registrar.name %> with legal documentation.</p>
<p>If the data is not fixed within <%= @delete_period_length %> days, the domain <%= @domain.name %> will go to domain auction on <%= @domain.force_delete_date %> in the <a href="https://auction.internet.ee">.ee auction environment</a>. If no offer is made for the domain <%= @domain.name %> at auction within 24 hours, the domain will be released and made freely available for registration to anyone interested on a first-come, first-served basis. Read more about other potential auction results <a href="https://www.internet.ee/domains/auction-environment-user-agreement#3-terms-and-conditions-for-participation-in-the-auction-of-the-auction-environment">here</a>.</p>
<p>Should you have additional questions, please contact your registrar:</p>
<%= render 'mailers/shared/registrar/registrar.en.html', registrar: @registrar %>
<%= render 'mailers/shared/signatures/signature.en.html' %>
<hr>
<p>Уважаемый регистрант/административный контакт домена .ee</p>
<p>Целевому учреждению Eesti Internet (EIS) стало известно, что юридическое лицо с регистрационным кодом <%= @domain.registrant.ident %> удалено из коммерческого реестра.</p>
<p>Поскольку удаленное из коммерческого регистра юридическое лицо не может являться регистрантом домена, <%= Date.today.strftime('%d.%m.%y') %> начат 45-дневный процесс удаления домена <%= @domain.name %>. Домен доступен в интернете на протяжении 15 дней после начала процесса удаления.</p>
<p>Лицо, обладающее правом на домен, может подать регистратору <%= @registrar.name %> домена <%= @domain.name %> ходатайство о передаче домена, представив вместе с ходатайством подтверждающие документы. Документы должны быть представлены регистратору в течение 45 дней.</p>
<p>Если контактные данные не будут исправлены в течение <%= @delete_period_length %> дней, домен <%= @domain.name %> отправится <%= @domain.force_delete_date %> на доменный аукцион в <a href="https://auction.internet.ee">аукционной среде.ee</a>. Если в течение 24 часов в отношении домена <%= @domain.name %> е поступит предложений, домен освободится и станет доступным для всех желающих по принципу «кто раньше». О других возможных результатах аукциона читайте <a href="https://www.internet.ee/domains/auction-environment-user-agreement#3-terms-and-conditions-for-participation-in-the-auction-of-the-auction-environment">здесь</a>.</p>
<p>В случае возникновения дополнительных вопросов свяжитесь, пожалуйста, со своим регистратором:
<%= render 'mailers/shared/registrar/registrar.ru.html', registrar: @registrar %></p>
<%= render 'mailers/shared/signatures/signature.ru.html' %>

View file

@ -0,0 +1,46 @@
<p>Lugupeetud domeeni <%= @domain.name %> registreerija/halduskontakt</p>
<p>Eesti Interneti Sihtasutusele on saanud teatavaks, et juriidiline isik registrikoodiga <%= @domain.registrant.ident %> on äriregistrist kustutatud.</p>
<p>Kuna äriregistrist kustutatud juriidiline isik ei saa olla domeeni registreerijaks, algas domeeni <%= @domain.name %> suhtes 45 päevane kustutusmenetlus. Menetluse käigus on domeen 15 esimest päeva internetis kättesaadav.</p>
<p>Domeeni suhtes õigust omaval isikul on võimalus esitada domeeni <%= @domain.name %> registripidajale <%= @registrar.name %> domeeni üleandmise taotlus koos seda tõendava dokumendiga.</p>
<p>Kui kontaktandmed ei ole <%= @delete_period_length %> päeva jooksul parandatud, läheb domeen <%= @domain.name %> <%= @domain.force_delete_date %> domeenioksjonile <a href="https://auction.internet.ee">.ee oksjonikeskkonda</a>. Juhul kui domeenile <%= @domain.name %> ei tehta oksjonil 24h möödudes pakkumist, domeen vabaneb ja on registreerimiseks vabalt kättesaadav kõigile huvilistele. Muude võimalike oksjoni tulemuste kohta loe <a href="https://www.internet.ee/domeenid/domeenide-oksjonikeskkonna-kasutajatingimused#3-oksjonikeskkonna-enampakkumisel-osalemise-tingimused">siit</a>.</p>
<p>Lisaküsimuste korral võtke palun ühendust oma registripidajaga:</p>
<%= render 'mailers/shared/registrar/registrar.et.html', registrar: @registrar %>
<%= render 'mailers/shared/signatures/signature.et.html' %>
<hr>
<p>Dear registrant/administrative contact of .ee domain,</p>
<p>Estonian Internet Foundation has learned that contact(s) phone number data of the domain <%= @domain.name %> are invalid.</p>
<p>Estonian Internet Foundation has learned that the legal person with registry code <%= @domain.registrant.ident %> has been deleted from the Business Registry.</p>
<p>As a terminated legal person cannot be the registrant of a domain, a 45-day deletion process has started for the <%= @domain.name %> domain. For the first 15 days the domain will remain available on the Internet during the deletion process.</p>
<p>The registrant holding a right to the domain name <%= @domain.name %> can submit a domain name transfer application to the registrar <%= @registrar.name %> with legal documentation.</p>
<p>If the data is not fixed within <%= @delete_period_length %> days, the domain <%= @domain.name %> will go to domain auction on <%= @domain.force_delete_date %> in the <a href="https://auction.internet.ee">.ee auction environment</a>. If no offer is made for the domain <%= @domain.name %> at auction within 24 hours, the domain will be released and made freely available for registration to anyone interested on a first-come, first-served basis. Read more about other potential auction results <a href="https://www.internet.ee/domains/auction-environment-user-agreement#3-terms-and-conditions-for-participation-in-the-auction-of-the-auction-environment">here</a>.</p>
<p>Should you have additional questions, please contact your registrar:</p>
<%= render 'mailers/shared/registrar/registrar.en.html', registrar: @registrar %>
<%= render 'mailers/shared/signatures/signature.en.html' %>
<hr>
<p>Уважаемый регистрант/административный контакт домена .ee</p>
<p>Целевому учреждению Eesti Internet (EIS) стало известно, что юридическое лицо с регистрационным кодом <%= @domain.registrant.ident %> удалено из коммерческого реестра.</p>
<p>Поскольку удаленное из коммерческого регистра юридическое лицо не может являться регистрантом домена, <%= Date.today.strftime('%d.%m.%y') %> начат 45-дневный процесс удаления домена <%= @domain.name %>. Домен доступен в интернете на протяжении 15 дней после начала процесса удаления.</p>
<p>Лицо, обладающее правом на домен, может подать регистратору <%= @registrar.name %> домена <%= @domain.name %> ходатайство о передаче домена, представив вместе с ходатайством подтверждающие документы. Документы должны быть представлены регистратору в течение 45 дней.</p>
<p>Если контактные данные не будут исправлены в течение <%= @delete_period_length %> дней, домен <%= @domain.name %> отправится <%= @domain.force_delete_date %> на доменный аукцион в <a href="https://auction.internet.ee">аукционной среде.ee</a>. Если в течение 24 часов в отношении домена <%= @domain.name %> е поступит предложений, домен освободится и станет доступным для всех желающих по принципу «кто раньше». О других возможных результатах аукциона читайте <a href="https://www.internet.ee/domains/auction-environment-user-agreement#3-terms-and-conditions-for-participation-in-the-auction-of-the-auction-environment">здесь</a>.</p>
<p>В случае возникновения дополнительных вопросов свяжитесь, пожалуйста, со своим регистратором:
<%= render 'mailers/shared/registrar/registrar.ru.html', registrar: @registrar %></p>
<%= render 'mailers/shared/signatures/signature.ru.html' %>

View file

@ -252,3 +252,7 @@ billing_system_integrated: 'true'
secret_access_word: 'please-Give-Me-accesS' secret_access_word: 'please-Give-Me-accesS'
secret_word: 'this-secret-should-be-change' secret_word: 'this-secret-should-be-change'
allow_accr_endspoints: 'true' allow_accr_endspoints: 'true'
whitelist_companies:
- '12345678'
- '87654321'

View file

@ -202,6 +202,7 @@ en:
invalid_cert: 'Invalid certificate' invalid_cert: 'Invalid certificate'
failed_epp_conn: 'Failed to open connection to EPP server!' failed_epp_conn: 'Failed to open connection to EPP server!'
epp_conn_error: 'CONNECTION ERROR - Is the EPP server running?' epp_conn_error: 'CONNECTION ERROR - Is the EPP server running?'
company_not_registered: 'Company is not registered'
code: 'Code' code: 'Code'
action: 'Action' action: 'Action'

View file

@ -0,0 +1,5 @@
class AddCheckedCompanyAtToContacts < ActiveRecord::Migration[6.1]
def change
add_column :contacts, :checked_company_at, :datetime
end
end

View file

@ -0,0 +1,5 @@
class AddCompanyRegisterStatusToContacts < ActiveRecord::Migration[6.1]
def change
add_column :contacts, :company_register_status, :string
end
end

View file

@ -692,7 +692,9 @@ CREATE TABLE public.contacts (
uuid uuid DEFAULT public.gen_random_uuid() NOT NULL, uuid uuid DEFAULT public.gen_random_uuid() NOT NULL,
disclosed_attributes character varying[] DEFAULT '{}'::character varying[] NOT NULL, disclosed_attributes character varying[] DEFAULT '{}'::character varying[] NOT NULL,
email_history character varying, email_history character varying,
registrant_publishable boolean DEFAULT false registrant_publishable boolean DEFAULT false,
checked_company_at timestamp without time zone,
company_register_status character varying
); );
@ -1099,6 +1101,45 @@ CREATE SEQUENCE public.email_addresses_verifications_id_seq
ALTER SEQUENCE public.email_addresses_verifications_id_seq OWNED BY public.email_addresses_verifications.id; ALTER SEQUENCE public.email_addresses_verifications_id_seq OWNED BY public.email_addresses_verifications.id;
--
-- Name: epp_logs; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public.epp_logs (
id bigint NOT NULL,
request text,
response text,
request_command character varying(255),
request_object character varying,
request_successful boolean,
api_user_name character varying(255),
api_user_registrar character varying(255),
ip character varying(255),
created_at timestamp without time zone,
updated_at timestamp without time zone,
uuid character varying
);
--
-- Name: epp_logs_id_seq; Type: SEQUENCE; Schema: public; Owner: -
--
CREATE SEQUENCE public.epp_logs_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
--
-- Name: epp_logs_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
--
ALTER SEQUENCE public.epp_logs_id_seq OWNED BY public.epp_logs.id;
-- --
-- Name: epp_sessions; Type: TABLE; Schema: public; Owner: - -- Name: epp_sessions; Type: TABLE; Schema: public; Owner: -
-- --
@ -2553,6 +2594,45 @@ CREATE SEQUENCE public.registrars_id_seq
ALTER SEQUENCE public.registrars_id_seq OWNED BY public.registrars.id; ALTER SEQUENCE public.registrars_id_seq OWNED BY public.registrars.id;
--
-- Name: repp_logs; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public.repp_logs (
id bigint NOT NULL,
request_path character varying(255),
request_method character varying(255),
request_params text,
response text,
response_code character varying(255),
api_user_name character varying(255),
api_user_registrar character varying(255),
ip character varying(255),
created_at timestamp without time zone,
updated_at timestamp without time zone,
uuid character varying
);
--
-- Name: repp_logs_id_seq; Type: SEQUENCE; Schema: public; Owner: -
--
CREATE SEQUENCE public.repp_logs_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
--
-- Name: repp_logs_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
--
ALTER SEQUENCE public.repp_logs_id_seq OWNED BY public.repp_logs.id;
-- --
-- Name: reserved_domains; Type: TABLE; Schema: public; Owner: - -- Name: reserved_domains; Type: TABLE; Schema: public; Owner: -
-- --
@ -3061,6 +3141,13 @@ ALTER TABLE ONLY public.email_addresses_validations ALTER COLUMN id SET DEFAULT
ALTER TABLE ONLY public.email_addresses_verifications ALTER COLUMN id SET DEFAULT nextval('public.email_addresses_verifications_id_seq'::regclass); ALTER TABLE ONLY public.email_addresses_verifications ALTER COLUMN id SET DEFAULT nextval('public.email_addresses_verifications_id_seq'::regclass);
--
-- Name: epp_logs id; Type: DEFAULT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.epp_logs ALTER COLUMN id SET DEFAULT nextval('public.epp_logs_id_seq'::regclass);
-- --
-- Name: epp_sessions id; Type: DEFAULT; Schema: public; Owner: - -- Name: epp_sessions id; Type: DEFAULT; Schema: public; Owner: -
-- --
@ -3320,6 +3407,13 @@ ALTER TABLE ONLY public.registrant_verifications ALTER COLUMN id SET DEFAULT nex
ALTER TABLE ONLY public.registrars ALTER COLUMN id SET DEFAULT nextval('public.registrars_id_seq'::regclass); ALTER TABLE ONLY public.registrars ALTER COLUMN id SET DEFAULT nextval('public.registrars_id_seq'::regclass);
--
-- Name: repp_logs id; Type: DEFAULT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.repp_logs ALTER COLUMN id SET DEFAULT nextval('public.repp_logs_id_seq'::regclass);
-- --
-- Name: reserved_domains id; Type: DEFAULT; Schema: public; Owner: - -- Name: reserved_domains id; Type: DEFAULT; Schema: public; Owner: -
-- --
@ -3567,6 +3661,14 @@ ALTER TABLE ONLY public.email_addresses_verifications
ADD CONSTRAINT email_addresses_verifications_pkey PRIMARY KEY (id); ADD CONSTRAINT email_addresses_verifications_pkey PRIMARY KEY (id);
--
-- Name: epp_logs epp_logs_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.epp_logs
ADD CONSTRAINT epp_logs_pkey PRIMARY KEY (id);
-- --
-- Name: epp_sessions epp_sessions_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- Name: epp_sessions epp_sessions_pkey; Type: CONSTRAINT; Schema: public; Owner: -
-- --
@ -3863,6 +3965,14 @@ ALTER TABLE ONLY public.registrars
ADD CONSTRAINT registrars_pkey PRIMARY KEY (id); ADD CONSTRAINT registrars_pkey PRIMARY KEY (id);
--
-- Name: repp_logs repp_logs_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.repp_logs
ADD CONSTRAINT repp_logs_pkey PRIMARY KEY (id);
-- --
-- Name: reserved_domains reserved_domains_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- Name: reserved_domains reserved_domains_pkey; Type: CONSTRAINT; Schema: public; Owner: -
-- --
@ -4055,6 +4165,13 @@ ALTER TABLE ONLY public.zones
ADD CONSTRAINT zones_pkey PRIMARY KEY (id); ADD CONSTRAINT zones_pkey PRIMARY KEY (id);
--
-- Name: epp_logs_uuid; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX epp_logs_uuid ON public.epp_logs USING btree (uuid);
-- --
-- Name: index_account_activities_on_account_id; Type: INDEX; Schema: public; Owner: - -- Name: index_account_activities_on_account_id; Type: INDEX; Schema: public; Owner: -
-- --
@ -4755,6 +4872,13 @@ CREATE INDEX log_domains_object_legacy_id ON public.log_contacts USING btree (((
CREATE INDEX log_nameservers_object_legacy_id ON public.log_contacts USING btree ((((object ->> 'legacy_domain_id'::text))::integer)); CREATE INDEX log_nameservers_object_legacy_id ON public.log_contacts USING btree ((((object ->> 'legacy_domain_id'::text))::integer));
--
-- Name: repp_logs_uuid; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX repp_logs_uuid ON public.repp_logs USING btree (uuid);
-- --
-- Name: unique_data_migrations; Type: INDEX; Schema: public; Owner: - -- Name: unique_data_migrations; Type: INDEX; Schema: public; Owner: -
-- --
@ -4992,6 +5116,7 @@ ALTER TABLE ONLY public.users
SET search_path TO "$user", public; SET search_path TO "$user", public;
INSERT INTO "schema_migrations" (version) VALUES INSERT INTO "schema_migrations" (version) VALUES
('0'),
('20140616073945'), ('20140616073945'),
('20140620130107'), ('20140620130107'),
('20140627082711'), ('20140627082711'),
@ -5470,7 +5595,12 @@ INSERT INTO "schema_migrations" (version) VALUES
('20221214073933'), ('20221214073933'),
('20221214074252'), ('20221214074252'),
('20230531111154'), ('20230531111154'),
('20230612094319'),
('20230612094326'),
('20230612094335'),
('20230707084741'), ('20230707084741'),
('20230710120154'),
('20230711083811'),
('20240816091049'), ('20240816091049'),
('20240816092636'); ('20240816092636');

Binary file not shown.

View file

@ -0,0 +1,209 @@
require 'csv'
require 'open-uri'
require 'zip'
require 'net/http'
require 'uri'
require 'optparse'
require 'rake_option_parser_boilerplate'
namespace :company_status do
# bundle exec rake company_status:check_all -- --open_data_file_path=tmp/ettevotja_rekvisiidid__lihtandmed.csv --missing_companies_output_path=tmp/missing_companies_in_business_registry.csv --deleted_companies_output_path=tmp/deleted_companies_from_business_registry.csv --download_path=https://avaandmed.ariregister.rik.ee/sites/default/files/avaandmed/ettevotja_rekvisiidid__lihtandmed.csv.zip --soft_delete_enable=false --registrants_only=true
desc 'Get Estonian companies status from Business Registry.'
DELETED_FROM_REGISTRY_STATUS = 'K'
DESTINATION = Rails.root.join('tmp').to_s + '/'
COMPANY_STATUS = 'ettevotja_staatus'
BUSINESS_REGISTRY_CODE = 'ariregistri_kood'
task :check_all => :environment do
options = initialize_rake_task
open_data_file_path = options[:open_data_file_path]
missing_companies_in_business_registry_path = options[:missing_companies_output_path]
deleted_companies_from_business_registry_path = options[:deleted_companies_output_path]
download_path = options[:download_path]
soft_delete_enable = options[:soft_delete_enable]
downloaded_filename = File.basename(URI(download_path).path)
are_registrants_only = options[:registrants_only]
puts "*** Run 1 step. Downloading fresh open data file. ***"
remove_old_file(DESTINATION + downloaded_filename)
download_open_data_file(download_path, downloaded_filename)
unzip_file(downloaded_filename, DESTINATION)
puts "*** Run 2 step. I am collecting data from open business registry sources. ***"
company_data = collect_company_data(open_data_file_path)
puts "*** Run 3 step. I process companies, update their information, and sort them into different files based on whether the companies are missing or removed from the business registry ***"
whitelisted_companies = JSON.parse(ENV['whitelist_companies']) # ["12345678", "87654321"]
contacts_query = Contact.where(ident_type: 'org', ident_country_code: 'EE')
if are_registrants_only
contacts_query = contacts_query.joins(:registrant_domains).distinct
end
unique_contacts = contacts_query.to_a.uniq(&:ident)
unique_contacts.each do |contact|
next if whitelisted_companies.include?(contact.ident)
if company_data.key?(contact.ident)
update_company_status(contact: contact, status: company_data[contact.ident][COMPANY_STATUS])
puts "Company: #{contact.name} with ident: #{contact.ident} and ID: #{contact.id} has status: #{company_data[contact.ident][COMPANY_STATUS]}"
else
update_company_status(contact: contact, status: 'K')
sort_companies_to_files(
contact: contact,
missing_companies_in_business_registry_path: missing_companies_in_business_registry_path,
deleted_companies_from_business_registry_path: deleted_companies_from_business_registry_path,
soft_delete_enable: soft_delete_enable
)
end
end
puts '*** Done ***'
end
private
def initialize_rake_task
open_data_file_path = "#{DESTINATION}ettevotja_rekvisiidid__lihtandmed.csv"
missing_companies_in_business_registry_path = "#{DESTINATION}missing_companies_in_business_registry.csv"
deleted_companies_from_business_registry_path = "#{DESTINATION}deleted_companies_from_business_registry.csv"
url = 'https://avaandmed.ariregister.rik.ee/sites/default/files/avaandmed/ettevotja_rekvisiidid__lihtandmed.csv.zip'
options = {
open_data_file_path: open_data_file_path,
missing_companies_output_path: missing_companies_in_business_registry_path,
deleted_companies_output_path: deleted_companies_from_business_registry_path,
download_path: url,
soft_delete_enable: false,
registrants_only: false,
}
banner = 'Usage: rake companies:check_all -- [options]'
RakeOptionParserBoilerplate.process_args(options: options,
banner: banner,
hash: companies_opts_hash)
end
def companies_opts_hash
{
open_data_file_path: ['-o [OPEN_DATA_FILE_PATH]', '--open_data_file_path [DOMAIN_NAME]', String],
missing_companies_output_path: ['-m [MISSING_COMPANIES_OUTPUT_PATH]', '--missing_companies_output_path [MISSING_COMPANIES_OUTPUT_PATH]', String],
deleted_companies_output_path: ['-s [DELETED_COMPANIES_OUTPUT_PATH]', '--deleted_companies_output_path [DELETED_COMPANIES_OUTPUT_PATH]', String],
download_path: ['-d [DOWNLOAD_PATH]', '--download_path [DOWNLOAD_PATH]', String],
soft_delete_enable: ['-e [SOFT_DELETE_ENABLE]', '--soft_delete_enable [SOFT_DELETE_ENABLE]', FalseClass],
registrants_only: ['-r', '--registrants_only [REGISTRANTS_ONLY]', FalseClass],
}
end
def remove_old_file(output_file_path)
FileUtils.rm(output_file_path) if File.exist?(output_file_path)
end
def unzip_file(filename, destination)
Zip::File.open(filename) do |zip_file|
zip_file.each do |entry|
entry.extract(File.join(destination, entry.name)) { true }
end
end
puts "Archive invoke to #{destination}"
end
def collect_company_data(open_data_file_path)
company_data = {}
CSV.foreach(open_data_file_path, headers: true, col_sep: ';', quote_char: '"', liberal_parsing: true) do |row|
company_data[row[BUSINESS_REGISTRY_CODE]] = row
end
company_data
end
def download_open_data_file(url, filename)
uri = URI(url)
Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
request = Net::HTTP::Get.new(uri)
response = http.request(request)
if response.code == '200'
File.open(filename, 'wb') do |file|
file.write(response.body)
end
else
puts "Failed to download file: #{response.code} #{response.message}"
end
end
puts "File saved as #{filename}"
end
def update_company_status(contact:, status:)
contact.update(company_register_status: status, checked_company_at: Time.zone.now)
end
def put_company_to_missing_file(contact:, path:)
write_to_csv_file(csv_file_path: path, headers: ["ID", "Ident", "Name", "Contact Type"], attrs: [contact.id, contact.ident, contact.name, determine_contact_type(contact)])
end
def sort_companies_to_files(contact:, missing_companies_in_business_registry_path:, deleted_companies_from_business_registry_path:, soft_delete_enable:)
sleep 1
resp = contact.return_company_details
if resp.empty?
put_company_to_missing_file(contact: contact, path: missing_companies_in_business_registry_path)
puts "Company: #{contact.name} with ident: #{contact.ident} and ID: #{contact.id} is missing in registry, company id: #{contact.id}"
soft_delete_company(contact) if soft_delete_enable
else
status = resp.first.status.upcase
kandeliik_type = resp.first.kandeliik.last.last.kandeliik
kandeliik_tekstina = resp.first.kandeliik.last.last.kandeliik_tekstina
kande_kpv = resp.first.kandeliik.last.last.kande_kpv
if status == DELETED_FROM_REGISTRY_STATUS
csv_file_path = deleted_companies_from_business_registry_path
headers = ["ID", "Ident", "Name", "Status", "Kandeliik Type", "Kandeliik Tekstina", "kande_kpv", "Contact Type"]
attrs = [contact.id, contact.ident, contact.name, status, kandeliik_type, kandeliik_tekstina, kande_kpv, determine_contact_type(contact)]
write_to_csv_file(csv_file_path: csv_file_path, headers: headers, attrs: attrs)
puts "Company: #{contact.name} with ident: #{contact.ident} and ID: #{contact.id} has status #{status}, company id: #{contact.id}"
soft_delete_company(contact) if soft_delete_enable
end
end
end
def determine_contact_type(contact)
roles = []
roles << 'Registrant' if contact.registrant_domains.any?
roles += contact.domain_contacts.pluck(:type).uniq if contact.domain_contacts.any?
roles << 'Unknown' if roles.empty?
roles.join(', ')
end
def soft_delete_company(contact)
contact.domains.reject { |domain| domain.force_delete_scheduled? }.each do |domain|
domain.schedule_force_delete(type: :soft)
end
puts "Soft delete process initiated for company: #{contact.name} with ID: #{contact.id}"
end
def write_to_csv_file(csv_file_path:, headers:, attrs:)
write_headers = !File.exist?(csv_file_path)
begin
CSV.open(csv_file_path, "ab", write_headers: write_headers, headers: headers) do |csv|
csv << attrs
end
puts "Successfully wrote to CSV: #{csv_file_path}"
rescue => e
puts "Error writing to CSV: #{e.message}"
end
end
end

View file

@ -0,0 +1,239 @@
require 'test_helper'
require 'webmock/minitest'
require 'tempfile'
require 'csv'
require 'zip'
module CompanyStatusTaskTestOverrides
def download_open_data_file(url, filename)
uri = URI(url)
Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
request = Net::HTTP::Get.new(uri)
response = http.request(request)
if response.code == '200'
File.open(filename, 'wb') do |file|
file.write(response.body)
end
else
puts "Failed to download file: #{response.code} #{response.message}"
end
end
puts "File saved as #{filename}"
end
def unzip_file(filename, destination)
Zip::File.open(filename) do |zip_file|
zip_file.each do |entry|
entry_path = File.join(destination, entry.name)
entry.extract(entry_path) { true } # Overwrite existing files
end
end
true
end
def collect_company_data(open_data_file_path)
$test_options = open_data_file_path
# Return test data
{ '12345678' => { 'ettevotja_staatus' => 'active' } }
end
def update_company_status(contact:, status:)
# Do nothing
end
def sort_companies_to_files(contact:, missing_companies_in_business_registry_path:, deleted_companies_from_business_registry_path:, soft_delete_enable:)
# Do nothing
end
def initialize_rake_task
options = {
open_data_file_path: "#{DESTINATION}ettevotja_rekvisiidid__lihtandmed.csv",
missing_companies_output_path: "#{DESTINATION}missing_companies_in_business_registry.csv",
deleted_companies_output_path: "#{DESTINATION}deleted_companies_from_business_registry.csv",
download_path: 'https://avaandmed.ariregister.rik.ee/sites/default/files/avaandmed/ettevotja_rekvisiidid__lihtandmed.csv.zip',
soft_delete_enable: false,
registrants_only: false,
}
# Process command line arguments
RakeOptionParserBoilerplate.process_args(
options: options,
banner: 'Usage: rake company_status:check_all [options]',
hash: {
open_data_file_path: ['-o', '--open_data_file_path PATH', String],
missing_companies_output_path: ['-m', '--missing_companies_output_path PATH', String],
deleted_companies_output_path: ['-d', '--deleted_companies_output_path PATH', String],
download_path: ['-u', '--download_path URL', String],
soft_delete_enable: ['-s', '--soft_delete_enable', :NONE],
registrants_only: ['-r', '--registrants_only', :NONE]
}
)
options
end
end
class CompanyStatusTaskTest < ActiveSupport::TestCase
include CompanyStatusTaskTestOverrides
def setup
super # Always call super when overriding setup
# Create temporary CSV file with test data
@temp_csv = Tempfile.new(['test_data', '.csv'])
CSV.open(@temp_csv.path, 'wb') do |csv|
csv << ['ariregistri_kood', 'ettevotja_staatus']
csv << ['12345678', 'active']
end
@temp_csv_path = @temp_csv.path
$temp_csv_path = @temp_csv.path # Set the global variable
# Create temporary zip file containing our CSV
@temp_zip = Tempfile.new(['test_data', '.zip'])
Zip::File.open(@temp_zip.path, Zip::File::CREATE) do |zipfile|
zipfile.add('ettevotja_rekvisiidid__lihtandmed.csv', @temp_csv_path)
end
# Stub HTTP request
stub_request(:get, 'https://avaandmed.ariregister.rik.ee/sites/default/files/avaandmed/ettevotja_rekvisiidid__lihtandmed.csv.zip')
.to_return(status: 200, body: File.read(@temp_zip.path), headers: {})
# Prepend the module to the main object to override methods
main = TOPLEVEL_BINDING.eval('self')
main.singleton_class.prepend(CompanyStatusTaskTestOverrides)
end
def teardown
super # Always call super when overriding teardown
@temp_csv.close if @temp_csv
@temp_csv.unlink if @temp_csv
@temp_zip.close if @temp_zip
@temp_zip.unlink if @temp_zip
WebMock.reset!
end
test "initialize_rake_task sets default options correctly and handles file processing" do
stub_request(:get, 'https://avaandmed.ariregister.rik.ee/sites/default/files/avaandmed/ettevotja_rekvisiidid__lihtandmed.csv.zip')
.to_return(status: 200, body: File.read(@temp_zip.path), headers: {})
ENV['whitelist_companies'] = '["12345678", "87654321"]'
$test_options = nil
# No need to prepend again; it's already done in setup
# Stub external dependencies
RakeOptionParserBoilerplate.stub :process_args, ->(options:, banner:, hash:) { options } do
run_task
# Assertions
assert_not_nil $test_options, "Options should not be nil"
expected_path = Rails.root.join('tmp', 'ettevotja_rekvisiidid__lihtandmed.csv').to_s
assert_equal expected_path, $test_options
# Add more assertions as needed
end
assert_requested :get, 'https://avaandmed.ariregister.rik.ee/sites/default/files/avaandmed/ettevotja_rekvisiidid__lihtandmed.csv.zip'
end
test "initialize_rake_task processes command line arguments" do
simulated_args = [
'--open_data_file_path=/custom/path.csv',
'--missing_companies_output_path=/custom/missing.csv',
'--deleted_companies_output_path=/custom/deleted.csv',
'--download_path=https://example.com/custom.zip',
'--soft_delete_enable',
'--registrants_only'
]
# Replace ARGV with simulated arguments
original_argv = ARGV.dup
ARGV.replace(simulated_args)
# Stub RakeOptionParserBoilerplate to process ARGV
RakeOptionParserBoilerplate.stub :process_args, ->(options:, banner:, hash:) {
OptionParser.new do |opts|
hash.each do |key, (short, long, type)|
opts.on(*[short, long, type].compact) do |value|
# Convert string 'true'/'false' to boolean if needed
if [TrueClass, FalseClass].include?(type)
value = true
end
options[key] = value
end
end
end.parse!(ARGV)
options
} do
options = initialize_rake_task
# Assertions
assert_equal '/custom/path.csv', options[:open_data_file_path]
assert_equal '/custom/missing.csv', options[:missing_companies_output_path]
assert_equal '/custom/deleted.csv', options[:deleted_companies_output_path]
assert_equal 'https://example.com/custom.zip', options[:download_path]
assert_equal true, options[:soft_delete_enable]
assert_equal true, options[:registrants_only]
end
# Restore ARGV
ARGV.replace(original_argv)
end
test "download_open_data_file downloads file successfully" do
# Setup a temporary filename
temp_filename = 'test_download.zip'
# Stub the HTTP request
stub_request(:get, 'https://example.com/test.zip')
.to_return(status: 200, body: 'Test content', headers: {})
# Call the actual method
download_open_data_file('https://example.com/test.zip', temp_filename)
# Assertions
assert File.exist?(temp_filename), "File should exist after download"
assert_equal 'Test content', File.read(temp_filename)
assert_requested :get, 'https://example.com/test.zip'
# Cleanup
File.delete(temp_filename) if File.exist?(temp_filename)
end
test "unzip_file extracts contents correctly" do
# Create a temporary zip file with known content
temp_zip = Tempfile.new(['test', '.zip'])
temp_dir = Dir.mktmpdir
Zip::File.open(temp_zip.path, Zip::File::CREATE) do |zipfile|
zipfile.get_output_stream('test.txt') { |f| f.write 'Hello, world!' }
end
# Call the method
unzip_file(temp_zip.path, temp_dir)
# Assertions
extracted_file = File.join(temp_dir, 'test.txt')
puts "Extracted file path: #{extracted_file}" # Add debug information
puts "Directory contents: #{Dir.entries(temp_dir)}" # Add debug information
assert File.exist?(extracted_file), "File should be extracted"
assert_equal 'Hello, world!', File.read(extracted_file)
# Cleanup
temp_zip.close
temp_zip.unlink
FileUtils.remove_entry(temp_dir)
end
def run_task
Rake::Task['company_status:check_all'].execute
end
end

2
test_data 2.csv Normal file
View file

@ -0,0 +1,2 @@
company_code,company_name,status
12345678,Test Company,active
1 company_code company_name status
2 12345678 Test Company active

2
test_data.csv Normal file
View file

@ -0,0 +1,2 @@
company_code,company_name,status
12345678,Test Company,active
1 company_code company_name status
2 12345678 Test Company active