From d39da6d0da8f67bc6ab7d5cab7b19793a2d1989c Mon Sep 17 00:00:00 2001 From: Maikel Linke Date: Thu, 23 Jan 2025 12:14:57 +1100 Subject: [PATCH] Provide endpoint to show a product group Our Spree::Product corresponds to a DFC SuppliedProduct with variants. --- .../dfc_provider/product_groups_controller.rb | 14 ++++++ .../app/services/product_group_builder.rb | 17 +++++++ .../app/services/supplied_product_builder.rb | 9 ++-- .../spec/requests/product_groups_spec.rb | 49 +++++++++++++++++++ swagger/dfc.yaml | 28 +++++++++++ 5 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 engines/dfc_provider/app/controllers/dfc_provider/product_groups_controller.rb create mode 100644 engines/dfc_provider/app/services/product_group_builder.rb create mode 100644 engines/dfc_provider/spec/requests/product_groups_spec.rb diff --git a/engines/dfc_provider/app/controllers/dfc_provider/product_groups_controller.rb b/engines/dfc_provider/app/controllers/dfc_provider/product_groups_controller.rb new file mode 100644 index 0000000000..ab527381ba --- /dev/null +++ b/engines/dfc_provider/app/controllers/dfc_provider/product_groups_controller.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +# Show Spree::Product as SuppliedProduct with variants. +module DfcProvider + class ProductGroupsController < DfcProvider::ApplicationController + before_action :check_enterprise + + def show + spree_product = current_enterprise.supplied_products.find(params[:id]) + product = ProductGroupBuilder.product_group(spree_product) + render json: DfcIo.export(product) + end + end +end diff --git a/engines/dfc_provider/app/services/product_group_builder.rb b/engines/dfc_provider/app/services/product_group_builder.rb new file mode 100644 index 0000000000..fd25b21f84 --- /dev/null +++ b/engines/dfc_provider/app/services/product_group_builder.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +class ProductGroupBuilder < DfcBuilder + def self.product_group(product) + id = urls.enterprise_product_group_url( + enterprise_id: product.variants.first.supplier_id, + id: product.id, + ) + variants = product.variants.map do |spree_variant| + SuppliedProductBuilder.semantic_id(spree_variant) + end + + DataFoodConsortium::Connector::SuppliedProduct.new( + id, variants:, + ) + 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 5ab8f2a686..c442302bc8 100644 --- a/engines/dfc_provider/app/services/supplied_product_builder.rb +++ b/engines/dfc_provider/app/services/supplied_product_builder.rb @@ -1,11 +1,14 @@ # frozen_string_literal: true class SuppliedProductBuilder < DfcBuilder - def self.supplied_product(variant) - id = urls.enterprise_supplied_product_url( + def self.semantic_id(variant) + urls.enterprise_supplied_product_url( enterprise_id: variant.supplier_id, id: variant.id, ) + end + + def self.supplied_product(variant) product_uri = urls.enterprise_url( variant.supplier_id, spree_product_id: variant.product_id @@ -16,7 +19,7 @@ class SuppliedProductBuilder < DfcBuilder ) DfcProvider::SuppliedProduct.new( - id, + semantic_id(variant), name: variant.product_and_full_name, description: variant.description, productType: product_type(variant), diff --git a/engines/dfc_provider/spec/requests/product_groups_spec.rb b/engines/dfc_provider/spec/requests/product_groups_spec.rb new file mode 100644 index 0000000000..b3d1f3dbff --- /dev/null +++ b/engines/dfc_provider/spec/requests/product_groups_spec.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +require_relative "../swagger_helper" + +RSpec.describe "ProductGroups", swagger_doc: "dfc.yaml", rswag_autodoc: true do + let!(:user) { create(:oidc_user) } + let!(:enterprise) { create(:distributor_enterprise, id: 10_000, owner: user) } + let!(:product) { + create( + :product_with_image, + id: 90_000, + name: "Pesto", description: "Basil Pesto", + variants: [variant] + ) + } + let(:variant) { + build(:base_variant, id: 10_001, unit_value: 1, primary_taxon: taxon, supplier: enterprise) + } + let(:taxon) { + build( + :taxon, + name: "Processed Vegetable", + dfc_id: "https://github.com/datafoodconsortium/taxonomies/releases/latest/download/productTypes.rdf#processed-vegetable" + ) + } + + before { login_as user } + + path "/api/dfc/enterprises/{enterprise_id}/product_groups/{id}" do + parameter name: :enterprise_id, in: :path, type: :string + parameter name: :id, in: :path, type: :string + + let(:enterprise_id) { enterprise.id } + + get "Show ProductGroup" do + produces "application/json" + + response "200", "success" do + let(:id) { product.id } + + run_test! do + expect(json_response["@id"]).to eq "http://test.host/api/dfc/enterprises/10000/product_groups/90000" + + expect(json_response["dfc-b:hasVariant"]).to eq "http://test.host/api/dfc/enterprises/10000/supplied_products/10001" + end + end + end + end +end diff --git a/swagger/dfc.yaml b/swagger/dfc.yaml index f49e7180b2..b40e8ab013 100644 --- a/swagger/dfc.yaml +++ b/swagger/dfc.yaml @@ -554,6 +554,34 @@ paths: "@type": dfc-b:Person '404': description: not found + "/api/dfc/enterprises/{enterprise_id}/product_groups/{id}": + parameters: + - name: enterprise_id + in: path + required: true + schema: + type: string + - name: id + in: path + required: true + schema: + type: string + get: + summary: Show ProductGroup + tags: + - ProductGroups + responses: + '200': + description: success + content: + application/json: + examples: + test_example: + value: + "@context": https://www.datafoodconsortium.org + "@id": http://test.host/api/dfc/enterprises/10000/product_groups/90000 + "@type": dfc-b:SuppliedProduct + dfc-b:hasVariant: http://test.host/api/dfc/enterprises/10000/supplied_products/10001 "/api/dfc/enterprises/{enterprise_id}/social_medias/{name}": get: summary: Show social media