mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2024-12-29 11:45:18 +08:00
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:
commit
a825f1c2ec
12 changed files with 142 additions and 76 deletions
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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/ }
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue