mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-02-27 01:43:22 +00:00
Merge branch 'master' of github.com:eaterprises/openfoodweb
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -35,3 +35,4 @@ config/heroku_env.rb
|
||||
config/initializers/feature_toggle.rb
|
||||
NERD_tree*
|
||||
coverage
|
||||
libpeerconnection.log
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
13
app/helpers/checkout_helper.rb
Normal file
13
app/helpers/checkout_helper.rb
Normal file
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
36
app/views/spree/checkout/_summary.html.erb
Normal file
36
app/views/spree/checkout/_summary.html.erb
Normal file
@@ -0,0 +1,36 @@
|
||||
<!-- Copied from spree. Modifications marked below. -->
|
||||
<h3><%= t(:order_summary) %></h3>
|
||||
|
||||
<table data-hook="order_summary">
|
||||
<tbody>
|
||||
<tr data-hook="item_total">
|
||||
<td><strong><%= t(:item_total) %>:</strong></td>
|
||||
<td><strong><%= order.display_item_total %></strong></td>
|
||||
</tr>
|
||||
<tbody id="summary-order-charges" data-hook>
|
||||
<!-- Begin modifications -->
|
||||
<% adjustments = checkout_adjustments_for_summary(order) %>
|
||||
<% adjustments.each do |adjustment| %>
|
||||
<tr>
|
||||
<td><%= adjustment.label %>: </td>
|
||||
<td><%= adjustment.display_amount.to_html %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<!-- End modifications -->
|
||||
</tbody>
|
||||
<tr data-hook="order_total">
|
||||
<td><strong><%= t(:order_total) %>:</strong></td>
|
||||
<td><strong><span id='summary-order-total'><%= @order.display_total.to_html %></span></strong></td>
|
||||
</tr>
|
||||
<% if order.price_adjustment_totals.present? %>
|
||||
<tbody id="price-adjustments" data-hook="order_details_price_adjustments">
|
||||
<% @order.price_adjustment_totals.each do |label, total| %>
|
||||
<tr class="total">
|
||||
<td><strong><%= label %></strong></td>
|
||||
<td><strong><span><%= total %></span></strong></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -32,5 +32,5 @@ Collection / Delivery Details
|
||||
|
||||
Thanks for your support.
|
||||
|
||||
Marcus and Angie,
|
||||
Local Organics
|
||||
<%= @order.distributor.contact %>,
|
||||
<%= @order.distributor.name %>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
9
spec/support/feature_toggle_helper.rb
Normal file
9
spec/support/feature_toggle_helper.rb
Normal file
@@ -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
|
||||
Reference in New Issue
Block a user