Merge branch 'optimise-shopfront' into combined/unique-enterprise-names_parallel-fuubars_rob-github-fixes

This commit is contained in:
Rohan Mitchell
2015-06-19 11:34:41 +10:00
18 changed files with 111 additions and 61 deletions

View File

@@ -46,10 +46,12 @@ class ShopController < BaseController
def products_for_shop
if current_order_cycle
scoper = OpenFoodNetwork::ScopeProductToHub.new(current_distributor)
current_order_cycle.
valid_products_distributed_by(current_distributor).
order(taxon_order).
each { |p| p.scope_to_hub current_distributor }.
each { |p| scoper.scope(p) }.
select { |p| !p.deleted? && p.has_stock_for_distribution?(current_order_cycle, current_distributor) }
end
end
@@ -69,9 +71,10 @@ class ShopController < BaseController
# We use the in_stock? method here instead of the in_stock scope because we need to
# look up the stock as overridden by VariantOverrides, and the scope method is not affected
# by them.
scoper = OpenFoodNetwork::ScopeVariantToHub.new(current_distributor)
Spree::Variant.
for_distribution(current_order_cycle, current_distributor).
each { |v| v.scope_to_hub current_distributor }.
each { |v| scoper.scope(v) }.
select(&:in_stock?)
end

View File

@@ -14,9 +14,10 @@ Spree::Admin::VariantsController.class_eval do
if params[:distributor_id].present?
distributor = Enterprise.find params[:distributor_id]
@variants = @variants.in_distributor(distributor)
scoper = OpenFoodNetwork::ScopeVariantToHub.new(distributor)
# Perform scoping after all filtering is done.
# Filtering could be a problem on scoped variants.
@variants.each { |v| v.scope_to_hub(distributor) }
@variants.each { |v| scoper.scope(v) }
end
end

View File

@@ -4,9 +4,10 @@ module Spree
return [] unless order.completed?
#increase inventory to meet initial requirements
scoper = OpenFoodNetwork::ScopeVariantToHub.new(order.distributor)
order.line_items.each do |line_item|
# Scope variant to hub so that stock levels may be subtracted from VariantOverride.
line_item.variant.scope_to_hub order.distributor
scoper.scope(line_item.variant)
increase(order, line_item.variant, line_item.quantity)
end

View File

@@ -9,7 +9,7 @@ Spree::OrderPopulator.class_eval do
errors.add(:base, "That distributor or order cycle can't supply all the products in your cart. Please choose another.")
end
if valid?
if valid?
@order.with_lock do
@order.empty! if overwrite
@@ -33,7 +33,7 @@ Spree::OrderPopulator.class_eval do
def attempt_cart_add(variant_id, quantity, max_quantity = nil)
quantity = quantity.to_i
variant = Spree::Variant.find(variant_id)
variant.scope_to_hub @distributor
OpenFoodNetwork::ScopeVariantToHub.new(@distributor).scope(variant)
if quantity > 0
if check_stock_levels(variant, quantity) &&
check_order_cycle_provided_for(variant) &&

View File

@@ -1,8 +1,4 @@
require 'open_food_network/scope_product_to_hub'
Spree::Product.class_eval do
include OpenFoodNetwork::ProductScopableToHub
# We have an after_destroy callback on Spree::ProductOptionType. However, if we
# don't specify dependent => destroy on this association, it is not called. See:
# https://github.com/rails/rails/issues/7618

View File

@@ -1,10 +1,7 @@
require 'open_food_network/scope_variant_to_hub'
require 'open_food_network/enterprise_fee_calculator'
require 'open_food_network/option_value_namer'
Spree::Variant.class_eval do
include OpenFoodNetwork::VariantScopableToHub
has_many :exchange_variants, dependent: :destroy
has_many :exchanges, through: :exchange_variants
has_many :variant_overrides

View File

@@ -8,6 +8,12 @@ class VariantOverride < ActiveRecord::Base
where(hub_id: hubs)
}
def self.indexed(hub)
Hash[
for_hubs(hub).map { |vo| [vo.variant, vo] }
]
end
def self.price_for(hub, variant)
self.for(hub, variant).andand.price
end
@@ -25,12 +31,21 @@ class VariantOverride < ActiveRecord::Base
if vo.nil?
Bugsnag.notify RuntimeError.new "Attempting to decrement stock level for a variant without a VariantOverride."
elsif vo.count_on_hand.blank?
Bugsnag.notify RuntimeError.new "Attempting to decrement stock level on a VariantOverride without a count_on_hand specified."
else
vo.decrement! :count_on_hand, quantity
vo.decrement_stock! quantity
end
end
def stock_overridden?
count_on_hand.present?
end
def decrement_stock!(quantity)
if stock_overridden?
decrement! :count_on_hand, quantity
else
Bugsnag.notify RuntimeError.new "Attempting to decrement stock level on a VariantOverride without a count_on_hand specified."
end
end

View File

@@ -22,7 +22,12 @@ class Api::UncachedProductSerializer < ActiveModel::Serializer
attributes :price
def price
object.master.price_with_fees(options[:current_distributor], options[:current_order_cycle])
if options[:enterprise_fee_calculator]
object.master.price + options[:enterprise_fee_calculator].indexed_fees_for(object.master)
else
object.master.price_with_fees(options[:current_distributor], options[:current_order_cycle])
end
end
end

View File

@@ -1,5 +1,6 @@
= inject_enterprises
#hubs.hubs{"ng-controller" => "EnterprisesCtrl"}
= inject_enterprises
#hubs.hubs{"ng-controller" => "EnterprisesCtrl", "ng-cloak" => true}
.row
.small-12.columns
%h1 Shop in your local area

View File

@@ -1,16 +1,23 @@
require 'open_food_network/scope_variant_to_hub'
module OpenFoodNetwork
module ScopeProductToHub
def variants_distributed_by(order_cycle, distributor)
super.each { |v| v.scope_to_hub @hub }
end
end
module ProductScopableToHub
def scope_to_hub(hub)
extend OpenFoodNetwork::ScopeProductToHub
class ScopeProductToHub
def initialize(hub)
@hub = hub
@variant_overrides = VariantOverride.indexed @hub
end
def scope(product)
product.send :extend, OpenFoodNetwork::ScopeProductToHub::ScopeProductToHub
product.instance_variable_set :@hub, @hub
product.instance_variable_set :@variant_overrides, @variant_overrides
end
module ScopeProductToHub
def variants_distributed_by(order_cycle, distributor)
super.each { |v| ScopeVariantToHub.new(@hub, @variant_overrides).scope(v) }
end
end
end
end

View File

@@ -1,30 +1,38 @@
module OpenFoodNetwork
module ScopeVariantToHub
def price
VariantOverride.price_for(@hub, self) || super
class ScopeVariantToHub
def initialize(hub, variant_overrides=nil)
@hub = hub
@variant_overrides = variant_overrides || VariantOverride.indexed(@hub)
end
def price_in(currency)
Spree::Price.new(amount: price, currency: currency)
def scope(variant)
variant.send :extend, OpenFoodNetwork::ScopeVariantToHub::ScopeVariantToHub
variant.instance_variable_set :@hub, @hub
variant.instance_variable_set :@variant_override, @variant_overrides[variant]
end
def count_on_hand
VariantOverride.count_on_hand_for(@hub, self) || super
end
def decrement!(attribute, by=1)
if attribute == :count_on_hand && VariantOverride.stock_overridden?(@hub, self)
VariantOverride.decrement_stock! @hub, self, by
else
super
module ScopeVariantToHub
def price
@variant_override.andand.price || super
end
def price_in(currency)
Spree::Price.new(amount: price, currency: currency)
end
def count_on_hand
@variant_override.andand.count_on_hand || super
end
def decrement!(attribute, by=1)
if attribute == :count_on_hand && @variant_override.andand.stock_overridden?
@variant_override.decrement_stock! by
else
super
end
end
end
end
module VariantScopableToHub
def scope_to_hub(hub)
extend OpenFoodNetwork::ScopeVariantToHub
@hub = hub
end
end
end

View File

@@ -3,8 +3,9 @@ Spree::Core::ControllerHelpers::Order.class_eval do
order = current_order_without_scoped_variants(create_order_if_necessary)
if order
scoper = OpenFoodNetwork::ScopeVariantToHub.new(order.distributor)
order.line_items.each do |li|
li.variant.scope_to_hub order.distributor
scoper.scope(li.variant)
end
end

View File

@@ -162,7 +162,10 @@ describe ShopController do
end
it "returns price including fees" do
Spree::Variant.any_instance.stub(:price_with_fees).and_return 998.00
# Price is 19.99
OpenFoodNetwork::EnterpriseFeeCalculator.any_instance.
stub(:indexed_fees_for).and_return 978.01
xhr :get, :products
response.body.should have_content "998.0"
end

View File

@@ -27,6 +27,8 @@ describe Spree::OrdersController do
end
it "redirects home with message if hub is not ready for checkout" do
VariantOverride.stub(:indexed).and_return({})
order = subject.current_order(true)
distributor.stub(:ready_for_checkout?) { false }
order.stub(distributor: distributor, order_cycle: order_cycle)

View File

@@ -5,16 +5,17 @@ module OpenFoodNetwork
let(:hub) { create(:distributor_enterprise) }
let(:v) { create(:variant, price: 11.11, count_on_hand: 1) }
let(:vo) { create(:variant_override, hub: hub, variant: v, price: 22.22, count_on_hand: 2) }
let(:scoper) { ScopeVariantToHub.new(hub) }
describe "overriding price" do
it "returns the overridden price when one is present" do
vo
v.scope_to_hub hub
scoper.scope v
v.price.should == 22.22
end
it "returns the variant's price otherwise" do
v.scope_to_hub hub
scoper.scope v
v.price.should == 11.11
end
end
@@ -22,12 +23,12 @@ module OpenFoodNetwork
describe "overriding price_in" do
it "returns the overridden price when one is present" do
vo
v.scope_to_hub hub
scoper.scope v
v.price_in('AUD').amount.should == 22.22
end
it "returns the variant's price otherwise" do
v.scope_to_hub hub
scoper.scope v
v.price_in('AUD').amount.should == 11.11
end
end
@@ -35,12 +36,12 @@ module OpenFoodNetwork
describe "overriding stock levels" do
it "returns the overridden stock level when one is present" do
vo
v.scope_to_hub hub
scoper.scope v
v.count_on_hand.should == 2
end
it "returns the variant's stock level otherwise" do
v.scope_to_hub hub
scoper.scope v
v.count_on_hand.should == 1
end
end

View File

@@ -21,7 +21,7 @@ module Spree
op.populate(params).should be_false
op.errors.to_a.should == ["That distributor or order cycle can't supply all the products in your cart. Please choose another."]
end
it "empties the order if override is true" do
op.stub(:distribution_can_supply_products_in_cart).and_return true
order.stub(:with_lock).and_yield
@@ -38,7 +38,7 @@ module Spree
it "attempts cart add with max_quantity" do
op.stub(:distribution_can_supply_products_in_cart).and_return true
order.should_receive(:empty!)
params = {variants: {"1" => {quantity: 1, max_quantity: 2}}}
params = {variants: {"1" => {quantity: 1, max_quantity: 2}}}
order.stub(:with_lock).and_yield
op.should_receive(:attempt_cart_add).with("1", 1, 2).and_return true
op.populate(params, true)
@@ -48,9 +48,9 @@ module Spree
describe "attempt_cart_add" do
it "performs additional validations" do
variant = double(:variant)
variant.stub(:scope_to_hub)
quantity = 123
Spree::Variant.stub(:find).and_return(variant)
VariantOverride.stub(:for).and_return(nil)
op.should_receive(:check_stock_levels).with(variant, quantity).and_return(true)
op.should_receive(:check_order_cycle_provided_for).with(variant).and_return(true)

View File

@@ -14,8 +14,16 @@ describe VariantOverride do
it "finds variant overrides for a set of hubs" do
VariantOverride.for_hubs([hub1, hub2]).should match_array [vo1, vo2]
end
describe "fetching variant overrides indexed by variant" do
it "gets indexed variant overrides for one hub" do
VariantOverride.indexed(hub1).should == {v => vo1}
VariantOverride.indexed(hub2).should == {v => vo2}
end
end
end
describe "looking up prices" do
it "returns the numeric price when present" do
VariantOverride.create!(variant: variant, hub: hub, price: 12.34)

View File

@@ -8,11 +8,12 @@ describe ShopController, type: :controller, performance: true do
before do
controller.stub(:current_distributor) { d }
controller.stub(:current_order_cycle) { order_cycle }
Spree::Config.currency = 'AUD'
end
describe "fetching products" do
let(:exchange) { order_cycle.exchanges.to_enterprises(d).outgoing.first }
let(:image) { File.open(File.expand_path('../../../app/assets/images/logo.jpg', __FILE__)) }
let(:image) { File.open(File.expand_path('../../../app/assets/images/logo-white.png', __FILE__)) }
before do
11.times do