From ec8c710e3a2676f4fa3d258342fa977e670b46b3 Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Thu, 25 May 2023 17:20:20 +1000 Subject: [PATCH] Import simple DFC SuppliedProduct OFN products and variants need more data like a price but the DFC stores that in a different object. We may get a larger graph containing that information but we don't have any test data yet. --- .../supplied_products_controller.rb | 16 +++++++++ .../services/quantitative_value_builder.rb | 15 ++++++++ .../app/services/supplied_product_builder.rb | 12 +++++++ engines/dfc_provider/config/routes.rb | 2 +- .../spec/requests/supplied_products_spec.rb | 34 +++++++++++++++++++ 5 files changed, 78 insertions(+), 1 deletion(-) diff --git a/engines/dfc_provider/app/controllers/dfc_provider/supplied_products_controller.rb b/engines/dfc_provider/app/controllers/dfc_provider/supplied_products_controller.rb index 215f634ee0..c7b9a60134 100644 --- a/engines/dfc_provider/app/controllers/dfc_provider/supplied_products_controller.rb +++ b/engines/dfc_provider/app/controllers/dfc_provider/supplied_products_controller.rb @@ -1,10 +1,22 @@ # frozen_string_literal: true +require "data_food_consortium/connector/connector" + # Controller used to provide the SuppliedProducts API for the DFC application # SuppliedProducts are products that are managed by an enterprise. module DfcProvider class SuppliedProductsController < DfcProvider::BaseController before_action :check_enterprise + rescue_from JSON::LD::JsonLdError::LoadingDocumentFailed, with: -> do + head :bad_request + end + + def create + supplied_product = import.first + product = SuppliedProductBuilder.import(supplied_product) + product.supplier = current_enterprise + product.save! + end def show product = SuppliedProductBuilder.supplied_product(variant) @@ -27,6 +39,10 @@ module DfcProvider private + def import + DfcLoader.connector.import(request.body) + end + def variant @variant ||= VariantFetcher.new(current_enterprise).scope.find(params[:id]) diff --git a/engines/dfc_provider/app/services/quantitative_value_builder.rb b/engines/dfc_provider/app/services/quantitative_value_builder.rb index c88deef266..8291b3c0b0 100644 --- a/engines/dfc_provider/app/services/quantitative_value_builder.rb +++ b/engines/dfc_provider/app/services/quantitative_value_builder.rb @@ -26,4 +26,19 @@ class QuantitativeValueBuilder < DfcBuilder DfcLoader.connector.MEASURES.UNIT.QUANTITYUNIT.PIECE end end + + def self.apply(quantity, product) + product.variant_unit, product.variant_unit_name = + case quantity.unit + when DfcLoader.connector.MEASURES.UNIT.QUANTITYUNIT.LITRE + ["volume", "liter"] + when DfcLoader.connector.MEASURES.UNIT.QUANTITYUNIT.GRAM + ["weight", "gram"] + else + ["items", "items"] + end + + product.variant_unit_scale = 1 + product.unit_value = quantity.value + end end diff --git a/engines/dfc_provider/app/services/supplied_product_builder.rb b/engines/dfc_provider/app/services/supplied_product_builder.rb index 2c4639042d..40dfe0c186 100644 --- a/engines/dfc_provider/app/services/supplied_product_builder.rb +++ b/engines/dfc_provider/app/services/supplied_product_builder.rb @@ -15,4 +15,16 @@ class SuppliedProductBuilder < DfcBuilder quantity: QuantitativeValueBuilder.quantity(variant), ) end + + def self.import(supplied_product) + Spree::Product.new( + name: supplied_product.name, + description: supplied_product.description, + price: 0, # will be in DFC Offer + primary_taxon: Spree::Taxon.first, # dummy value until we have a mapping + shipping_category: DefaultShippingCategory.find_or_create, + ).tap do |product| + QuantitativeValueBuilder.apply(supplied_product.quantity, product) + end + end end diff --git a/engines/dfc_provider/config/routes.rb b/engines/dfc_provider/config/routes.rb index f8fde9365b..a016a9f5b9 100644 --- a/engines/dfc_provider/config/routes.rb +++ b/engines/dfc_provider/config/routes.rb @@ -3,7 +3,7 @@ DfcProvider::Engine.routes.draw do resources :enterprises, only: [:show] do resources :catalog_items, only: [:index, :show, :update] - resources :supplied_products, only: [:show, :update] + resources :supplied_products, only: [:create, :show, :update] end resources :persons, only: [:show] end diff --git a/engines/dfc_provider/spec/requests/supplied_products_spec.rb b/engines/dfc_provider/spec/requests/supplied_products_spec.rb index f48d761561..6a2b736f91 100644 --- a/engines/dfc_provider/spec/requests/supplied_products_spec.rb +++ b/engines/dfc_provider/spec/requests/supplied_products_spec.rb @@ -8,6 +8,40 @@ describe "SuppliedProducts", type: :request do let!(:product) { create(:simple_product, supplier: enterprise ) } let!(:variant) { product.variants.first } + describe :create do + let(:endpoint) do + enterprise_supplied_products_path(enterprise_id: enterprise.id) + end + let(:supplied_product) do + SuppliedProductBuilder.supplied_product(new_variant) + end + let(:new_variant) do + # We need an id to generate a URL as semantic id when exporting. + build(:variant, id: 0, name: "Apple", unit_value: 3) + end + + it "flags a bad request" do + post endpoint, headers: auth_header(user.uid) + + expect(response).to have_http_status :bad_request + end + + it "creates a variant" do + request_body = DfcLoader.connector.export(supplied_product) + + expect do + post endpoint, + params: request_body, + headers: auth_header(user.uid) + end + .to change { enterprise.supplied_products.count }.by(1) + + variant = Spree::Variant.last + expect(variant.name).to eq "Apple" + expect(variant.unit_value).to eq 3 + end + end + describe :show do it "returns variants" do get enterprise_supplied_product_path(