spree_cm_commissioner 2.5.1.pre.pre1 → 2.5.1.pre.pre2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/app/controllers/spree/admin/guests_controller.rb +5 -5
  4. data/app/controllers/spree/api/chatrace/check_ins_controller.rb +6 -4
  5. data/app/controllers/spree/api/chatrace/guests_controller.rb +5 -18
  6. data/app/controllers/spree/api/v2/operator/check_in_bulks_controller.rb +6 -5
  7. data/app/controllers/spree/api/v2/operator/check_in_sessions_controller.rb +32 -0
  8. data/app/controllers/spree/api/v2/operator/check_ins_controller.rb +5 -5
  9. data/app/controllers/spree/api/v2/operator/event_qrs_controller.rb +2 -0
  10. data/app/controllers/spree/api/v2/storefront/popular_route_places_controller.rb +1 -1
  11. data/app/controllers/spree/api/v2/storefront/self_check_in_controller.rb +7 -7
  12. data/app/controllers/spree/api/v2/storefront/transit/draft_orders_controller.rb +4 -4
  13. data/app/controllers/spree/api/v2/tenant/popular_route_places_controller.rb +60 -0
  14. data/app/controllers/spree/api/v2/tenant/routes_controller.rb +50 -0
  15. data/app/controllers/spree/api/v2/tenant/transit/draft_orders_controller.rb +46 -0
  16. data/app/controllers/spree/events/guests_controller.rb +9 -10
  17. data/app/controllers/spree/transit/trips_controller.rb +3 -3
  18. data/app/finders/spree_cm_commissioner/places/find_with_route.rb +12 -12
  19. data/app/finders/spree_cm_commissioner/route_metrics/find_popular.rb +44 -0
  20. data/app/finders/spree_cm_commissioner/routes/find.rb +94 -0
  21. data/app/finders/spree_cm_commissioner/routes/find_popular.rb +20 -35
  22. data/app/interactors/spree_cm_commissioner/event_qr_generator.rb +2 -1
  23. data/app/interactors/spree_cm_commissioner/stock/permanent_inventory_items_generator.rb +11 -4
  24. data/app/interactors/spree_cm_commissioner/stock/stock_movement_creator.rb +10 -1
  25. data/app/interactors/spree_cm_commissioner/trip_clone_creator.rb +4 -3
  26. data/app/interactors/spree_cm_commissioner/trip_stops_creator.rb +2 -2
  27. data/app/jobs/spree_cm_commissioner/guests/preload_check_in_session_ids_job.rb +10 -0
  28. data/app/jobs/spree_cm_commissioner/route_metrics/decrease_trip_count_job.rb +10 -0
  29. data/app/jobs/spree_cm_commissioner/route_metrics/increase_fulfilled_order_count_job.rb +10 -0
  30. data/app/jobs/spree_cm_commissioner/route_metrics/increase_order_count_job.rb +10 -0
  31. data/app/jobs/spree_cm_commissioner/route_metrics/increase_trip_count_job.rb +10 -0
  32. data/app/jobs/spree_cm_commissioner/stock/permanent_inventory_items_generator_job.rb +2 -2
  33. data/app/models/concerns/spree_cm_commissioner/route_order_countable.rb +2 -2
  34. data/app/models/spree_cm_commissioner/check_in.rb +34 -7
  35. data/app/models/spree_cm_commissioner/check_in_session.rb +8 -3
  36. data/app/models/spree_cm_commissioner/guest.rb +60 -28
  37. data/app/models/spree_cm_commissioner/guest_dynamic_field.rb +2 -2
  38. data/app/models/spree_cm_commissioner/place.rb +5 -8
  39. data/app/models/spree_cm_commissioner/pricing_actions/create_guest_adjustments.rb +52 -0
  40. data/app/models/spree_cm_commissioner/pricing_actions/create_line_item_adjustments.rb +6 -0
  41. data/app/models/spree_cm_commissioner/pricing_rule.rb +4 -0
  42. data/app/models/spree_cm_commissioner/pricing_rules/age_group.rb +45 -0
  43. data/app/models/spree_cm_commissioner/pricing_rules/nationality.rb +21 -2
  44. data/app/models/spree_cm_commissioner/pricing_rules/nationality_group.rb +41 -0
  45. data/app/models/spree_cm_commissioner/product_decorator.rb +1 -0
  46. data/app/models/spree_cm_commissioner/route.rb +46 -5
  47. data/app/models/spree_cm_commissioner/route_metric.rb +21 -0
  48. data/app/models/spree_cm_commissioner/route_photo.rb +12 -0
  49. data/app/models/spree_cm_commissioner/taxon_decorator.rb +1 -0
  50. data/app/models/spree_cm_commissioner/trip.rb +8 -33
  51. data/app/models/spree_cm_commissioner/trip_stop.rb +16 -2
  52. data/app/models/spree_cm_commissioner/vendor_decorator.rb +3 -1
  53. data/app/queries/spree_cm_commissioner/trip_query.rb +2 -2
  54. data/app/serializers/spree/v2/tenant/transit_cart_serializer.rb +11 -0
  55. data/app/serializers/spree_cm_commissioner/v2/operator/check_in_serializer.rb +1 -2
  56. data/app/serializers/spree_cm_commissioner/v2/operator/check_in_session_serializer.rb +9 -0
  57. data/app/serializers/spree_cm_commissioner/v2/operator/guest_serializer.rb +1 -1
  58. data/app/serializers/spree_cm_commissioner/v2/storefront/guest_serializer.rb +2 -1
  59. data/app/serializers/spree_cm_commissioner/v2/storefront/route_serializer.rb +3 -1
  60. data/app/serializers/spree_cm_commissioner/v2/storefront/transit_line_item_serializer.rb +17 -0
  61. data/app/serializers/spree_cm_commissioner/v2/storefront/trip_stop_serializer.rb +1 -1
  62. data/app/services/spree_cm_commissioner/check_ins/create_bulk.rb +65 -0
  63. data/app/services/spree_cm_commissioner/check_ins/destroy_bulk.rb +54 -0
  64. data/app/services/spree_cm_commissioner/guests/preload_check_in_session_ids.rb +22 -0
  65. data/app/services/spree_cm_commissioner/pricing_models/create_with_rule_groups.rb +56 -0
  66. data/app/services/spree_cm_commissioner/pricing_models/update_with_rule_groups.rb +69 -0
  67. data/app/services/spree_cm_commissioner/pricing_rules/build_params.rb +16 -7
  68. data/app/services/spree_cm_commissioner/route_metrics/decrease_trip_count.rb +31 -0
  69. data/app/services/spree_cm_commissioner/{routes/increment_fulfilled_order_count.rb → route_metrics/increase_fulfilled_order_count.rb} +3 -3
  70. data/app/services/spree_cm_commissioner/{routes/increment_order_count.rb → route_metrics/increase_order_count.rb} +3 -3
  71. data/app/services/spree_cm_commissioner/route_metrics/increase_trip_count.rb +31 -0
  72. data/app/services/spree_cm_commissioner/{routes/base_update_order_metrics.rb → route_metrics/update_route_metrics.rb} +11 -16
  73. data/app/services/spree_cm_commissioner/routes/create.rb +51 -0
  74. data/app/services/spree_cm_commissioner/routes/update.rb +25 -0
  75. data/app/{interactors/spree_cm_commissioner/transit/draft_order_creator.rb → services/spree_cm_commissioner/transit_order/create.rb} +13 -16
  76. data/app/services/spree_cm_commissioner/trips/create_single_leg.rb +123 -0
  77. data/app/services/spree_cm_commissioner/trips/service_calendars/create_or_update.rb +54 -0
  78. data/app/services/spree_cm_commissioner/trips/update_single_leg.rb +88 -0
  79. data/app/services/spree_cm_commissioner/trips/variants/create.rb +103 -0
  80. data/app/views/spree/transit/trip_stops/index.html.erb +4 -2
  81. data/app/views/spree_cm_commissioner/guest_mailer/send_ticket_to_guest.html.erb +0 -1
  82. data/config/initializers/spree_permitted_attributes.rb +11 -0
  83. data/config/locales/en.yml +2 -0
  84. data/config/locales/km.yml +2 -0
  85. data/config/routes.rb +8 -0
  86. data/db/migrate/20251224033103_migrate_cm_routes_to_cm_route_metrics.rb +17 -0
  87. data/db/migrate/20251224033910_migrate_cm_vendor_routes_to_cm_routes.rb +30 -0
  88. data/db/migrate/20251225100000_add_age_group_to_cm_guests.rb +6 -0
  89. data/db/migrate/20260105024742_add_type_to_cm_pricing_actions.rb +11 -0
  90. data/db/migrate/20260105072450_migrate_cm_trip_stops_to_support_trip_connection.rb +12 -0
  91. data/db/migrate/20260108101406_add_allow_booking_to_cm_trips.rb +5 -0
  92. data/db/migrate/20260121024645_add_nationality_group_to_cm_guests.rb +5 -0
  93. data/docs/pricing_model/age_group.md +40 -0
  94. data/docs/pricing_model/nationality_group.md +35 -0
  95. data/lib/spree_cm_commissioner/test_helper/factories/check_in_factory.rb +3 -1
  96. data/lib/spree_cm_commissioner/test_helper/factories/check_in_session_factory.rb +26 -0
  97. data/lib/spree_cm_commissioner/test_helper/factories/guest_factory.rb +4 -0
  98. data/lib/spree_cm_commissioner/test_helper/factories/pricing_action_factory.rb +4 -0
  99. data/lib/spree_cm_commissioner/test_helper/factories/pricing_rule_factory.rb +45 -1
  100. data/lib/spree_cm_commissioner/test_helper/factories/route_factory.rb +7 -6
  101. data/lib/spree_cm_commissioner/test_helper/factories/route_metric_factory.rb +12 -0
  102. data/lib/spree_cm_commissioner/test_helper/factories/route_photo_factory.rb +5 -0
  103. data/lib/spree_cm_commissioner/test_helper/factories/trip_factory.rb +4 -1
  104. data/lib/spree_cm_commissioner/test_helper/factories/trip_stop_factory.rb +3 -1
  105. data/lib/spree_cm_commissioner/test_helper/factories/vendor_factory.rb +2 -0
  106. data/lib/spree_cm_commissioner/test_helper/factories/vendor_place_factory.rb +22 -0
  107. data/lib/spree_cm_commissioner/transit/route_stop.rb +61 -0
  108. data/lib/spree_cm_commissioner/transit/route_stop_collection.rb +175 -0
  109. data/lib/spree_cm_commissioner/transit/trip_form.rb +81 -0
  110. data/lib/spree_cm_commissioner/transit/trip_stop_form.rb +61 -0
  111. data/lib/spree_cm_commissioner/version.rb +1 -1
  112. data/lib/spree_cm_commissioner.rb +4 -0
  113. metadata +54 -20
  114. data/app/interactors/spree_cm_commissioner/check_in_bulk_creator.rb +0 -71
  115. data/app/interactors/spree_cm_commissioner/check_in_destroyer.rb +0 -43
  116. data/app/jobs/spree_cm_commissioner/transit/route_fulfilled_order_count_incrementer_job.rb +0 -10
  117. data/app/jobs/spree_cm_commissioner/transit/route_order_count_incrementer_job.rb +0 -10
  118. data/app/jobs/spree_cm_commissioner/transit/route_previous_trip_count_decrementer_job.rb +0 -13
  119. data/app/jobs/spree_cm_commissioner/transit/route_trip_count_decrementer_job.rb +0 -10
  120. data/app/jobs/spree_cm_commissioner/transit/route_trip_count_incrementer_job.rb +0 -10
  121. data/app/models/concerns/spree_cm_commissioner/route_trip_count_callbacks.rb +0 -48
  122. data/app/models/spree_cm_commissioner/trip_connection.rb +0 -36
  123. data/app/models/spree_cm_commissioner/vendor_route.rb +0 -9
  124. data/app/services/spree_cm_commissioner/routes/decrement_previous_trip_count.rb +0 -30
  125. data/app/services/spree_cm_commissioner/routes/decrement_trip_count.rb +0 -33
  126. data/app/services/spree_cm_commissioner/routes/increment_trip_count.rb +0 -33
  127. data/lib/spree_cm_commissioner/test_helper/factories/trip_connection_factory.rb +0 -6
@@ -1,11 +1,13 @@
1
1
  FactoryBot.define do
2
2
  factory :cm_transit_vendor, parent: :vendor do
3
+ from_email { FFaker::Internet.email } # required only when tenant exist.
3
4
  state { :active }
4
5
  primary_product_type { :transit }
5
6
  end
6
7
 
7
8
  factory :cm_vendor, parent: :vendor do
8
9
  sequence(:name) { |n| "#{FFaker::Company.name} #{n}#{Kernel.rand(9999)}" }
10
+ from_email { FFaker::Internet.email } # required only when tenant exist.
9
11
  state { :active }
10
12
  default_state_id { Spree::State.first&.id }
11
13
  primary_product_type { :ecommerce }
@@ -7,6 +7,17 @@ FactoryBot.define do
7
7
  position { FFaker::Number.number }
8
8
 
9
9
  place_type { :location }
10
+
11
+ transient do
12
+ place_name { nil }
13
+ end
14
+
15
+ before :create do |vendor_place, evaluator|
16
+ if evaluator.place_name.present?
17
+ vendor_place.place.name = evaluator.place_name
18
+ vendor_place.place.save!
19
+ end
20
+ end
10
21
  end
11
22
 
12
23
  factory :cm_vendor_place, class: SpreeCmCommissioner::VendorPlace do
@@ -30,5 +41,16 @@ FactoryBot.define do
30
41
  place_type { :location }
31
42
  location { nil }
32
43
  end
44
+
45
+ transient do
46
+ place_name { nil }
47
+ end
48
+
49
+ before :create do |vendor_place, evaluator|
50
+ if evaluator.place_name.present?
51
+ vendor_place.place.name = evaluator.place_name
52
+ vendor_place.place.save!
53
+ end
54
+ end
33
55
  end
34
56
  end
@@ -0,0 +1,61 @@
1
+ module SpreeCmCommissioner::Transit
2
+ class RouteStop
3
+ attr_accessor :location_id, :vendor_place_id, :type, :sequence, :vendor_place
4
+
5
+ STOP_TYPES = %i[branch stop].freeze
6
+
7
+ def initialize(options = {})
8
+ @location_id = options[:location_id]
9
+ @type = options[:type]&.to_sym
10
+ @sequence = options[:sequence]
11
+
12
+ # vendor place is either stop or branch
13
+ @vendor_place_id = options[:vendor_place_id]
14
+ end
15
+
16
+ def self.from_hash(hash)
17
+ hash = hash.symbolize_keys
18
+
19
+ new(
20
+ location_id: hash[:location_id],
21
+ vendor_place_id: hash[:vendor_place_id],
22
+ type: hash[:type],
23
+ sequence: hash[:sequence]
24
+ )
25
+ end
26
+
27
+ def to_h
28
+ {
29
+ location_id: @location_id,
30
+ vendor_place_id: @vendor_place_id,
31
+ type: @type,
32
+ sequence: @sequence
33
+ }
34
+ end
35
+
36
+ def branch?
37
+ @type == :branch
38
+ end
39
+
40
+ def stop?
41
+ @type == :stop
42
+ end
43
+
44
+ def valid?
45
+ errors.empty?
46
+ end
47
+
48
+ def errors
49
+ @errors ||= []
50
+ @errors.clear
51
+
52
+ @errors << 'location_id is required' if @location_id.blank?
53
+ @errors << 'vendor_place_id is required' if @vendor_place_id.blank?
54
+ @errors << 'type is required' if @type.blank?
55
+ @errors << 'type must be :branch or :stop' if @type.present? && STOP_TYPES.exclude?(@type)
56
+ @errors << 'sequence is required' if @sequence.nil?
57
+
58
+ @errors
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,175 @@
1
+ module SpreeCmCommissioner::Transit
2
+ class RouteStopCollection
3
+ include Enumerable
4
+
5
+ attr_reader :stops
6
+
7
+ def initialize(stops = [])
8
+ @stops = stops
9
+ @errors = []
10
+ end
11
+
12
+ def self.from_hash(array)
13
+ # Handle nil, empty array, or string "[]" when loaded from database
14
+ parsed_array = case array
15
+ when nil
16
+ []
17
+ when String
18
+ JSON.parse(array)
19
+ else
20
+ array
21
+ end
22
+
23
+ stops = Array(parsed_array).each_with_index.map do |raw, index|
24
+ hash = raw.to_h.symbolize_keys
25
+ RouteStop.from_hash(hash.merge(sequence: index))
26
+ end
27
+
28
+ new(stops)
29
+ end
30
+
31
+ def to_h
32
+ @stops.map(&:to_h)
33
+ end
34
+
35
+ def each(&block)
36
+ @stops.each(&block)
37
+ end
38
+
39
+ def [](index)
40
+ @stops[index]
41
+ end
42
+
43
+ def first
44
+ @stops.first
45
+ end
46
+
47
+ def last
48
+ @stops.last
49
+ end
50
+
51
+ def length
52
+ @stops.length
53
+ end
54
+
55
+ def empty?
56
+ @stops.empty?
57
+ end
58
+
59
+ def multi_leg?
60
+ branch_location_ids = @stops.select(&:branch?).map(&:location_id).uniq
61
+ branch_location_ids.length >= 3
62
+ end
63
+
64
+ def by_location
65
+ @stops.group_by(&:location_id)
66
+ end
67
+
68
+ # Fetches vendor places and groups route stops by their location object
69
+ # Returns: { location_obj => [route_stop_a, route_stop_b], location_obj_2 => [...] }
70
+ # Example: If you have stops for branches in "Bangkok" and "Chiang Mai",
71
+ # this returns all stops grouped by their location object
72
+ def by_location_with_data
73
+ return {} if @stops.empty?
74
+
75
+ # Extract unique vendor_place_ids from all stops
76
+ vendor_place_ids = @stops.map(&:vendor_place_id).compact.uniq
77
+ return {} if vendor_place_ids.empty?
78
+
79
+ # Single query: fetch all vendor places with their locations
80
+ # index_by(:id) creates a hash for O(1) lookup: { vendor_place_id => vendor_place_obj }
81
+ vendor_places = SpreeCmCommissioner::VendorPlace.where(id: vendor_place_ids).includes(:location).index_by(&:id)
82
+
83
+ grouped = {}
84
+ @stops.each do |stop|
85
+ # Set the vendor_place object on the stop for later use
86
+ stop.vendor_place = vendor_places[stop.vendor_place_id]
87
+
88
+ # Get the location from the vendor_place (e.g., "Bangkok" location)
89
+ location = stop.vendor_place&.location
90
+ next if location.nil?
91
+
92
+ # Group stops by location object
93
+ grouped[location] ||= []
94
+ grouped[location] << stop
95
+ end
96
+
97
+ grouped
98
+ end
99
+
100
+ # Groups route stops by their location in sequence order
101
+ # Returns an array of hashes where each hash contains:
102
+ # - location: the VendorPlace representing the location
103
+ # - stops: array of route stops at that location, sorted by sequence
104
+ # Example usage: @stops.group_by_sequence
105
+ # {
106
+ # location_object_1 => [stop1, stop2, stop3],
107
+ # location_object_2 => [stop4, stop5]
108
+ # }
109
+ # Stop 0: Location A
110
+ # Stop 1: Location A
111
+ # Stop 2: Location B
112
+ # Stop 3: Location A ← Same location again (For case when the bus has the same origin/destination)
113
+ def group_by_sequence
114
+ return [] if @stops.blank?
115
+
116
+ by_location = by_location_with_data || {}
117
+
118
+ # location_id => location_vendor_place (the "location" vendor_place in the hash key)
119
+ location_by_id = by_location.keys.index_by(&:id)
120
+
121
+ ordered_stops =
122
+ by_location.values
123
+ .flatten
124
+ .compact
125
+ .sort_by { |s| s.sequence.to_i }
126
+
127
+ grouped_stops = []
128
+ current_location_id = nil
129
+ current_group = nil
130
+
131
+ ordered_stops.each do |stop|
132
+ stop_location_id = stop.location_id
133
+
134
+ if stop_location_id != current_location_id
135
+ current_location_id = stop_location_id
136
+ current_group = {
137
+ location: location_by_id[stop_location_id],
138
+ stops: []
139
+ }
140
+ grouped_stops << current_group
141
+ end
142
+
143
+ current_group[:stops] << stop
144
+ end
145
+
146
+ grouped_stops
147
+ end
148
+
149
+ def valid?
150
+ errors.empty?
151
+ end
152
+
153
+ def errors
154
+ @errors = []
155
+
156
+ # Check each stop is valid
157
+ @stops.each_with_index do |stop, index|
158
+ next if stop.valid?
159
+
160
+ stop.errors.each do |error|
161
+ @errors << "Stop #{index}: #{error}"
162
+ end
163
+ end
164
+
165
+ # Check for duplicate vendor_place_ids
166
+ vendor_place_ids = @stops.map(&:vendor_place_id)
167
+ duplicates = vendor_place_ids.tally.select { |_, count| count > 1 }.keys
168
+ duplicates.each do |dup_id|
169
+ @errors << "vendor_place_id #{dup_id} appears more than once"
170
+ end
171
+
172
+ @errors
173
+ end
174
+ end
175
+ end
@@ -0,0 +1,81 @@
1
+ module SpreeCmCommissioner::Transit
2
+ class TripForm
3
+ include ActiveModel::Model
4
+
5
+ attr_accessor :route_id,
6
+ :name,
7
+ :short_name,
8
+ :price,
9
+ :allow_booking,
10
+ :allow_seat_selection,
11
+ :route_type,
12
+ :trip_stops, # TripStopForm[]
13
+ :service_calendar # monday, tuesday, wednesday, thursday, friday, saturday, sunday, start_date, end_date
14
+
15
+ def multi_leg?
16
+ trip_stops.map(&:location_id).uniq.size > 2
17
+ end
18
+
19
+ def total_duration_seconds
20
+ return 0 if trip_stops.size < 2
21
+
22
+ minutes = trip_stops[0...-1].sum { |s| s.duration_in_minutes || 0 }
23
+ minutes * 60
24
+ end
25
+
26
+ def valid_data? # rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
27
+ errors.clear
28
+
29
+ errors.add(:route_id, 'must be present') if route_id.blank?
30
+ errors.add(:trip_stops, 'must be present') if trip_stops.blank? || trip_stops.size < 2
31
+
32
+ first_stop = trip_stops&.first
33
+ last_stop = trip_stops&.last
34
+
35
+ errors.add(:trip_stops, 'first stop must allow boarding') unless first_stop&.allow_boarding?
36
+ errors.add(:trip_stops, 'last stop must allow drop off') unless last_stop&.allow_drop_off
37
+ errors.add(:departure_time, 'missing on first stop') if first_stop&.departure_time.blank?
38
+
39
+ errors.empty?
40
+ end
41
+
42
+ # Groups trip_stops into legs by location changes
43
+ # Separates legs when location_id changes (at branch stops)
44
+ # Break stops (stop_type = :stop) are included but don't trigger separation
45
+ #
46
+ # Example:
47
+ # [PP1, PP2, PTT1(break stop), BTB1, BTB2, PPT2(break stop), POIPET1, POIPET1]
48
+ #
49
+ # Output (legs):
50
+ # [
51
+ # [PP1, PP2, PTT, BTB1, BTB2],
52
+ # [BTB1, BTB2, PPT1, POIPET1, POIPET1]
53
+ # ]
54
+ def trip_stops_grouped_by_leg(stops)
55
+ return [] if trip_stops.empty?
56
+
57
+ legs = []
58
+ current_leg = []
59
+ last_location_id = nil
60
+
61
+ trip_stops.each do |trip_stop|
62
+ stop = stops[trip_stop.stop_id]
63
+
64
+ # If location changed and we have stops in current leg, start a new leg
65
+ current_leg << trip_stop
66
+ if last_location_id.present? && last_location_id != trip_stop.location_id && current_leg.any?
67
+ # Include the first stop of new location in previous leg
68
+ legs << current_leg
69
+ current_leg = [trip_stop]
70
+ end
71
+
72
+ # Update location only for branch stops (not for "just stops")
73
+ last_location_id = trip_stop.location_id if stop.branch?
74
+ end
75
+
76
+ # Add final leg if it has stops
77
+ legs << current_leg if current_leg.any?
78
+ legs
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,61 @@
1
+ module SpreeCmCommissioner::Transit
2
+ class TripStopForm
3
+ attr_accessor :location_id,
4
+ :stop_id,
5
+ :departure_time,
6
+ :duration_in_hours,
7
+ :route_type,
8
+ #
9
+ # when create, vehicle_type_id is required. But if board_to_trip_id present (from another route), we can copy from that trip.
10
+ # when edit, vehicle_type_id can be changed since we already copied the seat layout.
11
+ :vehicle_type_id,
12
+ #
13
+ # (optional), same as vehicle_type_id.
14
+ :vehicle_id,
15
+ #
16
+ # when create:
17
+ # if board_to_trip_id present, it mean it link to another trip to board.
18
+ #
19
+ # when edit:
20
+ # board_to_trip_id can't be set to nil or changed to another trip id.
21
+ :board_to_trip_id,
22
+ #
23
+ # for first stop, allow_boarding must be true.
24
+ # for last stop, allow_boarding must be false.
25
+ # for middle stops, both can be true/false.
26
+ #
27
+ # but when stop.type is not branch (eg. stop), allow_boarding must be false.
28
+ :allow_boarding,
29
+ #
30
+ # for first stop, allow_drop_off must be false.
31
+ # for last stop, allow_drop_off must be true.
32
+ # for middle stops, both can be true/false.
33
+ #
34
+ # but when stop.type is not branch (eg. stop), allow_drop_off must be false.
35
+ :allow_drop_off,
36
+ #
37
+ # when stop.type is branch, admin can toggle allow_seat_selection.
38
+ # but for edit, if board_to_trip_id is from another route, allow_seat_selection can't be changed.
39
+ # only allow changed from its own route.
40
+ :allow_seat_selection,
41
+ #
42
+ # when create, allow_booking only when stop.type is branch, use it to assign to create sub-trip.
43
+ # but for edit, if board_to_trip_id is from another route, allow_booking can't be changed.
44
+ # only allow changed from its own route.
45
+ :allow_booking,
46
+ :sequence,
47
+ #
48
+ # set from create service
49
+ :vendor_id
50
+
51
+ def allow_boarding?
52
+ ActiveModel::Type::Boolean.new.cast(allow_boarding)
53
+ end
54
+
55
+ def duration_in_minutes
56
+ return nil if duration_in_hours.blank?
57
+
58
+ (duration_in_hours.to_f * 60).to_i
59
+ end
60
+ end
61
+ end
@@ -1,5 +1,5 @@
1
1
  module SpreeCmCommissioner
2
- VERSION = '2.5.1-pre1'.freeze
2
+ VERSION = '2.5.1.pre.pre2'.freeze
3
3
 
4
4
  module_function
5
5
 
@@ -23,6 +23,10 @@ require 'spree_cm_commissioner/trip_query_result'
23
23
  require 'spree_cm_commissioner/cached_inventory_item'
24
24
  require 'spree_cm_commissioner/transit/leg'
25
25
  require 'spree_cm_commissioner/transit/seat_selection'
26
+ require 'spree_cm_commissioner/transit/route_stop'
27
+ require 'spree_cm_commissioner/transit/route_stop_collection'
28
+ require 'spree_cm_commissioner/transit/trip_form'
29
+ require 'spree_cm_commissioner/transit/trip_stop_form'
26
30
  require 'spree_cm_commissioner/intercity_taxi/map_place'
27
31
  require 'spree_cm_commissioner/distance'
28
32