spree_cm_commissioner 1.18.0 → 1.18.1.pre.pre1

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 (25) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/app/controllers/concerns/spree_cm_commissioner/content_cachable.rb +2 -1
  4. data/app/controllers/spree/api/v2/storefront/guests_controller.rb +25 -16
  5. data/app/controllers/spree/api/v2/tenant/checkout_controller.rb +2 -0
  6. data/app/controllers/spree_cm_commissioner/api/v2/storefront/checkout_controller_decorator.rb +11 -0
  7. data/app/controllers/spree_cm_commissioner/well_known_controller.rb +31 -17
  8. data/app/interactors/spree_cm_commissioner/apple_app_site_association_fetcher.rb +27 -0
  9. data/app/interactors/spree_cm_commissioner/asset_links_fetcher.rb +27 -0
  10. data/app/interactors/spree_cm_commissioner/telegram_chats_auto_finder.rb +144 -0
  11. data/app/models/spree_cm_commissioner/dynamic_field.rb +2 -0
  12. data/app/models/spree_cm_commissioner/dynamic_field_option.rb +2 -0
  13. data/app/models/spree_cm_commissioner/pin_code.rb +3 -2
  14. data/app/models/spree_cm_commissioner/pin_code_telegram.rb +28 -0
  15. data/app/models/spree_cm_commissioner/promotion_category_decorator.rb +11 -0
  16. data/app/models/spree_cm_commissioner/telegram_chat.rb +6 -0
  17. data/app/models/spree_cm_commissioner/vendor_decorator.rb +1 -0
  18. data/config/locales/en.yml +1 -0
  19. data/config/routes.rb +2 -1
  20. data/db/migrate/20250630103536_create_cm_telegram_chats.rb +13 -0
  21. data/db/migrate/20250707032008_add_vendor_id_to_spree_category.rb +7 -0
  22. data/db/migrate/20250711092937_add_position_to_cm_dynamic_fields.rb +11 -0
  23. data/db/migrate/20250711093045_add_position_to_cm_dynamic_field_options.rb +11 -0
  24. data/lib/spree_cm_commissioner/version.rb +1 -1
  25. metadata +14 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2c10fd2782b1a1ac7ecab5d27e02a49212f8e816f8f2325fadbcd717fe9882e9
4
- data.tar.gz: 3b1b296e3403e5dd040063c19a3ac4952afafb617af17cd2ca924ea8df25de23
3
+ metadata.gz: a6ca2c2a15690b9e44ae0b587937dd1276de763f86c333f23411069e7de81d15
4
+ data.tar.gz: 6ff68f2da2bd156cd2b00f3112ed3b911751a02c8140e5b531d01d1cd253f7a8
5
5
  SHA512:
6
- metadata.gz: 1f31cf8a9073664246d505c0494b2da2dc6565ec14c57fae06f34320039a478af4d8a1e0ee5eb1e68c42a5de37baf393bee0e791f7d9dfb8fd2b66356f143566
7
- data.tar.gz: e29ba3d6d3e2d8343209260edd69117fe67c14ea1c20c13891b6cd9930f044467daa7b2fffaff51ab27db42e98eb7f43a85254e33a4644927e3eb61a1e9d742f
6
+ metadata.gz: fbab9958f2ab7a92001a3118f068865a93bd222ebabf538a08cfdedfcdba27a57712f45d3f9edf179b4dc58596b8e799f28a421516130793240fd35f0f2f3df1
7
+ data.tar.gz: 35043475636128680bf5817039ac9b0153909d796f3f7c4b97a5f5e66a688512690a85766673ffa1a3fce9cfc74eb2a59f2061bec578d534abdc663dcaba089d
data/Gemfile.lock CHANGED
@@ -34,7 +34,7 @@ GIT
34
34
  PATH
35
35
  remote: .
36
36
  specs:
37
- spree_cm_commissioner (1.18.0)
37
+ spree_cm_commissioner (1.18.1.pre.pre1)
38
38
  activerecord-multi-tenant
39
39
  activerecord_json_validator (~> 2.1, >= 2.1.3)
40
40
  aws-sdk-cloudfront
@@ -6,8 +6,9 @@ module SpreeCmCommissioner
6
6
  after_action :set_cache_control_for_cdn
7
7
  end
8
8
 
9
+ # Override This Method based on your UseCase
9
10
  def max_age
10
- ENV.fetch('CONTENT_CACHE_MAX_AGE', '180')
11
+ ENV.fetch('CONTENT_CACHE_MAX_AGE', 1.day.to_i).to_i
11
12
  end
12
13
 
13
14
  def set_cache_control_for_cdn
@@ -38,27 +38,25 @@ module Spree
38
38
  def update
39
39
  spree_authorize! :update, spree_current_order, order_token
40
40
 
41
- if guest_params[:guest_dynamic_fields_attributes]
42
- resource.guest_dynamic_fields.destroy_all
41
+ begin
42
+ if guest_params[:guest_dynamic_fields_attributes]
43
+ resource.guest_dynamic_fields.destroy_all
43
44
 
44
- guest_params[:guest_dynamic_fields_attributes].each do |attr|
45
- field = resource.guest_dynamic_fields.build(attr.except(:id))
46
-
47
- if field.dynamic_field.requires_dynamic_field_options?
48
- option = field.dynamic_field.dynamic_field_options.find_by(id: field.value)
49
- field.dynamic_field_option = option if option
45
+ guest_params[:guest_dynamic_fields_attributes].each do |attr|
46
+ field = build_dynamic_field(attr)
47
+ field.save!
50
48
  end
51
-
52
- field.save!
53
49
  end
54
- end
55
50
 
56
- resource.assign_attributes(guest_params.except(:guest_dynamic_fields_attributes))
51
+ resource.assign_attributes(guest_params.except(:guest_dynamic_fields_attributes))
57
52
 
58
- if resource.save
59
- render_serialized_payload { serialize_resource(resource) }
60
- else
61
- render_error_payload(resource, 400)
53
+ if resource.save
54
+ render_serialized_payload { serialize_resource(resource) }
55
+ else
56
+ render_error_payload(resource.errors, 400)
57
+ end
58
+ rescue ActiveRecord::RecordInvalid => e
59
+ render_error_payload(e.record.errors, 400)
62
60
  end
63
61
  end
64
62
 
@@ -96,6 +94,17 @@ module Spree
96
94
  guest_dynamic_fields_attributes: %i[id dynamic_field_id dynamic_field_option_id value _destroy]
97
95
  )
98
96
  end
97
+
98
+ def build_dynamic_field(attr)
99
+ field = resource.guest_dynamic_fields.build(attr.except(:id))
100
+
101
+ if field.dynamic_field.requires_dynamic_field_options?
102
+ option = field.dynamic_field.dynamic_field_options.find_by(id: field.value)
103
+ field.dynamic_field_option = option if option
104
+ end
105
+
106
+ field
107
+ end
99
108
  end
100
109
  end
101
110
  end
@@ -27,6 +27,8 @@ module Spree
27
27
  end
28
28
 
29
29
  def complete
30
+ return render_serialized_payload { serialized_current_order } if spree_current_order.confirm? || spree_current_order.complete?
31
+
30
32
  spree_authorize! :update, spree_current_order, order_token
31
33
 
32
34
  result = complete_service.call(order: spree_current_order)
@@ -6,6 +6,17 @@ module SpreeCmCommissioner
6
6
  def self.prepended(base)
7
7
  base.include SpreeCmCommissioner::OrderConcern
8
8
  end
9
+
10
+ # Override Spree's default behavior:
11
+ # By default, Spree raises an error if `complete` is called on a completed or confirmed order.
12
+ # We want to allow this call to succeed, so the API can be used both to:
13
+ # - complete the order (if it's not yet complete), or
14
+ # - return the latest state of a confirmed or completed order without raising a forbidden error.
15
+ def complete
16
+ return render_serialized_payload { serialized_current_order } if spree_current_order.confirm? || spree_current_order.complete?
17
+
18
+ super
19
+ end
9
20
  end
10
21
  end
11
22
  end
@@ -3,18 +3,42 @@ module SpreeCmCommissioner
3
3
  before_action :identify_request_source
4
4
  rescue_from StandardError, with: :handle_error
5
5
 
6
- def show
7
- case params[:id]
8
- when 'assetlinks.json'
9
- render_preference(:preferred_assetlinks)
10
- when 'apple-app-site-association'
11
- render_preference(:preferred_apple_app_site_association)
6
+ def assetlinks_json
7
+ render_platform_link(:android)
8
+ end
9
+
10
+ def apple_app_site_association
11
+ render_platform_link(:ios)
12
+ end
13
+
14
+ private
15
+
16
+ def render_platform_link(platform)
17
+ fetcher_class = platform_link_finder(platform)
18
+
19
+ result = fetcher_class.call(
20
+ store: @store,
21
+ tenant: @tenant,
22
+ refreshed: params[:_refreshed].present?
23
+ )
24
+
25
+ if result.success? && result.contents.present?
26
+ render json: result.contents
12
27
  else
13
28
  render_not_found
14
29
  end
15
30
  end
16
31
 
17
- private
32
+ def platform_link_finder(platform)
33
+ case platform
34
+ when :android
35
+ SpreeCmCommissioner::AssetLinksFetcher
36
+ when :ios
37
+ SpreeCmCommissioner::AppleAppSiteAssociationFetcher
38
+ else
39
+ render_not_found
40
+ end
41
+ end
18
42
 
19
43
  def identify_request_source
20
44
  host = params[:original_host].presence || request.host.downcase
@@ -25,16 +49,6 @@ module SpreeCmCommissioner
25
49
  @tenant = result.tenant
26
50
  end
27
51
 
28
- def render_preference(preference_key)
29
- if @store&.send(preference_key).present?
30
- render json: @store.send(preference_key)
31
- elsif @tenant&.send(preference_key).present?
32
- render json: @tenant.send(preference_key)
33
- else
34
- render_not_found
35
- end
36
- end
37
-
38
52
  def render_not_found
39
53
  render json: { error: 'Not found' }, status: :not_found
40
54
  end
@@ -0,0 +1,27 @@
1
+ module SpreeCmCommissioner
2
+ class AppleAppSiteAssociationFetcher < BaseInteractor
3
+ delegate :store, :tenant, :refreshed, to: :context
4
+
5
+ def call
6
+ key = cache_key
7
+
8
+ CmAppLogger.log(label: 'LOOKING_UP_CACHE', data: { cache_key: key })
9
+
10
+ Rails.cache.delete(key) if refreshed
11
+
12
+ context.contents = Rails.cache.fetch(key) do
13
+ CmAppLogger.log(label: 'CACHE_MISS', data: { cache_key: key })
14
+ resource.preferred_apple_app_site_association
15
+ end
16
+ end
17
+
18
+ def cache_key
19
+ updated_at = tenant&.updated_at || store&.updated_at
20
+ "well_known:apple-app-site-association:#{resource.class.name}:#{resource.id}:#{updated_at}"
21
+ end
22
+
23
+ def resource
24
+ tenant || store
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ module SpreeCmCommissioner
2
+ class AssetLinksFetcher < BaseInteractor
3
+ delegate :store, :tenant, :refreshed, to: :context
4
+
5
+ def call
6
+ key = cache_key
7
+
8
+ CmAppLogger.log(label: 'LOOKING_UP_CACHE', data: { cache_key: key })
9
+
10
+ Rails.cache.delete(key) if refreshed
11
+
12
+ context.contents = Rails.cache.fetch(key) do
13
+ CmAppLogger.log(label: 'CACHE_MISS', data: { cache_key: key })
14
+ resource.preferred_assetlinks
15
+ end
16
+ end
17
+
18
+ def cache_key
19
+ updated_at = tenant&.updated_at || store&.updated_at
20
+ "well_known:assetlinks.json:#{resource.class.name}:#{resource.id}:#{updated_at}"
21
+ end
22
+
23
+ def resource
24
+ tenant || store
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,144 @@
1
+ module SpreeCmCommissioner
2
+ class TelegramChatsAutoFinder < BaseInteractor
3
+ delegate :contact, :pin_code, to: :context
4
+
5
+ def call
6
+ context.chats = []
7
+ context.verified_chat_ids = []
8
+
9
+ updates = fetch_updates
10
+
11
+ if updates['result'].any?
12
+ updates['result'].sort_by { |u| u['update_id'] }.reverse.each do |update|
13
+ handle_message_update(update) if update['message']
14
+ handle_channel_post_update(update) if update['channel_post']
15
+ handle_chat_member_update(update) if update['my_chat_member']
16
+ end
17
+ end
18
+ context.fail!(message: 'No pin codes verified') if context.verified_chat_ids.empty?
19
+ end
20
+
21
+ private
22
+
23
+ def handle_chat_member_update(update)
24
+ chat = update.dig('my_chat_member', 'chat')
25
+ return unless chat
26
+
27
+ chat_data = {
28
+ id: chat['id'],
29
+ title: chat['title'] || 'Unnamed Chat',
30
+ type: chat['type']
31
+ }
32
+
33
+ return if context.chats.any? { |c| c[:id] == chat_data[:id] }
34
+
35
+ db_chat = SpreeCmCommissioner::TelegramChat.find_or_initialize_by(chat_id: chat_data[:id])
36
+ is_new_chat = db_chat.new_record?
37
+ db_chat.update(chat_title: chat_data[:title], chat_type: chat_data[:type])
38
+ context.chats << chat_data
39
+ message = "👋Hello! This is Bookme+ bot.\n\nPlease enter the 6-digit PIN code displayed in your portal."
40
+ send_message(chat_data[:id], message) if is_new_chat
41
+ end
42
+
43
+ def handle_channel_post_update(update)
44
+ message = update['channel_post']
45
+ process_pin_code_message(message)
46
+ end
47
+
48
+ def handle_message_update(update)
49
+ message = update['message']
50
+ process_pin_code_message(message)
51
+ end
52
+
53
+ def process_pin_code_message(message)
54
+ chat_id = message.dig('chat', 'id')
55
+ text = message['text']&.strip
56
+
57
+ return unless valid_pin_code?(text, chat_id)
58
+
59
+ pin_code_record = find_pin_code_record
60
+ return unless pin_code_record
61
+
62
+ vendor = find_vendor
63
+ return unless vendor
64
+
65
+ chat = update_telegram_chat(message, chat_id)
66
+ return unless chat
67
+
68
+ handle_successful_verification(chat, vendor, pin_code_record)
69
+ end
70
+
71
+ def valid_pin_code?(text, chat_id)
72
+ text && chat_id && text == pin_code
73
+ end
74
+
75
+ def find_pin_code_record
76
+ pin_code_record = SpreeCmCommissioner::PinCodeTelegram.find_by(code: pin_code, contact: contact)
77
+ unless pin_code_record
78
+ context.fail!(message: "Pin code #{pin_code} not found for contact #{contact}")
79
+ return nil
80
+ end
81
+ pin_code_record
82
+ end
83
+
84
+ def find_vendor
85
+ vendor = Spree::Vendor.find_by(id: contact)
86
+ unless vendor
87
+ context.fail!(message: "Vendor not found for contact #{contact}")
88
+ return nil
89
+ end
90
+ vendor
91
+ end
92
+
93
+ def update_telegram_chat(message, chat_id)
94
+ chat = SpreeCmCommissioner::TelegramChat.find_or_initialize_by(chat_id: chat_id)
95
+ unless chat.update(
96
+ chat_title: message.dig('chat', 'title') || 'Unnamed Chat',
97
+ chat_type: message.dig('chat', 'type')
98
+ )
99
+ context.fail!(message: "Failed to update chat: #{chat.errors.full_messages.join(', ')}")
100
+ return nil
101
+ end
102
+
103
+ context.chats << { id: chat.chat_id, title: chat.chat_title, type: chat.chat_type }
104
+ chat
105
+ end
106
+
107
+ def handle_successful_verification(chat, vendor, pin_code_record)
108
+ return if chat.vendor && chat.vendor != vendor
109
+
110
+ update_vendor_preferences(vendor, chat)
111
+ chat.update(active: true, vendor: vendor)
112
+ expire_pin_code(pin_code_record)
113
+ send_success_message(chat.chat_id, vendor.name)
114
+ context.verified_chat_ids << chat.chat_id
115
+ end
116
+
117
+ def update_vendor_preferences(vendor, chat)
118
+ vendor.update(
119
+ preferred_telegram_chat_id: chat.chat_id,
120
+ preferred_telegram_chat_name: chat.chat_title,
121
+ preferred_telegram_chat_type: chat.chat_type
122
+ )
123
+ end
124
+
125
+ def expire_pin_code(pin_code_record)
126
+ pin_code_record.expire
127
+ pin_code_record.save
128
+ end
129
+
130
+ def send_success_message(chat_id, vendor_name)
131
+ message = "✅ PIN code verified successfully! This chat is now connected to <b>#{vendor_name}</b>.\n\n" \
132
+ 'All completed orders will be sent to this chat.'
133
+ send_message(chat_id, message)
134
+ end
135
+
136
+ def fetch_updates
137
+ ::Telegram.bot.get_updates
138
+ end
139
+
140
+ def send_message(chat_id, text)
141
+ ::Telegram.bot.send_message(chat_id: chat_id, text: text, parse_mode: 'HTML')
142
+ end
143
+ end
144
+ end
@@ -1,5 +1,7 @@
1
1
  module SpreeCmCommissioner
2
2
  class DynamicField < SpreeCmCommissioner::Base
3
+ acts_as_list column: :position, scope: :vendor_id
4
+
3
5
  belongs_to :vendor, class_name: 'Spree::Vendor', optional: false
4
6
 
5
7
  has_many :dynamic_field_options, class_name: 'SpreeCmCommissioner::DynamicFieldOption', dependent: :destroy
@@ -1,5 +1,7 @@
1
1
  module SpreeCmCommissioner
2
2
  class DynamicFieldOption < SpreeCmCommissioner::Base
3
+ acts_as_list column: :position, scope: :dynamic_field_id
4
+
3
5
  belongs_to :dynamic_field, class_name: 'SpreeCmCommissioner::DynamicField', optional: false
4
6
  has_many :guest_dynamic_fields, class_name: 'SpreeCmCommissioner::GuestDynamicField', dependent: :restrict_with_error
5
7
 
@@ -2,7 +2,7 @@ module SpreeCmCommissioner
2
2
  class PinCode < SpreeCmCommissioner::Base
3
3
  has_secure_token
4
4
 
5
- enum contact_type: { 'phone_number' => 0, 'email' => 1 }
5
+ enum contact_type: { 'phone_number' => 0, 'email' => 1, 'telegram' => 2 }
6
6
 
7
7
  validates :code, length: { maximum: 6 }
8
8
  validates :contact, presence: true
@@ -130,7 +130,8 @@ module SpreeCmCommissioner
130
130
  'SpreeCmCommissioner::PinCodeMobileConfirm' => I18n.t('pincode.readable_type.confirmation_code'),
131
131
  'SpreeCmCommissioner::PinCodeUpdateUserLogin' => I18n.t('pincode.readable_type.update_user_login'),
132
132
  'SpreeCmCommissioner::PinCodeEmailConfirm' => I18n.t('pincode.readable_type.confirmation_code'),
133
- 'SpreeCmCommissioner::OtpCode' => I18n.t('pincode.readable_type.otp_code')
133
+ 'SpreeCmCommissioner::OtpCode' => I18n.t('pincode.readable_type.otp_code'),
134
+ 'SpreeCmCommissioner::PinCodeTelegram' => I18n.t('pincode.readable_type.telegram_verification')
134
135
  }
135
136
  end
136
137
 
@@ -0,0 +1,28 @@
1
+ module SpreeCmCommissioner
2
+ class PinCodeTelegram < PinCode
3
+ before_validation :set_telegram_attrs, on: :create
4
+ validates :contact, presence: true, numericality: { only_integer: true }, if: :telegram?
5
+
6
+ belongs_to :vendor, class_name: 'Spree::Vendor', foreign_key: 'contact', primary_key: 'id'
7
+
8
+ def telegram?
9
+ true
10
+ end
11
+
12
+ def expires_in_seconds
13
+ 5 * 60
14
+ end
15
+
16
+ def expired?
17
+ expired_at < Time.zone.now
18
+ end
19
+
20
+ private
21
+
22
+ def set_telegram_attrs
23
+ self.contact_type = :telegram
24
+ self.type = 'SpreeCmCommissioner::PinCodeTelegram'
25
+ self.expired_at = Time.zone.now + expires_in_seconds unless expired_at
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,11 @@
1
+ module SpreeCmCommissioner
2
+ module PromotionCategoryDecorator
3
+ def self.prepended(base)
4
+ base.belongs_to :vendor, class_name: 'Spree::Vendor', optional: true
5
+ end
6
+ end
7
+ end
8
+
9
+ unless Spree::PromotionCategory.included_modules.include?(SpreeCmCommissioner::PromotionCategoryDecorator)
10
+ Spree::PromotionCategory.prepend(SpreeCmCommissioner::PromotionCategoryDecorator)
11
+ end
@@ -0,0 +1,6 @@
1
+ module SpreeCmCommissioner
2
+ class TelegramChat < Base
3
+ belongs_to :vendor, class_name: 'Spree::Vendor'
4
+ validates :chat_id, presence: true, uniqueness: true
5
+ end
6
+ end
@@ -78,6 +78,7 @@ module SpreeCmCommissioner
78
78
  base.has_many :invoices, class_name: 'SpreeCmCommissioner::Invoice', dependent: :destroy
79
79
  base.has_many :subscriptions, through: :customers, class_name: 'SpreeCmCommissioner::Subscription'
80
80
  base.has_many :subscription_orders, through: :subscriptions, class_name: 'Spree::Order', source: :orders
81
+ base.has_many :promotion_categories, class_name: 'Spree::PromotionCategory', foreign_key: :vendor_id, dependent: :destroy
81
82
 
82
83
  base.has_many :homepage_section_relatables,
83
84
  class_name: 'SpreeCmCommissioner::HomepageSectionRelatable',
@@ -547,6 +547,7 @@ en:
547
547
  update_user_login: "update user code"
548
548
  contact_update: "update contact code"
549
549
  otp_code: "OTP code"
550
+ telegram_verification: "telegram code"
550
551
 
551
552
  notifications:
552
553
  spree_cm_commissioner:
data/config/routes.rb CHANGED
@@ -669,5 +669,6 @@ Rails.application.routes.draw do
669
669
  get 'o/:id', to: 'spree_cm_commissioner/orders#show', as: 'order'
670
670
  get 'li/:id', to: 'spree_cm_commissioner/line_item_qr_images#show', as: 'line_item_qr_image'
671
671
  get 'g/:id', to: 'spree_cm_commissioner/guest_cards#show', as: 'guest_cards'
672
- get '.well-known/:id', to: 'spree_cm_commissioner/well_known#show', constraints: { id: /(assetlinks\.json|apple-app-site-association)/ }
672
+ get '.well-known/assetlinks.json', to: 'spree_cm_commissioner/well_known#assetlinks_json'
673
+ get '.well-known/apple-app-site-association', to: 'spree_cm_commissioner/well_known#apple_app_site_association'
673
674
  end
@@ -0,0 +1,13 @@
1
+ class CreateCmTelegramChats < ActiveRecord::Migration[7.0]
2
+ def change
3
+ create_table :cm_telegram_chats, if_not_exists: true do |t|
4
+ t.bigint :chat_id, null: false
5
+ t.string :chat_title
6
+ t.string :chat_type
7
+ t.boolean :active, default: false
8
+ t.references :vendor, foreign_key: { to_table: :spree_vendors }
9
+ t.timestamps
10
+ end
11
+ add_index :cm_telegram_chats, :chat_id, unique: true, if_not_exists: true
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ class AddVendorIdToSpreeCategory < ActiveRecord::Migration[7.0]
2
+ def change
3
+ unless column_exists?(:spree_promotion_categories, :vendor_id)
4
+ add_reference :spree_promotion_categories, :vendor, index: true, foreign_key: { to_table: :spree_vendors }
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,11 @@
1
+ class AddPositionToCmDynamicFields < ActiveRecord::Migration[7.0]
2
+ def change
3
+ unless column_exists?(:cm_dynamic_fields, :position)
4
+ add_column :cm_dynamic_fields, :position, :integer, default: 0, null: false
5
+ end
6
+
7
+ unless index_exists?(:cm_dynamic_fields, :position, name: 'index_dynamic_fields_on_position')
8
+ add_index :cm_dynamic_fields, :position, name: 'index_dynamic_fields_on_position'
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ class AddPositionToCmDynamicFieldOptions < ActiveRecord::Migration[7.0]
2
+ def change
3
+ unless column_exists?(:cm_dynamic_field_options, :position)
4
+ add_column :cm_dynamic_field_options, :position, :integer, default: 0, null: false
5
+ end
6
+
7
+ unless index_exists?(:cm_dynamic_field_options, :position, name: 'index_dynamic_field_options_on_position')
8
+ add_index :cm_dynamic_field_options, :position, name: 'index_dynamic_field_options_on_position'
9
+ end
10
+ end
11
+ end
@@ -1,5 +1,5 @@
1
1
  module SpreeCmCommissioner
2
- VERSION = '1.18.0'.freeze
2
+ VERSION = '1.18.1-pre1'.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: 1.18.0
4
+ version: 1.18.1.pre.pre1
5
5
  platform: ruby
6
6
  authors:
7
7
  - You
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-07-07 00:00:00.000000000 Z
11
+ date: 2025-07-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: spree
@@ -1038,7 +1038,9 @@ files:
1038
1038
  - app/interactors/spree_cm_commissioner/account_linkage.rb
1039
1039
  - app/interactors/spree_cm_commissioner/account_recover.rb
1040
1040
  - app/interactors/spree_cm_commissioner/account_updater.rb
1041
+ - app/interactors/spree_cm_commissioner/apple_app_site_association_fetcher.rb
1041
1042
  - app/interactors/spree_cm_commissioner/apply_service_availability.rb
1043
+ - app/interactors/spree_cm_commissioner/asset_links_fetcher.rb
1042
1044
  - app/interactors/spree_cm_commissioner/base_interactor.rb
1043
1045
  - app/interactors/spree_cm_commissioner/bib_number_swapper.rb
1044
1046
  - app/interactors/spree_cm_commissioner/chatrace_order_creator.rb
@@ -1107,6 +1109,7 @@ files:
1107
1109
  - app/interactors/spree_cm_commissioner/subscriptions_order_creator.rb
1108
1110
  - app/interactors/spree_cm_commissioner/subscriptions_order_cron_executor.rb
1109
1111
  - app/interactors/spree_cm_commissioner/subscriptions_prepaid_order_creator.rb
1112
+ - app/interactors/spree_cm_commissioner/telegram_chats_auto_finder.rb
1110
1113
  - app/interactors/spree_cm_commissioner/telegram_chats_finder.rb
1111
1114
  - app/interactors/spree_cm_commissioner/telegram_debug_pin_code_sender.rb
1112
1115
  - app/interactors/spree_cm_commissioner/telegram_notification_sender.rb
@@ -1301,6 +1304,7 @@ files:
1301
1304
  - app/models/spree_cm_commissioner/pin_code_mobile_confirm.rb
1302
1305
  - app/models/spree_cm_commissioner/pin_code_otp.rb
1303
1306
  - app/models/spree_cm_commissioner/pin_code_registration.rb
1307
+ - app/models/spree_cm_commissioner/pin_code_telegram.rb
1304
1308
  - app/models/spree_cm_commissioner/pin_code_update_user_login.rb
1305
1309
  - app/models/spree_cm_commissioner/place.rb
1306
1310
  - app/models/spree_cm_commissioner/product_completion_step.rb
@@ -1320,6 +1324,7 @@ files:
1320
1324
  - app/models/spree_cm_commissioner/promotion/rules/guest_occupations.rb
1321
1325
  - app/models/spree_cm_commissioner/promotion/rules/vendors.rb
1322
1326
  - app/models/spree_cm_commissioner/promotion/rules/weekend.rb
1327
+ - app/models/spree_cm_commissioner/promotion_category_decorator.rb
1323
1328
  - app/models/spree_cm_commissioner/promotion_decorator.rb
1324
1329
  - app/models/spree_cm_commissioner/property_decorator.rb
1325
1330
  - app/models/spree_cm_commissioner/prototype_decorator.rb
@@ -1354,6 +1359,7 @@ files:
1354
1359
  - app/models/spree_cm_commissioner/taxon_web_banner.rb
1355
1360
  - app/models/spree_cm_commissioner/taxonomy_decorator.rb
1356
1361
  - app/models/spree_cm_commissioner/telegram_bot.rb
1362
+ - app/models/spree_cm_commissioner/telegram_chat.rb
1357
1363
  - app/models/spree_cm_commissioner/tenant.rb
1358
1364
  - app/models/spree_cm_commissioner/transactional_email.rb
1359
1365
  - app/models/spree_cm_commissioner/trip.rb
@@ -2517,9 +2523,13 @@ files:
2517
2523
  - db/migrate/20250611023548_add_country_code_to_guests.rb
2518
2524
  - db/migrate/20250612035937_add_intel_phone_number_to_guests.rb
2519
2525
  - db/migrate/20250616084219_add_description_to_cm_vendor_place.rb
2526
+ - db/migrate/20250630103536_create_cm_telegram_chats.rb
2520
2527
  - db/migrate/20250701093203_add_configurations_to_cm_dynamic_field.rb
2521
2528
  - db/migrate/20250702091305_add_dynamic_field_option_to_guest_dynamic_field.rb
2522
2529
  - db/migrate/20250702091935_add_status_to_dynamic_field_option.rb
2530
+ - db/migrate/20250707032008_add_vendor_id_to_spree_category.rb
2531
+ - db/migrate/20250711092937_add_position_to_cm_dynamic_fields.rb
2532
+ - db/migrate/20250711093045_add_position_to_cm_dynamic_field_options.rb
2523
2533
  - docker-compose.yml
2524
2534
  - docs/option_types/attr_types.md
2525
2535
  - docs/private_key.pem
@@ -2672,9 +2682,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
2672
2682
  version: '2.7'
2673
2683
  required_rubygems_version: !ruby/object:Gem::Requirement
2674
2684
  requirements:
2675
- - - ">="
2685
+ - - ">"
2676
2686
  - !ruby/object:Gem::Version
2677
- version: '0'
2687
+ version: 1.3.1
2678
2688
  requirements:
2679
2689
  - none
2680
2690
  rubygems_version: 3.4.1