spree_cm_commissioner 1.13.0 → 1.15.0.pre.beta1

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 (77) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +12 -1
  3. data/README.md +43 -1
  4. data/app/assets/images/category_icons/art_icon.png +0 -0
  5. data/app/assets/images/category_icons/concert_icon.png +0 -0
  6. data/app/assets/images/category_icons/fundraising_icon.png +0 -0
  7. data/app/assets/images/category_icons/marathon_icon.png +0 -0
  8. data/app/assets/images/category_icons/online_icon.png +0 -0
  9. data/app/assets/images/category_icons/workshop_icon.png +0 -0
  10. data/app/controllers/spree/admin/users_controller_decorator.rb +13 -0
  11. data/app/controllers/spree/api/chatrace/guests_controller.rb +2 -1
  12. data/app/controllers/spree/api/v2/organizer/invite_guests_controller.rb +21 -0
  13. data/app/controllers/spree/api/v2/storefront/cart_payment_method_groups_controller.rb +12 -1
  14. data/app/controllers/spree/api/v2/storefront/guests_controller.rb +3 -1
  15. data/app/controllers/spree/api/v2/tenant/cart_controller.rb +11 -0
  16. data/app/controllers/spree/api/v2/tenant/checkout_controller.rb +1 -0
  17. data/app/controllers/spree/api/v2/tenant/order_histories_controller.rb +65 -0
  18. data/app/controllers/spree_cm_commissioner/admin/variants_controller_decorator.rb +1 -1
  19. data/app/controllers/spree_cm_commissioner/well_known_controller.rb +46 -0
  20. data/app/factory/spree_cm_commissioner/invite_guest_claimed_telegram_message_factory.rb +120 -0
  21. data/app/finders/spree_cm_commissioner/products/find_decorator.rb +16 -0
  22. data/app/helpers/spree_cm_commissioner/transit/order_query_helper.rb +17 -0
  23. data/app/helpers/spree_cm_commissioner/transit/trip_helper.rb +12 -0
  24. data/app/interactors/spree_cm_commissioner/create_event.rb +31 -6
  25. data/app/interactors/spree_cm_commissioner/create_ticket.rb +36 -1
  26. data/app/interactors/spree_cm_commissioner/host_matcher.rb +28 -0
  27. data/app/interactors/spree_cm_commissioner/place_decoder.rb +16 -0
  28. data/app/interactors/spree_cm_commissioner/place_service.rb +32 -0
  29. data/app/interactors/spree_cm_commissioner/user_pin_code_authenticator.rb +9 -0
  30. data/app/models/concerns/spree_cm_commissioner/json_preference_validator.rb +23 -0
  31. data/app/models/concerns/spree_cm_commissioner/kyc_bitwise.rb +3 -1
  32. data/app/models/concerns/spree_cm_commissioner/store_preference.rb +2 -0
  33. data/app/models/concerns/spree_cm_commissioner/tenant_preference.rb +11 -0
  34. data/app/models/spree_cm_commissioner/cms_page_decorator.rb +16 -1
  35. data/app/models/spree_cm_commissioner/guest.rb +11 -2
  36. data/app/models/spree_cm_commissioner/invite_guest.rb +8 -0
  37. data/app/models/spree_cm_commissioner/order_decorator.rb +5 -0
  38. data/app/models/spree_cm_commissioner/payment_method_decorator.rb +8 -1
  39. data/app/models/spree_cm_commissioner/place.rb +3 -0
  40. data/app/models/spree_cm_commissioner/store_decorator.rb +2 -1
  41. data/app/models/spree_cm_commissioner/taxon_decorator.rb +4 -0
  42. data/app/models/spree_cm_commissioner/taxon_place.rb +12 -0
  43. data/app/models/spree_cm_commissioner/tenant.rb +5 -0
  44. data/app/models/spree_cm_commissioner/user_decorator.rb +14 -3
  45. data/app/models/spree_cm_commissioner/vendor_decorator.rb +7 -3
  46. data/app/models/spree_cm_commissioner/vendor_place.rb +11 -3
  47. data/app/overrides/spree/admin/stores/_form/store_preferences.html.erb.deface +85 -12
  48. data/app/overrides/spree/admin/variants/_form/kyc_field.html.erb.deface +3 -4
  49. data/app/queries/spree_cm_commissioner/reservation_query.rb +12 -0
  50. data/app/queries/spree_cm_commissioner/trip_query.rb +35 -25
  51. data/app/serializers/spree/v2/organizer/invite_guest_serializer.rb +1 -1
  52. data/app/serializers/spree/v2/storefront/taxon_serializer_decorator.rb +1 -0
  53. data/app/serializers/spree/v2/tenant/cart_serializer.rb +8 -0
  54. data/app/serializers/spree_cm_commissioner/v2/storefront/guest_serializer.rb +1 -1
  55. data/app/services/spree_cm_commissioner/organizer/export_invite_guest_csv_service.rb +63 -0
  56. data/app/services/spree_cm_commissioner/payment_method_type_mapper.rb +11 -0
  57. data/app/views/spree/admin/tenants/_form.html.erb +68 -2
  58. data/config/initializers/spree_permitted_attributes.rb +3 -0
  59. data/config/routes.rb +7 -0
  60. data/db/migrate/20250127081646_add_preferences_to_cm_tenants.rb +7 -0
  61. data/db/migrate/20250527043231_create_spree_commissioner_taxon_places.rb +15 -0
  62. data/db/migrate/20250528073748_remove_unique_slug_index_on_spree_cms_pages.rb +12 -0
  63. data/db/migrate/20250528074043_add_unique_index_on_slug_tenant_id_deleted_at_to_spree_cms_pages.rb +13 -0
  64. data/db/migrate/20250528090330_add_place_type_to_cm_vendor_place.rb +6 -0
  65. data/db/migrate/20250602094751_add_host_to_cm_tenants.rb +6 -0
  66. data/db/migrate/20250609015216_remove_claimed_at_and_expires_at_from_cm_invite_guest.rb +6 -0
  67. data/db/migrate/20250610080108_add_contact_to_cm_guests.rb +5 -0
  68. data/db/migrate/20250611023548_add_country_code_to_guests.rb +5 -0
  69. data/db/migrate/20250612035937_add_intel_phone_number_to_guests.rb +5 -0
  70. data/lib/spree_cm_commissioner/test_helper/factories/cms_page_factory.rb +11 -0
  71. data/lib/spree_cm_commissioner/test_helper/factories/invite_guests_factory.rb +6 -0
  72. data/lib/spree_cm_commissioner/test_helper/factories/tenant_factory.rb +1 -0
  73. data/lib/spree_cm_commissioner/test_helper/factories/vendor_place_factory.rb +17 -4
  74. data/lib/spree_cm_commissioner/version.rb +1 -1
  75. data/lib/spree_cm_commissioner.rb +1 -0
  76. data/spree_cm_commissioner.gemspec +2 -0
  77. metadata +66 -4
@@ -0,0 +1,28 @@
1
+ module SpreeCmCommissioner
2
+ class HostMatcher < BaseInteractor
3
+ delegate :host, to: :context
4
+
5
+ def call
6
+ normalized_host = normalize_host(host)
7
+
8
+ context.store = find_store(normalized_host)
9
+ return if context.store.present?
10
+
11
+ context.tenant = find_tenant(normalized_host)
12
+ end
13
+
14
+ private
15
+
16
+ def normalize_host(host)
17
+ host.sub(/^www\./, '')
18
+ end
19
+
20
+ def find_store(normalized_host)
21
+ Spree::Store.find_by(code: normalized_host)
22
+ end
23
+
24
+ def find_tenant(normalized_host)
25
+ SpreeCmCommissioner::Tenant.find_by(host: "https://#{normalized_host}")
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,16 @@
1
+ module SpreeCmCommissioner
2
+ class PlaceDecoder
3
+ def self.process_place(base_64_content)
4
+ begin
5
+ place_data = JSON.parse(Base64.strict_decode64(base_64_content))
6
+ rescue ArgumentError, JSON::ParserError => e
7
+ Rails.logger.error("Failed to decode and parse place data: #{e.message}")
8
+ return nil
9
+ end
10
+
11
+ place = SpreeCmCommissioner::Place.where(reference: place_data['reference']).first_or_initialize
12
+ place.assign_attributes(place_data)
13
+ place
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,32 @@
1
+ module SpreeCmCommissioner
2
+ class PlaceService
3
+ def initialize(model:, place_class:, params:)
4
+ @model = model # e.g., Taxon or Product
5
+ @place_class = place_class # e.g., TaxonPlace or ProductPlace
6
+ @params = params
7
+ end
8
+
9
+ def call
10
+ @base64_content = @params[:base_64_content]
11
+ @place_name = @params[:place_name]
12
+
13
+ if @base64_content.blank?
14
+ existing_place = @place_class
15
+ existing_place.delete if existing_place && @place_name.blank?
16
+ return
17
+ end
18
+
19
+ place = PlaceDecoder.process_place(@base64_content)
20
+ return if place.nil?
21
+
22
+ if place.save # rubocop:disable Style/GuardClause
23
+ existing_place = @place_class
24
+ if existing_place.present?
25
+ existing_place.update(place_id: place.id)
26
+ else
27
+ @model.places << place
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -33,6 +33,7 @@ module SpreeCmCommissioner
33
33
 
34
34
  user = Spree::User.new(create_options)
35
35
  user.confirmed_at = Time.zone.now
36
+ assign_role(user) if context.role.present?
36
37
 
37
38
  if user.save
38
39
  context.user = user
@@ -41,6 +42,14 @@ module SpreeCmCommissioner
41
42
  end
42
43
  end
43
44
 
45
+ def assign_role(user)
46
+ role = Spree::Role.find_by(name: context.role)
47
+ return unless role
48
+
49
+ user.assigned_roles = [role.name]
50
+ user.spree_roles << role
51
+ end
52
+
44
53
  def mark_pin_code_expired!
45
54
  SpreeCmCommissioner::PinCode.mark_expired!(context.pin_code_token)
46
55
  end
@@ -0,0 +1,23 @@
1
+ module SpreeCmCommissioner
2
+ module JsonPreferenceValidator
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ validate :validate_json_preferences
7
+ end
8
+
9
+ private
10
+
11
+ def validate_json_preferences
12
+ %i[preferred_assetlinks preferred_apple_app_site_association].each do |pref|
13
+ next if send(pref).blank?
14
+
15
+ begin
16
+ JSON.parse(send(pref))
17
+ rescue JSON::ParserError => e
18
+ errors.add(pref, "is not valid JSON: #{e.message}")
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -15,13 +15,15 @@ module SpreeCmCommissioner
15
15
  guest_expectation: 0b1000000000,
16
16
  guest_social_contact: 0b10000000000,
17
17
  guest_address: 0b100000000000,
18
- guest_phone_number: 0b1000000000000
18
+ guest_phone_number: 0b1000000000000,
19
+ guest_contact: 0b10000000000000
19
20
  }.freeze
20
21
 
21
22
  ORDERED_BIT_FIELDS = %i[
22
23
  guest_name
23
24
  guest_gender
24
25
  guest_phone_number
26
+ guest_contact
25
27
  guest_dob
26
28
  guest_occupation
27
29
  guest_nationality
@@ -6,6 +6,8 @@ module SpreeCmCommissioner
6
6
  preference :sms_sender_id, :string
7
7
  preference :telegram_order_alert_chat_id, :string
8
8
  preference :telegram_order_request_alert_chat_id, :string
9
+ preference :assetlinks, :string, default: ''
10
+ preference :apple_app_site_association, :string, default: ''
9
11
  end
10
12
  end
11
13
  end
@@ -0,0 +1,11 @@
1
+ module SpreeCmCommissioner
2
+ module TenantPreference
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ preference :assetlinks, :string, default: ''
7
+ preference :apple_app_site_association, :string, default: ''
8
+ preference :brand_primary_color, :string, default: ''
9
+ end
10
+ end
11
+ end
@@ -2,8 +2,23 @@ module SpreeCmCommissioner
2
2
  module CmsPageDecorator
3
3
  def self.prepended(base)
4
4
  base.belongs_to :tenant, class_name: 'SpreeCmCommissioner::Tenant'
5
+
6
+ base.validates :slug,
7
+ uniqueness: {
8
+ scope: %i[tenant_id deleted_at],
9
+ allow_nil: true,
10
+ case_sensitive: true
11
+ }
5
12
  end
6
13
  end
7
14
  end
8
15
 
9
- Spree::CmsPage.prepend(SpreeCmCommissioner::CmsPageDecorator) unless Spree::CmsPage.included_modules.include?(SpreeCmCommissioner::CmsPageDecorator)
16
+ unless Spree::CmsPage.included_modules.include?(SpreeCmCommissioner::CmsPageDecorator)
17
+ # remove old :slug validations
18
+ Spree::CmsPage._validators.reject! { |key, _| key == :slug }
19
+ Spree::CmsPage._validate_callbacks.each do |c|
20
+ c.filter.attributes.delete(:slug) if c.filter.respond_to?(:attributes)
21
+ end
22
+
23
+ Spree::CmsPage.prepend(SpreeCmCommissioner::CmsPageDecorator)
24
+ end
@@ -1,6 +1,8 @@
1
+ # rubocop:disable Metrics/ClassLength
1
2
  module SpreeCmCommissioner
2
3
  class Guest < SpreeCmCommissioner::Base
3
4
  include SpreeCmCommissioner::KycBitwise
5
+ include SpreeCmCommissioner::PhoneNumberSanitizer
4
6
 
5
7
  delegate :kyc, to: :line_item, allow_nil: true
6
8
  delegate :allowed_upload_later?, to: :line_item, allow_nil: true
@@ -48,13 +50,13 @@ module SpreeCmCommissioner
48
50
  validates :bib_index, uniqueness: true, allow_nil: true
49
51
 
50
52
  self.whitelisted_ransackable_associations = %w[id_card event]
51
- self.whitelisted_ransackable_attributes = %w[first_name last_name phone_number gender occupation_id card_type created_at check_in_status]
53
+ self.whitelisted_ransackable_attributes = %w[first_name last_name phone_number gender contact occupation_id card_type created_at check_in_status]
52
54
 
53
55
  def self.csv_importable_columns
54
56
  %i[
55
57
  first_name last_name phone_number age dob gender address other_occupation
56
58
  entry_type nationality_id other_organization expectation emergency_contact bib_number
57
- preferred_telegram_user_id seat_number
59
+ preferred_telegram_user_id seat_number country_code contact
58
60
  ]
59
61
  end
60
62
 
@@ -77,6 +79,8 @@ module SpreeCmCommissioner
77
79
  return upload_later? || (id_card.present? && id_card.allowed_checkout?) if field == :guest_id_card
78
80
  return address.present? if field == :guest_address
79
81
  return phone_number.present? if field == :guest_phone_number
82
+ return country_code.present? if field == :guest_country_code
83
+ return contact.present? if field == :guest_contact
80
84
 
81
85
  false
82
86
  end
@@ -110,6 +114,10 @@ module SpreeCmCommissioner
110
114
  address.blank?
111
115
  when :guest_phone_number
112
116
  phone_number.blank?
117
+ when :guest_country_code
118
+ country_code.blank?
119
+ when :guest_contact
120
+ contact.blank?
113
121
  else
114
122
  false
115
123
  end
@@ -219,3 +227,4 @@ module SpreeCmCommissioner
219
227
  end
220
228
  end
221
229
  end
230
+ # rubocop:enable Metrics/ClassLength
@@ -19,5 +19,13 @@ module SpreeCmCommissioner
19
19
  line_item = order.line_items.first
20
20
  line_item.guests.count >= order.line_items.first.number_of_guests
21
21
  end
22
+
23
+ def invitation_link
24
+ "#{Spree::Store.default.formatted_url}/invite_guests/#{token}?utm_source=email"
25
+ end
26
+
27
+ def ticket_url(guest_token)
28
+ "#{Spree::Store.default.formatted_url}/invite_guests/#{token}/guest_invitations/#{guest_token}"
29
+ end
22
30
  end
23
31
  end
@@ -192,6 +192,11 @@ module SpreeCmCommissioner
192
192
  Spree::Money.new(outstanding_balance, currency: currency).to_s
193
193
  end
194
194
 
195
+ # override spree_vpago method
196
+ def payment_host
197
+ tenant&.host.presence || ENV.fetch('DEFAULT_URL_HOST')
198
+ end
199
+
195
200
  private
196
201
 
197
202
  # override :spree_api
@@ -1,11 +1,18 @@
1
1
  module SpreeCmCommissioner
2
2
  module PaymentMethodDecorator
3
- DISPLAY = %i[both front_end back_end frontend_for_early_adopter].freeze
3
+ DISPLAY = %i[both front_end back_end frontend_for_early_adopter mini_app].freeze
4
4
 
5
5
  def self.prepended(base)
6
6
  base.const_set(:DISPLAY, DISPLAY)
7
7
 
8
8
  base.scope :available_on_frontend_for_early_adopter, -> { active.where(display_on: %i[both front_end frontend_for_early_adopter]) }
9
+
10
+ # override
11
+ base.scope :available_on_front_end, -> { active.where(display_on: %i[front_end both mini_app]) }
12
+ end
13
+
14
+ def mini_app?
15
+ display_on == 'mini_app'
9
16
  end
10
17
  end
11
18
  end
@@ -19,6 +19,9 @@ module SpreeCmCommissioner
19
19
  has_many :children, -> { order(:lft) }, class_name: 'SpreeCmCommissioner::Place', foreign_key: :parent_id, dependent: :destroy
20
20
  has_many :vendor_stops, class_name: 'SpreeCmCommissioner::VendorStop', dependent: :destroy, foreign_key: :stop_id
21
21
 
22
+ has_many :taxon_places, class_name: 'SpreeCmCommissioner::TaxonPlace', dependent: :destroy
23
+ has_many :taxons, through: :taxon_places
24
+
22
25
  def self.ransackable_attributes(auth_object = nil)
23
26
  super & %w[name code]
24
27
  end
@@ -2,10 +2,11 @@ module SpreeCmCommissioner
2
2
  module StoreDecorator
3
3
  def self.prepended(base)
4
4
  base.include SpreeCmCommissioner::StorePreference
5
+ base.include SpreeCmCommissioner::JsonPreferenceValidator
5
6
 
6
7
  base.has_one :default_notification_image, class_name: 'SpreeCmCommissioner::FeatureImage', dependent: :destroy, as: :viewable
7
8
  base.accepts_nested_attributes_for :default_notification_image, reject_if: :all_blank
8
- base.multi_tenant :tenant, class_name: 'SpreeCmCommissioner::Tenant'
9
+ base.has_one :tenant, class_name: 'SpreeCmCommissioner::Tenant'
9
10
  end
10
11
  end
11
12
  end
@@ -59,6 +59,7 @@ module SpreeCmCommissioner
59
59
 
60
60
  base.has_many :line_items, through: :products
61
61
  base.has_many :event_line_items, class_name: 'Spree::LineItem', foreign_key: :event_id
62
+ base.has_many :event_products, class_name: 'Spree::Product', foreign_key: :event_id
62
63
 
63
64
  base.has_many :event_blazer_queries, class_name: 'SpreeCmCommissioner::TaxonBlazerQuery'
64
65
  base.has_many :blazer_queries, through: :event_blazer_queries, class_name: 'Blazer::Query'
@@ -68,6 +69,9 @@ module SpreeCmCommissioner
68
69
 
69
70
  base.after_commit :send_transaction_email_to_organizers, on: :create
70
71
 
72
+ base.has_many :taxon_places, class_name: 'SpreeCmCommissioner::TaxonPlace', dependent: :destroy
73
+ base.has_many :places, through: :taxon_places
74
+
71
75
  def base.active_homepage_events
72
76
  joins(:homepage_section_relatables)
73
77
  .joins("INNER JOIN spree_taxons taxon ON taxon.id = cm_homepage_section_relatables.relatable_id
@@ -0,0 +1,12 @@
1
+ module SpreeCmCommissioner
2
+ class TaxonPlace < Base
3
+ self.inheritance_column = '_type_disabled'
4
+
5
+ belongs_to :taxon, class_name: 'Spree::Taxon', optional: false
6
+ belongs_to :place, class_name: 'SpreeCmCommissioner::Place', optional: false
7
+
8
+ validates :place_id, uniqueness: { scope: :taxon_id }
9
+
10
+ enum type: { venue: 0, nearby_place: 1 }
11
+ end
12
+ end
@@ -1,5 +1,8 @@
1
1
  module SpreeCmCommissioner
2
2
  class Tenant < SpreeCmCommissioner::Base
3
+ include SpreeCmCommissioner::TenantPreference
4
+ include SpreeCmCommissioner::JsonPreferenceValidator
5
+
3
6
  extend FriendlyId
4
7
  friendly_id :name, use: :history
5
8
 
@@ -9,6 +12,8 @@ module SpreeCmCommissioner
9
12
  through: :vendors,
10
13
  source: :payment_methods
11
14
 
15
+ validates :host, uniqueness: true, presence: true
16
+
12
17
  enum state: { enabled: 0, disabled: 1 }
13
18
 
14
19
  before_validation :generate_slug, if: -> { slug.blank? && name.present? }
@@ -1,7 +1,8 @@
1
- # rubocop:disable Metrics/MethodLength
1
+ require 'strong_password'
2
+
2
3
  module SpreeCmCommissioner
3
4
  module UserDecorator
4
- def self.prepended(base) # rubocop:disable Metrics/AbcSize
5
+ def self.prepended(base) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
5
6
  base.include SpreeCmCommissioner::UserNotification
6
7
  base.include SpreeCmCommissioner::UserIdentity
7
8
  base.include SpreeCmCommissioner::UserPreference
@@ -36,6 +37,8 @@ module SpreeCmCommissioner
36
37
  base.whitelisted_ransackable_attributes = %w[email first_name last_name gender phone_number]
37
38
 
38
39
  base.before_save :update_otp_enabled
40
+ base.attr_accessor :assigned_roles
41
+ base.validates_password_strength :password, if: -> { requires_strong_password? && password.present? }
39
42
 
40
43
  define_user_places(base)
41
44
 
@@ -88,6 +91,15 @@ module SpreeCmCommissioner
88
91
  [first_name, last_name].compact_blank.join(' ')
89
92
  end
90
93
 
94
+ def privileged_role?
95
+ assigned = assigned_roles || []
96
+ assigned.map(&:to_s).include?('admin')
97
+ end
98
+
99
+ def requires_strong_password?
100
+ admin? || privileged_role?
101
+ end
102
+
91
103
  def display_name
92
104
  return full_name if full_name.present?
93
105
  return first_name if first_name.present?
@@ -144,4 +156,3 @@ module SpreeCmCommissioner
144
156
  end
145
157
 
146
158
  Spree::User.prepend(SpreeCmCommissioner::UserDecorator) unless Spree::User.included_modules.include?(SpreeCmCommissioner::UserDecorator)
147
- # rubocop:enable Metrics/MethodLength
@@ -36,8 +36,12 @@ module SpreeCmCommissioner
36
36
  base.has_many :vendor_kind_option_values,
37
37
  through: :option_value_vendors, source: :option_value
38
38
 
39
- base.has_many :branches, class_name: 'SpreeCmCommissioner::Branch'
40
- base.has_many :stops, class_name: 'SpreeCmCommissioner::Place'
39
+ base.has_many :branches, lambda {
40
+ where(cm_vendor_places: { place_type: 0 })
41
+ }, through: :vendor_places, class_name: 'SpreeCmCommissioner::VendorPlace'
42
+ base.has_many :stops, -> { where(cm_vendor_places: { place_type: 1 }) }, through: :vendor_places, class_name: 'SpreeCmCommissioner::VendorPlace'
43
+ base.has_many :locations, -> { where(cm_vendor_places: { place_type: 2 }) },
44
+ through: :vendor_places, class_name: 'SpreeCmCommissioner::VendorPlace'
41
45
 
42
46
  base.has_many :places,
43
47
  through: :nearby_places, source: :place, class_name: 'SpreeCmCommissioner::Place'
@@ -118,7 +122,7 @@ module SpreeCmCommissioner
118
122
  end
119
123
 
120
124
  def selected_place_references
121
- places.pluck(:reference)
125
+ places.where.not(reference: [nil, '']).pluck(:reference)
122
126
  end
123
127
 
124
128
  def search_data
@@ -2,15 +2,23 @@ require_dependency 'spree_cm_commissioner'
2
2
 
3
3
  module SpreeCmCommissioner
4
4
  class VendorPlace < ApplicationRecord
5
+ enum place_type: { branch: 0, stop: 1, locations: 2 }
5
6
  acts_as_list scope: :vendor
6
7
 
7
- belongs_to :vendor, class_name: 'Spree::Vendor'
8
- belongs_to :place, class_name: 'SpreeCmCommissioner::Place'
8
+ belongs_to :vendor, class_name: 'Spree::Vendor', optional: false
9
+ belongs_to :place, class_name: 'SpreeCmCommissioner::Place', optional: false
10
+
11
+ validates :place_type, presence: true
12
+ validates :position, presence: true, numericality: { only_integer: true, greater_than: 0 }
9
13
 
10
14
  accepts_nested_attributes_for :place, allow_destroy: true
11
15
 
16
+ scope :branches, -> { where(place_type: :branch) }
17
+ scope :stops, -> { where(place_type: :stop) }
18
+ scope :locations, -> { where(place_type: :locations) }
19
+
12
20
  def selected
13
- vendor.selected_place_references.include?(place.reference)
21
+ vendor.selected_place_references.include?(place&.reference)
14
22
  end
15
23
  end
16
24
  end
@@ -1,18 +1,91 @@
1
1
  <!-- insert_bottom "[data-hook='admin_store_form_fields']" -->
2
2
 
3
3
  <% if @store.persisted? %>
4
- <div class="card mb-4">
5
- <div class="card-header">
6
- <h5 class="card-title mb-0 h6">
7
- <%= Spree.t(:preference).pluralize %>
8
- </h5>
9
- </div>
10
- <div class="card-body">
11
- <div id="preference-settings" data-hook class="form-group">
12
- <% unless preference_fields(@store, f).empty? %>
13
- <%= preference_fields(@store, f) %>
14
- <% end %>
4
+ <div class="card mb-4">
5
+ <div class="card-header">
6
+ <h5 class="card-title mb-0 h6">
7
+ <%= Spree.t(:preference).pluralize %>
8
+ </h5>
9
+ </div>
10
+ <div class="card-body">
11
+ <div id="preference-settings" data-hook class="form-group">
12
+ <div class="row">
13
+ <!-- SMS Sender ID -->
14
+ <div class="col-6">
15
+ <%= f.field_container :preferred_sms_sender_id do %>
16
+ <%= f.label :preferred_sms_sender_id, Spree.t(:sms_sender_id) %>
17
+ <%= f.text_field :preferred_sms_sender_id, class: 'form-control' %>
18
+ <%= f.error_message_on :preferred_sms_sender_id %>
19
+ <% end %>
20
+ </div>
21
+
22
+ <!-- Telegram Order Alert Chat ID -->
23
+ <div class="col-6">
24
+ <%= f.field_container :preferred_telegram_order_alert_chat_id do %>
25
+ <%= f.label :preferred_telegram_order_alert_chat_id, Spree.t(:telegram_order_alert_chat_id) %>
26
+ <%= f.text_field :preferred_telegram_order_alert_chat_id, class: 'form-control' %>
27
+ <%= f.error_message_on :preferred_telegram_order_alert_chat_id %>
28
+ <% end %>
29
+ </div>
30
+
31
+ <!-- Telegram Order Request Alert Chat ID -->
32
+ <div class="col-6">
33
+ <%= f.field_container :preferred_telegram_order_request_alert_chat_id do %>
34
+ <%= f.label :preferred_telegram_order_request_alert_chat_id, Spree.t(:telegram_order_request_alert_chat_id) %>
35
+ <%= f.text_field :preferred_telegram_order_request_alert_chat_id, class: 'form-control' %>
36
+ <%= f.error_message_on :preferred_telegram_order_request_alert_chat_id %>
37
+ <% end %>
38
+ </div>
39
+
40
+ <!-- Assetlinks -->
41
+ <div class="col-12">
42
+ <%= f.field_container :preferred_assetlinks do %>
43
+ <%= f.label :preferred_assetlinks, Spree.t(:assetlinks) %>
44
+ <%= f.text_area :preferred_assetlinks, class: 'form-control', rows: 5,
45
+ placeholder: 'example:
46
+ [
47
+ {
48
+ "relation": ["delegate_permission/common.handle_all_urls"],
49
+ "target": {
50
+ "namespace": "android_app",
51
+ "package_name": "com.yourapp.app",
52
+ "sha256_cert_fingerprints": [
53
+ "SHA256_CERTIFICATE_FINGERPRINT_HERE"
54
+ ]
55
+ }
56
+ }
57
+ ]' %>
58
+ <%= f.error_message_on :preferred_assetlinks %>
59
+ <% end %>
60
+ </div>
61
+
62
+ <!-- Apple App Site Association -->
63
+ <div class="col-12">
64
+ <%= f.field_container :preferred_apple_app_site_association do %>
65
+ <%= f.label :preferred_apple_app_site_association, Spree.t(:apple_app_site_association) %>
66
+ <%= f.text_area :preferred_apple_app_site_association, class: 'form-control', rows: 5,
67
+ placeholder: 'example:
68
+ {
69
+ "webcredentials": {
70
+ "apps": [
71
+ "TEAM_ID.com.yourapp.app"
72
+ ]
73
+ },
74
+ "applinks": {
75
+ "apps": [],
76
+ "details": [
77
+ {
78
+ "appID": "TEAM_ID.com.yourapp.app",
79
+ "paths": ["*"]
80
+ }
81
+ ]
82
+ }
83
+ }' %>
84
+ <%= f.error_message_on :preferred_apple_app_site_association %>
85
+ <% end %>
86
+ </div>
87
+ </div>
88
+ </div>
15
89
  </div>
16
90
  </div>
17
- </div>
18
91
  <% end %>
@@ -1,15 +1,14 @@
1
1
  <!-- insert_bottom "[data-hook='admin_variant_form_additional_fields']" -->
2
2
 
3
3
  <p>Guest Information Fields</p>
4
-
5
4
  <div class="form-check mb-3">
6
- <%= f.check_box :use_product_kyc, id: "toggleGuestInfo", class: 'form-check-input mr-2', checked: (@variant.kyc == nil) %>
5
+ <%= f.check_box :use_product_kyc, id: "toggleGuestInfo", class: 'form-check-input mr-2', checked: (@variant.kyc == @product.kyc) %>
7
6
  <label for="toggleGuestInfo" class="form-check-label">
8
- Use Product KYC
7
+ Use Product Guest Information
9
8
  </label>
10
9
  </div>
11
10
 
12
- <div id="guestInfoForm" <% if @variant.kyc == nil %>style="display: none;"<% end %>">
11
+ <div id="guestInfoForm" <% if @variant.kyc == @product.kyc %>style="display: none;"<% end %>">
13
12
  <small class="form-text text-muted mb-4">
14
13
  <%= raw I18n.t('kyc.variant_note') %>
15
14
  </small>
@@ -0,0 +1,12 @@
1
+ module SpreeCmCommissioner
2
+ class ReservationQuery
3
+ def initialize(vendor)
4
+ @vendor = vendor
5
+ end
6
+
7
+ def base_scope
8
+ vendor_id = @vendor&.id
9
+ SpreeCmCommissioner::Transit::OrderQueryHelper.transit_orders_for_vendor(vendor_id)
10
+ end
11
+ end
12
+ end