From dd08e9913de5053746e048028c8c3ec43bb85afe Mon Sep 17 00:00:00 2001 From: PPeregrino <125605570+PPeregrino@users.noreply.github.com> Date: Mon, 8 Dec 2025 11:48:12 -0300 Subject: [PATCH 1/6] deletando arquivo duplicado de user --- app/models/usuario.rb | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 app/models/usuario.rb diff --git a/app/models/usuario.rb b/app/models/usuario.rb deleted file mode 100644 index 095adc1d9b..0000000000 --- a/app/models/usuario.rb +++ /dev/null @@ -1,7 +0,0 @@ -class Usuario < ApplicationRecord - has_secure_password - - validates :login, presence: true, uniqueness: true - validates :email, presence: true, uniqueness: true - validates :matricula, presence: true, uniqueness: true -end From 2e5bc8ec3645bb39569f169e508c65be918ebc6f Mon Sep 17 00:00:00 2001 From: PPeregrino <125605570+PPeregrino@users.noreply.github.com> Date: Mon, 8 Dec 2025 11:48:57 -0300 Subject: [PATCH 2/6] atualizando arquivo user --- app/models/Usuario.rb | 5 ----- app/models/user.rb | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 5 deletions(-) delete mode 100644 app/models/Usuario.rb create mode 100644 app/models/user.rb diff --git a/app/models/Usuario.rb b/app/models/Usuario.rb deleted file mode 100644 index 5746bc5f8b..0000000000 --- a/app/models/Usuario.rb +++ /dev/null @@ -1,5 +0,0 @@ -class Usuario < ApplicationRecord - #mais codigo acima assumindo que Usuario ja exista - has_many :matricula_turmas - has_many :turmas, through: :matricula_turmas -end diff --git a/app/models/user.rb b/app/models/user.rb new file mode 100644 index 0000000000..2e47818df0 --- /dev/null +++ b/app/models/user.rb @@ -0,0 +1,14 @@ +class User < ApplicationRecord + has_secure_password + has_many :sessions, dependent: :destroy + has_many :matricula_turmas + has_many :turmas, through: :matricula_turmas + + validates :email_address, presence: true, uniqueness: true + validates :login, presence: true, uniqueness: true + validates :matricula, presence: true, uniqueness: true + validates :nome, presence: true + + normalizes :email_address, with: ->(e) { e.strip.downcase } + normalizes :login, with: ->(l) { l.strip.downcase } +end From 151dd2f54a284fd783ee360a057b160a2424dd30 Mon Sep 17 00:00:00 2001 From: PPeregrino <125605570+PPeregrino@users.noreply.github.com> Date: Mon, 8 Dec 2025 12:30:47 -0300 Subject: [PATCH 3/6] =?UTF-8?q?Implementa=C3=A7=C3=A3o=20Issue=20#36?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/services/sigaa_import_service.rb | 135 +++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 app/services/sigaa_import_service.rb diff --git a/app/services/sigaa_import_service.rb b/app/services/sigaa_import_service.rb new file mode 100644 index 0000000000..093daa2446 --- /dev/null +++ b/app/services/sigaa_import_service.rb @@ -0,0 +1,135 @@ +require 'json' +require 'csv' + +class SigaaImportService + def initialize(file_path) + @file_path = file_path + @results = { + turmas_created: 0, + turmas_updated: 0, + usuarios_created: 0, + usuarios_updated: 0, + errors: [] + } + end + + def process + unless File.exist?(@file_path) + @results[:errors] << "Arquivo não encontrado: #{@file_path}" + return @results + end + + begin + ActiveRecord::Base.transaction do + case File.extname(@file_path).downcase + when '.json' + process_json + when '.csv' + process_csv + else + @results[:errors] << "Formato de arquivo não suportado: #{File.extname(@file_path)}" + end + + if @results[:errors].any? + raise ActiveRecord::Rollback + end + end + rescue JSON::ParserError + @results[:errors] << "Arquivo JSON inválido" + rescue ActiveRecord::StatementInvalid => e + @results[:errors] << "Erro de conexão com o banco de dados: #{e.message}" + rescue StandardError => e + @results[:errors] << "Erro inesperado: #{e.message}" + end + + @results + end + + private + + def process_json + file_content = File.read(@file_path) + data = JSON.parse(file_content) + data.each do |turma_data| + process_turma(turma_data) + end + end + + def process_csv + CSV.foreach(@file_path, headers: true, col_sep: ',') do |row| + # Assumindo estrutura do CSV + turma_data = { + 'codigo' => row['codigo_turma'], + 'nome' => row['nome_turma'], + 'semestre' => row['semestre'] + } + + turma = process_turma_record(turma_data) + + if turma&.persisted? + user_data = { + 'nome' => row['nome_usuario'], + 'email' => row['email'], + 'matricula' => row['matricula'], + 'papel' => row['papel'] + } + process_participante_single(turma, user_data) + end + end + end + + def process_turma(data) + turma = process_turma_record(data) + if turma&.persisted? + process_participantes(turma, data['participantes']) if data['participantes'] + end + end + + def process_turma_record(data) + turma = Turma.find_or_initialize_by(codigo: data['codigo'], semestre: data['semestre']) + + is_new_record = turma.new_record? + turma.nome = data['nome'] + + if turma.save + if is_new_record + @results[:turmas_created] += 1 + else + @results[:turmas_updated] += 1 + end + turma + else + @results[:errors] << "Erro ao salvar turma #{data['codigo']}: #{turma.errors.full_messages.join(', ')}" + nil + end + end + + def process_participantes(turma, participantes_data) + participantes_data.each do |p_data| + process_participante_single(turma, p_data) + end + end + + def process_participante_single(turma, p_data) + # Usuario identificado pela matrícula + user = User.find_or_initialize_by(matricula: p_data['matricula']) + + is_new_user = user.new_record? + user.nome = p_data['nome'] + user.email = p_data['email'] + + if user.save + if is_new_user + @results[:usuarios_created] += 1 + else + @results[:usuarios_updated] += 1 + end + + matricula = MatriculaTurma.find_or_initialize_by(turma: turma, user: user) + matricula.papel = p_data['papel'] + matricula.save! + else + @results[:errors] << "Erro ao salvar usuário #{p_data['matricula']}: #{user.errors.full_messages.join(', ')}" + end + end +end From d524a52f033f580c060b3e33ad375490f7178b01 Mon Sep 17 00:00:00 2001 From: PPeregrino <125605570+PPeregrino@users.noreply.github.com> Date: Mon, 8 Dec 2025 12:33:56 -0300 Subject: [PATCH 4/6] =?UTF-8?q?Implementa=C3=A7=C3=A3o=20Issue=20#36?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/services/sigaa_import_service_test.rb | 62 ++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 test/services/sigaa_import_service_test.rb diff --git a/test/services/sigaa_import_service_test.rb b/test/services/sigaa_import_service_test.rb new file mode 100644 index 0000000000..4a1a74737b --- /dev/null +++ b/test/services/sigaa_import_service_test.rb @@ -0,0 +1,62 @@ +require 'test_helper' + +class SigaaImportServiceTest < ActiveSupport::TestCase + def setup + @file_path = Rails.root.join('tmp', 'sigaa_data.json') + @data = [ + { + "codigo" => "TURMA123", + "nome" => "Engenharia de Software", + "semestre" => "2023.2", + "participantes" => [ + { + "nome" => "João Silva", + "email" => "joao@example.com", + "matricula" => "2023001", + "papel" => "discente" + } + ] + } + ] + File.write(@file_path, @data.to_json) + end + + def teardown + File.delete(@file_path) if File.exist?(@file_path) + end + + test "importa turmas e usuarios com sucesso" do + service = SigaaImportService.new(@file_path) + result = service.process + + assert_empty result[:errors] + assert_equal 1, result[:turmas_created] + assert_equal 1, result[:usuarios_created] + + turma = Turma.find_by(codigo: "TURMA123") + assert_not_nil turma + assert_equal "Engenharia de Software", turma.nome + + user = User.find_by(matricula: "2023001") + assert_not_nil user + assert_equal "João Silva", user.nome + + matricula = MatriculaTurma.find_by(turma: turma, user: user) + assert_not_nil matricula + assert_equal "discente", matricula.papel + end + + test "reverte em caso de erro de validação" do + # Criar dados inválidos (semestre faltando para Turma) + invalid_data = @data.dup + invalid_data[0]["semestre"] = nil + File.write(@file_path, invalid_data.to_json) + + service = SigaaImportService.new(@file_path) + result = service.process + + assert_not_empty result[:errors] + assert_equal 0, Turma.count + assert_equal 0, User.count + end +end From 90a74def89b75707ba7f0b6362753e2e50c091bc Mon Sep 17 00:00:00 2001 From: PPeregrino <125605570+PPeregrino@users.noreply.github.com> Date: Mon, 8 Dec 2025 12:46:06 -0300 Subject: [PATCH 5/6] =?UTF-8?q?Implementa=C3=A7=C3=A3o=20Issues=20#36=20e?= =?UTF-8?q?=20#37?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generate a password for new users and send a registration email. --- app/services/sigaa_import_service.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/services/sigaa_import_service.rb b/app/services/sigaa_import_service.rb index 093daa2446..ad82709c80 100644 --- a/app/services/sigaa_import_service.rb +++ b/app/services/sigaa_import_service.rb @@ -118,9 +118,16 @@ def process_participante_single(turma, p_data) user.nome = p_data['nome'] user.email = p_data['email'] + generated_password = nil + if is_new_user + generated_password = SecureRandom.hex(8) + user.password = generated_password + end + if user.save if is_new_user @results[:usuarios_created] += 1 + UserMailer.cadastro_email(user, generated_password).deliver_now else @results[:usuarios_updated] += 1 end From c42ae34f8533d02a07fc4fdb9b90bd20fd032978 Mon Sep 17 00:00:00 2001 From: PPeregrino <125605570+PPeregrino@users.noreply.github.com> Date: Mon, 8 Dec 2025 12:46:59 -0300 Subject: [PATCH 6/6] =?UTF-8?q?Implementa=C3=A7=C3=A3o=20Issues=20#36=20e?= =?UTF-8?q?=20#37?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/services/sigaa_import_service_test.rb | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/test/services/sigaa_import_service_test.rb b/test/services/sigaa_import_service_test.rb index 4a1a74737b..dd83ccecea 100644 --- a/test/services/sigaa_import_service_test.rb +++ b/test/services/sigaa_import_service_test.rb @@ -26,12 +26,14 @@ def teardown end test "importa turmas e usuarios com sucesso" do - service = SigaaImportService.new(@file_path) - result = service.process + assert_difference 'ActionMailer::Base.deliveries.size', 1 do + service = SigaaImportService.new(@file_path) + result = service.process - assert_empty result[:errors] - assert_equal 1, result[:turmas_created] - assert_equal 1, result[:usuarios_created] + assert_empty result[:errors] + assert_equal 1, result[:turmas_created] + assert_equal 1, result[:usuarios_created] + end turma = Turma.find_by(codigo: "TURMA123") assert_not_nil turma @@ -40,6 +42,7 @@ def teardown user = User.find_by(matricula: "2023001") assert_not_nil user assert_equal "João Silva", user.nome + assert user.authenticate(user.password) if user.respond_to?(:authenticate) # Optional verification if has_secure_password matricula = MatriculaTurma.find_by(turma: turma, user: user) assert_not_nil matricula