From 516759062fc753154cd9208cd9e3d236dddea91e Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Thu, 23 Jan 2025 16:44:40 +1100 Subject: [PATCH] Import variants for the same product group When importing another catalog, it's probably referring to external product groups. Storing the external link allows us to group several variants and replicate the same structure within OFN. --- app/models/spree/product.rb | 1 + .../app/services/supplied_product_importer.rb | 30 +++++++++++++++---- .../supplied_product_importer_spec.rb | 25 ++++++++++++++-- 3 files changed, 49 insertions(+), 7 deletions(-) diff --git a/app/models/spree/product.rb b/app/models/spree/product.rb index 81b1225c25..171f6de744 100755 --- a/app/models/spree/product.rb +++ b/app/models/spree/product.rb @@ -36,6 +36,7 @@ module Spree searchable_scopes :active, :with_properties has_one :image, class_name: "Spree::Image", as: :viewable, dependent: :destroy + has_one :semantic_link, as: :subject, dependent: :delete has_many :product_properties, dependent: :destroy has_many :properties, through: :product_properties diff --git a/engines/dfc_provider/app/services/supplied_product_importer.rb b/engines/dfc_provider/app/services/supplied_product_importer.rb index 6b4a62a27f..e887869de9 100644 --- a/engines/dfc_provider/app/services/supplied_product_importer.rb +++ b/engines/dfc_provider/app/services/supplied_product_importer.rb @@ -44,6 +44,7 @@ class SuppliedProductImporter < DfcBuilder # We will remove the old methods at some point. def self.referenced_spree_product(supplied_product, supplier) spree_product(supplied_product, supplier) || + spree_product_linked(supplied_product, supplier) || spree_product_from_uri(supplied_product, supplier) || spree_product_from_id(supplied_product, supplier) end @@ -51,15 +52,28 @@ class SuppliedProductImporter < DfcBuilder def self.spree_product(supplied_product, supplier) supplied_product.isVariantOf.lazy.map do |group| group_id = group.semanticId - route = Rails.application.routes.recognize_path(group_id) + id = begin + route = Rails.application.routes.recognize_path(group_id) - # Check that the given URI points to us: - next if group_id != urls.enterprise_technical_product_url(route) + # Check that the given URI points to us: + next if group_id != urls.enterprise_technical_product_url(route) - supplier.supplied_products.find_by(id: route[:id]) + route[:id] + rescue ActionController::RoutingError + next + end + + supplier.supplied_products.find_by(id:) end.compact.first end + def self.spree_product_linked(supplied_product, supplier) + semantic_ids = supplied_product.isVariantOf.map(&:semanticId) + supplier.supplied_products.includes(:semantic_link) + .where(semantic_link: { semantic_id: semantic_ids }) + .first + end + def self.spree_product_from_uri(supplied_product, supplier) uri = supplied_product.spree_product_uri return if uri.blank? @@ -86,6 +100,7 @@ class SuppliedProductImporter < DfcBuilder supplier_id: supplier.id, primary_taxon_id: taxon(supplied_product).id, image: ImageBuilder.import(supplied_product.image), + semantic_link: semantic_link(supplied_product), ).tap do |product| QuantitativeValueBuilder.apply(supplied_product.quantity, product) product.ensure_standard_variant @@ -105,9 +120,14 @@ class SuppliedProductImporter < DfcBuilder OfferBuilder.apply(offer, variant) end + def self.semantic_link(supplied_product) + semantic_id = supplied_product.isVariantOf.first&.semanticId + + SemanticLink.new(semantic_id:) if semantic_id.present? + end + def self.taxon(supplied_product) ProductTypeImporter.taxon(supplied_product.productType) end - private_class_method :taxon end diff --git a/engines/dfc_provider/spec/services/supplied_product_importer_spec.rb b/engines/dfc_provider/spec/services/supplied_product_importer_spec.rb index abbd435284..9f6bd6a98c 100644 --- a/engines/dfc_provider/spec/services/supplied_product_importer_spec.rb +++ b/engines/dfc_provider/spec/services/supplied_product_importer_spec.rb @@ -186,7 +186,7 @@ RSpec.describe SuppliedProductImporter do expect(imported_variant.on_hand).to eq 0 end - context "with spree_product_id supplied" do + context "linked to product group" do let(:imported_variant) { importer.import_variant(supplied_product, supplier) } let(:supplied_product) do @@ -229,7 +229,13 @@ RSpec.describe SuppliedProductImporter do value: 2, ), productType: product_type, - spree_product_uri: "http://another.host/api/dfc/enterprises/10/supplied_products/50" + spree_product_uri: "http://another.host/api/dfc/enterprises/10/supplied_products/50", + isVariantOf: [technical_product], + ) + end + let(:technical_product) do + DataFoodConsortium::Connector::TechnicalProduct.new( + "http://test.host/api/dfc/enterprises/7/technical_products/6" ) end @@ -243,6 +249,8 @@ RSpec.describe SuppliedProductImporter do expect(imported_product.name).to eq("Tomato") expect(imported_product.description).to eq("Awesome tomato") expect(imported_product.variant_unit).to eq("weight") + expect(imported_product.semantic_link.semantic_id) + .to eq "http://test.host/api/dfc/enterprises/7/technical_products/6" end end end @@ -270,6 +278,19 @@ RSpec.describe SuppliedProductImporter do expect(result).to eq spree_product end + it "returns a product referenced by external URI" do + variant.save! + supplied_product.isVariantOf << + DataFoodConsortium::Connector::TechnicalProduct.new( + "http://example.net/product_group" + ) + SemanticLink.create!( + subject: spree_product, + semantic_id: "http://example.net/product_group", + ) + expect(result).to eq spree_product + end + it "returns a product referenced by URI" do variant.save! supplied_product.spree_product_uri =