Class: VendorsService::InventorySync::RestaurantService

Inherits:
Object
  • Object
show all
Includes:
ElasticAPM::SpanHelpers, SupplierConfig
Defined in:
app/services/vendors_service/inventory_sync/restaurant_service.rb

Overview

Service for syncing restaurant inventory from external suppliers (Tablecheck, SevenRooms).

This service encapsulates all business logic for inventory sync, including:

  • Fetching timetables from the supplier via InventoryFetcherService

  • Importing and deleting inventory records in batches with retry logic

  • Triggering reservation workers and cache invalidation

  • Sending inventory events to HH-Search via Kafka

  • Error handling and reporting to APM (APMErrorHandler.report)

  • Logging business context and technical details in JSON format for OpenSearch (BUSINESS_LOGGER)

  • ElasticAPM instrumentation for tracing and performance monitoring

  • Centralized supplier validation logic via SUPPLIER_CONFIG

Examples:

Usage

service = VendorsService::InventorySync::RestaurantService.new(
  restaurant_id: 123,
  start_date: "2025-01-15",
  end_date: "2025-01-20",
  supplier: :tablecheck
)
result = service.call # => true on success, raises on failure

Constant Summary

Constants included from SupplierConfig

SupplierConfig::SUPPLIER_CONFIG

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from SupplierConfig

#get_supplier_config

Constructor Details

#initialize(restaurant_id:, start_date:, end_date:, supplier:) ⇒ RestaurantService

Returns a new instance of RestaurantService.



30
31
32
33
34
35
36
37
38
39
# File 'app/services/vendors_service/inventory_sync/restaurant_service.rb', line 30

def initialize(restaurant_id:, start_date:, end_date:, supplier:)
  @restaurant_id = restaurant_id
  @restaurant = Restaurant.fetch(restaurant_id)
  @restaurant_tz = Time.find_zone(restaurant.time_zone)
  @start_date = start_date.to_s
  @end_date = end_date.to_s
  @supplier = supplier.to_sym
  @config = get_supplier_config(supplier, restaurant_id: restaurant_id)
  validate_supplier_restaurant!
end

Instance Attribute Details

#configObject (readonly)

Returns the value of attribute config.



28
29
30
# File 'app/services/vendors_service/inventory_sync/restaurant_service.rb', line 28

def config
  @config
end

#end_dateObject (readonly)

Returns the value of attribute end_date.



28
29
30
# File 'app/services/vendors_service/inventory_sync/restaurant_service.rb', line 28

def end_date
  @end_date
end

#restaurantObject (readonly)

Returns the value of attribute restaurant.



28
29
30
# File 'app/services/vendors_service/inventory_sync/restaurant_service.rb', line 28

def restaurant
  @restaurant
end

#restaurant_idObject (readonly)

Returns the value of attribute restaurant_id.



28
29
30
# File 'app/services/vendors_service/inventory_sync/restaurant_service.rb', line 28

def restaurant_id
  @restaurant_id
end

#restaurant_tzObject (readonly)

Returns the value of attribute restaurant_tz.



28
29
30
# File 'app/services/vendors_service/inventory_sync/restaurant_service.rb', line 28

def restaurant_tz
  @restaurant_tz
end

#start_dateObject (readonly)

Returns the value of attribute start_date.



28
29
30
# File 'app/services/vendors_service/inventory_sync/restaurant_service.rb', line 28

def start_date
  @start_date
end

#supplierObject (readonly)

Returns the value of attribute supplier.



28
29
30
# File 'app/services/vendors_service/inventory_sync/restaurant_service.rb', line 28

def supplier
  @supplier
end

Instance Method Details

#callBoolean

Main entry point for syncing inventory.

Performs complete inventory sync including validation, fetching, database operations, and post-sync activities (workers, cache invalidation, HH-Search events).

Returns:

  • (Boolean)

    true on success

Raises:



50
51
52
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
# File 'app/services/vendors_service/inventory_sync/restaurant_service.rb', line 50

def call
  context_attrs = {
    restaurant_id: restaurant_id,
    start_date: start_date,
    end_date: end_date,
    supplier: supplier,
  }

  BUSINESS_LOGGER.set_business_context(context_attrs)

  BUSINESS_LOGGER.info("#{self.class}: started")

  start_date_obj = Date.parse(start_date)
  end_date_obj = Date.parse(end_date)

  timetable_data = fetch_timetable(start_date, end_date)
  if timetable_data.blank?
    BUSINESS_LOGGER.info("#{self.class}: No timetable found, deleting existing inventory")
  end
  sync_inventory(timetable_data, start_date_obj, end_date_obj)

  true
rescue VendorsService::InventorySync::InventoryFetcherService::SupplierApiError,
       VendorsService::InventorySync::InventoryFetcherService::RateLimitExceededError,
       StandardError => e
  error_message = "#{self.class} #{supplier.capitalize}: #{e.message}"
  APMErrorHandler.report(error_message, exception: e, context: context_attrs)
  BUSINESS_LOGGER.error(
    error_message, {
      exception: e.class.name,
      message: e.message,
      backtrace: e.backtrace&.first(5),
    }
  )
  raise e
end