mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-03-20 04:59:16 +00:00
Extract tag_rule filtering into separate service
This commit is contained in:
@@ -36,74 +36,7 @@ class OrderCycleDistributedProducts
|
||||
joins(:stock_items).
|
||||
where(query_stock_with_overrides)
|
||||
|
||||
if distributor_rules.any?
|
||||
stocked_variants = apply_tag_rules(stocked_variants)
|
||||
end
|
||||
|
||||
stocked_variants
|
||||
end
|
||||
|
||||
def apply_tag_rules(stocked_variants)
|
||||
stocked_variants.where(query_with_tag_rules)
|
||||
end
|
||||
|
||||
def distributor_rules
|
||||
@distributor_rules ||= TagRule::FilterProducts.prioritised.for(distributor)
|
||||
end
|
||||
|
||||
def customer_tag_list
|
||||
customer.andand.tag_list || []
|
||||
end
|
||||
|
||||
def default_rule_tags
|
||||
default_rules.map(&:preferred_variant_tags)
|
||||
end
|
||||
|
||||
def hide_rule_tags
|
||||
hide_rules.map(&:preferred_variant_tags)
|
||||
end
|
||||
|
||||
def show_rule_tags
|
||||
show_rules.map(&:preferred_variant_tags)
|
||||
end
|
||||
|
||||
def overrides_to_hide
|
||||
@overrides_to_hide = VariantOverride.where(hub_id: distributor.id).
|
||||
tagged_with(default_rule_tags + hide_rule_tags, any: true).
|
||||
pluck(:id)
|
||||
end
|
||||
|
||||
def overrides_to_show
|
||||
@overrides_to_show = VariantOverride.where(hub_id: distributor.id).
|
||||
tagged_with(show_rule_tags, any: true).
|
||||
pluck(:id)
|
||||
end
|
||||
|
||||
def customer_applicable_rules
|
||||
# Rules which apply specifically to the current customer
|
||||
@customer_applicable_rules ||= non_default_rules.select{ |rule| customer_tagged?(rule) }
|
||||
end
|
||||
|
||||
def default_rules
|
||||
# These rules hide a variant_override with tag X
|
||||
distributor_rules.select(&:is_default?)
|
||||
end
|
||||
|
||||
def non_default_rules
|
||||
# These rules show or hide a variant_override with tag X for customer with tag Y
|
||||
distributor_rules.reject(&:is_default?)
|
||||
end
|
||||
|
||||
def hide_rules
|
||||
@hide_rules ||= customer_applicable_rules.select{ |rule| rule.preferred_matched_variants_visibility == 'hidden'}
|
||||
end
|
||||
|
||||
def show_rules
|
||||
customer_applicable_rules - hide_rules
|
||||
end
|
||||
|
||||
def customer_tagged?(rule)
|
||||
customer_tag_list.include? rule.preferred_customer_tags
|
||||
ProductTagRulesFilterer.new(distributor, customer, stocked_variants).call
|
||||
end
|
||||
|
||||
def query_stock_with_overrides
|
||||
@@ -114,22 +47,6 @@ class OrderCycleDistributedProducts
|
||||
AND #{variant_not_on_demand} AND #{variant_in_stock} ) )"
|
||||
end
|
||||
|
||||
def query_with_tag_rules
|
||||
"#{variant_not_overriden} OR ( #{variant_overriden}
|
||||
AND ( #{override_not_hidden_by_rule}
|
||||
OR #{override_shown_by_rule} ) )"
|
||||
end
|
||||
|
||||
def override_not_hidden_by_rule
|
||||
return "FALSE" unless overrides_to_hide.any?
|
||||
"variant_overrides.id NOT IN (#{overrides_to_hide.join(',')})"
|
||||
end
|
||||
|
||||
def override_shown_by_rule
|
||||
return "FALSE" unless overrides_to_show.any?
|
||||
"variant_overrides.id IN (#{overrides_to_show.join(',')})"
|
||||
end
|
||||
|
||||
def variant_not_overriden
|
||||
"variant_overrides.id IS NULL"
|
||||
end
|
||||
|
||||
111
app/services/product_tag_rules_filterer.rb
Normal file
111
app/services/product_tag_rules_filterer.rb
Normal file
@@ -0,0 +1,111 @@
|
||||
# Takes a Spree::Variant AR object and filters results based on applicable tag rules.
|
||||
# Tag rules exists in the context of enterprise, customer, and variant_overrides,
|
||||
# and are applied to variant_overrides only. Returns a Spree::Variant AR object.
|
||||
|
||||
class ProductTagRulesFilterer
|
||||
def initialize(distributor, customer, variants_relation)
|
||||
@distributor = distributor
|
||||
@customer = customer
|
||||
@variants_relation = variants_relation
|
||||
end
|
||||
|
||||
def call
|
||||
return variants_relation unless distributor_rules.any?
|
||||
|
||||
filter(variants_relation)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_accessor :distributor, :customer, :variants_relation
|
||||
|
||||
def distributor_rules
|
||||
@distributor_rules ||= TagRule::FilterProducts.prioritised.for(distributor).all
|
||||
end
|
||||
|
||||
def filter(variants_relation)
|
||||
return variants_relation unless overrides_to_hide.any?
|
||||
|
||||
variants_relation.where(query_with_tag_rules)
|
||||
end
|
||||
|
||||
def query_with_tag_rules
|
||||
"#{variant_not_overriden} OR ( #{variant_overriden}
|
||||
AND ( #{override_not_hidden_by_rule}
|
||||
OR #{override_shown_by_rule} ) )"
|
||||
end
|
||||
|
||||
def variant_not_overriden
|
||||
"variant_overrides.id IS NULL"
|
||||
end
|
||||
|
||||
def variant_overriden
|
||||
"variant_overrides.id IS NOT NULL"
|
||||
end
|
||||
|
||||
def override_not_hidden_by_rule
|
||||
return "FALSE" unless overrides_to_hide.any?
|
||||
"variant_overrides.id NOT IN (#{overrides_to_hide.join(',')})"
|
||||
end
|
||||
|
||||
def override_shown_by_rule
|
||||
return "FALSE" unless overrides_to_show.any?
|
||||
"variant_overrides.id IN (#{overrides_to_show.join(',')})"
|
||||
end
|
||||
|
||||
def overrides_to_hide
|
||||
@overrides_to_hide ||= VariantOverride.where(hub_id: distributor.id).
|
||||
tagged_with(default_rule_tags + hide_rule_tags, any: true).
|
||||
pluck(:id)
|
||||
end
|
||||
|
||||
def overrides_to_show
|
||||
@overrides_to_show ||= VariantOverride.where(hub_id: distributor.id).
|
||||
tagged_with(show_rule_tags, any: true).
|
||||
pluck(:id)
|
||||
end
|
||||
|
||||
def default_rule_tags
|
||||
default_rules.map(&:preferred_variant_tags)
|
||||
end
|
||||
|
||||
def hide_rule_tags
|
||||
hide_rules.map(&:preferred_variant_tags)
|
||||
end
|
||||
|
||||
def show_rule_tags
|
||||
show_rules.map(&:preferred_variant_tags)
|
||||
end
|
||||
|
||||
def default_rules
|
||||
# These rules hide a variant_override with tag X and apply to all customers
|
||||
distributor_rules.select(&:is_default?)
|
||||
end
|
||||
|
||||
def non_default_rules
|
||||
# These rules show or hide a variant_override with tag X for customer with tag Y
|
||||
distributor_rules.reject(&:is_default?)
|
||||
end
|
||||
|
||||
def customer_applicable_rules
|
||||
# Rules which apply specifically to the current customer
|
||||
@customer_applicable_rules ||= non_default_rules.select{ |rule| customer_tagged?(rule) }
|
||||
end
|
||||
|
||||
def hide_rules
|
||||
@hide_rules ||= customer_applicable_rules.
|
||||
select{ |rule| rule.preferred_matched_variants_visibility == 'hidden' }
|
||||
end
|
||||
|
||||
def show_rules
|
||||
customer_applicable_rules - hide_rules
|
||||
end
|
||||
|
||||
def customer_tagged?(rule)
|
||||
customer_tag_list.include? rule.preferred_customer_tags
|
||||
end
|
||||
|
||||
def customer_tag_list
|
||||
customer.andand.tag_list || []
|
||||
end
|
||||
end
|
||||
98
spec/services/product_tag_rules_filterer_spec.rb
Normal file
98
spec/services/product_tag_rules_filterer_spec.rb
Normal file
@@ -0,0 +1,98 @@
|
||||
require "spec_helper"
|
||||
|
||||
describe ProductTagRulesFilterer do
|
||||
describe "filtering by tag rules" do
|
||||
let!(:distributor) { create(:distributor_enterprise) }
|
||||
let(:product) { create(:product, supplier: distributor) }
|
||||
let(:v1) { create(:variant, product: product) }
|
||||
let(:v2) { create(:variant, product: product) }
|
||||
let(:v3) { create(:variant, product: product) }
|
||||
let(:v4) { create(:variant, product: product) }
|
||||
let(:variant_hidden_by_default) { create(:variant_override, variant: v1, hub: distributor) }
|
||||
let(:variant_hidden_by_rule) { create(:variant_override, variant: v2, hub: distributor) }
|
||||
let(:variant_shown_by_rule) { create(:variant_override, variant: v3, hub: distributor) }
|
||||
let(:variant_hidden_for_another_customer) { create(:variant_override, variant: v4, hub: distributor) }
|
||||
let(:customer) { create(:customer, enterprise: distributor) }
|
||||
let(:variants_relation) {
|
||||
Spree::Variant.joins(:product).where("spree_products.supplier_id = ?", distributor.id)
|
||||
}
|
||||
let(:default_hide_rule) {
|
||||
create(:filter_products_tag_rule,
|
||||
enterprise: distributor,
|
||||
is_default: true,
|
||||
preferred_variant_tags: "hide_these_variants_from_everyone",
|
||||
preferred_matched_variants_visibility: "hidden")
|
||||
}
|
||||
let!(:hide_rule) {
|
||||
create(:filter_products_tag_rule,
|
||||
enterprise: distributor,
|
||||
preferred_variant_tags: "hide_these_variants",
|
||||
preferred_customer_tags: "hide_from_these_customers",
|
||||
preferred_matched_variants_visibility: "hidden" )
|
||||
}
|
||||
let!(:show_rule) {
|
||||
create(:filter_products_tag_rule,
|
||||
enterprise: distributor,
|
||||
preferred_variant_tags: "show_these_variants",
|
||||
preferred_customer_tags: "show_for_these_customers",
|
||||
preferred_matched_variants_visibility: "visible" )
|
||||
}
|
||||
let!(:non_applicable_rule) {
|
||||
create(:filter_products_tag_rule,
|
||||
enterprise: distributor,
|
||||
preferred_variant_tags: "hide_these_other_variants",
|
||||
preferred_customer_tags: "hide_from_other_customers",
|
||||
preferred_matched_variants_visibility: "hidden" )
|
||||
}
|
||||
let(:filterer) { described_class.new(distributor, customer, variants_relation) }
|
||||
|
||||
context "when the distributor has no rules" do
|
||||
it "returns the relation unchanged" do
|
||||
expect(filterer.call).to eq variants_relation
|
||||
end
|
||||
end
|
||||
|
||||
describe "#customer_applicable_rules" do
|
||||
it "returns a list of tags that apply to the current customer" do
|
||||
customer.update_attribute(:tag_list, show_rule.preferred_customer_tags)
|
||||
|
||||
customer_applicable_rules = filterer.__send__(:customer_applicable_rules)
|
||||
expect(customer_applicable_rules).to eq [show_rule]
|
||||
end
|
||||
end
|
||||
|
||||
describe "#overrides_to_hide" do
|
||||
context "with default rules" do
|
||||
it "lists overrides tagged as hidden for this customer" do
|
||||
variant_hidden_by_default.update_attribute(:tag_list, default_hide_rule.preferred_variant_tags)
|
||||
|
||||
overrides_to_hide = filterer.__send__(:overrides_to_hide)
|
||||
expect(overrides_to_hide).to eq [variant_hidden_by_default.id]
|
||||
end
|
||||
end
|
||||
|
||||
context "with default and specific rules" do
|
||||
it "lists overrides tagged as hidden for this customer" do
|
||||
customer.update_attribute(:tag_list, hide_rule.preferred_customer_tags)
|
||||
variant_hidden_by_default.update_attribute(:tag_list, default_hide_rule.preferred_variant_tags)
|
||||
variant_hidden_by_rule.update_attribute(:tag_list, hide_rule.preferred_variant_tags)
|
||||
variant_hidden_for_another_customer.update_attribute(:tag_list, non_applicable_rule.preferred_variant_tags)
|
||||
|
||||
overrides_to_hide = filterer.__send__(:overrides_to_hide)
|
||||
expect(overrides_to_hide).to eq [variant_hidden_by_default.id, variant_hidden_by_rule.id]
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe "#overrides_to_show" do
|
||||
it "lists overrides tagged as visible for this customer" do
|
||||
customer.update_attribute(:tag_list, show_rule.preferred_customer_tags)
|
||||
variant_shown_by_rule.update_attribute(:tag_list, show_rule.preferred_variant_tags)
|
||||
|
||||
overrides_to_show = filterer.__send__(:overrides_to_show)
|
||||
expect(overrides_to_show).to eq [variant_shown_by_rule.id]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user