spree_cm_commissioner 2.5.2.pre.pre3 → 2.5.2
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 +1 -1
- data/app/controllers/spree/api/v2/storefront/active_homepage_events_controller.rb +1 -6
- data/app/controllers/spree/api/v2/storefront/homepage_data_controller.rb +35 -4
- data/app/controllers/spree/api/v2/storefront/homepage_sections_controller.rb +4 -41
- data/app/controllers/spree/api/v2/storefront/invite_guests_controller.rb +2 -11
- data/app/interactors/spree_cm_commissioner/conversion_pre_calculator.rb +12 -3
- data/app/interactors/spree_cm_commissioner/notification_reader.rb +3 -1
- data/app/models/concerns/spree_cm_commissioner/option_type_attr_type.rb +1 -2
- data/app/models/concerns/spree_cm_commissioner/order_state_machine.rb +28 -4
- data/app/models/concerns/spree_cm_commissioner/variant_options_concern.rb +0 -1
- data/app/models/spree_cm_commissioner/guest.rb +3 -24
- data/app/models/spree_cm_commissioner/notification.rb +28 -0
- data/app/models/spree_cm_commissioner/taxon_decorator.rb +0 -26
- data/app/models/spree_cm_commissioner/variant_options.rb +0 -5
- data/app/serializers/spree/v2/storefront/product_serializer_decorator.rb +7 -36
- data/app/serializers/spree/v2/storefront/user_serializer_decorator.rb +2 -1
- data/app/serializers/spree_cm_commissioner/v2/storefront/homepage_data_serializer.rb +3 -9
- data/app/services/spree_cm_commissioner/guests/finalize.rb +76 -0
- data/app/services/spree_cm_commissioner/homepage_data.rb +23 -0
- data/app/services/spree_cm_commissioner/user_counters_service.rb +55 -0
- data/app/views/spree/admin/classifications/edit.html.erb +1 -1
- data/db/migrate/20260128043540_add_counter_cache_to_spree_users.rb +6 -0
- data/lib/spree_cm_commissioner/test_helper/factories/option_type_factory.rb +0 -6
- data/lib/spree_cm_commissioner/test_helper/factories/product_factory.rb +0 -13
- data/lib/spree_cm_commissioner/version.rb +1 -1
- metadata +7 -7
- data/app/controllers/concerns/spree/api/v2/product_list_includes_decorator.rb +0 -37
- data/app/controllers/spree/api/v2/storefront/products_controller_decorator.rb +0 -27
- data/app/controllers/spree/api/v2/storefront/taxons_controller_decorator.rb +0 -92
- data/app/models/spree/stock/quantifier_decorator.rb +0 -26
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 847e4b0b554ef076b2daeafe2d90509a434254ef6bb7bc19d34905d9a72f5a42
|
|
4
|
+
data.tar.gz: ce1c22521e38c5d012d2cb3fbe1ac041958a6054808c9b1786f4446a3046483d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1bfbb01640f43c2b9540063a8c5e368b44b4009ecd27653f739c030c65ceffcdc48d1141d466f90e2870d3c088f933260366f9db3f3bfb4b1c68dba402f5522e
|
|
7
|
+
data.tar.gz: 7f128de24e2ad50a06c9a148dc37c2ccc4e8396077a32c2456a89a35b45236562073a185f67e8e50dca5b1a59efd9b6dbcfeef2018aa63becc88b334fa070609
|
data/Gemfile.lock
CHANGED
|
@@ -6,12 +6,7 @@ module Spree
|
|
|
6
6
|
private
|
|
7
7
|
|
|
8
8
|
def collection
|
|
9
|
-
@collection ||= model_class.active_homepage_events
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def serialize_collection(collection)
|
|
13
|
-
model_class.preload_ancestors_for(collection)
|
|
14
|
-
super(collection)
|
|
9
|
+
@collection ||= model_class.active_homepage_events
|
|
15
10
|
end
|
|
16
11
|
|
|
17
12
|
def model_class
|
|
@@ -3,12 +3,43 @@ module Spree
|
|
|
3
3
|
module V2
|
|
4
4
|
module Storefront
|
|
5
5
|
class HomepageDataController < ::Spree::Api::V2::ResourceController
|
|
6
|
+
before_action :load_homepage_background, only: [:show]
|
|
7
|
+
before_action :load_menu, only: [:show]
|
|
8
|
+
|
|
6
9
|
def show
|
|
7
|
-
|
|
10
|
+
resource = SpreeCmCommissioner::HomepageData.new(
|
|
11
|
+
menu: @menu,
|
|
12
|
+
homepage_background: @homepage_background
|
|
13
|
+
)
|
|
14
|
+
render_serialized_payload { serialize_resource(resource) }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def serialize_resource(resource)
|
|
20
|
+
resource_serializer.new(
|
|
21
|
+
resource,
|
|
22
|
+
params: serializer_params,
|
|
23
|
+
include: resource_includes
|
|
24
|
+
).serializable_hash
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def load_homepage_background
|
|
28
|
+
@homepage_background ||= SpreeCmCommissioner::HomepageBackground
|
|
29
|
+
.active
|
|
30
|
+
.includes(:app_image, :web_image)
|
|
31
|
+
.where(segment: params[:segment] || :general)
|
|
32
|
+
.order(priority: :asc)
|
|
33
|
+
.first
|
|
34
|
+
end
|
|
8
35
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
36
|
+
def load_menu
|
|
37
|
+
# Spree::Menu::MENU_LOCATIONS = ['Header', 'Footer']
|
|
38
|
+
# Current our homepage use only location: header
|
|
39
|
+
@menu ||= Spree::Menu.by_locale(I18n.locale)
|
|
40
|
+
.includes({ menu_items: %i[children parent icon] })
|
|
41
|
+
.where(location: 'header')
|
|
42
|
+
.first
|
|
12
43
|
end
|
|
13
44
|
|
|
14
45
|
def resource_serializer
|
|
@@ -16,47 +16,10 @@ module Spree
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def collection
|
|
19
|
-
@collection
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
.includes(preload_associations)
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def preload_associations
|
|
27
|
-
{
|
|
28
|
-
homepage_section_relatables: {
|
|
29
|
-
relatable: [
|
|
30
|
-
:icon,
|
|
31
|
-
{
|
|
32
|
-
home_banner: { attachment_attachment: :blob }
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
category_icon: { attachment_attachment: :blob }
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
video_banner: { attachment_attachment: :blob }
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
app_banner: { attachment_attachment: :blob }
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
web_banner: { attachment_attachment: :blob }
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
children: [
|
|
48
|
-
:icon,
|
|
49
|
-
{
|
|
50
|
-
vendors: [
|
|
51
|
-
{ photos: { attachment_attachment: :blob } },
|
|
52
|
-
:default_state
|
|
53
|
-
]
|
|
54
|
-
}
|
|
55
|
-
]
|
|
56
|
-
}
|
|
57
|
-
]
|
|
58
|
-
}
|
|
59
|
-
}
|
|
19
|
+
@collection ||= model_class.filter_by_segment(params[:homepage_id] || :general)
|
|
20
|
+
.active
|
|
21
|
+
.where(tenant_id: nil)
|
|
22
|
+
.order(position: :asc)
|
|
60
23
|
end
|
|
61
24
|
end
|
|
62
25
|
end
|
|
@@ -42,17 +42,8 @@ module Spree
|
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
def load_invite_guest_by_token
|
|
45
|
-
@invite_guest = SpreeCmCommissioner::InviteGuest.
|
|
46
|
-
|
|
47
|
-
line_items: {
|
|
48
|
-
guests: %i[
|
|
49
|
-
guest_dynamic_fields
|
|
50
|
-
id_card
|
|
51
|
-
check_in
|
|
52
|
-
]
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
).find_by(token: params[:id])
|
|
45
|
+
@invite_guest = SpreeCmCommissioner::InviteGuest.find_by!(token: params[:id])
|
|
46
|
+
rescue ActiveRecord::RecordNotFound
|
|
56
47
|
render_error_payload(I18n.t('invite.url_not_found'))
|
|
57
48
|
end
|
|
58
49
|
|
|
@@ -5,7 +5,7 @@ module SpreeCmCommissioner
|
|
|
5
5
|
def call
|
|
6
6
|
update_conversion
|
|
7
7
|
reassign_guests_event_id
|
|
8
|
-
|
|
8
|
+
refinalize_guests
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
def update_conversion
|
|
@@ -28,14 +28,23 @@ module SpreeCmCommissioner
|
|
|
28
28
|
end
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
-
def
|
|
31
|
+
def refinalize_guests
|
|
32
32
|
return if event_id.blank?
|
|
33
33
|
|
|
34
34
|
SpreeCmCommissioner::Guest
|
|
35
35
|
.complete
|
|
36
36
|
.where(event_id: event_id)
|
|
37
37
|
.none_bib
|
|
38
|
-
.find_each
|
|
38
|
+
.find_each do |guest|
|
|
39
|
+
result = SpreeCmCommissioner::Guests::Finalize.call(
|
|
40
|
+
guest: guest,
|
|
41
|
+
user: guest.line_item.order.user,
|
|
42
|
+
event: guest.event,
|
|
43
|
+
variant: guest.variant
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
result.success? || raise(ActiveRecord::RecordInvalid, guest)
|
|
47
|
+
end
|
|
39
48
|
end
|
|
40
49
|
|
|
41
50
|
def event_id
|
|
@@ -15,9 +15,11 @@ module SpreeCmCommissioner
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
def read_all_user_unread_notifications
|
|
18
|
-
# mark all unread notifications
|
|
18
|
+
# mark all unread notifications except type 'guest_dynamic_field_notification'
|
|
19
19
|
# due to it requires user to fill info before mark as read
|
|
20
20
|
user.notifications.markable_notifications.mark_as_read!
|
|
21
|
+
|
|
22
|
+
SpreeCmCommissioner::UserCountersService.reset_unread_notifications_count(user)
|
|
21
23
|
end
|
|
22
24
|
end
|
|
23
25
|
end
|
|
@@ -4,7 +4,7 @@ module SpreeCmCommissioner
|
|
|
4
4
|
module OrderStateMachine
|
|
5
5
|
extend ActiveSupport::Concern
|
|
6
6
|
|
|
7
|
-
included do
|
|
7
|
+
included do # rubocop:disable Metrics/BlockLength
|
|
8
8
|
state_machine.before_transition to: :address, do: :hold_blocks
|
|
9
9
|
state_machine.before_transition to: :payment, do: :ensure_blocks_held
|
|
10
10
|
|
|
@@ -43,12 +43,14 @@ module SpreeCmCommissioner
|
|
|
43
43
|
event :request do
|
|
44
44
|
transition from: nil, to: :requested
|
|
45
45
|
end
|
|
46
|
+
after_transition to: :requested, do: :increment_user_request_orders_count
|
|
46
47
|
after_transition to: :requested, do: :send_order_requested_app_notification_to_user
|
|
47
48
|
after_transition to: :requested, do: :send_order_requested_telegram_alert_to_store
|
|
48
49
|
|
|
49
50
|
event :accept do
|
|
50
51
|
transition from: :requested, to: :accepted
|
|
51
52
|
end
|
|
53
|
+
after_transition from: :requested, to: :accepted, do: :decrement_user_request_orders_count
|
|
52
54
|
after_transition to: :accepted, do: :send_order_accepted_app_notification_to_user
|
|
53
55
|
after_transition to: :accepted, do: :send_order_accepted_telegram_alert_to_store
|
|
54
56
|
|
|
@@ -59,6 +61,8 @@ module SpreeCmCommissioner
|
|
|
59
61
|
transition from: :requested, to: :rejected
|
|
60
62
|
end
|
|
61
63
|
|
|
64
|
+
after_transition from: :requested, to: :rejected, do: :decrement_user_request_orders_count
|
|
65
|
+
|
|
62
66
|
after_transition to: :rejected, do: :send_order_rejected_app_notification_to_user
|
|
63
67
|
after_transition to: :rejected, do: :send_order_rejected_telegram_alert_to_store
|
|
64
68
|
|
|
@@ -72,6 +76,18 @@ module SpreeCmCommissioner
|
|
|
72
76
|
end
|
|
73
77
|
end
|
|
74
78
|
|
|
79
|
+
def increment_user_request_orders_count
|
|
80
|
+
return if user.nil?
|
|
81
|
+
|
|
82
|
+
SpreeCmCommissioner::UserCountersService.increment_request_orders_count(user)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def decrement_user_request_orders_count
|
|
86
|
+
return if user.nil?
|
|
87
|
+
|
|
88
|
+
SpreeCmCommissioner::UserCountersService.decrement_request_orders_count(user)
|
|
89
|
+
end
|
|
90
|
+
|
|
75
91
|
def product_completion_steps_exist?
|
|
76
92
|
product_completion_steps.any?
|
|
77
93
|
end
|
|
@@ -174,9 +190,17 @@ module SpreeCmCommissioner
|
|
|
174
190
|
line_item.generate_remaining_guests
|
|
175
191
|
|
|
176
192
|
line_item.guests.each do |guest|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
193
|
+
result = SpreeCmCommissioner::Guests::Finalize.call(
|
|
194
|
+
guest: guest,
|
|
195
|
+
user: user,
|
|
196
|
+
event: line_item.event,
|
|
197
|
+
variant: line_item.variant
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
unless result.success?
|
|
201
|
+
guest.errors.add(:base, result.error.value || result.error.to_s)
|
|
202
|
+
raise(ActiveRecord::RecordInvalid, guest)
|
|
203
|
+
end
|
|
180
204
|
end
|
|
181
205
|
end
|
|
182
206
|
end
|
|
@@ -62,7 +62,6 @@ module SpreeCmCommissioner
|
|
|
62
62
|
before_validation :assign_seat_number_with_block, if: -> { will_save_change_to_block_id? }
|
|
63
63
|
|
|
64
64
|
before_save :preload_eligible_check_in_session_ids, if: -> { new_record? }
|
|
65
|
-
before_create :generate_bib_if_needed, if: -> { line_item.reload && variant.bib_pre_generation_on_create? }
|
|
66
65
|
after_create :preload_order_block_ids, if: -> { block_id.present? }
|
|
67
66
|
after_update :preload_order_block_ids, if: :saved_change_to_block_id?
|
|
68
67
|
before_destroy :cancel_reserved_block!, if: -> { reserved_block.present? }
|
|
@@ -248,26 +247,6 @@ module SpreeCmCommissioner
|
|
|
248
247
|
line_item.variant.bib_display_prefix?
|
|
249
248
|
end
|
|
250
249
|
|
|
251
|
-
def generate_bib_if_needed
|
|
252
|
-
return if bib_prefix.present?
|
|
253
|
-
return unless bib_required?
|
|
254
|
-
return if event_id.blank?
|
|
255
|
-
|
|
256
|
-
self.bib_prefix = line_item.variant.bib_prefix
|
|
257
|
-
|
|
258
|
-
last_bib_number = event.guests
|
|
259
|
-
.where(bib_prefix: bib_prefix)
|
|
260
|
-
.maximum(:bib_number) || 0
|
|
261
|
-
|
|
262
|
-
self.bib_number = last_bib_number + 1
|
|
263
|
-
self.bib_index = "#{event_id}-#{bib_prefix}-#{bib_number}"
|
|
264
|
-
end
|
|
265
|
-
|
|
266
|
-
def generate_bib!
|
|
267
|
-
generate_bib_if_needed
|
|
268
|
-
save!
|
|
269
|
-
end
|
|
270
|
-
|
|
271
250
|
# bib_number: 345, bib_prefix: 5KM, bib_zerofill: 5 => return 5KM00345
|
|
272
251
|
# bib_number: 345, bib_prefix: 5KM, bib_zerofill: 2 => return 5KM345
|
|
273
252
|
def formatted_bib_number
|
|
@@ -446,15 +425,15 @@ module SpreeCmCommissioner
|
|
|
446
425
|
end
|
|
447
426
|
|
|
448
427
|
def pre_registration_fields?
|
|
449
|
-
line_item&.product&.dynamic_fields&.
|
|
428
|
+
line_item&.product&.dynamic_fields&.pre_registration&.any?
|
|
450
429
|
end
|
|
451
430
|
|
|
452
431
|
def post_registration_fields?
|
|
453
|
-
line_item&.product&.dynamic_fields&.
|
|
432
|
+
line_item&.product&.dynamic_fields&.post_registration&.any?
|
|
454
433
|
end
|
|
455
434
|
|
|
456
435
|
def during_check_in_fields?
|
|
457
|
-
line_item&.product&.dynamic_fields&.
|
|
436
|
+
line_item&.product&.dynamic_fields&.during_check_in&.any?
|
|
458
437
|
end
|
|
459
438
|
|
|
460
439
|
def product_dynamic_fields
|
|
@@ -26,5 +26,33 @@ module SpreeCmCommissioner
|
|
|
26
26
|
|
|
27
27
|
belongs_to :recipient, polymorphic: true
|
|
28
28
|
belongs_to :notificable, polymorphic: true
|
|
29
|
+
|
|
30
|
+
after_create :increment_user_counters
|
|
31
|
+
after_update :decrement_user_counters, if: :saved_change_to_read_at?
|
|
32
|
+
after_destroy :decrement_user_counters
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def increment_user_counters
|
|
37
|
+
return unless recipient.is_a?(Spree::User)
|
|
38
|
+
|
|
39
|
+
return unless unread?
|
|
40
|
+
|
|
41
|
+
SpreeCmCommissioner::UserCountersService.increment_unread_notifications_count(recipient)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def decrement_user_counters
|
|
45
|
+
return unless recipient.is_a?(Spree::User)
|
|
46
|
+
|
|
47
|
+
# On update: decrement only if transitioning from unread (nil) to read (present)
|
|
48
|
+
if saved_change_to_read_at
|
|
49
|
+
return unless saved_change_to_read_at[0].nil? && saved_change_to_read_at[1].present?
|
|
50
|
+
# On destroy: decrement only if currently unread
|
|
51
|
+
else
|
|
52
|
+
return unless read_at.nil?
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
SpreeCmCommissioner::UserCountersService.decrement_unread_notifications_count(recipient)
|
|
56
|
+
end
|
|
29
57
|
end
|
|
30
58
|
end
|
|
@@ -94,32 +94,6 @@ module SpreeCmCommissioner
|
|
|
94
94
|
def base.find_event(id)
|
|
95
95
|
find_by(slug: "events-#{id}")
|
|
96
96
|
end
|
|
97
|
-
|
|
98
|
-
def base.preload_ancestors_for(taxons)
|
|
99
|
-
return taxons if taxons.empty?
|
|
100
|
-
|
|
101
|
-
# Build a single query to fetch all ancestors for all taxons
|
|
102
|
-
conditions = taxons.map do |t|
|
|
103
|
-
sanitize_sql_array(['(lft <= ? AND rgt >= ?)', t.lft, t.rgt])
|
|
104
|
-
end.join(' OR ')
|
|
105
|
-
all_ancestors = where(conditions).distinct.order(:lft).to_a
|
|
106
|
-
|
|
107
|
-
# Store preloaded ancestors for each taxon
|
|
108
|
-
taxons.each do |t|
|
|
109
|
-
taxon_ancestors = all_ancestors.select { |a| a.lft <= t.lft && a.rgt >= t.rgt && a.id != t.id }
|
|
110
|
-
t.instance_variable_set(:@preloaded_ancestors, taxon_ancestors)
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
taxons
|
|
114
|
-
end
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
def pretty_name
|
|
118
|
-
ancestor_chain = @preloaded_ancestors || ancestors
|
|
119
|
-
ancestor_chain = ancestor_chain.inject('') do |chain, ancestor|
|
|
120
|
-
chain + "#{ancestor.name} -> "
|
|
121
|
-
end
|
|
122
|
-
ancestor_chain + name.to_s
|
|
123
97
|
end
|
|
124
98
|
|
|
125
99
|
def set_kind
|
|
@@ -126,11 +126,6 @@ module SpreeCmCommissioner
|
|
|
126
126
|
@bib_display_prefix == 1
|
|
127
127
|
end
|
|
128
128
|
|
|
129
|
-
def bib_pre_generation_on_create?
|
|
130
|
-
@bib_pre_generation_on_create ||= option_value_name_for(option_type_name: 'bib-pre-generation-on-create')&.to_i || 0
|
|
131
|
-
@bib_pre_generation_on_create == 1
|
|
132
|
-
end
|
|
133
|
-
|
|
134
129
|
def seat_number_positions
|
|
135
130
|
@seat_number_positions ||= option_value_name_for(option_type_name: 'seat-number-positions')&.split(',')
|
|
136
131
|
end
|
|
@@ -2,52 +2,24 @@ module Spree
|
|
|
2
2
|
module V2
|
|
3
3
|
module Storefront
|
|
4
4
|
module ProductSerializerDecorator
|
|
5
|
-
def self.prepended(base)
|
|
6
|
-
add_option_type_associations(base)
|
|
7
|
-
add_promotion_associations(base)
|
|
8
|
-
add_dynamic_field_associations(base)
|
|
9
|
-
add_taxon_associations(base)
|
|
10
|
-
add_basic_attributes(base)
|
|
11
|
-
add_custom_attributes(base)
|
|
12
|
-
add_cache_and_action_button(base)
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def self.add_option_type_associations(base)
|
|
5
|
+
def self.prepended(base) # rubocop:disable Metrics/MethodLength
|
|
16
6
|
base.has_many :variant_kind_option_types, serializer: :option_type
|
|
17
7
|
base.has_many :product_kind_option_types, serializer: :option_type
|
|
18
8
|
base.has_many :promoted_option_types, serializer: :option_type
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def self.add_promotion_associations(base)
|
|
22
9
|
base.has_many :possible_promotions, serializer: ::SpreeCmCommissioner::V2::Storefront::PromotionSerializer
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def self.add_dynamic_field_associations(base)
|
|
26
10
|
base.has_many :dynamic_fields, serializer: SpreeCmCommissioner::V2::Storefront::DynamicFieldSerializer
|
|
27
|
-
end
|
|
28
11
|
|
|
29
|
-
def self.add_taxon_associations(base)
|
|
30
|
-
base.has_many :taxons, serializer: :taxon, record_type: :taxon do |object, params|
|
|
31
|
-
filter_store_taxons(object, params)
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def self.filter_store_taxons(object, params)
|
|
36
|
-
object.classifications
|
|
37
|
-
.map(&:taxon)
|
|
38
|
-
.select { |taxon| taxon.taxonomy&.store_id == params[:store]&.id }
|
|
39
|
-
.sort_by(&:id)
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def self.add_basic_attributes(base)
|
|
43
12
|
base.has_one :default_state, serializer: :state
|
|
44
13
|
base.has_one :venue, serializer: ::SpreeCmCommissioner::V2::Storefront::ProductPlaceSerializer
|
|
14
|
+
|
|
45
15
|
base.attributes :need_confirmation, :product_type, :kyc, :kyc_fields, :allowed_upload_later, :allow_anonymous_booking, :use_video_as_default
|
|
46
16
|
base.attributes :reveal_description, :discontinue_on, :public_metadata, :purchasable_on
|
|
17
|
+
|
|
18
|
+
# Expose only the `event_id` here instead of the full event object.
|
|
19
|
+
# This lets the client fetch event details separately (usually already cached),
|
|
20
|
+
# avoids extra DB queries from a `has_one :event` association, and keeps this response lightweight.
|
|
47
21
|
base.attributes :event_id
|
|
48
|
-
end
|
|
49
22
|
|
|
50
|
-
def self.add_custom_attributes(base)
|
|
51
23
|
base.attribute :purchasable_on_app do |product|
|
|
52
24
|
product.purchasable_on == 'app' || product.purchasable_on == 'both'
|
|
53
25
|
end
|
|
@@ -75,10 +47,9 @@ module Spree
|
|
|
75
47
|
value = product.available?
|
|
76
48
|
[true, false].include?(value) ? value : nil
|
|
77
49
|
end
|
|
78
|
-
end
|
|
79
50
|
|
|
80
|
-
def self.add_cache_and_action_button(base)
|
|
81
51
|
base.cache_options store: nil
|
|
52
|
+
|
|
82
53
|
base.attribute :action_button, &:action_button
|
|
83
54
|
end
|
|
84
55
|
end
|
|
@@ -6,7 +6,8 @@ module Spree
|
|
|
6
6
|
base.attributes :first_name, :last_name, :gender, :phone_number, :intel_phone_number,
|
|
7
7
|
:country_code, :otp_enabled, :otp_email, :otp_phone_number,
|
|
8
8
|
:confirm_pin_code_enabled, :tenant_id, :has_incomplete_guest_info,
|
|
9
|
-
:login, :qr_data, :qr_data_version, :qr_data_invalidated_at
|
|
9
|
+
:login, :qr_data, :qr_data_version, :qr_data_invalidated_at,
|
|
10
|
+
:unread_notifications_count, :request_orders_count
|
|
10
11
|
|
|
11
12
|
base.has_one :profile, serializer: ::Spree::V2::Storefront::UserProfileSerializer
|
|
12
13
|
base.has_many :device_tokens, serializer: Spree::V2::Storefront::UserDeviceTokenSerializer
|
|
@@ -2,16 +2,10 @@ module SpreeCmCommissioner
|
|
|
2
2
|
module V2
|
|
3
3
|
module Storefront
|
|
4
4
|
class HomepageDataSerializer < BaseSerializer
|
|
5
|
-
|
|
5
|
+
attributes :menu_id, :homepage_background_id
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
has_many :featured_vendors, serializer: ::Spree::V2::Storefront::AccommodationSerializer
|
|
10
|
-
|
|
11
|
-
# has_many :trending_categories, serializer: :category_taxon
|
|
12
|
-
# has_many :top_categories, serializer: :category_taxon
|
|
13
|
-
# has_many :display_products, serializer: :taxon_include_product
|
|
14
|
-
# has_many :featured_brands, serializer: :brand_taxon
|
|
7
|
+
has_one :menu, serializer: Spree::Api::Dependencies.storefront_menu_serializer.constantize
|
|
8
|
+
has_one :homepage_background, serializer: SpreeCmCommissioner::V2::Storefront::HomepageBackgroundSerializer
|
|
15
9
|
end
|
|
16
10
|
end
|
|
17
11
|
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
module Guests
|
|
3
|
+
class Finalize
|
|
4
|
+
prepend ::Spree::ServiceModule::Base
|
|
5
|
+
|
|
6
|
+
MAX_RETRY_ATTEMPTS = 5
|
|
7
|
+
|
|
8
|
+
def call(guest:, variant:, event: nil, user: nil) # rubocop:disable Metrics/MethodLength,Metrics/PerceivedComplexity
|
|
9
|
+
attempts = 0
|
|
10
|
+
|
|
11
|
+
begin
|
|
12
|
+
attempts += 1
|
|
13
|
+
|
|
14
|
+
guest.user = user if user.present?
|
|
15
|
+
assign_bib(guest: guest, event: event, variant: variant)
|
|
16
|
+
guest.save!
|
|
17
|
+
|
|
18
|
+
success(guest)
|
|
19
|
+
rescue ActiveRecord::RecordInvalid => e
|
|
20
|
+
# Handle Rails-level validation error
|
|
21
|
+
if e.record.errors[:bib_index].any? && attempts < MAX_RETRY_ATTEMPTS
|
|
22
|
+
# Reload guest to get fresh data and retry
|
|
23
|
+
if guest.persisted?
|
|
24
|
+
guest.reload
|
|
25
|
+
else
|
|
26
|
+
# Clear bib values for new records so they get recalculated on retry
|
|
27
|
+
guest.bib_prefix = nil
|
|
28
|
+
guest.bib_number = nil
|
|
29
|
+
guest.bib_index = nil
|
|
30
|
+
end
|
|
31
|
+
retry
|
|
32
|
+
else
|
|
33
|
+
# Return failure if not a bib_index error or exceeded max attempts
|
|
34
|
+
failure(nil, e.message)
|
|
35
|
+
end
|
|
36
|
+
rescue ActiveRecord::RecordNotUnique => e
|
|
37
|
+
# Handle database-level uniqueness constraint violation
|
|
38
|
+
# Return failure if not a bib_index error or exceeded max attempts
|
|
39
|
+
return failure(nil, e.message) unless e.message.include?('bib_index') && attempts < MAX_RETRY_ATTEMPTS
|
|
40
|
+
|
|
41
|
+
# Reload guest to get fresh data and retry
|
|
42
|
+
if guest.persisted?
|
|
43
|
+
guest.reload
|
|
44
|
+
else
|
|
45
|
+
# Clear bib values for new records so they get recalculated on retry
|
|
46
|
+
guest.bib_prefix = nil
|
|
47
|
+
guest.bib_number = nil
|
|
48
|
+
guest.bib_index = nil
|
|
49
|
+
end
|
|
50
|
+
retry
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def assign_bib(guest:, event:, variant:)
|
|
55
|
+
bib_prefix = variant.bib_prefix
|
|
56
|
+
|
|
57
|
+
return false unless variant.bib_required?
|
|
58
|
+
|
|
59
|
+
return false if guest.bib_prefix.present?
|
|
60
|
+
return false if guest.event_id.blank?
|
|
61
|
+
return false if event.nil? || guest.event_id != event.id
|
|
62
|
+
|
|
63
|
+
guest.bib_prefix = bib_prefix
|
|
64
|
+
|
|
65
|
+
last_bib_number = event.guests
|
|
66
|
+
.where(bib_prefix: bib_prefix)
|
|
67
|
+
.maximum(:bib_number) || 0
|
|
68
|
+
|
|
69
|
+
guest.bib_number = last_bib_number + 1
|
|
70
|
+
guest.bib_index = "#{event.id}-#{bib_prefix}-#{guest.bib_number}"
|
|
71
|
+
|
|
72
|
+
true
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
class HomepageData
|
|
3
|
+
attr_reader :menu, :homepage_background
|
|
4
|
+
|
|
5
|
+
# Plain Old Ruby Object (PORO) for homepage data
|
|
6
|
+
def initialize(menu:, homepage_background:)
|
|
7
|
+
@menu = menu
|
|
8
|
+
@homepage_background = homepage_background
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def id
|
|
12
|
+
@id ||= SecureRandom.uuid
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def menu_id
|
|
16
|
+
menu&.id
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def homepage_background_id
|
|
20
|
+
homepage_background&.id
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
module SpreeCmCommissioner
|
|
2
|
+
class UserCountersService
|
|
3
|
+
def self.increment_unread_notifications_count(user)
|
|
4
|
+
return if user.nil?
|
|
5
|
+
|
|
6
|
+
user.increment!(:unread_notifications_count) # rubocop:disable Rails/SkipsModelValidations
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def self.decrement_unread_notifications_count(user)
|
|
10
|
+
return if user.nil?
|
|
11
|
+
|
|
12
|
+
user.class
|
|
13
|
+
.where(id: user.id)
|
|
14
|
+
.where('unread_notifications_count > 0')
|
|
15
|
+
.update_all('unread_notifications_count = unread_notifications_count - 1') # rubocop:disable Rails/SkipsModelValidations
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.reset_unread_notifications_count(user)
|
|
19
|
+
return if user.nil?
|
|
20
|
+
|
|
21
|
+
user.unread_notifications_count = 0
|
|
22
|
+
user.save!
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.increment_request_orders_count(user)
|
|
26
|
+
return if user.nil?
|
|
27
|
+
|
|
28
|
+
user.increment!(:request_orders_count) # rubocop:disable Rails/SkipsModelValidations
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def self.decrement_request_orders_count(user)
|
|
32
|
+
return if user.nil?
|
|
33
|
+
|
|
34
|
+
user.class
|
|
35
|
+
.where(id: user.id)
|
|
36
|
+
.where('request_orders_count > 0')
|
|
37
|
+
.update_all('request_orders_count = request_orders_count - 1') # rubocop:disable Rails/SkipsModelValidations
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# This Method is to Resolve the race condition of increment and decrement user counters
|
|
41
|
+
# We will create a Cron job to sync user counters from database Later
|
|
42
|
+
def self.sync_counters(user)
|
|
43
|
+
return if user.nil?
|
|
44
|
+
|
|
45
|
+
unread = user.notifications.unread_notifications.count
|
|
46
|
+
requested = user.orders.where(request_state: 'requested').count
|
|
47
|
+
|
|
48
|
+
user.update_columns( # rubocop:disable Rails/SkipsModelValidations
|
|
49
|
+
unread_notifications_count: unread,
|
|
50
|
+
request_orders_count: requested,
|
|
51
|
+
updated_at: Time.current
|
|
52
|
+
)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
<%= f.field_container :product do %>
|
|
25
25
|
<%= f.label :product_id, Spree.t(:products) %>
|
|
26
26
|
<%= f.select :product_id,
|
|
27
|
-
options_from_collection_for_select(Spree::Product.all, :id, :name),
|
|
27
|
+
options_from_collection_for_select(Spree::Product.all, :id, :name, f.object.product_id),
|
|
28
28
|
{ include_hidden: true }, class: 'select2 form-control', disabled: f.object.persisted? %>
|
|
29
29
|
<%= f.error_message_on :product_id %>
|
|
30
30
|
<% end %>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
class AddCounterCacheToSpreeUsers < ActiveRecord::Migration[7.0]
|
|
2
|
+
def change
|
|
3
|
+
add_column :spree_users, :unread_notifications_count, :integer, default: 0, null: false, if_not_exists: true
|
|
4
|
+
add_column :spree_users, :request_orders_count, :integer, default: 0, null: false, if_not_exists: true
|
|
5
|
+
end
|
|
6
|
+
end
|
|
@@ -141,12 +141,6 @@ FactoryBot.define do
|
|
|
141
141
|
presentation { 'Should display bib prefix?' }
|
|
142
142
|
end
|
|
143
143
|
|
|
144
|
-
trait :bib_pre_generation_on_create do
|
|
145
|
-
attr_type { :boolean }
|
|
146
|
-
name { 'bib-pre-generation-on-create' }
|
|
147
|
-
presentation { 'Should pre generate bib on create' }
|
|
148
|
-
end
|
|
149
|
-
|
|
150
144
|
trait :seat_number_positions do
|
|
151
145
|
attr_type { :array }
|
|
152
146
|
name { 'seat-number-positions' }
|
|
@@ -103,31 +103,18 @@ FactoryBot.define do
|
|
|
103
103
|
transient do
|
|
104
104
|
variant1_bib_prefix { '3KM' }
|
|
105
105
|
variant2_bib_prefix { '5KM' }
|
|
106
|
-
bib_pre_generation_on_create { false }
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
before(:create) do |product, evaluator|
|
|
110
|
-
if evaluator.bib_pre_generation_on_create
|
|
111
|
-
product.option_types << create(:cm_option_type, :bib_pre_generation_on_create)
|
|
112
|
-
end
|
|
113
106
|
end
|
|
114
107
|
|
|
115
108
|
after(:create) do |product, evaluator|
|
|
116
109
|
option_value1 = create(:cm_option_value, presentation: evaluator.variant1_bib_prefix, name: evaluator.variant1_bib_prefix, option_type: product.option_types[0])
|
|
117
110
|
option_value2 = create(:cm_option_value, presentation: evaluator.variant2_bib_prefix, name: evaluator.variant2_bib_prefix, option_type: product.option_types[0])
|
|
118
111
|
|
|
119
|
-
bib_pre_generation_option_value = if evaluator.bib_pre_generation_on_create
|
|
120
|
-
create(:cm_option_value, presentation: 'Yes', name: '1', option_type: product.option_types.find_by(name: 'bib-pre-generation-on-create'))
|
|
121
|
-
end
|
|
122
|
-
|
|
123
112
|
variant1 = create(:cm_variant, price: product.price, product: product)
|
|
124
113
|
variant1.option_values = [option_value1]
|
|
125
|
-
variant1.option_values << bib_pre_generation_option_value if evaluator.bib_pre_generation_on_create
|
|
126
114
|
variant1.save!
|
|
127
115
|
|
|
128
116
|
variant2 = create(:cm_variant, price: product.price, product: product)
|
|
129
117
|
variant2.option_values = [option_value2]
|
|
130
|
-
variant2.option_values << bib_pre_generation_option_value if evaluator.bib_pre_generation_on_create
|
|
131
118
|
variant2.save!
|
|
132
119
|
end
|
|
133
120
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: spree_cm_commissioner
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.5.2
|
|
4
|
+
version: 2.5.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- You
|
|
@@ -817,7 +817,6 @@ files:
|
|
|
817
817
|
- app/controllers/.gitkeep
|
|
818
818
|
- app/controllers/blazer/base_controller_decorator.rb
|
|
819
819
|
- app/controllers/blazer/queries_controller_decorator.rb
|
|
820
|
-
- app/controllers/concerns/spree/api/v2/product_list_includes_decorator.rb
|
|
821
820
|
- app/controllers/concerns/spree/billing/order_parents_concern.rb
|
|
822
821
|
- app/controllers/concerns/spree/billing/payment_creatable.rb
|
|
823
822
|
- app/controllers/concerns/spree/billing/payment_fireable.rb
|
|
@@ -980,7 +979,6 @@ files:
|
|
|
980
979
|
- app/controllers/spree/api/v2/storefront/pin_code_otp_checkers_controller.rb
|
|
981
980
|
- app/controllers/spree/api/v2/storefront/pin_code_otp_generators_controller.rb
|
|
982
981
|
- app/controllers/spree/api/v2/storefront/popular_route_places_controller.rb
|
|
983
|
-
- app/controllers/spree/api/v2/storefront/products_controller_decorator.rb
|
|
984
982
|
- app/controllers/spree/api/v2/storefront/profile_images_controller.rb
|
|
985
983
|
- app/controllers/spree/api/v2/storefront/provinces_controller.rb
|
|
986
984
|
- app/controllers/spree/api/v2/storefront/qr_urls_controller.rb
|
|
@@ -990,7 +988,6 @@ files:
|
|
|
990
988
|
- app/controllers/spree/api/v2/storefront/s3_signed_urls_controller.rb
|
|
991
989
|
- app/controllers/spree/api/v2/storefront/seat_layouts_controller.rb
|
|
992
990
|
- app/controllers/spree/api/v2/storefront/self_check_in_controller.rb
|
|
993
|
-
- app/controllers/spree/api/v2/storefront/taxons_controller_decorator.rb
|
|
994
991
|
- app/controllers/spree/api/v2/storefront/tenants_controller.rb
|
|
995
992
|
- app/controllers/spree/api/v2/storefront/transit/draft_orders_controller.rb
|
|
996
993
|
- app/controllers/spree/api/v2/storefront/trip_places_controller.rb
|
|
@@ -1414,7 +1411,6 @@ files:
|
|
|
1414
1411
|
- app/models/concerns/spree_cm_commissioner/vendor_promotable.rb
|
|
1415
1412
|
- app/models/concerns/spree_cm_commissioner/video_on_demand_bitwise.rb
|
|
1416
1413
|
- app/models/concerns/spree_cm_commissioner/webhooks/subscriber_rulable.rb
|
|
1417
|
-
- app/models/spree/stock/quantifier_decorator.rb
|
|
1418
1414
|
- app/models/spree_cm_commissioner.rb
|
|
1419
1415
|
- app/models/spree_cm_commissioner/ability_decorator.rb
|
|
1420
1416
|
- app/models/spree_cm_commissioner/address_decorator.rb
|
|
@@ -2017,7 +2013,9 @@ files:
|
|
|
2017
2013
|
- app/services/spree_cm_commissioner/google_wallets/hotel_class_updater.rb
|
|
2018
2014
|
- app/services/spree_cm_commissioner/google_wallets/hotel_object_builder.rb
|
|
2019
2015
|
- app/services/spree_cm_commissioner/guests/claim_invite_guest_service.rb
|
|
2016
|
+
- app/services/spree_cm_commissioner/guests/finalize.rb
|
|
2020
2017
|
- app/services/spree_cm_commissioner/guests/preload_check_in_session_ids.rb
|
|
2018
|
+
- app/services/spree_cm_commissioner/homepage_data.rb
|
|
2021
2019
|
- app/services/spree_cm_commissioner/homepage_data_loader.rb
|
|
2022
2020
|
- app/services/spree_cm_commissioner/imports/base_import_order_service.rb
|
|
2023
2021
|
- app/services/spree_cm_commissioner/imports/create_order_service.rb
|
|
@@ -2088,6 +2086,7 @@ files:
|
|
|
2088
2086
|
- app/services/spree_cm_commissioner/trips/variants/create.rb
|
|
2089
2087
|
- app/services/spree_cm_commissioner/update_guest_service.rb
|
|
2090
2088
|
- app/services/spree_cm_commissioner/user_authenticator.rb
|
|
2089
|
+
- app/services/spree_cm_commissioner/user_counters_service.rb
|
|
2091
2090
|
- app/services/spree_cm_commissioner/user_roles_assigner.rb
|
|
2092
2091
|
- app/services/spree_cm_commissioner/users/incomplete_guest_checker_service.rb
|
|
2093
2092
|
- app/services/spree_cm_commissioner/users/qr_data/extract_login.rb
|
|
@@ -2997,6 +2996,7 @@ files:
|
|
|
2997
2996
|
- db/migrate/20260108101406_add_allow_booking_to_cm_trips.rb
|
|
2998
2997
|
- db/migrate/20260121024645_add_nationality_group_to_cm_guests.rb
|
|
2999
2998
|
- db/migrate/20260126110528_seed_user_initial_usernames.rb
|
|
2999
|
+
- db/migrate/20260128043540_add_counter_cache_to_spree_users.rb
|
|
3000
3000
|
- docker-compose.yml
|
|
3001
3001
|
- docs/api/scoped-access-token-endpoints.md
|
|
3002
3002
|
- docs/option_types/attr_types.md
|
|
@@ -3177,9 +3177,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
3177
3177
|
version: '2.7'
|
|
3178
3178
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
3179
3179
|
requirements:
|
|
3180
|
-
- - "
|
|
3180
|
+
- - ">="
|
|
3181
3181
|
- !ruby/object:Gem::Version
|
|
3182
|
-
version:
|
|
3182
|
+
version: '0'
|
|
3183
3183
|
requirements:
|
|
3184
3184
|
- none
|
|
3185
3185
|
rubygems_version: 3.4.1
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
module Spree
|
|
2
|
-
module Api
|
|
3
|
-
module V2
|
|
4
|
-
module ProductListIncludesDecorator
|
|
5
|
-
# OVERRIDE: Extends base product_list_includes from Spree::Api::V2::ProductListIncludes
|
|
6
|
-
def product_list_includes
|
|
7
|
-
# Gets base from ProductListIncludes concern
|
|
8
|
-
base_includes = super
|
|
9
|
-
|
|
10
|
-
# Preload taxons with their taxonomies
|
|
11
|
-
base_includes[:classifications] = { taxon: :taxonomy }
|
|
12
|
-
|
|
13
|
-
# Add missing associations
|
|
14
|
-
base_includes[:vendor] = [:default_state]
|
|
15
|
-
base_includes[:venue] = []
|
|
16
|
-
base_includes[:variants_including_master] = { prices: [] }
|
|
17
|
-
base_includes[:product_option_types] = :option_type
|
|
18
|
-
base_includes[:product_promotion_rules] = {
|
|
19
|
-
promotion_rule: {
|
|
20
|
-
promotion: []
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
base_includes[:product_dynamic_fields] = :dynamic_field
|
|
24
|
-
|
|
25
|
-
%i[master variants variants_including_master].each do |key|
|
|
26
|
-
base_includes[key][:stock_items] = :stock_location if base_includes[key]
|
|
27
|
-
base_includes[key][:stock_locations] = []
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
base_includes
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
Spree::Api::V2::ProductListIncludes.prepend Spree::Api::V2::ProductListIncludesDecorator
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
# gems/spree_cm_commissioner/app/controllers/spree/api/v2/storefront/products_controller_decorator.rb
|
|
2
|
-
module Spree
|
|
3
|
-
module Api
|
|
4
|
-
module V2
|
|
5
|
-
module Storefront
|
|
6
|
-
module ProductsControllerDecorator
|
|
7
|
-
def scope_includes
|
|
8
|
-
base_includes = super
|
|
9
|
-
|
|
10
|
-
base_includes[:vendor] = { default_state: [] }
|
|
11
|
-
base_includes[:venue] = []
|
|
12
|
-
base_includes[:variants_including_master] = { prices: [] }
|
|
13
|
-
|
|
14
|
-
%i[master variants variants_including_master].each do |key|
|
|
15
|
-
base_includes[key][:stock_items] = :stock_location if base_includes[key]
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
base_includes
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
Spree::Api::V2::Storefront::ProductsController
|
|
27
|
-
.prepend Spree::Api::V2::Storefront::ProductsControllerDecorator
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
module Spree
|
|
2
|
-
module Api
|
|
3
|
-
module V2
|
|
4
|
-
module Storefront
|
|
5
|
-
module TaxonsControllerDecorator
|
|
6
|
-
def resource
|
|
7
|
-
@resource ||= begin
|
|
8
|
-
taxon = scope.find_by(permalink: params[:id]) || scope.find(params[:id])
|
|
9
|
-
|
|
10
|
-
if action_name == 'show' && should_include_products?
|
|
11
|
-
taxon.products = taxon.products
|
|
12
|
-
.includes(product_includes_for_show)
|
|
13
|
-
.order('spree_products_taxons.position ASC')
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
if action_name == 'show' && should_include_visible_products?
|
|
17
|
-
taxon.visible_products = taxon.visible_products
|
|
18
|
-
.includes(product_includes_for_show)
|
|
19
|
-
.order('spree_products_taxons.position ASC')
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
taxon
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
protected
|
|
27
|
-
|
|
28
|
-
def scope(skip_cancancan: false)
|
|
29
|
-
base_scope = super(skip_cancancan: skip_cancancan)
|
|
30
|
-
base_scope = base_scope.includes(asset_includes) if action_name == 'show'
|
|
31
|
-
base_scope
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
private
|
|
35
|
-
|
|
36
|
-
def should_include_products?
|
|
37
|
-
params[:include]&.include?('products')
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def should_include_visible_products?
|
|
41
|
-
params[:include]&.include?('visible_products')
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def product_includes_for_show
|
|
45
|
-
{
|
|
46
|
-
product_properties: [],
|
|
47
|
-
option_types: [],
|
|
48
|
-
variant_images: [],
|
|
49
|
-
classifications: :taxon,
|
|
50
|
-
variants_including_master: product_variant_includes,
|
|
51
|
-
master: product_variant_includes,
|
|
52
|
-
variants: product_variant_includes,
|
|
53
|
-
vendor: { default_state: [] },
|
|
54
|
-
venue: []
|
|
55
|
-
}
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def product_variant_includes
|
|
59
|
-
{
|
|
60
|
-
prices: [],
|
|
61
|
-
option_values: :option_type,
|
|
62
|
-
images: [],
|
|
63
|
-
stock_items: :stock_location
|
|
64
|
-
}
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def asset_includes
|
|
68
|
-
{
|
|
69
|
-
category_icon: { attachment_attachment: :blob },
|
|
70
|
-
app_banner: { attachment_attachment: :blob },
|
|
71
|
-
web_banner: { attachment_attachment: :blob },
|
|
72
|
-
home_banner: { attachment_attachment: :blob },
|
|
73
|
-
video_banner: { attachment_attachment: :blob },
|
|
74
|
-
children: {
|
|
75
|
-
icon: { attachment_attachment: :blob },
|
|
76
|
-
category_icon: { attachment_attachment: :blob },
|
|
77
|
-
app_banner: { attachment_attachment: :blob },
|
|
78
|
-
web_banner: { attachment_attachment: :blob },
|
|
79
|
-
home_banner: { attachment_attachment: :blob },
|
|
80
|
-
video_banner: { attachment_attachment: :blob }
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
end
|
|
86
|
-
end
|
|
87
|
-
end
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
Spree::Api::V2::Storefront::TaxonsController.prepend(
|
|
91
|
-
Spree::Api::V2::Storefront::TaxonsControllerDecorator
|
|
92
|
-
)
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
module Spree
|
|
2
|
-
module Stock
|
|
3
|
-
module QuantifierDecorator
|
|
4
|
-
private
|
|
5
|
-
|
|
6
|
-
def scope_to_location(collection)
|
|
7
|
-
# If stock_items are already loaded (preloaded via includes), filter in memory
|
|
8
|
-
if collection.loaded?
|
|
9
|
-
if stock_location.blank?
|
|
10
|
-
# Filter to only active stock locations in memory
|
|
11
|
-
collection.select { |si| si.stock_location&.active? }
|
|
12
|
-
else
|
|
13
|
-
collection.select { |si| si.stock_location_id == stock_location.id }
|
|
14
|
-
end
|
|
15
|
-
else
|
|
16
|
-
# Fall back to original behavior if not preloaded
|
|
17
|
-
return collection.with_active_stock_location if stock_location.blank?
|
|
18
|
-
|
|
19
|
-
collection.where(stock_location: stock_location)
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
Spree::Stock::Quantifier.prepend Spree::Stock::QuantifierDecorator
|