mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-02-14 23:47:48 +00:00
Merge pull request #11397 from rioug/11331-add-required-field-dcf-enterprise
Add required enterprise fields to DFC API
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Controller used to provide the Address API for the DFC application
|
||||
module DfcProvider
|
||||
class AddressesController < DfcProvider::ApplicationController
|
||||
def show
|
||||
address = Spree::Address.find(params.require(:id))
|
||||
|
||||
return not_found unless authorized(address)
|
||||
|
||||
dfc_address = AddressBuilder.address(address)
|
||||
render json: DfcIo.export(dfc_address)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Does the current user have access to this address?
|
||||
#
|
||||
# It's possible to guess address ids and therefore we need to prevent the
|
||||
# collection of sensitive customer data.
|
||||
#
|
||||
# We may want to extend the list of authorised addresses once the DFC API
|
||||
# references them. To start with, we would only need enterprise addresses
|
||||
# but I included a few more options to show how this will probably evolve.
|
||||
#
|
||||
# Currently not checked models:
|
||||
#
|
||||
# - Spree::Card
|
||||
# - Spree::Order
|
||||
# - Spree::Shipment
|
||||
# - Subscription
|
||||
def authorized(address)
|
||||
current_user.ship_address_id == address.id ||
|
||||
current_user.bill_address_id == address.id ||
|
||||
[
|
||||
customer_address(address),
|
||||
public_enterprise_group_address(address),
|
||||
public_enterprise_address(address),
|
||||
managed_enterprise_address(address),
|
||||
].any?(&:exists?)
|
||||
end
|
||||
|
||||
def customer_address(address)
|
||||
current_user.customers.where(bill_address: address).or(
|
||||
current_user.customers.where(ship_address: address)
|
||||
)
|
||||
end
|
||||
|
||||
def public_enterprise_group_address(address)
|
||||
EnterpriseGroup.where(address:)
|
||||
end
|
||||
|
||||
def public_enterprise_address(address)
|
||||
Enterprise.activated.visible.is_distributor.where(address:)
|
||||
end
|
||||
|
||||
def managed_enterprise_address(address)
|
||||
current_user.enterprises.where(address:)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -9,6 +9,7 @@ module DfcProvider
|
||||
enterprise = EnterpriseBuilder.enterprise(current_enterprise)
|
||||
render json: DfcIo.export(
|
||||
enterprise,
|
||||
*enterprise.localizations,
|
||||
*enterprise.suppliedProducts,
|
||||
*enterprise.catalogItems,
|
||||
)
|
||||
|
||||
13
engines/dfc_provider/app/services/address_builder.rb
Normal file
13
engines/dfc_provider/app/services/address_builder.rb
Normal file
@@ -0,0 +1,13 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class AddressBuilder < DfcBuilder
|
||||
def self.address(address)
|
||||
DataFoodConsortium::Connector::Address.new(
|
||||
urls.address_url(address),
|
||||
street: address.address1,
|
||||
postalCode: address.zipcode,
|
||||
city: address.city,
|
||||
country: address.country.name
|
||||
)
|
||||
end
|
||||
end
|
||||
@@ -5,13 +5,17 @@ class EnterpriseBuilder < DfcBuilder
|
||||
variants = VariantFetcher.new(enterprise).scope.to_a
|
||||
catalog_items = variants.map(&method(:catalog_item))
|
||||
supplied_products = catalog_items.map(&:product)
|
||||
address = AddressBuilder.address(enterprise.address)
|
||||
|
||||
DataFoodConsortium::Connector::Enterprise.new(
|
||||
enterprise.name
|
||||
urls.enterprise_url(enterprise.id),
|
||||
name: enterprise.name,
|
||||
description: enterprise.description,
|
||||
vatNumber: enterprise.abn,
|
||||
suppliedProducts: supplied_products,
|
||||
catalogItems: catalog_items
|
||||
).tap do |e|
|
||||
e.semanticId = urls.enterprise_url(enterprise.id)
|
||||
e.suppliedProducts = supplied_products
|
||||
e.catalogItems = catalog_items
|
||||
e.addLocalization(address)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
DfcProvider::Engine.routes.draw do
|
||||
resources :addresses, only: [:show]
|
||||
resources :enterprises, only: [:show] do
|
||||
resources :catalog_items, only: [:index, :show, :update]
|
||||
resources :supplied_products, only: [:create, :show, :update]
|
||||
|
||||
41
engines/dfc_provider/spec/requests/addresses_spec.rb
Normal file
41
engines/dfc_provider/spec/requests/addresses_spec.rb
Normal file
@@ -0,0 +1,41 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require DfcProvider::Engine.root.join("spec/swagger_helper")
|
||||
|
||||
describe "Addresses", type: :request, swagger_doc: "dfc-v1.7/swagger.yaml", rswag_autodoc: true do
|
||||
let(:user) { create(:oidc_user) }
|
||||
let(:address) { create(:address, id: 40_000) }
|
||||
let(:result) { json_response }
|
||||
|
||||
before { login_as user }
|
||||
|
||||
path "/api/dfc-v1.7/addresses/{id}" do
|
||||
get "Show address" do
|
||||
parameter name: :id, in: :path, type: :string
|
||||
produces "application/json"
|
||||
|
||||
response "200", "successful" do
|
||||
let(:id) { address.id }
|
||||
|
||||
before { create(:enterprise, owner: user, address:) }
|
||||
|
||||
run_test! do
|
||||
expect(result["@id"]).to eq "http://test.host/api/dfc-v1.7/addresses/40000"
|
||||
expect(result["@type"]).to eq "dfc-b:Address"
|
||||
end
|
||||
end
|
||||
|
||||
response "404", "not found" do
|
||||
context "when the address doesn't exist" do
|
||||
let(:id) { 0 }
|
||||
run_test!
|
||||
end
|
||||
|
||||
context "when the address doesn't belong to you" do
|
||||
let(:id) { address.id }
|
||||
run_test!
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -5,7 +5,13 @@ require DfcProvider::Engine.root.join("spec/swagger_helper")
|
||||
describe "CatalogItems", type: :request, swagger_doc: "dfc-v1.7/swagger.yaml",
|
||||
rswag_autodoc: true do
|
||||
let(:user) { create(:oidc_user, id: 12_345) }
|
||||
let(:enterprise) { create(:distributor_enterprise, id: 10_000, owner: user) }
|
||||
let(:enterprise) {
|
||||
create(
|
||||
:distributor_enterprise,
|
||||
id: 10_000, owner: user, name: "Fred's Farm", description: "Beautiful",
|
||||
address: build(:address, id: 40_000),
|
||||
)
|
||||
}
|
||||
let(:product) {
|
||||
create(
|
||||
:base_product,
|
||||
|
||||
@@ -4,7 +4,14 @@ require DfcProvider::Engine.root.join("spec/swagger_helper")
|
||||
|
||||
describe "Enterprises", type: :request, swagger_doc: "dfc-v1.7/swagger.yaml", rswag_autodoc: true do
|
||||
let!(:user) { create(:oidc_user) }
|
||||
let!(:enterprise) { create(:distributor_enterprise, id: 10_000, owner: user) }
|
||||
let!(:enterprise) do
|
||||
create(
|
||||
:distributor_enterprise,
|
||||
id: 10_000, owner: user, abn: "123 456", name: "Fred's Farm",
|
||||
description: "This is an awesome enterprise",
|
||||
address: build(:address, id: 40_000, address1: "42 Doveton Street"),
|
||||
)
|
||||
end
|
||||
let!(:product) {
|
||||
create(
|
||||
:base_product,
|
||||
@@ -36,7 +43,11 @@ describe "Enterprises", type: :request, swagger_doc: "dfc-v1.7/swagger.yaml", rs
|
||||
let(:id) { enterprise.id }
|
||||
|
||||
run_test! do
|
||||
expect(response.body).to include "Fred's Farm"
|
||||
expect(response.body).to include "This is an awesome enterprise"
|
||||
expect(response.body).to include "123 456"
|
||||
expect(response.body).to include "Apple"
|
||||
expect(response.body).to include "42 Doveton Street"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
37
engines/dfc_provider/spec/services/address_builder_spec.rb
Normal file
37
engines/dfc_provider/spec/services/address_builder_spec.rb
Normal file
@@ -0,0 +1,37 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require DfcProvider::Engine.root.join("spec/spec_helper")
|
||||
|
||||
describe AddressBuilder do
|
||||
subject(:result) { described_class.address(address) }
|
||||
let(:address) {
|
||||
build(
|
||||
:address,
|
||||
id: 1, address1: "Paradise 15", zipcode: "0001", city: "Goosnargh",
|
||||
)
|
||||
}
|
||||
|
||||
describe ".address" do
|
||||
it "assigns a semantic id" do
|
||||
expect(result.semanticId).to eq(
|
||||
"http://test.host/api/dfc-v1.7/addresses/1"
|
||||
)
|
||||
end
|
||||
|
||||
it "assigns a street" do
|
||||
expect(result.street).to eq "Paradise 15"
|
||||
end
|
||||
|
||||
it "assigns a postal code" do
|
||||
expect(result.postalCode).to eq "0001"
|
||||
end
|
||||
|
||||
it "assigns a city" do
|
||||
expect(result.city).to eq "Goosnargh"
|
||||
end
|
||||
|
||||
it "assigns a country" do
|
||||
expect(result.country).to eq "Australia"
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -4,23 +4,49 @@ require DfcProvider::Engine.root.join("spec/spec_helper")
|
||||
|
||||
describe EnterpriseBuilder do
|
||||
subject(:builder) { described_class }
|
||||
let(:enterprise) { variant.product.supplier }
|
||||
let(:variant) { create(:product, name: "Apple").variants.first }
|
||||
let(:enterprise) {
|
||||
build(
|
||||
:enterprise,
|
||||
id: 10_000, name: "Fabi's Farm",
|
||||
description: "The place where stuff grows", abn: "123 456 789 0",
|
||||
address: build(:address, id: 40_000, city: "Melbourne"),
|
||||
)
|
||||
}
|
||||
let(:variant) {
|
||||
create(:product, supplier: enterprise, name: "Apple").variants.first
|
||||
}
|
||||
|
||||
describe ".enterprise" do
|
||||
it "assigns a semantic id" do
|
||||
result = builder.enterprise(enterprise)
|
||||
let(:result) { builder.enterprise(enterprise) }
|
||||
|
||||
it "assigns a semantic id" do
|
||||
expect(result.semanticId).to eq(
|
||||
"http://test.host/api/dfc-v1.7/enterprises/#{enterprise.id}"
|
||||
"http://test.host/api/dfc-v1.7/enterprises/10000"
|
||||
)
|
||||
end
|
||||
|
||||
it "assignes products" do
|
||||
result = builder.enterprise(enterprise)
|
||||
it "assigns a name" do
|
||||
expect(result.name).to eq "Fabi's Farm"
|
||||
end
|
||||
|
||||
it "assigns a description" do
|
||||
expect(result.description).to eq "The place where stuff grows"
|
||||
end
|
||||
|
||||
it "assigns a VAT Number (ABN in australia)" do
|
||||
expect(result.vatNumber).to eq "123 456 789 0"
|
||||
end
|
||||
|
||||
it "assigns products" do
|
||||
expect(variant).to be_persisted
|
||||
|
||||
expect(result.suppliedProducts.count).to eq 1
|
||||
expect(result.suppliedProducts[0].name).to eq "Apple"
|
||||
end
|
||||
|
||||
it "assigns an address" do
|
||||
expect(result.localizations.count).to eq 1
|
||||
expect(result.localizations[0].city).to eq "Melbourne"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -38,6 +38,32 @@ security:
|
||||
- ofn_api_token: []
|
||||
- ofn_session: []
|
||||
paths:
|
||||
"/api/dfc-v1.7/addresses/{id}":
|
||||
get:
|
||||
summary: Show address
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: successful
|
||||
content:
|
||||
application/json:
|
||||
examples:
|
||||
test_example:
|
||||
value:
|
||||
"@context": https://www.datafoodconsortium.org
|
||||
"@id": http://test.host/api/dfc-v1.7/addresses/40000
|
||||
"@type": dfc-b:Address
|
||||
dfc-b:hasStreet: 10 Lovely Street
|
||||
dfc-b:hasPostalCode: '20170'
|
||||
dfc-b:hasCity: Herndon
|
||||
dfc-b:hasCountry: Australia
|
||||
'404':
|
||||
description: not found
|
||||
"/api/dfc-v1.7/enterprises/{enterprise_id}/catalog_items":
|
||||
parameters:
|
||||
- name: enterprise_id
|
||||
@@ -64,9 +90,9 @@ paths:
|
||||
dfc-b:affiliates: http://test.host/api/dfc-v1.7/enterprises/10000
|
||||
- "@id": http://test.host/api/dfc-v1.7/enterprises/10000
|
||||
"@type": dfc-b:Enterprise
|
||||
dfc-b:hasName: ''
|
||||
dfc-b:hasDescription: ''
|
||||
dfc-b:VATnumber: ''
|
||||
dfc-b:hasAddress: http://test.host/api/dfc-v1.7/addresses/40000
|
||||
dfc-b:hasName: Fred's Farm
|
||||
dfc-b:hasDescription: Beautiful
|
||||
dfc-b:supplies: http://test.host/api/dfc-v1.7/enterprises/10000/supplied_products/10001
|
||||
dfc-b:manages: http://test.host/api/dfc-v1.7/enterprises/10000/catalog_items/10001
|
||||
- "@id": http://test.host/api/dfc-v1.7/enterprises/10000/catalog_items/10001
|
||||
@@ -221,11 +247,18 @@ paths:
|
||||
"@graph":
|
||||
- "@id": http://test.host/api/dfc-v1.7/enterprises/10000
|
||||
"@type": dfc-b:Enterprise
|
||||
dfc-b:hasName: ''
|
||||
dfc-b:hasDescription: ''
|
||||
dfc-b:VATnumber: ''
|
||||
dfc-b:hasAddress: http://test.host/api/dfc-v1.7/addresses/40000
|
||||
dfc-b:hasName: Fred's Farm
|
||||
dfc-b:hasDescription: This is an awesome enterprise
|
||||
dfc-b:VATnumber: 123 456
|
||||
dfc-b:supplies: http://test.host/api/dfc-v1.7/enterprises/10000/supplied_products/10001
|
||||
dfc-b:manages: http://test.host/api/dfc-v1.7/enterprises/10000/catalog_items/10001
|
||||
- "@id": http://test.host/api/dfc-v1.7/addresses/40000
|
||||
"@type": dfc-b:Address
|
||||
dfc-b:hasStreet: 42 Doveton Street
|
||||
dfc-b:hasPostalCode: '20170'
|
||||
dfc-b:hasCity: Herndon
|
||||
dfc-b:hasCountry: Australia
|
||||
- "@id": http://test.host/api/dfc-v1.7/enterprises/10000/supplied_products/10001
|
||||
"@type": dfc-b:SuppliedProduct
|
||||
dfc-b:name: Apple
|
||||
|
||||
Reference in New Issue
Block a user