spree_additional_calculators 0.1.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 ADDED
@@ -0,0 +1,12 @@
1
+ \#*
2
+ *~
3
+ .#*
4
+ .DS_Store
5
+ .idea
6
+ .project
7
+ tmp
8
+ nbproject
9
+ *.swp
10
+ spec/test_app
11
+ Gemfile
12
+ *.gem
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,61 @@
1
+ Additional Spree Calculators
2
+ ============================
3
+
4
+ This gem contains additional calculators for [Spree Commerce](http://spreecommerce.com)
5
+
6
+ Currently there is only a single calculator implemented but the infrastructure allows to easily add more.
7
+
8
+ * "Weight And Quantity" calculator determines the shipping and handling cost based on total
9
+ item weigh and number or items in the order.
10
+
11
+
12
+
13
+ Usage
14
+ ----
15
+
16
+ Add the following line to your Rails 3 application:
17
+
18
+ gem 'spree_additional_calculators'
19
+
20
+ And then run:
21
+
22
+ $ bundle
23
+ $ rake spree_additional_calculators:install
24
+
25
+ Then go to [Configuration](http://localhost:3000/admin/configurations) and choose [Shipping Methods](http://localhost:3000/admin/shipping_methods)
26
+ And you will be able to select a new calculator - **Weight and Quantity**
27
+ Create the calculator and define the **Default item weight**.
28
+ That value will be used if you do not have defined the weight for your products.
29
+
30
+ After that you can go to [Configuration](http://localhost:3000/admin/configurations) and choose
31
+ [Additional Calculator Rates](http://localhost:3000/admin/additional_calculator_rates)
32
+ Click **Edit** and you will be able to add new or edit/remove existing weight and quantity ranges.
33
+
34
+ *This page is using Javascript to add and remove items in the browser. The changes are made only when you press the* **Update** *button.*
35
+
36
+ Development
37
+ -----------
38
+
39
+ In order to add a new calculator or fix a bug in existing one you will need both the spree source
40
+ and the extension source locally on your computer.
41
+
42
+ $ git clone https://jurgis@github.com/jurgis/spree-additional-calculators.git spree_additional_calculators
43
+ $ git clone https://github.com/spree/spree.git
44
+
45
+ You can test the extension by executing following commands:
46
+
47
+ $ cd spree_additional_calculators
48
+ $ rake test_app SPREE_PATH='../spree'
49
+ $ rake
50
+
51
+
52
+ TODO
53
+ ----
54
+
55
+ * Add RSpec tests
56
+ * Possibly add some cucumber scenarios
57
+ * Possibly use unobtrusive javascript
58
+
59
+
60
+
61
+ Copyright (c) 2011 Jurgis Jurksta, released under the New BSD License
data/Rakefile ADDED
@@ -0,0 +1,81 @@
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
+
24
+ desc "Default Task"
25
+ task :default => [ :spec ]
26
+ # task :default => [:spec, :cucumber ]
27
+
28
+ spec = eval(File.read('spree_additional_calculators.gemspec'))
29
+
30
+ Rake::GemPackageTask.new(spec) do |p|
31
+ p.gem_spec = spec
32
+ end
33
+
34
+
35
+ desc "Release to gemcutter"
36
+ task :release => :package do
37
+ require 'rake/gemcutter'
38
+ Rake::Gemcutter::Tasks.new(spec).define
39
+ Rake::Task['gem:push'].invoke
40
+ end
41
+
42
+
43
+ desc "Regenerates a rails 3 app for testing"
44
+ task :test_app do
45
+ SPREE_PATH = ENV['SPREE_PATH']
46
+ raise "SPREE_PATH should be specified" unless SPREE_PATH
47
+ require File.join(SPREE_PATH, 'lib/generators/spree/test_app_generator')
48
+ class SpreeAdditionalCalculatorTestAppGenerator < Spree::Generators::TestAppGenerator
49
+
50
+ def tweak_gemfile
51
+ append_file 'Gemfile' do
52
+ <<-gems
53
+ gem 'spree_core', :path => '#{File.join(SPREE_PATH, 'core')}'
54
+ gem 'spree_auth', :path => '#{File.join(SPREE_PATH, 'auth')}'
55
+ gem 'spree_additional_calculators', :path => '#{File.dirname(__FILE__)}'
56
+ gems
57
+ end
58
+ end
59
+
60
+ def install_gems
61
+ inside "test_app" do
62
+ run 'rake spree_core:install'
63
+ run 'rake spree_auth:install'
64
+ run 'rake spree_additional_calculators:install'
65
+ end
66
+ end
67
+
68
+ def migrate_db
69
+ run_migrations
70
+ end
71
+ end
72
+ SpreeAdditionalCalculatorTestAppGenerator.start
73
+ end
74
+
75
+
76
+ namespace :test_app do
77
+ desc 'Rebuild test and cucumber databases'
78
+ task :rebuild_dbs do
79
+ system("cd spec/test_app && rake db:drop db:migrate RAILS_ENV=test && rake db:drop db:migrate RAILS_ENV=cucumber")
80
+ end
81
+ end
data/Versionfile ADDED
@@ -0,0 +1 @@
1
+ "0.50.x" => { :branch => "master" }
@@ -0,0 +1,39 @@
1
+ class Admin::AdditionalCalculatorRatesController < Admin::BaseController
2
+ # resource_controller - not using because too much customization required
3
+ layout 'admin'
4
+ helper Admin::AdditionalCalculatorsHelper
5
+
6
+ before_filter :load_calculator, :only => [:edit, :update]
7
+
8
+ def index
9
+ @calculators = Calculator.where(:is_additional_calculator => true).order('created_at DESC')
10
+ end
11
+
12
+ def edit
13
+ @rates_by_type = get_rates_by_type(@calculator)
14
+ end
15
+
16
+ def update
17
+ if @calculator.update_attributes(params[:additional_calculator_weight_and_quantity]) # TODO: this must be changed!!!
18
+ flash[:notice] = t('resource_controller.successfully_updated')
19
+ redirect_to edit_admin_additional_calculator_rate_url(@calculator)
20
+ else
21
+ @rates_by_type = get_rates_by_type(@calculator, false) # set @rates_by_type before rendering the view
22
+ render :action => 'edit'
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def load_calculator
29
+ @calculator = Calculator.find(params[:id])
30
+ end
31
+
32
+ def get_rates_by_type(calculator, load_from_db = true)
33
+ rates_by_type = {}
34
+ calculator.supported_types.each { |type| rates_by_type[type] = [] }
35
+ rates = load_from_db ? calculator.sorted_rates : calculator.additional_calculator_rates
36
+ rates.each { |rate| rates_by_type[rate.rate_type] << rate }
37
+ rates_by_type
38
+ end
39
+ end
@@ -0,0 +1,20 @@
1
+ module Admin::AdditionalCalculatorsHelper
2
+
3
+ # Removes the rate fields
4
+ def link_to_remove_additional_calculator_rate_fields(name, f)
5
+ f.hidden_field(:_destroy) + link_to_function(name, 'remove_additional_calculator_rate_fields(this)')
6
+ end
7
+
8
+ # Adds the rate fields
9
+ def link_to_add_additional_calculator_rate_fields(name, f, association, attributes ={})
10
+ new_object = f.object.class.reflect_on_association(association).klass.new
11
+ new_object.attributes = attributes
12
+
13
+ fields = f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder|
14
+ render(association.to_s.singularize + "_fields", :f => builder)
15
+ end
16
+
17
+ link_to_function(name, %Q[add_additional_calculator_rate_fields(this, "#{association}", "#{escape_javascript(fields)}")])
18
+ end
19
+
20
+ end
@@ -0,0 +1,56 @@
1
+ class AdditionalCalculator::Base < Calculator
2
+ has_many :additional_calculator_rates,
3
+ :as => :calculator,
4
+ :dependent => :destroy
5
+
6
+ accepts_nested_attributes_for :additional_calculator_rates,
7
+ :allow_destroy => true,
8
+ :reject_if => lambda {|attr| attr[:from_value].blank? && attr[:to_value].blank? && attr[:rate].blank?}
9
+
10
+ before_save :set_is_additional_calculator
11
+
12
+ # Register the calculator
13
+ def self.register
14
+ super
15
+ ShippingMethod.register_calculator(self)
16
+ end
17
+
18
+ # Return calculator name
19
+ def name
20
+ calculable.respond_to?(:name) ? calculable.name : calculable.to_s
21
+ end
22
+
23
+ # supported types for the specified calculator (weight, qnty, ...)
24
+ # all the types are supported by default
25
+ def supported_types
26
+ AdditionalCalculatorRate.all_types
27
+ end
28
+
29
+ def sorted_rates
30
+ additional_calculator_rates.order("rate_type ASC, from_value ASC")
31
+ end
32
+
33
+ protected
34
+
35
+ # Get the rate from the database or nil if could not find the rate for the specified rate type
36
+ def get_rate(value, rate_type)
37
+ AdditionalCalculatorRate.find_rate(self.id, rate_type, value)
38
+ end
39
+
40
+ # Get the previous rate if rate for the specified value does not exist, return nil if no previous rate can be find
41
+ def get_previous_rate(value, rate_type)
42
+ AdditionalCalculatorRate.find_previous_rate(self.id, rate_type, value)
43
+ end
44
+
45
+ # Before saving the record set that this is the additional calculator
46
+ def set_is_additional_calculator
47
+ self.is_additional_calculator = true
48
+ end
49
+
50
+ # get the line items
51
+ def object_to_line_items(object)
52
+ return object.line_items if object.is_a?(Order)
53
+ return object.send(:order).line_items if object.respond_to?(:order)
54
+ nil
55
+ end
56
+ end
@@ -0,0 +1,59 @@
1
+ class AdditionalCalculator::WeightAndQuantity < AdditionalCalculator::Base
2
+ # if weight is not defined for an item, use this instead
3
+ preference :default_item_weight, :decimal, :default => 0
4
+
5
+ # The description of the calculator
6
+ def self.description
7
+ I18n.t('calculator_names.weight_and_quantity')
8
+ end
9
+
10
+ # object can be [Order, Shipment] and maybe something else ...
11
+ def compute(object)
12
+ line_items = object_to_line_items(object)
13
+ return nil if line_items.nil?
14
+
15
+ total_qnty = get_total_qnty(line_items)
16
+ weight_rate = get_rate(get_total_weight(line_items), AdditionalCalculatorRate::WEIGHT)
17
+
18
+ # NOTE: Maybe that has been fixed in the spree 0.50.x
19
+ # # sometimes the compute method is called without checking if the calculator is available
20
+ # if weight_rate.nil?
21
+ # logger.warn("The calculator's #{name} weight_rate is nil - returning. Availability is not checked!")
22
+ # return nil
23
+ # end
24
+
25
+ # quantity rate might be nil if the specified range is not available
26
+ qnty_rate = get_rate(total_qnty, AdditionalCalculatorRate::QNTY)
27
+ # find the previous qnty rate or set it to 0 if not found
28
+ qnty_rate = get_previous_rate(total_qnty, AdditionalCalculatorRate::QNTY) || 0 if qnty_rate.nil?
29
+
30
+ # the total rate is sum of weight and quantity rates
31
+ weight_rate + qnty_rate
32
+ end
33
+
34
+ # check if this calculator is available for the Order
35
+ def available?(object)
36
+ line_items = object_to_line_items(object)
37
+ return false if line_items.nil?
38
+
39
+ weight_rate = get_rate(get_total_weight(line_items), AdditionalCalculatorRate::WEIGHT)
40
+ !weight_rate.nil? # available only if the weight rate is not nil
41
+ end
42
+
43
+ protected
44
+
45
+ # get total weight of the order
46
+ def get_total_weight(line_items)
47
+ line_items.map do |li|
48
+ # use default item weight if the weight is not defined for a product
49
+ item_weight = li.variant.weight.nil? ? self.preferred_default_item_weight : li.variant.weight
50
+ item_weight * li.quantity
51
+ end.sum
52
+ end
53
+
54
+ # get total item quantity of the order
55
+ def get_total_qnty(line_items)
56
+ line_items.map(&:quantity).sum
57
+ end
58
+
59
+ end
@@ -0,0 +1,37 @@
1
+ class AdditionalCalculatorRate < ActiveRecord::Base
2
+
3
+ # Types (0 is the default value for the column, therefore I'm not using it)
4
+ WEIGHT = 1 # Total item weight
5
+ QNTY = 2 # Total item quantity
6
+
7
+ belongs_to :calculator
8
+
9
+ scope :for_type, lambda {|type| where(:rate_type => type) }
10
+ scope :for_calculator, lambda {|calculator_id| where(:calculator_id => calculator_id) }
11
+ scope :for_value, lambda {|value| where("from_value <= ? AND ? <= to_value", value, value)}
12
+
13
+ validates :calculator_id, :rate_type, :from_value, :to_value, :rate, :presence => true
14
+ validates :from_value, :to_value, :rate, :numericality => true, :allow_blank => true
15
+
16
+ def validate
17
+ errors.add(:base, I18n.t('errors.from_value_greater_than_to_value')) if from_value > to_value
18
+ end
19
+
20
+ # All complex calculator rate types
21
+ def self.all_types
22
+ [WEIGHT, QNTY]
23
+ end
24
+
25
+ # Find the rate for the specified value
26
+ def self.find_rate(calculator_id, rate_type, value)
27
+ # get the lowes rate if multiple rates are defined (overlaps)
28
+ rate = for_calculator(calculator_id).for_type(rate_type).for_value(value).order("rate").first()
29
+ rate.nil? ? nil : rate.rate
30
+ end
31
+
32
+ # Find the previous rate for the specified value
33
+ def self.find_previous_rate(calculator_id, rate_type, value)
34
+ rate = for_calculator(calculator_id).for_type(rate_type).where("to_value <= ?", value).order("rate DESC").first()
35
+ rate.nil? ? nil : rate.rate
36
+ end
37
+ end
@@ -0,0 +1,10 @@
1
+ <tr class="additional_calculator_rate_fields">
2
+ <td width="100px">&nbsp;</td>
3
+ <td><%= f.text_field :from_value, :size => 10 %></td>
4
+ <td><%= f.text_field :to_value, :size => 10 %></td>
5
+ <td>
6
+ <%= f.text_field :rate, :size => 10 %>
7
+ <%= link_to_remove_additional_calculator_rate_fields(t('remove'), f) %>
8
+ <%= f.hidden_field :rate_type %>
9
+ </td>
10
+ </tr>
@@ -0,0 +1,37 @@
1
+ <%= render "shared/error_messages", :target => @calculator %>
2
+ <h1><%= t("additional_calculator_rates") %></h1>
3
+ <h2><%=h "#{@calculator.name} (#{@calculator.description})" %></h2>
4
+
5
+ <%= form_for(@calculator, :url => admin_additional_calculator_rate_path, :html => { :method => :put}) do |f| %>
6
+
7
+ <table class="edit">
8
+ <% @calculator.supported_types.each do |rate_type| %>
9
+ <thead>
10
+ <tr>
11
+ <th><%= t("rate_type_#{rate_type}") %>:</th>
12
+ <th><%= t("from") %></th>
13
+ <th><%= t("to") %></th>
14
+ <th><%= t("value") %></th>
15
+ </tr>
16
+ </thead>
17
+
18
+ <tbody>
19
+ <%= f.fields_for :additional_calculator_rates, @rates_by_type[rate_type] do |rate_fields| %>
20
+ <%= render 'additional_calculator_rate_fields', :f => rate_fields %>
21
+ <% end %>
22
+
23
+ <tr>
24
+ <td colspan="4">
25
+ <%= link_to_add_additional_calculator_rate_fields(t('add_new'), f, :additional_calculator_rates,
26
+ { :rate_type => rate_type, :from_value => nil, :to_value => nil, :rate => nil }) %>
27
+ </td>
28
+ </tr>
29
+ </tbody>
30
+ <% end %>
31
+ </table>
32
+
33
+ <p class="form-buttons">
34
+ <%= button t('update') %>
35
+ <%= t("or") %> <%= link_to t("cancel"), admin_additional_calculator_rates_path %>
36
+ </p>
37
+ <% end %>
@@ -0,0 +1,23 @@
1
+ <h1><%= t("additional_calculators") %></h1>
2
+
3
+ <table class="index">
4
+ <thead>
5
+ <tr>
6
+ <th><%= t("shipping_method")%></th>
7
+ <th><%= t("calculator")%></th>
8
+ <th><%= t("action")%></th>
9
+ </tr>
10
+ </thead>
11
+ <tbody>
12
+ <% @calculators.each do |calculator| %>
13
+ <tr>
14
+ <td><%= calculator.name %></td>
15
+ <td><%= calculator.description %></td>
16
+ <td><%= link_to_with_icon('edit', t("edit"), edit_admin_additional_calculator_rate_path(calculator)) %></td>
17
+ </tr>
18
+ <% end %>
19
+ <% if @calculators.empty? %>
20
+ <tr><td colspan="5"><%= t(:none) %></td></tr>
21
+ <% end %>
22
+ </tbody>
23
+ </table>
@@ -0,0 +1,3 @@
1
+ <% if @current_controller == 'additional_calculator_rates' %>
2
+ <%= javascript_include_tag 'additional_calculators', :cache => true %>
3
+ <% end -%>
@@ -0,0 +1,11 @@
1
+ <% if target && target.errors.any? %>
2
+ <div id="errorExplanation" class="errorExplanation">
3
+ <h2><%= t(:errors_prohibited_this_record_from_being_saved, :count => target.errors.count) %>:</h2>
4
+ <p><%= t(:there_were_problems_with_the_following_fields) %>:</p>
5
+ <ul>
6
+ <% target.errors.full_messages.each do |msg| %>
7
+ <li><%= msg %></li>
8
+ <% end %>
9
+ </ul>
10
+ </div>
11
+ <% end %>
@@ -0,0 +1,19 @@
1
+ ---
2
+ en:
3
+ calculator_names:
4
+ weight_and_quantity: Weight and Quantity
5
+
6
+ errors:
7
+ from_value_greater_than_to_value: "'From' value is greater than 'To' value"
8
+
9
+ additional_calculator_rates: Additional Calculator Rates
10
+ additional_calculator_rates_description: Configure rates for additional calculators
11
+ additional_calculators: Additional Calculators
12
+ weight: Weight
13
+ quantity: Quantity
14
+ add_new: Add New
15
+ rate_type_1: Weight
16
+ rate_type_2: Quantity
17
+ from: From
18
+ to: To
19
+ default_item_weight: Default item weight
@@ -0,0 +1,19 @@
1
+ ---
2
+ lv:
3
+ calculator_names:
4
+ weight_and_quantity: "Svars un skaits"
5
+
6
+ errors:
7
+ from_value_greater_than_to_value: "'No' vērtība ir lielāka par 'Līdz' vērtību"
8
+
9
+ additional_calculator_rates: "Papildus kalkulatoru aprēķinu tabula"
10
+ additional_calculator_rates_description: "Aizpildiet papildus kalkulatoru aprēķinu tabulas"
11
+ additional_calculators: "Papildus kalkulatori"
12
+ weight: "Svars"
13
+ quantity: "Skaits"
14
+ add_new: "Pievienot jaunu ierakstu"
15
+ rate_type_1: "Svars"
16
+ rate_type_2: "Skaits"
17
+ from: "No"
18
+ to: "Līdz"
19
+ default_item_weight: "Noklusētais preces svars"
data/config/routes.rb ADDED
@@ -0,0 +1,6 @@
1
+ Rails.application.routes.draw do
2
+ # Add your extension routes here
3
+ namespace :admin do
4
+ resources :additional_calculator_rates, :only => [ :index, :edit, :update ]
5
+ end
6
+ end
@@ -0,0 +1,35 @@
1
+ class CreateAdditionalCalculatorRates < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :additional_calculator_rates do |t|
4
+ t.integer :calculator_id, :null => false
5
+ t.string :calculator_type, :null => false, :limit => 50
6
+ t.integer :rate_type, :null => false, :default => 0
7
+ t.decimal :from_value, :null => false, :precision => 8, :scale => 3, :default => 0.0
8
+ t.decimal :to_value, :null => false, :precision => 8, :scale => 3, :default => 0.0
9
+ t.decimal :rate, :null => false, :precision => 8, :scale => 2, :default => 0.0
10
+
11
+ t.timestamps
12
+ end
13
+
14
+ add_index(:additional_calculator_rates, :calculator_id)
15
+ add_index(:additional_calculator_rates, :calculator_type)
16
+ add_index(:additional_calculator_rates, :rate_type)
17
+ add_index(:additional_calculator_rates, :from_value)
18
+ add_index(:additional_calculator_rates, :to_value)
19
+
20
+ add_column(:calculators, :is_additional_calculator, :boolean, :default => false)
21
+ add_index(:calculators, :is_additional_calculator)
22
+ end
23
+
24
+ def self.down
25
+ remove_index(:additional_calculator_rates, :calculator_id)
26
+ remove_index(:additional_calculator_rates, :calculator_type)
27
+ remove_index(:additional_calculator_rates, :rate_type)
28
+ remove_index(:additional_calculator_rates, :from_value)
29
+ remove_index(:additional_calculator_rates, :to_value)
30
+ drop_table(:additional_calculator_rates)
31
+
32
+ remove_index(:calculators, :is_additional_calculator)
33
+ remove_column(:calculators, :is_additional_calculator)
34
+ end
35
+ end
@@ -0,0 +1,28 @@
1
+ require 'spree_core'
2
+ require 'spree_additional_calculators_hooks'
3
+
4
+ module SpreeAdditionalCalculators
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
+ #register all calculators
15
+ [
16
+ AdditionalCalculator::WeightAndQuantity
17
+ ].each do |c_model|
18
+ begin
19
+ c_model.register if c_model.table_exists?
20
+ rescue Exception => e
21
+ $stderr.puts "Error registering calculator #{c_model}"
22
+ end
23
+ end
24
+ end
25
+
26
+ config.to_prepare &method(:activate).to_proc
27
+ end
28
+ end
@@ -0,0 +1,12 @@
1
+ class SpreeAdditionalCalculatorsHooks < Spree::ThemeSupport::HookListener
2
+ # custom hooks go here
3
+
4
+ # Add a link on admin configuration page
5
+ insert_after :admin_configurations_menu do
6
+ %(<%= configurations_menu_item(t("additional_calculator_rates"), admin_additional_calculator_rates_path, t("additional_calculator_rates_description")) %>)
7
+ end
8
+
9
+ # Add js file to the head section
10
+ insert_after :admin_inside_head, 'shared/additional_calculators_admin_head'
11
+
12
+ end
@@ -0,0 +1,25 @@
1
+ namespace :spree_additional_calculators 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_additional_calculators:install:migrations'].invoke
5
+ Rake::Task['spree_additional_calculators: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
@@ -0,0 +1,10 @@
1
+ function remove_additional_calculator_rate_fields(link) {
2
+ $(link).prev("input[type=hidden]").val("1");
3
+ $(link).closest(".additional_calculator_rate_fields").hide();
4
+ }
5
+
6
+ function add_additional_calculator_rate_fields(link, association, content) {
7
+ var new_id = new Date().getTime();
8
+ var regexp = new RegExp("new_" + association, "g");
9
+ $(link).parent().parent().before(content.replace(regexp, new_id));
10
+ }
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe AdditionalCalculatorRate do
4
+ it "should do ..." do
5
+
6
+ end
7
+ end
@@ -0,0 +1,30 @@
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
+ RSpec.configure do |config|
12
+ # == Mock Framework
13
+ #
14
+ # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
15
+ #
16
+ # config.mock_with :mocha
17
+ # config.mock_with :flexmock
18
+ # config.mock_with :rr
19
+ config.mock_with :rspec
20
+
21
+ config.fixture_path = "#{::Rails.root}/spec/fixtures"
22
+
23
+ #config.include Devise::TestHelpers, :type => :controller
24
+ # If you're not using ActiveRecord, or you'd prefer not to run each of your
25
+ # examples within a transaction, comment the following line or assign false
26
+ # instead of true.
27
+ config.use_transactional_fixtures = true
28
+ end
29
+
30
+ @configuration ||= AppConfiguration.find_or_create_by_name("Default configuration")
@@ -0,0 +1,19 @@
1
+ Gem::Specification.new do |s|
2
+ s.platform = Gem::Platform::RUBY
3
+ s.name = 'spree_additional_calculators'
4
+ s.version = '0.1.0'
5
+ s.summary = 'Additional calculators for spree'
6
+ s.description = 'Allows to calculate shipping costs based on total item weigh and quantity in the order'
7
+ s.required_ruby_version = '>= 1.8.7'
8
+
9
+ s.author = 'Jurgis Jurksta'
10
+ s.email = 'jurgis@emails.lv'
11
+ s.homepage = 'https://github.com/jurgis/spree-additional-calculators'
12
+
13
+ s.files = `git ls-files`.split("\n")
14
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
+ s.require_path = 'lib'
16
+ s.requirements << 'none'
17
+
18
+ s.add_dependency('spree_core', '>= 0.50.2')
19
+ end
data/test_app.sh ADDED
@@ -0,0 +1 @@
1
+ rake test_app SPREE_PATH='~/rails/spree'
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: spree_additional_calculators
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.1.0
6
+ platform: ruby
7
+ authors:
8
+ - Jurgis Jurksta
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-05-03 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: spree_core
17
+ prerelease: false
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.50.2
24
+ type: :runtime
25
+ version_requirements: *id001
26
+ description: Allows to calculate shipping costs based on total item weigh and quantity in the order
27
+ email: jurgis@emails.lv
28
+ executables: []
29
+
30
+ extensions: []
31
+
32
+ extra_rdoc_files: []
33
+
34
+ files:
35
+ - .gitignore
36
+ - LICENSE
37
+ - README.md
38
+ - Rakefile
39
+ - Versionfile
40
+ - app/controllers/admin/additional_calculator_rates_controller.rb
41
+ - app/helpers/admin/additional_calculators_helper.rb
42
+ - app/models/additional_calculator/base.rb
43
+ - app/models/additional_calculator/weight_and_quantity.rb
44
+ - app/models/additional_calculator_rate.rb
45
+ - app/views/admin/additional_calculator_rates/_additional_calculator_rate_fields.html.erb
46
+ - app/views/admin/additional_calculator_rates/edit.html.erb
47
+ - app/views/admin/additional_calculator_rates/index.html.erb
48
+ - app/views/shared/_additional_calculators_admin_head.html.erb
49
+ - app/views/shared/_error_messages.html.erb
50
+ - config/locales/en.yml
51
+ - config/locales/lv.yml
52
+ - config/routes.rb
53
+ - db/migrate/20110430062411_create_additional_calculator_rates.rb
54
+ - lib/spree_additional_calculators.rb
55
+ - lib/spree_additional_calculators_hooks.rb
56
+ - lib/tasks/install.rake
57
+ - lib/tasks/spree_additional_calculators.rake
58
+ - public/javascripts/additional_calculators.js
59
+ - spec/app/models/additional_calculator_rate_spec.rb
60
+ - spec/spec_helper.rb
61
+ - spree_additional_calculators.gemspec
62
+ - test_app.sh
63
+ homepage: https://github.com/jurgis/spree-additional-calculators
64
+ licenses: []
65
+
66
+ post_install_message:
67
+ rdoc_options: []
68
+
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: 1.8.7
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ none: false
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: "0"
83
+ requirements:
84
+ - none
85
+ rubyforge_project:
86
+ rubygems_version: 1.7.2
87
+ signing_key:
88
+ specification_version: 3
89
+ summary: Additional calculators for spree
90
+ test_files:
91
+ - spec/app/models/additional_calculator_rate_spec.rb
92
+ - spec/spec_helper.rb