diff --git a/Gemfile.lock b/Gemfile.lock index 1205bec6..e766582f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -469,6 +469,7 @@ GEM sprockets (>= 3.0.0) sqlite3 (1.6.8) mini_portile2 (~> 2.8.0) + sqlite3 (1.6.8-x86_64-linux) ssrf_filter (1.1.2) stringio (3.1.1) thor (1.3.1) @@ -503,6 +504,7 @@ GEM PLATFORMS ruby x86-mingw32 + x86_64-linux DEPENDENCIES active_scaffold! diff --git a/app/controllers/affiliation_controller.rb b/app/controllers/affiliation_controller.rb new file mode 100644 index 00000000..fcdeae67 --- /dev/null +++ b/app/controllers/affiliation_controller.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +class AffiliationController < ApplicationController + authorize_resource + + active_scaffold :affiliation do |config| + columns = [:professor, :institution, :start_date, :end_date] + + config.list.columns = columns + config.create.columns = columns + config.update.columns = columns + config.show.columns = columns + + config.columns[:professor].form_ui = :record_select + config.columns[:institution].form_ui = :record_select + config.columns[:start_date].form_ui = :date_picker + config.columns[:end_date].form_ui = :date_picker + end + record_select( + per_page: 10, + search_on: [:name], + order_by: "name", + full_text_search: true + ) +end diff --git a/app/controllers/concerns/shared_pdf_concern.rb b/app/controllers/concerns/shared_pdf_concern.rb index af78e2ce..718d9793 100644 --- a/app/controllers/concerns/shared_pdf_concern.rb +++ b/app/controllers/concerns/shared_pdf_concern.rb @@ -41,7 +41,7 @@ def render_enrollments_academic_transcript_pdf(enrollment, filename = "transcrip .order("course_classes.year", "course_classes.semester") accomplished_phases = enrollment.accomplishments.order(:conclusion_date) - + program_level = ProgramLevel.on_date(enrollment.thesis_defense_date)&.last&.level || "" render_to_string( template: "enrollments/academic_transcript_pdf", type: "application/pdf", @@ -51,6 +51,7 @@ def render_enrollments_academic_transcript_pdf(enrollment, filename = "transcrip enrollment: enrollment, class_enrollments: class_enrollments, accomplished_phases: accomplished_phases, + program_level: program_level } ) end diff --git a/app/controllers/enrollments_controller.rb b/app/controllers/enrollments_controller.rb index 8e4dcb7c..3b921f0b 100644 --- a/app/controllers/enrollments_controller.rb +++ b/app/controllers/enrollments_controller.rb @@ -215,6 +215,7 @@ def to_pdf def academic_transcript_pdf enrollment = Enrollment.find(params[:id]) + respond_to do |format| format.pdf do title = I18n.t("pdf_content.enrollment.academic_transcript.title") diff --git a/app/controllers/professors_controller.rb b/app/controllers/professors_controller.rb index e9901761..9997fad9 100644 --- a/app/controllers/professors_controller.rb +++ b/app/controllers/professors_controller.rb @@ -29,7 +29,6 @@ class ProfessorsController < ApplicationController config.columns[:civil_status].options = { options: [["Solteiro(a)", "solteiro"], ["Casado(a)", "casado"]] } - config.columns[:institution].form_ui = :record_select config.columns[:sex].form_ui = :select config.columns[:sex].options = { options: [["Masculino", "M"], ["Feminino", "F"]] } @@ -53,9 +52,9 @@ class ProfessorsController < ApplicationController :address, :zip_code, :telephone1, :telephone2, :cpf, :identity_expedition_date, :identity_issuing_body, :identity_issuing_place, :identity_number, :enrollment_number, - :siape, :institution, :scholarships, :academic_title_level, + :siape, :scholarships, :academic_title_level, :academic_title_institution, :academic_title_country, - :academic_title_date, :obs, :professor_research_areas, + :academic_title_date, :obs, :professor_research_areas, :affiliations ] config.create.columns = form_columns @@ -64,7 +63,7 @@ class ProfessorsController < ApplicationController config.show.columns = [ :name, :email, :cpf, :birthdate, :address, :birthdate, :civil_status, :identity_expedition_date, :identity_issuing_body, :identity_number, - :neighborhood, :sex, :enrollment_number, :siape, + :neighborhood, :sex, :enrollment_number, :siape, :institutions, :telephone1, :telephone2, :zip_code, :scholarships, :advisement_authorizations, :advisements_with_points, :academic_title_level, :academic_title_institution, diff --git a/app/controllers/program_levels_controller.rb b/app/controllers/program_levels_controller.rb new file mode 100644 index 00000000..73015d2b --- /dev/null +++ b/app/controllers/program_levels_controller.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +class ProgramLevelsController < ApplicationController + authorize_resource + + active_scaffold :program_level do |config| + config.create.columns = [:level, :start_date, :end_date] + config.update.columns = [:level, :start_date, :end_date] + config.show.columns = [:level, :start_date, :end_date] + config.list.columns = [:level, :start_date, :end_date] + + config.actions.swap :search, :field_search + config.columns.add :active + config.field_search.columns = [:active] + config.columns[:active].form_ui = :select + + config.actions.exclude :deleted_records + end + +end diff --git a/app/helpers/enrollments_helper.rb b/app/helpers/enrollments_helper.rb index efd9f976..665ca3f0 100644 --- a/app/helpers/enrollments_helper.rb +++ b/app/helpers/enrollments_helper.rb @@ -261,8 +261,9 @@ def enrollment_thesis_defense_committee_participations_show_column( render( partial: "enrollments/show_defense_committee_table", locals: { - thesis_defense_committee_professors: - record.thesis_defense_committee_professors + thesis_defense_committee_professors: record.thesis_defense_committee_professors, + thesis_defense_date: record.thesis_defense_date, + dismissal_date: record.dismissal.date } ) end diff --git a/app/helpers/enrollments_pdf_helper.rb b/app/helpers/enrollments_pdf_helper.rb index bd6f1b12..53bfc32d 100644 --- a/app/helpers/enrollments_pdf_helper.rb +++ b/app/helpers/enrollments_pdf_helper.rb @@ -132,12 +132,12 @@ def grades_report_header(pdf, options = {}) def enrollment_header(pdf, options = {}) enrollment ||= options[:enrollment] + program_level ||= options[:program_level] pdf.bounding_box([0, pdf.cursor - 3], width: 560) do pdf.font("FreeMono", size: 8) do pdf.line_width 0.5 - common_header_part1(pdf, enrollment, [ - "#{i18n_eht(:program_level)} #{CustomVariable.program_level} " + "#{i18n_eht(:program_level)} #{program_level}" ]) common_header_part(pdf) do @@ -615,9 +615,12 @@ def thesis_table(curr_pdf, options = {}) "#{I18n.t("pdf_content.enrollment.thesis.defense_committee")} " ]] thesis_desense_committee.each do |professor| + dismissal_date = enrollment.dismissal.date + date = thesis_defense_date || dismissal_date + affiliation = Affiliation.professor_date(professor, date&.to_date)&.last data_table_rows_defense_committee += [[ "#{professor.name} / #{rescue_blank_text( - professor.institution, method_call: :name + affiliation&.institution, method_call: :name )}" ]] end diff --git a/app/helpers/professors_helper.rb b/app/helpers/professors_helper.rb index bc2b9924..4d980e24 100644 --- a/app/helpers/professors_helper.rb +++ b/app/helpers/professors_helper.rb @@ -62,6 +62,38 @@ def professor_advisements_with_points_show_column(record, options) resp.html_safe end + def professor_institutions_show_column(record, options) + affiliations = record.affiliations + return "-" if affiliations.empty? + + body = "" + count = 0 + affiliations.each do |affiliation| + count += 1 + tr_class = count.even? ? "even-record" : "" + body += " + #{affiliation.institution.name} + #{affiliation.start_date} + #{affiliation.end_date} + " + end + + resp = + " + + + + + + + + + #{body} + +
#{I18n.t("activerecord.attributes.institution.name")}#{I18n.t("activerecord.attributes.affiliation.start_date")}#{I18n.t("activerecord.attributes.affiliation.end_date")}
" + resp.html_safe + end + def permit_rs_browse_params [:page, :update, :utf8] end diff --git a/app/models/ability.rb b/app/models/ability.rb index 6cc965b2..fe451919 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -50,7 +50,7 @@ class Ability CONFIGURATION_MODELS = [ User, Role, Version, Notification, EmailTemplate, Query, NotificationLog, CustomVariable, ReportConfiguration, - YearSemester + YearSemester, ProgramLevel ] def initialize(user) diff --git a/app/models/affiliation.rb b/app/models/affiliation.rb new file mode 100644 index 00000000..58885356 --- /dev/null +++ b/app/models/affiliation.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +class Affiliation < ApplicationRecord + has_paper_trail + + belongs_to :institution + belongs_to :professor + + validates :start_date, presence: true + validates :end_date, presence: false + validates_uniqueness_of :start_date, scope: [:professor_id], + allow_nil: true, allow_blank: true, + message: "A afiliação só pode ser iniciada em uma data por professor" + validate :uniqueness_end_date + + scope :on_date, ->(date) { where("DATE(start_date) <= ? AND (DATE(end_date) > ? OR end_date IS null)", date, date) } + scope :of_professor, ->(professor) { where(professor_id: professor.id) } + scope :professor_date, ->(professor, date) { of_professor(professor).on_date(date) } + scope :active, -> { where(end_date: nil) } + + private + def uniqueness_end_date + exists = Affiliation.where(professor_id: professor_id, end_date: end_date).where.not(id: id).exists? + if exists + errors.add(:end_date,"Apenas uma afiliação pode estar ativa por professor e só pode ter uma data de fim por professor") + end + exists + end + +end diff --git a/app/models/custom_variable.rb b/app/models/custom_variable.rb index 09277ac1..a7bb4d8c 100644 --- a/app/models/custom_variable.rb +++ b/app/models/custom_variable.rb @@ -12,7 +12,6 @@ class CustomVariable < ApplicationRecord VARIABLES = { "single_advisor_points" => :text, "multiple_advisor_points" => :text, - "program_level" => :text, "identity_issuing_country" => :text, "class_schedule_text" => :text, "redirect_email" => :text, @@ -43,11 +42,6 @@ def self.multiple_advisor_points config.blank? ? 0.5 : config.value.to_f end - def self.program_level - config = CustomVariable.find_by_variable(:program_level) - config.blank? ? nil : config.value.to_i - end - def self.identity_issuing_country config = CustomVariable.find_by_variable(:identity_issuing_country) config.blank? ? "" : config.value diff --git a/app/models/institution.rb b/app/models/institution.rb index e3bdc403..af46c041 100644 --- a/app/models/institution.rb +++ b/app/models/institution.rb @@ -8,7 +8,9 @@ class Institution < ApplicationRecord has_paper_trail has_many :majors, dependent: :restrict_with_exception - has_many :professors, dependent: :restrict_with_exception + has_many :affiliations + has_many :professors, through: :affiliations + validates :name, presence: true, uniqueness: true diff --git a/app/models/professor.rb b/app/models/professor.rb index de52ea61..23bf18a8 100644 --- a/app/models/professor.rb +++ b/app/models/professor.rb @@ -18,9 +18,11 @@ class Professor < ApplicationRecord dependent: :restrict_with_exception has_many :thesis_defense_committee_enrollments, source: :enrollment, through: :thesis_defense_committee_participations + has_many :affiliations, dependent: :destroy + has_many :institutions, through: :affiliations + accepts_nested_attributes_for :affiliations, allow_destroy: false, reject_if: :all_blank belongs_to :city, optional: true - belongs_to :institution, optional: true belongs_to :academic_title_country, optional: true, class_name: "Country", diff --git a/app/models/program_level.rb b/app/models/program_level.rb new file mode 100644 index 00000000..0701593b --- /dev/null +++ b/app/models/program_level.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class ProgramLevel < ApplicationRecord + has_paper_trail + + validates :level, presence: true, on: [:create, :update] + validates :start_date, presence: true, on: [:create, :update] + validates :end_date, presence: false + + scope :active, -> { where(end_date: nil) } + scope :on_date, -> (date) { where("program_levels.start_date <= ? AND (program_levels.end_date > ? OR program_levels.end_date is null)", date, date)} + +end diff --git a/app/views/enrollments/_show_defense_committee_table.html.erb b/app/views/enrollments/_show_defense_committee_table.html.erb index 37bd476b..49e3bd54 100644 --- a/app/views/enrollments/_show_defense_committee_table.html.erb +++ b/app/views/enrollments/_show_defense_committee_table.html.erb @@ -2,7 +2,7 @@ <%= I18n.t("activerecord.attributes.professor.name") %> - <%= I18n.t("activerecord.attributes.professor.institution") %> + <%= I18n.t("activerecord.attributes.professor.institution.one") %> @@ -10,9 +10,10 @@ <% thesis_defense_committee_professors.each do |professor| %> <% count += 1 %> <% tr_class = count.even? ? "even-record" : "" %> + <% date = thesis_defense_date || dismissal_date %> <%= professor.name %> - <%= rescue_blank_text(professor.institution, method_call: :name) %> + <%= rescue_blank_text(Affiliation.professor_date(professor, date&.to_date)&.last&.institution, method_call: :name) %> <% end %> diff --git a/app/views/enrollments/academic_transcript_pdf.pdf.prawn b/app/views/enrollments/academic_transcript_pdf.pdf.prawn index 8d1f849a..b3e70d23 100644 --- a/app/views/enrollments/academic_transcript_pdf.pdf.prawn +++ b/app/views/enrollments/academic_transcript_pdf.pdf.prawn @@ -15,7 +15,7 @@ new_document( ) do |pdf| enrollment_student_header(pdf, enrollment: @enrollment) - enrollment_header(pdf, enrollment: @enrollment) + enrollment_header(pdf, enrollment: @enrollment, program_level: @program_level) transcript_table(pdf, class_enrollments: @class_enrollments) diff --git a/app/views/student_enrollment/_show_dismissal.html.erb b/app/views/student_enrollment/_show_dismissal.html.erb index 1827af75..11ad812b 100644 --- a/app/views/student_enrollment/_show_dismissal.html.erb +++ b/app/views/student_enrollment/_show_dismissal.html.erb @@ -34,7 +34,8 @@ <% unless thesis_defense_committee_professors.empty? %>

<%= t "activerecord.attributes.enrollment.thesis_defense_committee_professors" %>

<%= render partial: "enrollments/show_defense_committee_table", locals: { - thesis_defense_committee_professors: thesis_defense_committee_professors + thesis_defense_committee_professors: thesis_defense_committee_professors, + thesis_defense_date: enrollment.thesis_defense_date, } %> <% end %> diff --git a/config/application.rb b/config/application.rb index 38ce92cc..37750697 100644 --- a/config/application.rb +++ b/config/application.rb @@ -35,9 +35,11 @@ class Application < Rails::Application # config.autoload_paths += %W(#{config.root}/extras) config.autoload_paths << "#{config.root}/lib" + # Only load the plugins named here, in the order given (default is alphabetical). # :all can be used as a placeholder for all plugins not explicitly named. # config.plugins = [ :exception_notification, :ssl_requirement, :all ] + config.active_record.yaml_column_permitted_classes = [Symbol, Date, Time] # Activate observers that should always be running. # config.active_record.observers = :cacher, :garbage_collector, :forum_observer diff --git a/config/locales/affiliation.pt-BR.yml b/config/locales/affiliation.pt-BR.yml new file mode 100644 index 00000000..f4a2db88 --- /dev/null +++ b/config/locales/affiliation.pt-BR.yml @@ -0,0 +1,17 @@ +# Copyright (c) Universidade Federal Fluminense (UFF). +# This file is part of SAPOS. Please, consult the license terms in the LICENSE file. + +pt-BR: + activerecord: + attributes: + affiliation: + institution: "Instituição" + professor: "Professor" + start_date: "Data de início" + end_date: "Data de fim" + active: "Ativo" + + models: + affiliation: + one: "Afiliação" + other: "Afiliações" \ No newline at end of file diff --git a/config/locales/institution.pt-BR.yml b/config/locales/institution.pt-BR.yml index 1cab52e2..b6fb5eda 100644 --- a/config/locales/institution.pt-BR.yml +++ b/config/locales/institution.pt-BR.yml @@ -8,6 +8,7 @@ pt-BR: code: "Sigla" majors: "Cursos" name: "Nome" + affiliations: "Afiliações" models: institution: diff --git a/config/locales/navigation.pt-BR.yml b/config/locales/navigation.pt-BR.yml index 1e493224..78cee103 100644 --- a/config/locales/navigation.pt-BR.yml +++ b/config/locales/navigation.pt-BR.yml @@ -87,6 +87,7 @@ pt-BR: notification_log: Notificações Enviadas custom_variable: Variáveis report_configuration: Configurações de Relatório + program_level: Conceito CAPES logout: label: 'Logout' diff --git a/config/locales/professor.pt-BR.yml b/config/locales/professor.pt-BR.yml index 7707c445..65f65bf4 100644 --- a/config/locales/professor.pt-BR.yml +++ b/config/locales/professor.pt-BR.yml @@ -21,7 +21,11 @@ pt-BR: identity_issuing_body: "Órgão Expeditor" identity_issuing_place: "Local de Expedição" identity_number: "Número da identidade" - institution: "Instituição" + affiliations: "Afiliações" + institution: + one: "Instituição" + other: "Instituições" + institutions: "Instituições" name: "Nome" neighborhood: "Bairro" professor_research_areas: "Áreas de Pesquisa" diff --git a/config/locales/program_level.pt-BR.yml b/config/locales/program_level.pt-BR.yml new file mode 100644 index 00000000..de822339 --- /dev/null +++ b/config/locales/program_level.pt-BR.yml @@ -0,0 +1,13 @@ +pt-BR: + activerecord: + attributes: + program_level: + active: Ativo? + level: Nível + start_date: Data de início + end_date: Data de fim + + models: + program_level: + one: Conceito CAPES + other: Conceito CAPES \ No newline at end of file diff --git a/config/navigation.rb b/config/navigation.rb index 71455181..fd4c8b48 100644 --- a/config/navigation.rb +++ b/config/navigation.rb @@ -250,6 +250,7 @@ def can_read?(*args) submenu.modelitem NotificationLog submenu.modelitem CustomVariable submenu.modelitem ReportConfiguration + submenu.modelitem ProgramLevel end mainhelper.item :logout, destroy_user_session_path diff --git a/config/routes.rb b/config/routes.rb index 14a0c2f9..6596aab0 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -160,6 +160,11 @@ end end + resources :affiliation do + concerns :active_scaffold + record_select_routes + end + resources :professors do concerns :active_scaffold record_select_routes @@ -235,6 +240,10 @@ concerns :active_scaffold end + resources :program_levels do + concerns :active_scaffold + end + resources :thesis_defense_committee_participations do concerns :active_scaffold record_select_routes diff --git a/db/migrate/20240524135850_create_affiliation.rb b/db/migrate/20240524135850_create_affiliation.rb new file mode 100644 index 00000000..609a0073 --- /dev/null +++ b/db/migrate/20240524135850_create_affiliation.rb @@ -0,0 +1,64 @@ +class CreateAffiliation < ActiveRecord::Migration[7.0] + def up + create_table :affiliations do |t| + t.belongs_to :professor, index: true + t.belongs_to :institution, index: true + t.datetime :start_date + t.datetime :end_date + + t.timestamps + end + Professor.where.not(institution_id: nil).each do |professor| + initial_start_date = Enrollment.joins(:thesis_defense_committee_participations). + where(thesis_defense_committee_participations: { professor: professor }).minimum(:thesis_defense_date) + + start_date = professor.updated_at + end_date = nil + institution_id = professor.institution_id + institutions = [] + affiliation = Affiliation.create( + professor: professor, + institution_id: institution_id, + start_date: start_date + ) + professor = professor.paper_trail.previous_version + while professor.present? + # A data final é a data inicial da instituição anterior + end_date = start_date + # A data inicial é quando o professor recebeu algum + start_date = professor.updated_at + if ((professor.institution_id != institution_id )&& ((end_date - start_date) > 1.month)) && (!professor.institution_id.nil?) + # Atualiza a data caso a mudança de instituição seja maior que 1 mes, tenha uma intuição não nula diferente da atual + institutions << { institution_id:, start_date:, end_date: } + institution_id = professor.institution_id + affiliation = Affiliation.create( + professor: professor, + institution_id: institution_id, + start_date: start_date, + end_date: end_date + ) + elsif professor.institution_id == institution_id || ((end_date - start_date) <= 1.month) + affiliation.update(start_date: start_date) + end + professor = professor.paper_trail.previous_version + end + if initial_start_date.nil? || initial_start_date >= start_date + affiliation.update(start_date: start_date - 1.month) + elsif + affiliation.update(start_date: initial_start_date - 1.month) + end + institutions << { institution_id:, start_date:, end_date: } + end + + remove_column :professors, :institution_id + end + def down + add_column :professors, :institution_id, :integer + add_index :professors, :institution_id + Professor.all.each do |p| + affiliation = Affiliation&.of_professor(p)&.where(end_date: nil)&.last + p.update(institution_id: affiliation&.institution_id) + end + drop_table :affiliations + end +end diff --git a/db/migrate/20240527174758_create_program_level.rb b/db/migrate/20240527174758_create_program_level.rb new file mode 100644 index 00000000..5b3bf578 --- /dev/null +++ b/db/migrate/20240527174758_create_program_level.rb @@ -0,0 +1,45 @@ +class CreateProgramLevel < ActiveRecord::Migration[7.0] + def up + create_table :program_levels do |t| + t.integer :level, null: false + t.datetime :start_date, null: false + t.datetime :end_date + + t.timestamps + end + CustomVariable.where(variable: "program_level").each do |pl| + level = pl.value + program_level = ProgramLevel.create( + level: pl.value, + start_date: pl.updated_at, + ) + pl = pl.paper_trail.previous_version + while pl.present? + if pl.value != level + end_date = program_level.start_date + start_date = pl.updated_at + level = pl.value + program_level = ProgramLevel.create( + level: level, + end_date: end_date, + start_date: start_date, + ) + else + start_date = pl.updated_at - 1.month + program_level.update(start_date: start_date) + end + pl = pl.paper_trail.previous_version + end + end + CustomVariable.where(variable: "program_level").destroy_all + end + def down + ProgramLevel.all&.where(end_date: nil)&.each do |pl| + CustomVariable.create( + variable: "program_level", + value: pl.level, + ) + end + drop_table :program_levels + end +end diff --git a/db/schema.rb b/db/schema.rb index 0821ea84..2b120c03 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -257,6 +257,17 @@ t.index ["professor_id"], name: "index_advisements_on_professor_id" end + create_table "affiliations", force: :cascade do |t| + t.integer "professor_id" + t.integer "institution_id" + t.datetime "start_date" + t.datetime "end_date" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["institution_id"], name: "index_affiliations_on_institution_id" + t.index ["professor_id"], name: "index_affiliations_on_professor_id" + end + create_table "allocations", force: :cascade do |t| t.string "day", limit: 255 t.string "room", limit: 255 @@ -761,7 +772,6 @@ t.string "siape", limit: 255 t.string "enrollment_number", limit: 255 t.string "identity_issuing_place", limit: 255 - t.integer "institution_id" t.string "email", limit: 255 t.date "academic_title_date" t.integer "academic_title_country_id" @@ -775,10 +785,17 @@ t.index ["city_id"], name: "index_professors_on_city_id" t.index ["cpf"], name: "index_professors_on_cpf" t.index ["email"], name: "index_professors_on_email" - t.index ["institution_id"], name: "index_professors_on_institution_id" t.index ["user_id"], name: "index_professors_on_user_id" end + create_table "program_levels", force: :cascade do |t| + t.integer "level", null: false + t.datetime "start_date", null: false + t.datetime "end_date" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "queries", force: :cascade do |t| t.string "name", limit: 255 t.text "sql" diff --git a/db/seeds.rb b/db/seeds.rb index 9f89bc0e..1b5d107f 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -16,7 +16,7 @@ CustomVariable.create([ { description: "Pontos para orientador único", variable: "single_advisor_points", value: "1.0" }, { description: "Pontos para orientador múltiplo", variable: "multiple_advisor_points", value: "0.5" }, - { description: "Nível do Programa na CAPES", variable: "program_level", value: "5" }, + { description: "País padrão de emissão da identidade", variable: "identity_issuing_country", value: "Brasil" }, { description: "Texto no final do quadro de horários", variable: "class_schedule_text", value: "Alunos interessados em cursar disciplinas de Tópicos Avançados devem consultar os respectivos professores antes da matrícula." }, { description: "E-mail de redirecionamento para as notificações", variable: "redirect_email", value: "" }, @@ -34,6 +34,7 @@ { description: "Professor logado no sistema pode lançar notas. O valor yes habilita turmas do semestre atual, yes_all_semesters habilita qualquer semestre.", variable: "professor_login_can_post_grades", value: "no" }, { description: "Periodo da Avaliação Quadrienal", variable: "quadrennial_period", value: "2021 - 2021" }, ]) +ProgramLevel.create([{ value: "5", start_date: Time.now, end_date: nil }]) ReportConfiguration.create([ { name: "Boletim", scale: 1, x: 0, y: 0, order: 1, diff --git a/spec/factories/factory_affiliation.rb b/spec/factories/factory_affiliation.rb new file mode 100644 index 00000000..1425f5b6 --- /dev/null +++ b/spec/factories/factory_affiliation.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :affiliation do + institution + professor + start_date { Time.now } + end_date { Time.now } + end +end diff --git a/spec/factories/factory_program_level.rb b/spec/factories/factory_program_level.rb new file mode 100644 index 00000000..cbc232de --- /dev/null +++ b/spec/factories/factory_program_level.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :program_level do + sequence(:level) + start_date { Time.now } + end_date { nil } + end +end diff --git a/spec/features/custom_variables_spec.rb b/spec/features/custom_variables_spec.rb index 0f26a8c3..7d8ac606 100644 --- a/spec/features/custom_variables_spec.rb +++ b/spec/features/custom_variables_spec.rb @@ -15,7 +15,6 @@ @destroy_all << @role_adm = FactoryBot.create(:role_administrador) @destroy_all << @user = create_confirmed_user(@role_adm) - @destroy_all << FactoryBot.create(:custom_variable, variable: "program_level", value: "5") @destroy_all << @record = FactoryBot.create(:custom_variable, variable: "single_advisor_points", value: "1.0") @destroy_all << FactoryBot.create(:custom_variable, variable: "minimum_grade_for_approval", value: "6.0") end @@ -42,7 +41,7 @@ end it "should sort the list by variable, asc" do - expect(page.all("tr td.variable-column").map(&:text)).to eq ["minimum_grade_for_approval", "program_level", "single_advisor_points"] + expect(page.all("tr td.variable-column").map(&:text)).to eq ["minimum_grade_for_approval", "single_advisor_points"] end end @@ -64,12 +63,12 @@ expect(page).to have_css("tr:nth-child(1) td.variable-column", text: "identity_issuing_country") # Remove inserted record - expect(page.all("tr td.variable-column").map(&:text)).to eq ["identity_issuing_country", "minimum_grade_for_approval", "program_level", "single_advisor_points"] + expect(page.all("tr td.variable-column").map(&:text)).to eq ["identity_issuing_country", "minimum_grade_for_approval", "single_advisor_points"] record = model.last accept_confirm { find("#as_#{plural_name}-destroy-#{record.id}-link").click } sleep(0.2) visit current_path - expect(page.all("tr td.variable-column").map(&:text)).to eq ["minimum_grade_for_approval", "program_level", "single_advisor_points"] + expect(page.all("tr td.variable-column").map(&:text)).to eq ["minimum_grade_for_approval", "single_advisor_points"] end it "should have a selection for variable options" do diff --git a/spec/features/enrollments_spec.rb b/spec/features/enrollments_spec.rb index 53e991b6..a76f7e3d 100644 --- a/spec/features/enrollments_spec.rb +++ b/spec/features/enrollments_spec.rb @@ -37,6 +37,8 @@ @destroy_all << FactoryBot.create(:phase_duration, level: @level1, phase: @phase2, deadline_months: 3, deadline_days: 0) @destroy_all << FactoryBot.create(:phase_duration, level: @level1, phase: @phase3, deadline_months: 3, deadline_days: 0) + @destroy_all << FactoryBot.create(:program_level) + @destroy_all << @enrollment1 = FactoryBot.create(:enrollment, enrollment_number: "M02", student: @student1, level: @level2, enrollment_status: @enrollment_status1, admission_date: 3.years.ago.at_beginning_of_month.to_date) @destroy_all << @enrollment2 = FactoryBot.create(:enrollment, enrollment_number: "M01", student: @student2, level: @level2, enrollment_status: @enrollment_status2) @destroy_all << @enrollment3 = FactoryBot.create(:enrollment, enrollment_number: "M03", student: @student3, level: @level1, enrollment_status: @enrollment_status1, research_area: @reasearch_area1) diff --git a/spec/features/student_enrollment_spec.rb b/spec/features/student_enrollment_spec.rb index db72a664..67e12e8f 100644 --- a/spec/features/student_enrollment_spec.rb +++ b/spec/features/student_enrollment_spec.rb @@ -5,7 +5,7 @@ require "spec_helper" -RSpec.describe "StudentEnrollment features", type: :feature do +RSpec.describe "StudentEnrollment features", type: :feature, js: true do let(:url_path) { "/pendencies" } before(:all) do @destroy_later = [] @@ -51,6 +51,12 @@ @destroy_all << @professor3 = FactoryBot.create(:professor, name: "Gi", cpf: "1") @destroy_all << @professor4 = FactoryBot.create(:professor, name: "Helena", cpf: "4") + @destroy_all << @institution = FactoryBot.create(:institution, name: "UFF") + + @destroy_all << @affiliation1 = FactoryBot.create(:affiliation, institution: @institution, professor: @professor1, end_date: nil) + @destroy_all << @affiliation2 = FactoryBot.create(:affiliation, institution: @institution, professor: @professor2, end_date: nil) + @destroy_all << @affiliation3 = FactoryBot.create(:affiliation, institution: @institution, professor: @professor3, end_date: nil) + @destroy_all << FactoryBot.create(:advisement_authorization, professor: @professor1, level: @level1) @destroy_all << FactoryBot.create(:advisement_authorization, professor: @professor1, level: @level2) @destroy_all << FactoryBot.create(:advisement_authorization, professor: @professor2, level: @level1) @@ -59,7 +65,10 @@ @destroy_all << FactoryBot.create(:advisement_authorization, professor: @professor3, level: @level2) @destroy_all << @student1 = FactoryBot.create(:student, name: "Ana") - @destroy_all << @enrollment1 = FactoryBot.create(:enrollment, enrollment_number: "M01", student: @student1, level: @level2, enrollment_status: @enrollment_status1, admission_date: 3.years.ago.at_beginning_of_month.to_date, research_area: @research_area1) + @destroy_all << @enrollment1 = FactoryBot.create(:enrollment, enrollment_number: "M01", student: @student1, + level: @level2, enrollment_status: @enrollment_status1, + admission_date: 3.years.ago.at_beginning_of_month.to_date, + research_area: @research_area1, thesis_defense_date: Time.now) @destroy_all << @enrollment2 = FactoryBot.create(:enrollment, enrollment_number: "M02", student: @student1, level: @level2, enrollment_status: @enrollment_status1) @destroy_all << @enrollment3 = FactoryBot.create(:enrollment, enrollment_number: "D01", student: @student1, level: @level1, enrollment_status: @enrollment_status1) @destroy_all << @enrollment4 = FactoryBot.create(:enrollment, enrollment_number: "D02", student: @student1, level: @level1, enrollment_status: @enrollment_status1) @@ -109,7 +118,7 @@ @destroy_all << FactoryBot.create(:deferral, deferral_type: @deferral_type2, enrollment: @enrollment1, approval_date: 15.months.ago.at_beginning_of_month) # Holds - @destroy_all << @record = FactoryBot.create(:enrollment_hold, enrollment: @enrollment1, year: 2.years.ago.year, semester: 2, number_of_semesters: 1) + @destroy_all << @record = FactoryBot.create(:enrollment_hold, enrollment: @enrollment1, year: 3.years.ago.year, semester: 2, number_of_semesters: 1) # Scholarships @destroy_all << @sponsor1 = FactoryBot.create(:sponsor, name: "CNPq") @@ -184,6 +193,7 @@ "Nome", "Instituição" ] expect(page.all("tbody tr").size).to eq 3 + expect(page).to have_content "UFF" end end @@ -459,9 +469,8 @@ it "should show the proper allocations" do # Two allocations in the same day - expect(page.all(".enroll-table tbody tr:nth-of-type(1) td.cell-segunda").map(&:text)).to eq [ - "11-13 14-16" - ] + expect(page.all(".enroll-table tbody tr:nth-of-type(1) td.cell-segunda").map(&:text)).to have_text "11-13" + expect(page.all(".enroll-table tbody tr:nth-of-type(1) td.cell-segunda").map(&:text)).to have_text "14-16" # No allocations for class expect(page.all(".enroll-table tbody tr:nth-of-type(2) td.cell-segunda").map(&:text)).to eq [ "*" diff --git a/spec/models/affiliation_spec.rb b/spec/models/affiliation_spec.rb new file mode 100644 index 00000000..8d1d7598 --- /dev/null +++ b/spec/models/affiliation_spec.rb @@ -0,0 +1,78 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe Affiliation, type: :model do + it { should be_able_to_be_destroyed } + it { should belong_to(:institution) } + it { should belong_to(:professor) } + let(:affiliation) { FactoryBot.create :affiliation } + + + subject { affiliation } + context "Validation" do + it { should be_valid } + it { should validate_presence_of(:start_date) } + context "Active" do + let(:professor) { FactoryBot.create :professor } + let(:affiliation_active) { FactoryBot.create :affiliation, professor: professor, start_date: Time.now, end_date: nil } + let(:affiliation_inactive) { FactoryBot.create :affiliation, + professor: professor, + start_date: Time.now + 1.day, + end_date: Time.now + 2.day} + let(:affiliation_teste_active) { FactoryBot.build :affiliation, professor: professor, start_date: Time.now + 2.day } + let(:affiliation_teste_inactive) { FactoryBot.build :affiliation, + professor: professor, + start_date: Time.now + 3.day, + end_date: Time.now + 4.day } + + it "When active, do not add new affiliation active" do + affiliation_active + aff = FactoryBot.build(:affiliation, professor: professor, end_date: nil) + expect(aff).to be_invalid + end + context "When inactive, you can add new affiliation active/inactive" do + before do + affiliation_inactive + end + it { expect(affiliation_teste_active).to be_valid } + it { expect(affiliation_teste_inactive).to be_valid } + end + it "when inactive, you can add multiple affiliation" do + affiliation_inactive + expect(affiliation_inactive).to be_valid + affiliation_teste_inactive.save! + expect(Affiliation.all.count).to be_eql(2) + end + end + context "Active e End Date" do + let(:affiliation_active) { FactoryBot.create :affiliation, end_date: nil } + let(:affiliation_inactive_valid) { FactoryBot.create :affiliation, end_date: Time.now } + let(:affiliation_inactive_invalid) { FactoryBot.build :affiliation, professor: affiliation_active.professor, end_date: nil } + context "When active, don't need end date" do + it { expect(affiliation_active).to be_valid } + end + context "When inactive, need an end date" do + before(:each) do + affiliation_active + end + it { expect(affiliation_inactive_valid).to be_valid } + it { expect(affiliation_inactive_invalid).to be_invalid } + end + end + end + + context "Scope" do + context "date_professor" do + let!(:professor) { FactoryBot.create :professor } + let!(:affiliation_active) { FactoryBot.create :affiliation, professor: professor, start_date: Time.now, end_date: nil } + let!(:affiliation_inactive) do + FactoryBot.create :affiliation, professor: professor, start_date: Time.now - 1.day, end_date: Time.now + end + + + it { expect(Affiliation.professor_date(professor, Time.now).last).to eq(affiliation_active) } + it { expect(Affiliation.professor_date(professor, Time.now - 1.days).last).to eq(affiliation_inactive) } + end + end +end diff --git a/spec/models/custom_variable_spec.rb b/spec/models/custom_variable_spec.rb index a954cb5a..1c7945b0 100644 --- a/spec/models/custom_variable_spec.rb +++ b/spec/models/custom_variable_spec.rb @@ -61,23 +61,6 @@ end end - context "program_level" do - it "should return nil when there is no variable defined" do - config = CustomVariable.find_by_variable(:program_level) - config.delete unless config.nil? - - expect(CustomVariable.program_level).to eq(nil) - end - - it "should return 5 when it is defined to 5" do - config = CustomVariable.find_by_variable(:program_level) - config.delete unless config.nil? - @destroy_later << CustomVariable.create(variable: :program_level, value: "5") - - expect(CustomVariable.program_level).to eq(5) - end - end - context "identity_issuing_country" do it "should return '' when there is no variable defined" do config = CustomVariable.find_by_variable(:identity_issuing_country) diff --git a/spec/models/institution_spec.rb b/spec/models/institution_spec.rb index 1c2b82ce..67b3e817 100644 --- a/spec/models/institution_spec.rb +++ b/spec/models/institution_spec.rb @@ -8,7 +8,8 @@ RSpec.describe Institution, type: :model do it { should be_able_to_be_destroyed } it { should have_many(:majors).dependent(:restrict_with_exception) } - it { should have_many(:professors).dependent(:restrict_with_exception) } + it { should have_many(:affiliations) } + it { should have_many(:professors).through(:affiliations) } let(:institution) { Institution.new(name: "instituicao") } subject { institution } diff --git a/spec/models/professor_spec.rb b/spec/models/professor_spec.rb index 44caffb3..f0bba25d 100644 --- a/spec/models/professor_spec.rb +++ b/spec/models/professor_spec.rb @@ -16,7 +16,8 @@ it { should have_many(:course_classes).dependent(:restrict_with_exception) } it { should have_many(:thesis_defense_committee_participations).dependent(:restrict_with_exception) } it { should have_many(:thesis_defense_committee_enrollments).source(:enrollment).through(:thesis_defense_committee_participations) } - + it { should have_many(:affiliations).dependent(:destroy) } + it { should have_many(:institutions).through(:affiliations) } before(:all) do @professor_role = FactoryBot.create :role_professor @destroy_later = [] @@ -35,13 +36,12 @@ name: "professor", email: "professor@ic.uff.br", enrollment_number: "P1", - ) + ) end subject { professor } describe "Validations" do it { should be_valid } it { should belong_to(:city).required(false) } - it { should belong_to(:institution).required(false) } it { should belong_to(:academic_title_country).required(false) } it { should belong_to(:academic_title_institution).required(false) } it { should belong_to(:academic_title_level).required(false) }