spree_flexi_rate_shipping 0.3.0.beta

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 +19 -0
  2. data/Gemfile +4 -0
  3. data/README.markdown +111 -0
  4. data/Rakefile +28 -0
  5. data/Versionfile +11 -0
  6. data/app/controllers/admin/configurations_controller_decorator.rb +14 -0
  7. data/app/controllers/admin/flexi_shipping_rates_controller.rb +23 -0
  8. data/app/helpers/admin/flexi_shipping_rates_helper.rb +2 -0
  9. data/app/models/flexi_shipping_rate.rb +8 -0
  10. data/app/models/product_decorator.rb +4 -0
  11. data/app/models/shipping_category_decorator.rb +4 -0
  12. data/app/models/zone_decorator.rb +4 -0
  13. data/app/views/admin/flexi_shipping_rates/_form.html.erb +26 -0
  14. data/app/views/admin/flexi_shipping_rates/edit.html.erb +8 -0
  15. data/app/views/admin/flexi_shipping_rates/index.html.erb +41 -0
  16. data/app/views/admin/flexi_shipping_rates/new.html.erb +10 -0
  17. data/config/locales/en-GB.yml +18 -0
  18. data/config/locales/en-US.yml +18 -0
  19. data/config/roues.rb +6 -0
  20. data/db/migrate/20081020154802_create_flexi_shipping_rates.rb +14 -0
  21. data/db/sample/flexi_shipping_rates.yml +34 -0
  22. data/db/sample/shipping_categories.yml +4 -0
  23. data/db/sample/shipping_methods.yml +8 -0
  24. data/lib/generators/spree_flexi_rate_shipping/install_generator.rb +19 -0
  25. data/lib/spree/flexi_rate_shipping/calculator.rb +42 -0
  26. data/lib/spree/flexi_rate_shipping/engine.rb +27 -0
  27. data/lib/spree/flexi_rate_shipping/version.rb +3 -0
  28. data/lib/spree_flexi_rate_shipping.rb +3 -0
  29. data/lib/tasks/flexi_rate_shipping_extension_tasks.rake +12 -0
  30. data/script/rails +7 -0
  31. data/spec/controllers/admin/flexi_shipping_rates_controller_spec.rb +10 -0
  32. data/spec/models/flexi_shipping_calculator_spec.rb +139 -0
  33. data/spec/models/flexi_shipping_rate_spec.rb +16 -0
  34. data/spec/spec.opts +6 -0
  35. data/spec/spec_helper.rb +14 -0
  36. data/spree_flexi_rate_shipping.gemspec +24 -0
  37. metadata +115 -0
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ spec/dummy
19
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source :rubygems
2
+
3
+ gemspec
4
+
@@ -0,0 +1,111 @@
1
+ Flexi Rate Shipping
2
+ ===================
3
+ Supports Spree 0.70.x
4
+
5
+ Flexi Rate Shipping is an extension to Spree (a complete open source commerce solution for Ruby on Rails) that uses predefined values to calculate shipping. This extension is designed to be used when a traditional UPS / FedEx API approach in unavailable or unsuitable.
6
+
7
+ When installed, a new "Flexi Shipping Rates" link is added to the Configuration area in the Spree administration interface. Here you can define as many different rates as required, and link them to the relevant Shipping Categories and Zones.
8
+
9
+ Each FlexiShippingRate contains the following values:
10
+
11
+ 1. **Shipping Category:** Each FlexiShippingRate is associated with a _Shipping Category_, which is used to link products to particular rates. Several FlexiShippingRates can be associated with the same _Shipping Category_ provided that each one uses a different _Zone_.
12
+
13
+ 2. **Zone:** Relates the FlexiShippingRate with a particular _Zone_ so that you can specify different prices for the same _Shipping Category_ by zone.
14
+
15
+ 3. **First Item Price:** This is the amount added to the shipping total for the first item in the order that uses a particular FlexiShippingRate.
16
+
17
+ 4. **Additional Item Price:** Is the amount added to the shipping total for each additional item (after the first item) in the order.
18
+
19
+ 5. **Max. Items:** Is the maximum number of items that can be grouped in a single FlexiShippingRate, the first item that exceeds this value will be charged the _First Item Price_ and the each subsequent item will be charged at the _Additional Item Price_ until the value is reached again, and cycle restarts.
20
+
21
+
22
+ Examples
23
+ ========
24
+ The sample data contained with this extension shows how to configure Spree to support multiple FlexiShippingRates broken down by three different _Shipping Categories_ and two _Zones_.
25
+
26
+ Shipping Category Zone First Item Price Additional Item Price Max. Items
27
+ -----------------------------------------------------------------------------------------------------------------
28
+ Default Shipping EU_VAT $ 10.00 $ 2.00 5
29
+ Small Item Shipping EU_VAT $ 2.00 $ 0.50 10
30
+ Large Item Shipping EU_VAT $ 25.00 1
31
+
32
+ Default Shipping North America $ 40.00 $ 10.00 5
33
+ Small Item Shipping North America $ 6.00 $ 1.50 10
34
+ Large Item Shipping North America $ 75.00 1
35
+
36
+
37
+ ## Example 1
38
+
39
+ Cart Contents:
40
+
41
+ Product Quantity Shipping Category
42
+ ----------------------------------------------------------------
43
+ Apache Baseball Jersey 1 Default Shipping
44
+
45
+ The total shipping amount would be:
46
+
47
+ **EU_VAT Coutries:** $ 10.00 or **North America:** $ 40.00
48
+
49
+ ## Example 2
50
+
51
+ Cart Contents:
52
+
53
+ Product Quantity Shipping Category
54
+ ----------------------------------------------------------------
55
+ Apache Baseball Jersey 6 Default Shipping
56
+
57
+ The total shipping amount would be:
58
+
59
+ **EU_VAT Coutries:** $ 28.00 or **North America:** $ 120.00
60
+
61
+
62
+ ## Example 3
63
+
64
+ Cart Contents:
65
+
66
+ Product Quantity Shipping Category
67
+ ----------------------------------------------------------------
68
+ Apache Baseball Jersey 6 Default Shipping
69
+ Ruby on Rails Mug 2 Large Item Shipping
70
+
71
+ The total shipping amount would be:
72
+
73
+ **EU_VAT Coutries:** $ 78.00 or **North America:** $ 270.00
74
+
75
+ Quick Start for 0.70.x
76
+ ===========
77
+ 1. Add to your Gemfile
78
+
79
+ `gem 'spree_flexi_rate_shipping', :git => 'git://github.com/spree-flexi-rate-shipping.git'`
80
+
81
+ 2. Copy and run the migrations
82
+
83
+ `rake spree_flexi_rate_shipping:install`
84
+
85
+ 3. Log in to the Admin interface and associate Products with Shipping Categories.
86
+
87
+ 4. Set up Flexi-rate at /admin/flexi_shipping_rates
88
+
89
+ 5. Create a Shipping Method with "Flexible Rate - Categories" as it's calculator.
90
+
91
+ Work for 0.70 done by Chris Boertien of Bz Labs
92
+
93
+ Quick Start for 0.60.x
94
+ ============
95
+ 1. Add extension to Gemfile
96
+ `gem "spree_flexi_rate_shipping", :require => "spree_flexi_rate_shipping", :git => 'git://github.com/GeeksOnCoffee/spree-flexi-rate-shipping.git', :branch => '0.60.0'`
97
+
98
+ 2. Get Gem
99
+ bundle install
100
+
101
+ 3. Copy Assets and Migrate Database
102
+ `rake spree_flexi_rate_shipping:install`
103
+ `rake db:migrate`
104
+
105
+ 3. Log in to the Admin interface and associate Products with Shipping Categories.
106
+
107
+ 4. Set up Flexi-rate at /admin/flexi_shipping_rates/
108
+
109
+ 5. Create a Shipping Method with "Flexible Rate- Categories" as it's calculator.
110
+
111
+ Work for 0.60 done by adhlssu07 of Geeks On Coffee and sponsored by Workman Technology Services.
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env rake
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+ require 'rake/packagetask'
5
+ require 'rubygems/package_task'
6
+ require 'rspec/core/rake_task'
7
+ require 'spree_core/testing_support/common_rake'
8
+
9
+ #require "bundler/gem_tasks"
10
+
11
+ RSpec::Core::RakeTask.new
12
+
13
+ task :default => :spec
14
+
15
+ spec = eval(File.read('spree_flexi_rate_shipping.gemspec'))
16
+
17
+ Gem::PackageTask.new(spec) do |p|
18
+ p.gem_spec = spec
19
+ end
20
+
21
+ Bundler::GemHelper.install_tasks
22
+
23
+ desc "Generates a dummy app for testing"
24
+ task :test_app do
25
+ ENV['LIB_NAME'] = "spree_flexi_rate_shipping"
26
+ Rake::Task['common:test_app'].invoke
27
+ end
28
+
@@ -0,0 +1,11 @@
1
+ # This file is used to designate compatibilty with different versions of Spree
2
+ # Please see http://spreecommerce.com/documentation/extensions.html#versionfile for details
3
+
4
+ # Examples
5
+ #
6
+ # "0.50.x" => { :branch => "master" }
7
+ # "0.40.x" => { :tag => "v1.0.0", :version => "1.0.0" }
8
+
9
+ "0.70.x" => { :branch => "master" }
10
+ "0.60.x" => { :branch => "0.60.0" }
11
+ #"0.70.x" => { :tag => "v0.3.0", :version => "0.3.0" }
@@ -0,0 +1,14 @@
1
+ module Admin
2
+ ConfigurationsController.class_eval do
3
+ before_filter :add_flexi_rate_links, :only => :index
4
+
5
+ def add_flexi_rate_links
6
+ @extension_links << {
7
+ :link => admin_flexi_shipping_rates_path,
8
+ :link_text => FlexiShippingRate.human_name(:count => 2),
9
+ :description => t('flexi_shipping_rates_description')
10
+ }
11
+ end
12
+ end
13
+ end
14
+
@@ -0,0 +1,23 @@
1
+ class Admin::FlexiShippingRatesController < Admin::BaseController
2
+ resource_controller
3
+ before_filter :load_data
4
+ layout 'admin'
5
+
6
+ update.response do |wants|
7
+ wants.html { redirect_to collection_url }
8
+ end
9
+
10
+ create.response do |wants|
11
+ wants.html { redirect_to collection_url }
12
+ end
13
+
14
+ private
15
+ def collection
16
+ @collection ||= end_of_association_chain.order_by_zone_and_category
17
+ end
18
+
19
+ def load_data
20
+ @available_categories = ShippingCategory.find :all, :order => :name
21
+ @available_zones = Zone.find :all, :order => :name
22
+ end
23
+ end
@@ -0,0 +1,2 @@
1
+ module Admin::FlexiShippingRatesHelper
2
+ end
@@ -0,0 +1,8 @@
1
+ class FlexiShippingRate < ActiveRecord::Base
2
+ belongs_to :shipping_category
3
+ belongs_to :zone
4
+
5
+ validates_presence_of :first_item_price, :max_items, :shipping_category, :zone
6
+ validates_uniqueness_of :shipping_category_id, :scope => :zone_id
7
+ end
8
+
@@ -0,0 +1,4 @@
1
+ Product.class_eval do
2
+ belongs_to :shipping_category
3
+ end
4
+
@@ -0,0 +1,4 @@
1
+ ShippingCategory.class_eval do
2
+ has_many :flexi_shipping_rates
3
+ end
4
+
@@ -0,0 +1,4 @@
1
+ Zone.class_eval do
2
+ has_many :flexi_shipping_rates
3
+ end
4
+
@@ -0,0 +1,26 @@
1
+ <table>
2
+ <tr>
3
+ <td><%= ShippingCategory.model_name.human %>:</td>
4
+ <td><%= collection_select(:flexi_shipping_rate,
5
+ :shipping_category_id, @available_categories, :id, :name,
6
+ {}, {"style" => "width:200px"}) %></td>
7
+ </tr>
8
+ <tr>
9
+ <td><%=t("zone")%>:</td>
10
+ <td><%= collection_select(:flexi_shipping_rate,
11
+ :zone_id, @available_zones, :id, :name,
12
+ {}, {"style" => "width:200px"}) %></td>
13
+ </tr>
14
+ <tr>
15
+ <td><%= FlexiShippingRate.human_attribute_name("first_item_price")%>:</td>
16
+ <td><%= f.text_field :first_item_price, {"style" => "width:60px"} %></td>
17
+ </tr>
18
+ <tr>
19
+ <td><%= FlexiShippingRate.human_attribute_name("additional_item_price")%>:</td>
20
+ <td><%= f.text_field :additional_item_price, {"style" => "width:60px"} %></td>
21
+ </tr>
22
+ <tr>
23
+ <td><%= FlexiShippingRate.human_attribute_name("max_number_of_items")%>:</td>
24
+ <td><%= f.text_field :max_items, {"style" => "width:30px"} %></td>
25
+ </tr>
26
+ </table>
@@ -0,0 +1,8 @@
1
+ <h1><%= "#{t("editing")} #{FlexiShippingRate.model_name.human}" %></h1>
2
+ <%= error_messages_for :flexi_shipping_rate %>
3
+ <%= form_for(:flexi_shipping_rate, :url => object_url, :html => { :method => :put }) do |f| %>
4
+ <%= render :partial => "form", :locals => { :f => f } %>
5
+ <p>
6
+ <%=submit_tag t("actions.update")%>
7
+ </p>
8
+ <% end %>
@@ -0,0 +1,41 @@
1
+ <div class='toolbar'>
2
+ <ul class='actions'>
3
+ <li>
4
+ <%= button_link_to t("new_flexi_shipping_rate"), new_object_url, :icon => 'add' %>
5
+ </li>
6
+ </ul>
7
+ <br class='clear' />
8
+ </div>
9
+
10
+ <h1><%= FlexiShippingRate.human_name(:count => 2) %></h1>
11
+
12
+ <table class="index">
13
+ <thead>
14
+ <tr>
15
+ <th><%= FlexiShippingRate.human_attribute_name("shipping_category") %></th>
16
+ <th><%= FlexiShippingRate.human_attribute_name("zone")%></th>
17
+ <th><%= FlexiShippingRate.human_attribute_name("first_item_price")%></th>
18
+ <th><%= FlexiShippingRate.human_attribute_name("additional_item_price")%></th>
19
+ <th><%= FlexiShippingRate.human_attribute_name("max_number_of_items")%></th>
20
+ <th><%= t("action")%></th>
21
+ </tr>
22
+ </thead>
23
+ <tbody>
24
+ <% @flexi_shipping_rates.each do |flexi_shipping_rate| %>
25
+ <tr>
26
+ <td><%=flexi_shipping_rate.shipping_category.name %></td>
27
+ <td><%=flexi_shipping_rate.zone.name %></td>
28
+ <td><%=number_to_currency(flexi_shipping_rate.first_item_price) %></td>
29
+ <td><%=number_to_currency(flexi_shipping_rate.additional_item_price) %></td>
30
+ <td><%=flexi_shipping_rate.max_items %></td>
31
+ <td>
32
+ <%= link_to_edit flexi_shipping_rate %> &nbsp;
33
+ <%= link_to_delete flexi_shipping_rate %>
34
+ </td>
35
+ </tr>
36
+ <% end %>
37
+ <% if @flexi_shipping_rates.empty? %>
38
+ <tr><td colspan="5">None.</td></tr>
39
+ <% end %>
40
+ </tbody>
41
+ </table>
@@ -0,0 +1,10 @@
1
+ <h1><%= "#{t("actions.new")} #{FlexiShippingRate.human_name}" %></h1>
2
+
3
+ <%= error_messages_for :flexi_shipping_rate %>
4
+
5
+ <% form_for(:flexi_shipping_rate, :url => collection_url) do |f| %>
6
+ <%= render :partial => "form", :locals => { :f => f } %>
7
+ <p>
8
+ <%= submit_tag t("actions.create") %>
9
+ </p>
10
+ <% end %>
@@ -0,0 +1,18 @@
1
+ en-GB:
2
+ activerecord:
3
+ attributes:
4
+ flexi_shipping_rate:
5
+ first_item_price: "First item price"
6
+ additional_item_price: "Additional item price"
7
+ max_items: "Max. number of items"
8
+ models:
9
+ flexi_shipping_rate:
10
+ one: "Flexi Shipping Rate"
11
+ other: "Flexi Shipping Rates"
12
+ errors:
13
+ models:
14
+ flexi_shipping_rate:
15
+ taken: "already exists for the specified Zone."
16
+ flexi_shipping_rates_description: Manage rates and associated Shipping Categories for use with the FlexiRate Shipping Extension
17
+ new_flexi_shipping_rate: "New Flexi Shipping Rate"
18
+ editing: "Editing"
@@ -0,0 +1,18 @@
1
+ en-US:
2
+ activerecord:
3
+ attributes:
4
+ flexi_shipping_rate:
5
+ first_item_price: "First item price"
6
+ additional_item_price: "Additional item price"
7
+ max_items: "Max. number of items"
8
+ models:
9
+ flexi_shipping_rate:
10
+ one: "Flexi Shipping Rate"
11
+ other: "Flexi Shipping Rates"
12
+ errors:
13
+ models:
14
+ flexi_shipping_rate:
15
+ taken: "already exists for the specified Zone."
16
+ flexi_shipping_rates_description: Manage rates and associated Shipping Categories for use with the FlexiRate Shipping Extension
17
+ new_flexi_shipping_rate: "New Flexi Shipping Rate"
18
+ editing: "Editing"
@@ -0,0 +1,6 @@
1
+ Rails.application.routes.draw do
2
+ namespace :admin do
3
+ resources :flexi_shipping_rates
4
+ end
5
+ end
6
+
@@ -0,0 +1,14 @@
1
+ class CreateFlexiShippingRates < ActiveRecord::Migration
2
+ def change
3
+ create_table :flexi_shipping_rates do |t|
4
+ t.references :shipping_category
5
+ t.references :zone
6
+ t.decimal :first_item_price, :precision => 8, :scale => 2
7
+ t.decimal :additional_item_price, :precision => 8, :scale => 2
8
+ t.integer :max_items, :default => 0
9
+
10
+ t.timestamps
11
+ end
12
+ end
13
+ end
14
+
@@ -0,0 +1,34 @@
1
+ default_flexi_eu:
2
+ shipping_category: default_shipping
3
+ zone_id: 1
4
+ first_item_price: 10.00
5
+ additional_item_price: 2.00
6
+ max_items: 5
7
+ small_flexi_eu:
8
+ shipping_category: small_item_shipping
9
+ zone_id: 1
10
+ first_item_price: 2.00
11
+ additional_item_price: 0.50
12
+ max_items: 10
13
+ large_flexi_eu:
14
+ shipping_category: large_item_shipping
15
+ zone_id: 1
16
+ first_item_price: 25.00
17
+ max_items: 1
18
+ default_flexi_us:
19
+ shipping_category: default_shipping
20
+ zone: available_shipping
21
+ first_item_price: 40.00
22
+ additional_item_price: 10.00
23
+ max_items: 5
24
+ small_flexi_us:
25
+ shipping_category: small_item_shipping
26
+ zone: available_shipping
27
+ first_item_price: 6.00
28
+ additional_item_price: 1.50
29
+ max_items: 10
30
+ large_flexi_us:
31
+ shipping_category: large_item_shipping
32
+ zone: available_shipping
33
+ first_item_price: 75.00
34
+ max_items: 1
@@ -0,0 +1,4 @@
1
+ small_item_shipping:
2
+ name: Small Item Shipping
3
+ large_item_shipping:
4
+ name: Large Item Shipping
@@ -0,0 +1,8 @@
1
+ flexi_us:
2
+ name: Flexi Rate (US)
3
+ zone: available_shipping
4
+ shipping_calculator: Spree::FlexiRateShipping::Calculator
5
+ flexi_eu:
6
+ name: Flexi Rate (EU)
7
+ zone_id: 1
8
+ shipping_calculator: Spree::FlexiRateShipping::Calculator
@@ -0,0 +1,19 @@
1
+ module SpreeFlexiRateShipping
2
+ module Generators
3
+ class InstallGenerator < Rails::Generators::Base
4
+ def add_migrations
5
+ run "bundle exec rake railties:install:migrations FROM=spree_flexi_rate_shipping"
6
+ end
7
+
8
+ def run_migrations
9
+ res = ask "Would you like to run the migrations now? [Y/n]"
10
+ if res == "" || res.downcase == "y"
11
+ run "bundle exec rake db:migrate"
12
+ else
13
+ puts "Skipping rake db:migrate, don't forget to run it!"
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+
@@ -0,0 +1,42 @@
1
+ module Spree
2
+ module FlexiRateShipping
3
+ class Calculator
4
+ def calculate_shipping(shipment)
5
+ rates = {}
6
+ rate_count = {}
7
+ shipment.order.line_items.each do |li|
8
+
9
+ li.quantity.times do
10
+ sc = li.variant.product.shipping_category
11
+ sc ||= ShippingCategory.new()
12
+ flexi_rates = sc.flexi_shipping_rates
13
+
14
+ fsr = flexi_rates.detect{ | rate | rate.zone.include?(shipment.address) }
15
+
16
+ fsr ||= FlexiShippingRate.new(:id => 'default', :first_item_price => 0, :max_items => 1)
17
+ rate_count.has_key?(fsr.id) ? rate_count[fsr.id] += 1 : rate_count[fsr.id] = 1
18
+
19
+ rates[fsr.id] = 0 unless rates.has_key? fsr.id
20
+
21
+ if rates[fsr.id] == 0
22
+ #first time to add a product from this flexi-rate
23
+ rates[fsr.id] += fsr.first_item_price
24
+ else
25
+ #additional time to add a product from this flexi-rate
26
+
27
+ if rate_count[fsr.id] % fsr.max_items == 1
28
+ rates[fsr.id] += fsr.first_item_price
29
+ else
30
+ rates[fsr.id] += fsr.additional_item_price
31
+ end
32
+
33
+ end
34
+ end
35
+
36
+ end
37
+
38
+ return rates.values.inject(0){|sum, c| sum + c}
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,27 @@
1
+ module Spree
2
+ module FlexiRateShipping
3
+ class Engine < Rails::Engine
4
+ engine_name 'spree_flexi_rate_shipping'
5
+
6
+ config.autoload_paths += %W(#{config.root}/lib)
7
+
8
+ # use rspec for tests
9
+ config.generators do |g|
10
+ g.test_framework :rspec
11
+ end
12
+
13
+ def self.activate
14
+ Dir.glob(File.join(File.dirname(__FILE__), "../app/**/*_decorator.rb")) do |c|
15
+ Rails.application.config.cache_classes ? require(c) : load(c)
16
+ end
17
+
18
+ Dir.glob(File.join(File.dirname(__FILE__), "../app/overrides/**/*.rb")) do |c|
19
+ Rails.application.config.cache_classes ? require(c) : load(c)
20
+ end
21
+ end
22
+
23
+ config.to_prepare &method(:activate).to_proc
24
+ end
25
+ end
26
+ end
27
+
@@ -0,0 +1,3 @@
1
+ module SpreeFlexiRateShipping
2
+ VERSION = "0.3.0.beta"
3
+ end
@@ -0,0 +1,3 @@
1
+ require 'spree_core'
2
+ require 'spree/flexi_rate_shipping/engine'
3
+
@@ -0,0 +1,12 @@
1
+ namespace :db do
2
+ desc "Bootstrap your database for Spree."
3
+ task :bootstrap => :environment do
4
+ # load initial database fixtures (in db/sample/*.yml) into the current environment's database
5
+ ActiveRecord::Base.establish_connection(RAILS_ENV.to_sym)
6
+ Dir.glob(File.join(FlexiRateShippingExtension.root, "db", 'sample', '*.{yml,csv}')).each do |fixture_file|
7
+ Fixtures.create_fixtures("#{FlexiRateShippingExtension.root}/db/sample", File.basename(fixture_file, '.*'))
8
+ end
9
+
10
+ end
11
+ end
12
+
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ ENGINE_PATH = File.expand_path('../../', __FILE__)
4
+ APP_PATH = File.expand_path('../../../config/application', __FILE__)
5
+ require File.expand_path('../../../config/boot', __FILE__)
6
+ require 'rails/commands'
7
+
@@ -0,0 +1,10 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe Admin::FlexiShippingRatesController do
4
+
5
+ #Delete this example and add some real ones
6
+ it "should use Admin::FlexiShippingRatesController" do
7
+ controller.should be_an_instance_of(Admin::FlexiShippingRatesController)
8
+ end
9
+
10
+ end
@@ -0,0 +1,139 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+
4
+ describe Spree::FlexiRateShipping::Calculator do
5
+ before(:each) do
6
+ @zone = mock_model(Zone, :name => "North America", :include? => true)
7
+
8
+ @flexi_shipping_rate1 = mock_model(FlexiShippingRate, :first_item_price => 10.0, :additional_item_price => 2.0, :max_items => 6, :zone => @zone)
9
+
10
+ @shipping_category1 = mock_model(ShippingCategory, :flexi_shipping_rates => [@flexi_shipping_rate1])
11
+ @product1 = mock_model(Product, :shipping_category => @shipping_category1)
12
+ @variant1 = mock_model(Variant, :product => @product1)
13
+
14
+ @address = mock_model(Address, :zone => @zone)
15
+ end
16
+
17
+ it "should calculate shipping with no flexi shipping rate" do
18
+ @shipping_category1 = mock_model(ShippingCategory, :flexi_shipping_rates => [])
19
+ @product1 = mock_model(Product, :shipping_category => @shipping_category1)
20
+ @variant1 = mock_model(Variant, :product => @product1)
21
+
22
+ @line_item1 = mock_model(LineItem, :variant => @variant1, :quantity => 1)
23
+ @line_items = [@line_item1]
24
+ @order = mock_model(Order, :line_items => @line_items)
25
+ @shipment = mock_model(Shipment, :order => @order, :address => @address)
26
+
27
+ Spree::FlexiRateShipping::Calculator.new().calculate_shipping(@shipment).should == 0.0
28
+ end
29
+
30
+ it "should calculate shipping with one product with no flexi shipping rate" do
31
+ @no_rate_shipping_category = mock_model(ShippingCategory, :flexi_shipping_rates => [])
32
+ @product1 = mock_model(Product, :shipping_category => @no_rate_shipping_category)
33
+ @variant1 = mock_model(Variant, :product => @product1)
34
+
35
+ @line_item1 = mock_model(LineItem, :variant => @variant1, :quantity => 1)
36
+
37
+ @product2 = mock_model(Product, :shipping_category => @shipping_category1)
38
+ @variant2 = mock_model(Variant, :product => @product2)
39
+ @line_item2 = mock_model(LineItem, :variant => @variant2, :quantity => 2)
40
+
41
+ @line_items = [@line_item1, @line_item2]
42
+ @order = mock_model(Order, :line_items => @line_items)
43
+ @shipment = mock_model(Shipment, :order => @order, :address => @address)
44
+
45
+ Spree::FlexiRateShipping::Calculator.new().calculate_shipping(@shipment).should == 12.0
46
+ end
47
+
48
+
49
+ it "should calculate shipping with one product with no shipping category" do
50
+ @product1 = mock_model(Product, :shipping_category => nil)
51
+ @variant1 = mock_model(Variant, :product => @product1)
52
+
53
+ @line_item1 = mock_model(LineItem, :variant => @variant1, :quantity => 7)
54
+
55
+ @product2 = mock_model(Product, :shipping_category => @shipping_category1)
56
+ @variant2 = mock_model(Variant, :product => @product2)
57
+ @line_item2 = mock_model(LineItem, :variant => @variant2, :quantity => 2)
58
+
59
+ @line_items = [@line_item1, @line_item2]
60
+ @order = mock_model(Order, :line_items => @line_items)
61
+ @shipment = mock_model(Shipment, :order => @order, :address => @address)
62
+
63
+ Spree::FlexiRateShipping::Calculator.new().calculate_shipping(@shipment).should == 12.0
64
+ end
65
+
66
+ it "should calculate shipping with no shipping category" do
67
+ @product1 = mock_model(Product, :shipping_category => nil)
68
+ @variant1 = mock_model(Variant, :product => @product1)
69
+
70
+ @line_item1 = mock_model(LineItem, :variant => @variant1, :quantity => 7)
71
+ @line_items = [@line_item1]
72
+ @order = mock_model(Order, :line_items => @line_items)
73
+ @shipment = mock_model(Shipment, :order => @order, :address => @address)
74
+
75
+ Spree::FlexiRateShipping::Calculator.new().calculate_shipping(@shipment).should == 0.0
76
+ end
77
+
78
+ it "should calculate shipping correctly using one flexi shipping rate and one product" do
79
+ @line_item1 = mock_model(LineItem, :variant => @variant1, :quantity => 7)
80
+ @line_items = [@line_item1]
81
+ @order = mock_model(Order, :line_items => @line_items)
82
+ @shipment = mock_model(Shipment, :order => @order, :address => @address)
83
+
84
+ Spree::FlexiRateShipping::Calculator.new().calculate_shipping(@shipment).should == 30.0
85
+ end
86
+
87
+ it "should calculate shipping correctly using one flexi shipping rate and multiple products" do
88
+ @line_item1 = mock_model(LineItem, :variant => @variant1, :quantity => 3)
89
+
90
+ @product2 = mock_model(Product, :shipping_category => @shipping_category1)
91
+ @variant2 = mock_model(Variant, :product => @product2)
92
+ @line_item2 = mock_model(LineItem, :variant => @variant2, :quantity => 2)
93
+
94
+ @product3 = mock_model(Product, :shipping_category => @shipping_category1)
95
+ @variant3 = mock_model(Variant, :product => @product3)
96
+ @line_item3 = mock_model(LineItem, :variant => @variant3, :quantity => 4)
97
+
98
+ @line_items = [@line_item1, @line_item2, @line_item3]
99
+ @order = mock_model(Order, :line_items => @line_items)
100
+ @shipment = mock_model(Shipment, :order => @order, :address => @address)
101
+
102
+ Spree::FlexiRateShipping::Calculator.new().calculate_shipping(@shipment).should == 34.0
103
+ end
104
+
105
+ it "should calculate shipping correctly using two different flexi shipping rates" do
106
+
107
+ @flexi_shipping_rate2 = mock_model(FlexiShippingRate, :first_item_price => 50, :additional_item_price => 10, :max_items => 10, :zone => @zone)
108
+ @shipping_category2 = mock_model(ShippingCategory, :flexi_shipping_rates => [@flexi_shipping_rate2])
109
+ @product2 = mock_model(Product, :shipping_category => @shipping_category2)
110
+ @variant2 = mock_model(Variant, :product => @product2)
111
+
112
+ @line_item1 = mock_model(LineItem, :variant => @variant1, :quantity => 6)
113
+ @line_item2 = mock_model(LineItem, :variant => @variant2, :quantity => 3)
114
+ @line_items = [@line_item1, @line_item2]
115
+ @order = mock_model(Order, :line_items => @line_items)
116
+ @shipment = mock_model(Shipment, :order => @order, :address => @address)
117
+
118
+ Spree::FlexiRateShipping::Calculator.new().calculate_shipping(@shipment).should == 90.0
119
+ end
120
+
121
+
122
+ it "should calculate shipping correctly using two different flexi shipping rates, one with no addition_item_price" do
123
+
124
+ @flexi_shipping_rate2 = mock_model(FlexiShippingRate, :first_item_price => 50, :additional_item_price => nil, :max_items => 1, :zone => @zone)
125
+ @shipping_category2 = mock_model(ShippingCategory, :flexi_shipping_rates => [@flexi_shipping_rate2])
126
+ @product2 = mock_model(Product, :shipping_category => @shipping_category2)
127
+ @variant2 = mock_model(Variant, :product => @product2)
128
+
129
+ @line_item1 = mock_model(LineItem, :variant => @variant1, :quantity => 6)
130
+ @line_item2 = mock_model(LineItem, :variant => @variant2, :quantity => 1)
131
+ @line_items = [@line_item1, @line_item2]
132
+ @order = mock_model(Order, :line_items => @line_items)
133
+ @shipment = mock_model(Shipment, :order => @order, :address => @address)
134
+
135
+ Spree::FlexiRateShipping::Calculator.new().calculate_shipping(@shipment).should == 70.0
136
+ end
137
+
138
+
139
+ end
@@ -0,0 +1,16 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe FlexiShippingRate do
4
+ before(:each) do
5
+ @flexi_shipping_rate = FlexiShippingRate.new
6
+ end
7
+
8
+ ['first item price', 'max items'].each do |field|
9
+ it "should require #{field}" do
10
+ @flexi_shipping_rate.max_items = nil
11
+ @flexi_shipping_rate.valid?.should be_false
12
+ @flexi_shipping_rate.errors.full_messages.should include("#{field.capitalize} can't be blank")
13
+ end
14
+ end
15
+
16
+ end
@@ -0,0 +1,6 @@
1
+ --colour
2
+ --format
3
+ specdoc
4
+ --loadby
5
+ mtime
6
+ --reverse
@@ -0,0 +1,14 @@
1
+ # Configure Rails Environment
2
+ ENV['RAILS_ENV'] = "test"
3
+
4
+ require File.expand_path('../dummy/config/environment.rb', __FILE__)
5
+
6
+ require 'rspec/rails'
7
+
8
+ Dir[Rails.root.join('spec/support/**/*.rb')].each {|f| require f}
9
+
10
+ Rspec.configure do |config|
11
+ config.mock_with :rspec
12
+ config.use_transactional_fixtures = true
13
+ end
14
+
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/spree/flexi_rate_shipping/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.platform = Gem::Platform::RUBY
6
+ gem.authors = ["Chris Boertien"]
7
+ gem.email = ["chris.boertien@gmail.com"]
8
+ gem.description = %q(Provides flexible shipping rate configuration)
9
+ gem.summary = %q(Provides flexible shipping rate configuration.)
10
+ gem.homepage = "http://github.com/BZLabs/spree-flexi-rate-shipping"
11
+ gem.required_ruby_version = '>= 1.8.7'
12
+
13
+ gem.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
14
+ gem.files = `git ls-files`.split("\n")
15
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ gem.name = "spree_flexi_rate_shipping"
17
+ gem.require_paths = ["lib"]
18
+ gem.version = SpreeFlexiRateShipping::VERSION
19
+ gem.requirements << 'none'
20
+ gem.add_dependency 'spree_core', '>= 0.70.1'
21
+ gem.add_development_dependency 'rspec-rails'
22
+ gem.add_development_dependency 'sqlite3'
23
+ end
24
+
metadata ADDED
@@ -0,0 +1,115 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: spree_flexi_rate_shipping
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.0.beta
5
+ prerelease: 6
6
+ platform: ruby
7
+ authors:
8
+ - Chris Boertien
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-11-23 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: spree_core
16
+ requirement: &76850930 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 0.70.1
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *76850930
25
+ - !ruby/object:Gem::Dependency
26
+ name: rspec-rails
27
+ requirement: &76850230 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *76850230
36
+ - !ruby/object:Gem::Dependency
37
+ name: sqlite3
38
+ requirement: &76849610 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *76849610
47
+ description: Provides flexible shipping rate configuration
48
+ email:
49
+ - chris.boertien@gmail.com
50
+ executables: []
51
+ extensions: []
52
+ extra_rdoc_files: []
53
+ files:
54
+ - .gitignore
55
+ - Gemfile
56
+ - README.markdown
57
+ - Rakefile
58
+ - Versionfile
59
+ - app/controllers/admin/configurations_controller_decorator.rb
60
+ - app/controllers/admin/flexi_shipping_rates_controller.rb
61
+ - app/helpers/admin/flexi_shipping_rates_helper.rb
62
+ - app/models/flexi_shipping_rate.rb
63
+ - app/models/product_decorator.rb
64
+ - app/models/shipping_category_decorator.rb
65
+ - app/models/zone_decorator.rb
66
+ - app/views/admin/flexi_shipping_rates/_form.html.erb
67
+ - app/views/admin/flexi_shipping_rates/edit.html.erb
68
+ - app/views/admin/flexi_shipping_rates/index.html.erb
69
+ - app/views/admin/flexi_shipping_rates/new.html.erb
70
+ - config/locales/en-GB.yml
71
+ - config/locales/en-US.yml
72
+ - config/roues.rb
73
+ - db/migrate/20081020154802_create_flexi_shipping_rates.rb
74
+ - db/sample/flexi_shipping_rates.yml
75
+ - db/sample/shipping_categories.yml
76
+ - db/sample/shipping_methods.yml
77
+ - lib/generators/spree_flexi_rate_shipping/install_generator.rb
78
+ - lib/spree/flexi_rate_shipping/calculator.rb
79
+ - lib/spree/flexi_rate_shipping/engine.rb
80
+ - lib/spree/flexi_rate_shipping/version.rb
81
+ - lib/spree_flexi_rate_shipping.rb
82
+ - lib/tasks/flexi_rate_shipping_extension_tasks.rake
83
+ - script/rails
84
+ - spec/controllers/admin/flexi_shipping_rates_controller_spec.rb
85
+ - spec/models/flexi_shipping_calculator_spec.rb
86
+ - spec/models/flexi_shipping_rate_spec.rb
87
+ - spec/spec.opts
88
+ - spec/spec_helper.rb
89
+ - spree_flexi_rate_shipping.gemspec
90
+ homepage: http://github.com/BZLabs/spree-flexi-rate-shipping
91
+ licenses: []
92
+ post_install_message:
93
+ rdoc_options: []
94
+ require_paths:
95
+ - lib
96
+ required_ruby_version: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: 1.8.7
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ none: false
104
+ requirements:
105
+ - - ! '>'
106
+ - !ruby/object:Gem::Version
107
+ version: 1.3.1
108
+ requirements:
109
+ - none
110
+ rubyforge_project:
111
+ rubygems_version: 1.8.10
112
+ signing_key:
113
+ specification_version: 3
114
+ summary: Provides flexible shipping rate configuration.
115
+ test_files: []