spree_multi_vendor 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (124) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +44 -0
  5. data/Appraisals +11 -0
  6. data/Gemfile +7 -0
  7. data/LICENSE +26 -0
  8. data/README.md +166 -0
  9. data/Rakefile +21 -0
  10. data/app/controllers/spree/admin/vendor_settings_controller.rb +34 -0
  11. data/app/controllers/spree/admin/vendors_controller.rb +60 -0
  12. data/app/controllers/spree/api/v2/storefront/vendors_controller.rb +28 -0
  13. data/app/controllers/spree_multi_vendor/spree/admin/base_controller_decorator.rb +10 -0
  14. data/app/controllers/spree_multi_vendor/spree/admin/option_types_controller_decorator.rb +7 -0
  15. data/app/controllers/spree_multi_vendor/spree/admin/products_controller_decorator.rb +24 -0
  16. data/app/controllers/spree_multi_vendor/spree/admin/properties_controller_decorator.rb +7 -0
  17. data/app/controllers/spree_multi_vendor/spree/admin/resource_controller_decorator.rb +8 -0
  18. data/app/controllers/spree_multi_vendor/spree/admin/shipping_methods_controller_decorator.rb +7 -0
  19. data/app/controllers/spree_multi_vendor/spree/admin/stock_locations_controller_decorator.rb +7 -0
  20. data/app/controllers/spree_multi_vendor/spree/admin/users_controller_decorator.rb +13 -0
  21. data/app/controllers/spree_multi_vendor/spree/admin/variants_controller_decorator.rb +7 -0
  22. data/app/controllers/spree_multi_vendor/spree/api/v1/variants_controller_decorator.rb +22 -0
  23. data/app/finders/spree_multi_vendor/products_finder_decorator.rb +31 -0
  24. data/app/helpers/spree/admin/vendor_helper.rb +15 -0
  25. data/app/mailers/spree/vendor_mailer.rb +15 -0
  26. data/app/models/concerns/spree/vendor_concern.rb +11 -0
  27. data/app/models/spree/order_commission.rb +11 -0
  28. data/app/models/spree/vendor.rb +77 -0
  29. data/app/models/spree/vendor_ability.rb +140 -0
  30. data/app/models/spree/vendor_image.rb +18 -0
  31. data/app/models/spree/vendor_order_totals.rb +28 -0
  32. data/app/models/spree/vendor_user.rb +16 -0
  33. data/app/models/spree_multi_vendor/configuration.rb +10 -0
  34. data/app/models/spree_multi_vendor/spree/ability_decorator.rb +9 -0
  35. data/app/models/spree_multi_vendor/spree/base_decorator.rb +13 -0
  36. data/app/models/spree_multi_vendor/spree/line_item_decorator.rb +48 -0
  37. data/app/models/spree_multi_vendor/spree/order_decorator.rb +105 -0
  38. data/app/models/spree_multi_vendor/spree/shipment_decorator.rb +8 -0
  39. data/app/models/spree_multi_vendor/spree/stock/package_decorator.rb +14 -0
  40. data/app/models/spree_multi_vendor/spree/user_decorator.rb +8 -0
  41. data/app/models/spree_multi_vendor/spree/variant_decorator.rb +41 -0
  42. data/app/overrides/spree/admin/orders/_form.rb +13 -0
  43. data/app/overrides/spree/admin/orders/_line_items.rb +6 -0
  44. data/app/overrides/spree/admin/orders/_line_items_edit_form.rb +6 -0
  45. data/app/overrides/spree/admin/orders/index.rb +6 -0
  46. data/app/overrides/spree/admin/products/form.rb +29 -0
  47. data/app/overrides/spree/admin/products/new.rb +16 -0
  48. data/app/overrides/spree/admin/shared/_main_menu.rb +23 -0
  49. data/app/overrides/spree/admin/shared/_order_summary.rb +35 -0
  50. data/app/overrides/spree/admin/users/_form.rb +13 -0
  51. data/app/serializers/spree/v2/storefront/vendor_image_serializer.rb +11 -0
  52. data/app/serializers/spree/v2/storefront/vendor_order_totals_serializer.rb +18 -0
  53. data/app/serializers/spree/v2/storefront/vendor_serializer.rb +14 -0
  54. data/app/serializers/spree_multi_vendor/cart_serializer_decorator.rb +19 -0
  55. data/app/serializers/spree_multi_vendor/serializer_decorator.rb +23 -0
  56. data/app/services/spree/orders/generate_commissions.rb +34 -0
  57. data/app/views/spree/admin/translations/vendor.html.erb +21 -0
  58. data/app/views/spree/admin/vendor_settings/edit.html.erb +47 -0
  59. data/app/views/spree/admin/vendors/_form.html.erb +36 -0
  60. data/app/views/spree/admin/vendors/edit.html.erb +11 -0
  61. data/app/views/spree/admin/vendors/index.html.erb +83 -0
  62. data/app/views/spree/admin/vendors/new.html.erb +11 -0
  63. data/app/views/spree/vendor_mailer/vendor_notification_email.html.erb +81 -0
  64. data/app/views/spree/vendor_mailer/vendor_notification_email.text.erb +36 -0
  65. data/bin/rails +7 -0
  66. data/config/initializers/spree_permitted_attributes.rb +10 -0
  67. data/config/locales/en.yml +34 -0
  68. data/config/locales/es.yml +33 -0
  69. data/config/locales/fr.yml +33 -0
  70. data/config/routes.rb +19 -0
  71. data/db/default/vendors.rb +13 -0
  72. data/db/migrate/20170406102250_create_spree_vendors.rb +9 -0
  73. data/db/migrate/20170406102944_add_vendor_id_to_spree_models.rb +10 -0
  74. data/db/migrate/20170410111150_add_state_to_vendors.rb +6 -0
  75. data/db/migrate/20170412124925_add_deleted_at_to_spree_vendors.rb +6 -0
  76. data/db/migrate/20170413094447_create_spree_vendor_users.rb +11 -0
  77. data/db/migrate/20190212161426_add_slug_to_spree_vendors.rb +6 -0
  78. data/db/migrate/20190214120226_add_about_us_to_spree_vendors.rb +5 -0
  79. data/db/migrate/20190214142526_add_contact_us_to_spree_vendors.rb +5 -0
  80. data/db/migrate/20190305120337_add_commission_to_spree_vendors.rb +5 -0
  81. data/db/migrate/20190308091546_add_priority_to_vendor.rb +8 -0
  82. data/db/migrate/20190312130754_create_spree_order_commissions.rb +14 -0
  83. data/db/migrate/20190322133128_add_notification_email_to_vendors.rb +5 -0
  84. data/db/migrate/20200416030721_add_translations_to_vendor.rb +19 -0
  85. data/gemfiles/spree_4_2.gemfile +9 -0
  86. data/gemfiles/spree_master.gemfile +9 -0
  87. data/lib/generators/spree_multi_vendor/install/install_generator.rb +21 -0
  88. data/lib/generators/spree_multi_vendor/mailers_preview/mailers_preview_generator.rb +22 -0
  89. data/lib/generators/spree_multi_vendor/mailers_preview/templates/mailers/previews/vendor_notification_preview.rb +5 -0
  90. data/lib/spree_multi_vendor.rb +14 -0
  91. data/lib/spree_multi_vendor/engine.rb +24 -0
  92. data/lib/spree_multi_vendor/factories.rb +7 -0
  93. data/lib/spree_multi_vendor/version.rb +11 -0
  94. data/lib/tasks/vendors.rake +8 -0
  95. data/spec/factories/spree/vendor_factory.rb +22 -0
  96. data/spec/factories/spree/vendor_image_factory.rb +5 -0
  97. data/spec/factories/spree/vendor_user_factory.rb +6 -0
  98. data/spec/features/spree/admin/orders_spec.rb +36 -0
  99. data/spec/features/spree/admin/product_spec.rb +177 -0
  100. data/spec/features/spree/admin/shipping_method_spec.rb +72 -0
  101. data/spec/features/spree/admin/stock_location_spec.rb +90 -0
  102. data/spec/features/spree/admin/vendor_settings_spec.rb +76 -0
  103. data/spec/features/spree/admin/vendor_spec.rb +125 -0
  104. data/spec/fixtures/thinking-cat.jpg +0 -0
  105. data/spec/mailers/vendor_mailer_spec.rb +45 -0
  106. data/spec/models/spree/line_item_spec.rb +32 -0
  107. data/spec/models/spree/order_commission_spec.rb +8 -0
  108. data/spec/models/spree/order_spec.rb +179 -0
  109. data/spec/models/spree/product_spec.rb +19 -0
  110. data/spec/models/spree/variant_spec.rb +104 -0
  111. data/spec/models/spree/vendor_order_totals_spec.rb +33 -0
  112. data/spec/models/spree/vendor_spec.rb +57 -0
  113. data/spec/models/spree/vendor_user_spec.rb +12 -0
  114. data/spec/requests/spree/api/v2/storefront/cart_spec.rb +67 -0
  115. data/spec/requests/spree/api/v2/storefront/products_spec.rb +93 -0
  116. data/spec/requests/spree/api/v2/storefront/vendors_spec.rb +52 -0
  117. data/spec/serializers/spree/v2/storefront/stock_location_serializer_spec.rb +32 -0
  118. data/spec/serializers/spree/v2/storefront/vendor_image_serializer_spec.rb +18 -0
  119. data/spec/serializers/spree/v2/storefront/vendor_order_totals_serializer_spec.rb +54 -0
  120. data/spec/serializers/spree/v2/storefront/vendor_serializer_spec.rb +34 -0
  121. data/spec/spec_helper.rb +11 -0
  122. data/spec/support/shoulda_matchers.rb +6 -0
  123. data/spree_multi_vendor.gemspec +41 -0
  124. metadata +313 -0
@@ -0,0 +1,10 @@
1
+ module SpreeMultiVendor::Spree::Admin::BaseControllerDecorator
2
+ Spree::Admin::BaseController.include(Spree::Admin::VendorHelper)
3
+
4
+ def self.prepended(base)
5
+ base.helper_method :current_spree_vendor
6
+ base.helper_method :vendor_state_options
7
+ end
8
+ end
9
+
10
+ Spree::Admin::BaseController.prepend SpreeMultiVendor::Spree::Admin::BaseControllerDecorator
@@ -0,0 +1,7 @@
1
+ module SpreeMultiVendor::Spree::Admin::OptionTypesControllerDecorator
2
+ def self.prepended(base)
3
+ base.before_action :set_vendor_id, only: [:create, :update]
4
+ end
5
+ end
6
+
7
+ Spree::Admin::OptionTypesController.prepend SpreeMultiVendor::Spree::Admin::OptionTypesControllerDecorator
@@ -0,0 +1,24 @@
1
+ module SpreeMultiVendor::Spree::Admin::ProductsControllerDecorator
2
+ def self.prepended(base)
3
+ base.before_action :set_vendor_id, only: [:create, :update]
4
+ base.before_action :load_vendors, only: [:new, :edit, :update]
5
+ end
6
+
7
+ def stock
8
+ @variants = @product.variants.includes(*variant_stock_includes)
9
+ @variants = [@product.master] if @variants.empty?
10
+ @stock_locations = Spree::StockLocation.accessible_by(current_ability, :read).where(vendor_id: @product.vendor_id)
11
+ if @stock_locations.empty?
12
+ flash[:error] = Spree.t(:stock_management_requires_a_stock_location)
13
+ redirect_to admin_stock_locations_path
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def load_vendors
20
+ @vendors = Spree::Vendor.order(Arel.sql('LOWER(name)'))
21
+ end
22
+ end
23
+
24
+ Spree::Admin::ProductsController.prepend SpreeMultiVendor::Spree::Admin::ProductsControllerDecorator
@@ -0,0 +1,7 @@
1
+ module SpreeMultiVendor::Spree::Admin::PropertiesControllerDecorator
2
+ def self.prepended(base)
3
+ base.before_action :set_vendor_id, only: [:create, :update]
4
+ end
5
+ end
6
+
7
+ Spree::Admin::PropertiesController.prepend SpreeMultiVendor::Spree::Admin::PropertiesControllerDecorator
@@ -0,0 +1,8 @@
1
+ module SpreeMultiVendor::Spree::Admin::ResourceControllerDecorator
2
+ def set_vendor_id
3
+ return unless current_spree_vendor
4
+ params[resource.object_name.to_sym][:vendor_id] = current_spree_vendor.id
5
+ end
6
+ end
7
+
8
+ Spree::Admin::ResourceController.prepend SpreeMultiVendor::Spree::Admin::ResourceControllerDecorator
@@ -0,0 +1,7 @@
1
+ module SpreeMultiVendor::Spree::Admin::ShippingMethodsControllerDecorator
2
+ def self.prepended(base)
3
+ base.before_action :set_vendor_id, only: [:create, :update]
4
+ end
5
+ end
6
+
7
+ Spree::Admin::ShippingMethodsController.prepend SpreeMultiVendor::Spree::Admin::ShippingMethodsControllerDecorator
@@ -0,0 +1,7 @@
1
+ module SpreeMultiVendor::Spree::Admin::StockLocationsControllerDecorator
2
+ def self.prepended(base)
3
+ base.before_action :set_vendor_id, only: [:create, :update]
4
+ end
5
+ end
6
+
7
+ Spree::Admin::StockLocationsController.prepend SpreeMultiVendor::Spree::Admin::StockLocationsControllerDecorator
@@ -0,0 +1,13 @@
1
+ module SpreeMultiVendor::Spree::Admin::UsersControllerDecorator
2
+ private
3
+
4
+ def user_params
5
+ params.require(:user).permit(permitted_user_attributes |
6
+ [spree_role_ids: [],
7
+ vendor_ids: [],
8
+ ship_address_attributes: permitted_address_attributes,
9
+ bill_address_attributes: permitted_address_attributes])
10
+ end
11
+ end
12
+
13
+ Spree::Admin::UsersController.prepend SpreeMultiVendor::Spree::Admin::UsersControllerDecorator
@@ -0,0 +1,7 @@
1
+ module SpreeMultiVendor::Spree::Admin::VariantsControllerDecorator
2
+ def self.prepended(base)
3
+ base.before_action :set_vendor_id, only: [:create, :update]
4
+ end
5
+ end
6
+
7
+ Spree::Admin::VariantsController.prepend SpreeMultiVendor::Spree::Admin::VariantsControllerDecorator
@@ -0,0 +1,22 @@
1
+ module SpreeMultiVendor::Spree::Api::V1::VariantsControllerDecorator
2
+ private
3
+
4
+ def scope
5
+ variants = if @product
6
+ @product.variants_including_master
7
+ else
8
+ Spree::Variant
9
+ end
10
+
11
+ if current_ability.can?(:manage, Spree::Variant) && params[:show_deleted]
12
+ variants = variants.with_deleted
13
+ end
14
+
15
+ variants = variants.for_vendor_user(current_spree_user) unless @current_user_roles.include?('admin')
16
+ variants = variants.eligible if Spree.version.to_f >= 3.7
17
+
18
+ variants.accessible_by(current_ability, :read)
19
+ end
20
+ end
21
+
22
+ Spree::Api::V1::VariantsController.prepend SpreeMultiVendor::Spree::Api::V1::VariantsControllerDecorator
@@ -0,0 +1,31 @@
1
+ module SpreeMultiVendor
2
+ module ProductsFinderDecorator
3
+ def initialize(scope:, params:, current_currency:)
4
+ super
5
+
6
+ @vendors = params.dig(:filter, :vendor_ids)&.split(',')
7
+ end
8
+
9
+ def execute
10
+ products = by_vendors(super)
11
+
12
+ products.distinct
13
+ end
14
+
15
+ private
16
+
17
+ attr_reader :vendors
18
+
19
+ def vendors?
20
+ vendors.present?
21
+ end
22
+
23
+ def by_vendors(products)
24
+ return products unless vendors?
25
+
26
+ products.where(vendor_id: vendors)
27
+ end
28
+ end
29
+ end
30
+
31
+ ::Spree::Products::Find.prepend(SpreeMultiVendor::ProductsFinderDecorator)
@@ -0,0 +1,15 @@
1
+ module Spree
2
+ module Admin
3
+ module VendorHelper
4
+ def current_spree_vendor
5
+ if current_spree_user.vendors.any? && (!current_spree_user.respond_to?(:has_spree_role?) || !current_spree_user.has_spree_role?(:admin))
6
+ current_spree_user.vendors.first
7
+ end
8
+ end
9
+
10
+ def vendor_state_options
11
+ @vendor_state_options ||= Spree::Vendor.state_machines[:state].states.collect { |s| [Spree.t("vendor_states.#{s.name}"), s.value] }
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module Spree
2
+ class VendorMailer < ::Spree::BaseMailer
3
+ def vendor_notification_email(order_id, vendor_id)
4
+ @vendor = Spree::Vendor.find(vendor_id)
5
+ return unless @vendor.notification_email.present?
6
+
7
+ @order = Spree::Order.find(order_id)
8
+ @line_items = @order.line_items.for_vendor(@vendor)
9
+ @subtotal = @order.vendor_subtotal(@vendor)
10
+ @total = @order.vendor_total(@vendor)
11
+ subject = "#{Spree::Store.current.name} #{Spree.t('order_mailer.vendor_notification_email.subject')} ##{@order.number}"
12
+ mail(to: @vendor.notification_email, from: from_address, subject: subject)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,11 @@
1
+ module Spree
2
+ module VendorConcern
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ belongs_to :vendor, class_name: 'Spree::Vendor', touch: true, optional: true
7
+
8
+ scope :with_vendor, ->(vendor_id) { where(vendor_id: vendor_id) }
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Spree
2
+ class OrderCommission < Base
3
+ belongs_to :order, required: Spree.version.to_f >= 3.5
4
+ belongs_to :vendor, required: Spree.version.to_f >= 3.5
5
+
6
+ validates :order, :vendor, presence: true
7
+ validates :vendor_id, uniqueness: { scope: :order_id }
8
+
9
+ scope :for_vendor, ->(vendor) { where(vendor_id: vendor.id) }
10
+ end
11
+ end
@@ -0,0 +1,77 @@
1
+ module Spree
2
+ class Vendor < Spree::Base
3
+ extend FriendlyId
4
+
5
+ acts_as_paranoid
6
+ acts_as_list column: :priority
7
+ friendly_id :name, use: %i[slugged history]
8
+
9
+ validates :name,
10
+ presence: true,
11
+ uniqueness: { case_sensitive: false }
12
+
13
+ validates :slug, uniqueness: true
14
+ validates_associated :image if Spree.version.to_f >= 3.6
15
+
16
+ validates :notification_email, email: true, allow_blank: true
17
+
18
+ with_options dependent: :destroy do
19
+ has_one :image, as: :viewable, dependent: :destroy, class_name: 'Spree::VendorImage'
20
+ has_many :commissions, class_name: 'Spree::OrderCommission'
21
+ has_many :vendor_users
22
+
23
+ SpreeMultiVendor::Config[:vendorized_models].uniq.compact.each do |model|
24
+ has_many model.pluralize.to_sym
25
+ end
26
+ end
27
+
28
+ has_many :users, through: :vendor_users, class_name: Spree.user_class.to_s
29
+
30
+ after_create :create_stock_location
31
+ after_update :update_stock_location_names
32
+
33
+ state_machine :state, initial: :pending do
34
+ event :activate do
35
+ transition to: :active
36
+ end
37
+
38
+ event :block do
39
+ transition to: :blocked
40
+ end
41
+ end
42
+
43
+ scope :active, -> { where(state: 'active') }
44
+
45
+ self.whitelisted_ransackable_attributes = %w[name state]
46
+
47
+ def update_notification_email(email)
48
+ update(notification_email: email)
49
+ end
50
+
51
+ # Spree Globalize support
52
+ # https://github.com/spree-contrib/spree_multi_vendor/issues/104
53
+ if defined?(SpreeGlobalize)
54
+ attr_accessor :translations_attributes
55
+ translates :name,
56
+ :about_us,
57
+ :contact_us,
58
+ :slug, fallbacks_for_empty_translations: true
59
+ end
60
+
61
+ private
62
+
63
+ def create_stock_location
64
+ stock_locations.where(name: name, country: Spree::Country.default).first_or_create!
65
+ end
66
+
67
+ def should_generate_new_friendly_id?
68
+ slug.blank? || name_changed?
69
+ end
70
+
71
+ def update_stock_location_names
72
+ if (Spree.version.to_f < 3.5 && self.name_changed?) || (Spree.version.to_f >= 3.5 && saved_changes&.include?(:name))
73
+ stock_locations.update_all({ name: name })
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,140 @@
1
+ class Spree::VendorAbility
2
+ include CanCan::Ability
3
+
4
+ def initialize(user)
5
+ @vendor_ids = user.vendors.active.ids
6
+
7
+ if @vendor_ids.any?
8
+ apply_classifications_permissions
9
+ apply_order_permissions
10
+ apply_image_permissions
11
+ apply_option_type_permissions
12
+ apply_price_permissions
13
+ apply_product_option_type_permissions
14
+ apply_product_permissions
15
+ apply_product_properties_permissions
16
+ apply_properties_permissions
17
+ apply_prototypes_permissions
18
+ apply_shipment_permissions
19
+ apply_shipping_methods_permissions
20
+ apply_stock_permissions
21
+ apply_stock_item_permissions
22
+ apply_stock_location_permissions
23
+ apply_stock_movement_permissions
24
+ apply_variant_permissions
25
+ apply_vendor_permissions
26
+ apply_vendor_settings_permissions
27
+ apply_state_changes_permissions
28
+ end
29
+ end
30
+
31
+ protected
32
+
33
+ def apply_classifications_permissions
34
+ can :manage, Spree::Classification, product: { vendor_id: @vendor_ids }
35
+ end
36
+
37
+ def apply_order_permissions
38
+ cannot :create, Spree::Order
39
+ can [:admin, :index, :edit, :update, :cart], Spree::Order do |order|
40
+ (order.vendor_ids & @vendor_ids).any?
41
+ end
42
+ end
43
+
44
+ def apply_image_permissions
45
+ can :create, Spree::Image
46
+
47
+ can [:manage, :modify], Spree::Image, ['viewable_type = ?', 'Spree::Variant'] do |image|
48
+ vendor_id = image.viewable.try(:vendor_id)
49
+ vendor_id.present? && @vendor_ids.include?(vendor_id)
50
+ end
51
+ end
52
+
53
+ def apply_option_type_permissions
54
+ cannot_display_model(Spree::OptionType)
55
+ can :manage, Spree::OptionType, vendor_id: @vendor_ids
56
+ can :create, Spree::OptionType
57
+ end
58
+
59
+ def apply_price_permissions
60
+ can :modify, Spree::Price, variant: { vendor_id: @vendor_ids }
61
+ end
62
+
63
+ def apply_product_option_type_permissions
64
+ can :display, Spree::OptionType
65
+ can :display, Spree::OptionValue
66
+ can :manage, Spree::ProductOptionType, product: { vendor_id: @vendor_ids }
67
+ can :create, Spree::ProductOptionType
68
+ can :manage, Spree::OptionValueVariant, variant: { vendor_id: @vendor_ids }
69
+ can :create, Spree::OptionValueVariant
70
+ end
71
+
72
+ def apply_product_permissions
73
+ cannot_display_model(Spree::Product)
74
+ can :manage, Spree::Product, vendor_id: @vendor_ids
75
+ can :create, Spree::Product
76
+ end
77
+
78
+ def apply_properties_permissions
79
+ can :display, Spree::Property
80
+ end
81
+
82
+ def apply_product_properties_permissions
83
+ can :manage, Spree::ProductProperty, product: { vendor_id: @vendor_ids }
84
+ can :create, Spree::ProductProperty
85
+ end
86
+
87
+ def apply_prototypes_permissions
88
+ can [:read, :admin], Spree::Prototype
89
+ end
90
+
91
+ def apply_shipment_permissions
92
+ can :update, Spree::Shipment, inventory_units: { line_item: { product: { vendor_id: @vendor_ids } } }
93
+ end
94
+
95
+ def apply_shipping_methods_permissions
96
+ can :manage, Spree::ShippingMethod, vendor_id: @vendor_ids
97
+ can :create, Spree::ShippingMethod
98
+ end
99
+
100
+ def apply_stock_permissions
101
+ can :admin, Spree::Stock
102
+ end
103
+
104
+ def apply_stock_item_permissions
105
+ can [:admin, :modify, :read], Spree::StockItem, stock_location: { vendor_id: @vendor_ids }
106
+ end
107
+
108
+ def apply_stock_location_permissions
109
+ can :manage, Spree::StockLocation, vendor_id: @vendor_ids
110
+ can :create, Spree::StockLocation
111
+ end
112
+
113
+ def apply_stock_movement_permissions
114
+ can :create, Spree::StockMovement
115
+ can :manage, Spree::StockMovement, stock_item: { stock_location: { vendor_id: @vendor_ids } }
116
+ end
117
+
118
+ def apply_variant_permissions
119
+ can :manage, Spree::Variant, vendor_id: @vendor_ids
120
+ can :create, Spree::Variant
121
+ end
122
+
123
+ def apply_vendor_permissions
124
+ can [:admin, :update], Spree::Vendor, id: @vendor_ids
125
+ end
126
+
127
+ def apply_vendor_settings_permissions
128
+ can :manage, :vendor_settings
129
+ end
130
+
131
+ def apply_state_changes_permissions
132
+ can [:admin, :index], Spree::StateChange do |state_change|
133
+ (@vendor_ids & state_change.user.vendor_ids).any?
134
+ end
135
+ end
136
+
137
+ def cannot_display_model(model)
138
+ Spree.version.to_f < 4.0 ? (cannot :display, model) : (cannot :read, model)
139
+ end
140
+ end
@@ -0,0 +1,18 @@
1
+ module Spree
2
+ class VendorImage < Asset
3
+ include Spree::Image::Configuration::ActiveStorage
4
+ include Rails.application.routes.url_helpers
5
+
6
+ def styles
7
+ self.class.styles.map do |_, size|
8
+ width, height = size[/(\d+)x(\d+)/].split('x')
9
+
10
+ {
11
+ url: polymorphic_path(attachment.variant(resize: size), only_path: true),
12
+ width: width,
13
+ height: height
14
+ }
15
+ end
16
+ end
17
+ end
18
+ end