Class: InventoryUpdater

Inherits:
Trailblazer::Operation
  • Object
show all
Extended by:
Contract::DSL
Defined in:
app/my_lib/inventory_updater.rb

Overview

typed: ignore frozen_string_literal: true

Constant Summary collapse

PrimaryAttributesForm =
ImmutableStruct.new(:restaurant_id, :start_date, :end_date, :start_time, :end_time,
                                            :quantity_available, :reason) do
  def errors
    @errors ||= ActiveModel::Errors.new(self)
  end
end
SettingsForm =
ImmutableStruct.new(:notify_staff)

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.update_in_bg(ids, quantity_available, inv_type) ⇒ Object



280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
# File 'app/my_lib/inventory_updater.rb', line 280

def self.update_in_bg(ids, quantity_available, inv_type)
  inv_model = inv_type.to_s == 'dine_in' ? Inventory : InventoryTakeAway
  restaurant_id = nil

  dates = []
  inv_model.where(id: ids).find_each do |inventory|
    restaurant_id = inventory.restaurant_id
    dates.push(inventory.date)
    inventory.update!(quantity_available: quantity_available)
  end

  if restaurant_id && dates.present?
    restaurant = Restaurant.fetch(restaurant_id)
    Karafka.producer.produce_async(
      topic: EVENTS::INVENTORY::CACHE::TOPIC,
      payload: {
        event_type: EVENTS::INVENTORY::CACHE::TYPES::RESET_CACHE,
        restaurant_id: restaurant.id,
        restaurant_level: true,
        dates: dates,
        class_name: 'InventoryUpdater',
        method_name: 'update_in_bg',
        triggered_at: Time.current.to_s,
        # Debug attributes
        trigger_context: {
          update_mode: 'background',
          dates_count: dates.count,
          restaurant_id: restaurant_id,
        },
        caller: Rails.backtrace_cleaner.clean(caller),
      }.to_json,
    )
    Rails.logger.info "Published cache reset event for restaurant #{restaurant.id}"
  end

  true
end

Instance Method Details

#_modify_params(options) ⇒ Object



46
47
48
49
50
51
52
53
# File 'app/my_lib/inventory_updater.rb', line 46

def _modify_params(options, *)
  options['params'] = if options['params'].respond_to?(:permit!)
                        options['params'].permit!.to_h.with_indifferent_access
                      else
                        options['params'].to_h.with_indifferent_access
                      end
  true
end

#_set_fail_message(options) ⇒ Object

set fail message for error handling



171
172
173
174
175
# File 'app/my_lib/inventory_updater.rb', line 171

def _set_fail_message(options, *)
  options['result.fail_message'] = errors.full_messages.to_sentence

  true
end

#_set_processing_mode(options) ⇒ Object

set processing mode based on time difference between start and end time if more than 2 hours, then do it on background



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'app/my_lib/inventory_updater.rb', line 81

def _set_processing_mode(options, *)
  start_date_time = Time.use_zone(restaurant.time_zone) do
    Time.zone.parse("#{model.start_date} #{model.start_time}")
  end
  end_date_time = Time.use_zone(restaurant.time_zone) do
    Time.zone.parse("#{model.end_date} #{model.end_time}")
  end
  options['processing_mode'] = if end_date_time - start_date_time <= 2.hours
                                 :jit
                               else
                                 :in_bg
                               end

  true
end

#_set_success_message(options) ⇒ Object

set success message based on processing mode



157
158
159
160
161
162
163
164
165
166
167
168
# File 'app/my_lib/inventory_updater.rb', line 157

def _set_success_message(options, *)
  case options['processing_mode']
  when :jit
    options['result.success_message'] = 'Seat allotment successfully updated'
  when :in_bg
    options['result.success_message'] = 'Your request is being processed, please check the result within few minutes'
  else
    raise(NotImplementedError)
  end

  true
end

#_update(options) ⇒ Object

update inventory based on the processing mode



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
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
# File 'app/my_lib/inventory_updater.rb', line 98

def _update(options, *)
  inv_type = options[:inventory_type] || 'dine_in'
  unless log_updated_inventory(model, inv_type)
    errors.add(:base, 'Something went wrong, unable to complete your request')
    return false
  end

  inv_to_be_updated = affected_inventories(model, inv_type)
  return true if inv_to_be_updated.count.zero?

  case options['processing_mode']
  when :jit
    # update inventory just-in-time
    affected_invs = update_jit(inv_to_be_updated, model.quantity_available, inv_type)
    # to update the inventories.total_booked_seat
    InventoryReservationWorker.perform_async(model.restaurant_id, model.start_date, model.end_date)

    # convert affected_invs to datetimes format
    dates = affected_invs.map do |inv|
      inv.date
    end

    Karafka.producer.produce_async(
      topic: EVENTS::INVENTORY::CACHE::TOPIC,
      payload: {
        event_type: EVENTS::INVENTORY::CACHE::TYPES::RESET_CACHE,
        restaurant_id: restaurant.id,
        restaurant_level: true,
        dates: dates,
        class_name: 'InventoryUpdater',
        triggered_at: Time.current.to_s,
        # Debug attributes
        trigger_method: 'update_jit',
        trigger_context: {
          update_mode: 'immediate',
          affected_inventories_count: affected_invs.count,
        },
        caller: Rails.backtrace_cleaner.clean(caller),
      }.to_json,
    )
    Rails.logger.info "Published cache reset event for restaurant #{restaurant.id}"

    # schedule a worker to notify GetYourGuide about the inventory update
    ::Vendors::Getyourguide::NotifyWorker.perform_async([restaurant.id])

    send_update_jit_inventory_event(restaurant, options['params'])

    return true
  when :in_bg
    # update inventory in background if time difference is more than 2 hours
    Inventory::UpdateInBgWorker.perform_async(inv_to_be_updated.pluck(:id), model.quantity_available, inv_type)
  else
    raise(NotImplementedError)
  end

  true
end

#_validate(options) ⇒ Object

validate the input against the contract



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'app/my_lib/inventory_updater.rb', line 56

def _validate(options, *)
  options['model.default'] = form = PrimaryAttributesForm.new(options['params'])
  validator = options['contract.default.class'].new(form)
  validator.validate(options['params'])
  if validator.valid?
    start_date_time = Time.use_zone(restaurant.time_zone) do
      Time.zone.parse("#{model.start_date} #{model.start_time}")
    end
    end_date_time = Time.use_zone(restaurant.time_zone) do
      Time.zone.parse("#{model.end_date} #{model.end_time}")
    end
    if start_date_time >= end_date_time
      errors.add(:base, 'Invalid time')
      return false
    end

    return true
  end

  errors.add(:base, validator.errors.full_messages.to_sentence)
  false
end