diff --git a/app/controllers/admin/tag_rules_controller.rb b/app/controllers/admin/tag_rules_controller.rb index 0d5d06b35f..d5112abf74 100644 --- a/app/controllers/admin/tag_rules_controller.rb +++ b/app/controllers/admin/tag_rules_controller.rb @@ -41,6 +41,7 @@ module Admin end end + # Used by the tag input autocomplete def map_by_tag respond_to do |format| format.json do @@ -50,6 +51,26 @@ module Admin end end + # Use to populate autocomplete with available rule for the given tag/enterprise + def variant_tag_rules + tag_rules = + TagRule.matching_variant_tag_rules_by_enterprises(params[:enterprise_id], params[:q]) + + @formatted_tag_rules = tag_rules.each_with_object({}) do |rule, mapping| + rule.preferred_customer_tags.split(",").each do |tag| + if mapping[tag] + mapping[tag][:rules] += 1 + else + mapping[tag] = { tag:, rules: 1 } + end + end + end.values + + respond_with do |format| + format.html { render :variant_tag_rules, layout: false } + end + end + private def collection_actions diff --git a/app/models/tag_rule.rb b/app/models/tag_rule.rb index d1efddb9da..3fbc131c48 100644 --- a/app/models/tag_rule.rb +++ b/app/models/tag_rule.rb @@ -10,6 +10,7 @@ class TagRule < ApplicationRecord scope :exclude_inventory, -> { where.not(type: "TagRule::FilterProducts") } scope :exclude_variant, -> { where.not(type: "TagRule::FilterVariants") } + # TODO doesn not exluce inventory and or variant tag rule def self.mapping_for(enterprises) self.for(enterprises).each_with_object({}) do |rule, mapping| rule.preferred_customer_tags.split(",").each do |tag| @@ -22,6 +23,14 @@ class TagRule < ApplicationRecord end end + def self.matching_variant_tag_rules_by_enterprises(enterprise_id, tag) + rules = where(type: "TagRule::FilterVariants").for(enterprise_id) + + return [] if rules.empty? + + rules.select { |r| r.preferred_customer_tags =~ /#{tag}/ } + end + # The following method must be overriden in a concrete tagRule def tags raise NotImplementedError, 'please use concrete TagRule' diff --git a/app/views/admin/tag_rules/variant_tag_rules.html.haml b/app/views/admin/tag_rules/variant_tag_rules.html.haml new file mode 100644 index 0000000000..e0318a7a54 --- /dev/null +++ b/app/views/admin/tag_rules/variant_tag_rules.html.haml @@ -0,0 +1,3 @@ +- @formatted_tag_rules.each do |tag_rule| + %li.suggestion-item{ role: "option", "data-autocomplete-value": tag_rule[:tag], "data-autocomplete-label": tag_rule[:tag] } + = t("admin.products_v3.tag_rules.rules_per_tag", tag: tag_rule[:tag], count: tag_rule[:rules]) diff --git a/config/locales/en.yml b/config/locales/en.yml index aba0f24f28..8246b85d2b 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1026,6 +1026,10 @@ en: clone: success: Successfully cloned the product error: Unable to clone the product + tag_rules: + rules_per_tag: + one: "%{tag} has 1 rule" + other: "%{tag} has %{count} rules" product_import: title: Product Import file_not_found: File not found or could not be opened diff --git a/config/routes/admin.rb b/config/routes/admin.rb index 5a0875ee64..b80d340bd4 100644 --- a/config/routes/admin.rb +++ b/config/routes/admin.rb @@ -91,8 +91,9 @@ Openfoodnetwork::Application.routes.draw do resources :customers, only: [:index, :create, :update, :destroy, :show] - resources :tag_rules, only: [], format: :json do - get :map_by_tag, on: :collection + resources :tag_rules, only: [] do + get :map_by_tag, on: :collection, format: :json + get :variant_tag_rules, on: :collection end resource :contents diff --git a/spec/models/tag_rule_spec.rb b/spec/models/tag_rule_spec.rb index b4b53310ae..1282f27254 100644 --- a/spec/models/tag_rule_spec.rb +++ b/spec/models/tag_rule_spec.rb @@ -9,6 +9,39 @@ RSpec.describe TagRule do end end + describe ".matching_variant_tag_rules_by_enterprises" do + let(:enterprise) { create(:enterprise) } + let!(:rule1) { + create(:filter_variants_tag_rule, enterprise:, preferred_customer_tags: "filtered" ) + } + let!(:rule2) { + create(:filter_variants_tag_rule, enterprise:, preferred_customer_tags: "filtered" ) + } + let!(:rule3) { + create(:filter_variants_tag_rule, enterprise:, preferred_customer_tags: "filtered" ) + } + let!(:rule4) { + create(:filter_variants_tag_rule, enterprise:, preferred_customer_tags: "other-tag" ) + } + let!(:rule5) { + create(:filter_order_cycles_tag_rule, enterprise:, preferred_customer_tags: "filtered" ) + } + + it "returns a list of rule partially matching the tag" do + rules = described_class.matching_variant_tag_rules_by_enterprises(enterprise.id, "filte") + + expect(rules).to include rule1, rule2, rule3 + expect(rules).not_to include rule4 + end + + context "when no matching rules" do + it "returns an empty array" do + rules = described_class.matching_variant_tag_rules_by_enterprises(enterprise.id, "no-tag") + expect(rules).to eq([]) + end + end + end + describe '#tags' do subject(:rule) { Class.new(TagRule).new }