Browse files

Updated to 1.0.0.rc

  • Loading branch information...
1 parent b491e5a commit 5f8ead50bcfc62f21eb167fb2f02b548483db6e2 @BDQ BDQ committed Jan 27, 2012
Showing with 832 additions and 630 deletions.
  1. +1 −1 .gitignore
  2. +5 −0 .travis.yml
  3. +7 −30 Gemfile
  4. +242 −0 Gemfile.lock
  5. +7 −67 Rakefile
  6. +0 −1 VERSION
  7. +2 −2 Versionfile
  8. +1 −0 app/assets/javascripts/admin/spree_store_credits.js
  9. +1 −0 app/assets/javascripts/store/spree_store_credits.js
  10. +3 −0 app/assets/stylesheets/admin/spree_store_credits.css
  11. +3 −0 app/assets/stylesheets/store/spree_store_credits.css
  12. +0 −21 app/controllers/admin/store_credits_controller.rb
  13. +0 −14 app/controllers/checkout_controller_decorator.rb
  14. +22 −0 app/controllers/spree/admin/store_credits_controller.rb
  15. +18 −0 app/controllers/spree/checkout_controller_decorator.rb
  16. +11 −0 app/controllers/spree/users_controller_decorator.rb
  17. +0 −9 app/controllers/users_controller_decorator.rb
  18. +13 −0 app/helpers/spree/checkout_helper_decorator.rb
  19. +0 −95 app/models/order_decorator.rb
  20. +0 −10 app/models/promotion/actions/give_store_credit.rb
  21. +5 −0 app/models/spree/adjustment_decorator.rb
  22. +89 −0 app/models/spree/order_decorator.rb
  23. +12 −0 app/models/spree/promotion/actions/give_store_credit.rb
  24. +9 −0 app/models/spree/store_credit.rb
  25. +5 −0 app/models/spree/store_credit_adjustment.rb
  26. +13 −0 app/models/spree/user_decorator.rb
  27. +0 −7 app/models/store_credit.rb
  28. +0 −3 app/models/store_credit_adjustment.rb
  29. +0 −11 app/models/user_decorator.rb
  30. +6 −18 app/overrides/views_decorator.rb
  31. +0 −10 app/views/admin/store_credits/edit.html.erb
  32. +0 −1 app/views/admin/store_credits/show.html.erb
  33. 0 app/views/{ → spree}/admin/store_credits/_form.html.erb
  34. +10 −0 app/views/spree/admin/store_credits/edit.html.erb
  35. +1 −1 app/views/{ → spree}/admin/store_credits/index.html.erb
  36. +3 −3 app/views/{ → spree}/admin/store_credits/new.html.erb
  37. +1 −0 app/views/spree/admin/store_credits/show.html.erb
  38. 0 app/views/{ → spree}/checkout/_store_credits.html.erb
  39. +33 −0 app/views/spree/users/_store_credits.html.erb
  40. +0 −33 app/views/users/_store_credits.html.erb
  41. +1 −3 config/routes.rb
  42. 0 {lib/generators/templates → }/db/migrate/20100928140217_create_store_credits.rb
  43. +5 −0 db/migrate/20120127100416_namespace_tables.rb
  44. +10 −10 lib/generators/spree_store_credits/install_generator.rb
  45. +12 −5 lib/spree_store_credits.rb
  46. +5 −0 script/rails
  47. +2 −2 spec/factories/store_credits_factory.rb
  48. +0 −198 spec/models/order_spec.rb
  49. +200 −0 spec/models/spree/order_spec.rb
  50. +18 −0 spec/models/spree/user_spec.rb
  51. +0 −16 spec/models/user_spec.rb
  52. +19 −0 spec/requests/spree/store_credits_spec.rb
  53. +0 −30 spec/requests/store_credits_spec.rb
  54. +29 −28 spec/spec_helper.rb
  55. +8 −1 spree_store_credits.gemspec
View
2 .gitignore
@@ -1,2 +1,2 @@
-spec/test_app
+spec/dummy
*.swp
View
5 .travis.yml
@@ -0,0 +1,5 @@
+language: ruby
+rvm:
+ - 1.8.7
+ - ree
+ - 1.9.3
View
37 Gemfile
@@ -1,36 +1,13 @@
source 'http://rubygems.org'
-gem 'rake', '~> 0.8.7'
-gem 'linecache', '0.43'
-
group :test do
- gem 'rspec-rails', '= 2.6.1'
- gem 'factory_girl', '= 1.3.3'
- gem 'factory_girl_rails', '= 1.0.1'
- gem 'rcov'
- gem 'shoulda'
- gem 'faker'
- if RUBY_VERSION < "1.9"
- gem "ruby-debug"
- else
- gem "ruby-debug19"
- end
+ gem 'ffaker'
end
-group :cucumber do
- gem 'cucumber-rails'
- gem 'database_cleaner', '= 0.6.7'
- gem 'nokogiri'
- gem 'capybara', '= 0.4.1.2'
- gem 'factory_girl', '= 1.3.3'
- gem 'factory_girl_rails', '= 1.0.1'
- gem 'faker'
- gem 'launchy'
-
- if RUBY_VERSION < "1.9"
- gem "ruby-debug"
- else
- gem "ruby-debug19"
- end
+if RUBY_VERSION < "1.9"
+ gem "ruby-debug"
+else
+ gem "ruby-debug19"
end
-gem 'spree', :git => 'git://github.com/spree/spree.git'
+
+gemspec
View
242 Gemfile.lock
@@ -0,0 +1,242 @@
+PATH
+ remote: .
+ specs:
+ spree_store_credits (1.0.1)
+ spree (~> 1.0.0.rc2)
+
+GEM
+ remote: http://rubygems.org/
+ specs:
+ actionmailer (3.1.3)
+ actionpack (= 3.1.3)
+ mail (~> 2.3.0)
+ actionpack (3.1.3)
+ activemodel (= 3.1.3)
+ activesupport (= 3.1.3)
+ builder (~> 3.0.0)
+ erubis (~> 2.7.0)
+ i18n (~> 0.6)
+ rack (~> 1.3.5)
+ rack-cache (~> 1.1)
+ rack-mount (~> 0.8.2)
+ rack-test (~> 0.6.1)
+ sprockets (~> 2.0.3)
+ active_utils (1.0.2)
+ activesupport (>= 2.3.11)
+ i18n
+ activemerchant (1.20.1)
+ active_utils (>= 1.0.1)
+ activesupport (>= 2.3.11)
+ braintree (>= 2.0.0)
+ builder (>= 2.0.0)
+ i18n
+ json (>= 1.5.1)
+ money (<= 3.7.1)
+ activemodel (3.1.3)
+ activesupport (= 3.1.3)
+ builder (~> 3.0.0)
+ i18n (~> 0.6)
+ activerecord (3.1.3)
+ activemodel (= 3.1.3)
+ activesupport (= 3.1.3)
+ arel (~> 2.2.1)
+ tzinfo (~> 0.3.29)
+ activeresource (3.1.3)
+ activemodel (= 3.1.3)
+ activesupport (= 3.1.3)
+ activesupport (3.1.3)
+ multi_json (~> 1.0)
+ acts_as_list (0.1.4)
+ arel (2.2.1)
+ bcrypt-ruby (3.0.1)
+ braintree (2.13.2)
+ builder (>= 2.0.0)
+ builder (3.0.0)
+ cancan (1.6.7)
+ capybara (1.0.1)
+ mime-types (>= 1.16)
+ nokogiri (>= 1.3.3)
+ rack (>= 1.0.0)
+ rack-test (>= 0.5.4)
+ selenium-webdriver (~> 2.0)
+ xpath (~> 0.1.4)
+ childprocess (0.3.0)
+ ffi (~> 1.0.6)
+ cocaine (0.2.1)
+ columnize (0.3.6)
+ database_cleaner (0.7.1)
+ deface (0.7.2)
+ nokogiri (~> 1.5.0)
+ rails (>= 3.0.9)
+ devise (1.4.8)
+ bcrypt-ruby (~> 3.0)
+ orm_adapter (~> 0.0.3)
+ warden (~> 1.0.3)
+ diff-lcs (1.1.3)
+ erubis (2.7.0)
+ factory_girl (2.4.2)
+ activesupport
+ factory_girl_rails (1.5.0)
+ factory_girl (~> 2.4.0)
+ railties (>= 3.0.0)
+ ffaker (1.12.1)
+ ffi (1.0.11)
+ highline (1.6.8)
+ hike (1.2.1)
+ i18n (0.6.0)
+ jquery-rails (1.0.19)
+ railties (~> 3.0)
+ thor (~> 0.14)
+ json (1.6.5)
+ kaminari (0.13.0)
+ actionpack (>= 3.0.0)
+ activesupport (>= 3.0.0)
+ railties (>= 3.0.0)
+ linecache (0.46)
+ rbx-require-relative (> 0.0.4)
+ mail (2.3.0)
+ i18n (>= 0.4.0)
+ mime-types (~> 1.16)
+ treetop (~> 1.4.8)
+ meta_search (1.1.1)
+ actionpack (~> 3.1.0)
+ activerecord (~> 3.1.0)
+ activesupport (~> 3.1.0)
+ polyamorous (~> 0.5.0)
+ mime-types (1.17.2)
+ money (3.7.1)
+ i18n (~> 0.4)
+ multi_json (1.0.4)
+ nested_set (1.6.8)
+ activerecord (>= 3.0.0)
+ railties (>= 3.0.0)
+ nokogiri (1.5.0)
+ orm_adapter (0.0.6)
+ paperclip (2.4.1)
+ activerecord (>= 2.3.0)
+ activesupport (>= 2.3.2)
+ cocaine (>= 0.0.2)
+ mime-types
+ polyamorous (0.5.0)
+ activerecord (~> 3.0)
+ polyglot (0.3.3)
+ rack (1.3.6)
+ rack-cache (1.1)
+ rack (>= 0.4)
+ rack-mount (0.8.3)
+ rack (>= 1.0.0)
+ rack-ssl (1.3.2)
+ rack
+ rack-test (0.6.1)
+ rack (>= 1.0)
+ rails (3.1.3)
+ actionmailer (= 3.1.3)
+ actionpack (= 3.1.3)
+ activerecord (= 3.1.3)
+ activeresource (= 3.1.3)
+ activesupport (= 3.1.3)
+ bundler (~> 1.0)
+ railties (= 3.1.3)
+ railties (3.1.3)
+ actionpack (= 3.1.3)
+ activesupport (= 3.1.3)
+ rack-ssl (~> 1.3.2)
+ rake (>= 0.8.7)
+ rdoc (~> 3.4)
+ thor (~> 0.14.6)
+ rake (0.9.2.2)
+ rbx-require-relative (0.0.5)
+ rdoc (3.12)
+ json (~> 1.4)
+ rspec (2.8.0)
+ rspec-core (~> 2.8.0)
+ rspec-expectations (~> 2.8.0)
+ rspec-mocks (~> 2.8.0)
+ rspec-core (2.8.0)
+ rspec-expectations (2.8.0)
+ diff-lcs (~> 1.1.2)
+ rspec-mocks (2.8.0)
+ rspec-rails (2.8.1)
+ actionpack (>= 3.0)
+ activesupport (>= 3.0)
+ railties (>= 3.0)
+ rspec (~> 2.8.0)
+ ruby-debug (0.10.4)
+ columnize (>= 0.1)
+ ruby-debug-base (~> 0.10.4.0)
+ ruby-debug-base (0.10.4)
+ linecache (>= 0.3)
+ rubyzip (0.9.5)
+ selenium-webdriver (2.17.0)
+ childprocess (>= 0.2.5)
+ ffi (~> 1.0.9)
+ multi_json (~> 1.0.4)
+ rubyzip
+ spree (1.0.0.rc2)
+ spree_api (= 1.0.0.rc2)
+ spree_auth (= 1.0.0.rc2)
+ spree_cmd (= 1.0.0.rc2)
+ spree_core (= 1.0.0.rc2)
+ spree_dash (= 1.0.0.rc2)
+ spree_promo (= 1.0.0.rc2)
+ spree_sample (= 1.0.0.rc2)
+ spree_api (1.0.0.rc2)
+ spree_auth (= 1.0.0.rc2)
+ spree_core (= 1.0.0.rc2)
+ spree_auth (1.0.0.rc2)
+ cancan (= 1.6.7)
+ devise (= 1.4.8)
+ spree_core (= 1.0.0.rc2)
+ spree_cmd (1.0.0.rc2)
+ rails (>= 3.1.1, <= 3.1.3)
+ spree_core (1.0.0.rc2)
+ activemerchant (= 1.20.1)
+ acts_as_list (= 0.1.4)
+ deface (>= 0.7.2)
+ ffaker (~> 1.12.0)
+ highline (= 1.6.8)
+ jquery-rails (>= 1.0.18, <= 1.0.19)
+ kaminari (>= 0.13.0)
+ meta_search (= 1.1.1)
+ nested_set (= 1.6.8)
+ paperclip (= 2.4.1)
+ rails (>= 3.1.1, <= 3.1.3)
+ state_machine (= 1.1.1)
+ stringex (~> 1.3.0)
+ spree_dash (1.0.0.rc2)
+ spree_core (= 1.0.0.rc2)
+ spree_promo (1.0.0.rc2)
+ spree_auth (= 1.0.0.rc2)
+ spree_core (= 1.0.0.rc2)
+ spree_sample (1.0.0.rc2)
+ spree_core (= 1.0.0.rc2)
+ sprockets (2.0.3)
+ hike (~> 1.2)
+ rack (~> 1.0)
+ tilt (~> 1.1, != 1.3.0)
+ sqlite3 (1.3.5)
+ state_machine (1.1.1)
+ stringex (1.3.0)
+ thor (0.14.6)
+ tilt (1.3.3)
+ treetop (1.4.10)
+ polyglot
+ polyglot (>= 0.3.1)
+ tzinfo (0.3.31)
+ warden (1.0.6)
+ rack (>= 1.0)
+ xpath (0.1.4)
+ nokogiri (~> 1.3)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ capybara (= 1.0.1)
+ database_cleaner
+ factory_girl_rails (~> 1.5.0)
+ ffaker
+ rspec-rails (~> 2.7)
+ ruby-debug
+ spree_store_credits!
+ sqlite3
View
74 Rakefile
@@ -1,83 +1,23 @@
-# encoding: utf-8
-require 'rubygems'
require 'rake'
require 'rake/testtask'
require 'rake/packagetask'
require 'rubygems/package_task'
+require 'rspec/core/rake_task'
+require 'spree/core/testing_support/common_rake'
-gemfile = File.expand_path('../spec/test_app/Gemfile', __FILE__)
-if File.exists?(gemfile) && (%w(spec cucumber).include?(ARGV.first.to_s) || ARGV.size == 0)
- require 'bundler'
- ENV['BUNDLE_GEMFILE'] = gemfile
- Bundler.setup
+RSpec::Core::RakeTask.new
- require 'rspec'
- require 'rspec/core/rake_task'
- RSpec::Core::RakeTask.new
-
- require 'cucumber/rake/task'
- Cucumber::Rake::Task.new do |t|
- t.cucumber_opts = %w{--format progress}
- end
-end
-
-desc "Default Task"
-task :default => [:spec, :cucumber ]
+task :default => [:spec]
spec = eval(File.read('spree_store_credits.gemspec'))
Gem::PackageTask.new(spec) do |p|
p.gem_spec = spec
end
-desc "Release to gemcutter"
-task :release => :package do
- require 'rake/gemcutter'
- Rake::Gemcutter::Tasks.new(spec).define
- Rake::Task['gem:push'].invoke
-end
-
-desc "Default Task"
-task :default => [ :spec ]
-
-desc "Regenerates a rails 3 app for testing"
+desc "Generates a dummy app for testing"
task :test_app do
- SPREE_PATH = ENV['SPREE_PATH']
- raise "SPREE_PATH should be specified" unless SPREE_PATH
- require File.join(SPREE_PATH, 'lib/generators/spree/test_app_generator')
-
- class SpreeStoreCreditTestAppGenerator < Spree::Generators::TestAppGenerator
-
- def install_gems
- inside "test_app" do
- run 'bundle exec rake spree_core:install'
- run 'bundle exec rake spree_auth:install'
- run 'bundle exec rake spree_promo:install'
- generate 'spree_store_credits:install -f'
- end
- end
-
- def migrate_db
- run_migrations
- end
-
- protected
- def full_path_for_local_gems
- <<-gems
-gem 'spree_core', :path => \'#{File.join(SPREE_PATH, "core")}\'
-gem 'spree_auth', :path => \'#{File.join(SPREE_PATH, "auth")}\'
-gem 'spree_promo', :path => \'#{File.join(SPREE_PATH, "promo")}\'
-gem 'spree_store_credits', :path => \'#{File.expand_path('..', __FILE__)}\'
- gems
- end
-
- end
- SpreeStoreCreditTestAppGenerator.start
+ ENV['LIB_NAME'] = 'spree_store_credits'
+ Rake::Task['common:test_app'].invoke
end
-namespace :test_app do
- desc 'Rebuild test and cucumber databases'
- task :rebuild_dbs do
- system("cd spec/test_app && bundle exec rake db:drop db:migrate RAILS_ENV=test && bundle exec rake db:drop db:migrate RAILS_ENV=cucumber")
- end
-end
View
1 VERSION
@@ -1 +0,0 @@
-0.30.0.beta2
View
4 Versionfile
@@ -1,4 +1,4 @@
-"0.70.x" => { :branch => "master" }
+"1.0.x" => { :branch => "master" }
+"0.70.x" => { :branch => "0-70-stable" }
"0.60.x" => { :branch => "0-60-x" }
"0.50.x" => { :branch => "0-50-x" }
-
View
1 app/assets/javascripts/admin/spree_store_credits.js
@@ -0,0 +1 @@
+//= require admin/spree_core
View
1 app/assets/javascripts/store/spree_store_credits.js
@@ -0,0 +1 @@
+//= require store/spree_core
View
3 app/assets/stylesheets/admin/spree_store_credits.css
@@ -0,0 +1,3 @@
+/*
+ *= require admin/spree_core
+*/
View
3 app/assets/stylesheets/store/spree_store_credits.css
@@ -0,0 +1,3 @@
+/*
+ *= require store/spree_core
+*/
View
21 app/controllers/admin/store_credits_controller.rb
@@ -1,21 +0,0 @@
-class Admin::StoreCreditsController < Admin::ResourceController
- before_filter :check_amounts, :only => [:edit, :update]
- prepend_before_filter :set_remaining_amount, :only => [:create, :update]
-
- private
- def check_amounts
- if (@store_credit.remaining_amount < @store_credit.amount)
- flash[:error] = "Can't be edit, b/c already was used."
- redirect_to admin_store_credits_path
- end
- end
-
- def set_remaining_amount
- params[:store_credit][:remaining_amount] = params[:store_credit][:amount]
- end
-
- def collection
- super.page(params[:page])
- end
-
-end
View
14 app/controllers/checkout_controller_decorator.rb
@@ -1,14 +0,0 @@
-CheckoutController.class_eval do
- before_filter :remove_payments_attributes_if_total_is_zero
-
- private
- def remove_payments_attributes_if_total_is_zero
- return unless params[:order] && params[:order][:store_credit_amount]
- store_credit_amount = [BigDecimal.new(params[:order][:store_credit_amount]), current_user.store_credits_total].min
- if store_credit_amount >= current_order.total
- params[:order].delete(:source_attributes)
- params.delete(:payment_source)
- params[:order].delete(:payments_attributes)
- end
- end
-end
View
22 app/controllers/spree/admin/store_credits_controller.rb
@@ -0,0 +1,22 @@
+module Spree
+ class Admin::StoreCreditsController < Admin::ResourceController
+ before_filter :check_amounts, :only => [:edit, :update]
+ prepend_before_filter :set_remaining_amount, :only => [:create, :update]
+
+ private
+ def check_amounts
+ if (@store_credit.remaining_amount < @store_credit.amount)
+ flash[:error] = "Can't be edit, b/c already was used."
+ redirect_to admin_store_credits_path
+ end
+ end
+
+ def set_remaining_amount
+ params[:store_credit][:remaining_amount] = params[:store_credit][:amount]
+ end
+
+ def collection
+ super.page(params[:page])
+ end
+ end
+end
View
18 app/controllers/spree/checkout_controller_decorator.rb
@@ -0,0 +1,18 @@
+module Spree
+ CheckoutController.class_eval do
+ before_filter :remove_payments_attributes_if_total_is_zero
+
+ private
+ def remove_payments_attributes_if_total_is_zero
+ load_order
+
+ return unless params[:order] && params[:order][:store_credit_amount]
+ store_credit_amount = [BigDecimal.new(params[:order][:store_credit_amount]), current_user.store_credits_total].min
+ if store_credit_amount >= (current_order.total + @order.store_credit_amount)
+ params[:order].delete(:source_attributes)
+ params.delete(:payment_source)
+ params[:order].delete(:payments_attributes)
+ end
+ end
+ end
+end
View
11 app/controllers/spree/users_controller_decorator.rb
@@ -0,0 +1,11 @@
+module Spree
+ UsersController.class_eval do
+ before_filter :find_orders_with_store_credit, :only => :show
+
+ private
+
+ def find_orders_with_store_credit
+ @orders_with_store_credit = @user.orders.includes(:adjustments).where(:spree_adjustments => {:source_type => 'StoreCredit'})
+ end
+ end
+end
View
9 app/controllers/users_controller_decorator.rb
@@ -1,9 +0,0 @@
-UsersController.class_eval do
- before_filter :find_orders_with_store_credit, :only => :show
-
- private
-
- def find_orders_with_store_credit
- @orders_with_store_credit = @user.orders.joins(:adjustments).where(:adjustments => {:source_type => 'StoreCredit'})
- end
-end
View
13 app/helpers/spree/checkout_helper_decorator.rb
@@ -0,0 +1,13 @@
+module Spree
+ CheckoutHelper.module_eval do
+
+ def checkout_states
+ if @order.payment.nil? || (@order.payment and @order.payment.payment_method.payment_profiles_supported?)
+ %w(address delivery payment confirm complete)
+ else
+ %w(address delivery payment complete)
+ end
+ end
+
+ end
+end
View
95 app/models/order_decorator.rb
@@ -1,95 +0,0 @@
-Order.class_eval do
- attr_accessible :store_credit_amount, :remove_store_credits
- attr_accessor :store_credit_amount, :remove_store_credits
- # the check for user? below is to ensure we don't break the
- # admin app when creating a new order from the admin console
- # In that case, we create an order before assigning a user
- before_save :process_store_credit, :if => "self.user.present? && @store_credit_amount"
- before_save :remove_store_credits, :if => "self.user.present?"
- after_save :ensure_sufficient_credit, :if => "self.user.present?"
-
- has_many :store_credits, :class_name => 'StoreCreditAdjustment', :conditions => "source_type='StoreCredit'"
-
- def store_credit_amount
- store_credits.sum(:amount).abs
- end
-
-
- # override core process payments to force payment present
- # in case store credits were destroyed by ensure_sufficient_credit
- def process_payments!
- if total > 0 && payment.nil?
- false
- else
- ret = payments.each(&:process!)
- end
- end
-
-
- private
-
- # credit or update store credit adjustment to correct value if amount specified
- #
- def process_store_credit
- @store_credit_amount = BigDecimal.new(@store_credit_amount.to_s).round(2)
-
- # store credit can't be greater than order total (not including existing credit), or the users available credit
- @store_credit_amount = [@store_credit_amount, user.store_credits_total, (total + store_credit_amount.abs)].min
-
- if @store_credit_amount <= 0
- if sca = adjustments.detect {|adjustment| adjustment.source_type == "StoreCredit" }
- sca.destroy
- end
- else
- if sca = adjustments.detect {|adjustment| adjustment.source_type == "StoreCredit" }
- sca.update_attributes({:amount => -(@store_credit_amount)})
- else
- #create adjustment off association to prevent reload
- sca = adjustments.create(:source_type => "StoreCredit", :label => I18n.t(:store_credit) , :amount => -(@store_credit_amount))
- end
-
- #recalc totals and ensure payment is set to new amount
- update_totals
- payment.amount = total if payment
- end
- end
-
- # consume users store credit once the order has completed.
- fsm = self.state_machines[:state]
- fsm.after_transition :to => 'complete', :do => :consume_users_credit
-
- def consume_users_credit
- return unless completed?
- credit_used = self.store_credit_amount
-
- user.store_credits.each do |store_credit|
- break if credit_used == 0
- if store_credit.remaining_amount > 0
- if store_credit.remaining_amount > credit_used
- store_credit.remaining_amount -= credit_used
- store_credit.save
- credit_used = 0
- else
- credit_used -= store_credit.remaining_amount
- store_credit.update_attribute(:remaining_amount, 0)
- end
- end
- end
-
- end
-
- # ensure that user has sufficient credits to cover adjustments
- #
- def ensure_sufficient_credit
- if user.store_credits_total < store_credit_amount
- #user's credit does not cover all adjustments.
- store_credits.destroy_all
-
- update!
- end
- end
-
- def remove_store_credits
- store_credits.clear if @remove_store_credits == '1'
- end
-end
View
10 app/models/promotion/actions/give_store_credit.rb
@@ -1,10 +0,0 @@
-class Promotion::Actions::GiveStoreCredit < PromotionAction
- preference :amount, :decimal, :default => 0.0
-
- def perform(options = {})
- if user = options[:user]
- user.store_credits.create(:amount => preferred_amount, :remaining_amount => preferred_amount, :reason => "Promotion: #{promotion.name}")
- else
- end
- end
-end
View
5 app/models/spree/adjustment_decorator.rb
@@ -0,0 +1,5 @@
+module Spree
+ Adjustment.class_eval do
+ scope :store_credits, lambda { where(:source_type => 'Spree::StoreCredit') }
+ end
+end
View
89 app/models/spree/order_decorator.rb
@@ -0,0 +1,89 @@
+module Spree
+ Order.class_eval do
+ attr_accessible :store_credit_amount, :remove_store_credits
+ attr_accessor :store_credit_amount, :remove_store_credits
+
+ # the check for user? below is to ensure we don't break the
+ # admin app when creating a new order from the admin console
+ # In that case, we create an order before assigning a user
+ before_save :process_store_credit, :if => "self.user.present? && @store_credit_amount"
+ after_save :ensure_sufficient_credit, :if => "self.user.present?"
+
+ def store_credit_amount
+ adjustments.store_credits.sum(:amount).abs
+ end
+
+
+ # override core process payments to force payment present
+ # in case store credits were destroyed by ensure_sufficient_credit
+ def process_payments!
+ if total > 0 && payment.nil?
+ false
+ else
+ ret = payments.each(&:process!)
+ end
+ end
+
+
+ private
+
+ # credit or update store credit adjustment to correct value if amount specified
+ #
+ def process_store_credit
+ @store_credit_amount = BigDecimal.new(@store_credit_amount.to_s).round(2)
+
+ # store credit can't be greater than order total (not including existing credit), or the users available credit
+ @store_credit_amount = [@store_credit_amount, user.store_credits_total, (total + store_credit_amount.abs)].min
+
+ if @store_credit_amount <= 0
+ adjustments.store_credits.destroy_all
+ else
+ if sca = adjustments.store_credits.first
+ sca.update_attributes({:amount => -(@store_credit_amount)})
+ else
+ #create adjustment off association to prevent reload
+ sca = adjustments.store_credits.create(:label => I18n.t(:store_credit) , :amount => -(@store_credit_amount))
+ end
+ end
+
+ #recalc totals and ensure payment is set to new amount
+ update_totals
+ payment.amount = total if payment
+ end
+
+ # consume users store credit once the order has completed.
+ fsm = self.state_machines[:state]
+ fsm.after_transition :to => 'complete', :do => :consume_users_credit
+
+ def consume_users_credit
+ return unless completed?
+ credit_used = self.store_credit_amount
+
+ user.store_credits.each do |store_credit|
+ break if credit_used == 0
+ if store_credit.remaining_amount > 0
+ if store_credit.remaining_amount > credit_used
+ store_credit.remaining_amount -= credit_used
+ store_credit.save
+ credit_used = 0
+ else
+ credit_used -= store_credit.remaining_amount
+ store_credit.update_attribute(:remaining_amount, 0)
+ end
+ end
+ end
+
+ end
+
+ # ensure that user has sufficient credits to cover adjustments
+ #
+ def ensure_sufficient_credit
+ if user.store_credits_total < store_credit_amount
+ #user's credit does not cover all adjustments.
+ adjustments.store_credits.destroy_all
+
+ update!
+ end
+ end
+ end
+end
View
12 app/models/spree/promotion/actions/give_store_credit.rb
@@ -0,0 +1,12 @@
+module Spree
+ class Promotion::Actions::GiveStoreCredit < PromotionAction
+ preference :amount, :decimal, :default => 0.0
+
+ def perform(options = {})
+ if user = options[:user]
+ user.store_credits.create(:amount => preferred_amount, :remaining_amount => preferred_amount, :reason => "Promotion: #{promotion.name}")
+ else
+ end
+ end
+ end
+end
View
9 app/models/spree/store_credit.rb
@@ -0,0 +1,9 @@
+module Spree
+ class StoreCredit < ActiveRecord::Base
+ validates :amount, :presence => true, :numericality => true
+ validates :reason, :presence => true
+ validates :user, :presence => true
+
+ belongs_to :user
+ end
+end
View
5 app/models/spree/store_credit_adjustment.rb
@@ -0,0 +1,5 @@
+module Spree
+ class StoreCreditAdjustment < Adjustment
+
+ end
+end
View
13 app/models/spree/user_decorator.rb
@@ -0,0 +1,13 @@
+module Spree
+ User.class_eval do
+ has_many :store_credits
+
+ def has_store_credit?
+ store_credits_total > 0
+ end
+
+ def store_credits_total
+ store_credits.sum(:remaining_amount)
+ end
+ end
+end
View
7 app/models/store_credit.rb
@@ -1,7 +0,0 @@
-class StoreCredit < ActiveRecord::Base
- validates :amount, :presence => true, :numericality => true
- validates :reason, :presence => true
- validates :user, :presence => true
-
- belongs_to :user
-end
View
3 app/models/store_credit_adjustment.rb
@@ -1,3 +0,0 @@
-class StoreCreditAdjustment < Adjustment
-
-end
View
11 app/models/user_decorator.rb
@@ -1,11 +0,0 @@
-User.class_eval do
- has_many :store_credits
-
- def has_store_credit?
- store_credits_total > 0
- end
-
- def store_credits_total
- store_credits.sum(:remaining_amount)
- end
-end
View
24 app/overrides/views_decorator.rb
@@ -1,39 +1,27 @@
Deface::Override.new(
- :virtual_path => "admin/configurations/index",
+ :virtual_path => "spree/admin/configurations/index",
:name => "store_credits_admin_configurations_menu",
:insert_bottom => "[data-hook='admin_configurations_menu']",
:text => "<%= configurations_menu_item(I18n.t('store_credits'), admin_store_credits_url, I18n.t('manage_store_credits')) %>",
:disabled => false)
Deface::Override.new(
- :virtual_path => "admin/users/index",
+ :virtual_path => "spree/admin/users/index",
:name => "store_credits_admin_users_index_row_actions",
:insert_bottom => "[data-hook='admin_users_index_row_actions']",
:text => "&nbsp;<%= link_to_with_icon('add', t('add_store_credit'), new_admin_user_store_credit_url(user)) %>",
:disabled => false)
Deface::Override.new(
- :virtual_path => "checkout/_payment",
+ :virtual_path => "spree/checkout/_payment",
:name => "store_credits_checkout_payment_step",
:insert_after => "[data-hook='checkout_payment_step']",
- :partial => "checkout/store_credits",
+ :partial => "spree/checkout/store_credits",
:disabled => false)
Deface::Override.new(
- :virtual_path => "users/show",
+ :virtual_path => "spree/users/show",
:name => "store_credits_account_my_orders",
:insert_after => "[data-hook='account_my_orders']",
- :partial => "users/store_credits",
- :disabled => false)
-
-Deface::Override.new(
- :virtual_path => "shared/_order_details",
- :name => "store_credits_order_details_adjustments",
- :insert_after => "[data-hook='order_details_adjustments']",
- :text => "
- <% if @order.store_credits.present? && !@order.completed? %>
- <tr><td colspan=\"4\">
- <%= check_box :order, :remove_store_credits %> <%= label :order, :remove_store_credits %>
- </td></tr>
- <% end %>",
+ :partial => "spree/users/store_credits",
:disabled => false)
View
10 app/views/admin/store_credits/edit.html.erb
@@ -1,10 +0,0 @@
-<%= render :partial => 'admin/shared/configuration_menu' %>
-
-<h1><%=t("editing_store_credit")%></h1>
-
-<%= render 'shared/error_messages', :target => @store_credit %>
-
-<%= form_for(:store_credit, :url => object_url, :html => { :method => :put }) do |f| %>
- <%= render :partial => "form", :locals => { :f => f } %>
- <%= render :partial => "admin/shared/edit_resource_links" %>
-<% end %>
View
1 app/views/admin/store_credits/show.html.erb
@@ -1 +0,0 @@
-<%= render :partial => 'admin/shared/configuration_menu' %>
View
0 app/views/admin/store_credits/_form.html.erb → .../spree/admin/store_credits/_form.html.erb
File renamed without changes.
View
10 app/views/spree/admin/store_credits/edit.html.erb
@@ -0,0 +1,10 @@
+<%= render :partial => 'spree/admin/shared/configuration_menu' %>
+
+<h1><%=t("editing_store_credit")%></h1>
+
+<%= render 'spree/shared/error_messages', :target => @store_credit %>
+
+<%= form_for(:store_credit, :url => object_url, :html => { :method => :put }) do |f| %>
+ <%= render :partial => "form", :locals => { :f => f } %>
+ <%= render :partial => "spree/admin/shared/edit_resource_links" %>
+<% end %>
View
2 app/views/admin/store_credits/index.html.erb → .../spree/admin/store_credits/index.html.erb
@@ -1,4 +1,4 @@
-<%= render :partial => 'admin/shared/configuration_menu' %>
+<%= render :partial => 'spree/admin/shared/configuration_menu' %>
<h1><%= t("listing_store_credits") %></h1>
<table class="index">
View
6 app/views/admin/store_credits/new.html.erb → ...ws/spree/admin/store_credits/new.html.erb
@@ -1,11 +1,11 @@
-<%= render :partial => 'admin/shared/configuration_menu' %>
+<%= render :partial => 'spree/admin/shared/configuration_menu' %>
<h1><%=t("new_store_credit")%></h1>
-<%= render 'shared/error_messages', :target => @store_credit %>
+<%= render 'spree/shared/error_messages', :target => @store_credit %>
<%= form_for(:store_credit, :url => admin_user_store_credits_url(params[:user_id])) do |f| %>
<%= f.hidden_field :user_id, :value => params[:user_id] %>
<%= render :partial => "form", :locals => { :f => f } %>
- <%= render :partial => "admin/shared/new_resource_links" %>
+ <%= render :partial => "spree/admin/shared/new_resource_links" %>
<% end %>
View
1 app/views/spree/admin/store_credits/show.html.erb
@@ -0,0 +1 @@
+<%= render :partial => 'spree/admin/shared/configuration_menu' %>
View
0 app/views/checkout/_store_credits.html.erb → ...ws/spree/checkout/_store_credits.html.erb
File renamed without changes.
View
33 app/views/spree/users/_store_credits.html.erb
@@ -0,0 +1,33 @@
+<% if @user.has_store_credit? %>
+ <h2><%= t("store_credits") %></h2>
+ <p>
+ <%= t('current_store_credit') %>: <strong><%= number_to_currency @user.store_credits_total %></strong>
+ </p>
+ <% if @orders_with_store_credit.present? %>
+ <h3><%= t('orders_with_store_credit') %></h3>
+ <table class="order-summary" width="545">
+ <thead>
+ <tr>
+ <th><%= t("order_number") %></th>
+ <th><%= t("order_date") %></th>
+ <th><%= t("status") %></th>
+ <th><%= t("customer") %></th>
+ <th><%= t("total") %></th>
+ <th><%= t("store_credit") %></th>
+ </tr>
+ </thead>
+ <tbody>
+ <% @orders_with_store_credit.each do |order| %>
+ <tr class="<%= cycle('even', 'odd') %>">
+ <td><%= link_to order.number, order_url(order) %></td>
+ <td><%=order.created_at.to_date%></td>
+ <td><%= t(order.state).titleize %></td>
+ <td><%= order.user.email if order.user %></td>
+ <td><%= number_to_currency order.total %></td>
+ <td><%= number_to_currency order.store_credit_amount %></td>
+ </tr>
+ <% end %>
+ </tbody>
+ </table>
+ <% end %>
+<% end %>
View
33 app/views/users/_store_credits.html.erb
@@ -1,33 +0,0 @@
-<% if @user.has_store_credit? %>
-<h2><%= t("store_credits") %></h2>
-<p>
-<%= t('current_store_credit') %>: <strong><%= number_to_currency @user.store_credits_total %></strong>
-</p>
-<% if @orders_with_store_credit.present? %>
-<h3><%= t('orders_with_store_credit') %></h3>
-<table class="order-summary" width="545">
- <thead>
- <tr>
- <th><%= t("order_number") %></th>
- <th><%= t("order_date") %></th>
- <th><%= t("status") %></th>
- <th><%= t("customer") %></th>
- <th><%= t("total") %></th>
- <th><%= t("store_credit") %></th>
- </tr>
- </thead>
- <tbody>
- <% @orders_with_store_credit.each do |order| %>
- <tr class="<%= cycle('even', 'odd') %>">
- <td><%= link_to order.number, order_url(order) %></td>
- <td><%=order.created_at.to_date%></td>
- <td><%= t(order.state).titleize %></td>
- <td><%= order.user.email if order.user %></td>
- <td><%= number_to_currency order.total %></td>
- <td><%= number_to_currency order.store_credit_amount %></td>
- </tr>
- <% end %>
- </tbody>
-</table>
-<% end %>
-<% end %>
View
4 config/routes.rb
@@ -1,10 +1,8 @@
-Rails.application.routes.draw do
-
+Spree::Core::Engine.routes.append do
namespace :admin do
resources :store_credits
resources :users do
resources :store_credits
end
end
-
end
View
0 ...te/20100928140217_create_store_credits.rb → ...te/20100928140217_create_store_credits.rb
File renamed without changes.
View
5 db/migrate/20120127100416_namespace_tables.rb
@@ -0,0 +1,5 @@
+class NamespaceTables < ActiveRecord::Migration
+ def change
+ rename_table :store_credits, :spree_store_credits
+ end
+end
View
20 lib/generators/spree_store_credits/install_generator.rb
@@ -1,18 +1,18 @@
module SpreeStoreCredits
module Generators
class InstallGenerator < Rails::Generators::Base
- source_root File.expand_path("../../templates", __FILE__)
-
- desc "Configures your Rails application for use with spree_store_credits"
-
- def copy_migrations
- directory "db"
+ def add_migrations
+ run 'bundle exec rake railties:install:migrations FROM=spree_store_credits'
end
-# def copy_public
-# directory "public"
-# end
-
+ def run_migrations
+ res = ask "Would you like to run the migrations now? [Y/n]"
+ if res == "" || res.downcase == "y"
+ run 'bundle exec rake db:migrate'
+ else
+ puts "Skiping rake db:migrate, don't forget to run it!"
+ end
+ end
end
end
end
View
17 lib/spree_store_credits.rb
@@ -1,20 +1,27 @@
-require 'spree_core'
-require 'spree_promo'
+require 'spree'
module SpreeStoreCredits
class Engine < Rails::Engine
+ engine_name = 'spree_store_credits'
+
+ # use rspec for tests
+ config.generators do |g|
+ g.test_framework :rspec
+ end
+
def self.activate
Dir.glob(File.join(File.dirname(__FILE__), "../app/**/*_decorator*.rb")) do |c|
Rails.env == "production" ? require(c) : load(c)
end
end
+ initializer 'spree_store_credits.register.promotion.actions', :after => 'spree.promo.register.promotions.actions' do |app|
+ app.config.spree.promotions.actions << Spree::Promotion::Actions::GiveStoreCredit
+ end
+
config.to_prepare &method(:activate).to_proc
config.autoload_paths += %W(#{config.root}/lib)
- initializer "spree.promo.register.promotions.actions" do |app|
- app.config.spree.promotions.actions.concat([Promotion::Actions::GiveStoreCredit])
- end
end
end
View
5 script/rails
@@ -0,0 +1,5 @@
+#!/usr/bin/env ruby
+# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
+
+ENGINE_PATH = File.expand_path('../..', __FILE__)
+load File.expand_path('../../spec/dummy/script/rails', __FILE__)
View
4 spec/factories/store_credits_factory.rb
@@ -1,9 +1,9 @@
# this :promotion factory is defined in spree_promo, but I can't reuse it (i believe) b/c it is in spec/factories vs. lib/....
-Factory.define :promotion, :class => Promotion, :parent => :activator do |f|
+Factory.define :promotion, :class => Spree::Promotion, :parent => :activator do |f|
f.name 'Promo'
end
-Factory.define :give_store_credit_action, :class => Promotion::Actions::GiveStoreCredit do |f|
+Factory.define :give_store_credit_action, :class => Spree::Promotion::Actions::GiveStoreCredit do |f|
f.association :promotion
f.after_create do |action|
View
198 spec/models/order_spec.rb
@@ -1,198 +0,0 @@
-require 'spec_helper'
-
-describe Order do
- let(:user) { mock_model User, :email => 'spree@example.com', :store_credits_total => 45.00 }
- let(:line_item) { mock_model(LineItem, :variant => mock('variant'), :quantity => 5, :price => 10) }
- let(:order) { Order.create() }
-
- before { order.stub(:user => user, :total => 50 ) }
-
- context "process_store_credit" do
- it "should create store credit adjustment when user has sufficient credit" do
- order.store_credit_amount = 5.0
- order.save
- order.store_credits.size.should == 1
- order.store_credit_amount.should == 5.0
- end
-
- it "should only create adjustment with amount equal to users total credit" do
- order.store_credit_amount = 50.0
- order.save
- order.store_credit_amount.should == 45.00
- end
-
- it "should only create adjusment with amount equal to order total" do
- user.stub(:store_credits_total => 100.0)
- order.store_credit_amount = 90.0
- order.save
- order.store_credit_amount.should == 50.00
- end
-
- it "should not create adjustment when you does not have any credit" do
- user.stub(:store_credits_total => 0.0)
- order.store_credit_amount = 5.0
- order.save
- order.store_credits.size.should == 0
- order.store_credit_amount.should == 0.0
- end
-
- it "should update order totals if credit is applied" do
- order.should_receive(:update_totals)
- order.store_credit_amount = 5.0
- order.save
- end
-
- it "should update payment amount if credit is applied" do
- order.stub(:payment => mock('payment'))
- order.payment.should_receive(:amount=)
- order.store_credit_amount = 5.0
- order.save
- end
-
- it "should create negative adjustment" do
- order.store_credit_amount = 5.0
- order.save
- order.adjustments[0].amount.should == -5.0
- end
-
- it "should process credits if order total is already zero" do
- order.stub(:total => 0)
- order.store_credit_amount = 5.0
- order.should_receive(:process_store_credit)
- order.save
- order.store_credits.size.should == 0
- order.store_credit_amount.should == 0.0
- end
-
- context "with an existing adjustment" do
- before { order.adjustments.create(:source_type => "StoreCredit", :label => I18n.t(:store_credit) , :amount => -10) }
-
- it "should decrease existing adjustment if specific amount is less than adjustment amount" do
- order.store_credit_amount = 5.0
- order.save
- order.store_credits.size.should == 1
- order.store_credit_amount.should == 5.0
- end
-
- it "should increase existing adjustment if specified amount is greater than adjustment amount" do
- order.store_credit_amount = 25.0
- order.save
- order.store_credits.size.should == 1
- order.store_credit_amount.should == 25.0
- end
-
- it "should destroy the adjustment if specified amount is zero" do
- order.store_credit_amount = 0.0
- order.save
- order.store_credits.size.should == 0
- order.store_credit_amount.should == 0.0
- end
-
- it "should decrease existing adjustment when existing credit amount is equal to the order total" do
- order.stub(:total => 10)
- order.store_credit_amount = 5.0
- order.save
- order.store_credits.size.should == 1
- order.store_credit_amount.should == 5.0
- end
- end
-
- end
-
- context "store_credit_amount" do
- it "should return total for all store credit adjustments applied to order" do
- order.adjustments.create(:source_type => "StoreCredit", :label => I18n.t(:store_credit) , :amount => -10)
- order.adjustments.create(:source_type => "StoreCredit", :label => I18n.t(:store_credit) , :amount => -5)
-
- order.store_credit_amount.should == 15
- end
- end
-
- context "consume_users_credit" do
- let(:store_credit_1) { mock_model(StoreCredit, :amount => 100, :remaining_amount => 100) }
- let(:store_credit_2) { mock_model(StoreCredit, :amount => 10, :remaining_amount => 5) }
- let(:store_credit_3) { mock_model(StoreCredit, :amount => 60, :remaining_amount => 50 ) }
- before { order.stub(:completed? => true, :store_credit_amount => 35) }
-
- it "should reduce remaining amount on a single credit when that credit satisfies the entire amount" do
- user.stub(:store_credits => [store_credit_1])
- store_credit_1.should_receive(:remaining_amount=).with(65)
- store_credit_1.should_receive(:save)
- order.send(:consume_users_credit)
- end
-
- it "should reduce remaining amount on a mutliple creidts when a single credit does not satify the entire amount" do
- order.stub(:store_credit_amount => 55)
- user.stub(:store_credits => [store_credit_2, store_credit_3])
- store_credit_2.should_receive(:update_attribute).with(:remaining_amount, 0)
- store_credit_3.should_receive(:update_attribute).with(:remaining_amount, 0)
- order.send(:consume_users_credit)
- end
-
- it "should call consume_users_credit after transition to complete" do
- order = Order.new()
- order.state = "confirm"
- order.should_receive(:consume_users_credit).at_least(1).times
- order.next!
- end
-
- end
-
-
- context "ensure_sufficient_credit" do
- let(:payment) { mock_model(Payment, :checkout? => true, :amount => 50)}
- before do
- order.adjustments.create(:source_type => "StoreCredit", :label => I18n.t(:store_credit) , :amount => -10)
- order.stub(:completed? => true, :store_credit_amount => 35, :payment => payment )
-
- end
-
- it "should do nothing when user has credits" do
- order.store_credits.should_not_receive(:destroy_all)
- order.payment.should_not_receive(:update_attributes_without_callbacks)
- order.send(:ensure_sufficient_credit)
- end
-
- context "when user no longer has sufficient credit to cover entire credit amount" do
- before do
- payment.stub(:amount => 40)
- user.stub(:store_credits_total => 0.0)
- end
-
- it "should destory all store credit adjustments" do
- order.payment.stub(:update_attributes_without_callbacks)
- order.store_credits.should_receive(:destroy_all)
- order.send(:ensure_sufficient_credit)
- end
-
- it "should update payment" do
- order.payment.should_receive(:update_attributes_without_callbacks).with(:amount => 50)
- order.send(:ensure_sufficient_credit)
- end
- end
-
- end
-
- context "process_payments!" do
- it "should return false when total is greater than zero and payment is nil" do
- order.process_payments!.should be_false
- end
-
- it "should return true when total is zero and payment is nil" do
- order.stub(:total => 0.0)
- order.process_payments!.should be_true
- end
-
- it "should return true when total is zero and payment is not nil" do
- order.stub(:payment => mock_model(Payment, :process! => true))
- order.process_payments!.should be_true
- end
-
- it "should process payment when total is zero and payment is not nil" do
- order.stub(:payments => [mock_model(Payment)])
- order.payment.should_receive(:process!)
- order.process_payments!
- end
-
- end
-end
View
200 spec/models/spree/order_spec.rb
@@ -0,0 +1,200 @@
+require 'spec_helper'
+
+module Spree
+ describe Order do
+ let(:user) { mock_model User, :email => 'spree@example.com', :store_credits_total => 45.00 }
+ let(:line_item) { mock_model(LineItem, :variant => mock('variant'), :quantity => 5, :price => 10) }
+ let(:order) { Order.create() }
+
+ before { order.stub(:user => user, :total => 50 ) }
+
+ context "process_store_credit" do
+ it "should create store credit adjustment when user has sufficient credit" do
+ order.store_credit_amount = 5.0
+ order.save
+ order.adjustments.store_credits.size.should == 1
+ order.store_credit_amount.should == 5.0
+ end
+
+ it "should only create adjustment with amount equal to users total credit" do
+ order.store_credit_amount = 50.0
+ order.save
+ order.store_credit_amount.should == 45.00
+ end
+
+ it "should only create adjusment with amount equal to order total" do
+ user.stub(:store_credits_total => 100.0)
+ order.store_credit_amount = 90.0
+ order.save
+ order.store_credit_amount.should == 50.00
+ end
+
+ it "should not create adjustment when you does not have any credit" do
+ user.stub(:store_credits_total => 0.0)
+ order.store_credit_amount = 5.0
+ order.save
+ order.adjustments.store_credits.size.should == 0
+ order.store_credit_amount.should == 0.0
+ end
+
+ it "should update order totals if credit is applied" do
+ order.should_receive(:update_totals)
+ order.store_credit_amount = 5.0
+ order.save
+ end
+
+ it "should update payment amount if credit is applied" do
+ order.stub(:payment => mock('payment'))
+ order.payment.should_receive(:amount=)
+ order.store_credit_amount = 5.0
+ order.save
+ end
+
+ it "should create negative adjustment" do
+ order.store_credit_amount = 5.0
+ order.save
+ order.adjustments[0].amount.should == -5.0
+ end
+
+ it "should process credits if order total is already zero" do
+ order.stub(:total => 0)
+ order.store_credit_amount = 5.0
+ order.should_receive(:process_store_credit)
+ order.save
+ order.adjustments.store_credits.size.should == 0
+ order.store_credit_amount.should == 0.0
+ end
+
+ context "with an existing adjustment" do
+ before { order.adjustments.store_credits.create(:label => I18n.t(:store_credit) , :amount => -10) }
+
+ it "should decrease existing adjustment if specific amount is less than adjustment amount" do
+ order.store_credit_amount = 5.0
+ order.save
+ order.adjustments.store_credits.size.should == 1
+ order.store_credit_amount.should == 5.0
+ end
+
+ it "should increase existing adjustment if specified amount is greater than adjustment amount" do
+ order.store_credit_amount = 25.0
+ order.save
+ order.adjustments.store_credits.size.should == 1
+ order.store_credit_amount.should == 25.0
+ end
+
+ it "should destroy the adjustment if specified amount is zero" do
+ order.store_credit_amount = 0.0
+ order.save
+ order.adjustments.store_credits.size.should == 0
+ order.store_credit_amount.should == 0.0
+ end
+
+ it "should decrease existing adjustment when existing credit amount is equal to the order total" do
+ order.stub(:total => 10)
+ order.store_credit_amount = 5.0
+ order.save
+ order.adjustments.store_credits.size.should == 1
+ order.store_credit_amount.should == 5.0
+ end
+ end
+
+ end
+
+ context "store_credit_amount" do
+ it "should return total for all store credit adjustments applied to order" do
+ order.adjustments.store_credits.create(:label => I18n.t(:store_credit) , :amount => -10)
+ order.adjustments.store_credits.create(:label => I18n.t(:store_credit) , :amount => -5)
+
+ order.store_credit_amount.should == BigDecimal.new('15')
+ end
+ end
+
+ context "consume_users_credit" do
+ let(:store_credit_1) { mock_model(StoreCredit, :amount => 100, :remaining_amount => 100) }
+ let(:store_credit_2) { mock_model(StoreCredit, :amount => 10, :remaining_amount => 5) }
+ let(:store_credit_3) { mock_model(StoreCredit, :amount => 60, :remaining_amount => 50 ) }
+ before { order.stub(:completed? => true, :store_credit_amount => 35) }
+
+ it "should reduce remaining amount on a single credit when that credit satisfies the entire amount" do
+ user.stub(:store_credits => [store_credit_1])
+ store_credit_1.should_receive(:remaining_amount=).with(65)
+ store_credit_1.should_receive(:save)
+ order.send(:consume_users_credit)
+ end
+
+ it "should reduce remaining amount on a mutliple creidts when a single credit does not satify the entire amount" do
+ order.stub(:store_credit_amount => 55)
+ user.stub(:store_credits => [store_credit_2, store_credit_3])
+ store_credit_2.should_receive(:update_attribute).with(:remaining_amount, 0)
+ store_credit_3.should_receive(:update_attribute).with(:remaining_amount, 0)
+ order.send(:consume_users_credit)
+ end
+
+ it "should call consume_users_credit after transition to complete" do
+ order = Order.new()
+ order.state = "confirm"
+ order.should_receive(:consume_users_credit).at_least(1).times
+ order.next!
+ end
+
+ end
+
+
+ context "ensure_sufficient_credit" do
+ let(:payment) { mock_model(Payment, :checkout? => true, :amount => 50)}
+ before do
+ order.adjustments.store_credits.create(:label => I18n.t(:store_credit) , :amount => -10)
+ order.stub(:completed? => true, :store_credit_amount => 35, :payment => payment )
+
+ end
+
+ it "should do nothing when user has credits" do
+ order.adjustments.store_credits.should_not_receive(:destroy_all)
+ order.payment.should_not_receive(:update_attributes_without_callbacks)
+ order.send(:ensure_sufficient_credit)
+ end
+
+ context "when user no longer has sufficient credit to cover entire credit amount" do
+ before do
+ payment.stub(:amount => 40)
+ user.stub(:store_credits_total => 0.0)
+ end
+
+ it "should destory all store credit adjustments" do
+ order.payment.stub(:update_attributes_without_callbacks)
+ order.send(:ensure_sufficient_credit)
+ order.adjustments.store_credits.size.should == 0
+ end
+
+ it "should update payment" do
+ order.payment.should_receive(:update_attributes_without_callbacks).with(:amount => 50)
+ order.send(:ensure_sufficient_credit)
+ end
+ end
+
+ end
+
+ context "process_payments!" do
+ it "should return false when total is greater than zero and payment is nil" do
+ order.process_payments!.should be_false
+ end
+
+ it "should return true when total is zero and payment is nil" do
+ order.stub(:total => 0.0)
+ order.process_payments!.should be_true
+ end
+
+ it "should return true when total is zero and payment is not nil" do
+ order.stub(:payment => mock_model(Payment, :process! => true))
+ order.process_payments!.should be_true
+ end
+
+ it "should process payment when total is zero and payment is not nil" do
+ order.stub(:payments => [mock_model(Payment)])
+ order.payment.should_receive(:process!)
+ order.process_payments!
+ end
+
+ end
+ end
+end
View
18 spec/models/spree/user_spec.rb
@@ -0,0 +1,18 @@
+require 'spec_helper'
+
+module Spree
+ describe User do
+ let(:user) { User.create(:email => "foo@bar.com", :password => "secret", :password_confirmation => "secret") }
+
+ context "store_credits_total" do
+ before do
+ user.store_credits.create(:amount => 100, :remaining_amount => 100, :reason => "A")
+ user.store_credits.create(:amount => 60, :remaining_amount => 55, :reason => "B")
+ end
+
+ it "should return the total remaining amount for users store credits" do
+ user.store_credits_total.should == 155.00
+ end
+ end
+ end
+end
View
16 spec/models/user_spec.rb
@@ -1,16 +0,0 @@
-require 'spec_helper'
-
-describe User do
- let(:user) { User.create(:email => "foo@bar.com", :password => "secret", :password_confirmation => "secret") }
-
- context "store_credits_total" do
- before do
- user.store_credits.create(:amount => 100, :remaining_amount => 100, :reason => "A")
- user.store_credits.create(:amount => 60, :remaining_amount => 55, :reason => "B")
- end
-
- it "should return the total remaining amount for users store credits" do
- user.store_credits_total.should == 155.00
- end
- end
-end
View
19 spec/requests/spree/store_credits_spec.rb
@@ -0,0 +1,19 @@
+require 'spec_helper'
+
+module Spree
+ describe "Promotion for Store Credits" do
+
+ context "#new user" do
+ it "should give me a store credit when I register" do
+
+ Factory(:promotion_for_store_credits, :event_name => "spree.user.signup")
+
+ new_user = Factory.build(:user)
+
+ post spree.user_registration_path, {"commit"=>"Create", "user"=> {"password" => new_user.password, "email" => new_user.email }}
+ new_user = User.find_by_email new_user.email
+ new_user.store_credits.size.should == 1
+ end
+ end
+ end
+end
View
30 spec/requests/store_credits_spec.rb
@@ -1,30 +0,0 @@
-require 'spec_helper'
-
-describe "Promotion for Store Credits" do
-
- before(:all) do
- DatabaseCleaner.strategy = :truncation
- DatabaseCleaner.clean
- end
-
- before(:each) do
- DatabaseCleaner.start
- end
-
- after(:each) do
- DatabaseCleaner.clean
- end
-
- context "#new user" do
- it "should give me a store credit when I register" do
-
- Factory(:promotion_for_store_credits, :event_name => "spree.user.signup")
-
- new_user = Factory.build(:user)
-
- post user_registration_path, {"commit"=>"Create", "user"=> {"password" => new_user.password, "email" => new_user.email }}
- new_user = User.find_by_email new_user.email
- new_user.store_credits.size.should == 1
- end
- end
-end
View
57 spec/spec_helper.rb
@@ -1,27 +1,24 @@
-# from the project root directory.
-ENV["RAILS_ENV"] ||= 'test'
-require File.expand_path("../test_app/config/environment", __FILE__)
-require 'rspec/rails'
+# Configure Rails Environment
+ENV["RAILS_ENV"] = "test"
-require 'database_cleaner'
+require File.expand_path("../dummy/config/environment.rb", __FILE__)
-# Requires supporting files with custom matchers and macros, etc,
-# in ./support/ and its subdirectories.
-Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
+require 'rspec/rails'
+require 'factory_girl'
+require 'spree/url_helpers'
+require 'database_cleaner'
-require 'spree_core/testing_support/factories'
+# Requires supporting ruby files with custom matchers and macros, etc,
+# in spec/support/ and its subdirectories.
+Dir[File.join(File.dirname(__FILE__), "support/**/*.rb")].each {|f| require f }
# include local factories
Dir["#{File.dirname(__FILE__)}/factories/**/*.rb"].each { |f| require File.expand_path(f)}
+# Requires factories defined in spree_core
+require 'spree/core/testing_support/factories'
+
RSpec.configure do |config|
- # == Mock Framework
- #
- # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
- #
- # config.mock_with :mocha
- # config.mock_with :flexmock
- # config.mock_with :rr
config.mock_with :rspec
config.fixture_path = "#{::Rails.root}/spec/fixtures"
@@ -30,19 +27,23 @@
# examples within a transaction, comment the following line or assign false
# instead of true.
config.use_transactional_fixtures = false
-end
-
-# https://groups.google.com/forum/m/#!msg/ruby-capybara/JI6JrirL9gM/R6YiXj4gi_UJ
+ config.before(:each) do
+ if example.metadata[:js]
+ DatabaseCleaner.strategy = :truncation, { :except => ['spree_countries', 'spree_zones', 'spree_zone_members', 'spree_states', 'spree_roles'] }
+ else
+ DatabaseCleaner.strategy = :transaction
+ end
+ end
-class ActiveRecord::Base
- mattr_accessor :shared_connection
- @@shared_connection = nil
+ config.before(:each) do
+ DatabaseCleaner.start
+ end
- def self.connection
- @@shared_connection || retrieve_connection
+ config.after(:each) do
+ DatabaseCleaner.clean
end
-end
-# Forces all threads to share the same connection. This works on
-# Capybara because it starts the web server in a thread.
-ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection
+ config.include Spree::UrlHelpers
+ config.include Devise::TestHelpers, :type => :controller
+ config.include Rack::Test::Methods, :type => :requests
+end
View
9 spree_store_credits.gemspec
@@ -17,6 +17,13 @@ Gem::Specification.new do |s|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
s.require_paths = ["lib"]
- s.add_dependency('spree_core', '>= 0.30.1')
+ s.add_dependency 'spree', '~> 1.0.0.rc2'
+
+ s.add_development_dependency 'capybara', '1.0.1'
+ s.add_development_dependency 'ffaker'
+ s.add_development_dependency 'rspec-rails', '~> 2.7'
+ s.add_development_dependency 'sqlite3'
+ s.add_development_dependency 'factory_girl_rails', '~> 1.5.0'
+ s.add_development_dependency 'database_cleaner'
end

0 comments on commit 5f8ead5

Please sign in to comment.