solidus_legacy_return_authorizations 1.0.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.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.rspec +1 -0
  4. data/Gemfile +10 -0
  5. data/LICENSE +26 -0
  6. data/README.md +62 -0
  7. data/Rakefile +21 -0
  8. data/app/assets/javascripts/spree/backend/solidus_legacy_return_authorizations.js +2 -0
  9. data/app/assets/stylesheets/spree/backend/solidus_legacy_return_authorizations.css +4 -0
  10. data/app/controllers/spree/admin/legacy_return_authorizations_controller.rb +25 -0
  11. data/app/controllers/spree/api/legacy_return_authorizations_controller.rb +74 -0
  12. data/app/helpers/spree/admin/navigation_helper_decorator.rb +12 -0
  13. data/app/helpers/spree/api/api_helpers_decorator.rb +7 -0
  14. data/app/models/spree/adjustment_decorator.rb +3 -0
  15. data/app/models/spree/inventory_unit_decorator.rb +3 -0
  16. data/app/models/spree/legacy_return_authorization.rb +108 -0
  17. data/app/models/spree/order_decorator.rb +3 -0
  18. data/app/models/spree/permission_sets/legacy_return_authorization_display.rb +9 -0
  19. data/app/models/spree/permission_sets/legacy_return_authorization_management.rb +9 -0
  20. data/app/models/spree/strong_parameters_decorator.rb +5 -0
  21. data/app/overrides/admin_legacy_return_authorizations.rb +14 -0
  22. data/app/views/spree/admin/legacy_return_authorizations/_form.html.erb +78 -0
  23. data/app/views/spree/admin/legacy_return_authorizations/edit.html.erb +32 -0
  24. data/app/views/spree/admin/legacy_return_authorizations/index.html.erb +48 -0
  25. data/app/views/spree/api/legacy_return_authorizations/index.v1.rabl +7 -0
  26. data/app/views/spree/api/legacy_return_authorizations/new.v1.rabl +3 -0
  27. data/app/views/spree/api/legacy_return_authorizations/show.v1.rabl +2 -0
  28. data/bin/rails +7 -0
  29. data/circle.yml +6 -0
  30. data/config/locales/en.yml +19 -0
  31. data/config/routes.rb +25 -0
  32. data/db/migrate/20140710044402_create_spree_legacy_return_authorizations.rb +26 -0
  33. data/lib/generators/solidus_legacy_return_authorizations/install/install_generator.rb +29 -0
  34. data/lib/solidus_legacy_return_authorizations.rb +2 -0
  35. data/lib/spree_legacy_return_authorizations/engine.rb +20 -0
  36. data/lib/spree_legacy_return_authorizations/factories.rb +13 -0
  37. data/solidus_legacy_return_authorizations.gemspec +29 -0
  38. data/spec/controllers/admin/legacy_return_authorizations_controller_spec.rb +32 -0
  39. data/spec/controllers/spree/api/legacy_return_authorizations_controller_spec.rb +157 -0
  40. data/spec/features/admin/orders/legacy_return_authorizations_spec.rb +26 -0
  41. data/spec/models/spree/legacy_return_authorization_spec.rb +214 -0
  42. data/spec/models/spree/permission_sets/legacy_return_authorization_display_spec.rb +22 -0
  43. data/spec/models/spree/permission_sets/legacy_return_authorization_management_spec.rb +20 -0
  44. data/spec/spec_helper.rb +74 -0
  45. data/spec/support/authentication_support.rb +7 -0
  46. data/spec/support/have_attributes_matcher.rb +8 -0
  47. metadata +245 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 18ac64c290153dc76aa973685a5dc58ea3190508
4
+ data.tar.gz: 539c2555b6e921869fee35ff7925b155446d3472
5
+ SHA512:
6
+ metadata.gz: b3767c15416db0beb83c325f3a50557fd3ac98c222fa9f37ae490aa9598a74bbb046b05d5405921c60638e0635b3d63230a5b20a1276bedea2d94b5ea61b478e
7
+ data.tar.gz: 79ea178bd773d20e8bdd6741dd8f6c67afb7206948f51be81a82c631c215eaccf26195d3c2d2a7bf92329c19955fe507e3dfb4f17bd0d0264665340105348eb6
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ \#*
2
+ *~
3
+ .#*
4
+ .DS_Store
5
+ .idea
6
+ .project
7
+ .sass-cache
8
+ coverage
9
+ Gemfile.lock
10
+ tmp
11
+ nbproject
12
+ pkg
13
+ *.swp
14
+ spec/dummy
15
+ .ruby-version
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "solidus", github: "solidusio/solidus", branch: "master"
4
+ gem "solidus_auth_devise", "~> 1.0"
5
+
6
+ group :development, :test do
7
+ gem "pry-rails"
8
+ end
9
+
10
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,26 @@
1
+ Copyright (c) 2014 Bonobos, Inc
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without modification,
5
+ are permitted provided that the following conditions are met:
6
+
7
+ * Redistributions of source code must retain the above copyright notice,
8
+ this list of conditions and the following disclaimer.
9
+ * Redistributions in binary form must reproduce the above copyright notice,
10
+ this list of conditions and the following disclaimer in the documentation
11
+ and/or other materials provided with the distribution.
12
+ * Neither the name Spree nor the names of its contributors may be used to
13
+ endorse or promote products derived from this software without specific
14
+ prior written permission.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.md ADDED
@@ -0,0 +1,62 @@
1
+ Solidus Legacy Return Authorizations
2
+ ====================================
3
+
4
+ This is an extension for users migrating from legacy versions of Spree (2.3.x
5
+ and prior) which had a different representation of and handling for return
6
+ authorizations.
7
+
8
+ When upgrading from a prior version of Spree to Solidus, simply include this
9
+ extension in your application's Gemfile and your old data will be preserved in
10
+ separate tables (e.g., `spree_legacy_return_authorizations`) and columns (e.g.
11
+ `spree_inventory_units.legacy_return_authorization_id`).
12
+
13
+ This extension maintains the legacy admin interfaces for viewing and closing
14
+ out (receiving/canceling) any existing legacy return authorizations. It does
15
+ not allow creating any new legacy return authorizations. New return
16
+ authorizations should be handled through the new returns system included in
17
+ Solidus.
18
+
19
+ If an order has existing legacy return authorizations then an additional admin
20
+ menu item "Legacy Return Authorizations" will appear in the admin interface for
21
+ that order (/admin/orders/XXX/edit).
22
+
23
+ Installation
24
+ ------------
25
+
26
+ Add solidus_legacy_return_authorizations to your Gemfile:
27
+
28
+ ```ruby
29
+ gem "solidus_legacy_return_authorizations"
30
+ ```
31
+
32
+ Bundle your dependencies and run the installation generator:
33
+
34
+ ```shell
35
+ bundle
36
+ bundle exec rails g solidus_legacy_return_authorizations:install
37
+ ```
38
+
39
+ Authorization
40
+ -------------
41
+
42
+ For discrete authorization, two permission sets have been added to allow for granular display in the admin.
43
+
44
+ `Spree::PermissionSets::LegacyReturnAuthorizationDisplay` and `Spree::PermissionSets::LegacyReturnAuthorizationManagement` have been added and can be assigned via [RoleConfiguration](http://docs.solidus.io/Spree/RoleConfiguration.html)
45
+
46
+
47
+ Testing
48
+ -------
49
+
50
+ First bundle your dependencies, then run `rake`. `rake` will default to building the dummy app if it does not exist, then it will run specs. The dummy app can be regenerated by using `rake test_app`.
51
+
52
+ ```shell
53
+ bundle
54
+ bundle exec rake
55
+ ```
56
+
57
+ When testing your applications integration with this extension you may use it's factories.
58
+ Simply add this require statement to your spec_helper:
59
+
60
+ ```ruby
61
+ require 'spree_legacy_return_authorizations/factories'
62
+ ```
data/Rakefile ADDED
@@ -0,0 +1,21 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ require 'spree/testing_support/extension_rake'
6
+
7
+ RSpec::Core::RakeTask.new
8
+
9
+ task :default do
10
+ if Dir["spec/dummy"].empty?
11
+ Rake::Task[:test_app].invoke
12
+ Dir.chdir("../../")
13
+ end
14
+ Rake::Task[:spec].invoke
15
+ end
16
+
17
+ desc 'Generates a dummy app for testing'
18
+ task :test_app do
19
+ ENV['LIB_NAME'] = 'solidus_legacy_return_authorizations'
20
+ Rake::Task['extension:test_app'].invoke
21
+ end
@@ -0,0 +1,2 @@
1
+ // Placeholder manifest file.
2
+ // the installer will append this file to the app vendored assets here: vendor/assets/javascripts/spree/backend/all.js'
@@ -0,0 +1,4 @@
1
+ /*
2
+ Placeholder manifest file.
3
+ the installer will append this file to the app vendored assets here: 'vendor/assets/stylesheets/spree/backend/all.css'
4
+ */
@@ -0,0 +1,25 @@
1
+ module Spree
2
+ module Admin
3
+ class LegacyReturnAuthorizationsController < ResourceController
4
+ belongs_to 'spree/order', :find_by => :number
5
+
6
+ update.after :associate_inventory_units
7
+ create.after :associate_inventory_units
8
+
9
+ def fire
10
+ @legacy_return_authorization.send("#{params[:e]}!")
11
+ flash[:success] = Spree.t(:legacy_return_authorization_updated)
12
+ redirect_to :back
13
+ end
14
+
15
+ # We don't want to allow creating new legacy RMAs so remove the default methods provided by Admin::ResourceController
16
+ undef new
17
+ undef create
18
+
19
+ protected
20
+ def associate_inventory_units
21
+ (params[:return_quantity] || []).each { |variant_id, qty| @legacy_return_authorization.add_variant(variant_id.to_i, qty.to_i) }
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,74 @@
1
+ module Spree
2
+ module Api
3
+ class LegacyReturnAuthorizationsController < Spree::Api::BaseController
4
+
5
+ def destroy
6
+ @legacy_return_authorization = order.legacy_return_authorizations.accessible_by(current_ability, :destroy).find(params[:id])
7
+ @legacy_return_authorization.destroy
8
+ respond_with(@legacy_return_authorization, status: 204)
9
+ end
10
+
11
+ def index
12
+ authorize! :admin, LegacyReturnAuthorization
13
+ @legacy_return_authorizations = order.legacy_return_authorizations.accessible_by(current_ability, :read).
14
+ ransack(params[:q]).result.
15
+ page(params[:page]).per(params[:per_page])
16
+ respond_with(@legacy_return_authorizations)
17
+ end
18
+
19
+ def show
20
+ authorize! :admin, LegacyReturnAuthorization
21
+ @legacy_return_authorization = order.legacy_return_authorizations.accessible_by(current_ability, :read).find(params[:id])
22
+ respond_with(@legacy_return_authorization)
23
+ end
24
+
25
+ def update
26
+ @legacy_return_authorization = order.legacy_return_authorizations.accessible_by(current_ability, :update).find(params[:id])
27
+ if @legacy_return_authorization.update_attributes(legacy_return_authorization_params)
28
+ respond_with(@legacy_return_authorization, default_template: :show)
29
+ else
30
+ invalid_resource!(@legacy_return_authorization)
31
+ end
32
+ end
33
+
34
+ def add
35
+ @legacy_return_authorization = order.legacy_return_authorizations.accessible_by(current_ability, :update).find(params[:id])
36
+ @legacy_return_authorization.add_variant params[:variant_id].to_i, params[:quantity].to_i
37
+ if @legacy_return_authorization.valid?
38
+ respond_with @legacy_return_authorization, default_template: :show
39
+ else
40
+ invalid_resource!(@legacy_return_authorization)
41
+ end
42
+ end
43
+
44
+ def receive
45
+ @legacy_return_authorization = order.legacy_return_authorizations.accessible_by(current_ability, :update).find(params[:id])
46
+ if @legacy_return_authorization.receive
47
+ respond_with @legacy_return_authorization, default_template: :show
48
+ else
49
+ invalid_resource!(@legacy_return_authorization)
50
+ end
51
+ end
52
+
53
+ def cancel
54
+ @legacy_return_authorization = order.legacy_return_authorizations.accessible_by(current_ability, :update).find(params[:id])
55
+ if @legacy_return_authorization.cancel
56
+ respond_with @legacy_return_authorization, default_template: :show
57
+ else
58
+ invalid_resource!(@legacy_return_authorization)
59
+ end
60
+ end
61
+
62
+ private
63
+
64
+ def order
65
+ @order ||= Spree::Order.find_by!(number: order_id)
66
+ authorize! :read, @order
67
+ end
68
+
69
+ def legacy_return_authorization_params
70
+ params.require(:legacy_return_authorization).permit(permitted_legacy_return_authorization_attributes)
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,12 @@
1
+ Spree::Admin::NavigationHelper.module_eval do
2
+ def tab_with_legacy_return_authorizations(*args)
3
+ if args.first == :orders
4
+ options = args.pop if args.last.is_a?(Hash)
5
+ args << :legacy_return_authorizations
6
+ args << options
7
+ end
8
+ tab_without_legacy_return_authorizations(*args)
9
+ end
10
+
11
+ alias_method_chain :tab, :legacy_return_authorizations
12
+ end
@@ -0,0 +1,7 @@
1
+ Spree::Api::ApiHelpers.module_eval do
2
+ def legacy_return_authorization_attributes
3
+ [:id, :number, :state, :amount, :order_id, :reason, :created_at, :updated_at]
4
+ end
5
+
6
+ self.inventory_unit_attributes << :legacy_return_authorization_id
7
+ end
@@ -0,0 +1,3 @@
1
+ Spree::Adjustment.class_eval do
2
+ scope :legacy_return_authorization, -> { where(source_type: "Spree::LegacyReturnAuthorization") }
3
+ end
@@ -0,0 +1,3 @@
1
+ Spree::InventoryUnit.class_eval do
2
+ belongs_to :legacy_return_authorization, class_name: "Spree::LegacyReturnAuthorization"
3
+ end
@@ -0,0 +1,108 @@
1
+ module Spree
2
+ class LegacyReturnAuthorization < ActiveRecord::Base
3
+ belongs_to :order, class_name: 'Spree::Order'
4
+
5
+ has_many :inventory_units, dependent: :nullify
6
+ belongs_to :stock_location
7
+ before_create :generate_number
8
+ before_save :force_positive_amount
9
+
10
+ validates :order, presence: true
11
+ validates :amount, numericality: true
12
+ validate :must_have_shipped_units
13
+
14
+ state_machine initial: :authorized do
15
+ after_transition to: :received, do: :process_return
16
+
17
+ event :receive do
18
+ transition to: :received, from: :authorized, if: :allow_receive?
19
+ end
20
+ event :cancel do
21
+ transition to: :canceled, from: :authorized
22
+ end
23
+ end
24
+
25
+ def currency
26
+ order.nil? ? Spree::Config[:currency] : order.currency
27
+ end
28
+
29
+ def display_amount
30
+ Spree::Money.new(amount, { currency: currency })
31
+ end
32
+
33
+ def add_variant(variant_id, quantity)
34
+ order_units = returnable_inventory.group_by(&:variant_id)
35
+ returned_units = inventory_units.group_by(&:variant_id)
36
+ return false if order_units.empty?
37
+
38
+ count = 0
39
+
40
+ if returned_units[variant_id].nil? || returned_units[variant_id].size < quantity
41
+ count = returned_units[variant_id].nil? ? 0 : returned_units[variant_id].size
42
+
43
+ order_units[variant_id].each do |inventory_unit|
44
+ next unless inventory_unit.legacy_return_authorization.nil? && count < quantity
45
+
46
+ inventory_unit.legacy_return_authorization = self
47
+ inventory_unit.save!
48
+
49
+ count += 1
50
+ end
51
+ elsif returned_units[variant_id].size > quantity
52
+ (returned_units[variant_id].size - quantity).times do |i|
53
+ returned_units[variant_id][i].legacy_return_authorization_id = nil
54
+ returned_units[variant_id][i].save!
55
+ end
56
+ end
57
+
58
+ order.authorize_return! if inventory_units.reload.size > 0 && !order.awaiting_return?
59
+ end
60
+
61
+ def returnable_inventory
62
+ order.shipped_shipments.collect{|s| s.inventory_units.to_a}.flatten
63
+ end
64
+
65
+ # Used when Adjustment#update! wants to update the related adjustmenrt
66
+ def compute_amount(*args)
67
+ amount.abs * -1
68
+ end
69
+
70
+ private
71
+
72
+ def must_have_shipped_units
73
+ errors.add(:order, Spree.t(:has_no_shipped_units)) if order.nil? || !order.shipped_shipments.any?
74
+ end
75
+
76
+ def generate_number
77
+ self.number ||= loop do
78
+ random = "RMA#{Array.new(9){rand(9)}.join}"
79
+ break random unless self.class.exists?(number: random)
80
+ end
81
+ end
82
+
83
+ def process_return
84
+ inventory_units(include: :variant).each do |iu|
85
+ iu.return!
86
+
87
+ if iu.variant.should_track_inventory?
88
+ if stock_item = Spree::StockItem.find_by(variant_id: iu.variant_id, stock_location_id: stock_location_id)
89
+ Spree::StockMovement.create!(stock_item_id: stock_item.id, quantity: 1)
90
+ end
91
+ end
92
+ end
93
+
94
+ Adjustment.create(adjustable: order, amount: compute_amount, label: Spree.t(:legacy_rma_credit), source: self)
95
+ order.update!
96
+
97
+ order.return if inventory_units.all?(&:returned?)
98
+ end
99
+
100
+ def allow_receive?
101
+ !inventory_units.empty?
102
+ end
103
+
104
+ def force_positive_amount
105
+ self.amount = amount.abs
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,3 @@
1
+ Spree::Order.class_eval do
2
+ has_many :legacy_return_authorizations, dependent: :destroy
3
+ end
@@ -0,0 +1,9 @@
1
+ module Spree
2
+ module PermissionSets
3
+ class LegacyReturnAuthorizationDisplay < PermissionSets::Base
4
+ def activate!
5
+ can [:display, :admin], Spree::LegacyReturnAuthorization
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Spree
2
+ module PermissionSets
3
+ class LegacyReturnAuthorizationManagement < PermissionSets::Base
4
+ def activate!
5
+ can :manage, Spree::LegacyReturnAuthorization
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ Spree::Core::ControllerHelpers::StrongParameters.module_eval do
2
+ def permitted_legacy_return_authorization_attributes
3
+ [:amount, :reason, :stock_location_id]
4
+ end
5
+ end