From f21beeaee7232db56480b1cff498b80d992fbd5c Mon Sep 17 00:00:00 2001 From: Sylvain Date: Tue, 30 Aug 2022 14:16:49 +0200 Subject: [PATCH] (api) OpenAPI prices index endpoint --- CHANGELOG.md | 1 + .../open_api/v1/prices_controller.rb | 23 +++++++ app/doc/open_api/v1/prices_doc.rb | 63 +++++++++++++++++++ .../open_api/v1/prices/index.json.jbuilder | 5 ++ config/initializers/apipie.rb | 9 ++- config/routes.rb | 1 + test/integration/open_api/prices_test.rb | 32 ++++++++++ .../integration/open_api/reservations_test.rb | 4 ++ 8 files changed, 136 insertions(+), 2 deletions(-) create mode 100644 app/controllers/open_api/v1/prices_controller.rb create mode 100644 app/doc/open_api/v1/prices_doc.rb create mode 100644 app/views/open_api/v1/prices/index.json.jbuilder create mode 100644 test/integration/open_api/prices_test.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index c04472f1a..b85e8c438 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ - OpenAPI spaces endpoints (index/show) - OpenAPI plans endpoints (index/show) - OpenAPI plans categories index endpoint +- OpenAPI prices index endpoint - Improved automated test on statistics generation - Refactored statistics generation - Refactored test helpers diff --git a/app/controllers/open_api/v1/prices_controller.rb b/app/controllers/open_api/v1/prices_controller.rb new file mode 100644 index 000000000..b5652bb81 --- /dev/null +++ b/app/controllers/open_api/v1/prices_controller.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +# public API controller for resources of type Price +class OpenAPI::V1::PricesController < OpenAPI::V1::BaseController + extend OpenAPI::ApiDoc + include Rails::Pagination + expose_doc + + def index + @prices = PriceService.list(params).order(created_at: :desc) + + return if params[:page].blank? + + @prices = @prices.page(params[:page]).per(per_page) + paginate @prices, per_page: per_page + end + + private + + def per_page + params[:per_page] || 20 + end +end diff --git a/app/doc/open_api/v1/prices_doc.rb b/app/doc/open_api/v1/prices_doc.rb new file mode 100644 index 000000000..7f5fc9209 --- /dev/null +++ b/app/doc/open_api/v1/prices_doc.rb @@ -0,0 +1,63 @@ +# frozen_string_literal: true + +# openAPI documentation for prices endpoint +class OpenAPI::V1::PricesDoc < OpenAPI::V1::BaseDoc + resource_description do + short 'Prices' + desc 'Prices for all resources' + formats FORMATS + api_version API_VERSION + end + + include OpenAPI::V1::Concerns::ParamGroups + + doc_for :index do + api :GET, "/#{API_VERSION}/prices", 'Prices index' + description 'Index of prices, with optional pagination. Order by *created_at* descendant.' + param_group :pagination + param :plan_id, [Integer, Array, 'null'], optional: true, desc: 'Scope the request to one or various plans. Provide "null" to ' \ + 'this parameter to get prices not associated with any plans (prices ' \ + 'that applies to users without subscriptions).' + param :group_id, [Integer, Array], optional: true, desc: 'Scope the request to one or various groups.' + param :priceable_type, %w[Machine Space], optional: true, desc: 'Scope the request to a specific type of resource.' + param :priceable_id, [Integer, Array], optional: true, desc: 'Scope the request to one or various resources.' + + example <<-PRICES + # /open_api/v1/prices?priceable_type=Space&page=1&per_page=3 + { + "prices": [ + { + "id": 502, + "priceable_id": 1, + "priceable_type": "Space", + "group_id": 4, + "plan_id": 5, + "amount": 1800, + "updated_at": "2021-06-21T09:40:40.467277+01:00", + "created_at": "2021-06-21T09:40:40.467277+01:00", + }, + { + "id": 503, + "priceable_id": 1, + "priceable_type": "Space", + "group_id": 2, + "plan_id": 1, + "amount": 1600, + "updated_at": "2021-06-21T09:40:40.470904+01:00", + "created_at": "2021-06-21T09:40:40.470904+01:00", + }, + { + "id": 504, + "priceable_id": 1, + "priceable_type": "Space", + "group_id": 3, + "plan_id": 3, + "amount": 2000, + "updated_at": "2021-06-21T09:40:40.470876+01:00", + "created_at": "2021-06-21T09:40:40.470876+01:00", + } + ] + } + PRICES + end +end diff --git a/app/views/open_api/v1/prices/index.json.jbuilder b/app/views/open_api/v1/prices/index.json.jbuilder new file mode 100644 index 000000000..d37f251f2 --- /dev/null +++ b/app/views/open_api/v1/prices/index.json.jbuilder @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +json.prices @prices do |price| + json.extract! price, :id, :group_id, :plan_id, :priceable_id, :priceable_type, :amount, :created_at, :updated_at +end diff --git a/config/initializers/apipie.rb b/config/initializers/apipie.rb index 1ddb26ee5..20da686ae 100644 --- a/config/initializers/apipie.rb +++ b/config/initializers/apipie.rb @@ -5,7 +5,7 @@ Apipie.configure do |config| config.api_base_url = '/open_api' config.doc_base_url = '/open_api/doc' # where is your API defined? - config.api_controllers_matcher = "#{Rails.root}/app/controllers/open_api/v1/*.rb" + config.api_controllers_matcher = Rails.root.join('app/controllers/open_api/v1/*.rb') config.validate = false config.translate = false config.default_locale = nil @@ -22,7 +22,12 @@ Apipie.configure do |config| = Json --- - Depending on your client, you may have to set header Accept: application/json for every request, + Depending on your client, you may have to set header Accept: application/json for every request, otherwise some clients may request *html* by default which will result in error. + + = Amounts + --- + Everywhere in the OpenAPI amounts are reported in cents. For exemple, if you get { "amount" : 1000 }, + from the OpenAPI, this means that the price is 10 € (or whatever your currency is). RDOC end diff --git a/config/routes.rb b/config/routes.rb index 763080a7f..2c8c4adab 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -242,6 +242,7 @@ Rails.application.routes.draw do scope only: :index do resources :plans, only: %i[index show] resources :plan_categories + resources :prices resources :users resources :trainings resources :user_trainings diff --git a/test/integration/open_api/prices_test.rb b/test/integration/open_api/prices_test.rb new file mode 100644 index 000000000..19086af3b --- /dev/null +++ b/test/integration/open_api/prices_test.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +require 'test_helper' + +module OpenApi; end + +class OpenApi::PricesTest < ActionDispatch::IntegrationTest + def setup + @token = OpenAPI::Client.find_by(name: 'minitest').token + end + + test 'list all prices' do + get '/open_api/v1/prices', headers: open_api_headers(@token) + assert_response :success + + assert_equal Price.count, json_response(response.body)[:prices].length + end + + test 'list all prices with pagination' do + get '/open_api/v1/prices?page=1&per_page=5', headers: open_api_headers(@token) + assert_response :success + + assert_equal 5, json_response(response.body)[:prices].length + end + + test 'list all prices for a specific machine' do + get '/open_api/v1/prices?priceable_type=Machine&priceable_id=1', headers: open_api_headers(@token) + assert_response :success + + assert_equal [1], json_response(response.body)[:prices].pluck(:priceable_id).uniq + end +end diff --git a/test/integration/open_api/reservations_test.rb b/test/integration/open_api/reservations_test.rb index d1cec96f2..975351afc 100644 --- a/test/integration/open_api/reservations_test.rb +++ b/test/integration/open_api/reservations_test.rb @@ -12,11 +12,15 @@ class OpenApi::ReservationsTest < ActionDispatch::IntegrationTest test 'list all reservations' do get '/open_api/v1/reservations', headers: open_api_headers(@token) assert_response :success + + assert_equal Reservation.count, json_response(response.body)[:reservations].length end test 'list all reservations with pagination' do get '/open_api/v1/reservations?page=1&per_page=5', headers: open_api_headers(@token) assert_response :success + + assert json_response(response.body)[:reservations].length <= 5 end test 'list all reservations for a user' do