diff --git a/app/services/tasks/samples_to_repository_migration_service.rb b/app/services/tasks/samples_to_repository_migration_service.rb index fa5592564..151adc79c 100644 --- a/app/services/tasks/samples_to_repository_migration_service.rb +++ b/app/services/tasks/samples_to_repository_migration_service.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Helper module for dealing with the migration from samples # to custom repositories. We need to query with SQL because probably we will not # have the "Sample" and other related models at the time this code will execute @@ -23,7 +25,7 @@ module Tasks repository_columns = [] custom_columns.each_with_index do |column, index| - repository_column = RepositoryColumn.create( + repository_column = RepositoryColumn.create!( repository: repository, created_by_id: column.fetch('user_id') { repository.created_by_id }, data_type: :RepositoryTextValue, @@ -51,16 +53,22 @@ module Tasks sample_types = ActiveRecord::Base.connection.execute(sample_types_sql) sample_groups = ActiveRecord::Base.connection.execute(sample_groups_sql) - repository_columns = [] - - repository_columns << RepositoryColumn.create( + sample_group = RepositoryColumn.create!( repository: repository, created_by_id: repository.created_by_id, data_type: :RepositoryListValue, name: 'Sample group' ) - repository_columns << RepositoryColumn.create( + # needs some random string to prevent duplications error + sample_group_color = RepositoryColumn.create!( + repository: repository, + created_by_id: repository.created_by_id, + data_type: :RepositoryTextValue, + name: 'Sample group color hex (e980a0f5)' + ) + + sample_type = RepositoryColumn.create!( repository: repository, created_by_id: repository.created_by_id, data_type: :RepositoryListValue, @@ -68,28 +76,30 @@ module Tasks ) sample_groups.each_with_index do |item, index| - RepositoryListItem.create( + created_by = item['created_by_id'] || team.created_by_id + last_modified_by = item['last_modified_by_id'] || team.created_by_id + RepositoryListItem.create!( data: item.fetch('name') { "sample group item (#{index})" }, - created_by_id: item.fetch('created_by_id') { team.created_by_id }, - last_modified_by_id: - item.fetch('last_modified_by_id') { team.created_by_id }, - repository_column: repository_columns.first, + created_by_id: created_by, + last_modified_by_id: last_modified_by, + repository_column: sample_group, repository: repository ) end sample_types.each_with_index do |item, index| - RepositoryListItem.create( + created_by = item['created_by_id'] || team.created_by_id + last_modified_by = item['last_modified_by_id'] || team.created_by_id + RepositoryListItem.create!( data: item.fetch('name') { "sample group item (#{index})" }, - created_by_id: item.fetch('created_by_id') { team.created_by_id }, - last_modified_by_id: - item.fetch('last_modified_by_id') { team.created_by_id }, - repository_column: repository_columns.last, + created_by_id: created_by, + last_modified_by_id: last_modified_by, + repository_column: sample_type, repository: repository ) end - repository_columns + [sample_group, sample_type, sample_group_color] end def self.get_sample_custom_fields(sample_id) @@ -108,7 +118,7 @@ module Tasks def self.get_assigned_sample_module(sample_id) assigned_samples_sql = <<-SQL - SELECT my_module_id, assigned_by_id, assigned_on + SELECT my_module_id, assigned_by_id FROM sample_my_modules WHERE sample_my_modules.sample_id = #{sample_id} SQL @@ -125,12 +135,17 @@ module Tasks sample_groups.name AS sample_group_name, sample_groups.color AS sample_group_color FROM samples - JOIN sample_types ON samples.sample_type_id = sample_types.id - JOIN sample_groups ON samples.sample_type_id = sample_groups.id + LEFT OUTER JOIN sample_types ON samples.sample_type_id = sample_types.id + LEFT OUTER JOIN sample_groups ON samples.sample_type_id = sample_groups.id WHERE samples.team_id = #{team.id} SQL ActiveRecord::Base.connection.execute(samples_sql).to_a end + + def self.get_custom_columns(team, repository) + prepare_text_value_custom_columns(team, repository) + + prepare_list_value_custom_columns_with_list_items(team, repository) + end end end diff --git a/lib/tasks/samples_to_repository_migration.rake b/lib/tasks/samples_to_repository_migration.rake index 28385b326..1941d9feb 100644 --- a/lib/tasks/samples_to_repository_migration.rake +++ b/lib/tasks/samples_to_repository_migration.rake @@ -9,19 +9,104 @@ namespace :samples_to_repository_migration do params[:start] = args[:last_id].to_i end Team.find_each(params) do |team| - puts "******************************* \n\n\n\n" - puts "Processing Team id => [#{team.id}] \n\n\n\n" + puts "******************************* \n\n" + puts "Processing Team id => [#{team.id}] \n\n" puts '*******************************' - # byebug - migration_service.fetch_all_team_samples(team) - repository = migration_service.prepare_repository(team) - custom_columns = migration_service.prepare_text_value_custom_columns(team, repository) + - migration_service.prepare_list_value_custom_columns_with_list_items( - team, - repository - ) - # byebug + ActiveRecord::Base.transaction do + team_samples = migration_service.fetch_all_team_samples(team) + repository = migration_service.prepare_repository(team) + custom_columns = migration_service.get_custom_columns(team, repository) + + team_samples.each do |item| + created_by = item['sample_created_by_id'] || team.created_by_id + last_modified_by = item['sample_last_modified_by_id'] || team.created_by_id + row = RepositoryRow.create!(name: item['sample_name'], + created_by_id: created_by, + last_modified_by_id: last_modified_by, + repository: repository) + # check if sample has sample type assigned + if item['sample_type_name'] + column = custom_columns.detect { |el| el['name'] == 'Sample type' } + list_item = column.repository_list_items.where( + data: item['sample_type_name'] + ).take + RepositoryListValue.create!( + created_by: list_item.created_by, + last_modified_by: list_item.last_modified_by, + repository_list_item: list_item, + repository_cell_attributes: { + repository_row: row, + repository_column: column + } + ) + end + + # check if sample has sample group assigned + if item['sample_group_name'] + column = custom_columns.detect { |el| el['name'] == 'Sample group' } + list_item = column.repository_list_items.where( + data: item['sample_group_name'] + ).take + RepositoryListValue.create!( + created_by: list_item.created_by, + last_modified_by: list_item.last_modified_by, + repository_list_item: list_item, + repository_cell_attributes: { + repository_row: row, + repository_column: column + } + ) + + # assign sample group color to the sample + if item['sample_group_color'] + column = custom_columns.detect do |el| + el['name'] == 'Sample group color hex (e980a0f5)' + end + RepositoryTextValue.create!( + data: item['sample_group_color'], + created_by_id: created_by, + last_modified_by_id: last_modified_by, + repository_cell_attributes: { + repository_row: row, + repository_column: column + } + ) + end + end + + # append custom fields + custom_fields = migration_service.get_sample_custom_fields( + item['sample_id'] + ) + custom_fields.each do |field| + column = custom_columns.detect do |el| + el['name'] == field['column_name_reference'] + end + RepositoryTextValue.create!( + data: field['value'], + created_by_id: created_by, + last_modified_by_id: last_modified_by, + repository_cell_attributes: { + repository_row: row, + repository_column: column + } + ) + end + + # assign repository item to a tasks + assigned_modules = migration_service.get_assigned_sample_module( + item['sample_id'] + ) + assigned_modules.each do |element| + MyModuleRepositoryRow.create!( + my_module_id: element['my_module_id'], + repository_row: row, + assigned_by_id: element['assigned_by_id'] || created_by + ) + end + end + end end end end diff --git a/spec/lib/tasks/samples_to_repository_migration_spec.rb b/spec/lib/tasks/samples_to_repository_migration_spec.rb index 7b28b1e6e..f8b135fb8 100644 --- a/spec/lib/tasks/samples_to_repository_migration_spec.rb +++ b/spec/lib/tasks/samples_to_repository_migration_spec.rb @@ -1,3 +1,76 @@ +require 'rails_helper' + describe 'samples_to_repository_migration:run' do include_context 'rake' + let!(:user) { create :user, email: 'happy.user@scinote.net' } + let!(:team) { create :team, created_by: user } + let!(:user_team) { create :user_team, user: user, team: team } + let!(:my_module) { create :my_module } + let!(:samples_table) { create :samples_table, user: user, team: team } + let(:sample_types_names) { %w(type_one type_two type_three) } + let(:sample_group_names) { %w(group_one group_two group_three) } + + before do + sample_types = [] + sample_types_names.each do |name| + sample_type = create :sample_type, name: name, team: team + sample_types << sample_type + end + sample_groups = [] + sample_group_names.each do |name| + sample_group = create :sample_group, name: name, team: team + sample_groups << sample_group + end + custom_field = create :custom_field, name: 'Banana', team: team, user: user + 100.times do |index| + sample = create :sample, name: "Sample (#{index})", user: user, team: team + create :sample_my_module, sample: sample, my_module: my_module + sample.sample_type = sample_types[rand(0...2)] + sample.sample_group = sample_groups[rand(0...2)] + custom_value = create :sample_custom_field, + value: "custom value (#{index})", + custom_field: custom_field, + sample: sample + sample.sample_custom_fields << custom_value + sample.save + end + end + + it 'generates a new custom repository with exact copy of samples' do + subject.invoke + expect(Repository.first.name).to eq 'Samples' + expect(RepositoryRow.count).to eq 100 + RepositoryRow.all.each do |row| + row_my_module = MyModuleRepositoryRow.where(repository_row: row, + my_module: my_module) + expect(row_my_module).to exist + expect(row.name).to match(/Sample \([0-9]*\)/) + expect(row.created_by).to eq user + + # repository sample_type column + sample_type_column = row.repository_cells.first + expect(sample_types_names).to include(sample_type_column.value.formatted) + expect(sample_type_column.repository_column.name).to eq 'Sample type' + expect(sample_type_column.value_type).to eq 'RepositoryListValue' + + # repository sample_group column + sample_group_column = row.repository_cells.second + expect(sample_group_names).to include(sample_group_column.value.formatted) + expect(sample_group_column.repository_column.name).to eq 'Sample group' + expect(sample_group_column.value_type).to eq 'RepositoryListValue' + + # repository color column + color_column = row.repository_cells.third + expect( + color_column.repository_column.name + ).to eq 'Sample group color hex (e980a0f5)' + expect(color_column.value_type).to eq 'RepositoryTextValue' + + # repository custom column + custom_column = row.repository_cells.last + expect(custom_column.value.formatted).to match(/custom value \([0-9]*\)/) + expect(custom_column.repository_column.name).to eq 'Banana' + expect(custom_column.value_type).to eq 'RepositoryTextValue' + end + end end diff --git a/spec/services/tasks/samples_to_repository_migration_service_spec.rb b/spec/services/tasks/samples_to_repository_migration_service_spec.rb index 5463fe47c..bbbed741c 100644 --- a/spec/services/tasks/samples_to_repository_migration_service_spec.rb +++ b/spec/services/tasks/samples_to_repository_migration_service_spec.rb @@ -81,15 +81,17 @@ describe Tasks::SamplesToRepositoryMigrationService do end it { is_expected.to be_an Array } - it { expect(subject.length).to eq 2 } + it { expect(subject.length).to eq 3 } it { expect(subject.first).to be_an_instance_of(RepositoryColumn) } it { expect(subject.first.name).to eq 'Sample group' } it { expect(subject.first.data_type).to eq 'RepositoryListValue' } - it { expect(subject.last.name).to eq 'Sample type' } - it { expect(subject.last.data_type).to eq 'RepositoryListValue' } + it { expect(subject.second.name).to eq 'Sample type' } + it { expect(subject.second.data_type).to eq 'RepositoryListValue' } + it { expect(subject.last.name).to eq 'Sample group color hex (e980a0f5)' } + it { expect(subject.last.data_type).to eq 'RepositoryTextValue' } describe 'generated list items from sample types' do - let!(:generated_list_items) { subject.last.repository_list_items } + let!(:generated_list_items) { subject.second.repository_list_items } it { expect(generated_list_items.count).to eq 10 } it 'has generated list_items with similar properties' do @@ -101,6 +103,24 @@ describe Tasks::SamplesToRepositoryMigrationService do end end end + + describe 'sample type without created_at/last_modified_by field' do + before do + team.sample_types.update_all(created_by_id: nil, + last_modified_by_id: nil) + end + + it 'generates valid list_items' do + generated_list_items = subject.second.repository_list_items + expect(generated_list_items.count).to eq 10 + generated_list_items.each_with_index do |item, index| + expect(item.data).to eq "Sample Type Item (#{index})" + expect(item).to be_an_instance_of RepositoryListItem + expect(item.created_by).to eq team.created_by + expect(item.last_modified_by).to eq team.created_by + end + end + end end context 'with samples groups' do @@ -115,13 +135,15 @@ describe Tasks::SamplesToRepositoryMigrationService do end it { is_expected.to be_an Array } - it { expect(subject.length).to eq 2 } + it { expect(subject.length).to eq 3 } it { expect(subject.first).to be_an_instance_of(RepositoryColumn) } it { expect(subject.last).to be_an_instance_of(RepositoryColumn) } it { expect(subject.first.name).to eq 'Sample group' } it { expect(subject.first.data_type).to eq 'RepositoryListValue' } - it { expect(subject.last.name).to eq 'Sample type' } - it { expect(subject.last.data_type).to eq 'RepositoryListValue' } + it { expect(subject.second.name).to eq 'Sample type' } + it { expect(subject.second.data_type).to eq 'RepositoryListValue' } + it { expect(subject.last.name).to eq 'Sample group color hex (e980a0f5)' } + it { expect(subject.last.data_type).to eq 'RepositoryTextValue' } describe 'generated list items from sample groups' do let!(:generated_list_items) { subject.first.repository_list_items } @@ -136,6 +158,24 @@ describe Tasks::SamplesToRepositoryMigrationService do end end end + + describe 'sample group without created_at/last_modified_by field' do + before do + team.sample_groups.update_all(created_by_id: nil, + last_modified_by_id: nil) + end + + it 'generates valid list_items' do + generated_list_items = subject.first.repository_list_items + expect(generated_list_items.count).to eq 10 + generated_list_items.each_with_index do |item, index| + expect(item.data).to eq "Sample Group Item (#{index})" + expect(item).to be_an_instance_of RepositoryListItem + expect(item.created_by).to eq team.created_by + expect(item.last_modified_by).to eq team.created_by + end + end + end end end @@ -202,9 +242,6 @@ describe Tasks::SamplesToRepositoryMigrationService do expect( my_module_data.fetch('assigned_by_id') ).to eq sample_my_module.assigned_by_id - expect( - my_module_data.fetch('assigned_on') - ).to eq sample_my_module.assigned_on end end diff --git a/spec/support/shared_contexts/rake.rb b/spec/support/shared_contexts/rake.rb index cc0031460..b7522bb67 100644 --- a/spec/support/shared_contexts/rake.rb +++ b/spec/support/shared_contexts/rake.rb @@ -1,4 +1,4 @@ -require "rake" +require 'rake' shared_context 'rake' do let(:rake) { Rake::Application.new }