feat: add more status to contact import email

This commit is contained in:
Muhsin
2025-10-25 09:22:36 +05:30
parent b9864fe1f6
commit dae0366420
7 changed files with 70 additions and 24 deletions
+25 -8
View File
@@ -20,15 +20,18 @@ class DataImportJob < ApplicationJob
def process_import_file
@data_import.update!(status: :processing)
contacts, rejected_contacts = parse_csv_and_build_contacts
identifiable_contacts, non_identifiable_contacts, rejected_contacts = parse_csv_and_build_contacts
import_contacts(contacts)
update_data_import_status(contacts.length, rejected_contacts.length)
all_valid_contacts = identifiable_contacts + non_identifiable_contacts
import_contacts(all_valid_contacts)
update_data_import_status(identifiable_contacts.length, non_identifiable_contacts.length, rejected_contacts.length)
save_failed_records_csv(rejected_contacts)
end
# rubocop:disable Metrics/MethodLength
def parse_csv_and_build_contacts
contacts = []
identifiable_contacts = []
non_identifiable_contacts = []
rejected_contacts = []
# Ensuring that importing non utf-8 characters will not throw error
data = @data_import.import_file.download
@@ -42,14 +45,21 @@ class DataImportJob < ApplicationJob
csv.each do |row|
current_contact = @contact_manager.build_contact(row.to_h.with_indifferent_access)
if current_contact.valid?
contacts << current_contact
is_identifiable = @contact_manager.contact_identifiable?(current_contact)
if is_identifiable
identifiable_contacts << current_contact
else
non_identifiable_contacts << current_contact
end
else
append_rejected_contact(row, current_contact, rejected_contacts)
end
end
[contacts, rejected_contacts]
[identifiable_contacts, non_identifiable_contacts, rejected_contacts]
end
# rubocop:enable Metrics/MethodLength
def append_rejected_contact(row, contact, rejected_contacts)
row['errors'] = contact.errors.full_messages.join(', ')
@@ -61,8 +71,15 @@ class DataImportJob < ApplicationJob
Contact.import(contacts, synchronize: contacts, on_duplicate_key_ignore: true, track_validation_failures: true, validate: true, batch_size: 1000)
end
def update_data_import_status(processed_records, rejected_records)
@data_import.update!(status: :completed, processed_records: processed_records, total_records: processed_records + rejected_records)
def update_data_import_status(identifiable_records, non_identifiable_records, rejected_records)
total_records = identifiable_records + non_identifiable_records + rejected_records
processed_records = identifiable_records + non_identifiable_records
@data_import.update!(
status: :completed,
processed_records: processed_records,
non_identifiable_records: non_identifiable_records,
total_records: total_records
)
end
def save_failed_records_csv(rejected_contacts)
@@ -32,9 +32,16 @@ class AdministratorNotifications::AccountNotificationMailer < AdministratorNotif
"#{ENV.fetch('FRONTEND_URL', nil)}/app/accounts/#{resource.account.id}/contacts"
end
# Calculate metrics with backward compatibility
non_identifiable_count = resource.respond_to?(:non_identifiable_records) ? resource.non_identifiable_records : 0
identifiable_count = resource.processed_records - non_identifiable_count
failed_count = resource.total_records - resource.processed_records
meta = {
'failed_contacts' => resource.total_records - resource.processed_records,
'imported_contacts' => resource.processed_records
'identifiable_contacts' => identifiable_count,
'non_identifiable_contacts' => non_identifiable_count,
'failed_contacts' => failed_count,
'total_contacts' => resource.total_records
}
send_notification(subject, action_url: action_url, meta: meta)
+10 -9
View File
@@ -2,15 +2,16 @@
#
# Table name: data_imports
#
# id :bigint not null, primary key
# data_type :string not null
# processed_records :integer
# processing_errors :text
# status :integer default("pending"), not null
# total_records :integer
# created_at :datetime not null
# updated_at :datetime not null
# account_id :bigint not null
# id :bigint not null, primary key
# data_type :string not null
# non_identifiable_records :integer default(0), not null
# processed_records :integer
# processing_errors :text
# status :integer default("pending"), not null
# total_records :integer
# created_at :datetime not null
# updated_at :datetime not null
# account_id :bigint not null
#
# Indexes
#
@@ -9,6 +9,10 @@ class DataImport::ContactManager
contact
end
def contact_identifiable?(contact)
contact.email.present? || contact.phone_number.present? || contact.identifier.present?
end
def find_or_initialize_contact(params)
contact = find_existing_contact(params)
contact_params = params.slice(:email, :identifier, :phone_number)
@@ -1,10 +1,21 @@
<p>Hello,</p>
<p>Your contact import has been completed. Please check the contacts tab to view the imported contacts.</p>
<p>Your contact import has been completed. Here's a summary of the results:</p>
<p>Number of records imported: {{meta['imported_contacts']}}</p>
<p><strong>Contacts imported successfully:</strong> {{meta['identifiable_contacts']}}</p>
<p><em>These contacts are visible in your contacts list and can be used for conversations.</em></p>
<p>Number of records failed: {{meta['failed_contacts']}}</p>
{% if meta['non_identifiable_contacts'] > 0 %}
<p><strong>Contacts created but not visible:</strong> {{meta['non_identifiable_contacts']}}</p>
<p><em>These contacts were created successfully but don't have email, phone number, or identifier, so they won't appear in your contacts list until you add this information.</em></p>
{% endif %}
{% if meta['failed_contacts'] > 0 %}
<p><strong>Contacts that failed to import:</strong> {{meta['failed_contacts']}}</p>
<p><em>These contacts had validation errors and could not be imported.</em></p>
{% endif %}
<p><strong>Total contacts processed:</strong> {{meta['total_contacts']}}</p>
{% if meta['failed_contacts'] == 0 %}
<p>
@@ -12,6 +23,6 @@
</p>
{% else %}
<p>
Click <a href="{{ action_url }}" target="_blank">here</a> to view failed records.
Click <a href="{{ action_url }}" target="_blank">here</a> to download the failed records and see specific error messages.
</p>
{% endif %}
@@ -0,0 +1,5 @@
class AddNonIdentifiableRecordsToDataImports < ActiveRecord::Migration[7.0]
def change
add_column :data_imports, :non_identifiable_records, :integer, default: 0, null: false
end
end
+2 -1
View File
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.1].define(version: 2025_10_03_091242) do
ActiveRecord::Schema[7.1].define(version: 2025_10_25_033349) do
# These extensions should be enabled to support this database
enable_extension "pg_stat_statements"
enable_extension "pg_trgm"
@@ -784,6 +784,7 @@ ActiveRecord::Schema[7.1].define(version: 2025_10_03_091242) do
t.integer "processed_records"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "non_identifiable_records", default: 0, null: false
t.index ["account_id"], name: "index_data_imports_on_account_id"
end