Class: SpreeCmCommissioner::Transit::DraftOrderCreator

Inherits:
BaseInteractor
  • Object
show all
Defined in:
app/interactors/spree_cm_commissioner/transit/draft_order_creator.rb

Instance Method Summary collapse

Instance Method Details

#build_guests_for!(line_item, seat_selections) ⇒ Object



95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'app/interactors/spree_cm_commissioner/transit/draft_order_creator.rb', line 95

def build_guests_for!(line_item, seat_selections)
  block_ids = seat_selections.flat_map(&:block_ids)

  if block_ids.any? && block_ids.size != line_item.quantity
    raise StandardError, "Number of blocks (#{block_ids.size}) does not match quantity (#{line_item.quantity})"
  end

  Array.new(line_item.quantity) do |index|
    line_item.guests.new(block_id: block_ids[index])
  end

  line_item
end

#build_line_items_for!(leg, order, date) ⇒ Object



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/interactors/spree_cm_commissioner/transit/draft_order_creator.rb', line 66

def build_line_items_for!(leg, order, date)
  trip = SpreeCmCommissioner::Trip.find(leg.trip_id)
  trip_stops = trip.trip_stops.where(id: [leg.boarding_trip_stop_id, leg.drop_off_trip_stop_id]).index_by(&:id)

  from_date, to_date = calculate_line_item_duration!(
    date: date,
    departure_time: trip_stops[leg.boarding_trip_stop_id].departure_time,
    arrival_time: trip_stops[leg.drop_off_trip_stop_id].arrival_time
  )

  leg.seat_selections.group_by(&:variant_id).map do |variant_id, seat_selections|
    line_item = order.line_items.new(
      product_type: :transit,
      from_date: from_date,
      to_date: to_date,
      variant_id: variant_id,
      quantity: seat_selections.sum(&:quantity),
      private_metadata: {
        direction: leg.direction,
        trip_id: leg.trip_id.to_s,
        boarding_trip_stop_id: leg.boarding_trip_stop_id.to_s,
        drop_off_trip_stop_id: leg.drop_off_trip_stop_id.to_s
      }
    )

    build_guests_for!(line_item, seat_selections)
  end
end

#build_line_items_for_legs!(order:, legs:, initial_date:) ⇒ Object

Build line items for each leg, using the previous leg’s to_date as the next leg’s date, or the initial date for the first leg.



51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'app/interactors/spree_cm_commissioner/transit/draft_order_creator.rb', line 51

def build_line_items_for_legs!(order:, legs:, initial_date:)
  all_line_items = []
  current_leg_date = initial_date

  legs.each do |leg|
    leg_line_items = build_line_items_for!(leg, order, current_leg_date)
    leg_line_items = insert_saved_guests_per_line_items_leg(leg_line_items)

    all_line_items.concat(leg_line_items)
    current_leg_date = leg_line_items.last.to_date.to_date if leg_line_items.any?
  end

  all_line_items
end

#calculate_line_item_duration!(date:, departure_time:, arrival_time:) ⇒ Object

Raises:

  • (StandardError)


120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'app/interactors/spree_cm_commissioner/transit/draft_order_creator.rb', line 120

def calculate_line_item_duration!(date:, departure_time:, arrival_time:)
  raise StandardError, 'Departure or arrival time in trip stop is missing' if departure_time.blank? || arrival_time.blank?
  raise StandardError, 'Arrival time cannot be before departure time' if arrival_time < departure_time

  trip_duration_in_seconds = arrival_time - departure_time

  # The input `date` is in local time (e.g., 10-10-2022).
  # Combine it with the departure_time in Rails default timezone so that
  # the resulting from_date stays on the intended local calendar day when stored in UTC.
  from_date = Time.zone.local(date.year, date.month, date.day, departure_time.hour, departure_time.min, departure_time.sec)
  to_date = from_date + trip_duration_in_seconds.seconds

  [from_date, to_date]
end

#callObject



23
24
25
26
27
28
29
30
31
# File 'app/interactors/spree_cm_commissioner/transit/draft_order_creator.rb', line 23

def call
  return context.fail!(message: 'Outbound legs are missing') if outbound_legs.blank?

  begin
    context.order = create_order!
  rescue StandardError => e
    context.fail!(message: e.message)
  end
end

#create_order!Object

Raises:

  • (StandardError)


33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'app/interactors/spree_cm_commissioner/transit/draft_order_creator.rb', line 33

def create_order!
  order = Spree::Order.new(state: 'cart', use_billing: true, user: user)

  outbound_line_items = build_line_items_for_legs!(order: order, legs: outbound_legs, initial_date: outbound_date)
  inbound_line_items = inbound_legs.blank? ? [] : build_line_items_for_legs!(order: order, legs: inbound_legs, initial_date: inbound_date)

  outbound_qty = outbound_line_items.sum(&:quantity)
  inbound_qty = inbound_line_items.sum(&:quantity)

  raise StandardError, 'Outbound & inbound line item quantities do not match' if inbound_line_items.any? && outbound_qty != inbound_qty
  raise StandardError, order.errors.full_messages.to_sentence unless order.save

  order.update_with_updater!
  order
end

#insert_saved_guests_per_line_items_leg(line_items) ⇒ Object



109
110
111
112
113
114
115
116
117
118
# File 'app/interactors/spree_cm_commissioner/transit/draft_order_creator.rb', line 109

def insert_saved_guests_per_line_items_leg(line_items)
  line_items.flat_map(&:guests).each_with_index do |guest, index|
    context.saved_guests ||= []
    context.saved_guests << SpreeCmCommissioner::SavedGuest.new if context.saved_guests[index].blank?

    guest.saved_guest = context.saved_guests[index]
  end

  line_items
end