diff --git a/Gemfile b/Gemfile index 87667cbb..89ac45fb 100644 --- a/Gemfile +++ b/Gemfile @@ -57,6 +57,8 @@ group :development, :test do gem 'brakeman', require: false # RSpec for more modern testing gem 'rspec-rails', '~> 5.0' + gem "roo", "~> 2.8" + gem "pry", "~> 0.14.2" end group :test do diff --git a/Gemfile.lock b/Gemfile.lock index e1cd2b09..ecbdaacd 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -75,6 +75,7 @@ GEM brakeman (4.7.0) builder (3.2.4) byebug (11.0.1) + coderay (1.1.3) concurrent-ruby (1.1.9) connection_pool (2.2.5) cookiejar (0.3.3) @@ -190,6 +191,9 @@ GEM request_store (~> 1.1) pdfkit (0.8.4.1) pg (0.21.0) + pry (0.14.2) + coderay (~> 1.1) + method_source (~> 1.0) public_suffix (4.0.6) puma (4.3.9) nio4r (~> 2.0) @@ -248,6 +252,9 @@ GEM actionpack (>= 5.0) railties (>= 5.0) rollbar (2.22.1) + roo (2.8.3) + nokogiri (~> 1) + rubyzip (>= 1.3.0, < 3.0.0) rspec-core (3.10.1) rspec-support (~> 3.10.0) rspec-expectations (3.10.1) @@ -265,6 +272,7 @@ GEM rspec-mocks (~> 3.10) rspec-support (~> 3.10) rspec-support (3.10.2) + rubyzip (2.3.2) rufus-scheduler (3.4.2) et-orbi (~> 1.0) sass (3.7.4) @@ -346,6 +354,7 @@ DEPENDENCIES paper_trail pdfkit pg + pry (~> 0.14.2) puma pundit (~> 2.1) pundit-matchers (~> 1.6) @@ -354,6 +363,7 @@ DEPENDENCIES rails-controller-testing render_anywhere rollbar + roo (~> 2.8) rspec-rails (~> 5.0) sass-rails (~> 5.0) shoulda-matchers diff --git a/scripts/evaluation_importer.rb b/scripts/evaluation_importer.rb new file mode 100644 index 00000000..b40de59a --- /dev/null +++ b/scripts/evaluation_importer.rb @@ -0,0 +1,44 @@ +class EvaluationImporter + + attr_reader :evaluation, :leader, :principle_data, :user_data, + :point_data, :comment_data, :members, :not_members + + def initialize(evaluation:, principles:, users:, points:, comments:) + @evaluation = evaluation + @leader = evaluation.group.leader.user + @principle_data = principles + @user_data = users + @point_data = points + @comment_data = comments + @members = evaluation.group.active_members.map(&:user) + @not_members = [] + end + + def self.call(evaluation:, principles:, users:, points:, comments:) + new(evaluation: evaluation, principles: principles, users: users, points: points, comments: comments).call + end + + def call + ActiveRecord::Base.transaction do + principles = principle_data.map do |attributes| + principle = Principle.new(attributes) + principle.evaluation = evaluation + principle.save! + principle + end + user_data.each.with_index do |user_name, row| + user = members.find { |member| member.full_name == user_name } + not_members << user and next unless user + point_request = PointRequest.create!(user: user, evaluation: evaluation) + + point_data[row].each.with_index do |point, col| + next unless point + principle = principles[col] + pd = PointDetail.create!(point_request: point_request, principle: principle, point: point) + comment = comment_data[row][col] + PointDetailComment.create!(point_detail: pd, comment: comment, user: leader) if comment + end + end + end + end +end \ No newline at end of file diff --git a/scripts/evaluation_xlsx_parser.rb b/scripts/evaluation_xlsx_parser.rb new file mode 100644 index 00000000..9109b787 --- /dev/null +++ b/scripts/evaluation_xlsx_parser.rb @@ -0,0 +1,71 @@ +require 'roo' + +class EvaluationXlsxParser + attr_reader :filename, :user_count, :responsibility_count, :work_count, :principle_count + + def initialize(filename:,user_count:, responsibility_count:, work_count:) + @filename = filename + @user_count = user_count + @responsibility_count = responsibility_count + @work_count = work_count + @principle_count = responsibility_count + work_count + end + + def principles + result = [] + sheet = Roo::Spreadsheet.open(filename).sheet(0) + principle_count.times.each do |index| + row = index + 2 # skip first line, indexing starts from 1 + result << { name: sheet.cell(row, 1), + max_per_member: sheet.cell(row, 2), + description: sheet.cell(row, 4), + type: index < responsibility_count ? 'RESPONSIBILITY' : 'WORK' + } + end + result + end + + def users + result = [] + sheet = Roo::Spreadsheet.open(filename).sheet(1) + user_count.times.each do |index| + row = index + 2 # skip first line, indexing starts from 1 + result << sheet.cell(row, 1) + end + result + end + + def points + result = [] + sheet = Roo::Spreadsheet.open(filename).sheet(1) + user_count.times.each do |row| + row += 2 + point_row = [] + principle_count.times.each do |col| + col += 2 + point_row << sheet.cell(row, col) + end + result << point_row + end + result + end + + def comments + result = [] + sheet = Roo::Spreadsheet.open(filename).sheet(1) + user_count.times.each do |row| + row += 2 + comment_row = [] + principle_count.times.each do |col| + col += 2 + comment_row << sheet.comment(row, col) + end + result << comment_row + end + result + end + + def results + {principles: principles, users: users, points: points, comments: comments} + end +end diff --git a/spec/scripts/evaluation_importer_spec.rb b/spec/scripts/evaluation_importer_spec.rb new file mode 100644 index 00000000..850e7f8f --- /dev/null +++ b/spec/scripts/evaluation_importer_spec.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +require 'rails_helper' +require './scripts/evaluation_importer' + +RSpec.describe EvaluationImporter do + + subject(:import) { EvaluationImporter.call(evaluation: evaluation, principles: principles, users: users, points: points, comments: comments) } + + let(:evaluation) { create(:evaluation) } + let(:leader) { create(:user, firstname: 'Karcsi', lastname: 'Körvez') } + let(:member) { create(:user, firstname: 'Tibor', lastname: 'Tag') } + let(:users) { [leader, member].map(&:full_name) } + let(:principles) do + [{ name: "Felelősség elv", description: "Felelős munka.", type: "RESPONSIBILITY", max_per_member: 20 }, + { name: "Munka elv", description: "Dolgozni kell.", type: "WORK", max_per_member: 30 }] + end + + let(:points) do + [[15, 10], [nil, 20]] + end + + let(:comments) do + [['Komment a körveznek', nil], [nil, 'Sokat dologzott']] + end + + before do + create(:membership, user: member, group: evaluation.group) + create(:membership, user: leader, group: evaluation.group) + end + + it 'creates principles' do + expect { import }.to change { Principle.count }.by(2) + principles.each do |principle_attributes| + expect(Principle.find_by(principle_attributes)).to be_present + end + end + + it 'creates point request' do + expect { import }.to change { PointRequest.count }.by(2) + end + + it 'creates points' do + expect { import }.to change { PointDetail.count }.by(3) + expect(PointDetail.joins(:point_request, :principle).find_by(point: 15, 'principles.name': 'Felelősség elv', 'point_requests.user_id': leader.id)).to be_present + expect(PointDetail.joins(:point_request, :principle).find_by(point: 10, 'principles.name': 'Munka elv', 'point_requests.user_id': leader.id)).to be_present + expect(PointDetail.joins(:point_request, :principle).find_by(point: 20, 'principles.name': 'Munka elv', 'point_requests.user_id': member.id)).to be_present + end + + it 'creates comments' do + expect { import }.to change { PointDetailComment.count}.by(2) + expect(PointDetailComment.joins(point_detail: :point_request).find_by(comment: 'Komment a körveznek', 'point_requests.user_id': leader.id)).to be_present + expect(PointDetailComment.joins(point_detail: :point_request).find_by(comment: 'Sokat dologzott', 'point_requests.user_id': member.id)).to be_present + end +end diff --git a/spec/scripts/evaluation_xlsx_parser_spec.rb b/spec/scripts/evaluation_xlsx_parser_spec.rb new file mode 100644 index 00000000..e2e24098 --- /dev/null +++ b/spec/scripts/evaluation_xlsx_parser_spec.rb @@ -0,0 +1,50 @@ +require 'rails_helper' +require './scripts/evaluation_xlsx_parser' + +RSpec.describe EvaluationXlsxParser do + subject(:parser) { EvaluationXlsxParser.new(filename: './spec/scripts/test_evaluation.xlsx', user_count: 4, + responsibility_count: 2, work_count: 2) } + + it 'reads the principles' do + principles = parser.principles + + expect(principles[0]).to include(name: "Körvezető", type: "RESPONSIBILITY", max_point: 20, + description: "Körvezető felelőssége.") + expect(principles[1]).to include(name: "Gazdaságis", type: "RESPONSIBILITY", max_point: 15, + description: "A kör gazdasági ügyeit intézte.") + expect(principles[2]).to include(name: "Projekt munka", type: "WORK", max_point: 30, + description: "A kör projekjein végzett munka.") + expect(principles[3]).to include(name: "Tanfolyam tartás", type: "WORK", max_point: 15, + description: "A kör tanfolyamainak megtartása.") + end + + it 'reads users' do + users = parser.users + + expect(users).to be_eql(["Körvezető Károly", "Gazdaságis Géza", "Projekező Pál", "Tanfolyam Tibor"]) + end + + it 'reads points' do + points = parser.points + + expect(points).to be_eql([[20, 5, 30, 15], + [nil, 15, 20, 5], + [nil, nil, 40, nil], + [nil, nil, 20, 15]]) + end + + it 'reads comments' do + comments = parser.comments + + expect(comments).to be_eql([["Vezette a kört", "Számlákat kezelte", "Sok projekten dolgozott", "5 tanfolyam alklamat tartott"], + [nil, "Kezelte a gazdaságis ügyeket", "Projektezett sokat", "1 tanfolyam alkalom"], + [nil, nil, "Mindent feladatot is megcsinált", nil], + [nil, nil, "Sokat dolgozott", "Megtartott 5 tanfolyamalkalmat"]]) + end + + it 'has results' do + results = parser.results + + expect(results).to be_present + end +end \ No newline at end of file diff --git a/spec/scripts/test_evaluation.xlsx b/spec/scripts/test_evaluation.xlsx new file mode 100644 index 00000000..905efe7d Binary files /dev/null and b/spec/scripts/test_evaluation.xlsx differ