diff --git a/.gitignore b/.gitignore
index 78e0a36aef..12c35da681 100644
--- a/.gitignore
+++ b/.gitignore
@@ -35,3 +35,4 @@ config/heroku_env.rb
config/initializers/feature_toggle.rb
NERD_tree*
coverage
+libpeerconnection.log
diff --git a/app/controllers/admin/enterprises_controller.rb b/app/controllers/admin/enterprises_controller.rb
index a297eadc9c..981299a8ea 100644
--- a/app/controllers/admin/enterprises_controller.rb
+++ b/app/controllers/admin/enterprises_controller.rb
@@ -24,7 +24,7 @@ module Admin
end
def collection
- super.order('is_primary_producer DESC, is_distributor ASC, name')
+ super.managed_by(spree_current_user).order('is_primary_producer DESC, is_distributor ASC, name')
end
end
end
diff --git a/app/controllers/enterprises_controller.rb b/app/controllers/enterprises_controller.rb
index 772dd88265..9ea4f41a43 100644
--- a/app/controllers/enterprises_controller.rb
+++ b/app/controllers/enterprises_controller.rb
@@ -1,6 +1,7 @@
include Spree::ProductsHelper
+
class EnterprisesController < BaseController
-
+
def index
@enterprises = Enterprise.all
end
@@ -32,6 +33,20 @@ class EnterprisesController < BaseController
@products = @searcher.retrieve_products
end
+ def shop
+ distributor = Enterprise.is_distributor.find params[:id]
+ order = current_order(true)
+
+ if order.distributor and order.distributor != distributor
+ order.empty!
+ end
+
+ order.distributor = distributor
+ order.save!
+
+ redirect_to main_app.enterprise_path(distributor)
+ end
+
# essentially the new 'show' action that renders non-spree view
# will need to be renamed into show once the old one is removed
def shop_front
diff --git a/app/controllers/spree/admin/payment_methods_controller_decorator.rb b/app/controllers/spree/admin/payment_methods_controller_decorator.rb
new file mode 100644
index 0000000000..d1d367fc47
--- /dev/null
+++ b/app/controllers/spree/admin/payment_methods_controller_decorator.rb
@@ -0,0 +1,14 @@
+Spree::Admin::PaymentMethodsController.class_eval do
+ # Only show payment methods that user has access to.
+ # ! Redundant code copied from Spree::Admin::ResourceController with two added lines
+ def collection
+ return parent.send(controller_name) if parent_data.present?
+ if model_class.respond_to?(:accessible_by) && !current_ability.has_block?(params[:action], model_class)
+ model_class.accessible_by(current_ability, action).
+ managed_by(spree_current_user) # this line added
+ else
+ model_class.scoped.
+ managed_by(spree_current_user) # this line added
+ end
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/spree/admin/payments_controller_decorator.rb b/app/controllers/spree/admin/payments_controller_decorator.rb
index 4a58dbfe14..23db5eca09 100644
--- a/app/controllers/spree/admin/payments_controller_decorator.rb
+++ b/app/controllers/spree/admin/payments_controller_decorator.rb
@@ -1,14 +1,21 @@
-# When a user fires an event, take them back to where they came from
-# Responder: http://guides.spreecommerce.com/developer/logic.html#overriding-controller-action-responses
-
-# For some strange reason, adding PaymentsController.class_eval will cause gems/spree/app/controllers/spree/admin/payments_controller.rb:37 to error:
-# payments_url not defined.
-# This could be fixed by replacing line 37 with:
-# respond_with(@payment, location: admin_order_payments_url) { |format| format.html { redirect_to admin_order_payments_path(@order) } }
-
-
Spree::Admin::PaymentsController.class_eval do
+ # When a user fires an event, take them back to where they came from
+ # Responder: http://guides.spreecommerce.com/developer/logic.html#overriding-controller-action-responses
+
+ # For some strange reason, adding PaymentsController.class_eval will cause gems/spree/app/controllers/spree/admin/payments_controller.rb:37 to error:
+ # payments_url not defined.
+ # This could be fixed by replacing line 37 with:
+ # respond_with(@payment, location: admin_order_payments_url) { |format| format.html { redirect_to admin_order_payments_path(@order) } }
respond_override :fire => { :html => { :success => lambda {
redirect_to request.referer # Keeps any filter and sort prefs
} } }
+
+ append_before_filter :filter_payment_methods
+
+ # Only show payments for the order's distributor
+ def filter_payment_methods
+ @payment_methods = @payment_methods.select{ |pm| pm.has_distributor? @order.distributor}
+ @payment_method ||= @payment_methods.first
+ end
+
end
diff --git a/app/helpers/checkout_helper.rb b/app/helpers/checkout_helper.rb
new file mode 100644
index 0000000000..b21855bf7a
--- /dev/null
+++ b/app/helpers/checkout_helper.rb
@@ -0,0 +1,13 @@
+module CheckoutHelper
+ def checkout_adjustments_for_summary(order)
+ adjustments = order.adjustments.eligible
+
+ adjustments.reject! { |a| a.originator_type == 'Spree::TaxRate' && a.amount == 0 }
+
+ enterprise_fee_adjustments = adjustments.select { |a| a.originator_type == 'EnterpriseFee' }
+ adjustments.reject! { |a| a.originator_type == 'EnterpriseFee' }
+ adjustments << Spree::Adjustment.new(label: 'Distribution', amount: enterprise_fee_adjustments.sum(&:amount))
+
+ adjustments
+ end
+end
diff --git a/app/models/enterprise_fee.rb b/app/models/enterprise_fee.rb
index 96b062cdd0..05f3828ecd 100644
--- a/app/models/enterprise_fee.rb
+++ b/app/models/enterprise_fee.rb
@@ -12,4 +12,26 @@ class EnterpriseFee < ActiveRecord::Base
scope :for_enterprise, lambda { |enterprise| where(enterprise_id: enterprise) }
+
+
+ def self.clear_all_adjustments_for(line_item)
+ line_item.order.adjustments.where(originator_type: 'EnterpriseFee', source_id: line_item, source_type: 'Spree::LineItem').destroy_all
+ end
+
+ def self.clear_all_adjustments_on_order(order)
+ order.adjustments.where(originator_type: 'EnterpriseFee', source_type: 'Spree::LineItem').destroy_all
+ end
+
+ # Create an adjustment that starts as locked. Preferable to making an adjustment and locking it since
+ # the unlocked adjustment tends to get hit by callbacks before we have a chance to lock it.
+ def create_locked_adjustment(label, target, calculable, mandatory=false)
+ amount = compute_amount(calculable)
+ return if amount == 0 && !mandatory
+ target.adjustments.create({ :amount => amount,
+ :source => calculable,
+ :originator => self,
+ :label => label,
+ :mandatory => mandatory,
+ :locked => true}, :without_protection => true)
+ end
end
diff --git a/app/models/exchange.rb b/app/models/exchange.rb
index fe7f04933c..b56fef9e8b 100644
--- a/app/models/exchange.rb
+++ b/app/models/exchange.rb
@@ -17,4 +17,11 @@ class Exchange < ActiveRecord::Base
scope :incoming, joins(:order_cycle).where('exchanges.receiver_id = order_cycles.coordinator_id')
scope :outgoing, joins(:order_cycle).where('exchanges.sender_id = order_cycles.coordinator_id')
+ scope :from_enterprises, lambda { |enterprises| where('exchanges.sender_id IN (?)', enterprises) }
+ scope :to_enterprises, lambda { |enterprises| where('exchanges.receiver_id IN (?)', enterprises) }
+ scope :with_variant, lambda { |variant| joins(:exchange_variants).where('exchange_variants.variant_id = ?', variant) }
+
+ def incoming?
+ receiver == order_cycle.coordinator
+ end
end
diff --git a/app/models/order_cycle.rb b/app/models/order_cycle.rb
index 51af905060..88bcdefd7e 100644
--- a/app/models/order_cycle.rb
+++ b/app/models/order_cycle.rb
@@ -58,4 +58,52 @@ class OrderCycle < ActiveRecord::Base
end
+ # -- Fees
+ def create_adjustments_for(line_item)
+ fees_for(line_item).each { |fee| create_adjustment_for_fee line_item, fee[:enterprise_fee], fee[:label], fee[:role] }
+ end
+
+
+ private
+
+ # -- Fees
+ def fees_for(line_item)
+ fees = []
+
+ # If there are multiple distributors with this variant, won't this mean that we get a fee charged for each of them?
+ # We just want the one matching line_item.order.distributor
+
+ exchanges_carrying(line_item).each do |exchange|
+ exchange.enterprise_fees.each do |enterprise_fee|
+ role = exchange.incoming? ? 'supplier' : 'distributor'
+ fees << {enterprise_fee: enterprise_fee,
+ label: adjustment_label_for(line_item, enterprise_fee, role),
+ role: role}
+ end
+ end
+
+ coordinator_fees.each do |enterprise_fee|
+ fees << {enterprise_fee: enterprise_fee,
+ label: adjustment_label_for(line_item, enterprise_fee, 'coordinator'),
+ role: 'coordinator'}
+ end
+
+ fees
+ end
+
+ def create_adjustment_for_fee(line_item, enterprise_fee, label, role)
+ a = enterprise_fee.create_locked_adjustment(label, line_item.order, line_item, true)
+ AdjustmentMetadata.create! adjustment: a, enterprise: enterprise_fee.enterprise, fee_name: enterprise_fee.name, fee_type: enterprise_fee.fee_type, enterprise_role: role
+ end
+
+ def adjustment_label_for(line_item, enterprise_fee, role)
+ "#{line_item.variant.product.name} - #{enterprise_fee.fee_type} fee by #{role} #{enterprise_fee.enterprise.name}"
+ end
+
+ def exchanges_carrying(line_item)
+ coordinator = line_item.order.order_cycle.coordinator
+ distributor = line_item.order.distributor
+
+ exchanges.to_enterprises([coordinator, distributor]).with_variant(line_item.variant)
+ end
end
diff --git a/app/models/product_distribution.rb b/app/models/product_distribution.rb
index fbad4e6dd9..22a96dc5f0 100644
--- a/app/models/product_distribution.rb
+++ b/app/models/product_distribution.rb
@@ -8,13 +8,6 @@ class ProductDistribution < ActiveRecord::Base
validates_uniqueness_of :product_id, :scope => :distributor_id
- def ensure_correct_adjustment_for(line_item)
- if enterprise_fee
- clear_all_enterprise_fee_adjustments_for line_item
- create_adjustment_for line_item
- end
- end
-
def adjustment_for(line_item)
adjustments = line_item.order.adjustments.enterprise_fee.where(originator_id: enterprise_fee)
@@ -24,16 +17,11 @@ class ProductDistribution < ActiveRecord::Base
end
def create_adjustment_for(line_item)
- a = enterprise_fee.create_adjustment(adjustment_label_for(line_item), line_item.order, line_item, true)
+ a = enterprise_fee.create_locked_adjustment(adjustment_label_for(line_item), line_item.order, line_item, true)
AdjustmentMetadata.create! adjustment: a, enterprise: enterprise_fee.enterprise, fee_name: enterprise_fee.name, fee_type: enterprise_fee.fee_type, enterprise_role: 'distributor'
end
- def clear_all_enterprise_fee_adjustments_for(line_item)
- line_item.order.adjustments.where(originator_type: 'EnterpriseFee', source_id: line_item, source_type: 'Spree::LineItem').destroy_all
- end
-
def adjustment_label_for(line_item)
"Product distribution by #{distributor.name} for #{line_item.product.name}"
end
-
end
diff --git a/app/models/spree/ability_decorator.rb b/app/models/spree/ability_decorator.rb
index f29b8046c7..eae10efb66 100644
--- a/app/models/spree/ability_decorator.rb
+++ b/app/models/spree/ability_decorator.rb
@@ -30,7 +30,7 @@ class AbilityDecorator
#Enterprise User can only access payment methods for their distributors
can [:index, :create], Spree::PaymentMethod
- can [:admin, :read, :update, :fire, :resend ], Spree::PaymentMethod do |payment_method|
+ can [:admin, :read, :update, :fire, :resend, :destroy ], Spree::PaymentMethod do |payment_method|
user.enterprises.include? payment_method.distributor
end
@@ -40,6 +40,15 @@ class AbilityDecorator
can [:create], OrderCycle
+ can [:index, :read], EnterpriseFee
+ can [:admin, :index, :read, :create, :edit, :update], ExchangeVariant
+ can [:admin, :index, :read, :create, :edit, :update], Exchange
+ can [:admin, :index, :read, :create, :edit, :update], ExchangeFee
+ can [:admin, :index], Enterprise
+ can [:read, :edit, :update], Enterprise do |enterprise|
+ user.enterprises.include? enterprise
+ end
+
end
end
end
diff --git a/app/models/spree/order_decorator.rb b/app/models/spree/order_decorator.rb
index b4d94eb45e..f3ae861c84 100644
--- a/app/models/spree/order_decorator.rb
+++ b/app/models/spree/order_decorator.rb
@@ -54,9 +54,16 @@ Spree::Order.class_eval do
end
def update_distribution_charge!
+ EnterpriseFee.clear_all_adjustments_on_order self
+
line_items.each do |line_item|
- pd = product_distribution_for line_item
- pd.ensure_correct_adjustment_for line_item if pd
+ if provided_by_order_cycle? line_item
+ order_cycle.create_adjustments_for line_item
+
+ else
+ pd = product_distribution_for line_item
+ pd.create_adjustment_for line_item if pd
+ end
end
end
@@ -96,6 +103,11 @@ Spree::Order.class_eval do
end
end
+ def provided_by_order_cycle?(line_item)
+ order_cycle_variants = order_cycle.andand.variants || []
+ order_cycle_variants.include? line_item.variant
+ end
+
def product_distribution_for(line_item)
line_item.variant.product.product_distribution_for self.distributor
end
diff --git a/app/models/spree/payment_method_decorator.rb b/app/models/spree/payment_method_decorator.rb
index f8759ac06b..0f52a4e291 100644
--- a/app/models/spree/payment_method_decorator.rb
+++ b/app/models/spree/payment_method_decorator.rb
@@ -1,6 +1,8 @@
Spree::PaymentMethod.class_eval do
belongs_to :distributor, :class_name => 'Enterprise'
+ validates_presence_of :distributor_id
+
attr_accessible :distributor_id
# -- Scopes
@@ -13,6 +15,10 @@ Spree::PaymentMethod.class_eval do
where('distributor_id IN (?)', user.enterprises.map {|enterprise| enterprise.id })
end
}
+
+ def has_distributor?(distributor)
+ self.distributor == distributor
+ end
end
# Ensure that all derived classes also allow distributor_id
diff --git a/app/overrides/spree/admin/payment_methods/_form/add_distributor_to_admin_payment_method_edit.html.haml.deface b/app/overrides/spree/admin/payment_methods/_form/add_distributor_to_admin_payment_method_edit.html.haml.deface
index 8ac8e7aad9..d15ecec373 100644
--- a/app/overrides/spree/admin/payment_methods/_form/add_distributor_to_admin_payment_method_edit.html.haml.deface
+++ b/app/overrides/spree/admin/payment_methods/_form/add_distributor_to_admin_payment_method_edit.html.haml.deface
@@ -5,5 +5,5 @@
= f.label :distributor
%br
- = collection_select(:payment_method, :distributor_id, Enterprise.is_distributor.managed_by(spree_current_user), :id, :name, {:include_blank => true}, {:class => "select2 fullwidth"})
+ = collection_select(:payment_method, :distributor_id, Enterprise.is_distributor.managed_by(spree_current_user), :id, :name, {:include_blank => false}, {:class => "select2 fullwidth"})
= f.error_message_on :distributor
diff --git a/app/views/spree/checkout/_summary.html.erb b/app/views/spree/checkout/_summary.html.erb
new file mode 100644
index 0000000000..125254177e
--- /dev/null
+++ b/app/views/spree/checkout/_summary.html.erb
@@ -0,0 +1,36 @@
+
+
<%= t(:order_summary) %>
+
+
+
+
+ | <%= t(:item_total) %>: |
+ <%= order.display_item_total %> |
+
+
+
+ <% adjustments = checkout_adjustments_for_summary(order) %>
+ <% adjustments.each do |adjustment| %>
+
+ | <%= adjustment.label %>: |
+ <%= adjustment.display_amount.to_html %> |
+
+ <% end %>
+
+
+
+ | <%= t(:order_total) %>: |
+ <%= @order.display_total.to_html %> |
+
+ <% if order.price_adjustment_totals.present? %>
+
+ <% @order.price_adjustment_totals.each do |label, total| %>
+
+ | <%= label %> |
+ <%= total %> |
+
+ <% end %>
+
+ <% end %>
+
+
diff --git a/app/views/spree/products/_add_to_cart_order_cycle_unavailable.html.haml b/app/views/spree/products/_add_to_cart_order_cycle_unavailable.html.haml
index ba3a99dbbb..d061f0595c 100644
--- a/app/views/spree/products/_add_to_cart_order_cycle_unavailable.html.haml
+++ b/app/views/spree/products/_add_to_cart_order_cycle_unavailable.html.haml
@@ -1,4 +1,4 @@
.error-distributor
Please complete your order from
- = link_to current_order_cycle.name, root_path
+ = link_to (current_order_cycle.andand.name || 'your current order cycle'), root_path
before shopping in a different order cycle.
diff --git a/config/routes.rb b/config/routes.rb
index 41c217ec4a..de946a2627 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -9,7 +9,8 @@ Openfoodweb::Application.routes.draw do
end
member do
- get :shop_front
+ get :shop_front #new world
+ get :shop # old world
end
end
diff --git a/lib/chili/enterprises_distributor_info_rich_text_feature/app/views/spree/order_mailer/confirm_email_with_distributor_info.text.erb b/lib/chili/enterprises_distributor_info_rich_text_feature/app/views/spree/order_mailer/confirm_email_with_distributor_info.text.erb
index e88f053e1a..aa3b59de8c 100644
--- a/lib/chili/enterprises_distributor_info_rich_text_feature/app/views/spree/order_mailer/confirm_email_with_distributor_info.text.erb
+++ b/lib/chili/enterprises_distributor_info_rich_text_feature/app/views/spree/order_mailer/confirm_email_with_distributor_info.text.erb
@@ -32,5 +32,5 @@ Collection / Delivery Details
Thanks for your support.
-Marcus and Angie,
-Local Organics
\ No newline at end of file
+<%= @order.distributor.contact %>,
+<%= @order.distributor.name %>
diff --git a/lib/open_food_web/feature_toggle.rb b/lib/open_food_web/feature_toggle.rb
index ecb5fd1e1d..00834da4e0 100644
--- a/lib/open_food_web/feature_toggle.rb
+++ b/lib/open_food_web/feature_toggle.rb
@@ -11,7 +11,7 @@ module OpenFoodWeb
local_organics: false,
order_cycles: false,
multi_cart: false,
- enterprises_distributor_info_rich_text: false}
+ enterprises_distributor_info_rich_text: true}
end
end
end
diff --git a/lib/tasks/dev.rake b/lib/tasks/dev.rake
index 0c397c6325..97685544a8 100644
--- a/lib/tasks/dev.rake
+++ b/lib/tasks/dev.rake
@@ -16,7 +16,6 @@ namespace :openfoodweb do
country = Spree::Country.find_by_name('Australia')
Spree::ZoneMember.create(:zone => zone, :zoneable => country)
FactoryGirl.create(:shipping_method, :zone => zone)
- FactoryGirl.create(:payment_method, :environment => 'development')
end
@@ -96,6 +95,13 @@ namespace :openfoodweb do
end
end
+ # -- Enterprise Payment Methods
+ unless Spree::PaymentMethod.count > 1
+ Enterprise.is_distributor.each do |distributor|
+ FactoryGirl.create(:payment_method, distributor: distributor, name: "Cheque (#{distributor.name})", :environment => 'development')
+ end
+ end
+
# -- Products
unless Spree::Product.count > 0
puts "[#{task_name}] Seeding products"
diff --git a/spec/controllers/enterprises_controller_spec.rb b/spec/controllers/enterprises_controller_spec.rb
index 45d0374a84..f728210e2e 100644
--- a/spec/controllers/enterprises_controller_spec.rb
+++ b/spec/controllers/enterprises_controller_spec.rb
@@ -9,4 +9,41 @@ describe EnterprisesController do
assigns(:suppliers).should == [s]
end
+
+ context 'shopping for a distributor' do
+
+ before(:each) do
+ @current_distributor = create(:distributor_enterprise)
+ @distributor = create(:distributor_enterprise)
+ controller.current_order(true).distributor = @current_distributor
+ end
+
+ it "sets the shop as the distributor on the order when shopping for the distributor" do
+ spree_get :shop, {id: @distributor}
+
+ controller.current_order.distributor.should == @distributor
+ end
+
+ it "empties an order that was set for a previous distributor, when shopping at a new distributor" do
+ line_item = create(:line_item)
+ controller.current_order.line_items << line_item
+
+ spree_get :shop, {id: @distributor}
+
+ controller.current_order.distributor.should == @distributor
+ controller.current_order.line_items.size.should == 0
+ end
+
+ it "should not empty an order if returning to the same distributor" do
+ product = create(:product)
+ create(:product_distribution, product: product, distributor: @current_distributor)
+ line_item = create(:line_item, variant: product.master)
+ controller.current_order.line_items << line_item
+
+ spree_get :shop, {id: @current_distributor}
+
+ controller.current_order.distributor.should == @current_distributor
+ controller.current_order.line_items.size.should == 1
+ end
+ end
end
diff --git a/spec/factories.rb b/spec/factories.rb
index 82a8efe333..7385352ac5 100644
--- a/spec/factories.rb
+++ b/spec/factories.rb
@@ -7,16 +7,22 @@ FactoryGirl.define do
after(:create) do |oc|
# Suppliers
- ex1 = create(:exchange, :order_cycle => oc, :receiver => oc.coordinator)
- ex2 = create(:exchange, :order_cycle => oc, :receiver => oc.coordinator)
+ ex1 = create(:exchange, :order_cycle => oc,
+ :sender => create(:supplier_enterprise), :receiver => oc.coordinator)
+ ex2 = create(:exchange, :order_cycle => oc,
+ :sender => create(:supplier_enterprise), :receiver => oc.coordinator)
ExchangeFee.create!(exchange: ex1,
enterprise_fee: create(:enterprise_fee, enterprise: ex1.sender))
ExchangeFee.create!(exchange: ex2,
enterprise_fee: create(:enterprise_fee, enterprise: ex2.sender))
# Distributors
- ex3 = create(:exchange, :order_cycle => oc, :sender => oc.coordinator, :pickup_time => 'time 0', :pickup_instructions => 'instructions 0')
- ex4 = create(:exchange, :order_cycle => oc, :sender => oc.coordinator, :pickup_time => 'time 1', :pickup_instructions => 'instructions 1')
+ ex3 = create(:exchange, :order_cycle => oc,
+ :sender => oc.coordinator, :receiver => create(:distributor_enterprise),
+ :pickup_time => 'time 0', :pickup_instructions => 'instructions 0')
+ ex4 = create(:exchange, :order_cycle => oc,
+ :sender => oc.coordinator, :receiver => create(:distributor_enterprise),
+ :pickup_time => 'time 1', :pickup_instructions => 'instructions 1')
ExchangeFee.create!(exchange: ex3,
enterprise_fee: create(:enterprise_fee, enterprise: ex3.receiver))
ExchangeFee.create!(exchange: ex4,
@@ -30,6 +36,11 @@ FactoryGirl.define do
exchange.variants << product.master
end
+
+ variants = [ex1, ex2].map(&:variants).flatten
+ [ex3, ex4].each do |exchange|
+ variants.each { |v| exchange.variants << v }
+ end
end
end
@@ -84,12 +95,15 @@ FactoryGirl.define do
is_distributor true
end
+ sequence(:calculator_amount)
factory :enterprise_fee, :class => EnterpriseFee do
+ ignore { amount nil }
+
sequence(:name) { |n| "Enterprise fee #{n}" }
+ sequence(:fee_type) { |n| EnterpriseFee::FEE_TYPES[n % EnterpriseFee::FEE_TYPES.count] }
enterprise { Enterprise.first || FactoryGirl.create(:supplier_enterprise) }
- fee_type 'packing'
- calculator { FactoryGirl.build(:weight_calculator) }
+ calculator { Spree::Calculator::PerItem.new(preferred_amount: amount || generate(:calculator_amount)) }
after(:create) { |ef| ef.calculator.save! }
end
@@ -144,6 +158,18 @@ FactoryGirl.modify do
state { Spree::State.find_by_name 'Victoria' }
country { Spree::Country.find_by_name 'Australia' || Spree::Country.first }
end
+
+ factory :payment do
+ ignore do
+ distributor { order.distributor || Enterprise.is_distributor.first || FactoryGirl.create(:distributor_enterprise) }
+ end
+ payment_method { FactoryGirl.create(:payment_method, distributor: distributor) }
+ end
+
+ factory :payment_method do
+ distributor { Enterprise.is_distributor.first || FactoryGirl.create(:distributor_enterprise) } #Always need a distributor
+ end
+
end
diff --git a/spec/features/admin/enterprise_fees_spec.rb b/spec/features/admin/enterprise_fees_spec.rb
index e2af5bb65e..9d011ce493 100644
--- a/spec/features/admin/enterprise_fees_spec.rb
+++ b/spec/features/admin/enterprise_fees_spec.rb
@@ -17,7 +17,8 @@ feature %q{
end
scenario "listing enterprise fees" do
- fee = create(:enterprise_fee, name: '$0.50 / kg')
+ fee = create(:enterprise_fee, name: '$0.50 / kg', fee_type: 'packing')
+ amount = fee.calculator.preferred_amount
login_to_admin_section
click_link 'Configuration'
@@ -26,8 +27,8 @@ feature %q{
page.should have_selector "#enterprise_fee_set_collection_attributes_0_enterprise_id"
page.should have_selector "option[selected]", text: 'Packing'
page.should have_selector "input[value='$0.50 / kg']"
- page.should have_selector "option[selected]", text: 'Weight (per kg)'
- page.should have_selector "input[value='0.5']"
+ page.should have_selector "option[selected]", text: 'Flat Rate (per item)'
+ page.should have_selector "input[value='#{amount}']"
end
scenario "creating an enterprise fee" do
diff --git a/spec/features/admin/enterprises_spec.rb b/spec/features/admin/enterprises_spec.rb
index 3f7e72ba88..db97f28b9f 100644
--- a/spec/features/admin/enterprises_spec.rb
+++ b/spec/features/admin/enterprises_spec.rb
@@ -6,12 +6,12 @@ feature %q{
} do
include AuthenticationWorkflow
include WebHelper
-
+
before :all do
@default_wait_time = Capybara.default_wait_time
Capybara.default_wait_time = 5
end
-
+
after :all do
Capybara.default_wait_time = @default_wait_time
end
@@ -127,4 +127,31 @@ feature %q{
Enterprise.is_distributor.map { |d| d.next_collection_at }.should == %w(One Two Three)
end
+ context 'as an Enterprise user' do
+
+ let(:supplier1) { create(:supplier_enterprise, name: 'First Supplier') }
+ let(:supplier2) { create(:supplier_enterprise, name: 'Another Supplier') }
+ let(:distributor1) { create(:distributor_enterprise, name: 'First Distributor') }
+ let(:distributor2) { create(:distributor_enterprise, name: 'Another Distributor') }
+
+ before(:each) do
+ @new_user = create_enterprise_user
+ @new_user.enterprise_roles.build(enterprise: supplier1).save
+ @new_user.enterprise_roles.build(enterprise: distributor1).save
+
+ login_to_admin_as @new_user
+ end
+
+ scenario "can view enterprises I have permission to" do
+ oc_user_coordinating = create(:simple_order_cycle, { coordinator: supplier1, name: 'Order Cycle 1' } )
+ oc_for_other_user = create(:simple_order_cycle, { coordinator: supplier2, name: 'Order Cycle 2' } )
+
+ click_link "Enterprises"
+
+ page.should have_content supplier1.name
+ page.should have_content distributor1.name
+ page.should_not have_content supplier2.name
+ page.should_not have_content distributor2.name
+ end
+ end
end
diff --git a/spec/features/admin/order_cycles_spec.rb b/spec/features/admin/order_cycles_spec.rb
index c1bada0060..9697504901 100644
--- a/spec/features/admin/order_cycles_spec.rb
+++ b/spec/features/admin/order_cycles_spec.rb
@@ -206,6 +206,7 @@ feature %q{
scenario "updating an order cycle" do
# Given an order cycle with all the settings
oc = create(:order_cycle)
+ initial_variants = oc.variants
# And a coordinating, supplying and distributing enterprise with some products with variants
coordinator = create(:distributor_enterprise, name: 'My coordinator')
@@ -311,7 +312,7 @@ feature %q{
OrderCycle.last.exchanges.outgoing.last.enterprise_fee_ids.should == [distributor_fee2.id]
# And it should have some variants selected
- OrderCycle.last.variants.map { |v| v.id }.sort.should == [1, v1.id, v2.id].sort
+ OrderCycle.last.variants.map(&:id).sort.should == (initial_variants.map(&:id) + [v1.id, v2.id]).sort
# And the collection details should have been updated
OrderCycle.last.exchanges.where(pickup_time: 'New time 0', pickup_instructions: 'New instructions 0').should be_present
diff --git a/spec/features/chili/enterprises_distributor_info_rich_text_feature_spec.rb b/spec/features/chili/enterprises_distributor_info_rich_text_feature_spec.rb
index cd95945f8b..ae919c1a04 100644
--- a/spec/features/chili/enterprises_distributor_info_rich_text_feature_spec.rb
+++ b/spec/features/chili/enterprises_distributor_info_rich_text_feature_spec.rb
@@ -80,6 +80,7 @@ feature "enterprises distributor info as rich text" do
complete_purchase_from_checkout_address_page
wait_until { ActionMailer::Base.deliveries.length == 1 }
email = ActionMailer::Base.deliveries.last
+ binding.pry
email.body.should =~ /Chu ge sai yubi dan bisento tobi ashi yubi ge omote./
email.body.should =~ /Thursday 2nd May/
end
diff --git a/spec/features/consumer/checkout_spec.rb b/spec/features/consumer/checkout_spec.rb
index d9220c59aa..d474ea76bc 100644
--- a/spec/features/consumer/checkout_spec.rb
+++ b/spec/features/consumer/checkout_spec.rb
@@ -18,6 +18,8 @@ feature %q{
end
background do
+ set_feature_toggle :order_cycles, true
+
@distributor = create(:distributor_enterprise, :name => 'Edible garden',
:address => create(:address,
:address1 => '12 Bungee Rd',
@@ -37,11 +39,11 @@ feature %q{
:country => Spree::Country.find_by_name('Australia')),
:pickup_times => 'Tuesday, 4 PM')
- @enterprise_fee_1 = create(:enterprise_fee, :name => 'Shipping Method One', :calculator => Spree::Calculator::FlatRate.new)
+ @enterprise_fee_1 = create(:enterprise_fee, :name => 'Enterprise Fee One', :calculator => Spree::Calculator::PerItem.new)
@enterprise_fee_1.calculator.set_preference :amount, 1
@enterprise_fee_1.calculator.save!
- @enterprise_fee_2 = create(:enterprise_fee, :name => 'Shipping Method Two', :calculator => Spree::Calculator::FlatRate.new)
+ @enterprise_fee_2 = create(:enterprise_fee, :name => 'Enterprise Fee Two', :calculator => Spree::Calculator::PerItem.new)
@enterprise_fee_2.calculator.set_preference :amount, 2
@enterprise_fee_2.calculator.save!
@@ -49,22 +51,26 @@ feature %q{
@product_1.product_distributions.create(:distributor => @distributor, :enterprise_fee => @enterprise_fee_1)
@product_1.product_distributions.create(:distributor => @distributor_alternative, :enterprise_fee => @enterprise_fee_1)
+ @product_1a = create(:product, :name => 'Sundowner apples')
+ @product_1a.product_distributions.create(:distributor => @distributor, :enterprise_fee => @enterprise_fee_1)
+ @product_1a.product_distributions.create(:distributor => @distributor_alternative, :enterprise_fee => @enterprise_fee_1)
+
@product_2 = create(:product, :name => 'Garlic')
@product_2.product_distributions.create(:distributor => @distributor, :enterprise_fee => @enterprise_fee_2)
@product_2.product_distributions.create(:distributor => @distributor_alternative, :enterprise_fee => @enterprise_fee_2)
+ # -- Shipping
@zone = create(:zone)
c = Spree::Country.find_by_name('Australia')
Spree::ZoneMember.create(:zoneable => c, :zone => @zone)
create(:shipping_method, zone: @zone)
- @payment_method_all = create(:payment_method, :name => 'Cheque payment method', :description => 'Cheque payment method') #valid for any distributor
@payment_method_distributor = create(:payment_method, :name => 'Edible Garden payment method', :distributor => @distributor)
@payment_method_alternative = create(:payment_method, :name => 'Alternative Distributor payment method', :distributor => @distributor_alternative)
end
- scenario "viewing delivery fees" do
+ scenario "viewing delivery fees for product distribution" do
# Given I am logged in
login_to_consumer_section
@@ -78,28 +84,133 @@ feature %q{
click_button 'Add To Cart'
# Then I should see a breakdown of my delivery fees:
- # Item | Shipping Method | Delivery Fee
- # Garlic | Shipping Method Two | $2.00
- # Fuji apples | Shipping Method One | $1.00
- #
- # Subtotal: $3.00
+ checkout_fees_table.should ==
+ [['Product distribution by Edible garden for Fuji apples', '$1.00', ''],
+ ['Product distribution by Edible garden for Garlic', '$2.00', '']]
- # Disabled pending spec for the new table
- # table = page.find 'table#delivery'
- # rows = table.all('tr')
- # rows[0].all('th').map { |cell| cell.text.strip }.should == ['Item', 'Shipping Method', 'Delivery Fee']
- # rows[1].all('td').map { |cell| cell.text.strip }.should == ['Fuji apples', 'Shipping Method One', '$1.00']
- # rows[2].all('td').map { |cell| cell.text.strip }.should == ['Garlic', 'Shipping Method Two', '$2.00']
- # page.should have_selector '#delivery-fees span.order-total', :text => '$3.00'
+ page.should have_selector 'span.distribution-total', :text => '$3.00'
+ end
+
+ scenario "viewing delivery fees for order cycle distribution" do
+ # Given an order cycle
+ make_order_cycle
+
+ # And I am logged in
+ login_to_consumer_section
+
+ # When I add some bananas and zucchini to my cart
+ click_link 'Bananas'
+ select @distributor_oc.name, :from => 'distributor_id'
+ select @order_cycle.name, :from => 'order_cycle_id'
+ click_button 'Add To Cart'
+ click_link 'Continue shopping'
+
+ click_link 'Zucchini'
+ click_button 'Add To Cart'
+
+ # Then I should see a breakdown of my delivery fees:
+ checkout_fees_table.should ==
+ [["Bananas - packing fee by supplier Supplier 1", "$3.00", ""],
+ ["Bananas - transport fee by supplier Supplier 1", "$4.00", ""],
+ ["Bananas - packing fee by distributor Distributor 1", "$7.00", ""],
+ ["Bananas - transport fee by distributor Distributor 1", "$8.00", ""],
+ ["Bananas - admin fee by coordinator My coordinator", "$1.00", ""],
+ ["Bananas - sales fee by coordinator My coordinator", "$2.00", ""],
+ ["Zucchini - admin fee by supplier Supplier 2", "$5.00", ""],
+ ["Zucchini - sales fee by supplier Supplier 2", "$6.00", ""],
+ ["Zucchini - packing fee by distributor Distributor 1", "$7.00", ""],
+ ["Zucchini - transport fee by distributor Distributor 1", "$8.00", ""],
+ ["Zucchini - admin fee by coordinator My coordinator", "$1.00", ""],
+ ["Zucchini - sales fee by coordinator My coordinator", "$2.00", ""]]
+
+ page.should have_selector 'span.distribution-total', :text => '$54.00'
+ end
+
+ scenario "attempting to purchase products that mix product and order cycle distribution" do
+ # Given some products, one with product distribution only, (@product1)
+ # one with order cycle distribution only, (@product_oc)
+ supplier = create(:supplier_enterprise)
+ product_oc = create(:simple_product, name: 'Feijoas')
+ @order_cycle = create(:simple_order_cycle, suppliers: [supplier], distributors: [@distributor], variants: [product_oc.master])
+ @order_cycle.coordinator_fees << create(:enterprise_fee, enterprise: @order_cycle.coordinator)
+
+ # And I am logged in
+ login_to_consumer_section
+
+ # When I add the first to my cart
+ click_link 'Fuji apples'
+ select @distributor.name, :from => 'distributor_id'
+ click_button 'Add To Cart'
+ click_link 'Continue shopping'
+
+ # And I attempt to add another
+ click_link 'Feijoas'
+
+ # Then I should see an error about changing order cycle
+ page.should have_content 'Please complete your order from your current order cycle before shopping in a different order cycle.'
+ end
+
+ scenario "removing a product from cart removes its fees", js: true do
+ # Given I am logged in
+ login_to_consumer_section
+
+ # When I add some apples and some garlic to my cart
+ click_link 'Fuji apples'
+ select @distributor.name, :from => 'distributor_id'
+ click_button 'Add To Cart'
+ click_link 'Continue shopping'
+
+ click_link 'Garlic'
+ click_button 'Add To Cart'
+
+ # And I remove the applies
+ line_item = Spree::Order.last.line_items.first
+ page.find("a#delete_line_item_#{line_item.id}").click
+
+ # Then I should see fees for only the garlic
+ checkout_fees_table.should ==
+ [['Product distribution by Edible garden for Garlic', '$2.00', '']]
+
+ page.should have_selector 'span.distribution-total', :text => '$2.00'
+ end
+
+ scenario "adding products with differing quantities produces correct fees" do
+ # Given I am logged in
+ login_to_consumer_section
+
+ # When I add two products to my cart that share the same enterprise fee
+ click_link 'Fuji apples'
+ select @distributor.name, :from => 'distributor_id'
+ click_button 'Add To Cart'
+ click_link 'Continue shopping'
+
+ click_link 'Sundowner apples'
+ click_button 'Add To Cart'
+
+ # Then I should have some delivery fees
+ checkout_fees_table.should ==
+ [['Product distribution by Edible garden for Fuji apples', '$1.00', ''],
+ ['Product distribution by Edible garden for Sundowner apples', '$1.00', '']]
+ page.should have_selector 'span.distribution-total', :text => '$2.00'
+
+ # And I update the quantity of one of them
+ fill_in 'order_line_items_attributes_0_quantity', with: 2
+ click_button 'Update'
+
+ # Then I should see updated delivery fees
+ checkout_fees_table.should ==
+ [['Product distribution by Edible garden for Fuji apples', '$2.00', ''],
+ ['Product distribution by Edible garden for Sundowner apples', '$1.00', '']]
+ page.should have_selector 'span.distribution-total', :text => '$3.00'
end
scenario "changing distributor updates delivery fees" do
# Given two distributors and enterprise fees
d1 = create(:distributor_enterprise)
d2 = create(:distributor_enterprise)
- ef1 = create(:enterprise_fee, calculator: Spree::Calculator::FlatRate.new)
+ ef1 = create(:enterprise_fee, calculator: Spree::Calculator::PerItem.new)
ef1.calculator.set_preference :amount, 1.23; ef1.calculator.save!
- ef2 = create(:enterprise_fee, calculator: Spree::Calculator::FlatRate.new)
+ ef2 = create(:enterprise_fee, calculator: Spree::Calculator::PerItem.new)
ef2.calculator.set_preference :amount, 2.34; ef2.calculator.save!
# And two products both available from both distributors
@@ -177,18 +288,9 @@ feature %q{
# Distributor details should be displayed
within('fieldset#shipping') do
[@distributor.name,
- @distributor.address.address1,
- @distributor.address.city,
- @distributor.address.zipcode,
- @distributor.address.state_text,
- @distributor.address.country.name,
- @distributor.pickup_times,
- @distributor.next_collection_at,
- @distributor.contact,
- @distributor.phone,
- @distributor.email,
- @distributor.description,
- @distributor.website].each do |value|
+ @distributor.distributor_info,
+ @distributor.next_collection_at
+ ].each do |value|
page.should have_content value
end
@@ -201,13 +303,12 @@ feature %q{
# -- Checkout: Delivery
order_charges = page.all("tbody#summary-order-charges tr").map {|row| row.all('td').map(&:text)}.take(2)
- order_charges.should == [["Product distribution by Edible garden for Fuji apples:", "$1.00"],
- ["Product distribution by Edible garden for Garlic:", "$2.00"]]
+ order_charges.should == [["Shipping:", "$0.00"],
+ ["Distribution:", "$3.00"]]
click_checkout_continue_button
# -- Checkout: Payment
# Given the distributor I have selected for my order, I should only see payment methods valid for that distributor
- page.should have_selector 'label', :text => @payment_method_all.name
page.should have_selector 'label', :text => @payment_method_distributor.name
page.should_not have_selector 'label', :text => @payment_method_alternative.name
click_checkout_continue_button
@@ -221,4 +322,68 @@ feature %q{
# page.should have_content('On Tuesday, 4 PM')
# page.should have_content('12 Bungee Rd, Carion')
end
+
+
+ private
+
+ def make_order_cycle
+ @order_cycle = oc = create(:simple_order_cycle, coordinator: create(:distributor_enterprise, name: 'My coordinator'))
+
+ # Coordinator
+ coordinator_fee1 = create(:enterprise_fee, enterprise: oc.coordinator, fee_type: 'admin', amount: 1)
+ coordinator_fee2 = create(:enterprise_fee, enterprise: oc.coordinator, fee_type: 'sales', amount: 2)
+ oc.coordinator_fees << coordinator_fee1
+ oc.coordinator_fees << coordinator_fee2
+
+ # Suppliers
+ supplier1 = create(:supplier_enterprise, name: 'Supplier 1')
+ supplier2 = create(:supplier_enterprise, name: 'Supplier 2')
+ supplier_fee1 = create(:enterprise_fee, enterprise: supplier1, fee_type: 'packing', amount: 3)
+ supplier_fee2 = create(:enterprise_fee, enterprise: supplier1, fee_type: 'transport', amount: 4)
+ supplier_fee3 = create(:enterprise_fee, enterprise: supplier2, fee_type: 'admin', amount: 5)
+ supplier_fee4 = create(:enterprise_fee, enterprise: supplier2, fee_type: 'sales', amount: 6)
+ ex1 = create(:exchange, order_cycle: oc, sender: supplier1, receiver: oc.coordinator)
+ ex2 = create(:exchange, order_cycle: oc, sender: supplier2, receiver: oc.coordinator)
+ ExchangeFee.create!(exchange: ex1, enterprise_fee: supplier_fee1)
+ ExchangeFee.create!(exchange: ex1, enterprise_fee: supplier_fee2)
+ ExchangeFee.create!(exchange: ex2, enterprise_fee: supplier_fee3)
+ ExchangeFee.create!(exchange: ex2, enterprise_fee: supplier_fee4)
+
+ # Distributors
+ distributor1 = create(:distributor_enterprise, name: 'Distributor 1')
+ distributor2 = create(:distributor_enterprise, name: 'Distributor 2')
+ distributor_fee1 = create(:enterprise_fee, enterprise: distributor1, fee_type: 'packing', amount: 7)
+ distributor_fee2 = create(:enterprise_fee, enterprise: distributor1, fee_type: 'transport', amount: 8)
+ distributor_fee3 = create(:enterprise_fee, enterprise: distributor2, fee_type: 'admin', amount: 9)
+ distributor_fee4 = create(:enterprise_fee, enterprise: distributor2, fee_type: 'sales', amount: 10)
+ ex3 = create(:exchange, order_cycle: oc,
+ sender: oc.coordinator, receiver: distributor1,
+ pickup_time: 'time 0', pickup_instructions: 'instructions 0')
+ ex4 = create(:exchange, order_cycle: oc,
+ sender: oc.coordinator, receiver: distributor2,
+ pickup_time: 'time 1', pickup_instructions: 'instructions 1')
+ ExchangeFee.create!(exchange: ex3, enterprise_fee: distributor_fee1)
+ ExchangeFee.create!(exchange: ex3, enterprise_fee: distributor_fee2)
+ ExchangeFee.create!(exchange: ex4, enterprise_fee: distributor_fee3)
+ ExchangeFee.create!(exchange: ex4, enterprise_fee: distributor_fee4)
+
+ # Products
+ @distributor_oc = distributor1
+
+ @product_3 = create(:simple_product, name: 'Bananas', supplier: supplier1)
+ ex1.variants << @product_3.master
+ ex3.variants << @product_3.master
+ ex4.variants << @product_3.master
+
+ @product_4 = create(:simple_product, name: 'Zucchini', supplier: supplier2)
+ ex2.variants << @product_4.master
+ ex3.variants << @product_4.master
+ ex4.variants << @product_4.master
+ end
+
+ def checkout_fees_table
+ table = page.find 'tbody#cart_adjustments'
+ rows = table.all 'tr'
+ rows.map { |row| row.all('td').map { |cell| cell.text.strip } }
+ end
end
diff --git a/spec/features/consumer/product_spec.rb b/spec/features/consumer/product_spec.rb
index 4c983294b0..efd4fa1689 100644
--- a/spec/features/consumer/product_spec.rb
+++ b/spec/features/consumer/product_spec.rb
@@ -44,18 +44,9 @@ feature %q{
within '#product-distributor-details' do
[d.name,
- d.address.address1,
- d.address.city,
- d.address.zipcode,
- d.address.state_text,
- d.address.country.name,
- d.pickup_times,
- d.next_collection_at,
- d.contact,
- d.phone,
- d.email,
- d.description,
- d.website].each do |value|
+ d.distributor_info,
+ d.next_collection_at
+ ].each do |value|
page.should have_content value
end
diff --git a/spec/models/ability_spec.rb b/spec/models/ability_spec.rb
index 9007ff8a2a..0d9bb31cc3 100644
--- a/spec/models/ability_spec.rb
+++ b/spec/models/ability_spec.rb
@@ -137,6 +137,27 @@ module Spree
should have_ability([:create], for: OrderCycle)
end
end
+
+ context 'Enterprise manager' do
+ let (:user) do
+ user = create(:user)
+ user.spree_roles = []
+ s1.enterprise_roles.build(user: user).save
+ user
+ end
+
+ it 'should have the ability to read and edit enterprises that I manage' do
+ should have_ability([:read, :edit, :update], for: s1)
+ end
+
+ it 'should not have the ability to read and edit enterprises that I do not manage' do
+ should_not have_ability([:read, :edit, :update], for: s2)
+ end
+
+ it 'should have the ability administrate enterpises' do
+ should have_ability([:admin, :index], for: Enterprise)
+ end
+ end
end
end
end
\ No newline at end of file
diff --git a/spec/models/enterprise_fee_spec.rb b/spec/models/enterprise_fee_spec.rb
index 1616b0decd..98484d6545 100644
--- a/spec/models/enterprise_fee_spec.rb
+++ b/spec/models/enterprise_fee_spec.rb
@@ -8,4 +8,70 @@ describe EnterpriseFee do
describe "validations" do
it { should validate_presence_of(:name) }
end
+
+ describe "clearing all enterprise fee adjustments for a line item" do
+ it "clears adjustments originating from many different enterprise fees" do
+ p = create(:simple_product)
+ d1, d2 = create(:distributor_enterprise), create(:distributor_enterprise)
+ pd1 = create(:product_distribution, product: p, distributor: d1)
+ pd2 = create(:product_distribution, product: p, distributor: d2)
+ line_item = create(:line_item, product: p)
+ pd1.enterprise_fee.create_adjustment('foo1', line_item.order, line_item, true)
+ pd2.enterprise_fee.create_adjustment('foo2', line_item.order, line_item, true)
+
+ expect do
+ EnterpriseFee.clear_all_adjustments_for line_item
+ end.to change(line_item.order.adjustments, :count).by(-2)
+ end
+
+ it "does not clear adjustments originating from another source" do
+ p = create(:simple_product)
+ pd = create(:product_distribution)
+ line_item = create(:line_item, product: pd.product)
+ tax_rate = create(:tax_rate, calculator: build(:calculator, preferred_amount: 10))
+ tax_rate.create_adjustment('foo', line_item.order, line_item)
+
+ expect do
+ EnterpriseFee.clear_all_adjustments_for line_item
+ end.to change(line_item.order.adjustments, :count).by(0)
+ end
+ end
+
+ describe "clearing all enterprise fee adjustments on an order" do
+ it "clears adjustments from many fees and one all line items" do
+ order = create(:order)
+
+ p1 = create(:simple_product)
+ p2 = create(:simple_product)
+ d1, d2 = create(:distributor_enterprise), create(:distributor_enterprise)
+ pd1 = create(:product_distribution, product: p1, distributor: d1)
+ pd2 = create(:product_distribution, product: p1, distributor: d2)
+ pd3 = create(:product_distribution, product: p2, distributor: d1)
+ pd4 = create(:product_distribution, product: p2, distributor: d2)
+ line_item1 = create(:line_item, order: order, product: p1)
+ line_item2 = create(:line_item, order: order, product: p2)
+ pd1.enterprise_fee.create_adjustment('foo1', line_item1.order, line_item1, true)
+ pd2.enterprise_fee.create_adjustment('foo2', line_item1.order, line_item1, true)
+ pd3.enterprise_fee.create_adjustment('foo3', line_item2.order, line_item2, true)
+ pd4.enterprise_fee.create_adjustment('foo4', line_item2.order, line_item2, true)
+
+ expect do
+ EnterpriseFee.clear_all_adjustments_on_order order
+ end.to change(order.adjustments, :count).by(-4)
+ end
+
+ it "does not clear adjustments from another originator" do
+ order = create(:order)
+ tax_rate = create(:tax_rate, calculator: stub_model(Spree::Calculator))
+ order.adjustments.create({:amount => 12.34,
+ :source => order,
+ :originator => tax_rate,
+ :locked => true,
+ :label => 'hello' }, :without_protection => true)
+
+ expect do
+ EnterpriseFee.clear_all_adjustments_on_order order
+ end.to change(order.adjustments, :count).by(0)
+ end
+ end
end
diff --git a/spec/models/exchange_spec.rb b/spec/models/exchange_spec.rb
index 523ee23e5e..3dc72a8a2d 100644
--- a/spec/models/exchange_spec.rb
+++ b/spec/models/exchange_spec.rb
@@ -44,6 +44,24 @@ describe Exchange do
e.enterprise_fees.count.should == 1
end
+ describe "reporting whether it is an incoming exchange" do
+ let(:supplier) { create(:supplier_enterprise) }
+ let(:coordinator) { create(:distributor_enterprise) }
+ let(:distributor) { create(:distributor_enterprise) }
+ let(:oc) { create(:simple_order_cycle, coordinator: coordinator) }
+
+ let(:incoming_exchange) { oc.exchanges.create! sender: supplier, receiver: coordinator }
+ let(:outgoing_exchange) { oc.exchanges.create! sender: coordinator, receiver: distributor }
+
+ it "returns true for incoming exchanges" do
+ incoming_exchange.should be_incoming
+ end
+
+ it "returns false for outgoing exchanges" do
+ outgoing_exchange.should_not be_incoming
+ end
+ end
+
describe "scopes" do
let(:supplier) { create(:supplier_enterprise) }
let(:coordinator) { create(:distributor_enterprise) }
@@ -60,5 +78,23 @@ describe Exchange do
it "finds outgoing exchanges" do
Exchange.outgoing.should == [outgoing_exchange]
end
+
+ it "finds exchanges going to any of a number of enterprises" do
+ Exchange.to_enterprises([coordinator]).should == [incoming_exchange]
+ Exchange.to_enterprises([coordinator, distributor]).should == [incoming_exchange, outgoing_exchange]
+ end
+
+ it "finds exchanges coming from any of a number of enterprises" do
+ Exchange.from_enterprises([coordinator]).should == [outgoing_exchange]
+ Exchange.from_enterprises([supplier, coordinator]).should == [incoming_exchange, outgoing_exchange]
+ end
+
+ it "finds exchanges with a particular variant" do
+ v = create(:variant)
+ ex = create(:exchange)
+ ex.variants << v
+
+ Exchange.with_variant(v).should == [ex]
+ end
end
end
diff --git a/spec/models/order_cycle_spec.rb b/spec/models/order_cycle_spec.rb
index 14c17bce04..e5a2c58970 100644
--- a/spec/models/order_cycle_spec.rb
+++ b/spec/models/order_cycle_spec.rb
@@ -140,4 +140,60 @@ describe OrderCycle do
@oc.products.sort.should == [@p0, @p1, @p2]
end
end
+
+ describe "creating adjustments for a line item" do
+ let(:oc) { OrderCycle.new }
+ let(:line_item) { double(:line_item, variant: 123) }
+
+ it "creates adjustment for each fee" do
+ fee = {enterprise_fee: 'ef', label: 'label', role: 'role'}
+ oc.stub(:fees_for) { [fee] }
+ oc.should_receive(:create_adjustment_for_fee).with(line_item, 'ef', 'label', 'role')
+
+ oc.send(:create_adjustments_for, line_item)
+ end
+
+ it "finds fees for a line item" do
+ ef1 = double(:enterprise_fee)
+ ef2 = double(:enterprise_fee)
+ ef3 = double(:enterprise_fee)
+ incoming_exchange = double(:exchange, enterprise_fees: [ef1], incoming?: true)
+ outgoing_exchange = double(:exchange, enterprise_fees: [ef2], incoming?: false)
+ oc.stub(:exchanges_carrying) { [incoming_exchange, outgoing_exchange] }
+ oc.stub(:coordinator_fees) { [ef3] }
+ oc.stub(:adjustment_label_for) { 'label' }
+
+ oc.send(:fees_for, line_item).should ==
+ [{enterprise_fee: ef1, label: 'label', role: 'supplier'},
+ {enterprise_fee: ef2, label: 'label', role: 'distributor'},
+ {enterprise_fee: ef3, label: 'label', role: 'coordinator'}]
+ end
+
+ it "creates an adjustment for a fee" do
+ line_item = create(:line_item)
+ enterprise_fee = create(:enterprise_fee)
+
+ oc.send(:create_adjustment_for_fee, line_item, enterprise_fee, 'label', 'role')
+
+ adjustment = Spree::Adjustment.last
+ adjustment.label.should == 'label'
+ adjustment.adjustable.should == line_item.order
+ adjustment.source.should == line_item
+ adjustment.originator.should == enterprise_fee
+ adjustment.should be_mandatory
+
+ md = adjustment.metadata
+ md.enterprise.should == enterprise_fee.enterprise
+ md.fee_name.should == enterprise_fee.name
+ md.fee_type.should == enterprise_fee.fee_type
+ md.enterprise_role.should == 'role'
+ end
+
+ it "makes adjustment labels" do
+ line_item = double(:line_item, variant: double(:variant, product: double(:product, name: 'Bananas')))
+ enterprise_fee = double(:enterprise_fee, fee_type: 'packing', enterprise: double(:enterprise, name: 'Ballantyne'))
+
+ oc.send(:adjustment_label_for, line_item, enterprise_fee, 'distributor').should == "Bananas - packing fee by distributor Ballantyne"
+ end
+ end
end
diff --git a/spec/models/order_spec.rb b/spec/models/order_spec.rb
index fe8051ee3c..b64ae72eee 100644
--- a/spec/models/order_spec.rb
+++ b/spec/models/order_spec.rb
@@ -18,24 +18,74 @@ describe Spree::Order do
describe "updating the distribution charge" do
let(:order) { build(:order) }
+ it "clears all enterprise fee adjustments on the order" do
+ EnterpriseFee.should_receive(:clear_all_adjustments_on_order).with(subject)
+ subject.update_distribution_charge!
+ end
+
it "ensures the correct adjustment(s) are created for the product distribution" do
+ EnterpriseFee.stub(:clear_all_adjustments_on_order)
line_item = double(:line_item)
subject.stub(:line_items) { [line_item] }
+ subject.stub(:provided_by_order_cycle?) { false }
product_distribution = double(:product_distribution)
- product_distribution.should_receive(:ensure_correct_adjustment_for).with(line_item)
+ product_distribution.should_receive(:create_adjustment_for).with(line_item)
subject.stub(:product_distribution_for) { product_distribution }
- subject.send(:update_distribution_charge!)
+ subject.update_distribution_charge!
end
it "skips line items that don't have a product distribution" do
+ EnterpriseFee.stub(:clear_all_adjustments_on_order)
line_item = double(:line_item)
subject.stub(:line_items) { [line_item] }
+ subject.stub(:provided_by_order_cycle?) { false }
subject.stub(:product_distribution_for) { nil }
- subject.send(:update_distribution_charge!)
+ subject.update_distribution_charge!
+ end
+
+ it "ensures the correct adjustment(s) are created for order cycles" do
+ EnterpriseFee.stub(:clear_all_adjustments_on_order)
+ line_item = double(:line_item)
+ subject.stub(:line_items) { [line_item] }
+ subject.stub(:provided_by_order_cycle?) { true }
+
+ order_cycle = double(:order_cycle)
+ order_cycle.should_receive(:create_adjustments_for).with(line_item)
+ subject.stub(:order_cycle) { order_cycle }
+
+ subject.update_distribution_charge!
+ end
+
+ describe "looking up whether a line item can be provided by an order cycle" do
+ it "returns true when the variant is provided" do
+ v = double(:variant)
+ line_item = double(:line_item, variant: v)
+ order_cycle = double(:order_cycle, variants: [v])
+ subject.stub(:order_cycle) { order_cycle }
+
+ subject.send(:provided_by_order_cycle?, line_item).should be_true
+ end
+
+ it "returns false otherwise" do
+ v = double(:variant)
+ line_item = double(:line_item, variant: v)
+ order_cycle = double(:order_cycle, variants: [])
+ subject.stub(:order_cycle) { order_cycle }
+
+ subject.send(:provided_by_order_cycle?, line_item).should be_false
+ end
+
+ it "returns false when there is no order cycle" do
+ v = double(:variant)
+ line_item = double(:line_item, variant: v)
+ subject.stub(:order_cycle) { nil }
+
+ subject.send(:provided_by_order_cycle?, line_item).should be_false
+ end
end
it "looks up product distribution enterprise fees for a line item" do
diff --git a/spec/models/product_distribution_spec.rb b/spec/models/product_distribution_spec.rb
index ad18e3f8ad..a2fbf23873 100644
--- a/spec/models/product_distribution_spec.rb
+++ b/spec/models/product_distribution_spec.rb
@@ -65,56 +65,6 @@ describe ProductDistribution do
end
end
- describe "ensuring that a line item has the correct adjustment" do
- let(:enterprise_fee) { EnterpriseFee.new }
- let(:pd) { ProductDistribution.new enterprise_fee: enterprise_fee }
- let(:line_item) { double(:line_item) }
- let(:adjustment) { double(:adjustment) }
-
- # TODO: This spec will go away once enterprise_fee is required
- it "does nothing if there is no enterprise fee set" do
- pd.enterprise_fee = nil
- pd.should_receive(:clear_all_enterprise_fee_adjustments_for).never
- pd.should_receive(:create_adjustment_for).never
- pd.ensure_correct_adjustment_for line_item
- end
-
- describe "adding items to cart" do
- it "clears all enterprise fee adjustments on the line item" do
- pd.should_receive(:clear_all_enterprise_fee_adjustments_for).with(line_item)
- pd.stub(:create_adjustment_for)
- pd.ensure_correct_adjustment_for line_item
- end
-
- it "creates an adjustment on the line item" do
- pd.stub(:clear_all_enterprise_fee_adjustments_for)
- pd.should_receive(:create_adjustment_for).with(line_item)
- pd.ensure_correct_adjustment_for line_item
- end
- end
-
- describe "changing distributor" do
- it "clears and re-creates the adjustment for the line item" do
- # Given a line item with an adjustment via one enterprise fee
- p = create(:simple_product)
- d1, d2 = create(:distributor_enterprise), create(:distributor_enterprise)
- pd1 = create(:product_distribution, product: p, distributor: d1)
- pd2 = create(:product_distribution, product: p, distributor: d2)
- line_item = create(:line_item, product: p)
- pd1.enterprise_fee.create_adjustment('foo', line_item.order, line_item, true)
-
- # When I ensure correct adjustment through the other product distribution
- pd2.ensure_correct_adjustment_for line_item
-
- # Then I should have only an adjustment originating from the other product distribution
- line_item.order.reload
- adjustments = line_item.order.adjustments.enterprise_fee
- adjustments.count.should == 1
- adjustments.first.originator.should == pd2.enterprise_fee
- end
- end
- end
-
describe "finding our adjustment for a line item" do
it "returns nil when not present" do
line_item = build(:line_item)
@@ -125,7 +75,7 @@ describe ProductDistribution do
it "returns the adjustment when present" do
pd = create(:product_distribution)
line_item = create(:line_item)
- adjustment = pd.enterprise_fee.create_adjustment('foo', line_item.order, line_item, true)
+ adjustment = pd.enterprise_fee.create_locked_adjustment('foo', line_item.order, line_item, true)
pd.send(:adjustment_for, line_item).should == adjustment
end
@@ -133,8 +83,8 @@ describe ProductDistribution do
it "raises an error when there are multiple adjustments for this enterprise fee" do
pd = create(:product_distribution)
line_item = create(:line_item)
- pd.enterprise_fee.create_adjustment('one', line_item.order, line_item, true)
- pd.enterprise_fee.create_adjustment('two', line_item.order, line_item, true)
+ pd.enterprise_fee.create_locked_adjustment('one', line_item.order, line_item, true)
+ pd.enterprise_fee.create_locked_adjustment('two', line_item.order, line_item, true)
expect do
pd.send(:adjustment_for, line_item)
@@ -164,34 +114,6 @@ describe ProductDistribution do
md.enterprise_role.should == 'distributor'
end
end
-
- describe "clearing all enterprise fee adjustments for a line item" do
- it "clears adjustments originating from many different enterprise fees" do
- p = create(:simple_product)
- d1, d2 = create(:distributor_enterprise), create(:distributor_enterprise)
- pd1 = create(:product_distribution, product: p, distributor: d1)
- pd2 = create(:product_distribution, product: p, distributor: d2)
- line_item = create(:line_item, product: p)
- pd1.enterprise_fee.create_adjustment('foo1', line_item.order, line_item, true)
- pd2.enterprise_fee.create_adjustment('foo2', line_item.order, line_item, true)
-
- expect do
- pd1.send(:clear_all_enterprise_fee_adjustments_for, line_item)
- end.to change(line_item.order.adjustments, :count).by(-2)
- end
-
- it "does not clear adjustments originating from another source" do
- p = create(:simple_product)
- pd = create(:product_distribution)
- line_item = create(:line_item, product: pd.product)
- tax_rate = create(:tax_rate, calculator: build(:calculator, preferred_amount: 10))
- tax_rate.create_adjustment('foo', line_item.order, line_item)
-
- expect do
- pd.send(:clear_all_enterprise_fee_adjustments_for, line_item)
- end.to change(line_item.order.adjustments, :count).by(0)
- end
- end
end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 42d6fc251f..a60cc125a3 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -80,6 +80,7 @@ RSpec.configure do |config|
config.include Spree::CheckoutHelpers
config.include Spree::Core::TestingSupport::ControllerRequests, :type => :controller
config.include Devise::TestHelpers, :type => :controller
+ config.include OpenFoodWeb::FeatureToggleHelper
# Factory girl
require 'factory_girl_rails'
diff --git a/spec/support/feature_toggle_helper.rb b/spec/support/feature_toggle_helper.rb
new file mode 100644
index 0000000000..054bd9fead
--- /dev/null
+++ b/spec/support/feature_toggle_helper.rb
@@ -0,0 +1,9 @@
+module OpenFoodWeb
+ module FeatureToggleHelper
+ def set_feature_toggle(feature, status)
+ features = OpenFoodWeb::FeatureToggle.features
+ features[feature] = status
+ OpenFoodWeb::FeatureToggle.stub(:features) { features }
+ end
+ end
+end