Skip to content

Commit

Permalink
Merge pull request #2919 from OfficeForProductSafetyAndStandards/api/…
Browse files Browse the repository at this point in the history
…psd-2073-create-product

Create product API - PSD-2073
  • Loading branch information
acallaghan authored Feb 14, 2024
2 parents 28efcf4 + 08e9a42 commit b6d1f39
Show file tree
Hide file tree
Showing 7 changed files with 588 additions and 12 deletions.
2 changes: 1 addition & 1 deletion app/controllers/api/v1/notifications_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def create
@notification.tasks_status["search_for_or_add_a_product"] = "in_progress"
@notification.save!(context: :search_for_or_add_a_product)

render action: :show
render action: :show, status: :created
end

private
Expand Down
23 changes: 23 additions & 0 deletions app/controllers/api/v1/products_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,21 @@ def index
@products = ProductDecorator.decorate_collection(@results)
end

def create
@product_form = ProductForm.new(product_create_params)

if @product_form.valid?
context = CreateProduct.call!(
@product_form.serializable_hash.merge(ushaser: current_user)
)

@product = context.product.decorate
render action: :show, status: :created, location: api_v1_product_path(context.product)
else
render json: { error: "Product parameters are not valid", errors: @product_form.errors }, status: :not_acceptable
end
end

def show; end

private
Expand All @@ -22,6 +37,14 @@ def set_search_params
@search = SearchParams.new(query_params.except(:page_name))
end

def product_create_params
params.require(:product).permit(
:name, :brand, :category, :subcategory, :product_code,
:webpage, :description, :country_of_origin, :barcode,
:authenticity, :when_placed_on_market, :has_markings, markings: []
)
end

def query_params
params.permit(:q, :sort_by, :sort_dir, :direction, :category, :retired_status, :page_name)
end
Expand Down
2 changes: 1 addition & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@
namespace :api, defaults: { format: :json } do
namespace :v1 do
resource :auth, only: %i[create destroy]
resources :products, only: %i[index show]
resources :products, only: %i[index create show]
resources :notifications, only: %i[create show]
end
end
Expand Down
2 changes: 1 addition & 1 deletion spec/requests/api/v1/notifications_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@

parameter name: :notification, in: :body, schema: { '$ref' => '#/components/schemas/new_notification' }

response "200", "Notification created" do
response "201", "Notification created" do
schema '$ref' => '#/components/schemas/notification_object'
let(:Authorization) { "Authorization #{user.api_tokens.first&.token}" }
let(:notification) do
Expand Down
71 changes: 68 additions & 3 deletions spec/requests/api/v1/products_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

let(:Authorization) { "Authorization #{user.api_tokens.first&.token}" }

let(:id) { create(:product).id }
let(:id) { create(:product, country_of_origin: 'country:GB').id }
run_test! do |response|

end
Expand Down Expand Up @@ -64,10 +64,75 @@

path "/api/v1/products" do
post "Creates a Product" do
description "Creates a Product"
description "Creates a Product in PSD"
tags "Products"
produces "application/json"
security [bearer: []]
parameter name: :Authorization, in: :header, type: :string
let(:Authorization) { "Authorization #{user.api_tokens.first&.token}" }

consumes 'application/json'

request_body_example value: {
product: {
name: 'Super Vac 2020',
category: 'Electrical appliances and equipment',
subcategory: 'Vacuum cleaners',
country_of_origin: 'country:GB',
when_placed_on_market: 'on_or_after_2021',
authenticity: 'genuine',
has_markings: 'markings_no'
}
}, name: 'product', summary: "An sample product"

parameter name: :product, in: :body, schema: { '$ref' => '#/components/schemas/new_product' }

response "201", "Product created" do
schema '$ref' => '#/components/schemas/product_object'
let(:Authorization) { "Authorization #{user.api_tokens.first&.token}" }
let(:product) do
{
name: 'Super Vac 2020',
brand: 'SuperDuper',
category: 'Electrical appliances and equipment',
subcategory: 'Vacuum cleaners',
country_of_origin: 'country:GB',
when_placed_on_market: 'on_or_after_2021',
authenticity: 'genuine',
has_markings: 'markings_no'
}
end

run_test! do |response|
json = JSON.parse(response.body, symbolize_names: true)

expect(json[:id]).to be_present
expect(json[:name]).to eq('Super Vac 2020')
expect(json[:category]).to eq('Electrical appliances and equipment')
expect(json[:subcategory]).to eq('Vacuum cleaners')
expect(json[:country_of_origin]).to eq('country:GB')
end
end

response "406", "Product not valid" do
let(:Authorization) { "Authorization #{user.api_tokens.first&.token}" }
let(:product) do
{
subcategory: 'Vacuum cleaners',
}
end
run_test! do |response|
json = JSON.parse(response.body, symbolize_names: true)

expect(json[:errors]).to be_present
end
end

response "401", "Unauthorised user" do
let(:Authorization) { "Authorization 0000" }
let(:id) { "invalid" }
run_test!
end
end
end

end
59 changes: 56 additions & 3 deletions spec/swagger_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,52 @@
non_compliant_reason: { type: :string, nullable: true }
}
},
new_product: {
title: "New Product",
type: :object,
properties: {
name: { type: :string },
brand: { type: :string },
product_code: { type: :string, nullable: true },
barcode: { type: :string, nullable: true },
category: { '$ref': "#/components/schemas/product_category" },
subcategory: { type: :string, nullable: true },
description: { type: :string, nullable: true },
country_of_origin: { '$ref': "#/components/schemas/country_code" },
authenticity: { '$ref': "#/components/schemas/product_authenticity" },
when_placed_on_market: { '$ref': "#/components/schemas/product_when_placed_on_market" },
has_markings: { '$ref': "#/components/schemas/product_has_markings" },
markings: { type: :array, items: { '$ref': "#/components/schemas/product_has_markings" } },
webpage: { type: :string, nullable: true },
}
},
product_category: {
title: "Product (category)",
type: :string,
enum: Rails.application.config.product_constants["product_category"]
},
product_when_placed_on_market: {
title: "Product (when_placed_on_market)",
type: :string,
enum: %w[on_or_after_2021 before_2021 unknown_date]
},
product_authenticity: {
title: "Product (authenticity)",
type: :string,
enum: %w[genuine counterfeit unsure]
},
product_markings: {
title: "Product (markings)",
type: :array,
items: { type: :string },
enum: Product::MARKINGS
},
product_has_markings: {
title: "Product (markings)",
type: :array,
items: { type: :string },
enum: Product.has_markings.keys
},
notification_object: {
title: "Notification",
type: :object,
Expand Down Expand Up @@ -68,10 +114,12 @@
brand: { type: :string },
product_code: { type: :string, nullable: true },
barcode: { type: :string, nullable: true },
category: { type: :string },
category: { '$ref': "#/components/schemas/product_category" },
subcategory: { type: :string, nullable: true },
description: { type: :string },
country_of_origin: { type: :string },
description: { type: :string, nullable: true },
country_of_origin: { '$ref': "#/components/schemas/country_code" },
authenticity: { '$ref': "#/components/schemas/product_authenticity" },
when_placed_on_market: { '$ref': "#/components/schemas/product_when_placed_on_market" },
webpage: { type: :string, nullable: true },
owning_team: { type: :object,
properties: {
Expand All @@ -81,6 +129,11 @@
product_images: { type: :array, items: { type: :object, properties: { url: { type: :string } } } },
},
required: %w[name]
},
country_code: {
title: "Country",
type: :string,
enum: Country.notifying_countries.map { |c| c[1] }.sort
}
}
},
Expand Down
Loading

0 comments on commit b6d1f39

Please sign in to comment.