spree_user_groups 0.40.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 (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
+