(dev) POC for inventory import preview [SCI-10489]

This commit is contained in:
Gregor Lasnibat 2024-03-26 11:08:17 +01:00
parent 8ecef3719c
commit 2b92fda906
11 changed files with 104 additions and 49 deletions

View file

@ -5,10 +5,4 @@ class RepositoryChecklistItemsValue < ApplicationRecord
belongs_to :repository_checklist_value, inverse_of: :repository_checklist_items_values
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

View file

@ -70,17 +70,19 @@ class RepositoryChecklistValue < ApplicationRecord
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
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
.repository_checklist_items
.where(id: item_ids)
self.last_modified_by = user
save!
preview ? validate : save!
end
def snapshot!(cell_snapshot)

View file

@ -19,10 +19,15 @@ class RepositoryDateTimeValueBase < ApplicationRecord
I18n.l(data, format: format)
end
def update_data!(new_data, user)
self.data = Time.zone.parse(new_data)
def update_data!(new_data, user, preview: false)
self.data = if new_data.is_a?(String)
Time.zone.parse(new_data)
else
new_data
end
self.last_modified_by = user
save!
preview ? validate : save!
end
def snapshot!(cell_snapshot)

View file

@ -56,10 +56,15 @@ class RepositoryDateValue < RepositoryDateTimeValueBase
value
end
def update_data!(new_data, user)
self.data = Date.parse(new_data)
def update_data!(new_data, user, preview: false)
self.data = if new_data.is_a?(String)
Date.parse(new_data)
else
new_data.to_time.utc
end
self.last_modified_by = user
save!
preview ? validate : save!
end
def self.import_from_text(text, attributes, options = {})

View file

@ -57,10 +57,10 @@ class RepositoryListValue < ApplicationRecord
new_data.to_i != repository_list_item_id
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.last_modified_by = user
save!
preview ? validate : save!
end
def snapshot!(cell_snapshot)

View file

@ -49,10 +49,10 @@ class RepositoryNumberValue < ApplicationRecord
BigDecimal(new_data.to_s) != data
end
def update_data!(new_data, user)
def update_data!(new_data, user, preview: false)
self.data = BigDecimal(new_data.to_s)
self.last_modified_by = user
save!
preview ? validate : save!
end
def snapshot!(cell_snapshot)

View file

@ -48,10 +48,10 @@ class RepositoryStatusValue < ApplicationRecord
new_data.to_i != repository_status_item_id
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.last_modified_by = user
save!
preview ? validate : save!
end
def snapshot!(cell_snapshot)

View file

@ -108,7 +108,7 @@ class RepositoryStockValue < ApplicationRecord
(new_data[:unit_item_id].present? && new_data[:unit_item_id] != repository_stock_unit_item.id)
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.repository_stock_unit_item = repository_cell
.repository_column
@ -127,7 +127,7 @@ class RepositoryStockValue < ApplicationRecord
unit: repository_stock_unit_item&.data
)
self.amount = new_amount
save!
preview ? validate : save!
end
def snapshot!(cell_snapshot)

View file

@ -36,10 +36,10 @@ class RepositoryTextValue < ApplicationRecord
new_data != data
end
def update_data!(new_data, user)
def update_data!(new_data, user, preview: false)
self.data = new_data
self.last_modified_by = user
save!
preview ? validate : save!
end
def snapshot!(cell_snapshot)

View file

@ -2,7 +2,9 @@
module RepositoryDatatable
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:)
@value_object = value

View file

@ -29,7 +29,10 @@ module RepositoryImportParser
fetch_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
private
@ -55,7 +58,7 @@ module RepositoryImportParser
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
duplicate_ids = SpreadsheetParser.duplicate_ids(@sheet)
@ -68,7 +71,7 @@ module RepositoryImportParser
next if row.blank?
# Skip duplicates
next if duplicate_ids.include?(row.first)
next if duplicate_ids.include?(row.first) && !preview
unless @header_skipped
@header_skipped = true
@ -87,7 +90,7 @@ module RepositoryImportParser
if index == @name_index
# 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
unless existing_row
@ -104,16 +107,23 @@ module RepositoryImportParser
next
end
# 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
# if it's a preview always add the existing row
if preview
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
@ -128,13 +138,15 @@ module RepositoryImportParser
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 = []
batch_counter = 0
end
# 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
if errors
@ -145,7 +157,7 @@ module RepositoryImportParser
{ status: :ok, nr_of_added: @new_rows_added, total_nr: @total_new_rows }
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 = []
full_row_import_batch.each do |full_row|
@ -183,18 +195,30 @@ module RepositoryImportParser
next if cell_value.nil? && existing_cell.nil?
# no existing_cell. Create a new one.
if !existing_cell
cell_value.repository_cell.value = cell_value
cell_value.save!(validate: false)
else
if existing_cell
# existing_cell present && !can_edit_existing_items
next if can_edit_existing_items == '0'
# existing_cell present && can_edit_existing_items
if can_edit_existing_items == '1'
# 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
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
next if cell_value.nil? && should_overwrite_with_empty_cells == '0'
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
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)
if value.is_a?(BigDecimal)
value.frac.zero? ? value.to_i.to_s : value.to_s