mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-09-30 17:04:31 +08:00
(dev) POC for inventory import preview [SCI-10489]
This commit is contained in:
parent
8ecef3719c
commit
2b92fda906
11 changed files with 104 additions and 49 deletions
|
@ -5,10 +5,4 @@ class RepositoryChecklistItemsValue < ApplicationRecord
|
||||||
belongs_to :repository_checklist_value, inverse_of: :repository_checklist_items_values
|
belongs_to :repository_checklist_value, inverse_of: :repository_checklist_items_values
|
||||||
|
|
||||||
validates :repository_checklist_item, :repository_checklist_value, presence: true
|
validates :repository_checklist_item, :repository_checklist_value, presence: true
|
||||||
|
|
||||||
after_destroy :destroy_empty_value
|
|
||||||
|
|
||||||
def destroy_empty_value
|
|
||||||
repository_checklist_value.destroy! if repository_checklist_value.repository_checklist_items_values.blank?
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -70,17 +70,19 @@ class RepositoryChecklistValue < ApplicationRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_data!(new_data, user)
|
# TODO: after ticket for tracking changes on checklist items
|
||||||
|
def update_data!(new_data, user, preview: false)
|
||||||
item_ids = new_data.is_a?(String) ? JSON.parse(new_data) : new_data
|
item_ids = new_data.is_a?(String) ? JSON.parse(new_data) : new_data
|
||||||
|
|
||||||
return destroy! if item_ids.blank?
|
return destroy! if item_ids.blank?
|
||||||
|
|
||||||
# update!(repository_checklist_items: repository_cell.repository_column.repository_checklist_items.where(id: item_ids), last_modified_by: user)
|
self.last_modified_by = user
|
||||||
|
|
||||||
self.repository_checklist_items = repository_cell.repository_column
|
self.repository_checklist_items = repository_cell.repository_column
|
||||||
.repository_checklist_items
|
.repository_checklist_items
|
||||||
.where(id: item_ids)
|
.where(id: item_ids)
|
||||||
self.last_modified_by = user
|
|
||||||
save!
|
preview ? validate : save!
|
||||||
end
|
end
|
||||||
|
|
||||||
def snapshot!(cell_snapshot)
|
def snapshot!(cell_snapshot)
|
||||||
|
|
|
@ -19,10 +19,15 @@ class RepositoryDateTimeValueBase < ApplicationRecord
|
||||||
I18n.l(data, format: format)
|
I18n.l(data, format: format)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_data!(new_data, user)
|
def update_data!(new_data, user, preview: false)
|
||||||
self.data = Time.zone.parse(new_data)
|
self.data = if new_data.is_a?(String)
|
||||||
|
Time.zone.parse(new_data)
|
||||||
|
else
|
||||||
|
new_data
|
||||||
|
end
|
||||||
|
|
||||||
self.last_modified_by = user
|
self.last_modified_by = user
|
||||||
save!
|
preview ? validate : save!
|
||||||
end
|
end
|
||||||
|
|
||||||
def snapshot!(cell_snapshot)
|
def snapshot!(cell_snapshot)
|
||||||
|
|
|
@ -56,10 +56,15 @@ class RepositoryDateValue < RepositoryDateTimeValueBase
|
||||||
value
|
value
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_data!(new_data, user)
|
def update_data!(new_data, user, preview: false)
|
||||||
self.data = Date.parse(new_data)
|
self.data = if new_data.is_a?(String)
|
||||||
|
Date.parse(new_data)
|
||||||
|
else
|
||||||
|
new_data.to_time.utc
|
||||||
|
end
|
||||||
|
|
||||||
self.last_modified_by = user
|
self.last_modified_by = user
|
||||||
save!
|
preview ? validate : save!
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.import_from_text(text, attributes, options = {})
|
def self.import_from_text(text, attributes, options = {})
|
||||||
|
|
|
@ -57,10 +57,10 @@ class RepositoryListValue < ApplicationRecord
|
||||||
new_data.to_i != repository_list_item_id
|
new_data.to_i != repository_list_item_id
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_data!(new_data, user)
|
def update_data!(new_data, user, preview: false)
|
||||||
self.repository_list_item_id = new_data.to_i
|
self.repository_list_item_id = new_data.to_i
|
||||||
self.last_modified_by = user
|
self.last_modified_by = user
|
||||||
save!
|
preview ? validate : save!
|
||||||
end
|
end
|
||||||
|
|
||||||
def snapshot!(cell_snapshot)
|
def snapshot!(cell_snapshot)
|
||||||
|
|
|
@ -49,10 +49,10 @@ class RepositoryNumberValue < ApplicationRecord
|
||||||
BigDecimal(new_data.to_s) != data
|
BigDecimal(new_data.to_s) != data
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_data!(new_data, user)
|
def update_data!(new_data, user, preview: false)
|
||||||
self.data = BigDecimal(new_data.to_s)
|
self.data = BigDecimal(new_data.to_s)
|
||||||
self.last_modified_by = user
|
self.last_modified_by = user
|
||||||
save!
|
preview ? validate : save!
|
||||||
end
|
end
|
||||||
|
|
||||||
def snapshot!(cell_snapshot)
|
def snapshot!(cell_snapshot)
|
||||||
|
|
|
@ -48,10 +48,10 @@ class RepositoryStatusValue < ApplicationRecord
|
||||||
new_data.to_i != repository_status_item_id
|
new_data.to_i != repository_status_item_id
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_data!(new_data, user)
|
def update_data!(new_data, user, preview: false)
|
||||||
self.repository_status_item_id = new_data.to_i
|
self.repository_status_item_id = new_data.to_i
|
||||||
self.last_modified_by = user
|
self.last_modified_by = user
|
||||||
save!
|
preview ? validate : save!
|
||||||
end
|
end
|
||||||
|
|
||||||
def snapshot!(cell_snapshot)
|
def snapshot!(cell_snapshot)
|
||||||
|
|
|
@ -108,7 +108,7 @@ class RepositoryStockValue < ApplicationRecord
|
||||||
(new_data[:unit_item_id].present? && new_data[:unit_item_id] != repository_stock_unit_item.id)
|
(new_data[:unit_item_id].present? && new_data[:unit_item_id] != repository_stock_unit_item.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_data!(new_data, user)
|
def update_data!(new_data, user, preview: false)
|
||||||
self.low_stock_threshold = new_data[:low_stock_threshold].presence if new_data[:low_stock_threshold]
|
self.low_stock_threshold = new_data[:low_stock_threshold].presence if new_data[:low_stock_threshold]
|
||||||
self.repository_stock_unit_item = repository_cell
|
self.repository_stock_unit_item = repository_cell
|
||||||
.repository_column
|
.repository_column
|
||||||
|
@ -127,7 +127,7 @@ class RepositoryStockValue < ApplicationRecord
|
||||||
unit: repository_stock_unit_item&.data
|
unit: repository_stock_unit_item&.data
|
||||||
)
|
)
|
||||||
self.amount = new_amount
|
self.amount = new_amount
|
||||||
save!
|
preview ? validate : save!
|
||||||
end
|
end
|
||||||
|
|
||||||
def snapshot!(cell_snapshot)
|
def snapshot!(cell_snapshot)
|
||||||
|
|
|
@ -36,10 +36,10 @@ class RepositoryTextValue < ApplicationRecord
|
||||||
new_data != data
|
new_data != data
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_data!(new_data, user)
|
def update_data!(new_data, user, preview: false)
|
||||||
self.data = new_data
|
self.data = new_data
|
||||||
self.last_modified_by = user
|
self.last_modified_by = user
|
||||||
save!
|
preview ? validate : save!
|
||||||
end
|
end
|
||||||
|
|
||||||
def snapshot!(cell_snapshot)
|
def snapshot!(cell_snapshot)
|
||||||
|
|
|
@ -2,7 +2,9 @@
|
||||||
|
|
||||||
module RepositoryDatatable
|
module RepositoryDatatable
|
||||||
class RepositoryBaseValueSerializer
|
class RepositoryBaseValueSerializer
|
||||||
attr_accessor :value_object, :value_type, :scope
|
attr_accessor :value_object, :value_type, :scope, :changes, :errors
|
||||||
|
|
||||||
|
delegate :changes, :errors, to: :@value_object
|
||||||
|
|
||||||
def initialize(value, scope:)
|
def initialize(value, scope:)
|
||||||
@value_object = value
|
@value_object = value
|
||||||
|
|
|
@ -29,7 +29,10 @@ module RepositoryImportParser
|
||||||
fetch_columns
|
fetch_columns
|
||||||
return check_for_duplicate_columns if check_for_duplicate_columns
|
return check_for_duplicate_columns if check_for_duplicate_columns
|
||||||
|
|
||||||
import_rows!(can_edit_existing_items, should_overwrite_with_empty_cells)
|
# Used for developing preview changes (will be removed)
|
||||||
|
preview = false
|
||||||
|
|
||||||
|
import_rows!(can_edit_existing_items, should_overwrite_with_empty_cells, preview: preview)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -55,7 +58,7 @@ module RepositoryImportParser
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def import_rows!(can_edit_existing_items, should_overwrite_with_empty_cells)
|
def import_rows!(can_edit_existing_items, should_overwrite_with_empty_cells, preview: false)
|
||||||
errors = false
|
errors = false
|
||||||
duplicate_ids = SpreadsheetParser.duplicate_ids(@sheet)
|
duplicate_ids = SpreadsheetParser.duplicate_ids(@sheet)
|
||||||
|
|
||||||
|
@ -68,7 +71,7 @@ module RepositoryImportParser
|
||||||
next if row.blank?
|
next if row.blank?
|
||||||
|
|
||||||
# Skip duplicates
|
# Skip duplicates
|
||||||
next if duplicate_ids.include?(row.first)
|
next if duplicate_ids.include?(row.first) && !preview
|
||||||
|
|
||||||
unless @header_skipped
|
unless @header_skipped
|
||||||
@header_skipped = true
|
@header_skipped = true
|
||||||
|
@ -87,7 +90,7 @@ module RepositoryImportParser
|
||||||
if index == @name_index
|
if index == @name_index
|
||||||
|
|
||||||
# check if row (inventory) already exists
|
# check if row (inventory) already exists
|
||||||
existing_row = RepositoryRow.find_by(id: incoming_row[0])
|
existing_row = RepositoryRow.find_by(id: incoming_row[0].gsub(RepositoryRow::ID_PREFIX, ''))
|
||||||
|
|
||||||
# if it doesn't exist create it
|
# if it doesn't exist create it
|
||||||
unless existing_row
|
unless existing_row
|
||||||
|
@ -104,16 +107,23 @@ module RepositoryImportParser
|
||||||
next
|
next
|
||||||
end
|
end
|
||||||
|
|
||||||
# if it does exist but shouldn't be edited, error out and break
|
# if it's a preview always add the existing row
|
||||||
if existing_row && can_edit_existing_items == '0'
|
if preview
|
||||||
errors = true
|
|
||||||
break
|
|
||||||
end
|
|
||||||
|
|
||||||
# if it does exist and should be edited, update the existing row
|
|
||||||
if existing_row && can_edit_existing_items == '1'
|
|
||||||
# update the existing row with incoming row data
|
|
||||||
new_full_row[:repository_row] = existing_row
|
new_full_row[:repository_row] = existing_row
|
||||||
|
|
||||||
|
# otherwise add according to criteria
|
||||||
|
else
|
||||||
|
# if it does exist but shouldn't be edited, error out and break
|
||||||
|
if existing_row && can_edit_existing_items == '0'
|
||||||
|
errors = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
# if it does exist and should be edited, update the existing row
|
||||||
|
if existing_row && can_edit_existing_items == '1'
|
||||||
|
# update the existing row with incoming row data
|
||||||
|
new_full_row[:repository_row] = existing_row
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -128,13 +138,15 @@ module RepositoryImportParser
|
||||||
|
|
||||||
next if batch_counter < IMPORT_BATCH_SIZE
|
next if batch_counter < IMPORT_BATCH_SIZE
|
||||||
|
|
||||||
import_batch_to_database(full_row_import_batch, can_edit_existing_items, should_overwrite_with_empty_cells)
|
import_batch_to_database(full_row_import_batch, can_edit_existing_items, should_overwrite_with_empty_cells, preview: preview)
|
||||||
full_row_import_batch = []
|
full_row_import_batch = []
|
||||||
batch_counter = 0
|
batch_counter = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
# Import of the remaining rows
|
# Import of the remaining rows
|
||||||
import_batch_to_database(full_row_import_batch, can_edit_existing_items, should_overwrite_with_empty_cells) if full_row_import_batch.any?
|
import_batch_to_database(full_row_import_batch, can_edit_existing_items, should_overwrite_with_empty_cells, preview: preview) if full_row_import_batch.any?
|
||||||
|
|
||||||
|
full_row_import_batch
|
||||||
end
|
end
|
||||||
|
|
||||||
if errors
|
if errors
|
||||||
|
@ -145,7 +157,7 @@ module RepositoryImportParser
|
||||||
{ status: :ok, nr_of_added: @new_rows_added, total_nr: @total_new_rows }
|
{ status: :ok, nr_of_added: @new_rows_added, total_nr: @total_new_rows }
|
||||||
end
|
end
|
||||||
|
|
||||||
def import_batch_to_database(full_row_import_batch, can_edit_existing_items, should_overwrite_with_empty_cells)
|
def import_batch_to_database(full_row_import_batch, can_edit_existing_items, should_overwrite_with_empty_cells, preview: false)
|
||||||
skipped_rows = []
|
skipped_rows = []
|
||||||
|
|
||||||
full_row_import_batch.each do |full_row|
|
full_row_import_batch.each do |full_row|
|
||||||
|
@ -183,18 +195,30 @@ module RepositoryImportParser
|
||||||
|
|
||||||
next if cell_value.nil? && existing_cell.nil?
|
next if cell_value.nil? && existing_cell.nil?
|
||||||
|
|
||||||
# no existing_cell. Create a new one.
|
if existing_cell
|
||||||
if !existing_cell
|
|
||||||
cell_value.repository_cell.value = cell_value
|
|
||||||
cell_value.save!(validate: false)
|
|
||||||
else
|
|
||||||
# existing_cell present && !can_edit_existing_items
|
# existing_cell present && !can_edit_existing_items
|
||||||
next if can_edit_existing_items == '0'
|
next if can_edit_existing_items == '0'
|
||||||
|
|
||||||
# existing_cell present && can_edit_existing_items
|
# existing_cell present && can_edit_existing_items
|
||||||
if can_edit_existing_items == '1'
|
if can_edit_existing_items == '1'
|
||||||
# if incoming cell is not empty
|
# if incoming cell is not empty
|
||||||
existing_cell.value.update_data!(cell_value.data, @user) if !cell_value.nil?
|
case cell_value
|
||||||
|
|
||||||
|
when RepositoryStockValue
|
||||||
|
existing_cell.value.update_data!(cell_value, @user, preview: preview) unless cell_value.nil?
|
||||||
|
|
||||||
|
when RepositoryListValue
|
||||||
|
repository_list_item_id = cell_value[:repository_list_item_id]
|
||||||
|
existing_cell.value.update_data!(repository_list_item_id, @user, preview: preview) unless cell_value.nil?
|
||||||
|
|
||||||
|
when RepositoryStatusValue
|
||||||
|
repository_status_item_id = cell_value[:repository_status_item_id]
|
||||||
|
existing_cell.value.update_data!(repository_status_item_id, @user, preview: preview) unless cell_value.nil?
|
||||||
|
|
||||||
|
else
|
||||||
|
sanitized_cell_value_data = sanitize_cell_value_data(cell_value.data)
|
||||||
|
existing_cell.value.update_data!(sanitized_cell_value_data, @user, preview: preview) unless cell_value.nil?
|
||||||
|
end
|
||||||
|
|
||||||
# if incoming cell is empty && should_overwrite_with_empty_cells
|
# if incoming cell is empty && should_overwrite_with_empty_cells
|
||||||
existing_cell.value.destroy! if cell_value.nil? && should_overwrite_with_empty_cells == '1'
|
existing_cell.value.destroy! if cell_value.nil? && should_overwrite_with_empty_cells == '1'
|
||||||
|
@ -202,11 +226,34 @@ module RepositoryImportParser
|
||||||
# if incoming cell is empty && !should_overwrite_with_empty_cells
|
# if incoming cell is empty && !should_overwrite_with_empty_cells
|
||||||
next if cell_value.nil? && should_overwrite_with_empty_cells == '0'
|
next if cell_value.nil? && should_overwrite_with_empty_cells == '0'
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
# no existing_cell. Create a new one.
|
||||||
|
cell_value.repository_cell.value = cell_value
|
||||||
|
cell_value.save!(validate: false)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def sanitize_cell_value_data(cell_value_data)
|
||||||
|
case cell_value_data
|
||||||
|
# when importing from .csv for:
|
||||||
|
# repository_text_value, repository_number_value, repository_date_value, repository_date_time_value_base
|
||||||
|
when String, Numeric, Date, Time
|
||||||
|
cell_value_data
|
||||||
|
when Array
|
||||||
|
cell_value_data.filter_map do |element|
|
||||||
|
if element.is_a?(Hash) && element.key?(:value)
|
||||||
|
element[:value].to_s
|
||||||
|
elsif element.is_a?(String)
|
||||||
|
element
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
[]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def try_decimal_to_string(value)
|
def try_decimal_to_string(value)
|
||||||
if value.is_a?(BigDecimal)
|
if value.is_a?(BigDecimal)
|
||||||
value.frac.zero? ? value.to_i.to_s : value.to_s
|
value.frac.zero? ? value.to_i.to_s : value.to_s
|
||||||
|
|
Loading…
Add table
Reference in a new issue