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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 161198a81f4cf2dff359256d58c277e0c493602378c854a7e8c937803b1c32fa
4
- data.tar.gz: 71c19403432925ce94cdde05447d7f64766a7f7dec3a6e6637c06fd4e0e83990
3
+ metadata.gz: 20effeac142fface8df473f26f1a62707092ee81066953512b51f0a021657fa0
4
+ data.tar.gz: 82ffb806998821e0432c86aaabbe664b87d076453419926c392935e55b11d517
5
5
  SHA512:
6
- metadata.gz: dab6644c7af312064a7bb5779306048b3b8984cc33caa50e369d4a5a63ee4ce6bce0534435096cfaebabcae924a3eca7c14ab47fae728059c2700092e6a1e5e8
7
- data.tar.gz: 5e15d12cfa4f27ff55bd03f0d415d2862839d6f0fac91d3e9c233f2bb3af18d60819b20d6ae776d31115f437c71c7ae3029c306e1d58a9ae5268004b9f4d162d
6
+ metadata.gz: 944769159e8f13b6be0cfb8fda0929fb2ef5c19716c882aa7cfa0a16847820e19657e52cc50f831995c85a24299cb73f6d346a82f08483f702461f20f81199ea
7
+ data.tar.gz: fd28f9f3960e2bd0967e42d91f0434165f383fedf3c0e330fd812cce1a2ccea2921e1f07e380bbf8bd426a2e18adb5732974322b2083f2578b160cb57bd480f1
data/Gemfile.lock CHANGED
@@ -34,7 +34,7 @@ GIT
34
34
  PATH
35
35
  remote: .
36
36
  specs:
37
- spree_cm_commissioner (2.5.1.pre.pre1)
37
+ spree_cm_commissioner (2.5.1.pre.pre2)
38
38
  activerecord-multi-tenant
39
39
  activerecord_json_validator (~> 2.1, >= 2.1.3)
40
40
  aws-sdk-cloudfront
@@ -47,8 +47,8 @@ module Spree
47
47
  end
48
48
 
49
49
  def check_in
50
- result = SpreeCmCommissioner::CheckInBulkCreator.call(
51
- check_ins_attributes: [{ guest_id: @guest.id }],
50
+ result = SpreeCmCommissioner::CheckIns::CreateBulk.call(
51
+ check_ins_attributes: [{ guest_id: @guest.id, check_in_session_id: params[:check_in_session_id] }],
52
52
  check_in_by: spree_current_user
53
53
  )
54
54
 
@@ -62,15 +62,15 @@ module Spree
62
62
  end
63
63
 
64
64
  def uncheck_in
65
- result = SpreeCmCommissioner::CheckInDestroyer.call(
66
- guest_ids: [@guest.id],
65
+ result = SpreeCmCommissioner::CheckIns::DestroyBulk.call(
66
+ check_ins_attributes: [{ guest_id: @guest.id, check_in_session_id: params[:check_in_session_id] }],
67
67
  destroyed_by: spree_current_user
68
68
  )
69
69
 
70
70
  if result.success?
71
71
  flash[:success] = "Guest #{@guest.full_name} has been unchecked."
72
72
  else
73
- flash[:error] = result.message.to_s.titleize
73
+ flash[:error] = result.error.to_s
74
74
  end
75
75
 
76
76
  redirect_to collection_url
@@ -7,12 +7,14 @@ module Spree
7
7
  end
8
8
 
9
9
  def create
10
- context = SpreeCmCommissioner::CheckInBulkCreator.call(check_ins_attributes: [{ guest_id: guest.id }])
10
+ result = SpreeCmCommissioner::CheckIns::CreateBulk.call(
11
+ check_ins_attributes: [{ guest_id: guest.id, check_in_session_id: params[:check_in_session_id] }]
12
+ )
11
13
 
12
- if context.success?
13
- render json: { checked_in_at: context.check_ins[0].confirmed_at }, status: :ok
14
+ if result.success?
15
+ render json: { checked_in_at: result.value[:check_ins][0].confirmed_at }, status: :ok
14
16
  else
15
- render_error_payload(context.message)
17
+ render_error_payload(result.error)
16
18
  end
17
19
  end
18
20
  end
@@ -31,17 +31,11 @@ module Spree
31
31
  guest.guest_dynamic_fields
32
32
  .includes(:dynamic_field)
33
33
  .to_h do |gdf|
34
- label = gdf.dynamic_field.label.to_s.strip
35
- key =
36
- if label.ascii_only?
37
- label.parameterize(separator: '_')
38
- else
39
- label
40
- end
34
+ key = gdf.dynamic_field.label
35
+ .parameterize
36
+ .underscore
41
37
 
42
- value = gdf.value.strip
43
-
44
- [key, value]
38
+ [key, gdf.value]
45
39
  end
46
40
  end
47
41
 
@@ -55,13 +49,6 @@ module Spree
55
49
  dob: guest.dob,
56
50
  gender: guest.gender,
57
51
  age: guest.age,
58
- nationality_id: guest.nationality_id,
59
- emergency_contact: guest.emergency_contact,
60
- guest_phone_number: guest.phone_number,
61
- guest_contact: guest.contact,
62
- guest_social_contact: guest.social_contact,
63
- address: guest.address,
64
- guest_id_card: guest.id_card,
65
52
  occupation: guest.occupation&.name || guest.other_occupation,
66
53
  entry_type: guest.entry_type,
67
54
  organization: guest.other_organization,
@@ -73,7 +60,7 @@ module Spree
73
60
  order_first_name: order.customer_address&.firstname,
74
61
  order_last_name: order.customer_address&.lastname,
75
62
  order_phone_number: order.intel_phone_number || order.customer_address&.phone,
76
- checked_in_at: guest.check_in&.confirmed_at,
63
+ checked_in_at: guest.earliest_check_in&.created_at,
77
64
  qr_data: guest.qr_data,
78
65
  order_qr_data: order.qr_data,
79
66
  country_code: guest.country_code,
@@ -13,22 +13,22 @@ module Spree
13
13
  if params[:check_ins].present?
14
14
  check_ins = process_check_ins(params[:check_ins])
15
15
  elsif params[:guest_ids].present?
16
- check_ins = params[:guest_ids].map { |guest_id| { guest_id: guest_id } }
16
+ check_ins = params[:guest_ids].map { |guest_id| { guest_id: guest_id, check_in_session_id: params[:check_in_session_id] } }
17
17
  end
18
18
 
19
- context = SpreeCmCommissioner::CheckInBulkCreator.call(
19
+ result = SpreeCmCommissioner::CheckIns::CreateBulk.call(
20
20
  check_ins_attributes: check_ins,
21
21
  check_in_by: spree_current_user
22
22
  )
23
23
 
24
- if context.success?
24
+ if result.success?
25
25
  render_serialized_payload(201) do
26
26
  collection_serializer.new(
27
- context.check_ins, { include: resource_includes }
27
+ result.value[:check_ins], { include: resource_includes }
28
28
  ).serializable_hash
29
29
  end
30
30
  else
31
- render_error_payload(context.message)
31
+ render_error_payload(result.error)
32
32
  end
33
33
  end
34
34
 
@@ -39,6 +39,7 @@ module Spree
39
39
  check_in.permit(
40
40
  :guest_id,
41
41
  :confirmed_at,
42
+ :check_in_session_id,
42
43
  guest_attributes: %i[
43
44
  first_name
44
45
  last_name
@@ -0,0 +1,32 @@
1
+ module Spree
2
+ module Api
3
+ module V2
4
+ module Operator
5
+ class CheckInSessionsController < ::Spree::Api::V2::ResourceController
6
+ before_action :require_spree_current_user, only: %i[index]
7
+ before_action :load_event, only: %i[index]
8
+
9
+ def collection
10
+ @collection ||= @event.active_check_in_sessions
11
+ end
12
+
13
+ def load_event
14
+ @event = Spree::Taxon.find(params[:event_id])
15
+ end
16
+
17
+ def model_class
18
+ SpreeCmCommissioner::CheckInSession
19
+ end
20
+
21
+ def resource_serializer
22
+ SpreeCmCommissioner::V2::Operator::CheckInSessionSerializer
23
+ end
24
+
25
+ def collection_serializer
26
+ SpreeCmCommissioner::V2::Operator::CheckInSessionSerializer
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -14,15 +14,15 @@ module Spree
14
14
  def create
15
15
  spree_authorize! :create, model_class
16
16
 
17
- context = SpreeCmCommissioner::CheckInBulkCreator.call(
18
- check_ins_attributes: [{ guest_id: params[:guest_id] }],
17
+ result = SpreeCmCommissioner::CheckIns::CreateBulk.call(
18
+ check_ins_attributes: [{ guest_id: params[:guest_id], check_in_session_id: params[:check_in_session_id] }],
19
19
  check_in_by: spree_current_user
20
20
  )
21
21
 
22
- if context.success?
23
- render_serialized_payload(201) { serialize_resource(context.check_ins[0]) }
22
+ if result.success?
23
+ render_serialized_payload(201) { serialize_resource(result.value[:check_ins][0]) }
24
24
  else
25
- render_error_payload(context.message)
25
+ render_error_payload(result.error)
26
26
  end
27
27
  end
28
28
 
@@ -10,6 +10,7 @@ module Spree
10
10
  context = SpreeCmCommissioner::EventQrGenerator.call(
11
11
  operator: spree_current_user,
12
12
  event: @event,
13
+ check_in_session: @check_in_session,
13
14
  expired_in_mn: params[:expired_in_mn]&.to_i || 5
14
15
  )
15
16
 
@@ -20,6 +21,7 @@ module Spree
20
21
 
21
22
  def load_event
22
23
  @event = Spree::Taxon.find(params[:id])
24
+ @check_in_session = (@event.check_in_sessions.find(params[:check_in_session_id]) if params[:check_in_session_id].present?)
23
25
  end
24
26
 
25
27
  # override
@@ -31,7 +31,7 @@ module Spree
31
31
 
32
32
  # override
33
33
  def collection_finder
34
- SpreeCmCommissioner::Routes::FindPopular
34
+ SpreeCmCommissioner::RouteMetrics::FindPopular
35
35
  end
36
36
 
37
37
  # override
@@ -26,24 +26,24 @@ module Spree
26
26
  return
27
27
  end
28
28
 
29
- context = create_check_in_records(params[:guest_ids])
29
+ result = create_check_in_records(params[:guest_ids], params[:check_in_session_id])
30
30
 
31
- if context.success?
31
+ if result.success?
32
32
  render_serialized_payload(201) do
33
33
  collection_serializer.new(
34
- context.check_ins, { include: resource_includes }
34
+ result.value[:check_ins], { include: resource_includes }
35
35
  ).serializable_hash
36
36
  end
37
37
  else
38
- render_error_payload(context.message)
38
+ render_error_payload(result.error)
39
39
  end
40
40
  end
41
41
 
42
42
  private
43
43
 
44
- def create_check_in_records(guest_ids)
45
- SpreeCmCommissioner::CheckInBulkCreator.call(
46
- check_ins_attributes: guest_ids.map { |guest_id| { guest_id: guest_id } },
44
+ def create_check_in_records(guest_ids, check_in_session_id)
45
+ SpreeCmCommissioner::CheckIns::CreateBulk.call(
46
+ check_ins_attributes: guest_ids.map { |guest_id| { guest_id: guest_id, check_in_session_id: check_in_session_id } },
47
47
  check_in_by: @operator
48
48
  )
49
49
  end
@@ -15,7 +15,7 @@ module Spree
15
15
  @outbound_legs = params[:outbound_legs].is_a?(Array) && params[:outbound_legs].any? ? build_legs(:outbound, params[:outbound_legs]) : []
16
16
  @inbound_legs = params[:inbound_legs].is_a?(Array) && params[:inbound_legs].any? ? build_legs(:inbound, params[:inbound_legs]) : []
17
17
 
18
- context = SpreeCmCommissioner::Transit::DraftOrderCreator.call(
18
+ result = SpreeCmCommissioner::TransitOrder::Create.call(
19
19
  outbound_date: params[:outbound_date]&.to_date,
20
20
  inbound_date: params[:inbound_date]&.to_date,
21
21
  outbound_legs: @outbound_legs,
@@ -23,10 +23,10 @@ module Spree
23
23
  user: spree_current_user
24
24
  )
25
25
 
26
- if context.success?
27
- render_serialized_payload { serialize_resource(context.order) }
26
+ if result.success?
27
+ render_serialized_payload { serialize_resource(result.value[:order]) }
28
28
  else
29
- render_error_payload(context.message)
29
+ render_error_payload(result.error)
30
30
  end
31
31
  end
32
32
 
@@ -0,0 +1,60 @@
1
+ module Spree
2
+ module Api
3
+ module V2
4
+ module Tenant
5
+ class PopularRoutePlacesController < BaseController
6
+ private
7
+
8
+ # override
9
+ def collection
10
+ @collection ||= collection_finder.new(
11
+ tenant: @tenant,
12
+ route_type: params[:route_type]
13
+ ).execute
14
+ end
15
+
16
+ # override
17
+ def default_resource_includes
18
+ %w[origin_place destination_place]
19
+ end
20
+
21
+ # override
22
+ def collection_finder
23
+ SpreeCmCommissioner::Routes::FindPopular
24
+ end
25
+
26
+ # override
27
+ def collection_serializer
28
+ resource_serializer
29
+ end
30
+
31
+ # override
32
+ def resource_serializer
33
+ SpreeCmCommissioner::V2::Storefront::RouteSerializer
34
+ end
35
+
36
+ # override
37
+ def serializer_params
38
+ super.merge(
39
+ include_vendors: include_vendors?,
40
+ include_nearby_places: include_nearby_places?
41
+ )
42
+ end
43
+
44
+ # override
45
+ def required_schema
46
+ SpreeCmCommissioner::PopularRoutePlacesRequestSchema
47
+ end
48
+
49
+ def include_vendors?
50
+ resource_includes.include?(:vendors) || false
51
+ end
52
+
53
+ def include_nearby_places?
54
+ resource_includes.include?(:nearby_places) || false
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,50 @@
1
+ module Spree
2
+ module Api
3
+ module V2
4
+ module Tenant
5
+ class RoutesController < BaseController
6
+ private
7
+
8
+ # override
9
+ def collection
10
+ @collection ||= collection_finder.new(
11
+ tenant: @tenant,
12
+ params: params
13
+ ).execute
14
+ end
15
+
16
+ # override
17
+ def collection_finder
18
+ SpreeCmCommissioner::Routes::Find
19
+ end
20
+
21
+ # override
22
+ def collection_serializer
23
+ SpreeCmCommissioner::V2::Storefront::RouteSerializer
24
+ end
25
+
26
+ # override
27
+ def serializer_params
28
+ super.merge(
29
+ include_vendors: include_vendors?,
30
+ include_nearby_places: include_nearby_places?
31
+ )
32
+ end
33
+
34
+ # override
35
+ def required_schema
36
+ SpreeCmCommissioner::PopularRoutePlacesRequestSchema
37
+ end
38
+
39
+ def include_vendors?
40
+ resource_includes.include?(:vendors) || false
41
+ end
42
+
43
+ def include_nearby_places?
44
+ resource_includes.include?(:nearby_places) || false
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,46 @@
1
+ module Spree
2
+ module Api
3
+ module V2
4
+ module Tenant
5
+ module Transit
6
+ class DraftOrdersController < BaseController
7
+ # Creates a draft transit order for tenant.
8
+ # Endpoint: POST /api/v2/tenant/transit/draft_orders
9
+ # Params:
10
+ # - outbound_date: Date of outbound transit (optional)
11
+ # - inbound_date: Date of inbound transit (optional)
12
+ # - outbound_legs: Array of outbound leg details (required)
13
+ # - inbound_legs: Array of inbound leg details (optional)
14
+ def create
15
+ @outbound_legs = params[:outbound_legs].is_a?(Array) && params[:outbound_legs].any? ? build_legs(:outbound, params[:outbound_legs]) : []
16
+ @inbound_legs = params[:inbound_legs].is_a?(Array) && params[:inbound_legs].any? ? build_legs(:inbound, params[:inbound_legs]) : []
17
+
18
+ result = SpreeCmCommissioner::TransitOrder::Create.call(
19
+ outbound_date: params[:outbound_date]&.to_date,
20
+ inbound_date: params[:inbound_date]&.to_date,
21
+ outbound_legs: @outbound_legs,
22
+ inbound_legs: @inbound_legs,
23
+ user: spree_current_user
24
+ )
25
+
26
+ if result.success?
27
+ render_serialized_payload { serialize_resource(result.value[:order]) }
28
+ else
29
+ render_error_payload(result.error)
30
+ end
31
+ end
32
+
33
+ def build_legs(direction, legs_params)
34
+ SpreeCmCommissioner::Transit::LegsBuilderService.new(direction: direction, legs_params: legs_params).call
35
+ end
36
+
37
+ # override
38
+ def resource_serializer
39
+ Spree::V2::Tenant::TransitCartSerializer
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -15,38 +15,37 @@ module Spree
15
15
 
16
16
  def check_in
17
17
  guest_ids = [params[:id]]
18
- context = SpreeCmCommissioner::CheckInBulkCreator.call(
19
- check_ins_attributes: guest_ids.map { |guest_id| { guest_id: guest_id } },
18
+ result = SpreeCmCommissioner::CheckIns::CreateBulk.call(
19
+ check_ins_attributes: guest_ids.map { |guest_id| { guest_id: guest_id, check_in_session_id: params[:check_in_session_id] } },
20
20
  check_in_by: spree_current_user
21
21
  )
22
22
 
23
- if context.success?
23
+ if result.success?
24
24
  flash[:success] = Spree.t('event.check_in.success')
25
25
  else
26
- flash[:error] = context.message.to_s.titleize
26
+ flash[:error] = result.error.to_s
27
27
  end
28
28
 
29
29
  redirect_to edit_object_url
30
30
  end
31
31
 
32
32
  def uncheck_in
33
- guest_ids = [params[:id]]
34
- context = SpreeCmCommissioner::CheckInDestroyer.call(
35
- guest_ids: guest_ids,
33
+ result = SpreeCmCommissioner::CheckIns::DestroyBulk.call(
34
+ check_ins_attributes: [{ guest_id: params[:id], check_in_session_id: params[:check_in_session_id] }],
36
35
  destroyed_by: spree_current_user
37
36
  )
38
37
 
39
- if context.success?
38
+ if result.success?
40
39
  flash[:success] = Spree.t('event.uncheck_in.success')
41
40
  else
42
- flash[:error] = context.message.to_s.titleize
41
+ flash[:error] = result.error.to_s
43
42
  end
44
43
 
45
44
  redirect_to edit_object_url
46
45
  end
47
46
 
48
47
  def edit
49
- @check_in = @guest.check_in
48
+ @check_in = @guest.earliest_check_in
50
49
  end
51
50
 
52
51
  def edit_object_url
@@ -48,13 +48,13 @@ module Spree
48
48
  boarding_points_attributes = (cm_params.delete('boarding_points') || []).compact_blank
49
49
  .map do |point_id|
50
50
  trip_stop = trip_stops.delete(point_id.to_i)
51
- { stop_id: point_id, stop_type: 'boarding', id: trip_stop.try(:id) }
51
+ { stop_id: point_id, allow_boarding: true, id: trip_stop.try(:id) }
52
52
  end
53
53
 
54
54
  drop_off_points_attributes = (cm_params.delete('drop_off_points') || []).compact_blank
55
55
  .map do |point_id|
56
56
  trip_stop = trip_stops.delete(point_id.to_i)
57
- { stop_id: point_id, stop_type: 'drop_off', id: trip_stop.try(:id) }
57
+ { stop_id: point_id, allow_drop_off: true, id: trip_stop.try(:id) }
58
58
  end
59
59
 
60
60
  trip_stops.each_value do |trip_stop|
@@ -74,7 +74,7 @@ module Spree
74
74
  :origin_id, :destination_id, :vehicle_id, :hours, :minutes, :seconds,
75
75
  'departure_time(1i)', 'departure_time(2i)', 'departure_time(3i)',
76
76
  'departure_time(4i)', 'departure_time(5i)', :product_id,
77
- trip_stops_attributes: %i[stop_id stop_type _destroy id]
77
+ trip_stops_attributes: %i[stop_id allow_boarding allow_drop_off _destroy id]
78
78
  )
79
79
  end
80
80
 
@@ -1,20 +1,20 @@
1
- # Finds places connected via routes with optional filtering.
1
+ # Finds places connected via route metrics with optional filtering.
2
2
  #
3
3
  # @param place_type [String] Required. 'origin' or 'destination'
4
4
  # @param place_id [Integer] Optional. Filter by connected place ID
5
5
  # @param query [String] Optional. Filter by place name (case-insensitive)
6
- # @param route_type [Symbol, String] Optional. Filter by route type from associated trips (e.g., :ferry, :bus)
6
+ # @param route_type [Symbol, String] Optional. Filter by route type from route metrics (e.g., :ferry, :bus)
7
7
  #
8
8
  # @return [ActiveRecord::Relation<SpreeCmCommissioner::Place>]
9
9
  #
10
10
  # Modes:
11
11
  # - place_id only: returns connected places (origins TO or destinations FROM given place)
12
12
  # - query only: filters by name
13
- # - route_type only: filters by trip route types on those routes
13
+ # - route_type only: filters by route type on route metrics
14
14
  # - combinations: connected places filtered by name and/or route type
15
- # - neither: all origins/destinations in routes
15
+ # - neither: all origins/destinations in route metrics
16
16
  #
17
- # @example Origins with ferry trips to place 123
17
+ # @example Origins with ferry route metrics to place 123
18
18
  # FindWithRoute.new(place_type: 'origin', place_id: 123, route_type: :ferry).execute
19
19
  #
20
20
  # @example Destinations filtered by query and route type
@@ -46,14 +46,14 @@ module SpreeCmCommissioner
46
46
  def scope
47
47
  return SpreeCmCommissioner::Place.none unless valid_place_type?
48
48
 
49
- base_scope = origin? ? SpreeCmCommissioner::Place.with_routes_as_origin : SpreeCmCommissioner::Place.with_routes_as_destination
49
+ base_scope = origin? ? SpreeCmCommissioner::Place.with_route_metrics_as_origin : SpreeCmCommissioner::Place.with_route_metrics_as_destination
50
50
 
51
51
  return base_scope if place_id.blank?
52
52
 
53
53
  if origin?
54
- base_scope.where(routes_as_origin: { destination_place_id: place_id })
54
+ base_scope.where(route_metrics_as_origin: { destination_place_id: place_id })
55
55
  else
56
- base_scope.where(routes_as_destination: { origin_place_id: place_id })
56
+ base_scope.where(route_metrics_as_destination: { origin_place_id: place_id })
57
57
  end
58
58
  end
59
59
 
@@ -62,10 +62,10 @@ module SpreeCmCommissioner
62
62
  end
63
63
 
64
64
  def apply_route_type_filter(result)
65
- trips_association = origin? ? :trips_as_origin : :trips_as_destination
66
- result.joins(trips_association)
67
- .where(cm_trips: { route_type: route_type.to_sym })
68
- .distinct
65
+ # Use the association name as the table alias in the WHERE clause
66
+ # This works whether the association is already joined or not
67
+ association_name = origin? ? :route_metrics_as_origin : :route_metrics_as_destination
68
+ result.where(association_name => { route_type: route_type.to_sym })
69
69
  end
70
70
 
71
71
  def origin?
@@ -0,0 +1,44 @@
1
+ # Finds route metrics ordered by popularity based on order metrics.
2
+ #
3
+ # Route metrics are sorted by:
4
+ # 1. fulfilled_order_count (completed orders) - DESC
5
+ # 2. order_count (total orders including incomplete) - DESC
6
+ #
7
+ # @param route_type [Symbol, String] Optional. Filter by route type (e.g., :ferry, :bus)
8
+ #
9
+ # @return [ActiveRecord::Relation<SpreeCmCommissioner::RouteMetric>] Route metrics with origin and destination places loaded,
10
+ # ordered from most to least popular
11
+ #
12
+ # @example Get all popular route metrics
13
+ # finder = SpreeCmCommissioner::RouteMetrics::FindPopular.new
14
+ # finder.execute # => Returns all route metrics sorted by fulfillment and order counts
15
+ #
16
+ # @example Get popular ferry route metrics
17
+ # finder = SpreeCmCommissioner::RouteMetrics::FindPopular.new
18
+ # finder.execute(route_type: :ferry) # => Returns ferry route metrics sorted by popularity
19
+ #
20
+ # @example Get popular bus route metrics
21
+ # finder = SpreeCmCommissioner::RouteMetrics::FindPopular.new
22
+ # finder.execute(route_type: :bus) # => Returns bus route metrics sorted by popularity
23
+
24
+ module SpreeCmCommissioner
25
+ module RouteMetrics
26
+ class FindPopular
27
+ def execute(route_type: nil, query: nil)
28
+ scope(route_type: route_type, query: query)
29
+ end
30
+
31
+ private
32
+
33
+ def scope(route_type:, query:)
34
+ result = SpreeCmCommissioner::RouteMetric.all
35
+
36
+ result = result.where(route_type: route_type.to_sym) if route_type.present?
37
+ result = result.where('cm_route_metrics.route_name ILIKE ?', "%#{query}%") if query.present?
38
+
39
+ result.includes(:origin_place, :destination_place)
40
+ .order(fulfilled_order_count: :desc, order_count: :desc)
41
+ end
42
+ end
43
+ end
44
+ end