spree_drop_ship 3.1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/Gemfile +9 -0
  4. data/LICENSE +21 -0
  5. data/README.md +116 -0
  6. data/Rakefile +15 -0
  7. data/Versionfile +6 -0
  8. data/app/assets/javascripts/spree/backend/spree_drop_ship.js +2 -0
  9. data/app/assets/javascripts/spree/frontend/spree_drop_ship.js +1 -0
  10. data/app/assets/stylesheets/spree/backend/spree_drop_ship.scss +22 -0
  11. data/app/assets/stylesheets/spree/frontend/spree_drop_ship.css +3 -0
  12. data/app/controllers/ckeditor/attachment_files_controller_decorator.rb +20 -0
  13. data/app/controllers/ckeditor/pictures_controller_decorator.rb +17 -0
  14. data/app/controllers/spree/admin/drop_ship_settings_controller.rb +19 -0
  15. data/app/controllers/spree/admin/products_controller_decorator.rb +19 -0
  16. data/app/controllers/spree/admin/shipments_controller.rb +47 -0
  17. data/app/controllers/spree/admin/stock_locations_controller_decorator.rb +14 -0
  18. data/app/controllers/spree/admin/suppliers_controller.rb +32 -0
  19. data/app/controllers/spree/api/v1/stock_locations_controller_decorator.rb +18 -0
  20. data/app/controllers/spree/base_controller_decorator.rb +23 -0
  21. data/app/mailers/spree/drop_ship_order_mailer.rb +13 -0
  22. data/app/mailers/spree/supplier_mailer.rb +12 -0
  23. data/app/models/ckeditor/asset_decorator.rb +5 -0
  24. data/app/models/spree/drop_ship_configuration.rb +17 -0
  25. data/app/models/spree/order_decorator.rb +27 -0
  26. data/app/models/spree/payment_decorator.rb +7 -0
  27. data/app/models/spree/product_decorator.rb +32 -0
  28. data/app/models/spree/shipment_decorator.rb +39 -0
  29. data/app/models/spree/stock/splitter/drop_ship.rb +42 -0
  30. data/app/models/spree/stock_location_decorator.rb +18 -0
  31. data/app/models/spree/supplier.rb +117 -0
  32. data/app/models/spree/supplier_ability.rb +28 -0
  33. data/app/models/spree/supplier_variant.rb +6 -0
  34. data/app/models/spree/user_decorator.rb +11 -0
  35. data/app/models/spree/variant_decorator.rb +24 -0
  36. data/app/models/spree.rb +5 -0
  37. data/app/overrides/spree/admin/products/_form/converted_admin_product_form_right.html.erb.deface +5 -0
  38. data/app/overrides/spree/admin/products/index/override_rows.html.erb.deface +22 -0
  39. data/app/overrides/spree/admin/shared/sub_menu/_configuration/add_drop_ship_settings.html.erb.deface +3 -0
  40. data/app/overrides/spree/admin/stock_locations/_form/add_supplier.html.erb.deface +12 -0
  41. data/app/overrides/spree/admin/stock_movements/_form/fix_bootstrap_form.html.erb.deface +11 -0
  42. data/app/overrides/spree/layouts/admin/add_profile_admin_tabs.html.erb.deface +8 -0
  43. data/app/overrides/spree/layouts/admin/converted_admin_tabs.html.erb.deface +18 -0
  44. data/app/views/spree/admin/drop_ship_settings/edit.html.erb +21 -0
  45. data/app/views/spree/admin/shared/_header.html.erb +24 -0
  46. data/app/views/spree/admin/shipments/edit.html.erb +24 -0
  47. data/app/views/spree/admin/shipments/index.html.erb +95 -0
  48. data/app/views/spree/admin/suppliers/_form.html.erb +69 -0
  49. data/app/views/spree/admin/suppliers/edit.html.erb +22 -0
  50. data/app/views/spree/admin/suppliers/index.html.erb +71 -0
  51. data/app/views/spree/admin/suppliers/new.html.erb +17 -0
  52. data/app/views/spree/drop_ship_order_mailer/supplier_order.html.erb +119 -0
  53. data/app/views/spree/shared/unauthorized.erb +1 -0
  54. data/app/views/spree/supplier_mailer/welcome.html.erb +53 -0
  55. data/config/locales/en.yml +89 -0
  56. data/config/locales/es.yml +133 -0
  57. data/config/routes.rb +9 -0
  58. data/db/migrate/20121006073854_create_suppliers.rb +20 -0
  59. data/db/migrate/20130216070944_product_belongs_to_supplier.rb +6 -0
  60. data/db/migrate/20130405005502_stock_locations_belongs_to_supplier.rb +6 -0
  61. data/db/migrate/20130405011127_user_belongs_to_supplier.rb +6 -0
  62. data/db/migrate/20130428063053_add_balanced_token_to_suppliers.rb +7 -0
  63. data/db/migrate/20130510181443_add_supplier_id_to_ckeditor_assets.rb +8 -0
  64. data/db/migrate/20130606220913_add_permalink_to_suppliers.rb +6 -0
  65. data/db/migrate/20140323170638_add_supplier_commission_to_shipments.rb +5 -0
  66. data/db/migrate/20140416184616_migrate_payment_and_commission.rb +7 -0
  67. data/db/migrate/20140529041325_create_spree_supplier_variants.rb +15 -0
  68. data/lib/generators/spree_drop_ship/install/install_generator.rb +30 -0
  69. data/lib/spree_drop_ship/engine.rb +31 -0
  70. data/lib/spree_drop_ship/factories.rb +93 -0
  71. data/lib/spree_drop_ship.rb +6 -0
  72. data/lib/tasks/spree_sample.rake +72 -0
  73. data/script/rails +7 -0
  74. data/spec/features/admin/orders_spec.rb +12 -0
  75. data/spec/features/admin/products_spec.rb +25 -0
  76. data/spec/features/admin/return_authorizations_spec.rb +7 -0
  77. data/spec/features/admin/settings_spec.rb +33 -0
  78. data/spec/features/admin/shipments_spec.rb +80 -0
  79. data/spec/features/admin/stock_management_spec.rb +153 -0
  80. data/spec/features/admin/stock_spec.rb +98 -0
  81. data/spec/features/admin/suppliers_spec.rb +126 -0
  82. data/spec/models/spree/order_decorator_spec.rb +54 -0
  83. data/spec/models/spree/payment_decorator_spec.rb +7 -0
  84. data/spec/models/spree/product_decorator_spec.rb +13 -0
  85. data/spec/models/spree/shipment_decorator_spec.rb +47 -0
  86. data/spec/models/spree/stock/splitter/drop_ship_spec.rb +62 -0
  87. data/spec/models/spree/stock_location_decorator_spec.rb +33 -0
  88. data/spec/models/spree/supplier_ability_spec.rb +172 -0
  89. data/spec/models/spree/supplier_spec.rb +123 -0
  90. data/spec/models/spree/supplier_variant_spec.rb +5 -0
  91. data/spec/models/spree/user_decorator_spec.rb +17 -0
  92. data/spec/models/spree/variant_decorator_spec.rb +7 -0
  93. data/spec/spec_helper.rb +79 -0
  94. data/spec/support/integration_helpers.rb +15 -0
  95. data/spree_drop_ship.gemspec +42 -0
  96. metadata +411 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b8ec93dffafe0fa3317797b375deb1a2ac1de64e
4
+ data.tar.gz: 5550de66c5fcaf3adc6994e9892ebf554b70c705
5
+ SHA512:
6
+ metadata.gz: 22e0e8ff176b4c628b1db7ea4f92eb7af1425af8bde1548395c0ca16b797cebe52c808ed027ea5c265927bfd3234bb4de3bf75a7e321af4e695994e17cd1a7e2
7
+ data.tar.gz: 882264fb878a354f141fe3e78eca54e1e3300b2d560cc46d65952bd8adbfea993a6109a58d3614dbdc6525b5422db90842adcf2c2173205c0449e5897f08b659
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ \#*
2
+ *~
3
+ .#*
4
+ .bundle
5
+ .DS_Store
6
+ .idea
7
+ .project
8
+ .ruby-gemset
9
+ .ruby-version
10
+ .sass-cache
11
+ coverage
12
+ Gemfile.lock
13
+ tmp
14
+ nbproject
15
+ pkg
16
+ *.swp
17
+ spec/dummy
18
+ spec/vcr_cassettes
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ group :development, :test do
4
+ spree_branch = 'master'
5
+ gem 'spree', github: 'spree/spree', branch: spree_branch
6
+ gem 'spree_auth_devise', github: 'spree/spree_auth_devise', branch: spree_branch
7
+ end
8
+
9
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2016 Yad Faeq
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,116 @@
1
+ # Spree Drop Ship
2
+
3
+
4
+ * Notice: This [gem](https://github.com/spree-contrib/spree_drop_ship)'s skeleton was on Spree Contrib, and then I forked [this](https://github.com/mattfran/spree_drop_ship/tree/master). Credits to their work, though both were broken and left behind. This is a new version with few changes.
5
+
6
+ * current state :
7
+
8
+ 1. fixed the original issue #73 Ransack related `state_eq`
9
+ 2. Version Spree `3.1.0`
10
+ 3. also some smaller errors from the gem.
11
+
12
+
13
+
14
+
15
+ What is drop shipping?
16
+
17
+ "Drop shipping is a supply chain management technique in which the retailer does not keep goods in stock, but instead transfers customer orders
18
+ and shipment details to either the manufacturer or a wholesaler, who then ships the goods directly to the customer." - [wikipedia](http://en.wikipedia.org/wiki/Drop_shipping)
19
+
20
+ So the main goal with spree_drop_ship is to link products to suppliers and forward orders to the appropriate suppliers.
21
+
22
+ Once an order is placed for a product that belongs to a supplier a shipment is created for the product's supplier.
23
+ This shipment is then sent to the supplier (via Email by default). The supplier then follows a link to the shipment
24
+ within the email where they are prompted to confirm the shipment.
25
+
26
+ Spree Drop Ship used with [Spree Marketplace](https://github.com/jdutil/spree_marketplace) allows handling payments to your suppliers via ACH direct deposits.
27
+ This is still currently a work in progress, and any input is welcome.
28
+ .
29
+
30
+
31
+ Installation
32
+ ------------
33
+
34
+ Here's how to install spree_drop_ship into your existing spree site AFTER you've installed Spree:
35
+
36
+ Add the following to your Gemfile:
37
+
38
+ gem 'spree_drop_ship', github: '0bserver07/spree_drop_ship'
39
+
40
+ Make your bundle happy:
41
+
42
+ bundle install
43
+
44
+ Now run the generator:
45
+
46
+ rails g spree_drop_ship:install
47
+
48
+ Then migrate your database if you did not run during installation generator:
49
+
50
+ bundle exec rake db:migrate
51
+
52
+ And reboot your server:
53
+
54
+ rails s
55
+
56
+ You should be up and running now!
57
+
58
+ Sample Data
59
+ -----------
60
+
61
+ If you'd like to generate sample data, use the included rake tasks:
62
+
63
+ ```shell
64
+ rake spree_sample:load # Loads sample data into the store
65
+ rake spree_sample:suppliers # Create sample suppliers and randomly link to products
66
+ rake spree_sample:drop_ship_orders # Create sample drop ship orders
67
+ ```
68
+
69
+ Demo
70
+ ----
71
+
72
+ You can easily use the spec/dummy app as a demo of spree_drop_ship. Just `cd` to where you develop and run:
73
+
74
+ ```shell
75
+ git clone git://github.com/spree-contrib/spree_drop_ship.git
76
+ cd spree_drop_ship
77
+ bundle install
78
+ bundle exec rake test_app
79
+ cd spec/dummy
80
+ rake db:migrate db:seed spree_sample:load spree_sample:suppliers spree_sample:drop_ship_orders
81
+ rails s
82
+ ```
83
+
84
+ Testing
85
+ -------
86
+
87
+ * Needs To be updated
88
+
89
+ Todo
90
+ ----
91
+
92
+ - Stock Items should automatically be set to backorderable false if the variant doesnt belong to the stock locations supplier.
93
+ - Must allow suppliers to edit their stock location addresses & require it.
94
+ - Return Authorization UI
95
+ - Better documentation
96
+ - related products should only allow suppliers own products to be related
97
+
98
+ Contributing
99
+ ------------
100
+
101
+ In the spirit of [free software](http://www.fsf.org/licensing/essays/free-sw.html), **everyone** is encouraged to help improve this project.
102
+
103
+ Here are some ways *you* can contribute:
104
+
105
+ * by using prerelease versions
106
+ * by reporting [bugs](https://github.com/spree-contrib/spree_drop_ship/issues)
107
+ * by suggesting new features
108
+ * by [translating to a new language](https://github.com/spree-contrib/spree_drop_ship/tree/master/config/locales)
109
+ * by writing or editing documentation
110
+ * by writing specifications
111
+ * by writing code (*no patch is too small*: fix typos, add comments, clean up inconsistent whitespace)
112
+ * by refactoring code
113
+ * by resolving [issues](https://github.com/spree-contrib/spree_drop_ship/issues)
114
+ * by reviewing patches
115
+
116
+
data/Rakefile ADDED
@@ -0,0 +1,15 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ require 'spree/testing_support/common_rake'
6
+
7
+ RSpec::Core::RakeTask.new
8
+
9
+ task :default => [:spec]
10
+
11
+ desc 'Generates a dummy app for testing'
12
+ task :test_app do
13
+ ENV['LIB_NAME'] = 'spree_drop_ship'
14
+ Rake::Task['common:test_app'].invoke 'Spree::User'
15
+ end
data/Versionfile ADDED
@@ -0,0 +1,6 @@
1
+ # This file is used to designate compatibilty with different versions of Spree
2
+ # Please see http://spreecommerce.com/documentation/extensions.html#versionfile for details
3
+ # '1.3.x' => { :ref => 'e5624f7' } # Not going to be maintained but most of the works there if your looking for a starting point to branch off of.
4
+
5
+ '2.4.x' => { :branch => 'master' }
6
+ '2.3.x' => { :branch => '2-3-stable' }
@@ -0,0 +1,2 @@
1
+ //= require spree/backend
2
+ // Shipments AJAX API
@@ -0,0 +1 @@
1
+ //= require spree/frontend
@@ -0,0 +1,22 @@
1
+ /*
2
+ *= require spree/backend
3
+ */
4
+
5
+ .center {
6
+ text-align: center;
7
+ }
8
+
9
+ .state.delivered:before,
10
+ .state.confirmed:before {
11
+ background-color: #ff9300;
12
+ }
13
+
14
+ .supplier-banks ol li {
15
+ margin-left: 20px;
16
+ margin-bottom: 5px;
17
+ text-align: left;
18
+ }
19
+
20
+ a .without-textdecor{
21
+ text-decoration: none;
22
+ }
@@ -0,0 +1,3 @@
1
+ /*
2
+ *= require spree/frontend
3
+ */
@@ -0,0 +1,20 @@
1
+ if defined?(Ckeditor::AttachmentFilesController)
2
+ Ckeditor::AttachmentFilesController.class_eval do
3
+
4
+ load_and_authorize_resource :class => 'Ckeditor::AttachmentFile'
5
+ after_filter :set_supplier, only: [:create]
6
+
7
+ def index
8
+ end
9
+
10
+ private
11
+
12
+ def set_supplier
13
+ if try_spree_current_user.supplier? and @attachment
14
+ @attachment.supplier = try_spree_current_user.supplier
15
+ @attachment.save
16
+ end
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,17 @@
1
+ if defined?(Ckeditor::PicturesController)
2
+ Ckeditor::PicturesController.class_eval do
3
+ load_and_authorize_resource :class => 'Ckeditor::Picture'
4
+ after_filter :set_supplier, only: [:create]
5
+
6
+ def index
7
+ end
8
+
9
+ private
10
+ def set_supplier
11
+ if spree_current_user.supplier? and @picture
12
+ @picture.supplier = spree_current_user.supplier
13
+ @picture.save
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,19 @@
1
+ class Spree::Admin::DropShipSettingsController < Spree::Admin::BaseController
2
+
3
+ def edit
4
+ @config = Spree::DropShipConfiguration.new
5
+ end
6
+
7
+ def update
8
+ config = Spree::DropShipConfiguration.new
9
+
10
+ params.each do |name, value|
11
+ next unless config.has_preference? name
12
+ config[name] = value
13
+ end
14
+
15
+ flash[:success] = Spree.t('admin.drop_ship_settings.update.success')
16
+ redirect_to spree.edit_admin_drop_ship_settings_path
17
+ end
18
+
19
+ end
@@ -0,0 +1,19 @@
1
+ Spree::Admin::ProductsController.class_eval do
2
+
3
+ before_filter :get_suppliers, only: [:edit, :update]
4
+ before_filter :supplier_collection, only: [:index]
5
+
6
+ private
7
+
8
+ def get_suppliers
9
+ @suppliers = Spree::Supplier.order(:name)
10
+ end
11
+
12
+ # Scopes the collection to the Supplier.
13
+ def supplier_collection
14
+ if try_spree_current_user && !try_spree_current_user.admin? && try_spree_current_user.supplier?
15
+ @collection = @collection.joins(:suppliers).where('spree_suppliers.id = ?', try_spree_current_user.supplier_id)
16
+ end
17
+ end
18
+
19
+ end
@@ -0,0 +1,47 @@
1
+ module Spree
2
+ module Admin
3
+ class ShipmentsController < Spree::Admin::ResourceController
4
+
5
+ def index
6
+ params[:q] ||= {}
7
+ # params[:q][:completed_at_null] ||= '1'
8
+ # @show_only_incomplete = params[:q][:completed_at_null].present?
9
+ # params[:q][:s] ||= @show_only_incomplete ? 'created_at desc' : 'completed_at desc'
10
+
11
+ # As date params are deleted if @show_only_incomplete, store
12
+ # the original date so we can restore them into the params
13
+ # after the search
14
+ created_at_gt = params[:q][:created_at_gt]
15
+ created_at_lt = params[:q][:created_at_lt]
16
+
17
+ if !params[:q][:created_at_gt].blank?
18
+ params[:q][:created_at_gt] = Time.zone.parse(params[:q][:created_at_gt]).beginning_of_day rescue ""
19
+ end
20
+
21
+ if !params[:q][:created_at_lt].blank?
22
+ params[:q][:created_at_lt] = Time.zone.parse(params[:q][:created_at_lt]).end_of_day rescue ""
23
+ end
24
+
25
+ @search = Spree::Shipment.accessible_by(current_ability, :index).ransack(params[:q])
26
+ @shipments = @search.result.
27
+ page(params[:page]).
28
+ per(params[:per_page] || Spree::Config[:orders_per_page])
29
+
30
+ # Restore dates
31
+ params[:q][:created_at_gt] = created_at_gt
32
+ params[:q][:created_at_lt] = created_at_lt
33
+ end
34
+
35
+ private
36
+
37
+ def find_resource
38
+ if parent_data.present?
39
+ parent.send(controller_name).find_by!(number: params[:id])
40
+ else
41
+ model_class.find_by!(number: params[:id])
42
+ end
43
+ end
44
+
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,14 @@
1
+ Spree::Admin::StockLocationsController.class_eval do
2
+
3
+ create.after :set_supplier
4
+
5
+ private
6
+
7
+ def set_supplier
8
+ if try_spree_current_user.supplier?
9
+ @object.supplier = try_spree_current_user.supplier
10
+ @object.save
11
+ end
12
+ end
13
+
14
+ end
@@ -0,0 +1,32 @@
1
+ class Spree::Admin::SuppliersController < Spree::Admin::ResourceController
2
+
3
+ def edit
4
+ @object.address = Spree::Address.default unless @object.address.present?
5
+ respond_with(@object) do |format|
6
+ format.html { render :layout => !request.xhr? }
7
+ format.js { render :layout => false }
8
+ end
9
+ end
10
+
11
+ def new
12
+ @object = Spree::Supplier.new(address_attributes: {country_id: Spree::Address.default.country_id})
13
+ end
14
+
15
+ private
16
+
17
+ def collection
18
+ params[:q] ||= {}
19
+ params[:q][:meta_sort] ||= "name.asc"
20
+ @search = Spree::Supplier.search(params[:q])
21
+ @collection = @search.result.page(params[:page]).per(Spree::Config[:orders_per_page])
22
+ end
23
+
24
+ def find_resource
25
+ Spree::Supplier.friendly.find(params[:id])
26
+ end
27
+
28
+ def location_after_save
29
+ spree.edit_admin_supplier_path(@object)
30
+ end
31
+
32
+ end
@@ -0,0 +1,18 @@
1
+ Spree::Api::V1::StockLocationsController.class_eval do
2
+
3
+ before_filter :supplier_locations, only: [:index]
4
+ before_filter :supplier_transfers, only: [:index]
5
+
6
+ private
7
+
8
+ def supplier_locations
9
+ params[:q] ||= {}
10
+ params[:q][:supplier_id_eq] = spree_current_user.supplier_id
11
+ end
12
+
13
+ def supplier_transfers
14
+ params[:q] ||= {}
15
+ params[:q][:supplier_id_eq] = spree_current_user.supplier_id
16
+ end
17
+
18
+ end
@@ -0,0 +1,23 @@
1
+ Spree::BaseController.class_eval do
2
+
3
+ prepend_before_filter :redirect_supplier
4
+ # before_action :authorize_supplier
5
+
6
+ private
7
+
8
+ def authorize_supplier
9
+ if respond_to?(:model_class, true) && model_class
10
+ record = model_class
11
+ else
12
+ record = controller_name.to_sym
13
+ end
14
+ authorize! :supplier, record
15
+ authorize! :action, record
16
+ end
17
+
18
+ def redirect_supplier
19
+ if ['/admin', '/admin/authorization_failure'].include?(request.path) && try_spree_current_user.try(:supplier)
20
+ redirect_to '/admin/shipments' and return false
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,13 @@
1
+ module Spree
2
+ class DropShipOrderMailer < Spree::BaseMailer
3
+
4
+ default from: Spree::Store.current.mail_from_address
5
+
6
+ def supplier_order(shipment_id)
7
+ @shipment = Shipment.find shipment_id
8
+ @supplier = @shipment.supplier
9
+ mail to: @supplier.email, subject: Spree.t('drop_ship_order_mailer.supplier_order.subject', name: Spree::Store.current.name, number: @shipment.number)
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ module Spree
2
+ class SupplierMailer < Spree::BaseMailer
3
+
4
+ default from: Spree::Store.current.mail_from_address
5
+
6
+ def welcome(supplier_id)
7
+ @supplier = Supplier.find supplier_id
8
+ mail to: @supplier.email, subject: Spree.t('supplier_mailer.welcome.subject')
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,5 @@
1
+ if defined?(Ckeditor)
2
+ Ckeditor::Asset.class_eval do
3
+ belongs_to :supplier, class_name: 'Spree::Supplier'
4
+ end
5
+ end
@@ -0,0 +1,17 @@
1
+ module Spree
2
+ class DropShipConfiguration < Preferences::Configuration
3
+
4
+ # Automatically deliver drop ship orders by default.
5
+ preference :automatically_deliver_orders_to_supplier, :boolean, default: true
6
+
7
+ # Default flat rate to charge suppliers per order for commission.
8
+ preference :default_commission_flat_rate, :float, default: 0.0
9
+
10
+ # Default percentage to charge suppliers per order for commission.
11
+ preference :default_commission_percentage, :float, default: 0.0
12
+
13
+ # Determines whether or not to email a new supplier their welcome email.
14
+ preference :send_supplier_email, :boolean, default: true
15
+
16
+ end
17
+ end
@@ -0,0 +1,27 @@
1
+ Spree::Order.class_eval do
2
+
3
+ has_many :stock_locations, through: :shipments
4
+ has_many :suppliers, through: :stock_locations
5
+
6
+ # Once order is finalized we want to notify the suppliers of their drop ship orders.
7
+ # Here we are handling notification by emailing the suppliers.
8
+ # If you want to customize this you could override it as a hook for notifying a supplier with a API request instead.
9
+ def finalize_with_drop_ship!
10
+ finalize_without_drop_ship!
11
+ shipments.each do |shipment|
12
+ if SpreeDropShip::Config[:send_supplier_email] && shipment.supplier.present?
13
+ begin
14
+ Spree::DropShipOrderMailer.supplier_order(shipment.id).deliver!
15
+ rescue => ex #Errno::ECONNREFUSED => ex
16
+ puts ex.message
17
+ puts ex.backtrace.join("\n")
18
+ Rails.logger.error ex.message
19
+ Rails.logger.error ex.backtrace.join("\n")
20
+ return true # always return true so that failed email doesn't crash app.
21
+ end
22
+ end
23
+ end
24
+ end
25
+ alias_method_chain :finalize!, :drop_ship
26
+
27
+ end
@@ -0,0 +1,7 @@
1
+ module Spree
2
+ Payment.class_eval do
3
+
4
+ belongs_to :payable, polymorphic: true
5
+
6
+ end
7
+ end
@@ -0,0 +1,32 @@
1
+ Spree::Product.class_eval do
2
+
3
+ has_many :suppliers, through: :master
4
+
5
+ def add_supplier!(supplier_or_id)
6
+ supplier = supplier_or_id.is_a?(Spree::Supplier) ? supplier_or_id : Spree::Supplier.find(supplier_or_id)
7
+ populate_for_supplier! supplier if supplier
8
+ end
9
+
10
+ def add_suppliers!(supplier_ids)
11
+ Spree::Supplier.where(id: supplier_ids).each do |supplier|
12
+ populate_for_supplier! supplier
13
+ end
14
+ end
15
+
16
+ # Returns true if the product has a drop shipping supplier.
17
+ def supplier?
18
+ suppliers.present?
19
+ end
20
+
21
+ private
22
+
23
+ def populate_for_supplier!(supplier)
24
+ variants_including_master.each do |variant|
25
+ unless variant.suppliers.pluck(:id).include?(supplier.id)
26
+ variant.suppliers << supplier
27
+ supplier.stock_locations.each { |location| location.propagate_variant(variant) }
28
+ end
29
+ end
30
+ end
31
+
32
+ end
@@ -0,0 +1,39 @@
1
+ Spree::Shipment.class_eval do
2
+ self.whitelisted_ransackable_attributes = ['number', 'state']
3
+ # TODO here to fix cancan issue thinking its just Order
4
+ belongs_to :order, class_name: 'Spree::Order', touch: true, inverse_of: :shipments
5
+
6
+ has_many :payments, as: :payable
7
+
8
+ scope :by_supplier, -> (supplier_id) { joins(:stock_location).where(spree_stock_locations: { supplier_id: supplier_id }) }
9
+
10
+ delegate :supplier, to: :stock_location
11
+
12
+ def display_final_price_with_items
13
+ Spree::Money.new final_price_with_items
14
+ end
15
+
16
+ def final_price_with_items
17
+ self.item_cost + self.final_price
18
+ end
19
+
20
+ # TODO move commission to spree_marketplace?
21
+ def supplier_commission_total
22
+ ((self.final_price_with_items * self.supplier.commission_percentage / 100) + self.supplier.commission_flat_rate)
23
+ end
24
+
25
+ private
26
+
27
+ durably_decorate :after_ship, mode: 'soft', sha: 'e8eca7f8a50ad871f5753faae938d4d01c01593d' do
28
+ original_after_ship
29
+
30
+ if supplier.present?
31
+ update_commission
32
+ end
33
+ end
34
+
35
+ def update_commission
36
+ update_column :supplier_commission, self.supplier_commission_total
37
+ end
38
+
39
+ end
@@ -0,0 +1,42 @@
1
+ module Spree
2
+ module Stock
3
+ module Splitter
4
+ class DropShip < Spree::Stock::Splitter::Base
5
+
6
+ def split(packages)
7
+ split_packages = []
8
+ packages.each do |package|
9
+ # Package fulfilled items together.
10
+ fulfilled = package.contents.select { |content| content.variant.suppliers.count == 0 }
11
+ split_packages << build_package(fulfilled)
12
+ # Determine which supplier to package drop shipped items.
13
+ drop_ship = package.contents.select { |content| content.variant.suppliers.count > 0 }
14
+ drop_ship.each do |content|
15
+ # Select the related variant
16
+ variant = content.variant
17
+ # Select suppliers ordering ascending according to cost.
18
+ suppliers = variant.supplier_variants.order("spree_supplier_variants.cost ASC").map(&:supplier)
19
+ # Select first supplier that has stock location with avialable stock item.
20
+ available_supplier = suppliers.detect do |supplier|
21
+ supplier.stock_locations_with_available_stock_items(variant).any?
22
+ end
23
+ # Select the first available stock location with in the available_supplier stock locations.
24
+ stock_location = nil
25
+ if available_supplier.present?
26
+ stock_location = available_supplier.stock_locations_with_available_stock_items(variant).first
27
+ end
28
+ # Add to any existing packages or create a new one.
29
+ if existing_package = split_packages.detect { |p| p.stock_location == stock_location }
30
+ existing_package.contents << content
31
+ else
32
+ split_packages << Spree::Stock::Package.new(stock_location, [content])
33
+ end
34
+ end
35
+ end
36
+ return_next split_packages
37
+ end
38
+
39
+ end
40
+ end
41
+ end
42
+ end