solidus_marketplace 0.1.0
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 +7 -0
- data/.gitignore +18 -0
- data/.rspec +1 -0
- data/.travis.yml +11 -0
- data/Gemfile +8 -0
- data/LICENSE +26 -0
- data/README.md +123 -0
- data/Rakefile +15 -0
- data/Versionfile +6 -0
- data/app/assets/javascripts/spree/backend/solidus_marketplace.js +5 -0
- data/app/assets/javascripts/spree/backend/solidus_marketplace_routes.js +1 -0
- data/app/assets/javascripts/spree/backend/suppliers_autocomplete.js +55 -0
- data/app/assets/javascripts/spree/frontend/solidus_marketplace.js +1 -0
- data/app/assets/stylesheets/spree/backend/solidus_marketplace.scss +22 -0
- data/app/assets/stylesheets/spree/frontend/solidus_marketplace.css +3 -0
- data/app/controllers/ckeditor/attachment_files_controller_decorator.rb +20 -0
- data/app/controllers/ckeditor/pictures_controller_decorator.rb +17 -0
- data/app/controllers/spree/admin/marketplace_settings_controller.rb +19 -0
- data/app/controllers/spree/admin/products_controller_decorator.rb +79 -0
- data/app/controllers/spree/admin/reports_controller_decorator.rb +68 -0
- data/app/controllers/spree/admin/shipments_controller.rb +47 -0
- data/app/controllers/spree/admin/stock_items_controller_decorator.rb +10 -0
- data/app/controllers/spree/admin/stock_locations_controller_decorator.rb +23 -0
- data/app/controllers/spree/admin/suppliers_controller.rb +54 -0
- data/app/controllers/spree/admin/users_controller_decorator.rb +34 -0
- data/app/controllers/spree/api/suppliers_controller.rb +16 -0
- data/app/controllers/spree/api/v1/stock_locations_controller_decorator.rb +18 -0
- data/app/controllers/spree/base_controller_decorator.rb +13 -0
- data/app/helpers/spree/api/api_helpers_decorator.rb +22 -0
- data/app/mailers/spree/marketplace_order_mailer.rb +13 -0
- data/app/mailers/spree/supplier_mailer.rb +12 -0
- data/app/models/ckeditor/asset_decorator.rb +5 -0
- data/app/models/spree.rb +5 -0
- data/app/models/spree/marketplace_configuration.rb +14 -0
- data/app/models/spree/order_decorator.rb +44 -0
- data/app/models/spree/payment_decorator.rb +7 -0
- data/app/models/spree/product_decorator.rb +52 -0
- data/app/models/spree/shipment_decorator.rb +40 -0
- data/app/models/spree/stock/splitter/marketplace.rb +47 -0
- data/app/models/spree/stock_location_decorator.rb +23 -0
- data/app/models/spree/supplier.rb +120 -0
- data/app/models/spree/supplier_ability.rb +35 -0
- data/app/models/spree/supplier_variant.rb +6 -0
- data/app/models/spree/user_decorator.rb +23 -0
- data/app/models/spree/variant_decorator.rb +24 -0
- data/app/overrides/spree/admin/menus.rb +15 -0
- data/app/overrides/spree/admin/products/_form/converted_admin_product_form_right.html.erb.deface +5 -0
- data/app/overrides/spree/admin/products/edit/override_rows.html.erb.deface +22 -0
- data/app/overrides/spree/admin/stock_locations/_form/add_supplier.html.erb.deface +12 -0
- data/app/views/spree/admin/marketplace_settings/edit.html.erb +21 -0
- data/app/views/spree/admin/orders/index.html.erb +187 -0
- data/app/views/spree/admin/products/_form.html.erb +198 -0
- data/app/views/spree/admin/reports/earnings.html.erb +34 -0
- data/app/views/spree/admin/shared/_marketplace_settings.html.erb +1 -0
- data/app/views/spree/admin/shared/_marketplace_tabs.html.erb +4 -0
- data/app/views/spree/admin/shipments/edit.html.erb +24 -0
- data/app/views/spree/admin/shipments/index.html.erb +93 -0
- data/app/views/spree/admin/suppliers/_form.html.erb +75 -0
- data/app/views/spree/admin/suppliers/edit.html.erb +22 -0
- data/app/views/spree/admin/suppliers/index.html.erb +68 -0
- data/app/views/spree/admin/suppliers/new.html.erb +17 -0
- data/app/views/spree/api/shared/_pagination.json.jbuilder +5 -0
- data/app/views/spree/api/suppliers/_supplier.json.jbuilder +1 -0
- data/app/views/spree/api/suppliers/index.json.jbuilder +4 -0
- data/app/views/spree/marketplace_order_mailer/supplier_order.html.erb +119 -0
- data/app/views/spree/shared/unauthorized.erb +1 -0
- data/app/views/spree/supplier_mailer/welcome.html.erb +53 -0
- data/config/locales/en.yml +107 -0
- data/config/locales/es.yml +133 -0
- data/config/routes.rb +24 -0
- data/db/default/spree/marketplace_roles.rb +14 -0
- data/db/migrate/20121006073854_create_suppliers.rb +20 -0
- data/db/migrate/20130216070944_product_belongs_to_supplier.rb +6 -0
- data/db/migrate/20130405005502_stock_locations_belongs_to_supplier.rb +6 -0
- data/db/migrate/20130405011127_user_belongs_to_supplier.rb +6 -0
- data/db/migrate/20130428063053_add_balanced_token_to_suppliers.rb +7 -0
- data/db/migrate/20130510181443_add_supplier_id_to_ckeditor_assets.rb +8 -0
- data/db/migrate/20130606220913_add_permalink_to_suppliers.rb +6 -0
- data/db/migrate/20140323170638_add_supplier_commission_to_shipments.rb +5 -0
- data/db/migrate/20140416184616_migrate_payment_and_commission.rb +7 -0
- data/db/migrate/20140529041325_create_spree_supplier_variants.rb +15 -0
- data/db/migrate/20171027180043_add_paypal_email_to_suppliers.rb +5 -0
- data/db/seeds.rb +8 -0
- data/lib/generators/solidus_marketplace/install/install_generator.rb +36 -0
- data/lib/solidus_marketplace.rb +6 -0
- data/lib/solidus_marketplace/engine.rb +53 -0
- data/lib/solidus_marketplace/factories.rb +107 -0
- data/lib/solidus_marketplace/version.rb +3 -0
- data/lib/spree/permitted_attributes_decorator.rb +18 -0
- data/lib/tasks/spree_sample.rake +72 -0
- data/log/awesome.log +1 -0
- data/script/rails +7 -0
- data/solidus_marketplace.gemspec +46 -0
- data/spec/features/admin/orders_spec.rb +11 -0
- data/spec/features/admin/products_spec.rb +25 -0
- data/spec/features/admin/return_authorizations_spec.rb +7 -0
- data/spec/features/admin/settings_spec.rb +33 -0
- data/spec/features/admin/shipments_spec.rb +80 -0
- data/spec/features/admin/stock_management_spec.rb +156 -0
- data/spec/features/admin/stock_spec.rb +98 -0
- data/spec/features/admin/suppliers_spec.rb +130 -0
- data/spec/models/spree/order_decorator_spec.rb +80 -0
- data/spec/models/spree/payment_decorator_spec.rb +7 -0
- data/spec/models/spree/product_decorator_spec.rb +56 -0
- data/spec/models/spree/shipment_decorator_spec.rb +48 -0
- data/spec/models/spree/stock/splitter/marketplace_spec.rb +62 -0
- data/spec/models/spree/stock_location_decorator_spec.rb +33 -0
- data/spec/models/spree/supplier_ability_spec.rb +182 -0
- data/spec/models/spree/supplier_spec.rb +123 -0
- data/spec/models/spree/supplier_variant_spec.rb +5 -0
- data/spec/models/spree/user_decorator_spec.rb +57 -0
- data/spec/models/spree/variant_decorator_spec.rb +7 -0
- data/spec/spec_helper.rb +91 -0
- data/spec/support/ability_helpers.rb +11 -0
- data/spec/support/integration_helpers.rb +15 -0
- metadata +473 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
Spree::Shipment.class_eval do
|
|
2
|
+
# TODO here to fix cancan issue thinking its just Order
|
|
3
|
+
belongs_to :order, class_name: 'Spree::Order', touch: true, inverse_of: :shipments
|
|
4
|
+
|
|
5
|
+
has_many :payments, as: :payable
|
|
6
|
+
|
|
7
|
+
scope :by_supplier, -> (supplier_id) { joins(:stock_location).where(spree_stock_locations: { supplier_id: supplier_id }) }
|
|
8
|
+
|
|
9
|
+
delegate :supplier, to: :stock_location
|
|
10
|
+
|
|
11
|
+
self.whitelisted_ransackable_attributes = ["number", "state"]
|
|
12
|
+
|
|
13
|
+
def display_final_price_with_items
|
|
14
|
+
Spree::Money.new final_price_with_items
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def final_price_with_items
|
|
18
|
+
self.item_cost + self.final_price
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# TODO move commission to spree_marketplace?
|
|
22
|
+
def supplier_commission_total
|
|
23
|
+
((self.final_price_with_items * self.supplier.commission_percentage / 100) + self.supplier.commission_flat_rate)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
durably_decorate :after_ship, mode: 'soft', sha: '5401c76850108aba74c87a87ff634379bdc844ce' do
|
|
29
|
+
original_after_ship
|
|
30
|
+
|
|
31
|
+
if supplier.present?
|
|
32
|
+
update_commission
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def update_commission
|
|
37
|
+
update_column :supplier_commission, self.supplier_commission_total
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Stock
|
|
3
|
+
module Splitter
|
|
4
|
+
class Marketplace < Spree::Stock::Splitter::Base
|
|
5
|
+
|
|
6
|
+
def split(packages)
|
|
7
|
+
begin
|
|
8
|
+
split_packages = []
|
|
9
|
+
packages.each do |package|
|
|
10
|
+
# Package fulfilled items together.
|
|
11
|
+
fulfilled = package.contents.select { |content|
|
|
12
|
+
begin
|
|
13
|
+
content.variant.suppliers.count == 0
|
|
14
|
+
rescue => e
|
|
15
|
+
end
|
|
16
|
+
}
|
|
17
|
+
split_packages << build_package(fulfilled)
|
|
18
|
+
# Determine which supplier to package shipped items.
|
|
19
|
+
supplier_contents = package.contents.select { |content| content.variant.suppliers.count > 0 }
|
|
20
|
+
supplier_contents.each do |content|
|
|
21
|
+
# Select the related variant
|
|
22
|
+
variant = content.variant
|
|
23
|
+
# Select suppliers ordering ascending according to cost.
|
|
24
|
+
suppliers = variant.supplier_variants.order("spree_supplier_variants.cost ASC").map(&:supplier)
|
|
25
|
+
# Select first supplier that has stock location with avialable stock item.
|
|
26
|
+
available_supplier = suppliers.detect do |supplier|
|
|
27
|
+
supplier.stock_locations_with_available_stock_items(variant).any?
|
|
28
|
+
end
|
|
29
|
+
# Select the first available stock location with in the available_supplier stock locations.
|
|
30
|
+
stock_location = available_supplier.stock_locations_with_available_stock_items(variant).first
|
|
31
|
+
# Add to any existing packages or create a new one.
|
|
32
|
+
if existing_package = split_packages.detect { |p| p.stock_location == stock_location }
|
|
33
|
+
existing_package.contents << content
|
|
34
|
+
else
|
|
35
|
+
split_packages << Spree::Stock::Package.new(stock_location, [content])
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
rescue => e
|
|
40
|
+
end
|
|
41
|
+
return_next split_packages
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
Spree::StockLocation.class_eval do
|
|
2
|
+
|
|
3
|
+
belongs_to :supplier, class_name: 'Spree::Supplier'
|
|
4
|
+
|
|
5
|
+
scope :by_supplier, -> (supplier_id) { where(supplier_id: supplier_id) }
|
|
6
|
+
|
|
7
|
+
# Wrapper for creating a new stock item respecting the backorderable config and supplier
|
|
8
|
+
durably_decorate :propagate_variant, mode: 'soft', sha: '68fd322da48facbdbf567a2391c2495d04c3c8bc' do |variant|
|
|
9
|
+
if self.supplier_id.blank? || variant.suppliers.pluck(:id).include?(self.supplier_id)
|
|
10
|
+
self.stock_items.create!(variant: variant, backorderable: self.backorderable_default)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def unpropagate_variant(variant)
|
|
15
|
+
stock_items = self.stock_items.where(variant: variant)
|
|
16
|
+
stock_items.map(&:destroy)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def available?(variant)
|
|
20
|
+
stock_item(variant).try(:available?)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
class Spree::Supplier < Spree::Base
|
|
2
|
+
extend FriendlyId
|
|
3
|
+
# include ActiveModel::ForbiddenAttributesProtection
|
|
4
|
+
friendly_id :name, use: :slugged
|
|
5
|
+
|
|
6
|
+
attr_accessor :password, :password_confirmation
|
|
7
|
+
|
|
8
|
+
#==========================================
|
|
9
|
+
# Associations
|
|
10
|
+
|
|
11
|
+
belongs_to :address, class_name: 'Spree::Address'
|
|
12
|
+
accepts_nested_attributes_for :address
|
|
13
|
+
|
|
14
|
+
if defined?(Ckeditor::Asset)
|
|
15
|
+
has_many :ckeditor_pictures
|
|
16
|
+
has_many :ckeditor_attachment_files
|
|
17
|
+
end
|
|
18
|
+
has_many :supplier_variants
|
|
19
|
+
has_many :variants, through: :supplier_variants
|
|
20
|
+
has_many :products, through: :variants
|
|
21
|
+
|
|
22
|
+
has_many :stock_locations
|
|
23
|
+
has_many :shipments, through: :stock_locations
|
|
24
|
+
|
|
25
|
+
has_many :users, class_name: Spree.user_class.to_s
|
|
26
|
+
|
|
27
|
+
#==========================================
|
|
28
|
+
# Validations
|
|
29
|
+
|
|
30
|
+
validates :commission_flat_rate, presence: true
|
|
31
|
+
validates :commission_percentage, presence: true
|
|
32
|
+
validates :email, presence: true, email: true, uniqueness: true
|
|
33
|
+
validates :name, presence: true, uniqueness: true
|
|
34
|
+
validates :url, format: { with: URI::regexp(%w(http https)), allow_blank: true }
|
|
35
|
+
|
|
36
|
+
#==========================================
|
|
37
|
+
# Callbacks
|
|
38
|
+
|
|
39
|
+
after_create :assign_user
|
|
40
|
+
after_create :create_stock_location
|
|
41
|
+
after_create :send_welcome, if: -> { SolidusMarketplace::Config[:send_supplier_email] }
|
|
42
|
+
before_create :set_commission
|
|
43
|
+
before_validation :check_url
|
|
44
|
+
|
|
45
|
+
#==========================================
|
|
46
|
+
# Instance Methods
|
|
47
|
+
scope :active, -> { where(active: true) }
|
|
48
|
+
|
|
49
|
+
def deleted?
|
|
50
|
+
deleted_at.present?
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def user_ids_string
|
|
54
|
+
user_ids.join(',')
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def user_ids_string=(s)
|
|
58
|
+
self.user_ids = s.to_s.split(',').map(&:strip)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Retreive the stock locations that has available
|
|
62
|
+
# stock items of the given variant
|
|
63
|
+
def stock_locations_with_available_stock_items(variant)
|
|
64
|
+
stock_locations.select { |sl| sl.available?(variant) }
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
#==========================================
|
|
68
|
+
# Protected Methods
|
|
69
|
+
|
|
70
|
+
protected
|
|
71
|
+
|
|
72
|
+
def assign_user
|
|
73
|
+
if self.users.empty?
|
|
74
|
+
if user = Spree.user_class.find_by_email(self.email)
|
|
75
|
+
self.users << user
|
|
76
|
+
self.save
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def check_url
|
|
82
|
+
unless self.url.blank? or self.url =~ URI::regexp(%w(http https))
|
|
83
|
+
self.url = "http://#{self.url}"
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def create_stock_location
|
|
88
|
+
if self.stock_locations.empty?
|
|
89
|
+
location = self.stock_locations.build(
|
|
90
|
+
active: true,
|
|
91
|
+
country_id: self.address.try(:country_id),
|
|
92
|
+
name: self.name,
|
|
93
|
+
state_id: self.address.try(:state_id)
|
|
94
|
+
)
|
|
95
|
+
# It's important location is always created. Some apps add validations that shouldn't break this.
|
|
96
|
+
location.save validate: false
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def send_welcome
|
|
101
|
+
begin
|
|
102
|
+
Spree::SupplierMailer.welcome(self.id).deliver_later!
|
|
103
|
+
# Specs raise error for not being able to set default_url_options[:host]
|
|
104
|
+
rescue => ex #Errno::ECONNREFUSED => ex
|
|
105
|
+
Rails.logger.error ex.message
|
|
106
|
+
Rails.logger.error ex.backtrace.join("\n")
|
|
107
|
+
return true # always return true so that failed email doesn't crash app.
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def set_commission
|
|
112
|
+
unless changes.has_key?(:commission_flat_rate)
|
|
113
|
+
self.commission_flat_rate = SolidusMarketplace::Config[:default_commission_flat_rate]
|
|
114
|
+
end
|
|
115
|
+
unless changes.has_key?(:commission_percentage)
|
|
116
|
+
self.commission_percentage = SolidusMarketplace::Config[:default_commission_percentage]
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
class SupplierAbility
|
|
3
|
+
include CanCan::Ability
|
|
4
|
+
|
|
5
|
+
def initialize(user)
|
|
6
|
+
user ||= Spree.user_class.new
|
|
7
|
+
|
|
8
|
+
if user.supplier_admin?
|
|
9
|
+
can [:admin, :update, :read, :display, :stock], Spree::Product, suppliers: { id: user.supplier_id }
|
|
10
|
+
can [:admin, :create], Spree::Product
|
|
11
|
+
can [:admin, :create, :update, :destroy, :display], Spree::Variant, suppliers: { id: user.supplier_id }
|
|
12
|
+
|
|
13
|
+
can [:admin, :display, :index], Spree::Shipment, order: { state: 'complete' },
|
|
14
|
+
stock_location: { supplier_id: user.supplier_id }
|
|
15
|
+
|
|
16
|
+
can [:admin, :display], Spree::ReturnAuthorization, stock_location: { supplier_id: user.supplier_id }
|
|
17
|
+
can [:admin, :display], Spree::CustomerReturn, stock_location: { supplier_id: user.supplier_id }
|
|
18
|
+
|
|
19
|
+
#FIXME: come back to these when we work on shipping-related issues
|
|
20
|
+
# can [:admin, :manage, :read, :ready, :ship], Spree::Shipment, order: { state: 'complete' }, stock_location: { supplier_id: user.supplier_id }
|
|
21
|
+
# can [:admin, :create, :update], :stock_items
|
|
22
|
+
can [:admin, :index, :create, :edit, :read, :update], Spree::StockItem, stock_location: { supplier_id: user.supplier_id }
|
|
23
|
+
can [:admin, :manage, :create], Spree::StockLocation, supplier_id: user.supplier_id
|
|
24
|
+
can [:admin, :manage, :create], Spree::StockMovement, stock_item: { stock_location: { supplier_id: user.supplier_id } }
|
|
25
|
+
|
|
26
|
+
can [:admin, :create, :read, :update, :display], Spree::Supplier, id: user.supplier_id
|
|
27
|
+
cannot [:create], Spree::Supplier
|
|
28
|
+
|
|
29
|
+
can [:admin, :manage], Spree::User, supplier_id: user.supplier_id
|
|
30
|
+
can [:admin, :index, :edit], Spree::Order, stock_locations: { supplier_id: user.supplier_id }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
Spree.user_class.class_eval do
|
|
2
|
+
|
|
3
|
+
belongs_to :supplier, class_name: 'Spree::Supplier'
|
|
4
|
+
|
|
5
|
+
has_many :variants, through: :supplier
|
|
6
|
+
|
|
7
|
+
def supplier?
|
|
8
|
+
supplier.present?
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def supplier_admin?
|
|
12
|
+
spree_roles.map(&:name).include?("supplier_admin")
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def market_maker?
|
|
16
|
+
has_admin_role?
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def has_admin_role?
|
|
20
|
+
spree_roles.map(&:name).include?("admin")
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
Variant.class_eval do
|
|
3
|
+
|
|
4
|
+
has_many :supplier_variants
|
|
5
|
+
has_many :suppliers, through: :supplier_variants
|
|
6
|
+
|
|
7
|
+
before_create :populate_for_suppliers
|
|
8
|
+
|
|
9
|
+
private
|
|
10
|
+
|
|
11
|
+
durably_decorate :create_stock_items, mode: 'soft', sha: '98704433ac5c66ba46e02699f3cf03d13d4f1281' do
|
|
12
|
+
StockLocation.all.each do |stock_location|
|
|
13
|
+
if stock_location.supplier_id.blank? || self.suppliers.pluck(:id).include?(stock_location.supplier_id)
|
|
14
|
+
stock_location.propagate_variant(self) if stock_location.propagate_all_variants?
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def populate_for_suppliers
|
|
20
|
+
self.suppliers = self.product.suppliers
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
Deface::Override.new(
|
|
2
|
+
virtual_path: "spree/admin/shared/_menu",
|
|
3
|
+
name: "marketplace_menus",
|
|
4
|
+
insert_bottom: '[data-hook="admin_tabs"]',
|
|
5
|
+
partial: "spree/admin/shared/marketplace_tabs"
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
Deface::Override.new(
|
|
10
|
+
virtual_path: "spree/admin/shared/_configuration_menu",
|
|
11
|
+
name: "marketplace_admin_configurations_menu",
|
|
12
|
+
insert_bottom: "[data-hook='admin_configurations_sidebar_menu']",
|
|
13
|
+
disabled: false,
|
|
14
|
+
partial: "spree/admin/shared/marketplace_settings"
|
|
15
|
+
)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<!-- replace_contents '[data-hook="admin_products_index_rows"]' -->
|
|
2
|
+
|
|
3
|
+
<%# Changed classes to new like https://github.com/spree/spree/blob/master/backend/app/views/spree/admin/stock_locations/_form.html.erb %>
|
|
4
|
+
<td class="sku"><%= product.sku rescue '' %></td>
|
|
5
|
+
<td class="image"><%= mini_image product, class: "thumbnail" %></td>
|
|
6
|
+
<td>
|
|
7
|
+
<% if try_spree_current_user && try_spree_current_user.supplier? %>
|
|
8
|
+
<%= link_to product.try(:name), spree.admin_product_stock_path(product)%>
|
|
9
|
+
<% else %>
|
|
10
|
+
<%= link_to product.try(:name), edit_admin_product_path(product) %>
|
|
11
|
+
<% end %>
|
|
12
|
+
</td>
|
|
13
|
+
<td><%= product.display_price.to_html rescue '' %></td>
|
|
14
|
+
<td class="actions" data-hook="admin_products_index_row_actions">
|
|
15
|
+
<% if try_spree_current_user && try_spree_current_user.supplier? %>
|
|
16
|
+
<%= link_to 'Stock Management', spree.admin_product_stock_path(product), title:'Stock Management', class: 'btn btn-default btn-sm with-tip without-textdecor' if can?(:stock, product) && !product.deleted? %>
|
|
17
|
+
<% else %>
|
|
18
|
+
<%= link_to_edit product, :no_text => true, :class => 'edit' if can?(:edit, product) && !product.deleted? %>
|
|
19
|
+
<% end %>
|
|
20
|
+
<%= link_to_clone product, :no_text => true, :class => 'clone' if can?(:clone, product) %>
|
|
21
|
+
<%= link_to_delete product, :no_text => true if can?(:delete, product) && !product.deleted? %>
|
|
22
|
+
</td>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<!-- insert_after "[data-hook=admin_stock_locations_form_fields]" -->
|
|
2
|
+
|
|
3
|
+
<%# Remove extra div and change classes %>
|
|
4
|
+
<% if spree_current_user.admin? %>
|
|
5
|
+
<div class='form-group'>
|
|
6
|
+
<%= f.field_container :supplier do %>
|
|
7
|
+
<%= f.label :supplier_id, Spree.t(:supplier) %>
|
|
8
|
+
<%= f.collection_select(:supplier_id, Spree::Supplier.all, :id, :name, { :include_blank => 'None' }, { :class => 'select2' }) %>
|
|
9
|
+
<%= f.error_message_on :supplier %>
|
|
10
|
+
<% end %>
|
|
11
|
+
</div>
|
|
12
|
+
<% end %>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<% content_for :page_title do %>
|
|
2
|
+
<%= Spree.t("marketplace_settings") %>
|
|
3
|
+
<% end %>
|
|
4
|
+
|
|
5
|
+
<%= form_tag(spree.admin_marketplace_settings_path, :method => :put) do %>
|
|
6
|
+
<fieldset class="general no-border-top">
|
|
7
|
+
<% %w( default_commission_flat_rate default_commission_percentage automatically_deliver_orders_to_supplier send_supplier_email).each do |key|
|
|
8
|
+
type = SolidusMarketplace::Config.preference_type(key) %>
|
|
9
|
+
<div class="field col-md-6">
|
|
10
|
+
<%= label_tag(key, Spree.t(key) + ': ') + tag(:br) if type != :boolean %>
|
|
11
|
+
<%= preference_field_tag(key, SolidusMarketplace::Config[key], :type => type ,:class => 'form-control')%>
|
|
12
|
+
<%= label_tag(key, Spree.t(key)) + tag(:br) if type == :boolean %>
|
|
13
|
+
</div>
|
|
14
|
+
<% end %>
|
|
15
|
+
<div class="form-buttons" data-hook="buttons">
|
|
16
|
+
<%= button Spree.t(:update), 'update' %>
|
|
17
|
+
<span class="or"><%= Spree.t(:or) %></span>
|
|
18
|
+
<%= button_link_to Spree.t(:cancel), spree.edit_admin_marketplace_settings_url, :icon => 'cancel' %>
|
|
19
|
+
</div>
|
|
20
|
+
</fieldset>
|
|
21
|
+
<% end %>
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
<% admin_layout "full-width" %>
|
|
2
|
+
|
|
3
|
+
<% admin_breadcrumb(plural_resource_name(Spree::Order)) %>
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
<% content_for :page_actions do %>
|
|
7
|
+
<li>
|
|
8
|
+
<%= button_link_to Spree.t(:new_order), new_admin_order_url, id: 'admin_new_order' %>
|
|
9
|
+
</li>
|
|
10
|
+
<% end if can? :create, Spree::Order %>
|
|
11
|
+
|
|
12
|
+
<% content_for :table_filter_title do %>
|
|
13
|
+
<%= Spree.t(:search) %>
|
|
14
|
+
<% end %>
|
|
15
|
+
|
|
16
|
+
<% content_for :table_filter do %>
|
|
17
|
+
<div data-hook="admin_orders_index_search">
|
|
18
|
+
<%= search_form_for [:admin, @search] do |f| %>
|
|
19
|
+
<div class="row">
|
|
20
|
+
<div class="field-block col-12 col-md-6 col-lg-4 col-xl-3">
|
|
21
|
+
<div class="date-range-filter field">
|
|
22
|
+
<%= label_tag :q_created_at_gt, Spree.t(:date_range) %>
|
|
23
|
+
<div class="date-range-fields input-group">
|
|
24
|
+
<%= f.text_field :created_at_gt, class: 'datepicker form-control datepicker-from', value: params[:q][:created_at_gt], placeholder: Spree.t(:start) %>
|
|
25
|
+
|
|
26
|
+
<span class="range-divider input-group-addon">
|
|
27
|
+
<i class="fa fa-arrow-right"></i>
|
|
28
|
+
</span>
|
|
29
|
+
|
|
30
|
+
<%= f.text_field :created_at_lt, class: 'datepicker form-control datepicker-to', value: params[:q][:created_at_lt], placeholder: Spree.t(:stop) %>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<div class="field">
|
|
35
|
+
<%= label_tag :q_state_eq, Spree.t(:status) %>
|
|
36
|
+
<%= f.select :state_eq, Spree::Order.state_machines[:state].states.collect {|s| [Spree.t("order_state.#{s.name}"), s.value]}, {include_blank: true}, class: 'custom-select fullwidth' %>
|
|
37
|
+
</div>
|
|
38
|
+
|
|
39
|
+
<div class="field">
|
|
40
|
+
<%= label_tag nil, Spree.t(:promotion) %>
|
|
41
|
+
<%= f.text_field :order_promotions_promotion_code_value_cont, size: 25 %>
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
<div class="field">
|
|
45
|
+
<%= label_tag nil, Spree.t(:shipment_number) %>
|
|
46
|
+
<%= f.text_field :shipments_number_cont %>
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
<div class="col-12 col-md-6 col-lg-4 col-xl-6">
|
|
52
|
+
<div class="row">
|
|
53
|
+
<div class="col-12 col-xl-6">
|
|
54
|
+
<div class="field">
|
|
55
|
+
<%= label_tag :q_number_cont, Spree.t(:order_number, number: '') %>
|
|
56
|
+
<%= f.text_field :number_cont %>
|
|
57
|
+
</div>
|
|
58
|
+
|
|
59
|
+
<div class="field">
|
|
60
|
+
<%= label_tag :q_email_cont, Spree.t(:email) %>
|
|
61
|
+
<%= f.text_field :email_cont %>
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
<div class="col-12 col-xl-6">
|
|
66
|
+
<div class="field">
|
|
67
|
+
<%= label_tag :q_bill_address_firstname_start, Spree.t(:first_name_begins_with) %>
|
|
68
|
+
<%= f.text_field :bill_address_firstname_start, size: 25 %>
|
|
69
|
+
</div>
|
|
70
|
+
<div class="field">
|
|
71
|
+
<%= label_tag :q_bill_address_lastname_start, Spree.t(:last_name_begins_with) %>
|
|
72
|
+
<%= f.text_field :bill_address_lastname_start, size: 25%>
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
<div class="col-12 col-xl-6">
|
|
77
|
+
<div class="field" data-hook="sku-select">
|
|
78
|
+
<%= label_tag :q_line_items_variant_id_in, Spree.t(:variant) %>
|
|
79
|
+
<%= f.text_field :line_items_variant_id_in, class: "variant_autocomplete fullwidth" %>
|
|
80
|
+
</div>
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
|
|
85
|
+
<div class="col-12 col-md-6 col-lg-4 col-xl-3">
|
|
86
|
+
<% if Spree::Store.count > 1 %>
|
|
87
|
+
<div class="field">
|
|
88
|
+
<%= label_tag :q_store_id_eq, Spree.t(:store) %>
|
|
89
|
+
<%= f.select :store_id_eq, Spree::Store.all.map { |s| [s.name, s.id] }, { include_blank: true }, { class: "custom-select fullwidth" } %>
|
|
90
|
+
</div>
|
|
91
|
+
<% end %>
|
|
92
|
+
|
|
93
|
+
<div class="field checkbox">
|
|
94
|
+
<label>
|
|
95
|
+
<%= f.check_box :completed_at_not_null, {checked: @show_only_completed}, '1', '0' %>
|
|
96
|
+
<%= Spree.t(:show_only_complete_orders) %>
|
|
97
|
+
</label>
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
100
|
+
|
|
101
|
+
</div>
|
|
102
|
+
|
|
103
|
+
<div class="clearfix"></div>
|
|
104
|
+
|
|
105
|
+
<div class="actions filter-actions">
|
|
106
|
+
<div data-hook="admin_orders_index_search_buttons">
|
|
107
|
+
<%= button Spree.t(:filter_results) %>
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
<% end %>
|
|
111
|
+
</div>
|
|
112
|
+
<% end %>
|
|
113
|
+
|
|
114
|
+
<%= paginate @orders, theme: "solidus_admin" %>
|
|
115
|
+
|
|
116
|
+
<% if @orders.any? %>
|
|
117
|
+
<table class="index" id="listing_orders" data-hook>
|
|
118
|
+
<colgroup>
|
|
119
|
+
<col style="width: 13%;">
|
|
120
|
+
<col style="width: 10%;">
|
|
121
|
+
<col style="width: 10%;">
|
|
122
|
+
<col style="width: 12%;">
|
|
123
|
+
<% if Spree::Order.checkout_step_names.include?(:delivery) %>
|
|
124
|
+
<col style="width: 12%;">
|
|
125
|
+
<% end %>
|
|
126
|
+
<col style="width: 25%;">
|
|
127
|
+
<col style="width: 10%;">
|
|
128
|
+
<col style="width: 8%;">
|
|
129
|
+
</colgroup>
|
|
130
|
+
<thead>
|
|
131
|
+
<tr data-hook="admin_orders_index_headers">
|
|
132
|
+
<% if @show_only_completed %>
|
|
133
|
+
<th><%= sort_link @search, :completed_at %></th>
|
|
134
|
+
<% else %>
|
|
135
|
+
<th><%= sort_link @search, :created_at %></th>
|
|
136
|
+
<% end %>
|
|
137
|
+
<th><%= sort_link @search, :number %></th>
|
|
138
|
+
<th><%= sort_link @search, :state %></th>
|
|
139
|
+
<th><%= sort_link @search, :payment_state %></th>
|
|
140
|
+
<% if Spree::Order.checkout_step_names.include?(:delivery) %>
|
|
141
|
+
<th><%= sort_link @search, :shipment_state %></th>
|
|
142
|
+
<% end %>
|
|
143
|
+
<th><%= sort_link @search, :email %></th>
|
|
144
|
+
<th><%= sort_link @search, :total %></th>
|
|
145
|
+
<th data-hook="admin_orders_index_header_actions" class="actions"></th>
|
|
146
|
+
</tr>
|
|
147
|
+
</thead>
|
|
148
|
+
<tbody>
|
|
149
|
+
<% @orders.each do |order| %>
|
|
150
|
+
<tr data-hook="admin_orders_index_rows" class="state-<%= order.state.downcase %> <%= cycle('odd', 'even') %>">
|
|
151
|
+
<td class="align-center"><%= l (@show_only_completed ? order.completed_at : order.created_at).to_date %></td>
|
|
152
|
+
<td class="align-center"><%= link_to order.number, edit_admin_order_path(order) %></td>
|
|
153
|
+
<td class="align-center"><span class="state <%= order.state.downcase %>"><%= Spree.t("order_state.#{order.state.downcase}") %></span></td>
|
|
154
|
+
<td class="align-center"><span class="state <%= order.payment_state %>"><%= link_to Spree.t("payment_states.#{order.payment_state}"), admin_order_payments_path(order) if order.payment_state %></span></td>
|
|
155
|
+
<% if Spree::Order.checkout_step_names.include?(:delivery) %>
|
|
156
|
+
<td class="align-center"><span class="state <%= order.shipment_state %>"><%= Spree.t("shipment_states.#{order.shipment_state}") if order.shipment_state %></span></td>
|
|
157
|
+
<% end %>
|
|
158
|
+
<td>
|
|
159
|
+
<% if order.user %>
|
|
160
|
+
<%= link_to order.email, edit_admin_user_path(order.user) %>
|
|
161
|
+
<% else %>
|
|
162
|
+
<%= mail_to order.email %>
|
|
163
|
+
<% end %>
|
|
164
|
+
</td>
|
|
165
|
+
<td class="align-center">
|
|
166
|
+
<% if try_spree_current_user.supplier? %>
|
|
167
|
+
<%= order.supplier_total(try_spree_current_user).to_html %>
|
|
168
|
+
<% else %>
|
|
169
|
+
<%= order.display_total.to_html %>
|
|
170
|
+
<% end %>
|
|
171
|
+
</td>
|
|
172
|
+
<td class='actions align-center' data-hook="admin_orders_index_row_actions">
|
|
173
|
+
<%= link_to_edit_url edit_admin_order_path(order), title: "admin_edit_#{dom_id(order)}", no_text: true %>
|
|
174
|
+
</td>
|
|
175
|
+
</tr>
|
|
176
|
+
<% end %>
|
|
177
|
+
</tbody>
|
|
178
|
+
</table>
|
|
179
|
+
<% else %>
|
|
180
|
+
<div class="col-9 no-objects-found">
|
|
181
|
+
<%= render 'spree/admin/shared/no_objects_found',
|
|
182
|
+
resource: Spree::Order,
|
|
183
|
+
new_resource_url: spree.new_admin_order_path %>
|
|
184
|
+
</div>
|
|
185
|
+
<% end %>
|
|
186
|
+
|
|
187
|
+
<%= paginate @orders, theme: "solidus_admin" %>
|