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 =
+ "
+
+
+ #{I18n.t("activerecord.attributes.institution.name")} |
+ #{I18n.t("activerecord.attributes.affiliation.start_date")} |
+ #{I18n.t("activerecord.attributes.affiliation.end_date")} |
+
+
+
+ #{body}
+
+
"
+ 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) }