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 =