mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-03-03 11:13:06 +08:00
API: add endpoint for updating of stock [SCI-6549] (#3955)
* Add test for Stock repository cell [SCI-6549] * Create and update stock inventory cell [SCI-6549] * Fix hound errors [SCI-6549] * Fix ledger recording [SCI-6549] * Fix api endpoint [SCI-6549] * Fix hound [SCI-6549]
This commit is contained in:
parent
29cbf99498
commit
0ca9ae2ab9
4 changed files with 156 additions and 20 deletions
|
@ -44,19 +44,12 @@ class RepositoryStockValuesController < ApplicationController
|
|||
)
|
||||
end
|
||||
|
||||
render json: @repository_stock_vlaue
|
||||
render json: @repository_stock_value
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def update!
|
||||
@repository_stock_value.update_stock_with_ledger!(
|
||||
repository_stock_value_params[:amount],
|
||||
@repository,
|
||||
repository_stock_value_params[:comment].presence
|
||||
)
|
||||
@repository_stock_value.repository_stock_unit_item =
|
||||
@repository_column.repository_stock_unit_items.find(repository_stock_value_params[:unit_item_id])
|
||||
@repository_stock_value.update_data!(repository_stock_value_params, current_user)
|
||||
end
|
||||
|
||||
|
@ -66,9 +59,7 @@ class RepositoryStockValuesController < ApplicationController
|
|||
repository_stock_value_params,
|
||||
repository_cell: repository_cell,
|
||||
created_by: current_user,
|
||||
last_modified_by: current_user,
|
||||
repository_stock_unit_item: @repository_column.repository_stock_unit_items
|
||||
.find(repository_stock_value_params[:unit_item_id])
|
||||
last_modified_by: current_user
|
||||
)
|
||||
@repository_stock_value.save!
|
||||
@repository_stock_value.update_stock_with_ledger!(
|
||||
|
|
|
@ -34,6 +34,8 @@ class RepositoryCell < ApplicationRecord
|
|||
|
||||
has_many :hidden_repository_cell_reminders, dependent: :destroy
|
||||
|
||||
before_destroy :prevent_stock_cell_destroy
|
||||
|
||||
validates :repository_column,
|
||||
inclusion: { in: (lambda do |repository_cell|
|
||||
repository_cell.repository_row&.repository&.repository_columns || []
|
||||
|
@ -58,6 +60,12 @@ class RepositoryCell < ApplicationRecord
|
|||
last_modified_by: user)
|
||||
cell.value = value
|
||||
value.save!
|
||||
|
||||
if column.data_type == 'RepositoryStockValue'
|
||||
value.update_stock_with_ledger!(value.amount,
|
||||
value.repository_cell.repository_column.repository,
|
||||
'')
|
||||
end
|
||||
end
|
||||
cell
|
||||
end
|
||||
|
@ -84,4 +92,8 @@ class RepositoryCell < ApplicationRecord
|
|||
errors.add(:value_type, 'must match column data type')
|
||||
end
|
||||
end
|
||||
|
||||
def prevent_stock_cell_destroy
|
||||
raise NotImplementedError if value.class.name == 'RepositoryStockValue'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -83,14 +83,24 @@ class RepositoryStockValue < ApplicationRecord
|
|||
end
|
||||
end
|
||||
|
||||
def data_changed?(new_data)
|
||||
BigDecimal(new_data.to_s) != data
|
||||
def data_different?(new_data)
|
||||
BigDecimal(new_data[:amount].to_s) != amount ||
|
||||
(new_data[:unit_item_id].present? && new_data[:unit_item_id] != repository_stock_unit_item.id)
|
||||
end
|
||||
|
||||
def update_data!(new_data, user)
|
||||
self.amount = BigDecimal(new_data[:amount].to_s)
|
||||
self.low_stock_threshold = new_data[:low_stock_threshold]
|
||||
self.low_stock_threshold = new_data[:low_stock_threshold] if new_data[:low_stock_threshold].present?
|
||||
self.repository_stock_unit_item = repository_cell
|
||||
.repository_column
|
||||
.repository_stock_unit_items
|
||||
.find(new_data[:unit_item_id])
|
||||
self.last_modified_by = user
|
||||
|
||||
update_stock_with_ledger!(new_data[:amount],
|
||||
repository_cell.repository_column.repository,
|
||||
new_data[:comment].presence)
|
||||
|
||||
self.amount = BigDecimal(new_data[:amount].to_s)
|
||||
save!
|
||||
end
|
||||
|
||||
|
@ -116,10 +126,18 @@ class RepositoryStockValue < ApplicationRecord
|
|||
end
|
||||
|
||||
def self.new_with_payload(payload, attributes)
|
||||
value = new(attributes)
|
||||
value.amount = payload[:amount]
|
||||
value.low_stock_threshold = payload[:low_stock_threshold]
|
||||
value
|
||||
if payload[:amount].present?
|
||||
value = new(attributes)
|
||||
value.amount = payload[:amount]
|
||||
value.low_stock_threshold = payload[:low_stock_threshold]
|
||||
value.repository_stock_unit_item = value.repository_cell
|
||||
.repository_column
|
||||
.repository_stock_unit_items
|
||||
.find(payload['unit_item_id'])
|
||||
value
|
||||
else
|
||||
raise ActiveRecord::RecordInvalid, 'Missing amount value'
|
||||
end
|
||||
end
|
||||
|
||||
def self.import_from_text(text, attributes, _options = {})
|
||||
|
|
|
@ -42,6 +42,11 @@ RSpec.describe 'Api::V1::InventoryCellsController', type: :request do
|
|||
@date_time_range_column = create(:repository_column,
|
||||
repository: @valid_inventory, data_type: :RepositoryDateTimeRangeValue)
|
||||
@number_column = create(:repository_column, repository: @valid_inventory, data_type: :RepositoryNumberValue)
|
||||
@stock_column = create(:repository_column, name: Faker::Name.unique.name,
|
||||
data_type: :RepositoryStockValue, repository: @valid_inventory)
|
||||
@repository_stock_unit_item = create( :repository_stock_unit_item, created_by: @user,
|
||||
last_modified_by: @user,
|
||||
repository_column: @stock_column)
|
||||
|
||||
@valid_item = create(:repository_row, repository: @valid_inventory)
|
||||
|
||||
|
@ -80,6 +85,10 @@ RSpec.describe 'Api::V1::InventoryCellsController', type: :request do
|
|||
create(:repository_number_value,
|
||||
data: 1234.5678,
|
||||
repository_cell_attributes: { repository_row: @valid_item, repository_column: @number_column })
|
||||
create(:repository_stock_value,
|
||||
amount: 10,
|
||||
repository_stock_unit_item: @repository_stock_unit_item,
|
||||
repository_cell_attributes: { repository_row: @valid_item, repository_column: @stock_column })
|
||||
|
||||
@valid_headers =
|
||||
{ 'Authorization': 'Bearer ' + generate_token(@user.id),
|
||||
|
@ -214,6 +223,18 @@ RSpec.describe 'Api::V1::InventoryCellsController', type: :request do
|
|||
}
|
||||
}
|
||||
}
|
||||
@valid_stock_body = {
|
||||
data: {
|
||||
type: 'inventory_cells',
|
||||
attributes: {
|
||||
column_id: @stock_column.id,
|
||||
value: {
|
||||
amount: 19,
|
||||
unit_item_id: @repository_stock_unit_item.id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@update_text_body = {
|
||||
data: {
|
||||
id: @valid_item.repository_cells.where(repository_column: @text_column).first.id,
|
||||
|
@ -356,6 +377,19 @@ RSpec.describe 'Api::V1::InventoryCellsController', type: :request do
|
|||
}
|
||||
}
|
||||
}
|
||||
@update_stock_body = {
|
||||
data: {
|
||||
id: @valid_item.repository_cells.where(repository_column: @stock_column).first.id,
|
||||
type: 'inventory_cells',
|
||||
attributes: {
|
||||
column_id: @stock_column.id,
|
||||
value: {
|
||||
amount: 20,
|
||||
unit_item_id: @repository_stock_unit_item.id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
describe 'GET inventory_cells, #index' do
|
||||
|
@ -696,6 +730,55 @@ RSpec.describe 'Api::V1::InventoryCellsController', type: :request do
|
|||
)
|
||||
end
|
||||
|
||||
it 'Response with correct inventory cell, stock cell' do
|
||||
hash_body = nil
|
||||
empty_item = create(:repository_row, repository: @valid_inventory)
|
||||
post api_v1_team_inventory_item_cells_path(
|
||||
team_id: @team.id,
|
||||
inventory_id: @valid_inventory.id,
|
||||
item_id: empty_item.id
|
||||
), params: @valid_stock_body.to_json, headers: @valid_headers
|
||||
expect(response).to have_http_status 201
|
||||
expect { hash_body = json }.not_to raise_exception
|
||||
expect(hash_body[:data]).to match(
|
||||
JSON.parse(
|
||||
ActiveModelSerializers::SerializableResource
|
||||
.new(RepositoryCell.last, serializer: Api::V1::InventoryCellSerializer)
|
||||
.to_json
|
||||
)['data']
|
||||
)
|
||||
end
|
||||
|
||||
it 'Response with inventory cell, stock cell, missing stock unit' do
|
||||
hash_body = nil
|
||||
empty_item = create(:repository_row, repository: @valid_inventory)
|
||||
invalid_file_body = @valid_stock_body.deep_dup
|
||||
invalid_file_body[:data][:attributes][:value].delete(:unit_item_id)
|
||||
post api_v1_team_inventory_item_cells_path(
|
||||
team_id: @team.id,
|
||||
inventory_id: @valid_inventory.id,
|
||||
item_id: empty_item.id
|
||||
), params: invalid_file_body.to_json, headers: @valid_headers
|
||||
expect(response).to have_http_status 404
|
||||
expect { hash_body = json }.not_to raise_exception
|
||||
expect(hash_body['errors'][0]).to include('status': 404)
|
||||
end
|
||||
|
||||
it 'Response with inventory cell, stock cell, missing amount' do
|
||||
hash_body = nil
|
||||
empty_item = create(:repository_row, repository: @valid_inventory)
|
||||
invalid_file_body = @valid_stock_body.deep_dup
|
||||
invalid_file_body[:data][:attributes][:value].delete(:amount)
|
||||
post api_v1_team_inventory_item_cells_path(
|
||||
team_id: @team.id,
|
||||
inventory_id: @valid_inventory.id,
|
||||
item_id: empty_item.id
|
||||
), params: invalid_file_body.to_json, headers: @valid_headers
|
||||
expect(response).to have_http_status 400
|
||||
expect { hash_body = json }.not_to raise_exception
|
||||
expect(hash_body['errors'][0]).to include('status': 400)
|
||||
end
|
||||
|
||||
it 'When invalid request, payload mismatches column type' do
|
||||
hash_body = nil
|
||||
invalid_file_body = @valid_file_body.dup
|
||||
|
@ -1010,6 +1093,26 @@ RSpec.describe 'Api::V1::InventoryCellsController', type: :request do
|
|||
)
|
||||
end
|
||||
|
||||
it 'Response with correct inventory cell, stock cell' do
|
||||
hash_body = nil
|
||||
patch api_v1_team_inventory_item_cell_path(
|
||||
team_id: @team.id,
|
||||
inventory_id: @valid_inventory.id,
|
||||
item_id: @valid_item.id,
|
||||
id: @valid_item.repository_cells.where(repository_column: @stock_column).first.id
|
||||
), params: @update_stock_body.to_json, headers: @valid_headers
|
||||
expect(response).to have_http_status 200
|
||||
expect { hash_body = json }.not_to raise_exception
|
||||
expect(hash_body[:data]).to match(
|
||||
JSON.parse(
|
||||
ActiveModelSerializers::SerializableResource
|
||||
.new(@valid_item.repository_cells.where(repository_column: @stock_column).first,
|
||||
serializer: Api::V1::InventoryCellSerializer)
|
||||
.to_json
|
||||
)['data']
|
||||
)
|
||||
end
|
||||
|
||||
it 'When invalid request, payload mismatches column type' do
|
||||
hash_body = nil
|
||||
invalid_file_body = @valid_file_body.dup
|
||||
|
@ -1067,7 +1170,7 @@ RSpec.describe 'Api::V1::InventoryCellsController', type: :request do
|
|||
|
||||
describe 'DELETE inventory_cells, #destroy' do
|
||||
it 'Destroys inventory cell' do
|
||||
deleted_id = @valid_item.repository_cells.last.id
|
||||
deleted_id = @valid_item.repository_cells.where(repository_column: @number_column).first.id
|
||||
delete api_v1_team_inventory_item_cell_path(
|
||||
id: deleted_id,
|
||||
team_id: @team.id,
|
||||
|
@ -1078,6 +1181,18 @@ RSpec.describe 'Api::V1::InventoryCellsController', type: :request do
|
|||
expect(RepositoryCell.where(id: deleted_id)).to_not exist
|
||||
end
|
||||
|
||||
it 'Destroys stock inventory cell' do
|
||||
deleted_id = @valid_item.repository_cells.where(repository_column: @stock_column).first.id
|
||||
delete api_v1_team_inventory_item_cell_path(
|
||||
id: deleted_id,
|
||||
team_id: @team.id,
|
||||
inventory_id: @valid_inventory.id,
|
||||
item_id: @valid_item.id
|
||||
), headers: @valid_headers
|
||||
expect(response).to have_http_status(400)
|
||||
expect(RepositoryCell.where(id: deleted_id)).to exist
|
||||
end
|
||||
|
||||
it 'Invalid request, non existing inventory item' do
|
||||
deleted_id = RepositoryCell.last.id + 1
|
||||
delete api_v1_team_inventory_item_cell_path(
|
||||
|
|
Loading…
Reference in a new issue