spree_cm_commissioner 1.8.0 → 1.8.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/.tool-versions +1 -0
- data/Gemfile.lock +1 -1
- data/app/assets/images/mailer/bookme-plus_light.svg +1 -0
- data/app/controllers/spree/admin/taxons_controller_decorator.rb +5 -0
- data/app/controllers/spree/api/v2/organizer/invites_controller.rb +35 -0
- data/app/controllers/spree/api/v2/tenant/customer_notifications_controller.rb +20 -0
- data/app/controllers/spree/api/v2/tenant/line_items_controller.rb +56 -0
- data/app/controllers/spree/api/v2/tenant/notifications_controller.rb +55 -0
- data/app/controllers/spree/api/v2/tenant/profile_images_controller.rb +52 -0
- data/app/controllers/spree/api/v2/tenant/s3_signed_urls_controller.rb +29 -0
- data/app/interactors/spree_cm_commissioner/crew_inviter.rb +63 -0
- data/app/interactors/spree_cm_commissioner/customer_notification_sender.rb +10 -5
- data/app/interactors/spree_cm_commissioner/profile_image_destroyer.rb +16 -0
- data/app/mailers/spree_cm_commissioner/crew_invite_mailer.rb +13 -0
- data/app/models/concerns/spree_cm_commissioner/option_type_attr_type.rb +6 -1
- data/app/models/spree_cm_commissioner/crew_invite.rb +7 -0
- data/app/models/spree_cm_commissioner/invite.rb +22 -0
- data/app/models/spree_cm_commissioner/invite_user_event.rb +5 -0
- data/app/models/spree_cm_commissioner/invite_user_taxon.rb +11 -0
- data/app/models/spree_cm_commissioner/line_item_decorator.rb +1 -1
- data/app/models/spree_cm_commissioner/order_decorator.rb +1 -1
- data/app/models/spree_cm_commissioner/place.rb +2 -0
- data/app/models/spree_cm_commissioner/product_decorator.rb +4 -0
- data/app/models/spree_cm_commissioner/taxon_decorator.rb +5 -0
- data/app/models/spree_cm_commissioner/taxon_video_banner.rb +4 -0
- data/app/models/spree_cm_commissioner/user_decorator.rb +4 -0
- data/app/models/spree_cm_commissioner/variant_options.rb +23 -0
- data/app/models/spree_cm_commissioner/video.rb +15 -0
- data/app/overrides/spree/admin/taxons/_form/assets_form.html.erb.deface +19 -0
- data/app/overrides/spree/admin/taxons/_form/available_on.html.erb.deface +18 -0
- data/app/serializers/spree/v2/organizer/asset_serializer.rb +11 -0
- data/app/serializers/spree/v2/organizer/invite_serializer.rb +11 -0
- data/app/serializers/spree/v2/organizer/taxon_serializer.rb +10 -0
- data/app/serializers/spree/v2/organizer/user_serializer.rb +9 -0
- data/app/serializers/spree/v2/storefront/taxon_serializer_decorator.rb +2 -1
- data/app/serializers/spree/v2/tenant/customer_notification_serializer.rb +11 -0
- data/app/serializers/spree/v2/tenant/digital_link_serializer.rb +9 -0
- data/app/serializers/spree/v2/tenant/image_serializer.rb +11 -0
- data/app/serializers/spree/v2/tenant/line_item_serializer.rb +35 -0
- data/app/serializers/spree/v2/tenant/notification_serializer.rb +11 -0
- data/app/serializers/spree/v2/tenant/option_type_serializer.rb +12 -0
- data/app/serializers/spree/v2/tenant/option_value_serializer.rb +17 -0
- data/app/serializers/spree/v2/tenant/order_serializer.rb +8 -0
- data/app/serializers/spree/v2/tenant/s3_signed_url_serializer.rb +9 -0
- data/app/serializers/spree/v2/tenant/stock_item_serializer.rb +11 -0
- data/app/serializers/spree/v2/tenant/stock_location_serializer.rb +11 -0
- data/app/serializers/spree/v2/tenant/user_profile_serializer.rb +8 -0
- data/app/serializers/spree/v2/tenant/variant_serializer.rb +46 -0
- data/app/serializers/spree_cm_commissioner/v2/storefront/video_serializer.rb +9 -0
- data/app/views/spree/admin/customer_notifications/_form.html.erb +8 -0
- data/app/views/spree_cm_commissioner/crew_invite_mailer/_mailer_stylesheets.html.erb +82 -0
- data/app/views/spree_cm_commissioner/crew_invite_mailer/send_crew_invite_email.html.erb +33 -0
- data/app/views/spree_cm_commissioner/layouts/crew_invite_mailer.html.erb +15 -0
- data/config/initializers/spree_permitted_attributes.rb +1 -0
- data/config/locales/en.yml +10 -1
- data/config/locales/km.yml +10 -1
- data/config/routes.rb +15 -0
- data/db/migrate/20250304101907_create_spree_cm_commissioner_invite.rb +12 -0
- data/db/migrate/20250304101946_create_spree_cm_commissioner_invite_user_taxon.rb +11 -0
- data/db/migrate/20250307013422_add_parent_id_to_cm_place.rb +9 -0
- data/db/migrate/20250307073003_add_tenant_id_to_cm_customer_notifications.rb +6 -0
- data/db/migrate/20250307083809_remove_tenant_id_from_cm_notifications.rb +6 -0
- data/db/migrate/20250314013434_add_available_on_to_spree_taxons.rb +5 -0
- data/lib/spree_cm_commissioner/test_helper/factories/invite_factory.rb +7 -0
- data/lib/spree_cm_commissioner/test_helper/factories/invite_user_event_factory.rb +5 -0
- data/lib/spree_cm_commissioner/test_helper/factories/option_type_factory.rb +30 -0
- data/lib/spree_cm_commissioner/test_helper/factories/user_event_factory.rb +6 -0
- data/lib/spree_cm_commissioner/version.rb +1 -1
- metadata +50 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3e00b3e7d79896c88e4956cc766ba9e3538a3c9fd0f68b8835a6c5281bdfef6f
|
4
|
+
data.tar.gz: 421e9a6a7be136d047457d06e1e51822029e05b08e5bf42b9b9410541b234105
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 25a20ae201490fd79949c9b33a74ac4fa7597fffb80a84b8a54dd104dd02a89ead67397bfcfe276e131ad8a2dd95aed691530f8d1eb33c2d99b16982dcbbca3b
|
7
|
+
data.tar.gz: d0f39688eb2ea2f413052b02bf7cfb05d34c020c02704f41175e4f84a994934038e159c10c81f23e3b4f6ede78ea44b3cfa9cbc4092970e5de1cd49a02ab9e14
|
data/.tool-versions
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby 3.3.5
|
data/Gemfile.lock
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="408" height="66" fill="none"><path fill="#010304" d="M63.27 27.02c1.4-1.91 2.3-3.95 2.69-6.05l.82-4.51c.87-4.8-.26-8.67-3.38-11.52C60.33 2.14 55.8.72 49.95.72H17.81l-4.76 26.14-2.16 11.82-3.18 17.43c-.5 2.73 0 4.98 1.45 6.69 1.46 1.7 3.6 2.56 6.38 2.56h25.69c6.22 0 11.53-1.53 15.78-4.55 4.31-3.06 6.96-7.21 7.9-12.36l.86-4.69c.54-2.99.09-5.72-1.34-8.14-1.22-2.04-2.96-3.62-5.21-4.7 1.58-1.08 2.94-2.39 4.05-3.91zM51.78 43.77l-.72 3.97c-.31 1.68-1.14 2.93-2.54 3.84-1.47.95-3.47 1.43-5.93 1.43H22.27l2.61-14.31h21.67c1.9 0 3.34.48 4.28 1.44.92.94 1.23 2.13.96 3.65zm.76-25.96-.56 3.06c-.34 1.85-1.11 3.28-2.38 4.37-1.26 1.09-2.71 1.62-4.43 1.62H27.02l2.51-13.77h17.7c1.92 0 3.37.44 4.33 1.32.92.84 1.24 1.96.98 3.4"/><path fill="#010304" d="M44.91 26.87v11.82H.74l2.18-11.82zM114.17 19.64c-2.73-1.55-6.09-2.34-9.98-2.34h-8.11c-3.89 0-7.53.79-10.83 2.34-3.32 1.56-6.12 3.8-8.33 6.65-2.21 2.84-3.66 6.15-4.33 9.81l-1.92 10.55c-.67 3.67-.43 6.96.72 9.77 1.15 2.82 3.13 5.03 5.88 6.56 2.73 1.52 6.09 2.29 9.98 2.29h8.11c3.95 0 7.62-.77 10.91-2.29 3.31-1.53 6.11-3.74 8.31-6.56 2.2-2.81 3.66-6.1 4.33-9.77l1.92-10.55c.67-3.67.42-6.97-.75-9.81-1.17-2.85-3.16-5.08-5.91-6.65M89.63 53.17c-1.89 0-3.25-.66-4.18-2.03-.95-1.4-1.21-3.19-.79-5.49l1.59-8.74c.41-2.26 1.35-4.11 2.8-5.49 1.42-1.37 3.06-2.03 5.01-2.03h7.75c1.94 0 3.34.66 4.27 2.03.94 1.38 1.21 3.23.79 5.49l-1.59 8.74c-.41 2.26-1.35 4.11-2.79 5.49-1.43 1.37-3.1 2.03-5.1 2.03h-7.76M167.9 19.64c-2.73-1.55-6.09-2.34-9.98-2.34h-8.11c-3.89 0-7.54.79-10.83 2.34-3.32 1.56-6.12 3.8-8.33 6.65-2.21 2.84-3.66 6.15-4.33 9.81l-1.92 10.55c-.67 3.67-.43 6.95.72 9.77s3.13 5.03 5.88 6.56c2.73 1.52 6.09 2.29 9.98 2.29h8.11c3.95 0 7.62-.77 10.91-2.29 3.31-1.53 6.11-3.74 8.31-6.56 2.2-2.81 3.66-6.1 4.33-9.77l1.92-10.55c.67-3.67.42-6.97-.75-9.81-1.17-2.85-3.16-5.08-5.91-6.65m-29.51 26.02 1.59-8.74c.41-2.26 1.35-4.11 2.8-5.49 1.43-1.37 3.06-2.03 5.01-2.03h7.75c1.95 0 3.34.66 4.27 2.03.94 1.38 1.21 3.23.79 5.49l-1.59 8.74c-.41 2.26-1.35 4.11-2.8 5.49-1.43 1.37-3.09 2.03-5.1 2.03h-7.75c-1.88 0-3.25-.66-4.18-2.03-.95-1.4-1.21-3.19-.79-5.49M230.08 18.75h-16.44l-19.73 16.82L200.28.63h-13.81l-11.78 64.64h13.81l2.5-13.7 4.64-3.93 10.54 17.63h15.84L206.31 38.7zM265.04 36.88 251.68.63h-12.31l-11.78 64.64h13.72l6.87-37.7 7.91 21.35c.34.92.73 1.73 1.17 2.39l.04.06c.34.52.7.95 1.08 1.28.92.78 2.08 1.18 3.45 1.18h.27c1.37 0 2.68-.4 3.88-1.18.52-.34 1.04-.77 1.52-1.25.68-.65 1.39-1.48 2.12-2.46l15.68-21.35-6.87 37.69h13.72L303.93.64h-12.32l-26.56 36.25zM347.2 22.38c-3-3.37-7.54-5.08-13.48-5.08h-7.21c-3.89 0-7.53.79-10.83 2.34-3.32 1.56-6.12 3.78-8.32 6.6-2.2 2.81-3.66 6.1-4.33 9.77l-2.12 11.63c-.63 3.44-.33 6.54.88 9.2 1.21 2.67 3.22 4.77 5.99 6.23 2.74 1.46 6.1 2.2 9.99 2.2h6.85c3.87 0 7.48-.66 10.71-1.95 3.28-1.32 6.03-3.23 8.17-5.68 1.86-2.12 3.14-4.53 3.83-7.18h-13.8c-.37.67-.94 1.24-1.71 1.74-1.3.83-2.94 1.25-4.87 1.25h-7.03c-1.98 0-3.39-.52-4.31-1.59-.92-1.06-1.21-2.44-.89-4.21l.25-1.39h33.35l1.88-10.33c1.02-5.61 0-10.16-3.01-13.55zm-10.61 13.49H316.7c.45-2.03 1.35-3.68 2.68-4.94 1.42-1.34 3.06-1.99 5.01-1.99h7.3c1.89 0 3.24.61 4.13 1.86.9 1.27 1.15 2.92.77 5.06z"/><path fill="#6444D8" d="m372.06 63.5 8.12-44.57h13.06l-8.12 44.57z"/><path fill="#6444D8" d="M405.25 47.52h-47l2.44-13.22h46.99z"/></svg>
|
@@ -21,6 +21,10 @@ module Spree
|
|
21
21
|
remove_asset(@taxon.home_banner)
|
22
22
|
end
|
23
23
|
|
24
|
+
def remove_video_banner
|
25
|
+
remove_asset(@taxon.video_banner)
|
26
|
+
end
|
27
|
+
|
24
28
|
private
|
25
29
|
|
26
30
|
def remove_asset(asset)
|
@@ -38,6 +42,7 @@ module Spree
|
|
38
42
|
@taxon.build_app_banner(attachment: permitted_resource_params.delete(:app_banner)) if permitted_resource_params[:app_banner]
|
39
43
|
@taxon.build_web_banner(attachment: permitted_resource_params.delete(:web_banner)) if permitted_resource_params[:web_banner]
|
40
44
|
@taxon.build_home_banner(attachment: permitted_resource_params.delete(:home_banner)) if permitted_resource_params[:home_banner]
|
45
|
+
@taxon.build_video_banner(attachment: permitted_resource_params.delete(:video_banner)) if permitted_resource_params[:video_banner]
|
41
46
|
end
|
42
47
|
end
|
43
48
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Spree
|
2
|
+
module Api
|
3
|
+
module V2
|
4
|
+
module Organizer
|
5
|
+
class InvitesController < ::Spree::Api::V2::Organizer::BaseController
|
6
|
+
def show
|
7
|
+
if invite&.url_valid?
|
8
|
+
render_serialized_payload { serialize_resource(invite) }
|
9
|
+
else
|
10
|
+
render_error_payload(I18n.t('invite.url_not_found'))
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def update
|
15
|
+
context = invite.confirm(params[:user_id])
|
16
|
+
|
17
|
+
if context.success?
|
18
|
+
render_serialized_payload { serialize_resource(context.invite) }
|
19
|
+
else
|
20
|
+
render_error_payload(context.message || I18n.t('invite.accept_fail'))
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def invite
|
25
|
+
@invite ||= SpreeCmCommissioner::Invite.find_by!(token: params[:id])
|
26
|
+
end
|
27
|
+
|
28
|
+
def resource_serializer
|
29
|
+
::Spree::V2::Organizer::InviteSerializer
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Spree
|
2
|
+
module Api
|
3
|
+
module V2
|
4
|
+
module Tenant
|
5
|
+
class CustomerNotificationsController < BaseController
|
6
|
+
before_action :require_spree_current_user
|
7
|
+
|
8
|
+
def show
|
9
|
+
customer_notification = SpreeCmCommissioner::CustomerNotification.find(params[:id])
|
10
|
+
render_serialized_payload { serialize_resource(customer_notification) }
|
11
|
+
end
|
12
|
+
|
13
|
+
def resource_serializer
|
14
|
+
Spree::V2::Tenant::CustomerNotificationSerializer
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Spree
|
2
|
+
module Api
|
3
|
+
module V2
|
4
|
+
module Tenant
|
5
|
+
class LineItemsController < BaseController
|
6
|
+
around_action :wrap_with_multitenant_without
|
7
|
+
|
8
|
+
def collection
|
9
|
+
if spree_current_user.nil?
|
10
|
+
line_items_by_order_tokens
|
11
|
+
else
|
12
|
+
spree_current_user.line_items.filter_by_event(params[:event])
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def show
|
17
|
+
line_item = Spree::LineItem.find(params[:id])
|
18
|
+
render_serialized_payload { serialize_resource(line_item) }
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def allowed_sort_attributes
|
24
|
+
super << :to_date
|
25
|
+
super << :from_date
|
26
|
+
end
|
27
|
+
|
28
|
+
def resource_serializer
|
29
|
+
Spree::V2::Tenant::LineItemSerializer
|
30
|
+
end
|
31
|
+
|
32
|
+
def collection_serializer
|
33
|
+
Spree::V2::Tenant::LineItemSerializer
|
34
|
+
end
|
35
|
+
|
36
|
+
def line_items_by_order_tokens
|
37
|
+
order_tokens = params[:order_tokens]
|
38
|
+
event = params[:event]
|
39
|
+
|
40
|
+
return Spree::LineItem.none if order_tokens.blank?
|
41
|
+
|
42
|
+
Spree::LineItem.joins(:order)
|
43
|
+
.where(spree_orders: { token: order_tokens, state: 'complete', user_id: nil, tenant_id: 1 })
|
44
|
+
.filter_by_event(event)
|
45
|
+
.page(params[:page])
|
46
|
+
.per(params[:per_page])
|
47
|
+
end
|
48
|
+
|
49
|
+
def wrap_with_multitenant_without(&block)
|
50
|
+
MultiTenant.without(&block)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Spree
|
2
|
+
module Api
|
3
|
+
module V2
|
4
|
+
module Tenant
|
5
|
+
class NotificationsController < BaseController
|
6
|
+
before_action :require_spree_current_user
|
7
|
+
|
8
|
+
def collection
|
9
|
+
spree_current_user.notifications.newest_first.user_notifications
|
10
|
+
end
|
11
|
+
|
12
|
+
def serialize_collection(collection)
|
13
|
+
options_data = collection_options(collection).merge(params: serializer_params)
|
14
|
+
options_data[:meta][:unread_count] = collection.select(&:unread?).count
|
15
|
+
|
16
|
+
collection_serializer.new(
|
17
|
+
collection,
|
18
|
+
options_data
|
19
|
+
).serializable_hash
|
20
|
+
end
|
21
|
+
|
22
|
+
def show
|
23
|
+
notification = SpreeCmCommissioner::Notification.find(params[:id])
|
24
|
+
|
25
|
+
render_serialized_payload { serialize_resource(notification) }
|
26
|
+
end
|
27
|
+
|
28
|
+
def mark_as_read
|
29
|
+
result = SpreeCmCommissioner::NotificationReader.call(id: params[:id])
|
30
|
+
|
31
|
+
return unless result.success?
|
32
|
+
|
33
|
+
head :ok
|
34
|
+
end
|
35
|
+
|
36
|
+
def mark_all_as_read
|
37
|
+
result = SpreeCmCommissioner::NotificationReader.call(user: spree_current_user)
|
38
|
+
|
39
|
+
return unless result.success?
|
40
|
+
|
41
|
+
head :ok
|
42
|
+
end
|
43
|
+
|
44
|
+
def resource_serializer
|
45
|
+
Spree::V2::Tenant::NotificationSerializer
|
46
|
+
end
|
47
|
+
|
48
|
+
def collection_serializer
|
49
|
+
Spree::V2::Tenant::NotificationSerializer
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Spree
|
2
|
+
module Api
|
3
|
+
module V2
|
4
|
+
module Tenant
|
5
|
+
class ProfileImagesController < BaseController
|
6
|
+
before_action :require_spree_current_user
|
7
|
+
before_action :required_schema_validation!, except: [:destroy]
|
8
|
+
|
9
|
+
def update
|
10
|
+
context = SpreeCmCommissioner::ProfileImageUpdater.call(
|
11
|
+
user: spree_current_user,
|
12
|
+
url: schema.output.fetch(:url)
|
13
|
+
)
|
14
|
+
if context.success?
|
15
|
+
render_serialized_payload { serialize_resource(context.result) }
|
16
|
+
else
|
17
|
+
render_error_payload(context.message)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def destroy
|
22
|
+
context = SpreeCmCommissioner::ProfileImageDestroyer.call(
|
23
|
+
user: spree_current_user
|
24
|
+
)
|
25
|
+
if context.success?
|
26
|
+
render_serialized_payload(204) { serialize_resource(context.result) }
|
27
|
+
else
|
28
|
+
render_error_payload(context.message)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def required_schema_validation!
|
33
|
+
return true if required_schema.nil?
|
34
|
+
|
35
|
+
@schema = required_schema.new(request: request, locale: locale, user: spree_current_user)
|
36
|
+
return true if schema.success?
|
37
|
+
|
38
|
+
raise SchemaValidationError, schema.error_message
|
39
|
+
end
|
40
|
+
|
41
|
+
def required_schema
|
42
|
+
SpreeCmCommissioner::ProfileImageRequestSchema
|
43
|
+
end
|
44
|
+
|
45
|
+
def resource_serializer
|
46
|
+
Spree::V2::Tenant::UserProfileSerializer
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Spree
|
2
|
+
module Api
|
3
|
+
module V2
|
4
|
+
module Tenant
|
5
|
+
class S3SignedUrlsController < BaseController
|
6
|
+
def show
|
7
|
+
if resource.error_message.blank?
|
8
|
+
render_serialized_payload { serialize_resource(resource) }
|
9
|
+
else
|
10
|
+
render_error_payload(resource.error_message)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def resource
|
15
|
+
SpreeCmCommissioner::S3PresignedUrlBuilder.call(
|
16
|
+
bucket_name: params[:bucket_name],
|
17
|
+
object_key: params[:object_key],
|
18
|
+
file_name: params[:file_name]
|
19
|
+
)
|
20
|
+
end
|
21
|
+
|
22
|
+
def resource_serializer
|
23
|
+
Spree::V2::Tenant::S3SignedUrlSerializer
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module SpreeCmCommissioner
|
2
|
+
class CrewInviter < BaseInteractor
|
3
|
+
delegate :id, :invitee_id, to: :context
|
4
|
+
|
5
|
+
def call
|
6
|
+
validate_data
|
7
|
+
assign_role_to_user
|
8
|
+
create_user_event
|
9
|
+
update_invite_user_event
|
10
|
+
context.invite = crew_invite
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def validate_data
|
16
|
+
if invite_user_event.nil?
|
17
|
+
context.fail!(message: I18n.t('invite.url_not_found'))
|
18
|
+
elsif !invite_user_event.invite.url_valid?
|
19
|
+
context.fail!(message: I18n.t('invite.url_expired'))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def assign_role_to_user
|
24
|
+
return if user.operator?
|
25
|
+
|
26
|
+
role = Spree::Role.find_by(name: 'operator')
|
27
|
+
role_user = Spree::RoleUser.new(user_id: user.id, role_id: role.id)
|
28
|
+
role_user.save
|
29
|
+
end
|
30
|
+
|
31
|
+
def create_user_event
|
32
|
+
@user_event = SpreeCmCommissioner::UserEvent.new(
|
33
|
+
taxon_id: crew_invite.taxon_id,
|
34
|
+
user_id: user.id
|
35
|
+
)
|
36
|
+
|
37
|
+
return if @user_event.save
|
38
|
+
|
39
|
+
context.fail!(message: I18n.t('invite.already_invited'))
|
40
|
+
end
|
41
|
+
|
42
|
+
def update_invite_user_event
|
43
|
+
invite_user_event.user_taxon_id = @user_event.id
|
44
|
+
invite_user_event.confirmed_at = Time.current
|
45
|
+
|
46
|
+
return if @invite_user_event.save
|
47
|
+
|
48
|
+
context.fail!(message: I18n.t('invite.update_fail'))
|
49
|
+
end
|
50
|
+
|
51
|
+
def crew_invite
|
52
|
+
@crew_invite ||= SpreeCmCommissioner::CrewInvite.find(id)
|
53
|
+
end
|
54
|
+
|
55
|
+
def invite_user_event
|
56
|
+
@invite_user_event ||= crew_invite.invite_user_events.find_by(email: user.email, confirmed_at: nil)
|
57
|
+
end
|
58
|
+
|
59
|
+
def user
|
60
|
+
@user ||= Spree::User.find(invitee_id)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -55,15 +55,20 @@ module SpreeCmCommissioner
|
|
55
55
|
end
|
56
56
|
|
57
57
|
def end_users
|
58
|
+
users_scope = Spree.user_class.where(tenant_id: customer_notification.tenant_id)
|
59
|
+
|
58
60
|
if customer_notification.notification_taxons.exists?
|
59
61
|
taxon_ids = customer_notification.notification_taxons.pluck(:taxon_id)
|
60
|
-
SpreeCmCommissioner::UsersByEventFetcherQuery
|
61
|
-
|
62
|
-
|
63
|
-
|
62
|
+
users_scope = SpreeCmCommissioner::UsersByEventFetcherQuery
|
63
|
+
.new(taxon_ids)
|
64
|
+
.call
|
65
|
+
.end_users_push_notificable
|
66
|
+
.where(tenant_id: customer_notification.tenant_id)
|
64
67
|
else
|
65
|
-
|
68
|
+
users_scope = users_scope.end_users_push_notificable
|
66
69
|
end
|
70
|
+
|
71
|
+
users_scope
|
67
72
|
end
|
68
73
|
end
|
69
74
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module SpreeCmCommissioner
|
2
|
+
class ProfileImageDestroyer < BaseInteractor
|
3
|
+
delegate :user, to: :context
|
4
|
+
|
5
|
+
def call
|
6
|
+
profile_image = SpreeCmCommissioner::UserProfile.find_by(viewable: user)
|
7
|
+
|
8
|
+
if profile_image
|
9
|
+
profile_image.destroy
|
10
|
+
context.result = profile_image
|
11
|
+
else
|
12
|
+
context.fail!(message: 'No profile image to delete')
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module SpreeCmCommissioner
|
2
|
+
class CrewInviteMailer < Spree::BaseMailer
|
3
|
+
layout 'spree_cm_commissioner/layouts/crew_invite_mailer'
|
4
|
+
|
5
|
+
def send_crew_invite_email(invite_user_event_id)
|
6
|
+
@invite_user_event = SpreeCmCommissioner::InviteUserEvent.find(invite_user_event_id)
|
7
|
+
|
8
|
+
subject = Spree::Store.default.name.to_s
|
9
|
+
|
10
|
+
mail(from: from_address, to: @invite_user_event.email, subject: subject)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -46,7 +46,12 @@ module SpreeCmCommissioner
|
|
46
46
|
'bib-zerofill' => 'integer',
|
47
47
|
'bib-display-prefix' => 'boolean',
|
48
48
|
'bib-pre-generation-on-create' => 'boolean',
|
49
|
-
'seat-number-positions' => 'array'
|
49
|
+
'seat-number-positions' => 'array',
|
50
|
+
'origin' => 'origin',
|
51
|
+
'destination' => 'destination',
|
52
|
+
'departure-time' => 'time',
|
53
|
+
'vehicle' => 'vehicle_id',
|
54
|
+
'allow-seat-selection' => 'boolean'
|
50
55
|
}.freeze
|
51
56
|
|
52
57
|
included do
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module SpreeCmCommissioner
|
2
|
+
class Invite < SpreeCmCommissioner::Base
|
3
|
+
belongs_to :taxon, class_name: 'Spree::Taxon'
|
4
|
+
belongs_to :inviter, class_name: 'Spree::User'
|
5
|
+
has_many :invite_user_events, class_name: 'SpreeCmCommissioner::InviteUserEvent', dependent: :destroy
|
6
|
+
scope :active, -> { where('expires_at > ?', Time.current) }
|
7
|
+
|
8
|
+
after_create :set_expiration
|
9
|
+
|
10
|
+
def set_expiration
|
11
|
+
update(expires_at: 3.days.from_now)
|
12
|
+
end
|
13
|
+
|
14
|
+
def invite_url
|
15
|
+
"#{Spree::Store.default.formatted_url}/invite/#{token}?utm_source=email"
|
16
|
+
end
|
17
|
+
|
18
|
+
def url_valid?
|
19
|
+
expires_at.present? && expires_at > Time.current
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module SpreeCmCommissioner
|
2
|
+
class InviteUserTaxon < SpreeCmCommissioner::Base
|
3
|
+
belongs_to :user_taxon, class_name: 'SpreeCmCommissioner::UserTaxon'
|
4
|
+
belongs_to :invite, class_name: 'SpreeCmCommissioner::Invite'
|
5
|
+
after_create :send_crew_invite_email
|
6
|
+
|
7
|
+
def send_crew_invite_email
|
8
|
+
SpreeCmCommissioner::CrewInviteMailer.send_crew_invite_email(id).deliver_later
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -24,7 +24,7 @@ module SpreeCmCommissioner
|
|
24
24
|
|
25
25
|
base.validate :ensure_not_exceed_max_quantity_per_order, if: -> { variant&.max_quantity_per_order.present? }
|
26
26
|
|
27
|
-
base.whitelisted_ransackable_associations |= %w[guests]
|
27
|
+
base.whitelisted_ransackable_associations |= %w[guests order]
|
28
28
|
base.whitelisted_ransackable_attributes |= %w[number to_date from_date vendor_id]
|
29
29
|
|
30
30
|
base.delegate :delivery_required?, :permanent_stock?, :high_demand, :transit?,
|
@@ -42,7 +42,7 @@ module SpreeCmCommissioner
|
|
42
42
|
base.delegate :customer, to: :user, allow_nil: true
|
43
43
|
|
44
44
|
base.whitelisted_ransackable_associations |= %w[customer taxon payments invoice]
|
45
|
-
base.whitelisted_ransackable_attributes |= %w[intel_phone_number phone_number email number]
|
45
|
+
base.whitelisted_ransackable_attributes |= %w[intel_phone_number phone_number email number state]
|
46
46
|
|
47
47
|
def base.search_by_qr_data!(data)
|
48
48
|
token = data.match(/^R\d{9,}-([A-Za-z0-9_\-]+)$/)&.captures
|
@@ -13,6 +13,8 @@ module SpreeCmCommissioner
|
|
13
13
|
|
14
14
|
has_many :product_places, class_name: 'SpreeCmCommissioner::ProductPlace', dependent: :destroy
|
15
15
|
has_many :products, through: :product_places
|
16
|
+
has_many :children, class_name: 'SpreeCmCommissioner::Place', foreign_key: :parent_id, dependent: :destroy
|
17
|
+
belongs_to :parent, class_name: 'SpreeCmCommissioner::Place', optional: true
|
16
18
|
|
17
19
|
def self.ransackable_attributes(auth_object = nil)
|
18
20
|
super & %w[name code]
|
@@ -28,6 +28,7 @@ module SpreeCmCommissioner
|
|
28
28
|
base.has_one :web_banner, as: :viewable, dependent: :destroy, class_name: 'SpreeCmCommissioner::TaxonWebBanner'
|
29
29
|
base.has_one :app_banner, as: :viewable, dependent: :destroy, class_name: 'SpreeCmCommissioner::TaxonAppBanner'
|
30
30
|
base.has_one :home_banner, as: :viewable, dependent: :destroy, class_name: 'SpreeCmCommissioner::TaxonHomeBanner'
|
31
|
+
base.has_one :video_banner, as: :viewable, dependent: :destroy, class_name: 'SpreeCmCommissioner::TaxonVideoBanner'
|
31
32
|
|
32
33
|
# Update children association to work with nested set (lft, rgt)
|
33
34
|
base.has_many :children, -> { order(:lft) }, class_name: 'Spree::Taxon', foreign_key: :parent_id, dependent: :destroy
|
@@ -48,6 +49,10 @@ module SpreeCmCommissioner
|
|
48
49
|
base.whitelisted_ransackable_attributes |= %w[kind]
|
49
50
|
|
50
51
|
base.enum purchasable_on: { both: 0, web: 1, app: 2 }
|
52
|
+
base.has_many :crew_invites, class_name: 'SpreeCmCommissioner::CrewInvite', dependent: :destroy
|
53
|
+
base.has_many :invite_user_events, through: :user_events, class_name: 'SpreeCmCommissioner::InviteUserEvent'
|
54
|
+
|
55
|
+
base.has_many :line_items, through: :products
|
51
56
|
end
|
52
57
|
# rubocop:enable Metrics/MethodLength
|
53
58
|
|
@@ -143,5 +143,28 @@ module SpreeCmCommissioner
|
|
143
143
|
def number_of_guests
|
144
144
|
number_of_adults + number_of_kids
|
145
145
|
end
|
146
|
+
|
147
|
+
def origin
|
148
|
+
@origin ||= option_value_name_for(option_type_name: 'origin')&.to_i
|
149
|
+
end
|
150
|
+
|
151
|
+
def destination
|
152
|
+
@destination ||= option_value_name_for(option_type_name: 'destination')&.to_i
|
153
|
+
end
|
154
|
+
|
155
|
+
def vehicle
|
156
|
+
@vehicle ||= option_value_name_for(option_type_name: 'vehicle')&.to_i
|
157
|
+
end
|
158
|
+
|
159
|
+
def allow_seat_selection
|
160
|
+
@allow_seat_selection ||= option_value_name_for(option_type_name: 'allow-seat-selection')&.to_i
|
161
|
+
end
|
162
|
+
|
163
|
+
def departure_time
|
164
|
+
@departure_time ||= begin
|
165
|
+
time = option_value_name_for(option_type_name: 'departure-time')
|
166
|
+
Time.zone.parse(time) if time.present?
|
167
|
+
end
|
168
|
+
end
|
146
169
|
end
|
147
170
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module SpreeCmCommissioner
|
2
|
+
class Video < Spree::Asset
|
3
|
+
include ::Rails.application.routes.url_helpers
|
4
|
+
|
5
|
+
has_one_attached :attachment
|
6
|
+
|
7
|
+
validates :attachment, attached: true, content_type: %r{\Avideo/.*\z}
|
8
|
+
|
9
|
+
default_scope { includes(attachment_attachment: :blob) }
|
10
|
+
|
11
|
+
def original_url
|
12
|
+
cdn_image_url(attachment)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -47,5 +47,24 @@
|
|
47
47
|
form:f,
|
48
48
|
classes: ['col-md-5 ml-3']
|
49
49
|
%>
|
50
|
+
|
51
|
+
<%= f.field_container :video_banner, direct_upload: true, class: ['col-md-5 ml-3 rounded border p-3'] do %>
|
52
|
+
<% if @taxon.video_banner&.attachment.present? %>
|
53
|
+
<video class="rounded border mb-4 mw-150" style="max-height: 200px" controls>
|
54
|
+
<source src="<%= main_app.rails_blob_url(@taxon.video_banner.attachment) %>" type="<%= @taxon.video_banner.attachment.content_type %>">
|
55
|
+
Your browser does not support the video tag.
|
56
|
+
</video>
|
57
|
+
<% end %>
|
58
|
+
|
59
|
+
<div data-hook="file" class="mb-3" >
|
60
|
+
<%= f.label :video_banner, I18n.t('taxon.video_banner') %>
|
61
|
+
<%= f.label :video_banner, I18n.t('taxon.video_banner_require_size') %>
|
62
|
+
<%= f.file_field :video_banner, required: false, accept: "video/*" %>
|
63
|
+
</div>
|
64
|
+
|
65
|
+
<% if @taxon.video_banner.present? && defined?(remove_video_banner_admin_taxonomy_taxon_url) %>
|
66
|
+
<%= link_to Spree.t(:remove_video), remove_video_banner_admin_taxonomy_taxon_url, method: :delete %>
|
67
|
+
<% end %>
|
68
|
+
<% end %>
|
50
69
|
</div>
|
51
70
|
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<!-- insert_before "erb[loud]:contains('field_container :parent_id')" -->
|
2
|
+
|
3
|
+
<div class="form-group">
|
4
|
+
<%= label_tag nil, Spree.t(:available_on) %>
|
5
|
+
<div class="input-group datePickerFrom"
|
6
|
+
data-wrap="true"
|
7
|
+
data-alt-input="true"
|
8
|
+
data-min-date="<%= Time.now.strftime('%Y-%m-%d') %>"
|
9
|
+
data-enable-time="true">
|
10
|
+
<%= f.text_field :available_on,
|
11
|
+
value: @taxon.available_on,
|
12
|
+
placeholder: Spree.t(:select_a_date),
|
13
|
+
class: 'form-control shadow-none',
|
14
|
+
'data-input':'' %>
|
15
|
+
|
16
|
+
<%= render partial: 'spree/admin/shared/cal_close' %>
|
17
|
+
</div>
|
18
|
+
</div>
|