class DataImport < ApplicationRecord has_one_attached :file validates :import_type, presence: true, inclusion: { in: %w[asn country] } validates :status, presence: true, inclusion: { in: %w[pending processing completed failed] } validates :filename, presence: true attribute :import_stats, default: -> { {} } # Scopes scope :recent, -> { order(created_at: :desc) } scope :by_type, ->(type) { where(import_type: type) } scope :by_status, ->(status) { where(status: status) } scope :completed, -> { where(status: 'completed') } scope :failed, -> { where(status: 'failed') } scope :processing, -> { where(status: 'processing') } scope :pending, -> { where(status: 'pending') } # State management def pending? status == 'pending' end def processing? status == 'processing' end def completed? status == 'completed' end def failed? status == 'failed' end def start_processing! update!( status: 'processing', started_at: Time.current ) end def complete! updates = { status: 'completed', completed_at: Time.current } updates[:total_records] = processed_records if total_records.zero? update!(updates) end def fail!(error_message = nil) update!( status: 'failed', completed_at: Time.current, error_message: error_message ) end def progress_percentage if total_records.zero? processing? ? 0.1 : 0 # Show minimal progress for processing jobs else (processed_records.to_f / total_records * 100).round(2) end end def duration return 0 unless started_at end_time = completed_at || Time.current duration_seconds = (end_time - started_at).round(2) duration_seconds.negative? ? 0 : duration_seconds end def records_per_second # Handle very fast imports that complete in less than 1 second if duration.zero? # Use time since started if no duration available yet time_elapsed = started_at ? (Time.current - started_at) : 0 return 0 if time_elapsed < 1 (processed_records.to_f / time_elapsed).round(2) else (processed_records.to_f / duration).round(2) end end def update_progress(processed: nil, failed: nil, total_records: nil, stats: nil) updates = {} updates[:processed_records] = processed if processed updates[:failed_records] = failed if failed updates[:total_records] = total_records if total_records updates[:import_stats] = stats if stats update!(updates) if updates.any? end end