feat: add more status to contact import email
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
+15
-4
@@ -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
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user