Merge pull request #1280 from okriuchykhin/ok_SCI_2688

Add SHOW, UPDATE and DELETE inventory item endpoints [SCI-2688][SCI-2689]
This commit is contained in:
Alex Kriuchykhin 2018-08-24 15:49:34 +02:00 committed by GitHub
commit a825f1c2ec
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 142 additions and 76 deletions

View file

@ -7,8 +7,9 @@ module Api
before_action :load_inventory, only: %i(show) before_action :load_inventory, only: %i(show)
def index def index
inventories = inventories = @team.repositories
@team.repositories.page(params[:page]).per(params[:page_size]) .page(params.dig(:page, :number))
.per(params.dig(:page, :size))
render jsonapi: inventories, each_serializer: InventorySerializer render jsonapi: inventories, each_serializer: InventorySerializer
end end
@ -20,7 +21,7 @@ module Api
def load_team def load_team
@team = Team.find(params.require(:team_id)) @team = Team.find(params.require(:team_id))
return render jsonapi: {}, status: :forbidden unless can_read_team?(@team) render jsonapi: {}, status: :forbidden unless can_read_team?(@team)
end end
def load_inventory def load_inventory

View file

@ -5,7 +5,8 @@ module Api
class InventoryItemsController < BaseController class InventoryItemsController < BaseController
before_action :load_team before_action :load_team
before_action :load_inventory before_action :load_inventory
before_action :check_manage_permissions, only: %i(create) before_action :load_inventory_item, only: %i(show update destroy)
before_action :check_manage_permissions, only: %i(create update destroy)
def index def index
items = items =
@ -35,7 +36,7 @@ module Api
cell_attributes = cell_params[:attributes] cell_attributes = cell_params[:attributes]
column = column =
@inventory.repository_columns.find(cell_attributes[:column_id]) @inventory.repository_columns.find(cell_attributes[:column_id])
RepositoryCell.create_with_value( RepositoryCell.create_with_value!(
item, column, cell_attributes[:value], current_user item, column, cell_attributes[:value], current_user
) )
end end
@ -49,17 +50,62 @@ module Api
status: :created status: :created
end end
def show
render jsonapi: @inventory_item,
serializer: InventoryItemSerializer,
include: :inventory_cells
end
def update
item_changed = false
if inventory_cells_params.present?
inventory_cells_params.each do |p|
p.require(%i(id attributes))
p.require(:attributes).require(:value)
end
@inventory_item.transaction do
inventory_cells_params.each do |cell_params|
cell = @inventory_item.repository_cells.find(cell_params[:id])
cell_value = cell_params.dig(:attributes, :value)
next unless cell.value.data_changed?(cell_value)
cell.value.update_data!(cell_value, current_user)
item_changed = true
end
end
end
@inventory_item.attributes = update_inventory_item_params
item_changed = true if @inventory_item.changed?
if item_changed
@inventory_item.last_modified_by = current_user
@inventory_item.save!
render json: @inventory_item,
serializer: InventoryItemSerializer,
include: :inventory_cells
else
render body: nil
end
end
def destroy
@inventory_item.destroy!
render body: nil
end
private private
def load_team def load_team
@team = Team.find(params.require(:team_id)) @team = Team.find(params.require(:team_id))
return render jsonapi: {}, status: :forbidden unless can_read_team?(@team) render jsonapi: {}, status: :forbidden unless can_read_team?(@team)
end end
def load_inventory def load_inventory
@inventory = @team.repositories.find(params.require(:inventory_id)) @inventory = @team.repositories.find(params.require(:inventory_id))
end end
def load_inventory_item
@inventory_item = @inventory.repository_rows.find(params[:id].to_i)
end
def check_manage_permissions def check_manage_permissions
unless can_manage_repository_rows?(@team) unless can_manage_repository_rows?(@team)
render body: nil, status: :forbidden render body: nil, status: :forbidden
@ -75,6 +121,14 @@ module Api
params.permit(data: { attributes: %i(name uid) })[:data] params.permit(data: { attributes: %i(name uid) })[:data]
end end
def update_inventory_item_params
unless params.require(:data).require(:id).to_i == params[:id].to_i
raise ActionController::BadRequest,
'Object ID mismatch in URL and request body'
end
inventory_item_params[:attributes]
end
# Partially implement sideposting draft # Partially implement sideposting draft
# https://github.com/json-api/json-api/pull/1197 # https://github.com/json-api/json-api/pull/1197
def inventory_cells_params def inventory_cells_params

View file

@ -1,10 +1,14 @@
# frozen_string_literal: true
module Api module Api
module V1 module V1
class TeamsController < BaseController class TeamsController < BaseController
before_action :load_team, only: :show before_action :load_team, only: :show
def index def index
teams = current_user.teams.page(params[:page]).per(params[:page_size]) teams = current_user.teams
.page(params.dig(:page, :number))
.per(params.dig(:page, :size))
render jsonapi: teams, each_serializer: TeamSerializer render jsonapi: teams, each_serializer: TeamSerializer
end end
@ -16,7 +20,7 @@ module Api
def load_team def load_team
@team = Team.find(params.require(:id)) @team = Team.find(params.require(:id))
return render jsonapi: {}, status: :forbidden unless can_read_team?(@team) render jsonapi: {}, status: :forbidden unless can_read_team?(@team)
end end
end end
end end

View file

@ -23,6 +23,19 @@ class RepositoryAssetValue < ApplicationRecord
asset.file_file_name asset.file_file_name
end end
def data_changed?(_new_data)
true
end
def update_data!(new_data, user)
file = Paperclip.io_adapters.for(new_data[:file_data])
file.original_filename = new_data[:file_name]
asset.file = file
asset.last_modified_by = user
self.last_modified_by = user
asset.save! && save!
end
def self.new_with_payload(payload, attributes) def self.new_with_payload(payload, attributes)
value = new(attributes) value = new(attributes)
team = value.repository_cell.repository_column.repository.team team = value.repository_cell.repository_column.repository.team

View file

@ -41,7 +41,7 @@ class RepositoryCell < ActiveRecord::Base
uniqueness: { scope: :repository_column }, uniqueness: { scope: :repository_column },
unless: :importing unless: :importing
def self.create_with_value(row, column, data, user) def self.create_with_value!(row, column, data, user)
cell = new(repository_row: row, repository_column: column) cell = new(repository_row: row, repository_column: column)
cell.transaction do cell.transaction do
value_klass = column.data_type.constantize value_klass = column.data_type.constantize

View file

@ -18,6 +18,16 @@ class RepositoryDateValue < ApplicationRecord
data data
end end
def data_changed?(new_data)
new_data != data
end
def update_data!(new_data, user)
self.data = new_data
self.last_modified_by = user
save!
end
def self.new_with_payload(payload, attributes) def self.new_with_payload(payload, attributes)
value = new(attributes) value = new(attributes)
value.data = payload value.data = payload

View file

@ -1,6 +1,5 @@
class RepositoryListValue < ApplicationRecord class RepositoryListValue < ApplicationRecord
belongs_to :repository_list_item, belongs_to :repository_list_item
optional: true
belongs_to :created_by, belongs_to :created_by,
foreign_key: :created_by_id, foreign_key: :created_by_id,
class_name: 'User' class_name: 'User'
@ -11,6 +10,12 @@ class RepositoryListValue < ApplicationRecord
accepts_nested_attributes_for :repository_cell accepts_nested_attributes_for :repository_cell
validates :repository_cell, presence: true validates :repository_cell, presence: true
validates_inclusion_of :repository_list_item,
in: (lambda do |list_value|
list_value.repository_cell
.repository_column
.repository_list_items
end)
def formatted def formatted
data.to_s data.to_s
@ -21,6 +26,16 @@ class RepositoryListValue < ApplicationRecord
repository_list_item.data repository_list_item.data
end end
def data_changed?(new_data)
new_data.to_i != repository_list_item_id
end
def update_data!(new_data, user)
self.repository_list_item_id = new_data.to_i
self.last_modified_by = user
save!
end
def self.new_with_payload(payload, attributes) def self.new_with_payload(payload, attributes)
value = new(attributes) value = new(attributes)
value.repository_list_item = value.repository_cell value.repository_list_item = value.repository_cell

View file

@ -19,6 +19,16 @@ class RepositoryTextValue < ApplicationRecord
data data
end end
def data_changed?(new_data)
new_data != data
end
def update_data!(new_data, user)
self.data = new_data
self.last_modified_by = user
save!
end
def self.new_with_payload(payload, attributes) def self.new_with_payload(payload, attributes)
value = new(attributes) value = new(attributes)
value.data = payload value.data = payload

View file

@ -48,11 +48,10 @@ module RepositoryImportParser
if @column_list_items_size >= Constants::REPOSITORY_LIST_ITEMS_PER_COLUMN if @column_list_items_size >= Constants::REPOSITORY_LIST_ITEMS_PER_COLUMN
return return
end end
item = RepositoryListItem.new(data: value, item = @column.repository_list_items.new(data: value,
created_by: @user, created_by: @user,
last_modified_by: @user, last_modified_by: @user,
repository_column: @column, repository: @repository)
repository: @repository)
if item.save if item.save
@column_list_items_size += 1 @column_list_items_size += 1
return item return item

View file

@ -10,6 +10,7 @@ Api.configure do |config|
end end
config.core_api_v1_preview = true if ENV['CORE_API_V1_PREVIEW'] config.core_api_v1_preview = true if ENV['CORE_API_V1_PREVIEW']
Paperclip::DataUriAdapter.register if ENV['CORE_API_V1_PREVIEW'] Paperclip::DataUriAdapter.register if ENV['CORE_API_V1_PREVIEW']
vars = ENV.select { |name, _| name =~ /^[[:alnum:]]*_AZURE_AD_APP_ID/ } vars = ENV.select { |name, _| name =~ /^[[:alnum:]]*_AZURE_AD_APP_ID/ }

View file

@ -546,7 +546,7 @@ Rails.application.routes.draw do
resources :inventories, only: %i(index show) do resources :inventories, only: %i(index show) do
get 'columns', to: 'inventory_columns#index' get 'columns', to: 'inventory_columns#index'
resources :inventory_items, resources :inventory_items,
only: %i(index create), only: %i(index create show update destroy),
path: 'items', path: 'items',
as: :items as: :items
end end

View file

@ -20,13 +20,13 @@ RSpec.describe RepositoryListValue, type: :model do
describe '#formatted' do describe '#formatted' do
let!(:repository) { create :repository } let!(:repository) { create :repository }
let!(:repository_column) { create :repository_column, name: 'My column' }
let!(:repository_column) do let!(:repository_column) do
create :repository_column, data_type: :RepositoryListValue create :repository_column, name: 'My column',
data_type: :RepositoryListValue
end end
let!(:repository_row) { create :repository_row, name: 'My row' } let!(:repository_row) { create :repository_row, name: 'My row' }
let!(:repository_list_value) do let!(:repository_list_value) do
create :repository_list_value, repository_cell_attributes: { build :repository_list_value, repository_cell_attributes: {
repository_column: repository_column, repository_column: repository_column,
repository_row: repository_row repository_row: repository_row
} }
@ -38,49 +38,20 @@ RSpec.describe RepositoryListValue, type: :model do
repository: repository, repository: repository,
repository_column: repository_column repository_column: repository_column
repository_list_value.repository_list_item = list_item repository_list_value.repository_list_item = list_item
repository_list_value.save repository_list_value.save!
expect(repository_list_value.reload.formatted).to eq 'my item' expect(repository_list_value.reload.formatted).to eq 'my item'
end end
it 'retuns only the the item related to the list' do
repository_row_two = create :repository_row, name: 'New row'
repository_list_value_two =
create :repository_list_value, repository_cell_attributes: {
repository_column: repository_column,
repository_row: repository_row_two
}
list_item = create :repository_list_item,
data: 'new item',
repository: repository,
repository_column: repository_column
repository_list_value.repository_list_item = list_item
expect(repository_list_value.reload.formatted).to_not eq 'my item'
expect(repository_list_value.formatted).to eq ''
end
it 'returns an empty string if no item selected' do
list_item = create :repository_list_item,
data: 'my item',
repository: repository,
repository_column: repository_column
expect(repository_list_value.reload.formatted).to eq ''
end
it 'returns an empty string if item does not exists' do
repository_list_value.repository_list_item = nil
expect(repository_list_value.reload.formatted).to eq ''
end
end end
describe '#data' do describe '#data' do
let!(:repository) { create :repository } let!(:repository) { create :repository }
let!(:repository_column) { create :repository_column, name: 'My column' }
let!(:repository_column) do let!(:repository_column) do
create :repository_column, data_type: :RepositoryListValue create :repository_column, name: 'My column',
data_type: :RepositoryListValue
end end
let!(:repository_row) { create :repository_row, name: 'My row' } let!(:repository_row) { create :repository_row, name: 'My row' }
let!(:repository_list_value) do let!(:repository_list_value) do
create :repository_list_value, repository_cell_attributes: { build :repository_list_value, repository_cell_attributes: {
repository_column: repository_column, repository_column: repository_column,
repository_row: repository_row repository_row: repository_row
} }
@ -92,36 +63,24 @@ RSpec.describe RepositoryListValue, type: :model do
repository: repository, repository: repository,
repository_column: repository_column repository_column: repository_column
repository_list_value.repository_list_item = list_item repository_list_value.repository_list_item = list_item
repository_list_value.save repository_list_value.save!
expect(repository_list_value.reload.data).to eq 'my item' expect(repository_list_value.reload.data).to eq 'my item'
end end
it 'retuns only the the item related to the list' do it 'retuns only the the item related to the list' do
repository_row_two = create :repository_row, name: 'New row' repository_column_two = create :repository_column, name: 'New column'
create :repository_list_value,
repository_cell_attributes: {
repository_column: repository_column,
repository_row: repository_row_two
}
list_item = create :repository_list_item, list_item = create :repository_list_item,
data: 'new item', data: 'new item',
repository: repository, repository: repository,
repository_column: repository_column repository_column: repository_column_two
repository_list_value.repository_list_item = list_item repository_list_value_two = build :repository_list_value,
expect(repository_list_value.reload.data).to_not eq 'my item' repository_cell_attributes: {
expect(repository_list_value.data).to be_nil repository_column: repository_column,
end repository_row: repository_row
}
it 'returns an empty string if no item selected' do repository_list_value_two.repository_list_item = list_item
create :repository_list_item, data: 'my item', saved = repository_list_value_two.save
repository: repository, expect(saved).to eq false
repository_column: repository_column
expect(repository_list_value.reload.data).to be_nil
end
it 'returns an empty string if item does not exists' do
repository_list_value.repository_list_item = nil
expect(repository_list_value.reload.data).to be_nil
end end
end end
end end