mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2024-09-20 14:45:56 +08:00
Task stock consumption modal[SCI-6444][SCI-6445] (#3798)
Add main logic for consumption on task [SCI-6444] Co-authored-by: Anton <anton@scinote.net>
This commit is contained in:
parent
371d5f0636
commit
2c88843924
|
@ -191,6 +191,10 @@ var MyModuleRepositories = (function() {
|
|||
});
|
||||
}
|
||||
|
||||
function reloadSimpleTable() {
|
||||
SIMPLE_TABLE.ajax.reload(null, false);
|
||||
}
|
||||
|
||||
function renderFullViewTable(tableContainer, options = {}) {
|
||||
if (FULL_VIEW_TABLE) FULL_VIEW_TABLE.destroy();
|
||||
SELECTED_ROWS = {};
|
||||
|
@ -741,6 +745,9 @@ var MyModuleRepositories = (function() {
|
|||
initRepoistoryAssignView();
|
||||
initSelectAllCheckbox();
|
||||
initExportAssignedRows();
|
||||
},
|
||||
reloadSimpletable: () => {
|
||||
reloadSimpleTable();
|
||||
}
|
||||
};
|
||||
}());
|
||||
|
|
68
app/assets/javascripts/my_modules/stock.js
Normal file
68
app/assets/javascripts/my_modules/stock.js
Normal file
|
@ -0,0 +1,68 @@
|
|||
/* global SmartAnnotation I18n MyModuleRepositories */
|
||||
var MyModuleStockConsumption = (function() {
|
||||
const CONSUMPTION_MODAL = '#consumeRepositoryStockValueModal';
|
||||
const WARNING_MODAL = '#consumeRepositoryStockValueModalWarning';
|
||||
|
||||
function initManageAction() {
|
||||
$('.task-section').on('click', '.manage-repository-consumed-stock-value-link', function(e) {
|
||||
e.preventDefault();
|
||||
$.ajax({
|
||||
url: $(this).attr('href'),
|
||||
type: 'GET',
|
||||
dataType: 'json',
|
||||
success: (result) => {
|
||||
var $manageModal = $(CONSUMPTION_MODAL);
|
||||
$manageModal.find('.modal-content').html(result.html);
|
||||
$manageModal.modal('show');
|
||||
SmartAnnotation.init($(CONSUMPTION_MODAL + ' #comment')[0]);
|
||||
|
||||
$('#stock_consumption').on('change', function() {
|
||||
let initialValue = parseFloat($(this).data('initial-value'));
|
||||
let initialStock = parseFloat($(this).data('initial-stock'));
|
||||
let finalValue = initialValue - ($(this).val() || 0) + initialStock;
|
||||
$('.stock-final-container .value').text(finalValue);
|
||||
$('.stock-final-container').toggleClass('error', finalValue <= 0);
|
||||
$('.update-consumption-button').attr('disabled', $(this).val() === '');
|
||||
});
|
||||
|
||||
$(CONSUMPTION_MODAL + ' form').on('ajax:success', function() {
|
||||
MyModuleRepositories.reloadSimpletable();
|
||||
$manageModal.modal('hide');
|
||||
$(WARNING_MODAL).modal('hide');
|
||||
});
|
||||
|
||||
$('.update-consumption-button').on('click', function(event, skipValidation) {
|
||||
if (parseFloat($('.stock-final-container .value').text()) < 0 && !skipValidation) {
|
||||
event.preventDefault();
|
||||
$manageModal.modal('hide');
|
||||
$(WARNING_MODAL).modal('show');
|
||||
let units = $(CONSUMPTION_MODAL).find('.consumption-container .units').text();
|
||||
let value = $('#stock_consumption').val();
|
||||
$(WARNING_MODAL).find('.modal-body p').text(
|
||||
I18n.t('my_modules.repository.stock_warning_modal.description', { value: `${value} ${units}` })
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function initWarningModal() {
|
||||
$(WARNING_MODAL).on('click', '.cancel-consumption', function() {
|
||||
$(WARNING_MODAL).modal('hide');
|
||||
$(CONSUMPTION_MODAL).modal('show');
|
||||
}).on('click', '.confirm-consumption-button', function() {
|
||||
$('.update-consumption-button').trigger('click', [true]);
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
init: () => {
|
||||
initManageAction();
|
||||
initWarningModal();
|
||||
}
|
||||
};
|
||||
}());
|
||||
|
||||
MyModuleStockConsumption.init();
|
|
@ -210,16 +210,16 @@ $.fn.dataTable.render.RepositoryConsumedStockValue = function(data) {
|
|||
let canManage = $('.repository-table').data('stock-consumption-editable');
|
||||
if (data && data.value.consumed_stock_formatted) {
|
||||
if (canManage) {
|
||||
return `<a class="manage-repository-stock-value-link stock-value-view-render">
|
||||
${data.value.consumed_stock_formatted}
|
||||
return `<a href="${data.updateStockConsumptionUrl}" class="manage-repository-consumed-stock-value-link stock-value-view-render">
|
||||
${data.value.consumed_stock_formatted} ${data.value.unit}
|
||||
</a>`;
|
||||
}
|
||||
return `<span class="stock-value-view-render">
|
||||
${data.value.consumed_stock_formatted}
|
||||
${data.value.consumed_stock_formatted} ${data.value.unit}
|
||||
</span>`;
|
||||
}
|
||||
if (canManage && data && data.stock_present) {
|
||||
return `<a class="manage-repository-consumed-stock-value-link">
|
||||
return `<a href="${data.updateStockConsumptionUrl}" class="manage-repository-consumed-stock-value-link">
|
||||
<i class="fas fa-vial"></i>
|
||||
${I18n.t('libraries.manange_modal_column.stock_type.add_stock_consumption')}
|
||||
</a>`;
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
|
||||
#consumeRepositoryStockValueModal {
|
||||
.consumption-container {
|
||||
align-items: center;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
|
||||
.units {
|
||||
margin: 1.25em 0 0 .5em;
|
||||
}
|
||||
}
|
||||
|
||||
.comments-container {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
}
|
|
@ -1,7 +1,8 @@
|
|||
// scss-lint:disable SelectorDepth
|
||||
// scss-lint:disable NestingDepth
|
||||
|
||||
.repository-stock-modal {
|
||||
.repository-stock-modal,
|
||||
#consumeRepositoryStockValueModal {
|
||||
.stock-update-view {
|
||||
align-items: center;
|
||||
display: grid;
|
||||
|
@ -28,6 +29,12 @@
|
|||
.units {
|
||||
@include font-small;
|
||||
}
|
||||
|
||||
&.error {
|
||||
.value {
|
||||
color: $brand-danger;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.stock-arrow {
|
||||
|
|
|
@ -5,8 +5,9 @@ class MyModuleRepositoriesController < ApplicationController
|
|||
|
||||
before_action :load_my_module
|
||||
before_action :load_repository, except: %i(repositories_dropdown_list repositories_list_html)
|
||||
before_action :check_my_module_view_permissions, except: :update
|
||||
before_action :check_my_module_view_permissions, except: %i(update consume_modal update_consumption)
|
||||
before_action :check_repository_view_permissions, except: %i(repositories_dropdown_list repositories_list_html)
|
||||
before_action :check_repository_row_consumption_permissions, only: %i(consume_modal update_consumption)
|
||||
before_action :check_assign_repository_records_permissions, only: :update
|
||||
|
||||
def index_dt
|
||||
|
@ -140,6 +141,31 @@ class MyModuleRepositoriesController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def consume_modal
|
||||
@repository_row = @repository.repository_rows.find(params[:row_id])
|
||||
@module_repository_row = @my_module.my_module_repository_rows.find_by(repository_row: @repository_row)
|
||||
@stock_value = @module_repository_row.repository_row.repository_stock_value
|
||||
render json: {
|
||||
html: render_to_string(
|
||||
partial: 'my_modules/repositories/consume_stock_modal_content.html.erb'
|
||||
)
|
||||
}
|
||||
end
|
||||
|
||||
def update_consumption
|
||||
module_repository_row = @my_module.my_module_repository_rows.find_by(id: params[:module_row_id])
|
||||
module_repository_row.with_lock do
|
||||
module_repository_row.assign_attributes(
|
||||
stock_consumption: params[:stock_consumption],
|
||||
last_modified_by: current_user,
|
||||
comment: params[:comment]
|
||||
)
|
||||
module_repository_row.save!
|
||||
end
|
||||
|
||||
render json: {}, status: :ok
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def load_my_module
|
||||
|
@ -164,6 +190,10 @@ class MyModuleRepositoriesController < ApplicationController
|
|||
render_403 unless can_assign_my_module_repository_rows?(@my_module)
|
||||
end
|
||||
|
||||
def check_repository_row_consumption_permissions
|
||||
render_403 unless can_update_my_module_stock_consumption?(@my_module)
|
||||
end
|
||||
|
||||
def update_flash_message(service)
|
||||
assigned_count = service.assigned_rows_count
|
||||
unassigned_count = service.unassigned_rows_count
|
||||
|
|
|
@ -50,7 +50,7 @@ module RepositoryDatatableHelper
|
|||
end
|
||||
end
|
||||
|
||||
def prepare_simple_view_row_columns(repository_rows)
|
||||
def prepare_simple_view_row_columns(repository_rows, my_module)
|
||||
repository_rows.map do |record|
|
||||
row = {
|
||||
DT_RowId: record.id,
|
||||
|
@ -66,8 +66,14 @@ module RepositoryDatatableHelper
|
|||
end
|
||||
row['2'] = {
|
||||
stock_present: record.repository_stock_cell.present?,
|
||||
updateStockConsumptionUrl: Rails.application.routes.url_helpers.consume_modal_my_module_repository_path(
|
||||
my_module,
|
||||
record.repository,
|
||||
row_id: record.id
|
||||
),
|
||||
value: {
|
||||
consumed_stock_formatted: record.consumed_stock
|
||||
consumed_stock_formatted: record.consumed_stock,
|
||||
unit: record.repository_stock_value.repository_stock_unit_item&.data
|
||||
}
|
||||
}
|
||||
end
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
class MyModuleRepositoryRow < ApplicationRecord
|
||||
attr_accessor :last_modified_by
|
||||
attr_accessor :comment
|
||||
|
||||
belongs_to :assigned_by,
|
||||
foreign_key: 'assigned_by_id',
|
||||
class_name: 'User',
|
||||
|
@ -13,17 +16,28 @@ class MyModuleRepositoryRow < ApplicationRecord
|
|||
|
||||
around_save :deduct_stock_balance, if: :stock_consumption_changed?
|
||||
|
||||
before_save :nulify_stock_consumption, if: :stock_consumption_changed?
|
||||
|
||||
private
|
||||
|
||||
def nulify_stock_consumption
|
||||
self.stock_consumption = nil if stock_consumption.zero?
|
||||
end
|
||||
|
||||
def deduct_stock_balance
|
||||
stock_value = repository_row.repository_stock_value
|
||||
delta = stock_consumption_was.to_d - stock_consumption.to_d
|
||||
lock!
|
||||
delta = stock_consumption.to_d - stock_consumption_was.to_d
|
||||
stock_value.lock!
|
||||
stock_value.amount = stock_value.amount - delta
|
||||
yield
|
||||
stock_value.save!
|
||||
stock_value.repository_ledger_records.create!(user: last_modified_by, amount: delta, balance: stock_value.amount)
|
||||
stock_value.repository_ledger_records.create!(
|
||||
reference: self,
|
||||
user: last_modified_by,
|
||||
amount: delta,
|
||||
balance: stock_value.amount,
|
||||
comment: comment
|
||||
)
|
||||
save!
|
||||
end
|
||||
end
|
||||
|
|
|
@ -34,7 +34,8 @@ class RepositoryRow < ApplicationRecord
|
|||
repository_date: 'RepositoryDateValue',
|
||||
repository_date_time_range: 'RepositoryDateTimeRangeValue',
|
||||
repository_time_range: 'RepositoryTimeRangeValue',
|
||||
repository_date_range: 'RepositoryDateRangeValue'
|
||||
repository_date_range: 'RepositoryDateRangeValue',
|
||||
repository_stock: 'RepositoryStockValue'
|
||||
}.each do |relation, class_name|
|
||||
has_many "#{relation}_cells".to_sym, -> { where(value_type: class_name) }, class_name: 'RepositoryCell',
|
||||
inverse_of: :repository_row
|
||||
|
|
|
@ -157,6 +157,8 @@
|
|||
<!-- Delete file modal -->
|
||||
<%= render partial: 'assets/asset_delete_modal.html.erb' %>
|
||||
|
||||
<%= render partial: 'my_modules/repositories/consume_stock_modal.html.erb'%>
|
||||
|
||||
<%= stylesheet_link_tag 'datatables' %>
|
||||
<%= javascript_include_tag("my_modules/protocols") %>
|
||||
<%= javascript_include_tag("my_modules/status_flow") %>
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
<div class="modal small"
|
||||
id="consumeRepositoryStockValueModal"
|
||||
tabindex="-1"
|
||||
role="dialog"
|
||||
aria-labelledby="consumeRepositoryStockValueLabel">
|
||||
<div class="modal-dialog modal-sm" role="document">
|
||||
<div class="modal-content">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal small"
|
||||
id="consumeRepositoryStockValueModalWarning"
|
||||
tabindex="-1"
|
||||
role="dialog">
|
||||
<div class="modal-dialog modal-sm" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="<%= t('general.close') %>">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<h4 class="modal-title">
|
||||
<%= t('my_modules.repository.stock_warning_modal.title') %>
|
||||
</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p></p>
|
||||
<div class="modal-footer">
|
||||
<button type="button"
|
||||
id="cancel"
|
||||
class="btn btn-default cancel-consumption"><%=t('general.cancel') %></button>
|
||||
<%= submit_tag t('my_modules.repository.stock_warning_modal.consume_anyway'), class: "btn btn-primary confirm-consumption-button"%>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<%= javascript_include_tag 'my_modules/stock' %>
|
|
@ -0,0 +1,50 @@
|
|||
<%= form_with url: update_consumption_my_module_repository_path(@my_module, @repository, module_row_id: @module_repository_row), method: :post, remote: true do |f| %>
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="<%= t('general.close') %>">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<h4 class="modal-title">
|
||||
<%= t('my_modules.repository.stock_modal.title', name: @repository_row.name)%>
|
||||
</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p><%= t('my_modules.repository.stock_modal.description') %></p>
|
||||
<div class="consumption-container">
|
||||
<div class="sci-input-container">
|
||||
<%= f.label :stock_consumption, t('my_modules.repository.stock_modal.amount') %>
|
||||
<%= f.number_field :stock_consumption, value: @module_repository_row.stock_consumption , placeholder: t('my_modules.repository.stock_modal.consumed') , class: 'sci-input-field', data: {initial_value: (@module_repository_row.stock_consumption || 0), initial_stock: @stock_value.amount } %>
|
||||
</div>
|
||||
<span class="units"> <%= @stock_value.repository_stock_unit_item&.data %></span>
|
||||
</div>
|
||||
<div class="sci-input-container comments-container">
|
||||
<%= f.label :comment, t('my_modules.repository.stock_modal.comment') %>
|
||||
<%= f.text_field :comment, placeholder: t('my_modules.repository.stock_modal.enter_comment') , class: 'sci-input-field' %>
|
||||
</div>
|
||||
<div class="row mt-3">
|
||||
<div class="col-sm-12">
|
||||
<div class="stock-update-view">
|
||||
<div class="stock-initial-container">
|
||||
<span class="subtitle"><%= t('repository_stock_values.manage_modal.current_stock') %></span>
|
||||
<span class="value"><%= @stock_value.amount %></span>
|
||||
<span class="units"><%= @stock_value.repository_stock_unit_item&.data %></span>
|
||||
</div>
|
||||
<div class="stock-arrow">
|
||||
<i class="fas fa-arrow-right"></i>
|
||||
</div>
|
||||
<div class="stock-final-container">
|
||||
<span class="subtitle"><%= t('repository_stock_values.manage_modal.new_stock') %></span>
|
||||
<span class="value">-</span>
|
||||
<span class="units"><%= @stock_value.repository_stock_unit_item&.data %></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button"
|
||||
id="cancel"
|
||||
class="btn btn-default"
|
||||
data-dismiss="modal"><%=t('general.cancel') %></button>
|
||||
<%= submit_tag t('general.save'), class: "btn btn-primary update-consumption-button", disabled: @module_repository_row.stock_consumption.nil? %>
|
||||
</div>
|
||||
<% end %>
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
json.draw @draw
|
||||
json.data do
|
||||
json.array! prepare_simple_view_row_columns(@repository_rows)
|
||||
json.array! prepare_simple_view_row_columns(@repository_rows, @my_module)
|
||||
end
|
||||
json.recordsFiltered @repository_rows.first ? @repository_rows.first.filtered_count : 0
|
||||
json.recordsTotal @all_rows_count
|
||||
|
|
|
@ -33,6 +33,7 @@ Rails.application.config.assets.precompile += %w(my_modules/repositories.js)
|
|||
Rails.application.config.assets.precompile += %w(my_modules/status_flow.js)
|
||||
Rails.application.config.assets.precompile += %w(my_modules/protocols/protocol_status_bar.js)
|
||||
Rails.application.config.assets.precompile += %w(my_modules/results.js)
|
||||
Rails.application.config.assets.precompile += %w(my_modules/stock.js)
|
||||
Rails.application.config.assets.precompile += %w(my_modules/archived.js)
|
||||
Rails.application.config.assets.precompile += %w(my_modules/pwa_mobile_app.js)
|
||||
Rails.application.config.assets.precompile += %w(assets/wopi/create_wopi_file.js)
|
||||
|
|
|
@ -995,6 +995,17 @@ en:
|
|||
set_default_button: 'Set as default view'
|
||||
created_by: 'by %{full_name}'
|
||||
provisioning: 'Provisioning'
|
||||
stock_modal:
|
||||
title: 'Consume %{name}'
|
||||
description: 'Enter the total amount consumed in this task.'
|
||||
amount: 'Amount'
|
||||
consumed: 'Consumed'
|
||||
comment: 'Comment (optional)'
|
||||
enter_comment: 'Enter a comment'
|
||||
stock_warning_modal:
|
||||
title: 'Out of stock!'
|
||||
description: 'By consuming %{value} you will use more than you currently have in stock. This will result in negative stock.'
|
||||
consume_anyway: 'Consume anyway'
|
||||
flash:
|
||||
assign_to_task_html: "Successfully assigned <strong>%{assigned_items}</strong> item(s) to the task."
|
||||
assign_to_task_and_downstream_html: "Successfully assigned <strong>%{assigned_items}</strong> item(s) to the task and downstream tasks."
|
||||
|
|
|
@ -388,6 +388,8 @@ Rails.application.routes.draw do
|
|||
post :export_repository
|
||||
get :assign_repository_records_modal, as: :assign_modal
|
||||
get :update_repository_records_modal, as: :update_modal
|
||||
get :consume_modal
|
||||
post :update_consumption
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue