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.
- data/.gitignore +11 -0
- data/LICENSE +23 -0
- data/README.md +17 -0
- data/Rakefile +77 -0
- data/app/controllers/admin/user_groups_controller.rb +18 -0
- data/app/controllers/checkout_controller_decorator.rb +9 -0
- data/app/models/calculator/advanced_flat_percent.rb +47 -0
- data/app/models/order_decorator.rb +14 -0
- data/app/models/product_decorator.rb +5 -0
- data/app/models/user_decorator.rb +10 -0
- data/app/models/user_group.rb +15 -0
- data/app/models/variant_decorator.rb +9 -0
- data/app/views/admin/user_groups/_form.html.erb +5 -0
- data/app/views/admin/user_groups/edit.html.erb +10 -0
- data/app/views/admin/user_groups/index.html.erb +39 -0
- data/app/views/admin/user_groups/new.html.erb +10 -0
- data/app/views/admin/user_groups/show.html.erb +1 -0
- data/app/views/admin/users/_user_group.html.erb +9 -0
- data/config/locales/en.yml +17 -0
- data/config/routes.rb +5 -0
- data/db/migrate/20110207075544_create_user_groups.rb +17 -0
- data/features/checkout.feature +57 -0
- data/features/step_definitions/user_group_steps.rb +4 -0
- data/features/support/env.rb +22 -0
- data/features/support/paths.rb +43 -0
- data/lib/spree_user_groups.rb +26 -0
- data/lib/spree_user_groups_hooks.rb +6 -0
- data/lib/tasks/install.rake +25 -0
- data/lib/tasks/spree_user_groups.rake +1 -0
- data/spec/factories.rb +0 -0
- data/spec/factories/user_group_factory.rb +3 -0
- data/spec/models/calculator/advanced_flat_percent_spec.rb +58 -0
- data/spec/models/user_group_spec.rb +21 -0
- data/spec/models/user_spec.rb +9 -0
- data/spec/spec_helper.rb +33 -0
- data/spree_user_groups.gemspec +23 -0
- metadata +126 -0
data/.gitignore
ADDED
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.
|
data/README.md
ADDED
@@ -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
|
data/Rakefile
ADDED
@@ -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,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,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 %>
|
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,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
|
+
|
data/config/routes.rb
ADDED
@@ -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
|
data/spec/factories.rb
ADDED
File without changes
|
@@ -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
|
data/spec/spec_helper.rb
ADDED
@@ -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
|
+
|