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!(line_item, seat_selections) ⇒ Object



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

def build_guests!(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
end

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



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
# File 'app/interactors/spree_cm_commissioner/transit/draft_order_creator.rb', line 63

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!(line_item, seat_selections)

    line_item
  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.



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

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)
    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)


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

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

  from_date = date.to_datetime.change(hour: departure_time.hour, min: departure_time.min, sec: 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
# 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
end