diff --git a/app/assets/javascripts/views/descriptive_exams/form.js b/app/assets/javascripts/views/descriptive_exams/form.js index 46f6ae9be..ef0cbc7f1 100644 --- a/app/assets/javascripts/views/descriptive_exams/form.js +++ b/app/assets/javascripts/views/descriptive_exams/form.js @@ -1,36 +1,35 @@ -$(function () { - 'use strict'; - - var $opinionType = $('#descriptive_exam_opinion_type'), - $discipline = $('#descriptive_exam_discipline_id'), - $step = $('#descriptive_exam_step_id'), - $classroom_id = $('#descriptive_exam_classroom_id'), - $disciplineContainer = $('[data-descriptive-exam-discipline-container]'), - $stepContainer = $('[data-descriptive-exam-step-container]'), +$(function() { + "use strict"; + + var $opinionType = $("#descriptive_exam_opinion_type"), + $discipline = $("#descriptive_exam_discipline_id"), + $step = $("#descriptive_exam_step_id"), + $classroom_id = $("#descriptive_exam_classroom_id"), + $disciplineContainer = $("[data-descriptive-exam-discipline-container]"), + $stepContainer = $("[data-descriptive-exam-step-container]"), should_clear_discipline = true, should_clear_step = true, - discipline_id = $discipline.val(), - view_btn = $('#view-btn'); + view_btn = $("#view-btn"); - if ($opinionType.data('elements').length === 2) { - $opinionType.attr('readonly', true) + if ($opinionType.data("elements").length === 2) { + $opinionType.attr("readonly", true); } - $classroom_id.on('change', async function () { + $classroom_id.on("change", async function() { await getOpinionType(); await getStep(); await getDisciplines(); - setFields() - }) + await setFields(); + }); async function getOpinionType() { - let classroom_id = $('#descriptive_exam_classroom_id').select2('val'); + let classroom_id = $("#descriptive_exam_classroom_id").select2("val"); if (!_.isEmpty(classroom_id)) { return $.ajax({ url: Routes.opinion_types_descriptive_exams_pt_br_path({ classroom_id: classroom_id, - format: 'json' + format: "json" }), success: handleFetchOpinionTypeByClassroomSuccess, error: handleFetchOpinionTypeByClassroomError @@ -40,109 +39,123 @@ $(function () { function handleFetchOpinionTypeByClassroomSuccess(data) { var opinion_type = $("#descriptive_exam_opinion_type"); - var first_opinion = data[0]['table'] + var first_opinion = data[0]["table"]; - opinion_type.select2('data', first_opinion); + opinion_type.select2("data", first_opinion); } function handleFetchOpinionTypeByClassroomError() { - flashMessages.error('Ocorreu um erro ao buscar o tipo de avaliação da turma.'); + flashMessages.error( + "Ocorreu um erro ao buscar o tipo de avaliação da turma." + ); } async function getStep() { - let classroom_id = $('#descriptive_exam_classroom_id').select2('val'); + let classroom_id = $("#descriptive_exam_classroom_id").select2("val"); $step.select2({ data: [] }); if (!_.isEmpty(classroom_id)) { return $.ajax({ url: Routes.find_step_number_by_classroom_descriptive_exams_pt_br_path({ classroom_id: classroom_id, - format: 'json' + format: "json" }), success: handleFetchStepByClassroomSuccess, - error: handleFetchStepByClassroomError, + error: handleFetchStepByClassroomError }); } } function handleFetchStepByClassroomSuccess(data) { if (data) { - let selectedSteps = data.map(function (step) { - return { id: step['id'], text: step['description'] }; + let selectedSteps = data.map(function(step) { + return { id: step["id"], text: step["description"] }; }); $step.select2({ data: selectedSteps }); // Define a primeira opção como selecionada por padrão - $step.val(selectedSteps[0].id).trigger('change'); + $step.val(selectedSteps[0].id).trigger("change"); } } function handleFetchStepByClassroomError() { - flashMessages.error('Ocorreu um erro ao buscar a etapa da turma.'); + flashMessages.error("Ocorreu um erro ao buscar a etapa da turma."); } async function getDisciplines() { - let classroom_id = $('#descriptive_exam_classroom_id').select2('val'); + let classroom_id = $("#descriptive_exam_classroom_id").select2("val"); if (!_.isEmpty($classroom_id.val())) { - $.ajax({ - url: Routes.by_classroom_disciplines_pt_br_path({ classroom_id: classroom_id, format: 'json' }), - success: handleFetchDisciplinesSuccess, - error: handleFetchDisciplinesError - }); + try { + const data = await $.ajax({ + url: Routes.by_classroom_disciplines_pt_br_path({ + classroom_id: classroom_id, + format: "json" + }) + }); + handleFetchDisciplinesSuccess(data); + } catch (error) { + handleFetchDisciplinesError(); + } } - }; + } function handleFetchDisciplinesSuccess(data) { if (data.disciplines.length == 0) { blockFields(); - flashMessages.error('Não existem disciplinas para a turma selecionada.'); + flashMessages.error("Não existem disciplinas para a turma selecionada."); return; } else { - var selectedDisciplines = data.disciplines.map(function (discipline) { - return { id: discipline.table.id, name: discipline.table.name, text: discipline.table.text }; + var selectedDisciplines = data.disciplines.map(function(discipline) { + return { + id: discipline.table.id, + name: discipline.table.name, + text: discipline.table.text + }; }); $discipline.select2({ data: selectedDisciplines }); - $discipline.val(selectedDisciplines[0].id).trigger('change'); + $discipline.val(selectedDisciplines[0].id).trigger("change"); } - }; + } function handleFetchDisciplinesError() { - flashMessages.error('Ocorreu um erro ao buscar as disciplinas da turma selecionada.'); - }; + flashMessages.error( + "Ocorreu um erro ao buscar as disciplinas da turma selecionada." + ); + } - function setFields() { + async function setFields() { var opinionType = $opinionType.val(); should_clear_discipline = true; should_clear_step = true; - $disciplineContainer.addClass('hidden'); - $stepContainer.addClass('hidden'); + $disciplineContainer.addClass("hidden"); + $stepContainer.addClass("hidden"); if ($.inArray(opinionType, ["2", "3", "5", "6"]) >= 0) { if ($.inArray(opinionType, ["2", "5"]) >= 0) { - $disciplineContainer.removeClass('hidden'); + $disciplineContainer.removeClass("hidden"); should_clear_discipline = false; } if ($.inArray(opinionType, ["2", "3"]) >= 0) { - $stepContainer.removeClass('hidden'); + $stepContainer.removeClass("hidden"); should_clear_step = false; } } else { - $opinionType.val(''); - $step.select2('val', ''); + $opinionType.val(""); + $step.select2("val", ""); } if (should_clear_discipline) { - $discipline.val(''); + $discipline.val(null).trigger("change"); } else { $discipline.val(discipline_id); } if (should_clear_step) { - $step.val(''); + $step.val(""); } } @@ -150,7 +163,7 @@ $(function () { let step_id = $step.val(), discipline_id = $discipline.val(), classroom_id = $classroom_id.val(), - opinion_type = $('#descriptive_exam_opinion_type').val(); + opinion_type = $("#descriptive_exam_opinion_type").val(); $.ajax({ url: Routes.find_descriptive_exams_pt_br_path({ @@ -158,32 +171,35 @@ $(function () { classroom_id: classroom_id, step_id: step_id, opinion_type: opinion_type, - format: 'json' + format: "json" }), - success: function (descriptive_exam_id) { + success: function(descriptive_exam_id) { if (descriptive_exam_id === null || !$.isNumeric(descriptive_exam_id)) { - view_btn.addClass('disabled'); - view_btn.attr('href', ''); + view_btn.addClass("disabled"); + view_btn.attr("href", ""); return; } - view_btn.removeClass('disabled'); - view_btn.attr('href', Routes.descriptive_exam_pt_br_path(descriptive_exam_id)) + view_btn.removeClass("disabled"); + view_btn.attr( + "href", + Routes.descriptive_exam_pt_br_path(descriptive_exam_id) + ); } }); } - $opinionType.on('change', function () { + $opinionType.on("change", function() { setFields(); validateExistingExams(); }); setFields(); - $step.on('change', function () { + $step.on("change", function() { validateExistingExams(); - }) + }); validateExistingExams(); }); diff --git a/app/assets/javascripts/views/pedagogical_trackings/index.js b/app/assets/javascripts/views/pedagogical_trackings/index.js index 742239f3b..0109c5630 100644 --- a/app/assets/javascripts/views/pedagogical_trackings/index.js +++ b/app/assets/javascripts/views/pedagogical_trackings/index.js @@ -162,8 +162,6 @@ $('#search_end_date').on('change', function(e){ }); var unity_id = $('#unity_id').val(); -var start_date = $('#start_date').val(); -var end_date = $('#end_date').val(); var step_start_date = $('#step_start_date').val(); var step_end_date = $('#step_end_date').val(); @@ -171,18 +169,6 @@ if (unity_id) { $('#search_unity_id').val(unity_id); } -if (start_date) { - $('#search_start_date').val(start_date); -} else { - $('#search_start_date').attr('placeholder', step_start_date) -} - -if (end_date) { - $('#search_end_date').val(end_date); -} else { - $('#search_end_date').attr('placeholder', step_end_date) -} - if (_.isEmpty($('#filter_frequency_operator').val())){ $('#filter_frequency_percentage').attr('readonly', true).val(''); } diff --git a/app/controllers/daily_frequencies_in_batchs_controller.rb b/app/controllers/daily_frequencies_in_batchs_controller.rb index 5c2137d66..4f1b970d9 100644 --- a/app/controllers/daily_frequencies_in_batchs_controller.rb +++ b/app/controllers/daily_frequencies_in_batchs_controller.rb @@ -234,13 +234,17 @@ def view_data student = student_enrollment[:student] student_ids << student.id type_of_teaching = student_enrollment[:student_enrollment_classroom].type_of_teaching + left_at = student_enrollment[:student_enrollment_classroom].left_at + joined_at = student_enrollment[:student_enrollment_classroom].joined_at next if student.blank? @students_list << student @students << { student: student, - type_of_teaching: type_of_teaching + type_of_teaching: type_of_teaching, + left_at: left_at, + joined_at: joined_at } end @@ -254,8 +258,8 @@ def view_data dependences = student_has_dependence(student_enrollments_ids, dates) inactives_on_date = students_inactive_on_range(enrollment_classrooms.map{|i| - i[:student_enrollment_classroom] - }, dates) + i[:student_enrollment_classroom] + }, dates) exempteds_from_discipline = student_exempted_from_discipline_in_range(student_enrollments_ids, dates) active_searchs = ActiveSearch.new.in_active_search_in_range(student_enrollments_ids, dates) diff --git a/app/controllers/daily_notes_controller.rb b/app/controllers/daily_notes_controller.rb index da1498a88..6d1a64e89 100644 --- a/app/controllers/daily_notes_controller.rb +++ b/app/controllers/daily_notes_controller.rb @@ -160,7 +160,7 @@ def reload_students_list set_enrollment_classrooms.each do |enrollment_classroom| student = enrollment_classroom[:student] student_enrollment_id = enrollment_classroom[:student_enrollment].id - note_student = create_or_select_daily_note_student(student) + note_student = @daily_note.students.find_or_initialize_by(student_id: student.id) note_student.active = @active.include?(enrollment_classroom[:student_enrollment_classroom].id) note_student.dependence = @dependencies[student_enrollment_id] ? true : false note_student.exempted = @exempted_from_avaliation.map(&:student_id).include?(student.id) ? true : false @@ -293,12 +293,4 @@ def students_exempted_from_avaliations(avaliation_id, student_ids) students_exempt_from_avaliation[exempt.student_id] << exempt.avaliation_id end end - - def create_or_select_daily_note_student(student) - if action_name.eql?('edit') || action_name.eql?('create') - @daily_note.students.find_or_initialize_by(student_id: student.id) - else - @daily_note.students.select{ |dns| dns.student_id.eql?(student.id) }.first - end - end end diff --git a/app/controllers/descriptive_exams_controller.rb b/app/controllers/descriptive_exams_controller.rb index 55741198e..ad1609f0d 100644 --- a/app/controllers/descriptive_exams_controller.rb +++ b/app/controllers/descriptive_exams_controller.rb @@ -10,11 +10,7 @@ def new ) select_options_by_user - select_opinion_types - - if @opinion_types&.first&.text != 'Avaliação padrão (regular)' - @descriptive_exam.discipline_id = current_user_discipline.id - end + validate_opinion_type unless current_user.current_role_is_admin_or_employee? classroom_id = @descriptive_exam.classroom_id @@ -38,7 +34,7 @@ def create redirect_to edit_descriptive_exam_path(@descriptive_exam) else select_options_by_user(@descriptive_exam.classroom_id) - select_opinion_types + validate_opinion_type render :new end @@ -67,7 +63,7 @@ def update else fetch_students select_options_by_user(@descriptive_exam.classroom_id) - select_opinion_types + validate_opinion_type render :edit end @@ -91,7 +87,7 @@ def find step_id = opinion_type_by_year?(params[:opinion_type]) ? nil : params[:step_id].to_i select_options_by_user(classroom_id) - select_opinion_types + validate_opinion_type descriptive_exam_id = DescriptiveExam.by_classroom_id(classroom_id) .by_discipline_id(discipline_id) @@ -107,7 +103,7 @@ def find def opinion_types select_options_by_user(params[:classroom_id]) - select_opinion_types + validate_opinion_type render json: @opinion_types.to_json end @@ -271,12 +267,16 @@ def select_options_by_user(classroom_id = nil) end end - def select_opinion_types + def validate_opinion_type if @exam_rules.blank? flash[:error] = t('descriptive_exams.new.exam_rule_not_found') redirect_to new_descriptive_exam_path && return end + if [OpinionTypes::BY_YEAR, OpinionTypes::BY_STEP].exclude?(@exam_rules.first.opinion_type) + @descriptive_exam.discipline_id = current_user_discipline.id + end + @opinion_types = [] descriptive_exam_opinion_type = @exam_rules.find(&:allow_descriptive_exam?)&.opinion_type diff --git a/app/controllers/exam_record_report_controller.rb b/app/controllers/exam_record_report_controller.rb index a9df534ee..3137481de 100644 --- a/app/controllers/exam_record_report_controller.rb +++ b/app/controllers/exam_record_report_controller.rb @@ -15,7 +15,7 @@ def form end def report -@exam_record_report_form = ExamRecordReportForm.new(resource_params) + @exam_record_report_form = ExamRecordReportForm.new(resource_params) set_school_calendars if @exam_record_report_form.valid? diff --git a/app/controllers/final_recovery_diary_records_controller.rb b/app/controllers/final_recovery_diary_records_controller.rb index 2654738d0..695783974 100644 --- a/app/controllers/final_recovery_diary_records_controller.rb +++ b/app/controllers/final_recovery_diary_records_controller.rb @@ -135,6 +135,7 @@ def fetch_recovery_diary_records_by_user .by_teacher_id(current_teacher.id) .by_classroom_id(@classrooms.map(&:id)) .by_discipline_id(@disciplines.map(&:id)) + .select('DISTINCT final_recovery_diary_records.*, recovery_diary_records.recorded_at') .ordered end @@ -220,7 +221,8 @@ def number_of_decimal_places test_setting = test_setting(classroom, schoool_calendar) if test_setting.nil? - redirect_to final_recovery_diary_records_path, alert: t('final_recovery_diary_records.new.not_exists_test_setting') + redirect_to final_recovery_diary_records_path, +alert: t('final_recovery_diary_records.new.not_exists_test_setting') else @number_of_decimal_places = test_setting.number_of_decimal_places end @@ -234,7 +236,8 @@ def set_options_by_user end def fetch_linked_by_teacher - @fetch_linked_by_teacher ||= TeacherClassroomAndDisciplineFetcher.fetch!(current_teacher.id, current_unity, current_school_year) + @fetch_linked_by_teacher ||= TeacherClassroomAndDisciplineFetcher.fetch!(current_teacher.id, current_unity, +current_school_year) @classrooms ||= @fetch_linked_by_teacher[:classrooms] @disciplines ||= @fetch_linked_by_teacher[:disciplines] end diff --git a/app/controllers/pedagogical_trackings_controller.rb b/app/controllers/pedagogical_trackings_controller.rb index 0be1dc52d..5193550b5 100644 --- a/app/controllers/pedagogical_trackings_controller.rb +++ b/app/controllers/pedagogical_trackings_controller.rb @@ -1,55 +1,38 @@ class PedagogicalTrackingsController < ApplicationController before_action :require_current_year before_action :minimum_year + before_action :set_default_date def index - if (last_refresh = MvwFrequencyBySchoolClassroomTeacher.first&.last_refresh || - MvwContentRecordBySchoolClassroomTeacher.first&.last_refresh) - - @updated_at = last_refresh.to_date.strftime('%d/%m/%Y') - @updated_at_hour = last_refresh.hour - end - - employee_unity = employee_unities.first.id if employee_unities.presence&.one? - unity_id = params.dig(:search, :unity_id).presence || params[:unity_id] || employee_unity - - @start_date = params.dig(:search, :start_date).presence - start_date = (@start_date || params[:start_date]).try(:to_date) - - @end_date = params.dig(:search, :end_date).presence - end_date = (@end_date || params[:end_date]).try(:to_date) - - fetch_school_days_by_unity(unity_id, start_date, end_date) - - @school_days = @school_days_by_unity.values - .max_by { |school_days_by_unity| - school_days_by_unity[:school_days] - }[:school_days] - @school_frequency_done_percentage = school_frequency_done_percentage - @school_content_record_done_percentage = school_content_record_done_percentage - @unknown_teachers = school_unknown_teacher_frequency_done_percentage - @partial = :schools - - @percents = if unity_id - @partial = :classrooms - @classrooms = Classroom.where(unity_id: unity_id, year: current_user_school_year).ordered - - paginate(filter_from_params(percents(@classrooms.pluck(:id)), params.dig(:filter))) - else - paginate(filter_from_params(percents, params.dig(:filter))) - end - end - - def recalculate - - school_calendars = SchoolCalendar.ids + calculator = PedagogicalTrackingCalculator.new( + entity: @current_entity, + year: current_user_school_year, + current_user: current_user, + params: params, + employee_unities: employee_unities + ) - school_calendars.each do |school_calendar_id| + data = calculator.calculate_index_data - SchoolDaysCounterWorker.perform_async(@current_entity.id, school_calendar_id) + if data[:updated_at] + @updated_at = data[:updated_at][:date] + @updated_at_hour = data[:updated_at][:hour] end - redirect_to pedagogical_trackings_path + @school_days = data[:school_days] + @school_frequency_done_percentage = data[:school_frequency_done_percentage] + @school_content_record_done_percentage = data[:school_content_record_done_percentage] + @unknown_teachers = data[:unknown_teachers] + @percents = data[:percents] + @start_date = data[:start_date] + @end_date = data[:end_date] + + if data[:unity_id] + @partial = :classrooms + @classrooms = Classroom.where(unity_id: data[:unity_id], year: current_user_school_year).ordered + else + @partial = :schools + end end def teachers @@ -59,27 +42,26 @@ def teachers start_date = params[:start_date].try(:to_date) end_date = params[:end_date].try(:to_date) - fetch_school_days_by_unity(unity_id, start_date, end_date) - - teachers_ids = [teacher_id].compact.presence || - Teacher.by_classroom(classroom_id).by_year(current_user_school_year).pluck(:id).uniq - - @teacher_percents = [] - - teachers_ids.each do |teacher_id| - @teacher_percents << percents([params[:classroom_id]], teacher_id) - end - - @teacher_percents = @teacher_percents.flatten - - filter_params = params.slice( - :frequency_operator, - :frequency_percentage, - :content_record_operator, - :content_record_percentage + calculator = PedagogicalTrackingCalculator.new( + entity: @current_entity, + year: current_user_school_year, + current_user: current_user, + params: params ) - @teacher_percents = filter_from_params(@teacher_percents, filter_params) + @teacher_percents = calculator.calculate_teachers_data( + unity_id: unity_id, + classroom_id: classroom_id, + teacher_id: teacher_id, + start_date: start_date, + end_date: end_date, + filter_params: params.slice( + :frequency_operator, + :frequency_percentage, + :content_record_operator, + :content_record_percentage + ) + ) respond_with @teacher_percents end @@ -90,7 +72,6 @@ def minimum_year return if current_user_school_year >= 2020 flash[:alert] = t('pedagogical_trackings.minimum_year.error') - redirect_to root_path end @@ -110,255 +91,8 @@ def all_unities end helper_method :all_unities - def unities_total - @unities_total ||= @school_days_by_unity.size - end - - def fetch_school_days_by_unity(unity_id, start_date, end_date) - unity = Unity.find(unity_id) if unity_id - unities = unity || employee_unities || all_unities - - @school_days_by_unity = SchoolDaysCounterService.new( - unities: unities, - all_unities_size: all_unities.size, - start_date: start_date, - end_date: end_date, - year: current_user_school_year - ).school_days - end - - def school_frequency_done_percentage - percentage_sum = 0 - - @school_days_by_unity.each do |unity_id, school_days| - percentage_sum += frequency_done_percentage( - unity_id, - school_days[:start_date], - school_days[:end_date], - school_days[:school_days] - ) - end - - return 0 if unities_total.zero? - - (percentage_sum.to_f / unities_total).round(2) - end - - def school_unknown_teacher_frequency_done_percentage - unknown_teacher_percentage_sum = 0 - - @school_days_by_unity.each do |unity_id, school_days| - unknown_teacher_percentage_sum += unknown_teacher_frequency_done( - unity_id, - school_days[:start_date], - school_days[:end_date], - school_days[:school_days] - ) - end - - return 0 if unities_total.zero? - - (unknown_teacher_percentage_sum.to_f / unities_total).round(2) - end - - def school_content_record_done_percentage - percentage_sum = 0 - - @school_days_by_unity.each do |unity_id, school_days| - percentage_sum += content_record_done_percentage( - unity_id, - school_days[:start_date], - school_days[:end_date], - school_days[:school_days] - ) - end - - return 0 if unities_total.zero? - - (percentage_sum.to_f / unities_total).round(2) - end - - def frequency_done_percentage( - unity_id, - start_date, - end_date, - school_days, - classroom_id = nil, - teacher_id = nil - ) - @done_frequencies = MvwFrequencyBySchoolClassroomTeacher.by_unity_id(unity_id) - .by_date_between(start_date, end_date) - @done_frequencies = @done_frequencies.by_classroom_id(classroom_id) if classroom_id - @done_frequencies = @done_frequencies.by_teacher_id(teacher_id) if teacher_id - @done_frequencies = @done_frequencies.group_by(&:frequency_date).size - - ((@done_frequencies * 100).to_f / school_days).round(2) - end - - def content_record_done_percentage( - unity_id, - start_date, - end_date, - school_days, - classroom_id = nil, - teacher_id = nil - ) - @done_content_records = MvwContentRecordBySchoolClassroomTeacher.by_unity_id(unity_id) - .by_date_between(start_date, end_date) - @done_content_records = @done_content_records.by_classroom_id(classroom_id) if classroom_id - @done_content_records = @done_content_records.by_teacher_id(teacher_id) if teacher_id - @done_content_records = @done_content_records.group_by(&:record_date).size - - ((@done_content_records * 100).to_f / school_days).round(2) - end - - def percents(classrooms_ids = nil, teacher_id = nil) - percents = [] - - @school_days_by_unity.each do |unity_id, school_days| - unity = Unity.find(unity_id) - - if classrooms_ids.present? - classrooms_ids.each do |classroom_id| - percents << build_percent_table( - unity, - school_days[:start_date], - school_days[:end_date], - school_days[:school_days], - classroom_id, - teacher_id - ) - end - else - percents << build_percent_table( - unity, - school_days[:start_date], - school_days[:end_date], - school_days[:school_days] - ) - end - end - - percents - end - - def build_percent_table(unity, start_date, end_date, school_days, classroom_id = nil, teacher_id = nil) - frequency_percentage = frequency_done_percentage( - unity.id, - start_date, - end_date, - school_days, - classroom_id, - teacher_id - ) - content_record_percentage = content_record_done_percentage( - unity.id, - start_date, - end_date, - school_days, - classroom_id, - teacher_id - ) - - if classroom_id - classroom = Classroom.find(classroom_id) - - if teacher_id.blank? - OpenStruct.new( - unity_id: unity.id, - unity_name: unity.name, - classroom_id: classroom.id, - start_date: start_date, - end_date: end_date, - classroom_description: classroom.description, - frequency_percentage: frequency_percentage, - content_record_percentage: content_record_percentage - ) - else - teacher = Teacher.find(teacher_id) - - OpenStruct.new( - teacher_id: teacher_id, - start_date: start_date, - end_date: end_date, - teacher_name: teacher.name, - frequency_percentage: frequency_percentage, - content_record_percentage: content_record_percentage, - frequency_days: @done_frequencies, - content_record_days: @done_content_records - ) - end - else - OpenStruct.new( - unity_id: unity.id, - unity_name: unity.name, - start_date: start_date, - end_date: end_date, - frequency_percentage: frequency_percentage, - content_record_percentage: content_record_percentage - ) - end - end - - def filter_from_params(percents, params) - return percents if params.blank? - - params.delete_if do |_filter, value| - value.blank? - end - - params.each do |filter, value| - next if ['frequency_percentage', 'content_record_percentage'].include?(filter) - - percents = percents.select { |school_percent| - if ['unity_id', 'classroom_id'].include?(filter) - school_percent.send(filter).to_i == value.to_i - elsif filter == 'frequency_operator' - compare( - school_percent.send(:frequency_percentage).to_f, - value, - params[:frequency_percentage].to_f - ) - else - compare( - school_percent.send(:content_record_percentage).to_f, - value, - params[:content_record_percentage].to_f - ) - end - } - end - - percents - end - - def compare(percent, with, value) - case with - when ComparativeOperators::EQUALS - percent == value - when ComparativeOperators::GREATER_THAN - percent > value - when ComparativeOperators::LESS_THAN - percent < value - when ComparativeOperators::GREATER_THAN_OR_EQUAL_TO - percent >= value - when ComparativeOperators::LESS_THAN_OR_EQUAL_TO - percent <= value - end - end - - def paginate(array) - Kaminari.paginate_array(array).page(params[:page]).per(10) - end - - def unknown_teacher_frequency_done(unity_id, start_date, end_date, school_days) - done_frequencies = DailyFrequency.joins(classroom: :unity) - .by_unity_id(unity_id) - .by_frequency_date_between(start_date, end_date) - .where('EXTRACT(YEAR FROM frequency_date) = ?', current_user_school_year) - .where(owner_teacher_id: nil) - .group_by(&:frequency_date).size - - ((done_frequencies * 100).to_f / school_days).round(2) + def set_default_date + @start_date = (params[:start_date] ||= current_school_calendar.first_day) + @end_date = (params[:end_date] ||= current_school_calendar.last_day) end -end +end \ No newline at end of file diff --git a/app/controllers/school_term_recovery_diary_records_controller.rb b/app/controllers/school_term_recovery_diary_records_controller.rb index 9d6cfbd29..fa95a43ae 100644 --- a/app/controllers/school_term_recovery_diary_records_controller.rb +++ b/app/controllers/school_term_recovery_diary_records_controller.rb @@ -232,27 +232,30 @@ def fetch_student_enrollment_classrooms recovery_diary_record = @school_term_recovery_diary_record.recovery_diary_record return unless recovery_diary_record.recorded_at - students = StudentEnrollmentClassroomsRetriever.call( + @student_enrollment_classroom ||= StudentEnrollmentClassroomsRetriever.call( classrooms: recovery_diary_record.classroom, disciplines: recovery_diary_record.discipline, score_type: StudentEnrollmentScoreTypeFilters::NUMERIC, date: recovery_diary_record.recorded_at, search_type: :by_date ) - - date = @school_term_recovery_diary_record.recovery_diary_record.recorded_at - - students.select do |student| - student[:student_enrollment_classroom].left_at.blank? || student[:student_enrollment_classroom].left_at.to_date >= date - end end def reload_students_list recovery_diary_record = @school_term_recovery_diary_record.recovery_diary_record - return unless recovery_diary_record.recorded_at + + test_date = recovery_diary_record.recorded_at + + return unless test_date + + student_enrollment_ids = fetch_student_enrollment_classrooms.map { |sec| sec[:student_enrollment].id } + @active = ActiveStudentsOnDate.call(student_enrollments: student_enrollment_ids, date: test_date) + @students = [] @students = fetch_student_enrollment_classrooms.map do |student| - recovery_diary_record.students.find_or_initialize_by(student: student[:student]) + note_student = recovery_diary_record.students.find_or_initialize_by(student: student[:student]) + note_student.active = @active.include?(student[:student_enrollment_classroom].id) + note_student end end diff --git a/app/helpers/daily_frequencies_in_batchs_helper.rb b/app/helpers/daily_frequencies_in_batchs_helper.rb index 5dd5ebf69..646ca99ba 100644 --- a/app/helpers/daily_frequencies_in_batchs_helper.rb +++ b/app/helpers/daily_frequencies_in_batchs_helper.rb @@ -2,23 +2,30 @@ module DailyFrequenciesInBatchsHelper def data_additional(date, student) additional_class = nil tooltip = nil + student_id = student[:student][:id] - @additional_data.each do |additional_data| - if additional_data[:date] == date[:date] && additional_data[:student_id] == student[:student][:id] - additional_class = additional_data[:additional_class] - tooltip = additional_data[:tooltip] + @additional_data.each do |addit_data| + if addit_data[:date] == date[:date] && addit_data[:student_id] == student_id + additional_class = addit_data[:additional_class] + tooltip = addit_data[:tooltip] end end + if tooltip == 'Não enturmado' && student[:left_at].blank? && date[:date] >= student[:joined_at].to_date + additional_class = nil + tooltip = nil + end + { response_class: additional_class, response_tooltip: tooltip } end - def custom_student_name(student) + def custom_student_name(student, dates) student_name = student[:student][:name] color = false + has_enrolled = dates.pluck(:date).any? {|date| date > student[:joined_at].to_date } @additional_data.each do |additional_data| if additional_data[:student_id] == student[:student][:id] @@ -27,6 +34,11 @@ def custom_student_name(student) end end + if color == '#a90329' && student[:left_at].blank? && has_enrolled + student_name = student[:student][:name] + color = false + end + { name: student_name, color: color diff --git a/app/models/mvw_content_record_by_school_classroom_teacher.rb b/app/models/mvw_content_record_by_school_classroom_teacher.rb index aff9b90a1..d3dc16a84 100644 --- a/app/models/mvw_content_record_by_school_classroom_teacher.rb +++ b/app/models/mvw_content_record_by_school_classroom_teacher.rb @@ -7,5 +7,5 @@ class MvwContentRecordBySchoolClassroomTeacher < ApplicationRecord scope :by_unity_id, ->(unity_id) { where(unity_id: unity_id) } scope :by_teacher_id, ->(teacher_id) { where(teacher_id: teacher_id) } scope :by_classroom_id, ->(classroom_id) { where(classroom_id: classroom_id) } - scope :by_date_between, ->(start_date, end_date) { where(record_date: (start_date.to_date..end_date.to_date)) } + scope :by_date_between, ->(start_date, end_date) { where(record_date: (start_date.to_date..end_date.to_date)) if start_date.present? && end_date.present? } end diff --git a/app/models/mvw_frequency_by_school_classroom_teacher.rb b/app/models/mvw_frequency_by_school_classroom_teacher.rb index 7654c88d9..31fce989c 100644 --- a/app/models/mvw_frequency_by_school_classroom_teacher.rb +++ b/app/models/mvw_frequency_by_school_classroom_teacher.rb @@ -7,5 +7,5 @@ class MvwFrequencyBySchoolClassroomTeacher < ApplicationRecord scope :by_unity_id, ->(unity_id) { where(unity_id: unity_id) } scope :by_teacher_id, ->(teacher_id) { where(teacher_id: teacher_id) } scope :by_classroom_id, ->(classroom_id) { where(classroom_id: classroom_id) } - scope :by_date_between, ->(start_date, end_date) { where(frequency_date: (start_date.to_date..end_date.to_date)) } + scope :by_date_between, ->(start_date, end_date) { where(frequency_date: (start_date.to_date..end_date.to_date)) if start_date.present? && end_date.present? } end diff --git a/app/presenters/recovery_diary_record_student_presenter.rb b/app/presenters/recovery_diary_record_student_presenter.rb index 47eb62cfa..8948b1a90 100644 --- a/app/presenters/recovery_diary_record_student_presenter.rb +++ b/app/presenters/recovery_diary_record_student_presenter.rb @@ -4,7 +4,7 @@ def student_name_class if exempted_from_discipline name_class += 'exempted-student-from-discipline' - elsif active.present? && !active + elsif !active name_class += 'inactive-student' elsif dependence.present? && dependence name_class += 'dependence-student' @@ -16,7 +16,7 @@ def student_name_class def student_name if exempted_from_discipline "****#{student}" - elsif active.present? && !active + elsif !active "***#{student}" elsif dependence.present? && dependence "*#{student}" diff --git a/app/reports/exam_record_report.rb b/app/reports/exam_record_report.rb index 0c66405d3..a8e543f78 100644 --- a/app/reports/exam_record_report.rb +++ b/app/reports/exam_record_report.rb @@ -173,8 +173,10 @@ def daily_notes_table @info_students.each do |info_students| student = info_students[:student] student_enrollment = info_students[:student_enrollment] + student_enrollment_classroom = info_students[:student_enrollment_classroom] exempted_from_discipline = student_enrollments_exempts[student_enrollment.id] in_active_search = ActiveSearch.new.in_active_search?(student_enrollment.id, exam.test_date) + student_classroom_left_at = student_enrollment_classroom.left_at daily_note_student = nil if exempted_from_discipline || (avaliation_id.present? && exempted_avaliation?(student.id, avaliation_id)) @@ -204,6 +206,10 @@ def daily_notes_table school_term_recovery_scores[student_enrollment.id] = recovery_student.try(:score) end + if score.nil? && student_classroom_left_at != "" && student_classroom_left_at.to_date <= exam.test_date + score = set_student_score(exam, student, NullDailyNoteStudent.new, student_enrollment, daily_note_student) + end + self.any_student_with_dependence = any_student_with_dependence || student_has_dependence?(student_enrollment, exam.discipline_id) (students[student_enrollment.id] ||= {})[:name] = student.to_s @@ -397,7 +403,7 @@ def collect_exams_and_complementary_exams def student_transferred?(note_student) return note_student unless note_student.transfer_note_id - return note_student if note_student.note? + return note_student if note_student.note? || note_student.note == 0.0 nil end diff --git a/app/services/pedagogical_tracking_calculator.rb b/app/services/pedagogical_tracking_calculator.rb new file mode 100644 index 000000000..37ca24882 --- /dev/null +++ b/app/services/pedagogical_tracking_calculator.rb @@ -0,0 +1,373 @@ +# app/services/pedagogical_tracking_calculator.rb +class PedagogicalTrackingCalculator + def initialize(entity:, year:, current_user:, params:, employee_unities: nil) + @entity = entity + @year = year + @current_user = current_user + @params = params + @employee_unities = employee_unities + end + + def calculate_index_data + unity_id = extract_unity_id + start_date, end_date = extract_date_range + + fetch_school_days_by_unity(unity_id, start_date, end_date) + + # Pré-carregar os dados de frequências, conteúdos e frequências com professor desconhecido + preload_frequencies_and_contents(start_date, end_date, unity_id ? [unity_id] : nil) + + school_days = @school_days_by_unity.values + .max_by { |data| data[:school_days] }[:school_days] + + percentages = calculate_all_percentages + percents = fetch_percents(unity_id, start_date, end_date) + + { + updated_at: updated_at_data, + school_days: school_days, + school_frequency_done_percentage: percentages[:frequency_done_percentage], + school_content_record_done_percentage: percentages[:content_record_percentage], + unknown_teachers: percentages[:unknown_teacher_percentage], + unity_id: unity_id, + percents: percents, + start_date: start_date, + end_date: end_date + } + end + + def calculate_teachers_data(unity_id:, classroom_id:, teacher_id:, start_date:, end_date:, filter_params:) + fetch_school_days_by_unity(unity_id, start_date, end_date) + preload_frequencies_and_contents(start_date, end_date, [unity_id].compact) + + teachers_ids = teachers_for(classroom_id, teacher_id) + teacher_percents = calculate_teacher_percents(classroom_id, teachers_ids, filter_params) + + teacher_percents + end + + private + + def extract_unity_id + employee_unity = @employee_unities.first.id if @employee_unities.presence&.one? + @params.dig(:search, :unity_id).presence || @params[:unity_id] || employee_unity + end + + def extract_date_range + start_date = (@params.dig(:search, :start_date).presence || @params[:start_date]).try(:to_date) + end_date = (@params.dig(:search, :end_date).presence || @params[:end_date]).try(:to_date) + [start_date, end_date] + end + + def updated_at_data + last_refresh = MvwFrequencyBySchoolClassroomTeacher.first&.last_refresh || + MvwContentRecordBySchoolClassroomTeacher.first&.last_refresh + + return unless last_refresh + + { + date: last_refresh.to_date.strftime('%d/%m/%Y'), + hour: last_refresh.hour + } + end + + def fetch_school_days_by_unity(unity_id, start_date, end_date) + unity = Unity.find(unity_id) if unity_id + unities = unity || @employee_unities || all_unities + + now = Time.current + midnight = now.end_of_day + expires_in = (midnight - now).to_i + + @school_days_by_unity = + SchoolDaysCounterService.new( + unities: unities, + all_unities_size: all_unities.size, + start_date: start_date, + end_date: end_date, + year: @year + ).school_days + end + + def all_unities + @all_unities ||= Unity.joins(:school_calendars) + .where(school_calendars: { year: @year }) + .ordered + end + + def unities_total + @unities_total ||= @school_days_by_unity.size + end + + def preload_frequencies_and_contents(start_date, end_date, specific_unities = nil) + unity_ids = specific_unities || @school_days_by_unity.keys + + @frequencies_by_unity = load_frequencies_by_unity(unity_ids, start_date, end_date) + @contents_by_unity = load_contents_by_unity(unity_ids, start_date, end_date) + @unknown_frequencies_by_unity = load_unknown_frequencies_by_unity(unity_ids, start_date, end_date) + end + + def load_frequencies_by_unity(unity_ids, start_date, end_date) + records = MvwFrequencyBySchoolClassroomTeacher + .by_unity_id(unity_ids) + .by_date_between(start_date, end_date) + .distinct + .pluck(:unity_id, :classroom_id, :teacher_id, :frequency_date) + + frequencies_hash = Hash.new { |h, k| h[k] = [] } + + records.each do |u_id, c_id, t_id, f_date| + frequencies_hash[u_id] << [c_id, t_id, f_date] + end + + frequencies_hash + end + + def load_contents_by_unity(unity_ids, start_date, end_date) + records = MvwContentRecordBySchoolClassroomTeacher + .by_unity_id(unity_ids) + .by_date_between(start_date, end_date) + .distinct + .pluck(:unity_id, :classroom_id, :teacher_id, :record_date) + + contents_hash = Hash.new { |h, k| h[k] = [] } + + records.each do |u_id, c_id, t_id, r_date| + contents_hash[u_id] << [c_id, t_id, r_date] + end + + contents_hash + end + + def load_unknown_frequencies_by_unity(unity_ids, start_date, end_date) + records = DailyFrequency + .joins(classroom: :unity) + .where(unities: { id: unity_ids }) + .where('EXTRACT(YEAR FROM frequency_date) = ?', @year) + .where(owner_teacher_id: nil) + .where(frequency_date: start_date..end_date) + .distinct + .pluck('unities.id', 'classrooms.id', 'NULL', 'daily_frequencies.frequency_date') + + unknown_hash = Hash.new { |h, k| h[k] = [] } + + records.each do |u_id, c_id, _null_t_id, f_date| + unknown_hash[u_id] << [c_id, nil, f_date] + end + + unknown_hash + end + + def calculate_all_percentages + total_frequencies = 0 + total_unknown_teachers = 0 + total_content_records = 0 + + @school_days_by_unity.each do |unity_id, data| + start_date = data[:start_date] + end_date = data[:end_date] + total_days = data[:school_days] + + total_frequencies += frequency_done_percentage(unity_id, start_date, end_date, total_days) + total_unknown_teachers += unknown_teacher_frequency_done(unity_id, start_date, end_date, total_days) + total_content_records += content_record_done_percentage(unity_id, start_date, end_date, total_days) + end + + return { + frequency_done_percentage: 0, + unknown_teacher_percentage: 0, + content_record_percentage: 0 + } if unities_total.zero? + + { + frequency_done_percentage: (total_frequencies.to_f / unities_total).round(2), + unknown_teacher_percentage: (total_unknown_teachers.to_f / unities_total).round(2), + content_record_percentage: (total_content_records.to_f / unities_total).round(2) + } + end + + def frequency_done_percentage(unity_id, start_date, end_date, school_days, classroom_id = nil, teacher_id = nil) + records = @frequencies_by_unity[unity_id] || [] + + records = records.select { |c_id, t_id, date| + (classroom_id.nil? || c_id == classroom_id.to_i) && + (teacher_id.nil? || t_id == teacher_id.to_i) && + date >= start_date && date <= end_date + } + + distinct_days = records.map(&:last).uniq.size + + ((distinct_days * 100).to_f / school_days).round(2) + end + + def content_record_done_percentage(unity_id, start_date, end_date, school_days, classroom_id = nil, teacher_id = nil) + records = @contents_by_unity[unity_id] || [] + + records = records.select { |c_id, t_id, date| + (classroom_id.nil? || c_id == classroom_id.to_i) && + (teacher_id.nil? || t_id == teacher_id.to_i) && + date >= start_date && date <= end_date + } + + distinct_days = records.map(&:last).uniq.size + ((distinct_days * 100).to_f / school_days).round(2) + end + + def unknown_teacher_frequency_done(unity_id, start_date, end_date, school_days) + records = @unknown_frequencies_by_unity[unity_id] || [] + + records = records.select { |c_id, t_id, date| + date >= start_date && date <= end_date + } + + distinct_days = records.map(&:last).uniq.size + ((distinct_days * 100).to_f / school_days).round(2) + end + + def fetch_percents(unity_id, start_date, end_date) + if unity_id + classrooms = Classroom.where(unity_id: unity_id, year: @year).ordered + paginate(filter_from_params(percents(classrooms.pluck(:id)), @params.dig(:filter))) + else + paginate(filter_from_params(percents, @params.dig(:filter))) + end + end + + def percents(classrooms_ids = nil, teacher_id = nil) + unity_ids = @school_days_by_unity.keys + unities = Unity.where(id: unity_ids).index_by(&:id) + + result = [] + @school_days_by_unity.each do |unity_id, data| + unity = unities[unity_id] + + if classrooms_ids.present? + classrooms_ids.each do |classroom_id| + result << build_percent_table( + unity, + data[:start_date], + data[:end_date], + data[:school_days], + classroom_id, + teacher_id + ) + end + else + result << build_percent_table( + unity, + data[:start_date], + data[:end_date], + data[:school_days] + ) + end + end + + result + end + + def build_percent_table(unity, start_date, end_date, school_days, classroom_id = nil, teacher_id = nil) + frequency_percentage = frequency_done_percentage(unity.id, start_date, end_date, school_days, classroom_id, teacher_id) + content_record_percentage = content_record_done_percentage(unity.id, start_date, end_date, school_days, classroom_id, teacher_id) + + if classroom_id + classroom = Classroom.find(classroom_id) + if teacher_id.blank? + OpenStruct.new( + unity_id: unity.id, + unity_name: unity.name, + classroom_id: classroom.id, + start_date: start_date, + end_date: end_date, + classroom_description: classroom.description, + frequency_percentage: frequency_percentage, + content_record_percentage: content_record_percentage + ) + else + teacher = Teacher.find(teacher_id) + OpenStruct.new( + teacher_id: teacher_id, + start_date: start_date, + end_date: end_date, + teacher_name: teacher.name, + frequency_percentage: frequency_percentage, + content_record_percentage: content_record_percentage + ) + end + else + OpenStruct.new( + unity_id: unity.id, + unity_name: unity.name, + start_date: start_date, + end_date: end_date, + frequency_percentage: frequency_percentage, + content_record_percentage: content_record_percentage + ) + end + end + + def filter_from_params(percents, params) + return percents if params.blank? + + params.delete_if { |_filter, value| value.blank? } + + params.each do |filter, value| + next if ['frequency_percentage', 'content_record_percentage'].include?(filter) + + percents = percents.select do |school_percent| + if ['unity_id', 'classroom_id'].include?(filter) + school_percent.send(filter).to_i == value.to_i + elsif filter == 'frequency_operator' + compare( + school_percent.send(:frequency_percentage).to_f, + value, + params[:frequency_percentage].to_f + ) + else + compare( + school_percent.send(:content_record_percentage).to_f, + value, + params[:content_record_percentage].to_f + ) + end + end + end + + percents + end + + def compare(percent, operator, value) + case operator + when ComparativeOperators::EQUALS + percent == value + when ComparativeOperators::GREATER_THAN + percent > value + when ComparativeOperators::LESS_THAN + percent < value + when ComparativeOperators::GREATER_THAN_OR_EQUAL_TO + percent >= value + when ComparativeOperators::LESS_THAN_OR_EQUAL_TO + percent <= value + end + end + + def paginate(array) + Kaminari.paginate_array(array).page(@params[:page]).per(10) + end + + def teachers_for(classroom_id, teacher_id) + [teacher_id].compact.presence || + Teacher.by_classroom(classroom_id) + .by_year(@year) + .pluck(:id).uniq + end + + def calculate_teacher_percents(classroom_id, teachers_ids, filter_params) + teacher_percents = [] + teachers_ids.each do |tid| + teacher_percents << percents([classroom_id], tid) + end + + teacher_percents = teacher_percents.flatten + filter_from_params(teacher_percents, filter_params) + end +end \ No newline at end of file diff --git a/app/services/school_days_counter_service.rb b/app/services/school_days_counter_service.rb index 788bf529e..169968764 100644 --- a/app/services/school_days_counter_service.rb +++ b/app/services/school_days_counter_service.rb @@ -7,11 +7,12 @@ def initialize(params) @year = params.fetch(:year, nil) raise ArgumentError if @year.blank? || @all_unities_size.blank? + + preload_school_calendars end def school_days return all_school_days if @unities.size == @all_unities_size && @start_date.blank? && @end_date.blank? - fetch_school_days(@unities, @start_date, @end_date) end @@ -22,29 +23,41 @@ def all_school_days end def fetch_school_days(unities, start_date, end_date) + unity_ids = unities.map(&:id) + counts_by_unity = UnitySchoolDay + .where(unity_id: unity_ids) + .by_date_between(start_date, end_date) + .group(:unity_id) + .count + school_days_by_unity = {} - + unities.each do |unity| - school_days = school_days_fetcher(unity, start_date, end_date) - - next if school_days.blank? - - school_days_by_unity[unity.id] = school_days + school_calendar = @school_calendars_by_unity[unity.id] + next if school_calendar.blank? + + real_start_date = start_date.presence || school_calendar.steps.min_by(&:step_number).start_at + real_end_date = end_date.presence || school_calendar.steps.max_by(&:step_number).end_at + + school_days_count = counts_by_unity[unity.id] || 0 + + school_days_by_unity[unity.id] = { + school_days: school_days_count, + start_date: real_start_date, + end_date: real_end_date + } end - + school_days_by_unity end - def school_days_fetcher(unity, start_date, end_date) - school_calendar = SchoolCalendar.by_year(@year).by_unity_id(unity.id).first - - return if school_calendar.blank? - - start_date = start_date.presence || school_calendar.steps.min_by(&:step_number).start_at - end_date = end_date.presence || school_calendar.steps.max_by(&:step_number).end_at - - school_days = UnitySchoolDay.by_unity_id(unity.id).by_date_between(start_date, end_date).size + def preload_school_calendars + school_calendars = SchoolCalendar + .by_year(@year) + .where(unity_id: @unities.map(&:id)) + .includes(:steps) # para evitar N+1 nas steps + .to_a - { school_days: school_days, start_date: start_date, end_date: end_date } + @school_calendars_by_unity = school_calendars.index_by(&:unity_id) end -end +end \ No newline at end of file diff --git a/app/views/daily_frequencies_in_batchs/_student_fields.html.erb b/app/views/daily_frequencies_in_batchs/_student_fields.html.erb index 11ff4f4a0..8fd0809ec 100644 --- a/app/views/daily_frequencies_in_batchs/_student_fields.html.erb +++ b/app/views/daily_frequencies_in_batchs/_student_fields.html.erb @@ -1,7 +1,7 @@