spree_cm_commissioner 2.1.1 → 2.1.3.pre.beta

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 98200b6520e80906b028296c9226090ef2d61e33838da49bdda8bf2dd3e1a65d
4
- data.tar.gz: fbfcb39d2331a14519c5b8a59b3b2f8147126e804660fb093e96e6409256bd85
3
+ metadata.gz: 1b1bf8bbc92e68f9c6d475925cb6e45f64468be42f63495f6f0934ff396a8335
4
+ data.tar.gz: ebddd7396af6d5036a13656da0dd17f12c4b003bc2166bb62b8f008befdb1704
5
5
  SHA512:
6
- metadata.gz: 16b4707677a81711846bbc5b8f1d272531d6364e9a84d0f1d4a22c7b472e23e77cd9eeb7920cfdaa16a675237c6e092bd77368d9971ba7d4252592a9d80f9d6b
7
- data.tar.gz: ad7adc2b96e483948ad15e8760a910ae424c3d4534b2d2e16be10347a355aaf221a056365359cc646d81c51bf01d45220716377df4b848fb3cf7abbb10ccbe81
6
+ metadata.gz: e500edd2aaf333240d9cccdd410af03ddcf896853daa8eb2129320a60ecdc4b73097da3bc9f4aed9f7b7a74c3736a65dd97ac21e6927b383139f906426cf146d
7
+ data.tar.gz: 68c69b704746da48c93773dffce024b68c7274adde41e2f14b4a4f453eff876e8a0e422fc96067506c1a6a7b64c4c71cc4f34eddd3c99d45616aeb781d6a2e34
data/Gemfile.lock CHANGED
@@ -34,7 +34,7 @@ GIT
34
34
  PATH
35
35
  remote: .
36
36
  specs:
37
- spree_cm_commissioner (2.1.1)
37
+ spree_cm_commissioner (2.1.3.pre.beta)
38
38
  activerecord-multi-tenant
39
39
  activerecord_json_validator (~> 2.1, >= 2.1.3)
40
40
  aws-sdk-cloudfront
data/README.md CHANGED
@@ -116,7 +116,6 @@ ACCOMMODATION_MAX_STAY_DAYS = 10
116
116
  DEFAULT_TELEGRAM_BOT_API_TOKEN = ""
117
117
 
118
118
  PIN_CODE_DEBUG_NOTIFIY_TELEGRAM_ENABLE="yes"
119
- RECAPTCHA_TOKEN_VALIDATOR_ENABLE="yes"
120
119
 
121
120
  EXCEPTION_NOTIFY_ENABLE="yes" # yes or no
122
121
  EXCEPTION_TELEGRAM_BOT_TOKEN=""
@@ -3,22 +3,6 @@ module Spree
3
3
  module V2
4
4
  module Storefront
5
5
  class PinCodeGeneratorsController < ::Spree::Api::V2::ResourceController
6
- before_action :validate_recaptcha, only: [:create]
7
-
8
- def validate_recaptcha
9
- return unless ENV['RECAPTCHA_TOKEN_VALIDATOR_ENABLE'] == 'yes'
10
-
11
- context = SpreeCmCommissioner::RecaptchaTokenValidator.call(
12
- token: params[:recaptcha_token],
13
- action: params[:recaptcha_action],
14
- site_key: params[:recaptcah_site_key]
15
- )
16
-
17
- return if context.success?
18
-
19
- render_error_payload(context.message, 400)
20
- end
21
-
22
6
  # :phone_number, :email, :type, :tenant
23
7
  def create
24
8
  context = SpreeCmCommissioner::PinCodeGenerator.call(pin_code_attrs)
@@ -3,22 +3,6 @@ module Spree
3
3
  module V2
4
4
  module Storefront
5
5
  class PinCodeOtpGeneratorsController < ::Spree::Api::V2::ResourceController
6
- before_action :validate_recaptcha, only: [:create]
7
-
8
- def validate_recaptcha
9
- return unless ENV['RECAPTCHA_TOKEN_VALIDATOR_ENABLE'] == 'yes'
10
-
11
- context = SpreeCmCommissioner::RecaptchaTokenValidator.call(
12
- token: params[:recaptcha_token],
13
- action: params[:recaptcha_action],
14
- site_key: params[:recaptcah_site_key]
15
- )
16
-
17
- return if context.success?
18
-
19
- render_error_payload(context.message, 400)
20
- end
21
-
22
6
  # :phone_number, :email, :type, :recaptcha_token, :recaptcha_action, :recaptcah_site_key
23
7
  def create
24
8
  options = otp_attrs
@@ -14,7 +14,7 @@ module Spree
14
14
  else
15
15
  render json: {
16
16
  message: 'FAILED',
17
- error: result.error
17
+ error: result.message
18
18
  }, status: result.status || :unprocessable_entity
19
19
  end
20
20
  end
@@ -63,13 +63,15 @@ module SpreeCmCommissioner
63
63
  def process_line_items_attributes(params)
64
64
  date_param = raw_params[:date] || Date.current.to_s
65
65
 
66
+ load_variant
67
+
66
68
  params[:line_items_attributes].each_value do |item|
67
69
  pickup_time_minutes = item[:from_date]
68
70
  combined_datetime = "#{date_param} #{pickup_time_minutes}"
69
71
 
70
72
  item[:from_date] = combined_datetime
71
73
  item[:to_date] = combined_datetime
72
- item[:variant_id] = load_variant
74
+ item[:variant_id] = @variant.id
73
75
  item[:vendor_id] = current_vendor.id
74
76
  item[:quantity] = 1
75
77
  item[:currency] = 'USD'
@@ -100,7 +102,7 @@ module SpreeCmCommissioner
100
102
  end
101
103
 
102
104
  def load_variant
103
- trip.product.master.id
105
+ @variant = trip.product.variants.first
104
106
  end
105
107
  end
106
108
  end
@@ -0,0 +1,56 @@
1
+ module SpreeCmCommissioner
2
+ class TripStopsCreator < BaseInteractor
3
+ delegate :trip, :origin_place, :destination_place, :departure_time, :duration_seconds, to: :context
4
+
5
+ def call
6
+ validate_context!
7
+
8
+ ActiveRecord::Base.transaction do
9
+ create_origin_stop
10
+ create_destination_stop
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def validate_context!
17
+ context.fail!(message: 'Trip is missing') unless trip
18
+ context.fail!(message: 'Origin place is missing') unless origin_place
19
+ context.fail!(message: 'Destination place is missing') unless destination_place
20
+ context.fail!(message: 'Departure time is missing') unless departure_time
21
+ context.fail!(message: 'Duration (seconds) is missing') unless duration_seconds
22
+ end
23
+
24
+ def create_origin_stop
25
+ attributes = {
26
+ trip: trip,
27
+ stop_place: origin_place,
28
+ location_place: origin_place,
29
+ stop_type: :boarding
30
+ }
31
+
32
+ attributes[:departure_time] = departure_time
33
+
34
+ origin_trip_stop = SpreeCmCommissioner::TripStop.new(attributes)
35
+
36
+ context.fail!(message: origin_trip_stop.errors.full_messages.to_sentence) unless origin_trip_stop.save
37
+ context.origin_trip_stop = origin_trip_stop
38
+ end
39
+
40
+ def create_destination_stop
41
+ attributes = {
42
+ trip: trip,
43
+ stop_place: destination_place,
44
+ location_place: destination_place,
45
+ stop_type: :drop_off
46
+ }
47
+
48
+ attributes[:arrival_time] = departure_time + duration_seconds.seconds
49
+
50
+ destination_trip_stop = SpreeCmCommissioner::TripStop.new(attributes)
51
+
52
+ context.fail!(message: destination_trip_stop.errors.full_messages.to_sentence) unless destination_trip_stop.save
53
+ context.destination_trip_stop = destination_trip_stop
54
+ end
55
+ end
56
+ end
@@ -66,9 +66,12 @@ module SpreeCmCommissioner
66
66
 
67
67
  def find_existing_user
68
68
  user_data = context.user_data
69
+ intel_phone = normalized_phone_number(user_data['phoneNum'])
69
70
 
70
- context.user = Spree::User.find_by(
71
- 'email = ? OR phone_number = ?', user_data['email'], user_data['phoneNum']
71
+ context.user = Spree::User.by_non_tenant.find_by(
72
+ 'email = :email OR intel_phone_number = :intel_phone',
73
+ email: user_data['email'],
74
+ intel_phone: intel_phone
72
75
  )
73
76
  end
74
77
 
@@ -84,6 +87,7 @@ module SpreeCmCommissioner
84
87
  last_name: user_data['lastName'],
85
88
  email: user_data['email'],
86
89
  phone_number: user_data['phoneNum'],
90
+ intel_phone_number: normalized_phone_number(user_data['phoneNum']),
87
91
  password: SecureRandom.base64(16),
88
92
  user_identity_providers: [identity]
89
93
  )
@@ -119,6 +123,10 @@ module SpreeCmCommissioner
119
123
  context.data = signed_data
120
124
  end
121
125
 
126
+ def normalized_phone_number(phone_number)
127
+ SpreeCmCommissioner::PhoneNumberParser.call(phone_number: phone_number).intel_phone_number
128
+ end
129
+
122
130
  def session_id
123
131
  payload = { user_id: context.user.id }
124
132
  SpreeCmCommissioner::UserSessionJwtToken.encode(payload, context.user.reload.secure_token)
@@ -0,0 +1,45 @@
1
+ module SpreeCmCommissioner
2
+ class GuestSeatUpdater < BaseInteractor
3
+ delegate :line_item,
4
+ :guest,
5
+ :block_id,
6
+ :updated_by, to: :context
7
+
8
+ def call
9
+ context.fail!(errors: 'Updated user is required') if updated_by.blank?
10
+ context.fail!(errors: 'Line item not found') unless line_item
11
+ context.fail!(errors: 'Guest not found') unless guest
12
+ context.fail!(errors: 'Block ID is required') if block_id.blank?
13
+
14
+ if block_id.present? && !block_belongs_to_variant?(block_id, line_item.variant_id)
15
+ context.fail!(errors: "Variant change is not allowed — seat can only be updated for the same variant #{line_item.variant_id}")
16
+ end
17
+
18
+ ActiveRecord::Base.transaction do
19
+ update_seat_for_guest
20
+ end
21
+ rescue StandardError => e
22
+ raise if defined?(Interactor::Failure) && e.is_a?(Interactor::Failure)
23
+
24
+ context.fail!(errors: e.message)
25
+ end
26
+
27
+ def update_seat_for_guest
28
+ reserve_block = SpreeCmCommissioner::ReservedBlock.find_by(
29
+ guest_id: guest.id,
30
+ block_id: guest.block_id
31
+ )
32
+ reserve_block.update!(block_id: block_id, updated_by_id: updated_by.id) if reserve_block && reserve_block.block_id != block_id
33
+
34
+ guest.update!(block_id: block_id) if guest.block_id != block_id && block_id.present?
35
+
36
+ line_item
37
+ end
38
+
39
+ def block_belongs_to_variant?(block_id, variant_id)
40
+ return false unless block_id.present? && variant_id.present?
41
+
42
+ SpreeCmCommissioner::VariantBlock.exists?(variant_id: variant_id, block_id: block_id)
43
+ end
44
+ end
45
+ end
@@ -42,8 +42,7 @@ module SpreeCmCommissioner
42
42
  'bib-pre-generation-on-create' => 'boolean',
43
43
  'seat-number-positions' => 'array',
44
44
  'seat-type' => 'string',
45
- 'intercity-taxi' => 'string',
46
- 'pickup-time' => 'integer'
45
+ 'intercity-taxi' => 'string'
47
46
  }.freeze
48
47
 
49
48
  included do
@@ -33,6 +33,7 @@ module SpreeCmCommissioner
33
33
 
34
34
  base.multi_tenant :tenant, class_name: 'SpreeCmCommissioner::Tenant'
35
35
  base.scope :by_tenant, -> (tenant_id) { where(tenant_id: tenant_id) }
36
+ base.scope :by_non_tenant, -> { where(tenant_id: nil) }
36
37
  base.scope :vendor_users, -> (vendor_id) { joins(:role_users => :role).where(spree_roles: { vendor_id: vendor_id }).distinct }
37
38
 
38
39
  base.whitelisted_ransackable_attributes = %w[email first_name last_name gender phone_number]
@@ -88,6 +88,7 @@ module SpreeCmCommissioner
88
88
  id: trip&.id,
89
89
  departure_time: trip&.departure_time,
90
90
  duration: trip&.duration,
91
+ distance: trip&.distance,
91
92
  allow_seat_selection: trip&.allow_seat_selection,
92
93
  route_type: trip&.route_type,
93
94
  origin_place: {
@@ -0,0 +1,11 @@
1
+ module Spree
2
+ module V2
3
+ module Tenant
4
+ class ProductSerializer < Spree::V2::Storefront::ProductSerializer
5
+ # This serializer extends the Storefront ProductSerializer
6
+ # to include any additional attributes or relationships needed
7
+ # for the Tenant context.
8
+ end
9
+ end
10
+ end
11
+ end
@@ -5,7 +5,7 @@ module SpreeCmCommissioner
5
5
  set_type :trip_result
6
6
 
7
7
  attributes :origin_place, :destination_place, :boarding, :drop_off, :price, :compare_at_amount, :currency, :quantity_available, :max_capacity,
8
- :allow_seat_selection, :departure_time, :route_type
8
+ :allow_seat_selection, :departure_time, :route_type, :distance
9
9
  attribute :duration_in_hms, &:duration_in_hms
10
10
  attribute :arrival_time, &:arrival_time
11
11
  belongs_to :vendor, serializer: ::SpreeCmCommissioner::V2::Storefront::TripVendorSerializer
@@ -4,7 +4,7 @@ module SpreeCmCommissioner
4
4
  :departure_time, :duration, :route_type,
5
5
  :vehicle_id, :vehicle, :vendor_id, :vendor,
6
6
  :quantity_available, :max_capacity, :boarding, :drop_off,
7
- :product_id, :amenities, :price, :compare_at_amount, :currency
7
+ :product_id, :amenities, :price, :compare_at_amount, :currency, :distance
8
8
 
9
9
  def initialize(options = {})
10
10
  options.each do |key, value|
@@ -1,5 +1,5 @@
1
1
  module SpreeCmCommissioner
2
- VERSION = '2.1.1'.freeze
2
+ VERSION = '2.1.3-beta'.freeze
3
3
 
4
4
  module_function
5
5
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spree_cm_commissioner
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.1
4
+ version: 2.1.3.pre.beta
5
5
  platform: ruby
6
6
  authors:
7
7
  - You
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-08-28 00:00:00.000000000 Z
11
+ date: 2025-09-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: spree
@@ -1206,6 +1206,7 @@ files:
1206
1206
  - app/interactors/spree_cm_commissioner/transactional_email_sender.rb
1207
1207
  - app/interactors/spree_cm_commissioner/transit/draft_order_creator.rb
1208
1208
  - app/interactors/spree_cm_commissioner/trip_clone_creator.rb
1209
+ - app/interactors/spree_cm_commissioner/trip_stops_creator.rb
1209
1210
  - app/interactors/spree_cm_commissioner/unique_device_token_cron_executor.rb
1210
1211
  - app/interactors/spree_cm_commissioner/update_payment_gateway_status.rb
1211
1212
  - app/interactors/spree_cm_commissioner/user_contact_updater.rb
@@ -1288,6 +1289,7 @@ files:
1288
1289
  - app/mailers/spree_cm_commissioner/team_invite_mailer.rb
1289
1290
  - app/models/.gitkeep
1290
1291
  - app/models/concerns/spree_cm_commissioner/event_check_in_flowable.rb
1292
+ - app/models/concerns/spree_cm_commissioner/guest_seat_updater.rb
1291
1293
  - app/models/concerns/spree_cm_commissioner/homepage_section_bitwise.rb
1292
1294
  - app/models/concerns/spree_cm_commissioner/json_preference_validator.rb
1293
1295
  - app/models/concerns/spree_cm_commissioner/kyc_bitwise.rb
@@ -1749,6 +1751,7 @@ files:
1749
1751
  - app/serializers/spree/v2/tenant/order_serializer.rb
1750
1752
  - app/serializers/spree/v2/tenant/payment_method_group_serializer.rb
1751
1753
  - app/serializers/spree/v2/tenant/payment_method_serializer.rb
1754
+ - app/serializers/spree/v2/tenant/product_serializer.rb
1752
1755
  - app/serializers/spree/v2/tenant/reset_password_serializer.rb
1753
1756
  - app/serializers/spree/v2/tenant/role_serializer.rb
1754
1757
  - app/serializers/spree/v2/tenant/s3_signed_url_serializer.rb
@@ -2720,7 +2723,6 @@ files:
2720
2723
  - db/migrate/20250725092713_add_block_type_to_cm_blocks.rb
2721
2724
  - db/migrate/20250731062816_add_departure_time_and_arrival_time_to_trip_stop.rb
2722
2725
  - db/migrate/20250807033035_create_spree_cm_commissioner_saved_guests.rb
2723
- - db/migrate/20250807040000_generate_pickup_time_integer_option_values.rb
2724
2726
  - db/migrate/20250808054835_add_saved_guest_reference_to_cm_blocks.rb
2725
2727
  - db/migrate/20250812015522_remove_unique_indexes_from_cm_user_identity_providers.rb
2726
2728
  - db/migrate/20250812121745_add_data_fill_stage_phase_to_cm_guests.rb
@@ -2885,9 +2887,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
2885
2887
  version: '2.7'
2886
2888
  required_rubygems_version: !ruby/object:Gem::Requirement
2887
2889
  requirements:
2888
- - - ">="
2890
+ - - ">"
2889
2891
  - !ruby/object:Gem::Version
2890
- version: '0'
2892
+ version: 1.3.1
2891
2893
  requirements:
2892
2894
  - none
2893
2895
  rubygems_version: 3.4.1
@@ -1,71 +0,0 @@
1
- class GeneratePickupTimeIntegerOptionValues < ActiveRecord::Migration[7.0]
2
- def up
3
- generate_time_option_values(
4
- option_type_name: 'pickup-time',
5
- option_type_presentation: 'Pickup Time',
6
- start_time: '00:00',
7
- end_time: '23:45',
8
- interval_minutes: 15
9
- )
10
- end
11
-
12
- def down
13
- remove_time_option_values('pickup-time')
14
- end
15
-
16
- private
17
-
18
- def generate_time_option_values(option_type_name:, option_type_presentation:, start_time:, end_time:, interval_minutes:)
19
- option_type = Spree::OptionType.find_by(name: option_type_name)
20
- unless option_type
21
- option_type = Spree::OptionType.new(name: option_type_name, presentation: option_type_presentation)
22
- option_type.save(validate: false)
23
- end
24
-
25
- # Ensure correct attributes and scope
26
- option_type.update_columns(attr_type: 'integer', kind: 'variant')
27
-
28
- Spree::OptionValue.where(option_type_id: option_type.id).delete_all
29
-
30
- time_slots = []
31
- current_time = parse_time(start_time)
32
- end_time_parsed = parse_time(end_time)
33
-
34
- while current_time <= end_time_parsed
35
- time_slots << current_time
36
- current_time += interval_minutes.minutes
37
- end
38
-
39
- rows = []
40
- time_slots.each_with_index do |time, index|
41
- minutes_since_midnight = (time.hour * 60) + time.min
42
- rows << {
43
- name: minutes_since_midnight.to_s,
44
- presentation: minutes_since_midnight.to_s,
45
- position: index,
46
- option_type_id: option_type.id,
47
- created_at: Time.current,
48
- updated_at: Time.current
49
- }
50
- end
51
-
52
- Spree::OptionValue.insert_all(rows) if rows.any?
53
- puts "Created #{rows.size} #{option_type_name} option values as integer minutes since midnight"
54
- end
55
-
56
- def remove_time_option_values(option_type_name)
57
- option_type = Spree::OptionType.find_by(name: option_type_name)
58
- return unless option_type
59
-
60
- count = Spree::OptionValue.where(option_type_id: option_type.id).count
61
- Spree::OptionValue.where(option_type_id: option_type.id).delete_all
62
- option_type.delete
63
- puts "Removed #{option_type_name} option type and #{count} option values"
64
- end
65
-
66
- def parse_time(time_string)
67
- Time.zone.parse("2000-01-01 #{time_string}")
68
- end
69
- end
70
-
71
-