spree_cm_commissioner 1.18.0.pre.pre1 → 1.18.0.pre.pre3
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 +4 -4
- data/Gemfile.lock +5 -9
- data/app/controllers/spree/api/v2/storefront/guests_controller.rb +21 -19
- data/app/controllers/spree/api/v2/tenant/checkout_controller.rb +2 -0
- data/app/controllers/spree_cm_commissioner/api/v2/storefront/checkout_controller_decorator.rb +11 -0
- data/app/controllers/spree_cm_commissioner/well_known_controller.rb +21 -9
- data/app/interactors/spree_cm_commissioner/apple_app_site_association_fetcher.rb +27 -0
- data/app/interactors/spree_cm_commissioner/asset_links_fetcher.rb +27 -0
- data/app/interactors/spree_cm_commissioner/telegram_chats_auto_finder.rb +144 -0
- data/app/models/spree_cm_commissioner/pin_code.rb +3 -2
- data/app/models/spree_cm_commissioner/pin_code_telegram.rb +28 -0
- data/app/models/spree_cm_commissioner/promotion_category_decorator.rb +11 -0
- data/app/models/spree_cm_commissioner/telegram_chat.rb +6 -0
- data/app/models/spree_cm_commissioner/vendor_decorator.rb +1 -0
- data/config/locales/en.yml +1 -0
- data/db/migrate/20250630103536_create_cm_telegram_chats.rb +13 -0
- data/db/migrate/20250707032008_add_vendor_id_to_spree_category.rb +7 -0
- data/lib/spree_cm_commissioner/version.rb +1 -1
- metadata +10 -3
- data/app/interactors/spree_cm_commissioner/universal_link_fetcher.rb +0 -54
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6164958fb3e35c7708b3715aa8c5c88db95fcb47b0ba8f943e4ee0f382243b29
|
4
|
+
data.tar.gz: e0caefc60f2d2da898ff43beb800db4c693425eca118aca821db9a2f3b07b56d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a40709614ead0f6dcbb87f1da2a034e795fa261421853b5971895cd7179c0371b4efe9356c5c088079469cf46a44a2d6d80eb94b4d487b939c287272c679aed5
|
7
|
+
data.tar.gz: 92412f627c52530fae22c31a57b19c6c53239681a839876b6941c19f82a741d3c883b19099b4bd09508e7caeb42b79f1a78d65ed91b836b540e1a99318b76df5
|
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.pre.
|
37
|
+
spree_cm_commissioner (1.18.0.pre.pre3)
|
38
38
|
activerecord-multi-tenant
|
39
39
|
activerecord_json_validator (~> 2.1, >= 2.1.3)
|
40
40
|
aws-sdk-cloudfront
|
@@ -446,7 +446,6 @@ GEM
|
|
446
446
|
google-cloud-recaptcha_enterprise-v1beta1 (0.10.0)
|
447
447
|
gapic-common (>= 0.20.0, < 2.a)
|
448
448
|
google-cloud-errors (~> 1.0)
|
449
|
-
google-protobuf (3.25.8)
|
450
449
|
google-protobuf (3.25.8-x86_64-darwin)
|
451
450
|
google-protobuf (3.25.8-x86_64-linux)
|
452
451
|
googleapis-common-protos (1.4.0)
|
@@ -461,9 +460,6 @@ GEM
|
|
461
460
|
multi_json (~> 1.11)
|
462
461
|
os (>= 0.9, < 2.0)
|
463
462
|
signet (>= 0.16, < 2.a)
|
464
|
-
grpc (1.72.0)
|
465
|
-
google-protobuf (>= 3.25, < 5.0)
|
466
|
-
googleapis-common-protos-types (~> 1.0)
|
467
463
|
grpc (1.72.0-x86_64-darwin)
|
468
464
|
google-protobuf (>= 3.25, < 5.0)
|
469
465
|
googleapis-common-protos-types (~> 1.0)
|
@@ -551,7 +547,6 @@ GEM
|
|
551
547
|
method_source (1.0.0)
|
552
548
|
mini_magick (4.12.0)
|
553
549
|
mini_mime (1.1.5)
|
554
|
-
mini_portile2 (2.8.4)
|
555
550
|
minitest (5.20.0)
|
556
551
|
monetize (1.12.0)
|
557
552
|
money (~> 6.12)
|
@@ -569,8 +564,9 @@ GEM
|
|
569
564
|
net-smtp (0.4.0)
|
570
565
|
net-protocol
|
571
566
|
nio4r (2.5.9)
|
572
|
-
nokogiri (1.
|
573
|
-
|
567
|
+
nokogiri (1.18.8-x86_64-darwin)
|
568
|
+
racc (~> 1.4)
|
569
|
+
nokogiri (1.18.8-x86_64-linux-gnu)
|
574
570
|
racc (~> 1.4)
|
575
571
|
noticed (1.6.3)
|
576
572
|
http (>= 4.0.0)
|
@@ -926,11 +922,11 @@ GEM
|
|
926
922
|
zeitwerk (2.6.12)
|
927
923
|
|
928
924
|
PLATFORMS
|
929
|
-
ruby
|
930
925
|
x86_64-darwin-19
|
931
926
|
x86_64-darwin-20
|
932
927
|
x86_64-darwin-21
|
933
928
|
x86_64-darwin-22
|
929
|
+
x86_64-darwin-23
|
934
930
|
x86_64-linux
|
935
931
|
|
936
932
|
DEPENDENCIES
|
@@ -38,14 +38,25 @@ module Spree
|
|
38
38
|
def update
|
39
39
|
spree_authorize! :update, spree_current_order, order_token
|
40
40
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
41
|
+
begin
|
42
|
+
if guest_params[:guest_dynamic_fields_attributes]
|
43
|
+
resource.guest_dynamic_fields.destroy_all
|
44
|
+
|
45
|
+
guest_params[:guest_dynamic_fields_attributes].each do |attr|
|
46
|
+
field = build_dynamic_field(attr)
|
47
|
+
field.save!
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
resource.assign_attributes(guest_params.except(:guest_dynamic_fields_attributes))
|
52
|
+
|
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)
|
49
60
|
end
|
50
61
|
end
|
51
62
|
|
@@ -84,21 +95,12 @@ module Spree
|
|
84
95
|
)
|
85
96
|
end
|
86
97
|
|
87
|
-
def update_dynamic_fields
|
88
|
-
resource.guest_dynamic_fields.destroy_all
|
89
|
-
|
90
|
-
dynamic_fields_attrs = guest_params[:guest_dynamic_fields_attributes]
|
91
|
-
|
92
|
-
resource.guest_dynamic_fields = dynamic_fields_attrs.map do |attr|
|
93
|
-
build_dynamic_field(attr)
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
98
|
def build_dynamic_field(attr)
|
98
99
|
field = resource.guest_dynamic_fields.build(attr.except(:id))
|
99
100
|
|
100
101
|
if field.dynamic_field.requires_dynamic_field_options?
|
101
|
-
|
102
|
+
option = field.dynamic_field.dynamic_field_options.find_by(id: field.value)
|
103
|
+
field.dynamic_field_option = option if option
|
102
104
|
end
|
103
105
|
|
104
106
|
field
|
@@ -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)
|
data/app/controllers/spree_cm_commissioner/api/v2/storefront/checkout_controller_decorator.rb
CHANGED
@@ -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
|
@@ -4,25 +4,37 @@ module SpreeCmCommissioner
|
|
4
4
|
rescue_from StandardError, with: :handle_error
|
5
5
|
|
6
6
|
def assetlinks_json
|
7
|
-
|
7
|
+
render_platform_link(:android)
|
8
8
|
end
|
9
9
|
|
10
10
|
def apple_app_site_association
|
11
|
-
|
11
|
+
render_platform_link(:ios)
|
12
12
|
end
|
13
13
|
|
14
14
|
private
|
15
15
|
|
16
|
-
def
|
17
|
-
|
18
|
-
|
16
|
+
def render_platform_link(platform)
|
17
|
+
fetcher_class = platform_link_finder(platform)
|
18
|
+
|
19
|
+
result = fetcher_class.call(
|
19
20
|
store: @store,
|
20
21
|
tenant: @tenant,
|
21
|
-
|
22
|
-
)
|
22
|
+
refreshed: params[:_refreshed].present?
|
23
|
+
)
|
24
|
+
|
25
|
+
if result.success? && result.contents.present?
|
26
|
+
render json: result.contents
|
27
|
+
else
|
28
|
+
render_not_found
|
29
|
+
end
|
30
|
+
end
|
23
31
|
|
24
|
-
|
25
|
-
|
32
|
+
def platform_link_finder(platform)
|
33
|
+
case platform
|
34
|
+
when :android
|
35
|
+
SpreeCmCommissioner::AssetLinksFetcher
|
36
|
+
when :ios
|
37
|
+
SpreeCmCommissioner::AppleAppSiteAssociationFetcher
|
26
38
|
else
|
27
39
|
render_not_found
|
28
40
|
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
|
@@ -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
|
@@ -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',
|
data/config/locales/en.yml
CHANGED
@@ -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
|
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.pre.
|
4
|
+
version: 1.18.0.pre.pre3
|
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-
|
11
|
+
date: 2025-07-14 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
|
@@ -1116,7 +1119,6 @@ files:
|
|
1116
1119
|
- app/interactors/spree_cm_commissioner/telegram_web_app_vendor_user_checker.rb
|
1117
1120
|
- app/interactors/spree_cm_commissioner/transactional_email_sender.rb
|
1118
1121
|
- app/interactors/spree_cm_commissioner/unique_device_token_cron_executor.rb
|
1119
|
-
- app/interactors/spree_cm_commissioner/universal_link_fetcher.rb
|
1120
1122
|
- app/interactors/spree_cm_commissioner/update_payment_gateway_status.rb
|
1121
1123
|
- app/interactors/spree_cm_commissioner/user_contact_updater.rb
|
1122
1124
|
- app/interactors/spree_cm_commissioner/user_device_token_deregister.rb
|
@@ -1302,6 +1304,7 @@ files:
|
|
1302
1304
|
- app/models/spree_cm_commissioner/pin_code_mobile_confirm.rb
|
1303
1305
|
- app/models/spree_cm_commissioner/pin_code_otp.rb
|
1304
1306
|
- app/models/spree_cm_commissioner/pin_code_registration.rb
|
1307
|
+
- app/models/spree_cm_commissioner/pin_code_telegram.rb
|
1305
1308
|
- app/models/spree_cm_commissioner/pin_code_update_user_login.rb
|
1306
1309
|
- app/models/spree_cm_commissioner/place.rb
|
1307
1310
|
- app/models/spree_cm_commissioner/product_completion_step.rb
|
@@ -1321,6 +1324,7 @@ files:
|
|
1321
1324
|
- app/models/spree_cm_commissioner/promotion/rules/guest_occupations.rb
|
1322
1325
|
- app/models/spree_cm_commissioner/promotion/rules/vendors.rb
|
1323
1326
|
- app/models/spree_cm_commissioner/promotion/rules/weekend.rb
|
1327
|
+
- app/models/spree_cm_commissioner/promotion_category_decorator.rb
|
1324
1328
|
- app/models/spree_cm_commissioner/promotion_decorator.rb
|
1325
1329
|
- app/models/spree_cm_commissioner/property_decorator.rb
|
1326
1330
|
- app/models/spree_cm_commissioner/prototype_decorator.rb
|
@@ -1355,6 +1359,7 @@ files:
|
|
1355
1359
|
- app/models/spree_cm_commissioner/taxon_web_banner.rb
|
1356
1360
|
- app/models/spree_cm_commissioner/taxonomy_decorator.rb
|
1357
1361
|
- app/models/spree_cm_commissioner/telegram_bot.rb
|
1362
|
+
- app/models/spree_cm_commissioner/telegram_chat.rb
|
1358
1363
|
- app/models/spree_cm_commissioner/tenant.rb
|
1359
1364
|
- app/models/spree_cm_commissioner/transactional_email.rb
|
1360
1365
|
- app/models/spree_cm_commissioner/trip.rb
|
@@ -2518,9 +2523,11 @@ files:
|
|
2518
2523
|
- db/migrate/20250611023548_add_country_code_to_guests.rb
|
2519
2524
|
- db/migrate/20250612035937_add_intel_phone_number_to_guests.rb
|
2520
2525
|
- db/migrate/20250616084219_add_description_to_cm_vendor_place.rb
|
2526
|
+
- db/migrate/20250630103536_create_cm_telegram_chats.rb
|
2521
2527
|
- db/migrate/20250701093203_add_configurations_to_cm_dynamic_field.rb
|
2522
2528
|
- db/migrate/20250702091305_add_dynamic_field_option_to_guest_dynamic_field.rb
|
2523
2529
|
- db/migrate/20250702091935_add_status_to_dynamic_field_option.rb
|
2530
|
+
- db/migrate/20250707032008_add_vendor_id_to_spree_category.rb
|
2524
2531
|
- docker-compose.yml
|
2525
2532
|
- docs/option_types/attr_types.md
|
2526
2533
|
- docs/private_key.pem
|
@@ -1,54 +0,0 @@
|
|
1
|
-
module SpreeCmCommissioner
|
2
|
-
class UniversalLinkFetcher < BaseInteractor
|
3
|
-
delegate :universal_link, :store, :tenant, :refresh, to: :context
|
4
|
-
|
5
|
-
def call
|
6
|
-
return not_found unless resource
|
7
|
-
|
8
|
-
data = load_cached_preference(resource)
|
9
|
-
return not_found if data.blank?
|
10
|
-
|
11
|
-
{ success: true, data: data }
|
12
|
-
end
|
13
|
-
|
14
|
-
private
|
15
|
-
|
16
|
-
def resource
|
17
|
-
@resource ||= store.presence || tenant
|
18
|
-
end
|
19
|
-
|
20
|
-
def load_cached_preference(resource)
|
21
|
-
preference_key = preference_key_for(universal_link)
|
22
|
-
return nil unless preference_key && resource.respond_to?(preference_key)
|
23
|
-
|
24
|
-
updated_at = resource.try(:updated_at)&.to_i || 'no_updated_at'
|
25
|
-
cache_key = build_cache_key(universal_link, resource, updated_at)
|
26
|
-
|
27
|
-
CmAppLogger.log(label: 'LOOKING_UP_CACHE', data: { cache_key: cache_key })
|
28
|
-
|
29
|
-
Rails.cache.delete(cache_key) if refresh
|
30
|
-
|
31
|
-
Rails.cache.fetch(cache_key, expires_in: 1.day, force: refresh) do
|
32
|
-
CmAppLogger.log(label: 'CACHE_MISS', data: { cache_key: cache_key })
|
33
|
-
resource.public_send(preference_key).presence
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def build_cache_key(universal_link, resource, updated_at)
|
38
|
-
"well_known:#{universal_link}:#{resource.class.name}:#{resource.id}:#{updated_at}"
|
39
|
-
end
|
40
|
-
|
41
|
-
def preference_key_for(universal_link)
|
42
|
-
case universal_link
|
43
|
-
when 'assetlinks.json'
|
44
|
-
:preferred_assetlinks
|
45
|
-
when 'apple-app-site-association'
|
46
|
-
:preferred_apple_app_site_association
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def not_found
|
51
|
-
{ success: false, error: 'Not found' }
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|