Ran for half a minute, finished .
# frozen_string_literal: true
# Applies AgentPort persona visibility to existing custom fields and emails one CSV
# report. The legacy columns are compared against the database and reported, never
# written.
#
# Expected CSV headers:
# custom_field_id, company_guid, mbo_profile, agentport_profile_name,
# custom_field_name, traveller_visibility, admin_visibility,
# approval_visibility, legacy_type, legacy_number
class Maintenance::ImportPersonaVisibilityTask < MaintenanceTasks::Task
include ArrayHelper
csv_collection(in_batches: 100)
report_on(StandardError)
REPORT_COLUMNS = %w[
report company_guid mbo_profile agentport_profile_name custom_field_id custom_field_name
file_legacy_type file_legacy_number database_legacy_type database_legacy_number
discrepancy_flag detail
].freeze
# Fixed, so a run resumed in another process appends to the same report.
REPORT_FILE = 'tmp/import_persona_visibility.csv'
IMPORT_REPORTS = %w[IMPORTED WOULD_IMPORT].freeze
ROW_COLUMNS = %w[company_guid mbo_profile agentport_profile_name custom_field_id
custom_field_name].freeze
attribute :emails, :string
attribute :report_only, :boolean, default: false
validates :emails, presence: true, fcm_email_format: true
after_start :prepare_report
after_complete :send_report
after_error :send_report
def process(batch_of_rows)
lines = batch_of_rows.flat_map { |row| process_row(row.to_h) }
File.write(report_path, lines.join, mode: 'a')
end
def report_path
Rails.root.join(REPORT_FILE).to_s
end
private
def process_row(row)
return [line(row, report: 'FIELD_NOT_IN_COMPANY_PROFILE')] if row['custom_field_id'].blank?
custom_field = CustomField.find_by(id: row['custom_field_id'])
return [line(row, report: 'ERROR', detail: 'custom field no longer exists')] unless custom_field
[apply_visibility(row, custom_field), legacy_discrepancy(row, custom_field)].compact
end
def apply_visibility(row, custom_field)
return line(row, report: 'WOULD_IMPORT') if report_only
custom_field.update!(visibility_attributes(row))
line(row, report: 'IMPORTED')
rescue ActiveRecord::RecordInvalid => e
line(row, report: 'ERROR', detail: e.record.errors.full_messages.join('; '))
end
def visibility_attributes(row)
{ traveller_visibility: row['traveller_visibility'],
admin_visibility: row['admin_visibility'],
travel_arranger_visibility: row['approval_visibility'] }
end
# nil when file and database agree: consistent records stay out of the report.
def legacy_discrepancy(row, custom_field)
stored = custom_field.legacy_agent_port_code
return line(row, report: 'LEGACY_DISCREPANCY', discrepancy_flag: 'MISSING_IN_DATABASE') if stored.blank?
flag = discrepancy_flag(row, stored)
return unless flag
line(row, report: 'LEGACY_DISCREPANCY', discrepancy_flag: flag,
database_legacy_type: stored[0], database_legacy_number: stored[1..])
end
def discrepancy_flag(row, stored)
same_type = stored[0] == row['legacy_type']
same_number = stored[1..] == row['legacy_number'].to_s
return nil if same_type && same_number
return 'TYPE_AND_NUMBER_DIFFER' unless same_type || same_number
same_type ? 'NUMBER_DIFFERS' : 'TYPE_DIFFERS'
end
def line(row, **extra)
values = row.slice(*ROW_COLUMNS)
.merge('file_legacy_type' => row['legacy_type'],
'file_legacy_number' => row['legacy_number'])
.merge(extra.transform_keys(&:to_s))
REPORT_COLUMNS.map { |column| values[column] }.to_csv
end
def prepare_report
File.write(report_path, REPORT_COLUMNS.to_csv)
end
def send_report
return unless File.exist?(report_path)
append_confirmation
CsvReportMailer.send_report(recipients: emails_array(emails), file_path: report_path,
report_sender: 'Import Persona Visibility').deliver_now
ensure
FileUtils.rm_f(report_path)
end
# Counted from the file, not memory, so a resumed run still reports what landed.
def append_confirmation
counts = CSV.read(report_path, headers: true)
.select { |line| IMPORT_REPORTS.include?(line['report']) }
.group_by { |line| line['company_guid'] }
.transform_values(&:size)
File.open(report_path, 'a') { |file| counts.sort.each { |pair| file.puts(confirmation_line(*pair)) } }
end
def confirmation_line(company_guid, count)
values = { 'report' => 'CONFIRMATION', 'company_guid' => company_guid, 'detail' => count }
REPORT_COLUMNS.map { |column| values[column] }.to_csv
end
end
Processed 213 out of 213 items (100%).
Ran for half a minute, finished .
[FILTERED]
0
-1
Processed 213 out of 213 items (100%).
Ran for less than 5 seconds, finished .
[FILTERED]
1
-1