Class: SpreeCmCommissioner::TransitOrder::Create

Inherits:
Object
  • Object
show all
Includes:
Spree::ServiceModule::Base
Defined in:
app/services/spree_cm_commissioner/transit_order/create.rb

Instance Method Summary collapse

Instance Method Details

#build_guests_for!(line_item, seat_selections) ⇒ Object



102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'app/services/spree_cm_commissioner/transit_order/create.rb', line 102

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, connected_trip_id = nil) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'app/services/spree_cm_commissioner/transit_order/create.rb', line 70

def build_line_items_for!(leg, order, date, connected_trip_id = nil)
  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|
     = {
      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
    }
    [:connected_trip_id] = connected_trip_id if connected_trip_id.present?

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

    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.



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'app/services/spree_cm_commissioner/transit_order/create.rb', line 52

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

  # Use main_trip_id for connected trips (when legs have multiple trips)
  connected_trip_id = legs.size > 1 ? legs.first.main_trip_id&.to_s : nil

  legs.each do |leg|
    leg_line_items = build_line_items_for!(leg, order, current_leg_date, connected_trip_id)
    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)


127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'app/services/spree_cm_commissioner/transit_order/create.rb', line 127

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

#call(outbound_date:, inbound_date:, outbound_legs:, inbound_legs: [], user: nil) ⇒ Object



19
20
21
22
23
24
25
26
27
28
# File 'app/services/spree_cm_commissioner/transit_order/create.rb', line 19

def call(outbound_date:, inbound_date:, outbound_legs:, inbound_legs: [], user: nil)
  return failure(nil, 'Outbound legs are missing') if outbound_legs.blank?

  begin
    order = create_order!(outbound_date, inbound_date, outbound_legs, inbound_legs, user)
    success(order: order)
  rescue StandardError => e
    failure(nil, e.message)
  end
end

#create_order!(outbound_date, inbound_date, outbound_legs, inbound_legs, user) ⇒ Object

Raises:

  • (StandardError)


30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'app/services/spree_cm_commissioner/transit_order/create.rb', line 30

def create_order!(outbound_date, inbound_date, outbound_legs, inbound_legs, user)
  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

  trip_ids = (outbound_legs.map(&:trip_id) + inbound_legs.map(&:trip_id)).uniq
  order.preload_trip_ids = trip_ids

  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



116
117
118
119
120
121
122
123
124
125
# File 'app/services/spree_cm_commissioner/transit_order/create.rb', line 116

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

    guest.saved_guest = @saved_guests[index]
  end

  line_items
end