When creating backoffice orders hide variants with no stock by default

But let people include out of stock variants by checking a checkbox if they want.

Note, we only apply the variants in stock scope if a distributor is
present. I think this is because this search method is also used when
setting up subscriptions so I don't think we want to change the
behaviour there.

Co-authored-by: Maikel Linke <maikel@email.org.au>
This commit is contained in:
Cillian O'Ruanaidh
2021-08-06 18:35:15 +01:00
parent 86404045f2
commit 2462d71ab5
6 changed files with 134 additions and 4 deletions

View File

@@ -19,6 +19,7 @@ angular.module("admin.utils").directive "variantAutocomplete", ($timeout) ->
distributor_id: scope.distributor_id
order_cycle_id: scope.order_cycle_id
eligible_for_subscriptions: scope.eligible_for_subscriptions
include_out_of_stock: scope.include_out_of_stock
results: (data, page) ->
window.variants = data # this is how spree auto complete JS code picks up variants
results: data
@@ -27,3 +28,5 @@ angular.module("admin.utils").directive "variantAutocomplete", ($timeout) ->
formatSelection: (variant) ->
element.parent().children(".options_placeholder").html variant.options_text
variant.name
element.on "select2-opening", ->
scope.include_out_of_stock = if $('#include_out_of_stock').is(':checked') then "1" else ""

View File

@@ -114,7 +114,7 @@ module Spree
def variant_search_params
params.permit(
:q, :distributor_id, :order_cycle_id, :schedule_id, :eligible_for_subscriptions
:q, :distributor_id, :order_cycle_id, :schedule_id, :eligible_for_subscriptions, :include_out_of_stock
).to_h.with_indifferent_access
end
end

View File

@@ -7,8 +7,13 @@
- if @order.canceled?
= t(".cannot_add_item_to_canceled_order")
- else
.field.twelve.columns.alpha{"data-hook" => "add_product_name"}
.field.nine.columns.alpha{"data-hook" => "add_product_name"}
= label_tag :add_variant_id, Spree.t(:name_or_sku)
= hidden_field_tag :add_variant_id, "", :class => "variant_autocomplete fullwidth"
.five.columns.omega
.field
= label_tag 'include_out_of_stock', t(".include_out_of_stock_variants")
%br/
= check_box_tag 'include_out_of_stock', '1'
#stock_details

View File

@@ -3570,6 +3570,7 @@ See the %{link} to find out more about %{sitename}'s features and to start using
orders:
add_product:
cannot_add_item_to_canceled_order: "Cannot add item to canceled order"
include_out_of_stock_variants: "Include variants with no available stock"
index:
listing_orders: "Listing Orders"
new_order: "New Order"

View File

@@ -16,6 +16,7 @@ module OpenFoodNetwork
def search
@variants = query_scope
scope_to_in_stock_only if params[:distributor_id] && params[:include_out_of_stock] != "1"
scope_to_schedule if params[:schedule_id]
scope_to_order_cycle if params[:order_cycle_id]
scope_to_distributor if params[:distributor_id]
@@ -68,6 +69,18 @@ module OpenFoodNetwork
scope_variants_to_distributor(@variants, distributor)
end
def scope_to_in_stock_only
@variants = @variants.joins(
"INNER JOIN spree_stock_items ON spree_stock_items.variant_id = spree_variants.id
LEFT JOIN variant_overrides ON variant_overrides.variant_id = spree_variants.id"
).where("
variant_overrides.on_demand IS TRUE OR
variant_overrides.count_on_hand > 0 OR
(variant_overrides.on_demand IS NULL AND spree_stock_items.backorderable IS TRUE) OR
(variant_overrides.count_on_hand IS NULL AND spree_stock_items.count_on_hand > 0)
")
end
def scope_variants_to_distributor(variants, distributor)
scoper = OpenFoodNetwork::ScopeVariantToHub.new(distributor)
# Perform scoping after all filtering is done.

View File

@@ -37,8 +37,7 @@ describe OpenFoodNetwork::ScopeVariantsForSearch do
let(:params) { { q: "product", schedule_id: s1.id } }
it "returns all products distributed through that schedule" do
lala = result
expect(lala).to include v1, v3
expect(result).to include v1, v3
expect(result).to_not include v2, v4
end
end
@@ -59,6 +58,115 @@ describe OpenFoodNetwork::ScopeVariantsForSearch do
expect(result).to include v4
expect(result).to_not include v1, v2, v3
end
context "filtering by stock availability" do
let!(:distributor1_variant_on_hand_but_not_backorderable) do
create_variant_with_stock_item_for(d1, backorderable: false, count_on_hand: 1)
end
let!(:distributor1_variant_backorderable_but_not_on_hand) do
create_variant_with_stock_item_for(d1, backorderable: true, count_on_hand: 0)
end
let!(:distributor1_variant_not_backorderable_and_not_on_hand) do
create_variant_with_stock_item_for(d1, backorderable: false, count_on_hand: 0)
end
let!(:distributor1_variant_with_override_on_hand_but_not_on_demand) do
create_variant_with_variant_override_for(d1, on_demand: false, count_on_hand: 1)
end
let!(:distributor1_variant_with_override_on_demand_but_not_on_hand) do
create_variant_with_variant_override_for(d1, on_demand: true, count_on_hand: nil)
end
let!(:distributor1_variant_with_override_not_on_demand_and_not_on_hand) do
create_variant_with_variant_override_for(d1, on_demand: false, count_on_hand: 0)
end
let!(:distributor1_variant_with_override_not_in_stock_but_producer_in_stock) do
variant = create(:simple_product).variants.first
variant.stock_items.first.update!(backorderable: false, count_on_hand: 1)
create(:simple_order_cycle, distributors: [d1], variants: [variant])
create(:variant_override, variant: variant, hub: d1, on_demand: false, count_on_hand: 0)
variant
end
let!(:distributor1_variant_with_override_without_stock_level_set_and_producer_not_in_stock) do
variant = create(:simple_product).variants.first
variant.stock_items.first.update!(backorderable: false, count_on_hand: 0)
create(:simple_order_cycle, distributors: [d1], variants: [variant])
create(:variant_override, variant: variant, hub: d1, on_demand: nil, count_on_hand: nil)
variant
end
let!(:distributor1_variant_with_override_without_stock_level_set_but_producer_in_stock) do
variant = create(:simple_product).variants.first
variant.stock_items.first.update!(backorderable: false, count_on_hand: 1)
create(:simple_order_cycle, distributors: [d1], variants: [variant])
create(:variant_override, variant: variant, hub: d1, on_demand: nil, count_on_hand: nil)
variant
end
let!(:distributor2_variant_with_override_in_stock) do
create_variant_with_variant_override_for(d2, count_on_hand: 1)
end
context "when :include_out_of_stock is not specified" do
let(:params) { { distributor_id: d1.id } }
it "returns variants for the given distributor if they have a variant override which is
in stock, or if they have a variant override with no stock level set but the producer
has stock, or if they don't have a variant override and the producer has stock" do
expect(result).to include(
distributor1_variant_on_hand_but_not_backorderable,
distributor1_variant_backorderable_but_not_on_hand,
distributor1_variant_with_override_on_demand_but_not_on_hand,
distributor1_variant_with_override_on_hand_but_not_on_demand,
distributor1_variant_with_override_without_stock_level_set_but_producer_in_stock
)
expect(result).to_not include(
distributor1_variant_not_backorderable_and_not_on_hand,
distributor1_variant_with_override_not_on_demand_and_not_on_hand,
distributor1_variant_with_override_not_in_stock_but_producer_in_stock,
distributor1_variant_with_override_without_stock_level_set_and_producer_not_in_stock,
distributor2_variant_with_override_in_stock
)
end
end
context "when :include_out_of_stock is specified" do
let(:params) { { distributor_id: d1.id, include_out_of_stock: "1" } }
it "returns all variants for the given distributor even if they are not in stock" do
expect(result).to include(
distributor1_variant_on_hand_but_not_backorderable,
distributor1_variant_backorderable_but_not_on_hand,
distributor1_variant_with_override_on_demand_but_not_on_hand,
distributor1_variant_with_override_on_hand_but_not_on_demand,
distributor1_variant_with_override_without_stock_level_set_but_producer_in_stock,
distributor1_variant_with_override_without_stock_level_set_and_producer_not_in_stock,
distributor1_variant_not_backorderable_and_not_on_hand,
distributor1_variant_with_override_not_on_demand_and_not_on_hand,
distributor1_variant_with_override_not_in_stock_but_producer_in_stock
)
expect(result).to_not include(
distributor2_variant_with_override_in_stock
)
end
end
end
end
end
private
def create_variant_with_stock_item_for(distributor, stock_item_attributes)
variant = create(:simple_product).variants.first
variant.stock_items.first.update!(stock_item_attributes)
create(:simple_order_cycle, distributors: [distributor], variants: [variant])
variant
end
def create_variant_with_variant_override_for(distributor, variant_override_attributes)
variant = create(:simple_product).variants.first
variant.stock_items.first.update!(backorderable: false, count_on_hand: 0)
create(:simple_order_cycle, distributors: [distributor], variants: [variant])
create(:variant_override, {
variant: variant,
hub: distributor
}.merge(variant_override_attributes))
variant
end
end