diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index 4f1b17974..66374725e 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -305,10 +305,14 @@ class RepositoriesController < ApplicationController render_403 unless can_create_repository_rows?(Repository.accessible_by_teams(current_team) .find_by_id(import_params[:id])) + # Access the checkbox values from params + can_edit_existing_items = params[:edit_existing_items_checkbox] + should_overwrite_with_empty_cells = params[:overwrite_with_empty_cells] + # Check if there exist mapping for repository record (it's mandatory) if import_params[:mappings].value?('-1') import_records = repostiory_import_actions - status = import_records.import! + status = import_records.import!(can_edit_existing_items, should_overwrite_with_empty_cells) if status[:status] == :ok log_activity(:import_inventory_items, diff --git a/app/models/repository.rb b/app/models/repository.rb index a76e2be54..21c481033 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -231,9 +231,9 @@ class Repository < RepositoryBase new_repo end - def import_records(sheet, mappings, user) + def import_records(sheet, mappings, user, can_edit_existing_items, should_overwrite_with_empty_cells) importer = RepositoryImportParser::Importer.new(sheet, mappings, user, self) - importer.run + importer.run(can_edit_existing_items, should_overwrite_with_empty_cells) end def assigned_rows(my_module) diff --git a/app/services/import_repository/import_records.rb b/app/services/import_repository/import_records.rb index 4715dbe2a..0ce789e08 100644 --- a/app/services/import_repository/import_records.rb +++ b/app/services/import_repository/import_records.rb @@ -8,20 +8,22 @@ module ImportRepository @user = options.fetch(:user) end - def import! - status = run_import_actions + def import!(can_edit_existing_items, should_overwrite_with_empty_cells) + status = run_import_actions(can_edit_existing_items, should_overwrite_with_empty_cells) @temp_file.destroy status end private - def run_import_actions + def run_import_actions(can_edit_existing_items, should_overwrite_with_empty_cells) @temp_file.file.open do |temp_file| @repository.import_records( SpreadsheetParser.open_spreadsheet(temp_file), @mappings, - @user + @user, + can_edit_existing_items, + should_overwrite_with_empty_cells ) end end diff --git a/app/utilities/repository_import_parser/importer.rb b/app/utilities/repository_import_parser/importer.rb index b95d99be3..1e97b3f21 100644 --- a/app/utilities/repository_import_parser/importer.rb +++ b/app/utilities/repository_import_parser/importer.rb @@ -6,6 +6,7 @@ # @mappings: mappings for columns # @user: current_user # @repository: the repository in which we import the items + module RepositoryImportParser class Importer IMPORT_BATCH_SIZE = 500 @@ -24,11 +25,11 @@ module RepositoryImportParser @repository_columns = @repository.repository_columns end - def run + def run(can_edit_existing_items, should_overwrite_with_empty_cells) fetch_columns return check_for_duplicate_columns if check_for_duplicate_columns - import_rows! + import_rows!(can_edit_existing_items, should_overwrite_with_empty_cells) end private @@ -54,7 +55,7 @@ module RepositoryImportParser end end - def import_rows! + def import_rows!(can_edit_existing_items, should_overwrite_with_empty_cells) errors = false @repository.transaction do @@ -72,27 +73,50 @@ module RepositoryImportParser @total_new_rows += 1 new_full_row = {} - SpreadsheetParser.parse_row( + incoming_row = SpreadsheetParser.parse_row( row, @sheet, date_format: @user.settings['date_format'] - ).each_with_index do |value, index| + ) + + incoming_row.each_with_index do |value, index| if index == @name_index - new_row = + + # extract row_id + row_id = try_decimal_to_string(value) + + # check if row (inventory) already exists + existing_row = RepositoryRow.find_by(name: row_id, repository: @repository) + + # if it doesn't exist create it + unless existing_row + new_row = RepositoryRow.new(name: try_decimal_to_string(value), repository: @repository, created_by: @user, last_modified_by: @user) - unless new_row.valid? + unless new_row.valid? + errors = true + break + end + new_full_row[:repository_row] = new_row + 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 - new_full_row[:repository_row] = new_row - next + # 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 - next unless @columns[index] + next unless @columns[index] new_full_row[index] = value end @@ -103,13 +127,13 @@ module RepositoryImportParser next if batch_counter < IMPORT_BATCH_SIZE - import_batch_to_database(full_row_import_batch) + import_batch_to_database(full_row_import_batch, can_edit_existing_items, should_overwrite_with_empty_cells) full_row_import_batch = [] batch_counter = 0 end # Import of the remaining rows - import_batch_to_database(full_row_import_batch) if full_row_import_batch.any? + import_batch_to_database(full_row_import_batch, can_edit_existing_items, should_overwrite_with_empty_cells) if full_row_import_batch.any? end if errors @@ -120,45 +144,58 @@ 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) - repository_rows = full_row_import_batch.collect { |row| row[:repository_row] } - @new_rows_added += RepositoryRow.import(repository_rows, recursive: false, validate: false).ids.length - repository_rows.each { |row| row.run_callbacks(:create) } + def import_batch_to_database(full_row_import_batch, can_edit_existing_items, should_overwrite_with_empty_cells) + full_row_import_batch.each do |full_row| + full_row[:repository_row].save!(validate: false) + @new_rows_added += 1 - import_mappings = Hash[@columns.map { |column| column&.data_type&.to_sym } - .compact - .uniq - .map { |data_type| [data_type, []] }] - - full_row_import_batch.each do |row| - next unless row[:repository_row].id - - row.reject { |k| k == :repository_row }.each do |index, value| + full_row.reject { |k| k == :repository_row }.each do |index, value| column = @columns[index] value = try_decimal_to_string(value) unless column.repository_number_value? next if value.nil? - cell_value_attributes = { created_by: @user, - last_modified_by: @user, - repository_cell_attributes: { repository_row: row[:repository_row], - repository_column: column, - importing: true } } + cell_value_attributes = { + created_by: @user, + last_modified_by: @user, + repository_cell_attributes: { + repository_row: full_row[:repository_row], + repository_column: column, + importing: true + } + } + cell_value = column.data_type.constantize.import_from_text( value, cell_value_attributes, @user.as_json(root: true, only: :settings).deep_symbolize_keys ) - next if cell_value.nil? - cell_value.repository_cell.value = cell_value + existing_cell = full_row[:repository_row].repository_cells.find_by(repository_column: column) - import_mappings[column.data_type.to_sym] << cell_value + 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 + # 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? + + # if incoming cell is empty && should_overwrite_with_empty_cells + existing_cell.value.destroy! if cell_value.nil? && should_overwrite_with_empty_cells == '1' + + # if incoming cell is empty && !should_overwrite_with_empty_cells + next if cell_value.nil? && should_overwrite_with_empty_cells == '0' + end + end end end - - import_mappings.each do |data_type, cell_values| - data_type.to_s.constantize.import(cell_values, recursive: true, validate: false) - end end def try_decimal_to_string(value) diff --git a/app/views/repositories/_parse_records_modal.html.erb b/app/views/repositories/_parse_records_modal.html.erb index 8834096cc..f1072461e 100644 --- a/app/views/repositories/_parse_records_modal.html.erb +++ b/app/views/repositories/_parse_records_modal.html.erb @@ -14,6 +14,20 @@ <%= f.hidden_field :team_id, value: current_team.id %>
<%= t("repositories.parse_sheet.help_text") %>
+