spree_user_groups 0.40.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/.gitignore +11 -0
  2. data/LICENSE +23 -0
  3. data/README.md +17 -0
  4. data/Rakefile +77 -0
  5. data/app/controllers/admin/user_groups_controller.rb +18 -0
  6. data/app/controllers/checkout_controller_decorator.rb +9 -0
  7. data/app/models/calculator/advanced_flat_percent.rb +47 -0
  8. data/app/models/order_decorator.rb +14 -0
  9. data/app/models/product_decorator.rb +5 -0
  10. data/app/models/user_decorator.rb +10 -0
  11. data/app/models/user_group.rb +15 -0
  12. data/app/models/variant_decorator.rb +9 -0
  13. data/app/views/admin/user_groups/_form.html.erb +5 -0
  14. data/app/views/admin/user_groups/edit.html.erb +10 -0
  15. data/app/views/admin/user_groups/index.html.erb +39 -0
  16. data/app/views/admin/user_groups/new.html.erb +10 -0
  17. data/app/views/admin/user_groups/show.html.erb +1 -0
  18. data/app/views/admin/users/_user_group.html.erb +9 -0
  19. data/config/locales/en.yml +17 -0
  20. data/config/routes.rb +5 -0
  21. data/db/migrate/20110207075544_create_user_groups.rb +17 -0
  22. data/features/checkout.feature +57 -0
  23. data/features/step_definitions/user_group_steps.rb +4 -0
  24. data/features/support/env.rb +22 -0
  25. data/features/support/paths.rb +43 -0
  26. data/lib/spree_user_groups.rb +26 -0
  27. data/lib/spree_user_groups_hooks.rb +6 -0
  28. data/lib/tasks/install.rake +25 -0
  29. data/lib/tasks/spree_user_groups.rake +1 -0
  30. data/spec/factories.rb +0 -0
  31. data/spec/factories/user_group_factory.rb +3 -0
  32. data/spec/models/calculator/advanced_flat_percent_spec.rb +58 -0
  33. data/spec/models/user_group_spec.rb +21 -0
  34. data/spec/models/user_spec.rb +9 -0
  35. data/spec/spec_helper.rb +33 -0
  36. data/spree_user_groups.gemspec +23 -0
  37. metadata +126 -0
@@ -0,0 +1,11 @@
1
+ \#*
2
+ *~
3
+ .#*
4
+ .DS_Store
5
+ .idea
6
+ .project
7
+ tmp
8
+ nbproject
9
+ *.swp
10
+ spec/test_app
11
+ Gemfile
data/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ Redistribution and use in source and binary forms, with or without modification,
2
+ are permitted provided that the following conditions are met:
3
+
4
+ * Redistributions of source code must retain the above copyright notice,
5
+ this list of conditions and the following disclaimer.
6
+ * Redistributions in binary form must reproduce the above copyright notice,
7
+ this list of conditions and the following disclaimer in the documentation
8
+ and/or other materials provided with the distribution.
9
+ * Neither the name of the Rails Dog LLC nor the names of its
10
+ contributors may be used to endorse or promote products derived from this
11
+ software without specific prior written permission.
12
+
13
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
14
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
15
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
16
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
22
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,17 @@
1
+ SpreeUserGroups
2
+ ===============
3
+
4
+ Introduces user groups and calculator to add adjustment for specified user group.
5
+
6
+
7
+ Installation
8
+ ============
9
+
10
+ Add `gem "spree_user_groups", :git => "git://github.com/romul/spree_user_groups.git"`
11
+ Run `bundle install`
12
+ Run `rake spree_user_groups:install`
13
+ Run `rake db:migrate`
14
+
15
+
16
+
17
+ Copyright (c) 2011 Roman Smirnov, released under the New BSD License
@@ -0,0 +1,77 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+ require 'rake/packagetask'
5
+ require 'rake/gempackagetask'
6
+
7
+ gemfile = File.expand_path('../spec/test_app/Gemfile', __FILE__)
8
+ if File.exists?(gemfile) && (%w(spec cucumber).include?(ARGV.first.to_s) || ARGV.size == 0)
9
+ require 'bundler'
10
+ ENV['BUNDLE_GEMFILE'] = gemfile
11
+ Bundler.setup
12
+
13
+ require 'rspec'
14
+ require 'rspec/core/rake_task'
15
+ RSpec::Core::RakeTask.new
16
+
17
+ require 'cucumber/rake/task'
18
+ Cucumber::Rake::Task.new do |t|
19
+ t.cucumber_opts = %w{--format progress}
20
+ end
21
+ end
22
+
23
+ desc "Default Task"
24
+ task :default => [:spec, :cucumber ]
25
+
26
+ spec = eval(File.read('spree_user_groups.gemspec'))
27
+
28
+ Rake::GemPackageTask.new(spec) do |p|
29
+ p.gem_spec = spec
30
+ end
31
+
32
+ desc "Release to gemcutter"
33
+ task :release => :package do
34
+ require 'rake/gemcutter'
35
+ Rake::Gemcutter::Tasks.new(spec).define
36
+ Rake::Task['gem:push'].invoke
37
+ end
38
+
39
+ desc "Default Task"
40
+ task :default => [ :spec ]
41
+
42
+ desc "Regenerates a rails 3 app for testing"
43
+ task :test_app do
44
+ require '../spree/lib/generators/spree/test_app_generator'
45
+ class UserGroupsTestAppGenerator < Spree::Generators::TestAppGenerator
46
+
47
+ def install_gems
48
+ inside "test_app" do
49
+ run 'rake spree_core:install'
50
+ run 'rake spree_auth:install'
51
+ run 'rake spree_user_groups:install'
52
+ end
53
+ end
54
+
55
+ def migrate_db
56
+ run_migrations
57
+ end
58
+
59
+ protected
60
+ def full_path_for_local_gems
61
+ <<-gems
62
+ gem 'spree_core', :path => \'#{File.join(File.dirname(__FILE__), "../spree/", "core")}\'
63
+ gem 'spree_auth', :path => \'#{File.join(File.dirname(__FILE__), "../spree/", "auth")}\'
64
+ gem 'spree_user_groups', :path => \'#{File.dirname(__FILE__)}\'
65
+ gems
66
+ end
67
+
68
+ end
69
+ UserGroupsTestAppGenerator.start
70
+ end
71
+
72
+ namespace :test_app do
73
+ desc 'Rebuild test and cucumber databases'
74
+ task :rebuild_dbs do
75
+ system("cd spec/test_app && rake db:drop db:migrate RAILS_ENV=test && rake db:drop db:migrate RAILS_ENV=cucumber")
76
+ end
77
+ end
@@ -0,0 +1,18 @@
1
+ class Admin::UserGroupsController < Admin::BaseController
2
+ resource_controller
3
+ before_filter :load_data
4
+
5
+ update.wants.html { redirect_to edit_object_url }
6
+ create.wants.html { redirect_to edit_object_url }
7
+ destroy.success.wants.js { render_js_for_destroy }
8
+
9
+ private
10
+ def build_object
11
+ @object ||= end_of_association_chain.send((parent? ? :build : :new), object_params)
12
+ @object.calculator = params[:user_group][:calculator_type].constantize.new if params[:user_group]
13
+ end
14
+
15
+ def load_data
16
+ @calculators = UserGroup.calculators
17
+ end
18
+ end
@@ -0,0 +1,9 @@
1
+ CheckoutController.class_eval do
2
+ private
3
+ def before_address
4
+ @order.bill_address ||= Address.new(:country => default_country)
5
+ @order.ship_address ||= Address.new(:country => default_country)
6
+
7
+ @order.user.create_adjustment_for(@order) if @order.user
8
+ end
9
+ end
@@ -0,0 +1,47 @@
1
+ class Calculator::AdvancedFlatPercent < Calculator
2
+ preference :flat_percent, :decimal, :default => 0
3
+ preference :based_on_cost_price, :boolean, :default => false
4
+
5
+ def self.description
6
+ I18n.t("advanced_flat_percent")
7
+ end
8
+
9
+ def self.register
10
+ super
11
+ UserGroup.register_calculator(self)
12
+ end
13
+
14
+ def compute(object)
15
+ return unless object.present? and object.line_items.present? and object.user.present?
16
+
17
+ part = self.preferred_flat_percent.abs / 100.0
18
+ item_total = object.line_items.map(&:amount).sum
19
+
20
+ if self.preferred_based_on_cost_price
21
+ item_cost_price_total = object.line_items.map do |li|
22
+ if !li.variant.cost_price.nil? && li.variant.cost_price > 0
23
+ li.variant.cost_price * li.quantity
24
+ else
25
+ li.amount
26
+ end
27
+ end.sum
28
+ (item_cost_price_total * (1 + part) - item_total).round(2)
29
+ else
30
+ (item_total * (-part)).round(2)
31
+ end
32
+ end
33
+
34
+ def compute_item(variant)
35
+ part = self.preferred_flat_percent.abs / 100.0
36
+
37
+ if self.preferred_based_on_cost_price
38
+ if !variant.cost_price.nil? && variant.cost_price > 0
39
+ variant.cost_price * (1 + part)
40
+ else
41
+ variant.price
42
+ end
43
+ else
44
+ variant.price * (1 - part)
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,14 @@
1
+ Order.class_eval do
2
+
3
+ # Associates the specified user with the order and destroys any previous association with guest user if necessary.
4
+ def associate_user!(user)
5
+ self.user = user
6
+ self.email = user.email
7
+
8
+ # Create adjustment for user group
9
+ self.user.create_adjustment_for(self)
10
+
11
+ # disable validations since this can cause issues when associating an incomplete address during the address step
12
+ save(:validate => false)
13
+ end
14
+ end
@@ -0,0 +1,5 @@
1
+ Product.class_eval do
2
+ def price_for_user(user)
3
+ self.master.price_for_user(user)
4
+ end
5
+ end
@@ -0,0 +1,10 @@
1
+ User.class_eval do
2
+ belongs_to :user_group
3
+ attr_accessible :user_group_id
4
+
5
+ def create_adjustment_for(order)
6
+ if self.user_group && order.adjustments.where(:originator_type => "UserGroup").count == 0
7
+ self.user_group.create_adjustment(I18n.t(:user_group_adjustment), order, order, true)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,15 @@
1
+ class UserGroup < ActiveRecord::Base
2
+ has_many :users, :dependent => :nullify
3
+ validates :name, :presence => true
4
+
5
+ calculated_adjustments
6
+
7
+ def calculator_description
8
+ return t(:none) if calculator.nil?
9
+ if calculator.preferred_based_on_cost_price
10
+ "#{I18n.t(:cost_price)} + #{calculator.preferred_flat_percent}%"
11
+ else
12
+ "#{I18n.t(:price)} - #{calculator.preferred_flat_percent}%"
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ Variant.class_eval do
2
+ def price_for_user(user)
3
+ if user && user.user_group
4
+ user.user_group.calculator.compute_item(self)
5
+ else
6
+ price
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ <%= f.field_container :name do %>
2
+ <%= f.label :name %><br />
3
+ <%= f.text_field :name %>
4
+ <% end %>
5
+ <%= render "admin/shared/calculator_fields", :f => f %>
@@ -0,0 +1,10 @@
1
+ <%= render :partial => 'admin/shared/configuration_menu' %>
2
+
3
+ <h1><%=t("editing_user_group")%></h1>
4
+
5
+ <%= render 'shared/error_messages', :target => @user_group %>
6
+
7
+ <%= form_for(@user_group, :url => object_url, :html => { :method => :put }) do |f| %>
8
+ <%= render :partial => "form", :locals => { :f => f } %>
9
+ <%= render :partial => "admin/shared/edit_resource_links" %>
10
+ <% end %>
@@ -0,0 +1,39 @@
1
+ <%= render :partial => 'admin/shared/configuration_menu' %>
2
+
3
+ <div class='toolbar'>
4
+ <ul class='actions'>
5
+ <li>
6
+ <p><%= button_link_to t("new_user_group"), new_object_url, :icon => 'add',
7
+ :id => 'admin_new_user_groups_link' %>
8
+ </p>
9
+ </li>
10
+ </ul>
11
+ <br class='clear' />
12
+ </div>
13
+
14
+
15
+ <h1><%=t("listing_user_groups")%></h1>
16
+ <table class="index" id='listing_user_groups'>
17
+ <thead>
18
+ <tr>
19
+ <th><%= UserGroup.human_attribute_name(:name) %></th>
20
+ <th><%= t(:description) %>
21
+ <th></th>
22
+ </tr>
23
+ </thead>
24
+ <tbody>
25
+ <% @user_groups.each do |user_group|%>
26
+ <tr id="<%= dom_id user_group %>">
27
+ <td><%= user_group.name %></td>
28
+ <td><%= user_group.calculator_description %></td>
29
+ <td class="actions">
30
+ <%= link_to_edit user_group %> &nbsp;
31
+ <%= link_to_delete user_group %>
32
+ </tr>
33
+ <% end %>
34
+ <% if @user_groups.empty? %>
35
+ <tr><td colspan="3"><%= t(:none) %></td></tr>
36
+ <% end %>
37
+ </tbody>
38
+ </table>
39
+
@@ -0,0 +1,10 @@
1
+ <%= render :partial => 'admin/shared/configuration_menu' %>
2
+
3
+ <h1><%=t("new_user_group")%></h1>
4
+
5
+ <%= render 'shared/error_messages', :target => @user_group %>
6
+
7
+ <%= form_for(:user_group, :url => collection_url) do |f| %>
8
+ <%= render :partial => "form", :locals => { :f => f } %>
9
+ <%= render :partial => "admin/shared/new_resource_links" %>
10
+ <% end %>
@@ -0,0 +1 @@
1
+ <%= render :partial => 'admin/shared/configuration_menu' %>
@@ -0,0 +1,9 @@
1
+ <p>
2
+ <label><%= t("user_group") %></label><br />
3
+ <% for group in UserGroup.all %>
4
+ <label class="sub">
5
+ <%= f.radio_button(:user_group_id, group.id) %>
6
+ <%= group.name %>
7
+ </label> &nbsp;
8
+ <% end %>
9
+ </p>
@@ -0,0 +1,17 @@
1
+ en:
2
+ activerecord:
3
+ attributes:
4
+ address:
5
+ name: "Name"
6
+
7
+ user_group: "User Group"
8
+ user_groups: "User Groups"
9
+ listing_user_groups: "User Groups"
10
+ new_user_group: "New user group"
11
+ editing_user_group: "Editing user group"
12
+ based_on_cost_price: "Based on cost price"
13
+ based_on_master_price: "Based on master price"
14
+ advanced_flat_percent: "Advanced Flat Percent"
15
+ manage_user_groups: "Manage user groups"
16
+ user_group_adjustment: "User Group"
17
+
@@ -0,0 +1,5 @@
1
+ Rails.application.routes.draw do
2
+ namespace :admin do
3
+ resources :user_groups
4
+ end
5
+ end
@@ -0,0 +1,17 @@
1
+ class CreateUserGroups < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :user_groups do |t|
4
+ t.string :name
5
+ end
6
+ change_table :users do |t|
7
+ t.integer :user_group_id
8
+ end
9
+ end
10
+
11
+ def self.down
12
+ change_table :users do |t|
13
+ t.remove :user_group_id
14
+ end
15
+ drop_table :user_groups
16
+ end
17
+ end
@@ -0,0 +1,57 @@
1
+ Feature: Checkout
2
+ In order to buy stuff
3
+ As a user
4
+ I should be able make checkout
5
+
6
+ @selenium
7
+ Scenario: Member of the user group should get adjustment to order
8
+ Given a payment method exists
9
+ Given I am signed up in user group "10% off" as "email@person.com/password"
10
+
11
+ When I go to the sign in page
12
+ And I sign in as "email@person.com/password"
13
+ Then I should be logged in
14
+
15
+ When I go to the products page
16
+ When I add a product with name: "RoR Mug", price: 25 to cart
17
+ Then I should see "RoR Mug"
18
+ And I should see "Shopping Cart" within "h1"
19
+ When I follow "Checkout"
20
+ Then I should see "User Group"
21
+ And I should see "-$2.5"
22
+ When I fill billing address with correct data
23
+ And check "order_use_billing"
24
+ And press "Save and Continue"
25
+ Then I should see "Shipping Method"
26
+ When I choose "UPS Ground" as shipping method and "Check" as payment method
27
+ Then I should see "Your order has been processed successfully"
28
+ And I should have 1 order
29
+
30
+ @selenium
31
+ Scenario: Member of the user group should get adjustment to guest order after log in
32
+ Given a payment method exists
33
+ Given I am signed up in user group "10% off" as "email@person.com/password"
34
+
35
+ And I am logged out
36
+
37
+ When I add a product with name: "RoR Mug", price: 25 to cart
38
+ Then 2 users should exist
39
+
40
+ When I go to the sign in page
41
+ And I sign in as "email@person.com/password"
42
+ Then I should be logged in
43
+
44
+ When I follow "Cart"
45
+ Then I should see "RoR Mug"
46
+ And I should see "Shopping Cart" within "h1"
47
+ When I follow "Checkout"
48
+ Then I should see "User Group"
49
+ And I should see "-$2.5"
50
+ When I fill billing address with correct data
51
+ And check "order_use_billing"
52
+ And press "Save and Continue"
53
+ Then I should see "Shipping Method"
54
+ When I choose "UPS Ground" as shipping method and "Check" as payment method
55
+ Then I should see "Your order has been processed successfully"
56
+ And I should have 1 order
57
+
@@ -0,0 +1,4 @@
1
+ Given /^I am signed up in user group "(\d+)% off" as "(.+)\/(.+)"$/ do |percent, email, password|
2
+ user_group = Factory(:user_group, :name => "#{percent}% off", :calculator => Calculator::AdvancedFlatPercent.new(:preferred_flat_percent => percent))
3
+ Factory(:user, :email => email, :password => password, :password_confirmation => password, :user_group => user_group)
4
+ end
@@ -0,0 +1,22 @@
1
+ FEATURES_PATH = File.expand_path('../..', __FILE__)
2
+
3
+ # load shared env with features
4
+ require File.expand_path('../../../../spree/features/support/env', __FILE__)
5
+
6
+ # load the rest of files for support and step definitions
7
+ directories = [ File.expand_path('../../../../spree/features/support', __FILE__),
8
+ File.expand_path('../../../../spree/features/step_definitions', __FILE__),
9
+ File.expand_path('../../../spec/factories', __FILE__) ]
10
+
11
+ files = directories.map do |dir|
12
+ Dir["#{dir}/**/*.rb"]
13
+ end.flatten.uniq
14
+
15
+ files.each do |path|
16
+ if path !~ /env.rb$/
17
+ fp = File.expand_path(path)
18
+ #puts fp
19
+ load(fp)
20
+ end
21
+ end
22
+
@@ -0,0 +1,43 @@
1
+ module NavigationHelpers
2
+ # Maps a name to a path. Used by the
3
+ #
4
+ # When /^I go to (.+)$/ do |page_name|
5
+ #
6
+ # step definition in web_steps.rb
7
+ #
8
+ def path_to(page_name)
9
+ case page_name
10
+
11
+ when /the home\s?page/
12
+ '/'
13
+ when /the sign in page/
14
+ new_user_session_path
15
+ when /the sign up page/
16
+ new_user_registration_path
17
+ when /the forgot password page/
18
+ new_user_password_path
19
+ when /the admin home page/
20
+ admin_path
21
+ when /my account page/
22
+ '/account'
23
+
24
+ # Add more mappings here.
25
+ # Here is an example that pulls values out of the Regexp:
26
+ #
27
+ # when /^(.*)'s profile page$/i
28
+ # user_profile_path(User.find_by_login($1))
29
+
30
+ else
31
+ begin
32
+ page_name =~ /the (.*) page/
33
+ path_components = $1.split(/\s+/)
34
+ self.send(path_components.push('path').join('_').to_sym)
35
+ rescue Object => e
36
+ raise "Can't find mapping from \"#{page_name}\" to a path.\n" +
37
+ "Now, go and add a mapping in #{__FILE__}"
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ World(NavigationHelpers)
@@ -0,0 +1,26 @@
1
+ require 'spree_core'
2
+ require 'spree_user_groups_hooks'
3
+
4
+ module SpreeUserGroups
5
+ class Engine < Rails::Engine
6
+
7
+ config.autoload_paths += %W(#{config.root}/lib)
8
+
9
+ def self.activate
10
+ Dir.glob(File.join(File.dirname(__FILE__), "../app/**/*_decorator*.rb")) do |c|
11
+ Rails.env.production? ? require(c) : load(c)
12
+ end
13
+
14
+ if File.basename( $0 ) != "rake"
15
+ begin
16
+ UserGroup.register_calculator(Calculator::AdvancedFlatPercent)
17
+ rescue Exception => e
18
+ $stderr.puts "Error registering promotion calculator #{Calculator::AdvancedFlatPercent}"
19
+ end
20
+
21
+ end
22
+ end
23
+
24
+ config.to_prepare &method(:activate).to_proc
25
+ end
26
+ end
@@ -0,0 +1,6 @@
1
+ class SpreeUserGroupsHooks < Spree::ThemeSupport::HookListener
2
+ insert_after :admin_user_form_roles, 'admin/users/user_group'
3
+ insert_after :admin_configurations_menu do
4
+ "<%= configurations_menu_item(I18n.t(:user_groups), admin_user_groups_path, I18n.t(:manage_user_groups)) %>"
5
+ end
6
+ end
@@ -0,0 +1,25 @@
1
+ namespace :spree_user_groups do
2
+ desc "Copies all migrations and assets (NOTE: This will be obsolete with Rails 3.1)"
3
+ task :install do
4
+ Rake::Task['spree_user_groups:install:migrations'].invoke
5
+ Rake::Task['spree_user_groups:install:assets'].invoke
6
+ end
7
+
8
+ namespace :install do
9
+ desc "Copies all migrations (NOTE: This will be obsolete with Rails 3.1)"
10
+ task :migrations do
11
+ source = File.join(File.dirname(__FILE__), '..', '..', 'db')
12
+ destination = File.join(Rails.root, 'db')
13
+ Spree::FileUtilz.mirror_files(source, destination)
14
+ end
15
+
16
+ desc "Copies all assets (NOTE: This will be obsolete with Rails 3.1)"
17
+ task :assets do
18
+ source = File.join(File.dirname(__FILE__), '..', '..', 'public')
19
+ destination = File.join(Rails.root, 'public')
20
+ puts "INFO: Mirroring assets from #{source} to #{destination}"
21
+ Spree::FileUtilz.mirror_files(source, destination)
22
+ end
23
+ end
24
+
25
+ end
@@ -0,0 +1 @@
1
+ # add custom rake tasks here
File without changes
@@ -0,0 +1,3 @@
1
+ Factory.define(:user_group) do |f|
2
+ f.name { "Wholesaler" }
3
+ end
@@ -0,0 +1,58 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe 'Calculator::AdvancedFlatPercent based on master_price' do
4
+ let(:calculator) { Calculator::AdvancedFlatPercent.new }
5
+ let(:order) { mock_model Order, :line_items => [mock_model(LineItem, :amount => 10), mock_model(LineItem, :amount => 20)], :user => mock_model(User) }
6
+
7
+ before { calculator.stub :preferred_flat_percent => 10, :preferred_based_on_cost_price => false }
8
+
9
+ context "compute" do
10
+ it "should compute amount correctly" do
11
+ calculator.compute(order).should == -3.0
12
+ end
13
+
14
+ it "should round result correctly" do
15
+ order.stub :line_items => [mock_model(LineItem, :amount => 10.56), mock_model(LineItem, :amount => 20.49)]
16
+ calculator.compute(order).should == -3.11
17
+
18
+ order.stub :line_items => [mock_model(LineItem, :amount => 10.56), mock_model(LineItem, :amount => 20.48)]
19
+ calculator.compute(order).should == -3.10
20
+ end
21
+ end
22
+ end
23
+
24
+
25
+ describe 'Calculator::AdvancedFlatPercent based on cost_price' do
26
+ let(:calculator) { Calculator::AdvancedFlatPercent.new }
27
+ let(:variant1) { mock_model(Variant, :cost_price => 3, :price => 5) }
28
+ let(:variant2) { mock_model(Variant, :cost_price => 12, :price => 20) }
29
+ let(:order) { mock_model Order, :line_items => [mock_model(LineItem, :amount => 10, :quantity => 2, :variant => variant1), mock_model(LineItem, :amount => 20, :quantity => 1, :variant => variant2)], :user => mock_model(User) }
30
+
31
+ before { calculator.stub :preferred_flat_percent => 15, :preferred_based_on_cost_price => true }
32
+
33
+ context "compute" do
34
+ it "should compute amount correctly" do
35
+ calculator.compute(order).should == -9.3
36
+ end
37
+
38
+ it "should round result correctly" do
39
+ variant1.stub :cost_price => 2.7
40
+ variant2.stub :cost_price => 12.35
41
+ calculator.compute(order).should == -9.59 # -9.5875
42
+
43
+ variant1.stub :cost_price => 2.7
44
+ variant2.stub :cost_price => 12.25
45
+ calculator.compute(order).should == -9.70 # -9.7025
46
+ end
47
+ end
48
+
49
+ context "compute_item" do
50
+ it "should compute price correctly" do
51
+ calculator.compute_item(variant1).should == 3*1.15
52
+ variant1.stub :cost_price => 2.7
53
+ calculator.compute_item(variant1).should == 2.7*1.15
54
+ variant1.stub :cost_price => nil
55
+ calculator.compute_item(variant1).should == 5
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,21 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe UserGroup do
4
+ let(:user_group) { UserGroup.new }
5
+
6
+ context "shoulda validations" do
7
+ it { should have_many(:users) }
8
+ end
9
+
10
+ describe "#save" do
11
+ let(:user_group_valid) { UserGroup.new :name => "Wholesaler" }
12
+
13
+ context "when is invalid" do
14
+ it { user_group.save.should be_false }
15
+ end
16
+
17
+ context "when is valid" do
18
+ it { user_group_valid.save.should be_true }
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,9 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe User do
4
+
5
+ context "shoulda validations" do
6
+ it { should belong_to(:user_group) }
7
+ end
8
+
9
+ end
@@ -0,0 +1,33 @@
1
+ # This file is copied to ~/spec when you run 'ruby script/generate rspec'
2
+ # from the project root directory.
3
+ ENV["RAILS_ENV"] ||= 'test'
4
+ require File.expand_path("../test_app/config/environment", __FILE__)
5
+ require 'rspec/rails'
6
+
7
+ # Requires supporting files with custom matchers and macros, etc,
8
+ # in ./support/ and its subdirectories.
9
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
10
+
11
+ #require 'spree_core/testing_support/factories'
12
+ require 'factories'
13
+
14
+ RSpec.configure do |config|
15
+ # == Mock Framework
16
+ #
17
+ # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
18
+ #
19
+ # config.mock_with :mocha
20
+ # config.mock_with :flexmock
21
+ # config.mock_with :rr
22
+ config.mock_with :rspec
23
+
24
+ config.fixture_path = "#{::Rails.root}/spec/fixtures"
25
+
26
+ #config.include Devise::TestHelpers, :type => :controller
27
+ # If you're not using ActiveRecord, or you'd prefer not to run each of your
28
+ # examples within a transaction, comment the following line or assign false
29
+ # instead of true.
30
+ config.use_transactional_fixtures = true
31
+ end
32
+
33
+ @configuration ||= AppConfiguration.find_or_create_by_name("Default configuration")
@@ -0,0 +1,23 @@
1
+ Gem::Specification.new do |s|
2
+ s.platform = Gem::Platform::RUBY
3
+ s.name = 'spree_user_groups'
4
+ s.version = '0.40.0'
5
+ s.summary = 'Adds user groups'
6
+ s.description = 'Provides opportunity to add some rules for calculation price depending on the user group'
7
+ s.required_ruby_version = '>= 1.8.7'
8
+
9
+ s.author = 'Roman Smirnov'
10
+ s.email = 'roman@railsdog.com'
11
+ s.homepage = 'https://github.com/romul/spree_user_groups'
12
+ # s.rubyforge_project = 'actionmailer'
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ s.require_path = 'lib'
17
+ s.requirements << 'none'
18
+
19
+ s.has_rdoc = true
20
+
21
+ s.add_dependency('spree_core', '>= 0.30.1')
22
+ s.add_dependency('spree_auth', '>= 0.30.1')
23
+ end
metadata ADDED
@@ -0,0 +1,126 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: spree_user_groups
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 40
8
+ - 0
9
+ version: 0.40.0
10
+ platform: ruby
11
+ authors:
12
+ - Roman Smirnov
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-02-20 00:00:00 +03:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: spree_core
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ - 30
30
+ - 1
31
+ version: 0.30.1
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: spree_auth
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 0
43
+ - 30
44
+ - 1
45
+ version: 0.30.1
46
+ type: :runtime
47
+ version_requirements: *id002
48
+ description: Provides opportunity to add some rules for calculation price depending on the user group
49
+ email: roman@railsdog.com
50
+ executables: []
51
+
52
+ extensions: []
53
+
54
+ extra_rdoc_files: []
55
+
56
+ files:
57
+ - .gitignore
58
+ - LICENSE
59
+ - README.md
60
+ - Rakefile
61
+ - app/controllers/admin/user_groups_controller.rb
62
+ - app/controllers/checkout_controller_decorator.rb
63
+ - app/models/calculator/advanced_flat_percent.rb
64
+ - app/models/order_decorator.rb
65
+ - app/models/product_decorator.rb
66
+ - app/models/user_decorator.rb
67
+ - app/models/user_group.rb
68
+ - app/models/variant_decorator.rb
69
+ - app/views/admin/user_groups/_form.html.erb
70
+ - app/views/admin/user_groups/edit.html.erb
71
+ - app/views/admin/user_groups/index.html.erb
72
+ - app/views/admin/user_groups/new.html.erb
73
+ - app/views/admin/user_groups/show.html.erb
74
+ - app/views/admin/users/_user_group.html.erb
75
+ - config/locales/en.yml
76
+ - config/routes.rb
77
+ - db/migrate/20110207075544_create_user_groups.rb
78
+ - features/checkout.feature
79
+ - features/step_definitions/user_group_steps.rb
80
+ - features/support/env.rb
81
+ - features/support/paths.rb
82
+ - lib/spree_user_groups.rb
83
+ - lib/spree_user_groups_hooks.rb
84
+ - lib/tasks/install.rake
85
+ - lib/tasks/spree_user_groups.rake
86
+ - spec/factories.rb
87
+ - spec/factories/user_group_factory.rb
88
+ - spec/models/calculator/advanced_flat_percent_spec.rb
89
+ - spec/models/user_group_spec.rb
90
+ - spec/models/user_spec.rb
91
+ - spec/spec_helper.rb
92
+ - spree_user_groups.gemspec
93
+ has_rdoc: true
94
+ homepage: https://github.com/romul/spree_user_groups
95
+ licenses: []
96
+
97
+ post_install_message:
98
+ rdoc_options: []
99
+
100
+ require_paths:
101
+ - lib
102
+ required_ruby_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ segments:
107
+ - 1
108
+ - 8
109
+ - 7
110
+ version: 1.8.7
111
+ required_rubygems_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ segments:
116
+ - 0
117
+ version: "0"
118
+ requirements:
119
+ - none
120
+ rubyforge_project:
121
+ rubygems_version: 1.3.6
122
+ signing_key:
123
+ specification_version: 3
124
+ summary: Adds user groups
125
+ test_files: []
126
+