diff --git a/engines/dfc_provider/app/controllers/dfc_provider/catalog_items_controller.rb b/engines/dfc_provider/app/controllers/dfc_provider/catalog_items_controller.rb index 27cf9a824f..c8b2ba59ff 100644 --- a/engines/dfc_provider/app/controllers/dfc_provider/catalog_items_controller.rb +++ b/engines/dfc_provider/app/controllers/dfc_provider/catalog_items_controller.rb @@ -8,6 +8,12 @@ module DfcProvider def index person = PersonBuilder.person(current_user) + + enterprises = current_user.enterprises.map do |enterprise| + EnterpriseBuilder.enterprise(enterprise) + end + person.affiliatedOrganizations = enterprises + render json: DfcIo.export( person, *person.affiliatedOrganizations, diff --git a/engines/dfc_provider/app/controllers/dfc_provider/enterprise_groups_controller.rb b/engines/dfc_provider/app/controllers/dfc_provider/enterprise_groups_controller.rb new file mode 100644 index 0000000000..55600c1ccd --- /dev/null +++ b/engines/dfc_provider/app/controllers/dfc_provider/enterprise_groups_controller.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +# OFN EnterpriseGroup is represented as DFC Enterprise. +module DfcProvider + class EnterpriseGroupsController < DfcProvider::ApplicationController + def index + person = PersonBuilder.person(current_user) + groups = current_user.owned_groups + enterprises = groups.map do |group| + EnterpriseBuilder.enterprise_group(group) + end + person.affiliatedOrganizations = enterprises + render json: DfcIo.export(person, *enterprises) + end + + def show + group = EnterpriseGroup.find(params[:id]) + address = AddressBuilder.address(group.address) + enterprise = EnterpriseBuilder.enterprise_group(group) + enterprise.addLocalization(address) + render json: DfcIo.export(enterprise, address) + end + end +end diff --git a/engines/dfc_provider/app/controllers/dfc_provider/enterprises_controller.rb b/engines/dfc_provider/app/controllers/dfc_provider/enterprises_controller.rb index 74cb1b0ccd..5793d2819f 100644 --- a/engines/dfc_provider/app/controllers/dfc_provider/enterprises_controller.rb +++ b/engines/dfc_provider/app/controllers/dfc_provider/enterprises_controller.rb @@ -7,6 +7,12 @@ module DfcProvider def show enterprise = EnterpriseBuilder.enterprise(current_enterprise) + + group_ids = current_enterprise.groups.map do |group| + DfcProvider::Engine.routes.url_helpers.enterprise_group_url(group.id) + end + enterprise.registerSemanticProperty("dfc-b:affiliates") { group_ids } + render json: DfcIo.export( enterprise, *enterprise.localizations, diff --git a/engines/dfc_provider/app/services/enterprise_builder.rb b/engines/dfc_provider/app/services/enterprise_builder.rb index bc9a4e1cbd..a32d63dfcb 100644 --- a/engines/dfc_provider/app/services/enterprise_builder.rb +++ b/engines/dfc_provider/app/services/enterprise_builder.rb @@ -18,4 +18,22 @@ class EnterpriseBuilder < DfcBuilder e.addLocalization(address) end end + + def self.enterprise_group(group) + members = group.enterprises.map do |member| + urls.enterprise_url(member.id) + end + + DataFoodConsortium::Connector::Enterprise.new( + urls.enterprise_group_url(group.id), + name: group.name, + description: group.description, + ).tap do |enterprise| + # This property has been agreed by the DFC but hasn't made it's way into + # the Connector yet. + enterprise.registerSemanticProperty("dfc-b:affiliatedBy") do + members + end + end + end end diff --git a/engines/dfc_provider/app/services/person_builder.rb b/engines/dfc_provider/app/services/person_builder.rb index ce3c4beefa..69f22f6495 100644 --- a/engines/dfc_provider/app/services/person_builder.rb +++ b/engines/dfc_provider/app/services/person_builder.rb @@ -6,13 +6,6 @@ class PersonBuilder < DfcBuilder urls.person_url(user.id), firstName: user.bill_address&.firstname, lastName: user.bill_address&.lastname, - affiliatedOrganizations: enterprises(user), ) end - - def self.enterprises(user) - user.enterprises.map do |enterprise| - EnterpriseBuilder.enterprise(enterprise) - end - end end diff --git a/engines/dfc_provider/config/routes.rb b/engines/dfc_provider/config/routes.rb index 4064a83fca..0f81066b3a 100644 --- a/engines/dfc_provider/config/routes.rb +++ b/engines/dfc_provider/config/routes.rb @@ -6,5 +6,6 @@ DfcProvider::Engine.routes.draw do resources :catalog_items, only: [:index, :show, :update] resources :supplied_products, only: [:create, :show, :update] end + resources :enterprise_groups, only: [:index, :show] resources :persons, only: [:show] end diff --git a/engines/dfc_provider/spec/requests/enterprise_groups_spec.rb b/engines/dfc_provider/spec/requests/enterprise_groups_spec.rb new file mode 100644 index 0000000000..cf1d356707 --- /dev/null +++ b/engines/dfc_provider/spec/requests/enterprise_groups_spec.rb @@ -0,0 +1,70 @@ +# frozen_string_literal: true + +require_relative "../swagger_helper" + +describe "EnterpriseGroups", type: :request, swagger_doc: "dfc.yaml", rswag_autodoc: true do + let(:user) { create(:oidc_user, id: 12_345) } + let(:group) { + create( + :enterprise_group, + id: 60_000, owner: user, name: "Sustainable Farmers", address:, + enterprises: [enterprise], + ) + } + let(:address) { create(:address, id: 40_000, address1: "8 Acres Drive") } + let(:enterprise) { create(:enterprise, id: 10_000) } + + before { login_as user } + + path "/api/dfc/enterprise_groups" do + get "List groups" do + produces "application/json" + + response "200", "successful" do + let!(:groups) { [group] } + + run_test! do + graph = json_response["@graph"] + + expect(graph[0]["@type"]).to eq "dfc-b:Person" + expect(graph[0]).to include( + "dfc-b:affiliates" => "http://test.host/api/dfc/enterprise_groups/60000", + ) + + expect(graph[1]["@type"]).to eq "dfc-b:Enterprise" + expect(graph[1]).to include( + "dfc-b:hasName" => "Sustainable Farmers", + "dfc-b:affiliatedBy" => "http://test.host/api/dfc/enterprises/10000", + ) + end + end + end + end + + path "/api/dfc/enterprise_groups/{id}" do + get "Show groups" do + parameter name: :id, in: :path, type: :string + produces "application/json" + + response "200", "successful" do + let(:id) { group.id } + + run_test! do + graph = json_response["@graph"] + + expect(graph[0]).to include( + "@type" => "dfc-b:Enterprise", + "dfc-b:hasName" => "Sustainable Farmers", + "dfc-b:hasAddress" => "http://test.host/api/dfc/addresses/40000", + "dfc-b:affiliatedBy" => "http://test.host/api/dfc/enterprises/10000", + ) + + expect(graph[1]).to include( + "@type" => "dfc-b:Address", + "dfc-b:hasStreet" => "8 Acres Drive", + ) + end + end + end + end +end diff --git a/engines/dfc_provider/spec/requests/enterprises_spec.rb b/engines/dfc_provider/spec/requests/enterprises_spec.rb index ebe66f827b..3c3835452f 100644 --- a/engines/dfc_provider/spec/requests/enterprises_spec.rb +++ b/engines/dfc_provider/spec/requests/enterprises_spec.rb @@ -12,6 +12,13 @@ describe "Enterprises", type: :request, swagger_doc: "dfc.yaml", rswag_autodoc: address: build(:address, id: 40_000, address1: "42 Doveton Street"), ) end + let!(:enterprise_group) do + create( + :enterprise_group, + id: 60_000, owner: user, name: "Local Farmers", + enterprises: [enterprise], + ) + end let!(:product) { create( :base_product, @@ -48,6 +55,10 @@ describe "Enterprises", type: :request, swagger_doc: "dfc.yaml", rswag_autodoc: expect(response.body).to include "123 456" expect(response.body).to include "Apple" expect(response.body).to include "42 Doveton Street" + + expect(json_response["@graph"][0]).to include( + "dfc-b:affiliates" => "http://test.host/api/dfc/enterprise_groups/60000", + ) end end end diff --git a/swagger/dfc.yaml b/swagger/dfc.yaml index e0920b29c1..8927ccfc1d 100644 --- a/swagger/dfc.yaml +++ b/swagger/dfc.yaml @@ -234,6 +234,64 @@ paths: "@type": "@id" dfc-b:stockLimitation: '3' dfc-b:sku: new-sku + "/api/dfc/enterprise_groups": + get: + summary: List groups + tags: + - EnterpriseGroups + responses: + '200': + description: successful + content: + application/json: + examples: + test_example: + value: + "@context": https://www.datafoodconsortium.org + "@graph": + - "@id": http://test.host/api/dfc/persons/12345 + "@type": dfc-b:Person + dfc-b:affiliates: http://test.host/api/dfc/enterprise_groups/60000 + - "@id": http://test.host/api/dfc/enterprise_groups/60000 + "@type": dfc-b:Enterprise + dfc-b:hasName: Sustainable Farmers + dfc-b:hasDescription: this is a group + dfc-b:VATnumber: '' + dfc-b:affiliatedBy: http://test.host/api/dfc/enterprises/10000 + "/api/dfc/enterprise_groups/{id}": + get: + summary: Show groups + parameters: + - name: id + in: path + required: true + schema: + type: string + tags: + - EnterpriseGroups + responses: + '200': + description: successful + content: + application/json: + examples: + test_example: + value: + "@context": https://www.datafoodconsortium.org + "@graph": + - "@id": http://test.host/api/dfc/enterprise_groups/60000 + "@type": dfc-b:Enterprise + dfc-b:hasAddress: http://test.host/api/dfc/addresses/40000 + dfc-b:hasName: Sustainable Farmers + dfc-b:hasDescription: this is a group + dfc-b:VATnumber: '' + dfc-b:affiliatedBy: http://test.host/api/dfc/enterprises/10000 + - "@id": http://test.host/api/dfc/addresses/40000 + "@type": dfc-b:Address + dfc-b:hasStreet: 8 Acres Drive + dfc-b:hasPostalCode: '20170' + dfc-b:hasCity: Herndon + dfc-b:hasCountry: Australia "/api/dfc/enterprises/{id}": get: summary: Show enterprise @@ -263,6 +321,7 @@ paths: dfc-b:VATnumber: 123 456 dfc-b:supplies: http://test.host/api/dfc/enterprises/10000/supplied_products/10001 dfc-b:manages: http://test.host/api/dfc/enterprises/10000/catalog_items/10001 + dfc-b:affiliates: http://test.host/api/dfc/enterprise_groups/60000 - "@id": http://test.host/api/dfc/addresses/40000 "@type": dfc-b:Address dfc-b:hasStreet: 42 Doveton Street