Class: PartnerService::Reservations::RestaurantSyncService

Inherits:
ApplicationService show all
Defined in:
app/services/partner_service/reservations/restaurant_sync_service.rb

Instance Attribute Summary

Attributes inherited from ApplicationService

#object

Class Method Summary collapse

Methods inherited from ApplicationService

#execute, #execute!

Class Method Details

.bulk_status(restaurant_ids) ⇒ Array<Hash>

Quick status check for multiple restaurants Useful for monitoring and health checks

Examples:

Check status for multiple restaurants

PartnerService::Reservations::RestaurantSyncService.bulk_status([123, 456, 789])

Parameters:

  • restaurant_ids (Array<Integer>)

    array of restaurant IDs

Returns:

  • (Array<Hash>)

    array of status results



355
356
357
358
359
360
361
362
363
# File 'app/services/partner_service/reservations/restaurant_sync_service.rb', line 355

def self.bulk_status(restaurant_ids)
  results = []
  restaurant_ids.each do |restaurant_id|
    status = check_status(restaurant_id)
    results << status
  end

  results
end

.bulk_sync(restaurant_ids, options = {}) ⇒ Array<Hash>

Sync multiple restaurants with progress tracking Useful for bulk operations and data migrations

Examples:

Bulk sync multiple restaurants

PartnerService::Reservations::RestaurantSyncService.bulk_sync([123, 456, 789])

Bulk sync with custom options

PartnerService::Reservations::RestaurantSyncService.bulk_sync([123, 456], {
  days_back: 30,
  batch_size: 50
})

Parameters:

  • restaurant_ids (Array<Integer>)

    array of restaurant IDs

  • options (Hash) (defaults to: {})

    sync options

Returns:

  • (Array<Hash>)

    array of results



334
335
336
337
338
339
340
341
342
343
344
345
# File 'app/services/partner_service/reservations/restaurant_sync_service.rb', line 334

def self.bulk_sync(restaurant_ids, options = {})
  results = []
  restaurant_ids.each_with_index do |restaurant_id, index|
    result = sync_restaurant(restaurant_id, options)
    results << result.merge(restaurant_id: restaurant_id)

    # Small delay between restaurants to prevent overwhelming the system
    sleep(1) if options[:delay_between_restaurants] && restaurant_ids.size > 1
  end

  results
end

.calculate_percentage(numerator, denominator) ⇒ Float

Calculate percentage with safe division

Parameters:

  • numerator (Integer)

    numerator value

  • denominator (Integer)

    denominator value

Returns:

  • (Float)

    percentage rounded to 1 decimal place



307
308
309
310
311
# File 'app/services/partner_service/reservations/restaurant_sync_service.rb', line 307

def self.calculate_percentage(numerator, denominator)
  return 0.0 if denominator == 0

  (numerator.to_f / denominator * 100).round(1)
end

.check_status(restaurant_id, days_back = 90) ⇒ Hash

Status check: Analyze sync coverage and identify missing summaries

PURPOSE: Provides comprehensive sync status analysis and health metrics. Compares reservation count vs summary count to identify gaps.

WHEN TO USE:

  • Before running sync operations to assess scope

  • Monitoring sync health and coverage

  • Troubleshooting data inconsistencies

  • Regular health checks for critical restaurants

Parameters:

  • restaurant_id (Integer)

    the restaurant ID to check

  • days_back (Integer) (defaults to: 90)

    days to look back for comparison

Returns:

  • (Hash)

    status information with sync_percentage, missing_count, needs_sync



197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
# File 'app/services/partner_service/reservations/restaurant_sync_service.rb', line 197

def self.check_status(restaurant_id, days_back = 90)
  restaurant = ::Restaurant.find_by(id: restaurant_id)
  return { success: false, error: "Restaurant #{restaurant_id} not found" } unless restaurant

  end_date = Date.current
  start_date = end_date - days_back.days

  # Count reservations and summaries
  total_reservations = Reservation.where(restaurant_id: restaurant_id).
    where(created_at: start_date.beginning_of_day..end_date.end_of_day).
    where(for_locking_system: false).
    count

  total_summaries = Partners::ReservationSummary.where(restaurant_id: restaurant_id).
    where(created_at: start_date.beginning_of_day..end_date.end_of_day).
    count

  sync_percentage = total_reservations > 0 ? (total_summaries.to_f / total_reservations * 100).round(1) : 0
  missing_count = total_reservations - total_summaries

  # Check recent activity (last 24 hours)
  recent_reservations = Reservation.where(restaurant_id: restaurant_id).
    where(created_at: 24.hours.ago..Time.current).
    where(for_locking_system: false).
    count

  recent_summaries = Partners::ReservationSummary.where(restaurant_id: restaurant_id).
    where(created_at: 24.hours.ago..Time.current).
    count

  {
    success: true,
    restaurant_id: restaurant_id,
    restaurant_name: restaurant.name,
    date_range: "#{start_date} to #{end_date}",
    total_reservations: total_reservations,
    total_summaries: total_summaries,
    sync_percentage: sync_percentage,
    missing_count: missing_count,
    recent_activity: {
      reservations_24h: recent_reservations,
      summaries_24h: recent_summaries,
      recent_sync_percentage: calculate_percentage(recent_summaries, recent_reservations),
    },
    needs_sync: sync_percentage < 100 || recent_summaries < recent_reservations,
  }
rescue StandardError => e
  { success: false, error: "Status check failed: #{e.message}" }
end

.generate_sync_recommendations(restaurants_needing_sync_count, total_restaurants) ⇒ Array<Hash>

Generate sync recommendations based on statistics

Parameters:

  • restaurants_needing_sync_count (Integer)

    number of restaurants needing sync

  • total_restaurants (Integer)

    total number of restaurants with bookings

Returns:

  • (Array<Hash>)

    array of recommendations



584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
# File 'app/services/partner_service/reservations/restaurant_sync_service.rb', line 584

def self.generate_sync_recommendations(restaurants_needing_sync_count, total_restaurants)
  recommendations = []

  if restaurants_needing_sync_count == 0
    recommendations << {
      priority: 'low',
      action: 'none',
      message: 'All restaurants are fully synced',
      command: nil,
    }
  elsif restaurants_needing_sync_count < (total_restaurants * 0.1) # Less than 10%
    recommendations << {
      priority: 'medium',
      action: 'selective_sync',
      message: "#{restaurants_needing_sync_count} restaurants need sync (#{((restaurants_needing_sync_count.to_f / total_restaurants) * 100).round(1)}%)",
      command: 'Use sync_non_synced_bookings with specific restaurant IDs',
    }
  else
    recommendations << {
      priority: 'high',
      action: 'bulk_sync',
      message: "#{restaurants_needing_sync_count} restaurants need sync (#{((restaurants_needing_sync_count.to_f / total_restaurants) * 100).round(1)}%) - consider bulk operation",
      command: 'Use sync_non_synced_bookings or bulk_sync for affected restaurants',
    }
  end

  recommendations
end

.get_recommendations(restaurant_id) ⇒ Hash

Get sync recommendations based on current status

Parameters:

  • restaurant_id (Integer)

    the restaurant ID to analyze

Returns:

  • (Hash)

    recommendations



251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
# File 'app/services/partner_service/reservations/restaurant_sync_service.rb', line 251

def self.get_recommendations(restaurant_id)
  status = check_status(restaurant_id)
  return status unless status[:success]

  recommendations = []

  if status[:sync_percentage] < 90
    recommendations << {
      priority: 'high',
      action: 'full_sync',
      reason: "Only #{status[:sync_percentage]}% of reservations have summaries",
      command: "PartnerService::Reservations::RestaurantSyncService.sync_restaurant(#{restaurant_id})",
    }
  elsif status[:recent_activity][:recent_sync_percentage] < 100
    recommendations << {
      priority: 'medium',
      action: 'recent_sync',
      reason: 'Recent bookings missing summaries',
      command: "PartnerService::Reservations::RestaurantSyncService.sync_recent_bookings(#{restaurant_id})",
    }
  else
    recommendations << {
      priority: 'low',
      action: 'none',
      reason: 'Sync status looks good',
      command: nil,
    }
  end

  status.merge(recommendations: recommendations)
end

.get_reservation_ids(restaurant_id, days_back = 90) ⇒ Array<Integer>

Get reservation IDs for a restaurant ordered by ID DESC

Parameters:

  • restaurant_id (Integer)

    the restaurant ID

  • days_back (Integer) (defaults to: 90)

    number of days to look back

Returns:

  • (Array<Integer>)

    array of reservation IDs



100
101
102
103
104
105
106
107
108
109
# File 'app/services/partner_service/reservations/restaurant_sync_service.rb', line 100

def self.get_reservation_ids(restaurant_id, days_back = 90)
  end_date = Date.current
  start_date = end_date - days_back.days

  Reservation.where(restaurant_id: restaurant_id).
    where(created_at: start_date.beginning_of_day..end_date.end_of_day).
    where(for_locking_system: false).
    order(id: :desc). # Most recent first for immediate processing
    pluck(:id)
end

.helpvoid

This method returns an undefined value.

Display helpful usage examples for Rails console Useful for support team and developers

Examples:

Show help in Rails console

PartnerService::Reservations::RestaurantSyncService.help


533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
# File 'app/services/partner_service/reservations/restaurant_sync_service.rb', line 533

def self.help
  Rails.logger.info <<~HELP
    🔧 RESTAURANT SYNC SERVICE COMMANDS
    ===================================

    Basic Sync Operations:
      # Sync recent bookings (last 7 days) - recommended for immediate fixes
      PartnerService::Reservations::RestaurantSyncService.sync_recent_bookings(restaurant_id)

      # Full sync all reservations (90 days)
      PartnerService::Reservations::RestaurantSyncService.sync_restaurant(restaurant_id)

      # Sync with custom options
      PartnerService::Reservations::RestaurantSyncService.sync_restaurant(restaurant_id, {
        days_back: 30,     # Look back 30 days instead of 90
        batch_size: 50,    # Process 50 reservations per batch
        sync_type: 'full'  # Type of sync to perform
      })

    Status & Monitoring:
      # Check sync status and get recommendations
      PartnerService::Reservations::RestaurantSyncService.check_status(restaurant_id)

      # Get detailed recommendations
      PartnerService::Reservations::RestaurantSyncService.get_recommendations(restaurant_id)

    New Statistics & Bulk Sync:
      # Get restaurant booking statistics for last months
      PartnerService::Reservations::RestaurantSyncService.restaurant_booking_stats(3)

      # Sync only non-synced bookings for multiple restaurants
      PartnerService::Reservations::RestaurantSyncService.sync_non_synced_bookings([restaurant_id_1, restaurant_id_2])

    Bulk Operations:
      # Sync multiple restaurants
      PartnerService::Reservations::RestaurantSyncService.bulk_sync([restaurant_id_1, restaurant_id_2])

      # Check status for multiple restaurants
      PartnerService::Reservations::RestaurantSyncService.bulk_status([restaurant_id_1, restaurant_id_2])

    For more details, see the method documentation in the service file.
  HELP
end

.queue_batch_jobs(restaurant_id, restaurant_name, reservation_ids, options) ⇒ Hash

Queue batch jobs for reservation sync

Parameters:

  • restaurant_id (Integer)

    the restaurant ID

  • restaurant_name (String)

    the restaurant name

  • reservation_ids (Array<Integer>)

    array of reservation IDs

  • options (Hash)

    sync options

Returns:

  • (Hash)

    result with job information



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'app/services/partner_service/reservations/restaurant_sync_service.rb', line 118

def self.queue_batch_jobs(restaurant_id, restaurant_name, reservation_ids, options)
  total_count = reservation_ids.size
  total_batches = (total_count.to_f / options[:batch_size]).ceil

  batch_number = 0
  reservation_ids.each_slice(options[:batch_size]) do |batch_ids|
    batch_number += 1

    delay = options[:immediate] ? 0 : (batch_number - 1) * options[:delay_seconds]

    batch_info = {
      'batch_number' => batch_number,
      'total_batches' => total_batches,
      'restaurant_id' => restaurant_id,
      'restaurant_name' => restaurant_name,
      'sync_type' => options[:sync_type],
      'immediate' => options[:immediate],
      'ordered_by_recent' => true,
    }

    if delay > 0
      Partner::ReservationSummaryBatchSyncWorker.perform_in(delay, batch_ids, options[:sync_type], batch_info)
    else
      Partner::ReservationSummaryBatchSyncWorker.perform_async(batch_ids, options[:sync_type], batch_info)
    end
  end

  {
    success: true,
    restaurant_id: restaurant_id,
    restaurant_name: restaurant_name,
    total_count: total_count,
    total_batches: total_batches,
    batch_size: options[:batch_size],
    sync_type: options[:sync_type],
    immediate: options[:immediate],
    message: "Queued #{total_batches} batches for #{total_count} reservations (ordered by recent first)",
  }
end

.restaurant_booking_stats(months_back = 3) ⇒ Hash

Get restaurant booking statistics for last months

Provides comprehensive statistics about restaurants with bookings and their sync status. Useful for monitoring overall sync health and identifying restaurants that need attention.

Examples:

Get stats for last 3 months

PartnerService::Reservations::RestaurantSyncService.restaurant_booking_stats

Get stats for last 6 months

PartnerService::Reservations::RestaurantSyncService.restaurant_booking_stats(6)

Parameters:

  • months_back (Integer) (defaults to: 3)

    number of months to look back (default: 3)

Returns:

  • (Hash)

    comprehensive booking and sync statistics



378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
# File 'app/services/partner_service/reservations/restaurant_sync_service.rb', line 378

def self.restaurant_booking_stats(months_back = 3)
  end_date = Date.current
  start_date = end_date - months_back.months

  # Get restaurants with bookings in the period
  restaurants_with_bookings = Reservation.
    where(created_at: start_date.beginning_of_day..end_date.end_of_day).
    where(for_locking_system: false).
    group(:restaurant_id).
    count

  total_restaurants_with_bookings = restaurants_with_bookings.size
  total_bookings = restaurants_with_bookings.values.sum

  # Get restaurants with summary records
  restaurants_with_summaries = Partners::ReservationSummary.
    where(created_at_reservation: start_date.beginning_of_day..end_date.end_of_day).
    group(:restaurant_id).
    count

  total_restaurants_with_summaries = restaurants_with_summaries.size
  total_summaries = restaurants_with_summaries.values.sum

  # Calculate restaurants with incomplete sync
  restaurants_needing_sync = []
  restaurants_with_bookings.each do |restaurant_id, booking_count|
    summary_count = restaurants_with_summaries[restaurant_id] || 0
    sync_percentage = (summary_count.to_f / booking_count * 100).round(1)

    if sync_percentage < 100
      restaurants_needing_sync << {
        restaurant_id: restaurant_id,
        booking_count: booking_count,
        summary_count: summary_count,
        sync_percentage: sync_percentage,
        missing_summaries: booking_count - summary_count,
      }
    end
  end

  # Sort by missing summaries count (most problematic first)
  restaurants_needing_sync.sort_by! { |r| -r[:missing_summaries] }

  {
    success: true,
    generated_at: Time.current,
    period: {
      months_back: months_back,
      start_date: start_date,
      end_date: end_date,
    },
    overall_statistics: {
      total_restaurants_with_bookings: total_restaurants_with_bookings,
      total_restaurants_with_summaries: total_restaurants_with_summaries,
      total_bookings: total_bookings,
      total_summaries: total_summaries,
      overall_sync_percentage: calculate_percentage(total_summaries, total_bookings),
      restaurants_fully_synced: total_restaurants_with_bookings - restaurants_needing_sync.size,
      restaurants_needing_sync: restaurants_needing_sync.size,
    },
    restaurants_needing_sync: restaurants_needing_sync.first(20), # Top 20 most problematic
    recommendations: generate_sync_recommendations(restaurants_needing_sync.size, total_restaurants_with_bookings),
  }
rescue StandardError => e
  { success: false, error: "Failed to generate restaurant booking stats: #{e.message}" }
end

.sync_multiple_restaurants(restaurant_ids, options = {}) ⇒ Array<Hash>

Sync multiple restaurants

Parameters:

  • restaurant_ids (Array<Integer>)

    array of restaurant IDs

  • options (Hash) (defaults to: {})

    sync options

Returns:

  • (Array<Hash>)

    array of sync results



288
289
290
291
292
293
294
295
296
297
298
299
300
# File 'app/services/partner_service/reservations/restaurant_sync_service.rb', line 288

def self.sync_multiple_restaurants(restaurant_ids, options = {})
  results = []

  restaurant_ids.each do |restaurant_id|
    result = sync_restaurant(restaurant_id, options)
    results << result.merge(restaurant_id: restaurant_id)

    # Small delay between restaurants to prevent overwhelming the system
    sleep(1) if options[:delay_between_restaurants]
  end

  results
end

.sync_non_synced_bookings(restaurant_ids, options = {}) ⇒ Hash

Sync non-synced bookings for multiple restaurants based on last 3 months

Identifies and syncs only the missing reservation summaries for specified restaurants. More efficient than full sync as it only processes reservations without summaries.

Examples:

Sync non-synced bookings for specific restaurants

PartnerService::Reservations::RestaurantSyncService.sync_non_synced_bookings([123, 456, 789])

Sync with custom options

PartnerService::Reservations::RestaurantSyncService.sync_non_synced_bookings([123, 456], {
  months_back: 6,
  batch_size: 50
})

Parameters:

  • restaurant_ids (Array<Integer>)

    array of restaurant IDs to sync

  • options (Hash) (defaults to: {})

    sync options

Options Hash (options):

  • :months_back (Integer) — default: 3

    months to look back for missing summaries

  • :batch_size (Integer) — default: 100

    reservations per batch

  • :sync_type (String) — default: 'full'

    type of sync to perform

  • :immediate (Boolean) — default: true

    execute immediately

Returns:

  • (Hash)

    comprehensive sync results



466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
# File 'app/services/partner_service/reservations/restaurant_sync_service.rb', line 466

def self.sync_non_synced_bookings(restaurant_ids, options = {})
  return { success: false, error: 'No restaurant IDs provided' } if restaurant_ids.blank?

  opts = {
    months_back: 3,
    batch_size: 100,
    sync_type: 'full',
    immediate: true,
  }.merge(options)

  end_date = Date.current
  start_date = end_date - opts[:months_back].months

  results = {
    success: true,
    generated_at: Time.current,
    period: {
      months_back: opts[:months_back],
      start_date: start_date,
      end_date: end_date,
    },
    sync_options: opts,
    restaurant_results: [],
    summary: {
      total_restaurants: restaurant_ids.size,
      successful_restaurants: 0,
      failed_restaurants: 0,
      total_missing_reservations: 0,
      total_batches_queued: 0,
    },
  }

  restaurant_ids.each do |restaurant_id|
    restaurant_result = sync_single_restaurant_non_synced(restaurant_id, start_date, end_date, opts)
    results[:restaurant_results] << restaurant_result

    if restaurant_result[:success]
      results[:summary][:successful_restaurants] += 1
      results[:summary][:total_missing_reservations] += restaurant_result[:missing_count]
      results[:summary][:total_batches_queued] += restaurant_result[:total_batches]
    else
      results[:summary][:failed_restaurants] += 1
    end

    # Small delay between restaurants to prevent overwhelming the system
    sleep(0.5) if restaurant_ids.size > 1
  end

  results
rescue StandardError => e
  error_msg = "Non-synced bookings sync failed: #{e.message}"
  APMErrorHandler.report('Non-synced bookings sync service failed', {
                           restaurant_ids: restaurant_ids,
                           options: options,
                           error_message: e.message,
                           exception: e,
                         })
  { success: false, error: error_msg }
end

.sync_recent_bookings(restaurant_id, options = {}) ⇒ Hash

Quick sync: Sync recent bookings only (last 7 days) for immediate fixes

PURPOSE: Fast sync for troubleshooting recent booking issues. Optimized for immediate processing with smaller batch sizes.

WHEN TO USE:

  • Fixing recent booking display issues in Partner API

  • Quick troubleshooting for customer support

  • After system issues that affected recent reservations

  • Regular maintenance for active restaurants

Parameters:

  • restaurant_id (Integer)

    the restaurant ID to sync

  • options (Hash) (defaults to: {})

    additional options

Returns:

  • (Hash)

    sync result



172
173
174
175
176
177
178
179
180
181
# File 'app/services/partner_service/reservations/restaurant_sync_service.rb', line 172

def self.sync_recent_bookings(restaurant_id, options = {})
  opts = {
    days_back: 7,
    batch_size: 50,
    sync_type: 'full',
    immediate: true,
  }.merge(options)

  sync_restaurant(restaurant_id, opts)
end

.sync_restaurant(restaurant_id, options = {}) ⇒ Hash

Main sync method: Sync reservation summaries for a restaurant using batch workers

PURPOSE: Synchronizes reservation data to summary tables for Partner API performance. Orders by ID DESC to prioritize recent bookings for immediate processing.

WHEN TO USE:

  • Full data migration or backfill operations

  • Fixing data inconsistencies across all reservations

  • Initial setup for new restaurants

Parameters:

  • restaurant_id (Integer)

    the restaurant ID to sync

  • options (Hash) (defaults to: {})

    sync options

Options Hash (options):

  • :sync_type (String) — default: 'full'

    type of sync

  • :days_back (Integer) — default: 90

    days to look back

  • :batch_size (Integer) — default: 100

    reservations per batch

  • :delay_seconds (Integer) — default: 0

    delay between batches

  • :immediate (Boolean) — default: true

    execute immediately

Returns:

  • (Hash)

    sync result with status and details



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'app/services/partner_service/reservations/restaurant_sync_service.rb', line 53

def self.sync_restaurant(restaurant_id, options = {})
  # Validate restaurant
  restaurant = ::Restaurant.find_by(id: restaurant_id)
  return { success: false, error: "Restaurant #{restaurant_id} not found" } unless restaurant

  # Default options optimized for immediate processing
  opts = {
    sync_type: 'full',
    days_back: 90,
    batch_size: 100,
    delay_seconds: 0,
    immediate: true,
  }.merge(options)

  # Get reservation IDs ordered by ID DESC (most recent first)
  reservation_ids = get_reservation_ids(restaurant_id, opts[:days_back])

  if reservation_ids.empty?
    return {
      success: true,
      message: 'No reservations found',
      restaurant_id: restaurant_id,
      restaurant_name: restaurant.name,
      total_count: 0,
    }
  end

  # Queue batches using the existing batch worker
  result = queue_batch_jobs(restaurant_id, restaurant.name, reservation_ids, opts)

  result
rescue StandardError => e
  error_msg = "Restaurant sync failed for restaurant #{restaurant_id}: #{e.message}"
  APMErrorHandler.report('Restaurant sync service failed', {
                           restaurant_id: restaurant_id,
                           options: options,
                           error_message: e.message,
                           exception: e,
                         })
  { success: false, error: error_msg }
end

.sync_single_restaurant_non_synced(restaurant_id, start_date, end_date, options) ⇒ Hash

Sync non-synced bookings for a single restaurant

Parameters:

  • restaurant_id (Integer)

    restaurant ID to sync

  • start_date (Date)

    start date for sync period

  • end_date (Date)

    end date for sync period

  • options (Hash)

    sync options

Returns:

  • (Hash)

    sync result for the restaurant



620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
# File 'app/services/partner_service/reservations/restaurant_sync_service.rb', line 620

def self.sync_single_restaurant_non_synced(restaurant_id, start_date, end_date, options)
  restaurant = ::Restaurant.find_by(id: restaurant_id)
  unless restaurant
    return {
      success: false,
      restaurant_id: restaurant_id,
      error: "Restaurant #{restaurant_id} not found",
    }
  end

  # Get all reservations for the period
  all_reservation_ids = Reservation.where(restaurant_id: restaurant_id).
    where(created_at: start_date.beginning_of_day..end_date.end_of_day).
    where(for_locking_system: false).
    pluck(:id)

  # Get existing summary reservation IDs
  existing_summary_ids = Partners::ReservationSummary.where(restaurant_id: restaurant_id).
    where(created_at_reservation: start_date.beginning_of_day..end_date.end_of_day).
    pluck(:reservation_id)

  # Find missing reservation IDs (reservations without summaries)
  missing_reservation_ids = all_reservation_ids - existing_summary_ids

  if missing_reservation_ids.empty?
    return {
      success: true,
      restaurant_id: restaurant_id,
      restaurant_name: restaurant.name,
      total_reservations: all_reservation_ids.size,
      existing_summaries: existing_summary_ids.size,
      missing_count: 0,
      total_batches: 0,
      message: 'All reservations already have summaries',
    }
  end

  # Order missing IDs by DESC (most recent first) for immediate processing
  missing_reservation_ids = missing_reservation_ids.sort.reverse

  # Queue batch jobs for missing reservations only
  result = queue_batch_jobs(
    restaurant_id,
    restaurant.name,
    missing_reservation_ids,
    options.merge(sync_type: options[:sync_type]),
  )

  if result[:success]
    {
      success: true,
      restaurant_id: restaurant_id,
      restaurant_name: restaurant.name,
      total_reservations: all_reservation_ids.size,
      existing_summaries: existing_summary_ids.size,
      missing_count: missing_reservation_ids.size,
      total_batches: result[:total_batches],
      batch_size: result[:batch_size],
      sync_type: result[:sync_type],
      message: "Queued #{result[:total_batches]} batches for #{missing_reservation_ids.size} missing summaries",
    }
  else
    {
      success: false,
      restaurant_id: restaurant_id,
      restaurant_name: restaurant.name,
      error: result[:error] || 'Failed to queue batch jobs',
    }
  end
rescue StandardError => e
  {
    success: false,
    restaurant_id: restaurant_id,
    restaurant_name: restaurant&.name,
    error: "Sync failed: #{e.message}",
  }
end