diff --git a/engines/dfc_provider/app/services/supplied_product_builder.rb b/engines/dfc_provider/app/services/supplied_product_builder.rb index d35ca518ac..b1360b9443 100644 --- a/engines/dfc_provider/app/services/supplied_product_builder.rb +++ b/engines/dfc_provider/app/services/supplied_product_builder.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class SuppliedProductBuilder < DfcBuilder + PRODUCT_TYPES = {} # rubocop:disable Style/MutableConstant + def self.supplied_product(variant) id = urls.enterprise_supplied_product_url( enterprise_id: variant.product.supplier_id, @@ -63,11 +65,48 @@ class SuppliedProductBuilder < DfcBuilder return nil if taxon_name.nil? - root_product_types = DfcLoader.connector.PRODUCT_TYPES.methods(false).sort - search = root_product_types.index(taxon_name.upcase.to_sym) + populate_product_types if PRODUCT_TYPES.empty? - return nil if search.nil? + return nil if PRODUCT_TYPES[taxon_name.to_sym].nil? - DfcLoader.connector.PRODUCT_TYPES.public_send(root_product_types[search]) + call_dfc_product_type(PRODUCT_TYPES[taxon_name.to_sym]) end + + def self.populate_product_types + DfcLoader.connector.PRODUCT_TYPES.topConcepts.each do |product_type| + stack = [] + record_type(stack, product_type.to_s) + end + end + + def self.record_type(stack, product_type) + name = product_type.to_s + current_stack = stack.dup.push(name) + PRODUCT_TYPES[name.downcase.to_sym] = current_stack + + type = call_dfc_product_type(current_stack) + + # Narrower product types are defined as class method on the current product type object + narrowers = type.methods(false).sort + + # Leaf node + return if narrowers.empty? + + narrowers.each do |narrower| + # recursive call + record_type(current_stack, narrower) + end + end + + # Callproduct type method ie: DfcLoader.connector.PRODUCT_TYPES.DRINK.SOFT_DRINK + def self.call_dfc_product_type(product_type_path) + type = DfcLoader.connector.PRODUCT_TYPES + product_type_path.each do |pt| + type = type.public_send(pt) + end + + type + end + + private_class_method :product_type, :populate_product_types, :record_type end diff --git a/engines/dfc_provider/spec/services/supplied_product_builder_spec.rb b/engines/dfc_provider/spec/services/supplied_product_builder_spec.rb index 77fa2ae9e7..40ba5cc3e2 100644 --- a/engines/dfc_provider/spec/services/supplied_product_builder_spec.rb +++ b/engines/dfc_provider/spec/services/supplied_product_builder_spec.rb @@ -46,19 +46,38 @@ describe SuppliedProductBuilder do end context "product_type mapping" do - it "assigns a product type" do - product = builder.supplied_product(variant) + subject(:product) { builder.supplied_product(variant) } + + it "assigns a top level product type" do drink = DfcLoader.connector.PRODUCT_TYPES.DRINK expect(product.productType).to eq drink end + context "with second level product type" do + let(:taxon) { build(:taxon, name: "Soft Drink", dfc_name: "soft_drink") } + + it "assigns a second level product type" do + soft_drink = DfcLoader.connector.PRODUCT_TYPES.DRINK.SOFT_DRINK + + expect(product.productType).to eq soft_drink + end + end + + context "with leaf level product type" do + let(:taxon) { build(:taxon, name: "Lemonade", dfc_name: "lemonade") } + + it "assigns a leaf level product type" do + lemonade = DfcLoader.connector.PRODUCT_TYPES.DRINK.SOFT_DRINK.LEMONADE + + expect(product.productType).to eq lemonade + end + end + context "with non existing product type" do let(:taxon) { build(:taxon, name: "other", dfc_name: "other") } it "returns nil" do - product = builder.supplied_product(variant) - expect(product.productType).to be_nil end end @@ -67,8 +86,6 @@ describe SuppliedProductBuilder do let(:taxon) { nil } it "returns nil" do - product = builder.supplied_product(variant) - expect(product.productType).to be_nil end end