mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-02-27 01:43:22 +00:00
Importing products from DFC catalog
Technical demonstration of a complete product export-import roundtrip which we could now do between OFN instances.
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "private_address_check"
|
||||
require "private_address_check/tcpsocket_ext"
|
||||
|
||||
module Admin
|
||||
class DfcProductImportsController < Spree::Admin::BaseController
|
||||
|
||||
# Define model class for `can?` permissions:
|
||||
def model_class
|
||||
self.class
|
||||
@@ -12,8 +14,52 @@ module Admin
|
||||
# The plan:
|
||||
#
|
||||
# * Fetch DFC catalog as JSON from URL.
|
||||
enterprise = OpenFoodNetwork::Permissions.new(spree_current_user)
|
||||
.managed_product_enterprises.is_primary_producer
|
||||
.find(params.require(:enterprise_id))
|
||||
|
||||
catalog_url = params.require(:catalog_url)
|
||||
|
||||
json_catalog = fetch_catalog(catalog_url)
|
||||
graph = DfcIo.import(json_catalog)
|
||||
|
||||
# * First step: import all products for given enterprise.
|
||||
# * Second step: render table and let user decide which ones to import.
|
||||
imported = graph.map do |subject|
|
||||
import_product(subject, enterprise)
|
||||
end
|
||||
|
||||
@count = imported.compact.count
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def fetch_catalog(url)
|
||||
connection = Faraday.new(
|
||||
request: { timeout: 30 },
|
||||
headers: {
|
||||
'Content-Type' => 'application/json',
|
||||
'Authorization' => "Bearer #{spree_current_user.oidc_account.token}",
|
||||
}
|
||||
)
|
||||
response = PrivateAddressCheck.only_public_connections do
|
||||
connection.get(url)
|
||||
end
|
||||
|
||||
response.body
|
||||
end
|
||||
|
||||
# Most of this code is the same as in the DfcProvider::SuppliedProductsController.
|
||||
def import_product(subject, enterprise)
|
||||
return unless subject.is_a? DataFoodConsortium::Connector::SuppliedProduct
|
||||
|
||||
variant = SuppliedProductBuilder.import_variant(subject, enterprise)
|
||||
product = variant.product
|
||||
|
||||
product.save! if product.new_record?
|
||||
variant.save! if variant.new_record?
|
||||
|
||||
variant
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
%h2 Importing a DFC product catalog
|
||||
%p Catalog size: 0
|
||||
%p Imported products:
|
||||
= @count
|
||||
|
||||
@@ -87,6 +87,8 @@ class SuppliedProductBuilder < DfcBuilder
|
||||
end
|
||||
|
||||
def self.taxon(supplied_product)
|
||||
return unless supplied_product.productType
|
||||
|
||||
dfc_id = supplied_product.productType.semanticId
|
||||
Spree::Taxon.find_by(dfc_id: )
|
||||
end
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
# frozen_string_literal: false
|
||||
|
||||
require 'system_helper'
|
||||
require_relative '../../../engines/dfc_provider/spec/support/authorization_helper'
|
||||
|
||||
describe "DFC Product Import" do
|
||||
include AuthorizationHelper
|
||||
|
||||
let(:user) { create(:oidc_user, owned_enterprises: [enterprise]) }
|
||||
let(:enterprise) { create(:enterprise) }
|
||||
let(:source_product) { create(:product, supplier: enterprise) }
|
||||
|
||||
before do
|
||||
login_as user
|
||||
source_product # to be imported
|
||||
allow(PrivateAddressCheck).to receive(:private_address?).and_return(false)
|
||||
user.oidc_account.update!(token: allow_token_for(email: user.email))
|
||||
end
|
||||
|
||||
it "imports from given catalog" do
|
||||
@@ -17,10 +24,21 @@ describe "DFC Product Import" do
|
||||
|
||||
# We are testing against our own catalog for now but we want to replace
|
||||
# this with the URL of another app when available.
|
||||
fill_in "catalog_url", with: "/api/dfc/enterprises/#{enterprise.id}/supplied_products"
|
||||
host = Rails.application.default_url_options[:host]
|
||||
url = "http://#{host}/api/dfc/enterprises/#{enterprise.id}/catalog_items"
|
||||
fill_in "catalog_url", with: url
|
||||
|
||||
click_button "Import"
|
||||
# By feeding our own catalog to the import, we are effectively cloning the
|
||||
# products. But the DFC product references the spree_product_id which
|
||||
# make the importer create a variant for that product instead of creating
|
||||
# a new independent product.
|
||||
expect {
|
||||
click_button "Import"
|
||||
}.to change {
|
||||
source_product.variants.count
|
||||
}.by(1)
|
||||
|
||||
expect(page).to have_content "Importing a DFC product catalog"
|
||||
expect(page).to have_content "Imported products: 1"
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user