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:
ajugo 2022-04-08 11:30:44 +02:00 committed by GitHub
parent 29cbf99498
commit 0ca9ae2ab9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 156 additions and 20 deletions

View file

@ -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!(

View file

@ -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

View file

@ -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)
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 = {})

View file

@ -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(