mirror of
https://github.com/Freika/dawarich.git
synced 2026-01-11 17:51:39 -05:00
175 lines
4.2 KiB
Ruby
175 lines
4.2 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class Users::ImportData::Trips
|
|
BATCH_SIZE = 1000
|
|
|
|
def initialize(user, trips_data)
|
|
@user = user
|
|
@trips_data = trips_data
|
|
end
|
|
|
|
def call
|
|
return 0 unless trips_data.is_a?(Array)
|
|
|
|
Rails.logger.info "Importing #{trips_data.size} trips for user: #{user.email}"
|
|
|
|
valid_trips = filter_and_prepare_trips
|
|
|
|
if valid_trips.empty?
|
|
Rails.logger.info "Trips import completed. Created: 0"
|
|
return 0
|
|
end
|
|
|
|
deduplicated_trips = filter_existing_trips(valid_trips)
|
|
|
|
if deduplicated_trips.size < valid_trips.size
|
|
Rails.logger.debug "Skipped #{valid_trips.size - deduplicated_trips.size} duplicate trips"
|
|
end
|
|
|
|
total_created = bulk_import_trips(deduplicated_trips)
|
|
|
|
Rails.logger.info "Trips import completed. Created: #{total_created}"
|
|
total_created
|
|
end
|
|
|
|
private
|
|
|
|
attr_reader :user, :trips_data
|
|
|
|
def filter_and_prepare_trips
|
|
valid_trips = []
|
|
skipped_count = 0
|
|
|
|
trips_data.each do |trip_data|
|
|
next unless trip_data.is_a?(Hash)
|
|
|
|
unless valid_trip_data?(trip_data)
|
|
skipped_count += 1
|
|
next
|
|
end
|
|
|
|
prepared_attributes = prepare_trip_attributes(trip_data)
|
|
valid_trips << prepared_attributes if prepared_attributes
|
|
end
|
|
|
|
if skipped_count > 0
|
|
Rails.logger.warn "Skipped #{skipped_count} trips with invalid or missing required data"
|
|
end
|
|
|
|
valid_trips
|
|
end
|
|
|
|
def prepare_trip_attributes(trip_data)
|
|
attributes = trip_data.except('created_at', 'updated_at')
|
|
|
|
attributes['user_id'] = user.id
|
|
attributes['created_at'] = Time.current
|
|
attributes['updated_at'] = Time.current
|
|
|
|
attributes.symbolize_keys
|
|
rescue StandardError => e
|
|
ExceptionReporter.call(e, 'Failed to prepare trip attributes')
|
|
|
|
nil
|
|
end
|
|
|
|
def filter_existing_trips(trips)
|
|
return trips if trips.empty?
|
|
|
|
existing_trips_lookup = {}
|
|
user.trips.select(:name, :started_at, :ended_at).each do |trip|
|
|
key = [trip.name, normalize_timestamp(trip.started_at), normalize_timestamp(trip.ended_at)]
|
|
existing_trips_lookup[key] = true
|
|
end
|
|
|
|
filtered_trips = trips.reject do |trip|
|
|
key = [trip[:name], normalize_timestamp(trip[:started_at]), normalize_timestamp(trip[:ended_at])]
|
|
if existing_trips_lookup[key]
|
|
Rails.logger.debug "Trip already exists: #{trip[:name]}"
|
|
true
|
|
else
|
|
false
|
|
end
|
|
end
|
|
|
|
filtered_trips
|
|
end
|
|
|
|
def normalize_timestamp(timestamp)
|
|
case timestamp
|
|
when String
|
|
Time.parse(timestamp).utc.iso8601
|
|
when Time, DateTime
|
|
timestamp.utc.iso8601
|
|
else
|
|
timestamp.to_s
|
|
end
|
|
rescue StandardError
|
|
timestamp.to_s
|
|
end
|
|
|
|
def bulk_import_trips(trips)
|
|
total_created = 0
|
|
|
|
trips.each_slice(BATCH_SIZE) do |batch|
|
|
begin
|
|
result = Trip.upsert_all(
|
|
batch,
|
|
returning: %w[id],
|
|
on_duplicate: :skip
|
|
)
|
|
|
|
batch_created = result.count
|
|
total_created += batch_created
|
|
|
|
Rails.logger.debug "Processed batch of #{batch.size} trips, created #{batch_created}, total created: #{total_created}"
|
|
|
|
rescue StandardError => e
|
|
ExceptionReporter.call(e, 'Failed to process trip batch')
|
|
end
|
|
end
|
|
|
|
total_created
|
|
end
|
|
|
|
def valid_trip_data?(trip_data)
|
|
return false unless trip_data.is_a?(Hash)
|
|
|
|
return false unless validate_trip_name(trip_data)
|
|
return false unless validate_trip_started_at(trip_data)
|
|
return false unless validate_trip_ended_at(trip_data)
|
|
|
|
true
|
|
rescue StandardError => e
|
|
Rails.logger.debug "Trip validation failed: #{e.message} for data: #{trip_data.inspect}"
|
|
false
|
|
end
|
|
|
|
|
|
def validate_trip_name(trip_data)
|
|
if trip_data['name'].present?
|
|
true
|
|
else
|
|
Rails.logger.debug 'Trip validation failed: Name can\'t be blank'
|
|
false
|
|
end
|
|
end
|
|
|
|
def validate_trip_started_at(trip_data)
|
|
if trip_data['started_at'].present?
|
|
true
|
|
else
|
|
Rails.logger.debug 'Trip validation failed: Started at can\'t be blank'
|
|
false
|
|
end
|
|
end
|
|
|
|
def validate_trip_ended_at(trip_data)
|
|
if trip_data['ended_at'].present?
|
|
true
|
|
else
|
|
Rails.logger.debug 'Trip validation failed: Ended at can\'t be blank'
|
|
false
|
|
end
|
|
end
|
|
end
|